diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 626aadae8..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,354 +0,0 @@ -cmake_minimum_required(VERSION 3.3 FATAL_ERROR) -project(openmc C CXX) - -# Setup output directories -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -# Set module path -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) - -#=============================================================================== -# Command line options -#=============================================================================== - -option(openmp "Enable shared-memory parallelism with OpenMP" ON) -option(profile "Compile with profiling flags" OFF) -option(debug "Compile with debug flags" OFF) -option(optimize "Turn on all compiler optimization flags" OFF) -option(coverage "Compile with coverage analysis flags" OFF) -option(dagmc "Enable support for DAGMC (CAD) geometry" OFF) - -#=============================================================================== -# MPI for distributed-memory parallelism -#=============================================================================== - -set(MPI_ENABLED FALSE) -if($ENV{CXX} MATCHES "(mpi[^/]*|CC)$") - message(STATUS "Detected MPI wrapper: $ENV{CXX}") - set(MPI_ENABLED TRUE) -endif() - -#=============================================================================== -# DAGMC Geometry Support - need DAGMC/MOAB -#=============================================================================== -if(dagmc) - find_package(DAGMC REQUIRED) - link_directories(${DAGMC_LIBRARY_DIRS}) -endif() - -#=============================================================================== -# HDF5 for binary output -#=============================================================================== - -# Allow user to specify HDF5_ROOT -if (NOT (CMAKE_VERSION VERSION_LESS 3.12)) - cmake_policy(SET CMP0074 NEW) -endif() - -# Unfortunately FindHDF5.cmake will always prefer a serial HDF5 installation -# over a parallel installation if both appear on the user's PATH. To get around -# this, we check for the environment variable HDF5_ROOT and if it exists, use it -# to check whether its a parallel version. - -if(NOT DEFINED HDF5_PREFER_PARALLEL) - if(DEFINED ENV{HDF5_ROOT} AND EXISTS $ENV{HDF5_ROOT}/bin/h5pcc) - set(HDF5_PREFER_PARALLEL TRUE) - else() - set(HDF5_PREFER_PARALLEL FALSE) - endif() -endif() - -find_package(HDF5 REQUIRED COMPONENTS C HL) -if(HDF5_IS_PARALLEL) - if(NOT MPI_ENABLED) - message(FATAL_ERROR "Parallel HDF5 must be used with MPI.") - endif() - message(STATUS "Using parallel HDF5") -endif() - -#=============================================================================== -# Set compile/link flags based on which compiler is being used -#=============================================================================== - -# Skip for Visual Stduio which has its own configurations through GUI -if(NOT MSVC) - -if(openmp) - # Requires CMake 3.1+ - find_package(OpenMP) - if(OPENMP_FOUND) - list(APPEND cxxflags ${OpenMP_CXX_FLAGS}) - list(APPEND ldflags ${OpenMP_CXX_FLAGS}) - endif() -endif() - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -list(APPEND cxxflags -O2) -if(debug) - list(REMOVE_ITEM cxxflags -O2) - list(APPEND cxxflags -g -O0) -endif() -if(profile) - list(APPEND cxxflags -g -fno-omit-frame-pointer) -endif() -if(optimize) - list(REMOVE_ITEM cxxflags -O2) - list(APPEND cxxflags -O3) -endif() -if(coverage) - list(APPEND cxxflags --coverage) - list(APPEND ldflags --coverage) -endif() - -# Show flags being used -message(STATUS "OpenMC C++ flags: ${cxxflags}") -message(STATUS "OpenMC Linker flags: ${ldflags}") - -endif() - -#=============================================================================== -# pugixml library -#=============================================================================== - -add_library(pugixml vendor/pugixml/pugixml.cpp) -target_include_directories(pugixml PUBLIC vendor/pugixml/) - -#=============================================================================== -# xtensor header-only library -#=============================================================================== - -# CMake 3.13+ will complain about policy CMP0079 unless it is set explicitly -if (NOT (CMAKE_VERSION VERSION_LESS 3.13)) - cmake_policy(SET CMP0079 NEW) -endif() - -add_subdirectory(vendor/xtl) -add_subdirectory(vendor/xtensor) -target_link_libraries(xtensor INTERFACE xtl) - -#=============================================================================== -# GSL header-only library -#=============================================================================== - -add_library(gsl INTERFACE) -target_include_directories(gsl INTERFACE vendor/gsl/include) - -# Make sure contract violations throw exceptions -target_compile_definitions(gsl INTERFACE GSL_THROW_ON_CONTRACT_VIOLATION) - -#=============================================================================== -# 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://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling - -# 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() - -#=============================================================================== -# faddeeva library -#=============================================================================== - -add_library(faddeeva STATIC vendor/faddeeva/Faddeeva.cc) -target_include_directories(faddeeva PUBLIC vendor/faddeeva/) -target_compile_options(faddeeva PRIVATE ${cxxflags}) - -#=============================================================================== -# libopenmc -#=============================================================================== - -list(APPEND libopenmc_SOURCES - src/bank.cpp - src/bremsstrahlung.cpp - src/dagmc.cpp - src/cell.cpp - src/cmfd_solver.cpp - src/cross_sections.cpp - src/distribution.cpp - src/distribution_angle.cpp - src/distribution_energy.cpp - src/distribution_multi.cpp - src/distribution_spatial.cpp - src/eigenvalue.cpp - src/endf.cpp - src/error.cpp - src/initialize.cpp - src/finalize.cpp - src/geometry.cpp - src/geometry_aux.cpp - src/hdf5_interface.cpp - src/lattice.cpp - src/material.cpp - src/math_functions.cpp - src/mesh.cpp - src/message_passing.cpp - src/mgxs.cpp - src/mgxs_interface.cpp - src/nuclide.cpp - src/output.cpp - src/particle.cpp - src/particle_restart.cpp - src/photon.cpp - src/physics.cpp - src/physics_common.cpp - src/physics_mg.cpp - src/plot.cpp - src/position.cpp - src/progress_bar.cpp - src/random_lcg.cpp - src/reaction.cpp - src/reaction_product.cpp - src/scattdata.cpp - src/secondary_correlated.cpp - src/secondary_kalbach.cpp - src/secondary_nbody.cpp - src/secondary_thermal.cpp - src/secondary_uncorrelated.cpp - src/settings.cpp - src/simulation.cpp - src/source.cpp - src/state_point.cpp - src/string_utils.cpp - src/summary.cpp - src/surface.cpp - src/tallies/derivative.cpp - src/tallies/filter.cpp - src/tallies/filter_azimuthal.cpp - src/tallies/filter_cellborn.cpp - src/tallies/filter_cellfrom.cpp - src/tallies/filter_cell.cpp - src/tallies/filter_delayedgroup.cpp - src/tallies/filter_distribcell.cpp - src/tallies/filter_energyfunc.cpp - src/tallies/filter_energy.cpp - src/tallies/filter_legendre.cpp - src/tallies/filter_material.cpp - src/tallies/filter_mesh.cpp - src/tallies/filter_meshsurface.cpp - src/tallies/filter_mu.cpp - src/tallies/filter_particle.cpp - src/tallies/filter_polar.cpp - src/tallies/filter_sph_harm.cpp - src/tallies/filter_sptl_legendre.cpp - src/tallies/filter_surface.cpp - src/tallies/filter_universe.cpp - src/tallies/filter_zernike.cpp - src/tallies/tally.cpp - src/tallies/tally_scoring.cpp - src/tallies/trigger.cpp - src/timer.cpp - src/thermal.cpp - src/track_output.cpp - src/urr.cpp - src/volume_calc.cpp - src/wmp.cpp - src/xml_interface.cpp - src/xsdata.cpp) - -# For Visual Studio compilers -if(MSVC) - # Use static library (otherwise explicit symbol portings are needed) - add_library(libopenmc STATIC ${libopenmc_SOURCES}) - - # To use the shared HDF5 libraries on Windows, the H5_BUILT_AS_DYNAMIC_LIB - # compile definition must be specified. - target_compile_definitions(libopenmc PRIVATE -DH5_BUILT_AS_DYNAMIC_LIB) -else() - add_library(libopenmc SHARED ${libopenmc_SOURCES}) -endif() - -set_target_properties(libopenmc PROPERTIES - OUTPUT_NAME openmc) - -target_include_directories(libopenmc - PUBLIC include ${HDF5_INCLUDE_DIRS}) - -# Set compile flags -target_compile_options(libopenmc PRIVATE ${cxxflags}) - -if (HDF5_IS_PARALLEL) - target_compile_definitions(libopenmc PRIVATE -DPHDF5) -endif() -if (MPI_ENABLED) - target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) -endif() - -# Set git SHA1 hash as a compile definition -execute_process(COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE GIT_SHA1_SUCCESS - OUTPUT_VARIABLE GIT_SHA1 - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) -if(GIT_SHA1_SUCCESS EQUAL 0) - target_compile_definitions(libopenmc PRIVATE -DGIT_SHA1="${GIT_SHA1}") -endif() - -# target_link_libraries treats any arguments starting with - but not -l as -# linker flags. Thus, we can pass both linker flags and libraries together. -target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - pugixml faddeeva xtensor gsl) - -if(dagmc) - target_compile_definitions(libopenmc PRIVATE DAGMC) - target_link_libraries(libopenmc ${DAGMC_LIBRARIES}) - target_include_directories(libopenmc PRIVATE ${DAGMC_INCLUDE_DIRS}) -endif() - -#=============================================================================== -# openmc executable -#=============================================================================== -add_executable(openmc src/main.cpp) -target_compile_options(openmc PRIVATE ${cxxflags}) -target_link_libraries(openmc libopenmc) - -# Ensure C++14 standard is used. Starting with CMake 3.8, another way this could -# be done is using the cxx_std_14 compiler feature. -set_target_properties( - openmc libopenmc faddeeva pugixml - PROPERTIES CXX_STANDARD 14 CXX_EXTENSIONS OFF) - -#=============================================================================== -# Python package -#=============================================================================== - -add_custom_command(TARGET libopenmc POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - ${CMAKE_CURRENT_SOURCE_DIR}/openmc/lib/$ - COMMENT "Copying libopenmc to Python module directory") - -#=============================================================================== -# Install executable, scripts, manpage, license -#=============================================================================== - -install(TARGETS openmc 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/openmc" RENAME copyright) -install(DIRECTORY include/ DESTINATION include) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index d29d42adc..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at openmc@anl.gov. All complaints will -be reviewed and investigated and will result in a response that is deemed -necessary and appropriate to the circumstances. The project team is obligated to -maintain confidentiality with regard to the reporter of an incident. However, -note that some project team members may have a legal obligation to report -certain forms of harassment because of their affiliation (for example, staff and -faculty at universities in the United States). Further details of specific -enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index be506f919..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributing to OpenMC - -Welcome, and thank you for considering contributing to OpenMC! We look forward -to welcoming new members to the community and will do our best to help you get -up to speed. - -## Code of Conduct - -Participants in the OpenMC project are expected to follow and uphold the [Code -of Conduct](CODE_OF_CONDUCT.md). Please report any unacceptable behavior to -openmc@anl.gov. - -## Resources - -- [GitHub Repository](https://github.com/openmc-dev/openmc) -- [Documentation](http://openmc.readthedocs.io/en/latest) -- [User's Mailing List](openmc-users@googlegroups.com) -- [Developer's Mailing List](openmc-dev@googlegroups.com) -- [Slack Community](https://openmc.slack.com/signup) (If you don't see your - domain listed, contact openmc@anl.gov) - -## How to Report Bugs - -OpenMC is hosted on GitHub and all bugs are reported and tracked through the -[Issues](https://github.com/openmc-dev/openmc/issues) listed on GitHub. - -## How to Suggest Enhancements - -We welcome suggestions for new features or enhancements to the code and -encourage you to submit them as Issues on GitHub. However, it's important to -recognize that our development team is relatively small and does not have -unlimited time to devote to new feature suggestions. If you are interested in -working on the feature you are requesting, indicate so in the issue and the -development team will be happy to discuss it. - -## How to Submit Changes - -All changes to OpenMC happen through pull requests. For a full overview of the -process, see the developer's guide section on [Contributing to -OpenMC](http://openmc.readthedocs.io/en/latest/devguide/contributing.html). - -## Code Style - -Before you run off to make changes to the code, please have a look at our [style -guide](http://openmc.readthedocs.io/en/latest/devguide/styleguide.html), which -is used when reviewing new contributions. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 6466c7685..000000000 --- a/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM ubuntu:latest - -# Setup environment variables for Docker image -ENV FC=/usr/bin/mpif90 CC=/usr/bin/mpicc CXX=/usr/bin/mpicxx \ - PATH=/opt/openmc/bin:/opt/NJOY2016/build:$PATH \ - LD_LIBRARY_PATH=/opt/openmc/lib:$LD_LIBRARY_PATH \ - OPENMC_CROSS_SECTIONS=/root/nndc_hdf5/cross_sections.xml \ - OPENMC_ENDF_DATA=/root/endf-b-vii.1 - -# Install dependencies from Debian package manager -RUN apt-get update -y && \ - apt-get upgrade -y && \ - apt-get install -y python3-pip && \ - apt-get install -y wget git emacs && \ - apt-get install -y gfortran g++ cmake && \ - apt-get install -y mpich libmpich-dev && \ - apt-get install -y libhdf5-serial-dev libhdf5-mpich-dev && \ - apt-get install -y imagemagick && \ - apt-get autoremove - -# Update system-provided pip -RUN pip3 install --upgrade pip - -# Clone and install NJOY2016 -RUN git clone https://github.com/njoy/NJOY2016 /opt/NJOY2016 && \ - cd /opt/NJOY2016 && \ - mkdir build && cd build && \ - cmake -Dstatic=on .. && make 2>/dev/null && make install - -# Clone and install OpenMC -RUN git clone https://github.com/openmc-dev/openmc.git /opt/openmc && \ - cd /opt/openmc && mkdir -p build && cd build && \ - cmake -Doptimize=on -DHDF5_PREFER_PARALLEL=on .. && \ - make && make install && \ - cd .. && pip install -e .[test] - -# Download cross sections (NNDC and WMP) and ENDF data needed by test suite -RUN ./opt/openmc/tools/ci/download-xs.sh diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cfa34033c..000000000 --- a/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright (c) 2011-2018 Massachusetts Institute of Technology and OpenMC contributors - -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 -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 5715bfb44..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,46 +0,0 @@ -include CMakeLists.txt -include LICENSE -include CODE_OF_CONDUCT.md -include CONTRIBUTING.md -include schemas.xml -include pyproject.toml -include pytest.ini -include openmc/data/reconstruct.pyx -include docs/source/_templates/layout.html -include docs/sphinxext/LICENSE -recursive-include . *.rst -recursive-include cmake *.cmake -recursive-include docs *.css -recursive-include docs *.dia -recursive-include docs *.png -recursive-include docs *.py -recursive-include docs *.svg -recursive-include docs *.tex -recursive-include docs *.txt -recursive-include docs Makefile -recursive-include examples *.h5 -recursive-include examples *.ipynb -recursive-include examples *.png -recursive-include examples *.py -recursive-include examples *.xml -recursive-include man *.1 -recursive-include src *.F90 -recursive-include src *.c -recursive-include src *.cc -recursive-include src *.cpp -recursive-include src *.h -recursive-include src *.hpp -recursive-include src *.rnc -recursive-include src *.rng -recursive-include tests *.dat -recursive-include tests *.h5 -recursive-include tests *.py -recursive-include tests *.xml -recursive-include vendor CMakeLists.txt -recursive-include vendor *.cmake.in -recursive-include vendor *.cc -recursive-include vendor *.cpp -recursive-include vendor *.hh -recursive-include vendor *.hpp -prune docs/build -prune docs/source/pythonapi/generated/ diff --git a/README.md b/README.md deleted file mode 100644 index 57197c363..000000000 --- a/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# OpenMC Monte Carlo Particle Transport Code - -[![License](https://img.shields.io/github/license/openmc-dev/openmc.svg)](http://openmc.readthedocs.io/en/latest/license.html) -[![Travis CI build status (Linux)](https://travis-ci.org/openmc-dev/openmc.svg?branch=develop)](https://travis-ci.org/openmc-dev/openmc) -[![Code Coverage](https://coveralls.io/repos/github/openmc-dev/openmc/badge.svg?branch=develop)](https://coveralls.io/github/openmc-dev/openmc?branch=develop) - -The OpenMC project aims to provide a fully-featured Monte Carlo particle -transport code based on modern methods. It is a constructive solid geometry, -continuous-energy transport code that uses HDF5 format cross sections. The -project started under the Computational Reactor Physics Group at MIT. - -Complete documentation on the usage of OpenMC is hosted on Read the Docs (both -for the [latest release](http://openmc.readthedocs.io/en/stable/) and -[developmental](http://openmc.readthedocs.io/en/latest/) version). If you are -interested in the project or would like to help and contribute, please send a -message to the OpenMC User's Group [mailing -list](https://groups.google.com/forum/?fromgroups=#!forum/openmc-users). - -## Installation - -Detailed [installation -instructions](http://openmc.readthedocs.io/en/stable/usersguide/install.html) -can be found in the User's Guide. - -## Citing - -If you use OpenMC in your research, please consider giving proper attribution by -citing the following publication: - -- 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). - -## Troubleshooting - -If you run into problems compiling, installing, or running OpenMC, first check -the [Troubleshooting -section](http://openmc.readthedocs.io/en/stable/usersguide/troubleshoot.html) in -the User's Guide. If you are not able to find a solution to your problem there, -please send a message to the User's Group [mailing -list](https://groups.google.com/forum/?fromgroups=#!forum/openmc-users). - -## Reporting Bugs - -OpenMC is hosted on GitHub and all bugs are reported and tracked through the -[Issues](https://github.com/openmc-dev/openmc/issues) feature on GitHub. However, -GitHub Issues should not be used for common troubleshooting purposes. If you are -having trouble installing the code or getting your model to run properly, you -should first send a message to the User's Group mailing list. If it turns out -your issue really is a bug in the code, an issue will then be created on -GitHub. If you want to request that a feature be added to the code, you may -create an Issue on github. - -## License - -OpenMC is distributed under the MIT/X -[license](http://openmc.readthedocs.io/en/stable/license.html). diff --git a/cmake/Modules/FindDAGMC.cmake b/cmake/Modules/FindDAGMC.cmake deleted file mode 100644 index c644c8886..000000000 --- a/cmake/Modules/FindDAGMC.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Try to find DAGMC -# -# Once done this will define -# -# DAGMC_FOUND - system has DAGMC -# DAGMC_INCLUDE_DIRS - the DAGMC include directory -# DAGMC_LIBRARIES - Link these to use DAGMC -# DAGMC_DEFINITIONS - Compiler switches required for using DAGMC - -find_path(DAGMC_CMAKE_CONFIG NAMES DAGMCConfig.cmake - HINTS ${DAGMC_ROOT} $ENV{DAGMC_ROOT} - PATHS ENV LD_LIBRARY_PATH - PATH_SUFFIXES lib Lib cmake lib/cmake - NO_DEFAULT_PATH) - -message(STATUS "Found DAGMC in ${DAGMC_CMAKE_CONFIG}") - -include(${DAGMC_CMAKE_CONFIG}/DAGMCConfig.cmake) diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index a93338df3..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,141 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build -IMAGEDIR = source/_images - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -# Tikz to PNG conversion -PNGS = $(patsubst %.tex,%.png,$(wildcard $(IMAGEDIR)/*.tex)) - -.PHONY: help images clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -%.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,$<) $@ - -clean: - -rm -rf $(BUILDDIR)/* - -rm -rf source/pythonapi/generated/ - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - sed -i -e 's/div.body/div.content/' $(BUILDDIR)/html/_static/basic.css - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyne.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyne.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/pyne" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyne" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: images - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: images - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/diagrams/cross_sections.dia b/docs/diagrams/cross_sections.dia deleted file mode 100644 index b5495767b..000000000 Binary files a/docs/diagrams/cross_sections.dia and /dev/null differ diff --git a/docs/diagrams/overview.dia b/docs/diagrams/overview.dia deleted file mode 100644 index 5aa02e448..000000000 Binary files a/docs/diagrams/overview.dia and /dev/null differ diff --git a/docs/requirements-rtd.txt b/docs/requirements-rtd.txt deleted file mode 100644 index 7801c670f..000000000 --- a/docs/requirements-rtd.txt +++ /dev/null @@ -1,4 +0,0 @@ -sphinx-numfig -jupyter -sphinxcontrib-katex -sphinxcontrib-svg2pdfconverter diff --git a/docs/source/_images/3dba.png b/docs/source/_images/3dba.png deleted file mode 100644 index 69de65414..000000000 Binary files a/docs/source/_images/3dba.png and /dev/null differ diff --git a/docs/source/_images/3dcore.png b/docs/source/_images/3dcore.png deleted file mode 100644 index 69fed4a07..000000000 Binary files a/docs/source/_images/3dcore.png and /dev/null differ diff --git a/docs/source/_images/3dgeomplot.png b/docs/source/_images/3dgeomplot.png deleted file mode 100644 index 5c16d8d83..000000000 Binary files a/docs/source/_images/3dgeomplot.png and /dev/null differ diff --git a/docs/source/_images/Tracks.png b/docs/source/_images/Tracks.png deleted file mode 100644 index 39c83cd59..000000000 Binary files a/docs/source/_images/Tracks.png and /dev/null differ diff --git a/docs/source/_images/atr.png b/docs/source/_images/atr.png deleted file mode 100644 index e1f440584..000000000 Binary files a/docs/source/_images/atr.png and /dev/null differ diff --git a/docs/source/_images/cmfd_flow.png b/docs/source/_images/cmfd_flow.png deleted file mode 100644 index 078f1a4bf..000000000 Binary files a/docs/source/_images/cmfd_flow.png and /dev/null differ diff --git a/docs/source/_images/cmfd_flow.tex b/docs/source/_images/cmfd_flow.tex deleted file mode 100644 index 4f673b0d7..000000000 --- a/docs/source/_images/cmfd_flow.tex +++ /dev/null @@ -1,29 +0,0 @@ -\documentclass{standalone} -\usepackage[utf8]{inputenc} -\usepackage{amsmath} -\usepackage{tikz} -\usepackage{pgfplots} -\pgfplotsset{compat=1.11} -\usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy} -\pagestyle{empty} -\begin{document} -\begin{tikzpicture} - \matrix[every node/.style={draw, thick, minimum width=3cm, minimum height=1cm, align=center}, column sep=2cm, row sep=1cm] (m) { -\node[draw, fill=red!40] (start) {Batch $i$ \\ tally NDA}; & \\ - \node[draw, diamond, aspect=2, fill=green!40] (cmfd) {Run NDA?}; & \node[draw, fill=red!40] (end) {Batch $i + 1$ \\ tally NDA}; \\ -\node[draw, fill=blue!40] (xs) {Calculate XS \& DC}; & \node[draw, fill=blue!40] (modify) {Modify MC Source}; \\ -\node[draw, fill=blue!40] (nonlinear) {Calculate Equivalence}; & \node[draw, fill=blue!40] (eqs) {Solve NDA eqs.};\\ -}; - -\begin{scope}[every path/.style={->,very thick,draw}] - \draw (start.south) -- (cmfd.north); - \draw (cmfd.east) -- node[above] {no} (end.west); - \draw (cmfd.south) -- node[right] {yes} (xs.north); - \draw (xs.south) -- (nonlinear.north); - \draw (nonlinear.east) -- (eqs.west); - \draw (eqs.north) -- (modify.south); - \draw (modify.north) -- (end.south); - \end{scope} - -\end{tikzpicture} -\end{document} diff --git a/docs/source/_images/cosine-dist.png b/docs/source/_images/cosine-dist.png deleted file mode 100644 index f7c165dcf..000000000 Binary files a/docs/source/_images/cosine-dist.png and /dev/null differ diff --git a/docs/source/_images/fluxplot.png b/docs/source/_images/fluxplot.png deleted file mode 100644 index 9c13ff33f..000000000 Binary files a/docs/source/_images/fluxplot.png and /dev/null differ diff --git a/docs/source/_images/fork.png b/docs/source/_images/fork.png deleted file mode 100644 index 9bc63ae61..000000000 Binary files a/docs/source/_images/fork.png and /dev/null differ diff --git a/docs/source/_images/halfspace.svg b/docs/source/_images/halfspace.svg deleted file mode 100644 index 8f5c5d54d..000000000 --- a/docs/source/_images/halfspace.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - +1 - -1 - - diff --git a/docs/source/_images/hex_lat.svg b/docs/source/_images/hex_lat.svg deleted file mode 100644 index cc150e711..000000000 --- a/docs/source/_images/hex_lat.svg +++ /dev/null @@ -1,780 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/source/_images/loss.png b/docs/source/_images/loss.png deleted file mode 100644 index 37d4169a1..000000000 Binary files a/docs/source/_images/loss.png and /dev/null differ diff --git a/docs/source/_images/master-slave.png b/docs/source/_images/master-slave.png deleted file mode 100644 index 01d0cbe97..000000000 Binary files a/docs/source/_images/master-slave.png and /dev/null differ diff --git a/docs/source/_images/meshfig.png b/docs/source/_images/meshfig.png deleted file mode 100644 index c84becf3a..000000000 Binary files a/docs/source/_images/meshfig.png and /dev/null differ diff --git a/docs/source/_images/meshfig.tex b/docs/source/_images/meshfig.tex deleted file mode 100644 index d710107cd..000000000 --- a/docs/source/_images/meshfig.tex +++ /dev/null @@ -1,639 +0,0 @@ -\documentclass[tikz]{standalone} -\usepackage[utf8]{inputenc} -\usepackage{amsmath} -\usepackage{tikz} -\usepackage{pgfplots} -\pgfplotsset{compat=1.11} -\usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy} -\usepackage{fixltx2e} -\pagestyle{empty} -\begin{document} - - % these dimensions are determined in arrow_dimms.ods - - \def\scale{1.0} - - \def\latWidth{0.2808363589*\scale} - - \def\RPVOR{3*\scale} - \def\rectW{0.75*\scale} - \def\RPVIR{2.8694005485*\scale} - \def\BarrelIR{2.4547472901*\scale} - \def\BarrelOR{2.5293848766*\scale} - \def\ShieldOR{2.6040224631*\scale} - - \def\bafCIRx{0.9829272561*\scale} - \def\bafCIRy{2.1062726917*\scale} - \def\bafCORx{1.0119529842*\scale} - \def\bafCORy{2.1352984197*\scale} - \def\bafMIRx{1.8254363328*\scale} - \def\bafMIRy{1.5445999739*\scale} - \def\bafMORx{1.8544620609*\scale} - \def\bafMORy{1.573625702*\scale} - - \tikzset{Assembly/.style={ - inner sep=0pt, - text width=\latWidth in, - minimum size=\latWidth in, - draw=black, - align=center - } - } - - \def\tkzRPV{(0,0) circle (\RPVIR) (0,0) circle (\RPVOR)} - \def\tkzBarrel{(0,0) circle (\BarrelIR) (0,0) circle (\BarrelOR)} - \def\tkzShields{(0,0) circle (\BarrelOR) (0,0) circle (\ShieldOR)} - - \def\tkzBaffCOR{(-\bafCORx, -\bafCORy) rectangle (\bafCORx, \bafCORy)} - \def\tkzBaffCIR{(-\bafCIRx, -\bafCIRy) rectangle (\bafCIRx, \bafCIRy)} - \def\tkzBaffMOR{(-\bafMORx, -\bafMORy) rectangle (\bafMORx, \bafMORy)} - \def\tkzBaffMIR{(-\bafMIRx, -\bafMIRy) rectangle (\bafMIRx, \bafMIRy) } - \def\tkzBaffleC{ \tkzBaffCIR \tkzBaffCOR } - \def\tkzBaffleM{ \tkzBaffMIR \tkzBaffMOR } - - \def\tkzBaffCClip{\tkzBaffCIR (-\RPVOR, -\RPVOR) rectangle (\RPVOR, \RPVOR)} - \def\tkzBaffMClip{\tkzBaffMIR (-\RPVOR, -\RPVOR) rectangle (\RPVOR, \RPVOR)} - - \def\highenr{blue!50} - \def\midenr{yellow!50} - \def\lowenr{red!50} - \def\lightgray{black!25} - \def\darkgray{black!80} - - \begin{tikzpicture}[x=1in,y=1in, xshift=3in] -\scalebox{0.6}{ - % draw RPV, barrel, and shield panels - - \path[fill=black,even odd rule] \tkzRPV; - \path[fill=black,even odd rule] \tkzBarrel; - \begin{scope} - \clip[rotate around={45:(0,0)}] (-\RPVOR, -\rectW) rectangle (\RPVOR, \rectW) (-\rectW, \RPVOR) rectangle (\rectW, -\RPVOR); - \path[fill=black,even odd rule] \tkzShields; - \end{scope} - - - % draw assembly row/column headers - - \draw[red, thick] ($(-7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {R} -- ($(-7*\latWidth,4*\latWidth)$); - \draw[red, thick] ($(-6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {P} -- ($(-6*\latWidth,6*\latWidth)$); - \draw[red, thick] ($(-5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {N} -- ($(-5*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(-4*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {M} -- ($(-4*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(-3*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {L} -- ($(-3*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-2*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {K} -- ($(-2*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-1*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {J} -- ($(-1*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-0*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {H} -- ($(-0*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(1*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {G} -- ($(1*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(2*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {F} -- ($(2*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(3*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {E} -- ($(3*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(4*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {D} -- ($(4*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {C} -- ($(5*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {B} -- ($(6*\latWidth,6*\latWidth)$); - \draw[red, thick] ($(7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {A} -- ($(7*\latWidth,4*\latWidth)$); - - \begin{scope}[rotate=90] - \draw[red, thick] ($(-7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {15} -- ($(-7*\latWidth,4*\latWidth)$); - \draw[red, thick] ($(-6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {14} -- ($(-6*\latWidth,6*\latWidth)$); - \draw[red, thick] ($(-5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {13} -- ($(-5*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(-4*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {12} -- ($(-4*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(-3*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {11} -- ($(-3*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-2*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {10} -- ($(-2*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-1*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {9} -- ($(-1*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(-0*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {8} -- ($(-0*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(1*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {7} -- ($(1*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(2*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {6} -- ($(2*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(3*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {5} -- ($(3*\latWidth,8*\latWidth)$); - \draw[red, thick] ($(4*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {4} -- ($(4*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {3} -- ($(5*\latWidth,7*\latWidth)$); - \draw[red, thick] ($(6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {2} -- ($(6*\latWidth,6*\latWidth)$); - \draw[red, thick] ($(7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {1} -- ($(7*\latWidth,4*\latWidth)$); - \end{scope} - - % draw fuel assembly nodes - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-5*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-4*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-3*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-2*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-1*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-0*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 1*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 2*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 3*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 4*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 5*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,8*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-5*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-4*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-3*\latWidth,7*\latWidth)$) {}; % L1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-2*\latWidth,7*\latWidth)$) {6}; % K1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-1*\latWidth,7*\latWidth)$) {}; % J1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-0*\latWidth,7*\latWidth)$) {6}; % H1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 1*\latWidth,7*\latWidth)$) {}; % G1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 2*\latWidth,7*\latWidth)$) {6}; % F1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 3*\latWidth,7*\latWidth)$) {}; % E1 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 4*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 5*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,7*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-5*\latWidth,6*\latWidth)$) {}; % N2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-4*\latWidth,6*\latWidth)$) {}; % M2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-3*\latWidth,6*\latWidth)$) {16}; % L2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,6*\latWidth)$) {}; % K2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-1*\latWidth,6*\latWidth)$) {20}; % J2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,6*\latWidth)$) {}; % H2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 1*\latWidth,6*\latWidth)$) {20}; % G2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,6*\latWidth)$) {}; % F2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 3*\latWidth,6*\latWidth)$) {16}; % E2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 4*\latWidth,6*\latWidth)$) {}; % D2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 5*\latWidth,6*\latWidth)$) {}; % C2 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,6*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,5*\latWidth)$) {}; % P3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-5*\latWidth,5*\latWidth)$) {15}; % N3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,5*\latWidth)$) {16}; % M3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,5*\latWidth)$) {}; % L3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,5*\latWidth)$) {16}; % K3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,5*\latWidth)$) {}; % J3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,5*\latWidth)$) {16}; % H3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,5*\latWidth)$) {}; % G3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,5*\latWidth)$) {16}; % F3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,5*\latWidth)$) {}; % E3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,5*\latWidth)$) {16}; % D3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 5*\latWidth,5*\latWidth)$) {15}; % C3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,5*\latWidth)$) {}; % B3 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,5*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,4*\latWidth)$) {}; % P4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-5*\latWidth,4*\latWidth)$) {16}; % N4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,4*\latWidth)$) {}; % M4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-3*\latWidth,4*\latWidth)$) {16}; % L4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,4*\latWidth)$) {}; % K4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-1*\latWidth,4*\latWidth)$) {12}; % J4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,4*\latWidth)$) {}; % H4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 1*\latWidth,4*\latWidth)$) {12}; % G4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,4*\latWidth)$) {}; % F4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 3*\latWidth,4*\latWidth)$) {16}; % E4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,4*\latWidth)$) {}; % D4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 5*\latWidth,4*\latWidth)$) {16}; % C4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,4*\latWidth)$) {}; % B4 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,4*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,3*\latWidth)$) {}; % R5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,3*\latWidth)$) {16}; % P5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-5*\latWidth,3*\latWidth)$) {}; % N5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,3*\latWidth)$) {16}; % M5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,3*\latWidth)$) {}; % L5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,3*\latWidth)$) {12}; % K5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,3*\latWidth)$) {}; % J5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,3*\latWidth)$) {12}; % H5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,3*\latWidth)$) {}; % G5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,3*\latWidth)$) {12}; % F5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,3*\latWidth)$) {}; % E5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,3*\latWidth)$) {16}; % D5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 5*\latWidth,3*\latWidth)$) {}; % C5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,3*\latWidth)$) {16}; % B5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,3*\latWidth)$) {}; % A5 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,3*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,3*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,2*\latWidth)$) {6}; % R6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-6*\latWidth,2*\latWidth)$) {}; % P6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-5*\latWidth,2*\latWidth)$) {16}; % N6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-4*\latWidth,2*\latWidth)$) {}; % M6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-3*\latWidth,2*\latWidth)$) {12}; % L6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,2*\latWidth)$) {}; % K6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-1*\latWidth,2*\latWidth)$) {12}; % J6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,2*\latWidth)$) {}; % H6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 1*\latWidth,2*\latWidth)$) {12}; % G6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,2*\latWidth)$) {}; % F6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 3*\latWidth,2*\latWidth)$) {12}; % E6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 4*\latWidth,2*\latWidth)$) {}; % D6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 5*\latWidth,2*\latWidth)$) {16}; % C6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 6*\latWidth,2*\latWidth)$) {}; % B6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,2*\latWidth)$) {6}; % A6 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,2*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,2*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,1*\latWidth)$) {}; % R7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,1*\latWidth)$) {20}; % P7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-5*\latWidth,1*\latWidth)$) {}; % N7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,1*\latWidth)$) {12}; % M7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,1*\latWidth)$) {}; % L7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,1*\latWidth)$) {12}; % K7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,1*\latWidth)$) {}; % J7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,1*\latWidth)$) {16}; % H7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,1*\latWidth)$) {}; % G7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,1*\latWidth)$) {12}; % F7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,1*\latWidth)$) {}; % E7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,1*\latWidth)$) {12}; % D7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 5*\latWidth,1*\latWidth)$) {}; % C7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,1*\latWidth)$) {20}; % B7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,1*\latWidth)$) {}; % A7 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,1*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,1*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,0*\latWidth)$) {6}; % R8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-6*\latWidth,0*\latWidth)$) {}; % P8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-5*\latWidth,0*\latWidth)$) {16}; % N8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-4*\latWidth,0*\latWidth)$) {}; % M8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-3*\latWidth,0*\latWidth)$) {12}; % L8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,0*\latWidth)$) {}; % K8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-1*\latWidth,0*\latWidth)$) {16}; % J8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,0*\latWidth)$) {}; % H8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 1*\latWidth,0*\latWidth)$) {16}; % G8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,0*\latWidth)$) {}; % F8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 3*\latWidth,0*\latWidth)$) {12}; % E8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 4*\latWidth,0*\latWidth)$) {}; % D8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 5*\latWidth,0*\latWidth)$) {16}; % C8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 6*\latWidth,0*\latWidth)$) {}; % B8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,0*\latWidth)$) {6}; % A8 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,0*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,0*\latWidth)$) {}; - - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,-1*\latWidth)$) {}; % R9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,-1*\latWidth)$) {20}; % P9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-5*\latWidth,-1*\latWidth)$) {}; % N9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,-1*\latWidth)$) {12}; % M9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,-1*\latWidth)$) {}; % L9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,-1*\latWidth)$) {12}; % K9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,-1*\latWidth)$) {}; % J9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,-1*\latWidth)$) {16}; % H9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,-1*\latWidth)$) {}; % G9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,-1*\latWidth)$) {12}; % F9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,-1*\latWidth)$) {}; % E9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,-1*\latWidth)$) {12}; % D9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 5*\latWidth,-1*\latWidth)$) {}; % C9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,-1*\latWidth)$) {20}; % B9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,-1*\latWidth)$) {}; % A9 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,-1*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-1*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,-2*\latWidth)$) {6}; % R10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-6*\latWidth,-2*\latWidth)$) {}; % P10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-5*\latWidth,-2*\latWidth)$) {16}; % N10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-4*\latWidth,-2*\latWidth)$) {}; % M10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-3*\latWidth,-2*\latWidth)$) {12}; % L10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,-2*\latWidth)$) {}; % K10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-1*\latWidth,-2*\latWidth)$) {12}; % J10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,-2*\latWidth)$) {}; % H10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 1*\latWidth,-2*\latWidth)$) {12}; % G10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,-2*\latWidth)$) {}; % F10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 3*\latWidth,-2*\latWidth)$) {12}; % E10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 4*\latWidth,-2*\latWidth)$) {}; % D10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 5*\latWidth,-2*\latWidth)$) {16}; % C10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 6*\latWidth,-2*\latWidth)$) {}; % B10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,-2*\latWidth)$) {6}; % A10 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,-2*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-2*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-7*\latWidth,-3*\latWidth)$) {}; % R11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-7*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,-3*\latWidth)$) {16}; % P11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-5*\latWidth,-3*\latWidth)$) {}; % N11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,-3*\latWidth)$) {16}; % M11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,-3*\latWidth)$) {}; % L11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,-3*\latWidth)$) {12}; % K11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,-3*\latWidth)$) {}; % J11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,-3*\latWidth)$) {12}; % H11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,-3*\latWidth)$) {}; % G11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,-3*\latWidth)$) {12}; % F11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,-3*\latWidth)$) {}; % E11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,-3*\latWidth)$) {16}; % D11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 5*\latWidth,-3*\latWidth)$) {}; % C11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,-3*\latWidth)$) {16}; % B11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 7*\latWidth,-3*\latWidth)$) {}; % A11 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 7*\latWidth,-3*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-3*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,-4*\latWidth)$) {}; % P12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-5*\latWidth,-4*\latWidth)$) {16}; % N12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,-4*\latWidth)$) {}; % M12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-3*\latWidth,-4*\latWidth)$) {16}; % L12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,-4*\latWidth)$) {}; % K12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-1*\latWidth,-4*\latWidth)$) {12}; % J12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,-4*\latWidth)$) {}; % H12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 1*\latWidth,-4*\latWidth)$) {12}; % G12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,-4*\latWidth)$) {}; % F12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 3*\latWidth,-4*\latWidth)$) {16}; % E12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,-4*\latWidth)$) {}; % D12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 5*\latWidth,-4*\latWidth)$) {16}; % C12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,-4*\latWidth)$) {}; % B12 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-4*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-4*\latWidth)$) {}; - - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-6*\latWidth,-5*\latWidth)$) {}; % P13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-6*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-5*\latWidth,-5*\latWidth)$) {15}; % N13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-4*\latWidth,-5*\latWidth)$) {16}; % M13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-3*\latWidth,-5*\latWidth)$) {}; % L13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-2*\latWidth,-5*\latWidth)$) {16}; % K13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-1*\latWidth,-5*\latWidth)$) {}; % J13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($(-0*\latWidth,-5*\latWidth)$) {16}; % H13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 1*\latWidth,-5*\latWidth)$) {}; % G13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 2*\latWidth,-5*\latWidth)$) {16}; % F13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 3*\latWidth,-5*\latWidth)$) {}; % E13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\midenr] at ($( 4*\latWidth,-5*\latWidth)$) {16}; % D13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 5*\latWidth,-5*\latWidth)$) {15}; % C13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 6*\latWidth,-5*\latWidth)$) {}; % B13 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 6*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-5*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-5*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-5*\latWidth,-6*\latWidth)$) {}; % N14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-5*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-4*\latWidth,-6*\latWidth)$) {}; % M14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-4*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-3*\latWidth,-6*\latWidth)$) {16}; % L14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-2*\latWidth,-6*\latWidth)$) {}; % K14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-1*\latWidth,-6*\latWidth)$) {20}; % J14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($(-0*\latWidth,-6*\latWidth)$) {}; % H14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 1*\latWidth,-6*\latWidth)$) {20}; % G14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lowenr] at ($( 2*\latWidth,-6*\latWidth)$) {}; % F14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 3*\latWidth,-6*\latWidth)$) {16}; % E14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 4*\latWidth,-6*\latWidth)$) {}; % D14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 4*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 5*\latWidth,-6*\latWidth)$) {}; % C14 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 5*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-6*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-6*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-5*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-4*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-3*\latWidth,-7*\latWidth)$) {}; % L15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-3*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-2*\latWidth,-7*\latWidth)$) {6}; % K15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-2*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-1*\latWidth,-7*\latWidth)$) {}; % J15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-1*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($(-0*\latWidth,-7*\latWidth)$) {6}; % H15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($(-0*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 1*\latWidth,-7*\latWidth)$) {}; % G15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 1*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 2*\latWidth,-7*\latWidth)$) {6}; % F15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 2*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\highenr] at ($( 3*\latWidth,-7*\latWidth)$) {}; % E15 - \node [Assembly, fill=\darkgray, opacity=0.7] at ($( 3*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 4*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 5*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-7*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-7*\latWidth)$) {}; - - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-5*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-4*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-3*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-2*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-1*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($(-0*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 1*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 2*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 3*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 4*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 5*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-8*\latWidth)$) {}; - \node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-8*\latWidth)$) {}; - - % draw baffle north/south - - \begin{scope}[even odd rule] - \clip[rotate=90] \tkzBaffMClip; - \path[fill=black] \tkzBaffleC; - \end{scope} - \begin{scope}[even odd rule] - \clip \tkzBaffCClip; - \clip \tkzBaffMClip; - \path[fill=black, rotate=90] \tkzBaffleM; - \end{scope} - - % draw baffle east/west - - \begin{scope}[rotate=90] - \begin{scope}[even odd rule] - \clip[rotate=90] \tkzBaffMClip; - \path[fill=black] \tkzBaffleC; - \end{scope} - \begin{scope}[even odd rule] - \clip \tkzBaffCClip; - \clip \tkzBaffMClip; - \path[fill=black, rotate=90] \tkzBaffleM; - \end{scope} - \end{scope}} - \end{tikzpicture} -\end{document} diff --git a/docs/source/_images/nearest-neighbor-example.png b/docs/source/_images/nearest-neighbor-example.png deleted file mode 100644 index cd3b345f3..000000000 Binary files a/docs/source/_images/nearest-neighbor-example.png and /dev/null differ diff --git a/docs/source/_images/nearest-neighbor.png b/docs/source/_images/nearest-neighbor.png deleted file mode 100644 index a83a76863..000000000 Binary files a/docs/source/_images/nearest-neighbor.png and /dev/null differ diff --git a/docs/source/_images/openmc_logo.png b/docs/source/_images/openmc_logo.png deleted file mode 100644 index 73d476538..000000000 Binary files a/docs/source/_images/openmc_logo.png and /dev/null differ diff --git a/docs/source/_images/openmc_logo.svg b/docs/source/_images/openmc_logo.svg deleted file mode 100644 index a7352b79a..000000000 --- a/docs/source/_images/openmc_logo.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/docs/source/_images/plotmeshtally.png b/docs/source/_images/plotmeshtally.png deleted file mode 100644 index d874b4906..000000000 Binary files a/docs/source/_images/plotmeshtally.png and /dev/null differ diff --git a/docs/source/_images/prod.png b/docs/source/_images/prod.png deleted file mode 100644 index a4c2887d8..000000000 Binary files a/docs/source/_images/prod.png and /dev/null differ diff --git a/docs/source/_images/rect_lat.svg b/docs/source/_images/rect_lat.svg deleted file mode 100644 index cec6260c6..000000000 --- a/docs/source/_images/rect_lat.svg +++ /dev/null @@ -1,711 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/source/_images/union.svg b/docs/source/_images/union.svg deleted file mode 100644 index 066fa2ba1..000000000 --- a/docs/source/_images/union.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - +1 - -1 - -2 - +2 - -3 - +3 - - diff --git a/docs/source/_static/theme_overrides.css b/docs/source/_static/theme_overrides.css deleted file mode 100644 index 2d5e114c7..000000000 --- a/docs/source/_static/theme_overrides.css +++ /dev/null @@ -1,29 +0,0 @@ -/* override table width restrictions */ -.wy-table-responsive table td, .wy-table-responsive table th { - white-space: normal; -} - -.wy-table-responsive { - margin-bottom: 24px; - max-width: 100%; - overflow: visible; -} - -.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul { - margin-bottom: 0px; -} - -.wy-table, .rst-content table.docutils, .rst-content table.field-list { - margin-bottom: 0px; -} - -.wy-side-nav-search { - background-color: #343131; -} - -/* Make embedded Jupyter notebooks look better */ -div#notebook-container.container { - padding: 0px; - width: auto; - box-shadow: none; -} diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html deleted file mode 100644 index 9df3ab446..000000000 --- a/docs/source/_templates/layout.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "!layout.html" %} - -{% block footer %} -{{ super() }} - -{% endblock %} diff --git a/docs/source/_templates/mycallable.rst b/docs/source/_templates/mycallable.rst deleted file mode 100644 index 85fdd34c3..000000000 --- a/docs/source/_templates/mycallable.rst +++ /dev/null @@ -1,9 +0,0 @@ -{{ fullname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :members: - :special-members: __call__ - diff --git a/docs/source/_templates/myclass.rst b/docs/source/_templates/myclass.rst deleted file mode 100644 index a0560f93a..000000000 --- a/docs/source/_templates/myclass.rst +++ /dev/null @@ -1,7 +0,0 @@ -{{ fullname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :members: diff --git a/docs/source/_templates/myclassinherit.rst b/docs/source/_templates/myclassinherit.rst deleted file mode 100644 index ed93a2966..000000000 --- a/docs/source/_templates/myclassinherit.rst +++ /dev/null @@ -1,8 +0,0 @@ -{{ fullname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :members: - :inherited-members: diff --git a/docs/source/_templates/myfunction.rst b/docs/source/_templates/myfunction.rst deleted file mode 100644 index 4d7ea38a1..000000000 --- a/docs/source/_templates/myfunction.rst +++ /dev/null @@ -1,6 +0,0 @@ -{{ fullname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autofunction:: {{ objname }} diff --git a/docs/source/_templates/myintegrator.rst b/docs/source/_templates/myintegrator.rst deleted file mode 100644 index 803dfde06..000000000 --- a/docs/source/_templates/myintegrator.rst +++ /dev/null @@ -1,9 +0,0 @@ -{{ fullname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :members: - :inherited-members: - :special-members: __call__, __len__, __iter__ diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst deleted file mode 100644 index 0ce1c234d..000000000 --- a/docs/source/capi/index.rst +++ /dev/null @@ -1,596 +0,0 @@ -.. _capi: - -========= -C/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/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.lib` module. - -.. warning:: The C/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:: int openmc_calculate_volumes() - - Run a stochastic volume calculation - - :return: Return status (negative if an error occurred) - :rtype: int - -.. 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 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_get_temperature(int32_t index, const int32_t* instance, double* T) - - Get the temperature of a cell - - :param int32_t index: Index in the cells array - :param int32_t* instance: Which instance of the cell. If a null pointer is passed, the temperature - of the first instance is returned. - :param double* T: temperature of the cell - :return: Return status (negative if an error occurred) - :rtype: int - -.. 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 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: 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 - -.. c:function:: int openmc_finalize() - - Finalize a simulation - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance) - - Determine the ID of the cell/material containing a given point - - :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. - :return: Return status (negative if an error occurs) - :rtype: int - -.. 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 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_filter_index(int32_t id, int32_t* index) - - 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:: void openmc_get_filter_next_id(int32_t* id) - - Get an integer ID that has not been used by any filters. - - :param int32_t* id: Unused integer ID - -.. c:function:: int openmc_get_keff(double k_combined[2]) - - :param double[2] k_combined: Combined estimate of k-effective - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_get_material_index(int32_t id, int32_t* index) - - Get the index in the materials array for a material with a given ID - - :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(const char name[], int* index) - - Get the index in the nuclides array for a nuclide with a given name - - :param name: Name of the nuclide - :type name: const char[] - :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 - -.. c:function:: int openmc_hard_reset() - - Reset tallies, timers, and pseudo-random number generator state - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_init(int argc, char** argv, const void* intracomm) - - Initialize OpenMC - - :param int argc: Number of command-line arguments (including command) - :param char** argv: Command-line arguments - :param intracomm: MPI intracommunicator. If MPI is not being used, a null - pointer should be passed. - :type intracomm: const void* - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_load_nuclide(char name[]) - - Load data for a nuclide from the HDF5 data library. - - :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, const char name[], double density) - - Add a nuclide to an existing material. If the nuclide already exists, the - density is overwritten. - - :param int32_t index: Index in the materials array - :param name: Name of the nuclide - :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, int* n) - - Get density for each nuclide in a material. - - :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 - -.. c:function:: int openmc_material_get_density(int32_t index, double* density) - - Get density of a material. - - :param int32_t index: Index in the materials array - :param double* denity: Pointer to a density - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_material_get_id(int32_t index, int32_t* id) - - Get 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_set_density(int32_t index, double density, const char* units) - - Set the density of a material. - - :param int32_t index: Index in the materials array - :param double density: Density of the material - :param units: Units for density - :type units: const char* - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_material_set_densities(int32_t index, int n, const char** name, const double density*) - - :param int32_t index: Index in the materials array - :param int n: Length of name/density - :param name: Array of nuclide names - :type name: const char** - :param density: Array of densities - :type density: const double* - :return: Return status (negative if an error occurs) - :rtype: int - -.. 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 int index: Index in the nuclides array - :param char** name: Name of the nuclide - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_plot_geometry() - - Run plotting mode. - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_reset() - - Resets all tally scores - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_run() - - Run a simulation - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_simulation_finalize() - - Finalize a simulation. - - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_simulation_init() - - Initialize a simulation. Must be called after openmc_init(). - - :return: Return status (negative if an error occurs) - :rtype: int - -.. 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:: int openmc_statepoint_write(const char filename[], const bool* write_source) - - 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[] - :param write_source: Whether to include the source bank - :type write_source: const bool* - :return: Return status (negative if an error occurs) - :rtype: int - -.. c:function:: int openmc_tally_get_id(int32_t index, int32_t* id) - - Get 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_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 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 - -.. c:function:: int openmc_tally_results(int32_t index, double** ptr, int shape_[3]) - - Get a pointer to tally results array. - - :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_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 int32_t index: Index in the tallies array - :param int n: Number of nuclides - :param nuclides: Array of nuclide names - :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 diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index f54a8df0e..000000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,260 +0,0 @@ -# -*- coding: utf-8 -*- -# -# metasci documentation build configuration file, created by -# sphinx-quickstart on Sun Feb 7 22:29:49 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# Determine if we're on Read the Docs server -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 -from unittest.mock import MagicMock - - -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', 'openmc.checkvalue' -] -sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES) - -import numpy as np -np.ndarray = MagicMock -np.polynomial.Polynomial = MagicMock - - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../sphinxext')) -sys.path.insert(0, os.path.abspath('../..')) - - -# -- General configuration ----------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.autosummary', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', - 'sphinxcontrib.katex', - 'sphinx_numfig', - 'notebook_sphinxext'] -if not on_rtd: - extensions.append('sphinxcontrib.rsvgconverter') - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'OpenMC' -copyright = '2011-2019, Massachusetts Institute of Technology and OpenMC contributors' - -# 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.11" -# The full version, including alpha/beta/rc tags. -release = "0.11.0" - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -#pygments_style = 'sphinx' -#pygments_style = 'friendly' -#pygments_style = 'bw' -#pygments_style = 'fruity' -#pygments_style = 'manni' -pygments_style = 'tango' - - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages -if not on_rtd: - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -html_logo = '_images/openmc_logo.png' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = "OpenMC Documentation" - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -def setup(app): - app.add_stylesheet('theme_overrides.css') - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'openmcdoc' - - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'openmc.tex', 'OpenMC Documentation', - 'OpenMC contributors', 'manual'), -] - -latex_elements = { -'preamble': r""" -\usepackage{enumitem} -\usepackage{amsfonts} -\usepackage{amsmath} -\setlistdepth{99} -\usepackage{tikz} -\usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy} -\usepackage{fixltx2e} -\hypersetup{bookmarksdepth=3} -\setcounter{tocdepth}{2} -\numberwithin{equation}{section} -""", -'printindex': r"" -} - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -#Autodocumentation Flags -#autodoc_member_order = "groupwise" -#autoclass_content = "both" -autosummary_generate = True - -napoleon_use_ivar = True - -intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), - 'numpy': ('https://docs.scipy.org/doc/numpy/', None), - 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), - 'matplotlib': ('https://matplotlib.org/', None) -} diff --git a/docs/source/devguide/contributing.rst b/docs/source/devguide/contributing.rst deleted file mode 100644 index c08b1a362..000000000 --- a/docs/source/devguide/contributing.rst +++ /dev/null @@ -1,129 +0,0 @@ -.. _devguide_contributing: - -====================== -Contributing to OpenMC -====================== - -Thank you for considering contributing to OpenMC! We look forward to welcoming -new members to the community and will do our best to help you get up to speed. -The purpose of this section is to document how the project is managed: how -contributions (bug fixes, enhancements, new features) are made, how they are -evaluated, who is permitted to merge pull requests, and what happens in the -event of disagreements. Once you have read through this section, the -:ref:`devguide_workflow` section outlines the actual mechanics of making a -contribution (forking, submitting a pull request, etc.). - -The goal of our governance model is to: - -- Encourage new contributions. -- Encourage contributors to remain involved. -- Avoid unnecessary processes and bureaucracy whenever possible. -- Create a transparent decision making process which makes it clear how - contributors can be involved in decision making. - -Overview --------- - -OpenMC uses a liberal contribution model for project governance. Anyone involved -in development in a non-trivial capacity is given an opportunity to influence -the direction of the project. Project decisions are made through a -consensus-seeking process rather than by voting. - -Terminology ------------ - -- A *Contributor* is any individual creating or commenting on an issue or pull - request. -- A *Committer* is a subset of contributors who are authorized to review and - merge pull requests. -- The *TC* (Technical Committee) is a group of committers who have the authority - to make decisions on behalf of the project team in order to resolve disputes. -- The *Project Lead* is a single individual who has the authority to make a final - decision when the TC is unable to reach consensus. - -Contribution Process --------------------- - -Any change to the OpenMC repository must be made through a pull request (PR). -This applies to all changes to documentation, code, binary files, etc. Even long -term committers and TC members must use pull requests. - -No pull request may be merged without being independently reviewed. - -For non-trivial contributions, pull requests should not be merged for at least -36 hours to ensure that contributors in other timezones have time to review. -Consideration should be given to weekends and other holiday periods to ensure -active committers have reasonable time to become involved in the discussion and -review process if they wish. Any committer may request that the review period be -extended if they are unable to review the change within 36 hours. - -During review, a committer may request that a specific contributor who is most -versed in a particular area review the PR before it can be merged. - -A pull request can be merged by any committer, but only if no objections are -raised by any other committer. In the case of an objection being raised, all -involved committers should seek consensus through discussion and compromise. - -In the case of an objection being raised in a pull request by another committer, -all involved committers should seek to arrive at a consensus by way of -addressing concerns being expressed through discussion, compromise on the -proposed change, or withdrawal of the proposed change. - -If objections to a PR are made and committers cannot reach a consensus on how to -proceed, the decision is escalated to the TC. TC members should regularly -discuss pending contributions in order to find a resolution. It is expected that -only a small minority of issues be brought to the TC for resolution and that -discussion and compromise among committers be the default resolution mechanism. - -Becoming a Committer --------------------- - -All contributors who make a non-trivial contribution will be added as a -committer in a timely manner. Committers are expected to follow this policy. - -TC Process ----------- - -Any issues brought to the TC will be addressed among the committee with a -consensus-seeking process. The group tries to find a resolution that has no -objections among TC members. If a consensus cannot be reached, the Project Lead -has the ultimate authority to make a final decision. It is expected that the -majority of decisions made by the TC are via a consensus seeking process and -that the Project Lead intercedes only as a last resort. - -Resolution may involve returning the issue to committers with suggestions on how -to move forward towards a consensus. - -Members can be added to the TC at any time. Any committer can nominate another -committer to the TC and the TC uses its standard consensus seeking process to -evaluate whether or not to add this new member. Members who do not participate -consistently at the level of a majority of the other members are expected to -resign. - -In the event that the Project Lead resigns or otherwise steps down, the TC uses -a consensus seeking process to choose a new Project Lead. - -Leadership Team ---------------- - -The TC consists of the following individuals: - -- `Paul Romano `_ -- `Sterling Harper `_ -- `Adam Nelson `_ -- `Benoit Forget `_ - -The Project Lead is Paul Romano. - -Next Steps ----------- - -If you are interested in working on a specific feature or helping to address -outstanding issues, consider joining the developer's `mailing list -`_ and/or `Slack community -`_. Note that some issues have specifically -been labeled as good for `first-time contributors -`_. -Once you're at the point of writing code, make sure your read through the -:ref:`devguide_workflow` section to understand the mechanics of making pull -requests and what is expected during code reviews. diff --git a/docs/source/devguide/docbuild.rst b/docs/source/devguide/docbuild.rst deleted file mode 100644 index 38ef628df..000000000 --- a/docs/source/devguide/docbuild.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. _devguide_docbuild: - -============================= -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: - -.. code-block:: sh - - pip install sphinx - -Additionally, you will need several Sphinx extensions that can be installed -directly with pip: - -.. code-block:: sh - - pip install sphinx-numfig - pip install sphinxcontrib-katex - pip install sphinxcontrib-svg2pdfconverter - ------------------------------------ -Building Documentation as a Webpage ------------------------------------ - -To build the documentation as a webpage (what appears at -https://docs.openmc.org), simply go to the ``docs`` directory and run: - -.. code-block:: sh - - make html - -------------------------------- -Building Documentation as a PDF -------------------------------- - -To build PDF documentation, you will need to have a LaTeX distribution installed -on your computer. Once you have a LaTeX distribution installed, simply go to the -``docs`` directory and run: - -.. code-block:: sh - - make latexpdf diff --git a/docs/source/devguide/docker.rst b/docs/source/devguide/docker.rst deleted file mode 100644 index 0b2191168..000000000 --- a/docs/source/devguide/docker.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. _devguide_docker: - -====================== -Deployment with Docker -====================== - -OpenMC can be easily deployed using `Docker `_ on any -Windows, Mac or Linux system. With Docker running, execute the following -command in the shell to build a `Docker image`_ called ``debian/openmc:latest``: - -.. code-block:: sh - - docker build -t debian/openmc:latest https://github.com/openmc-dev/openmc.git#develop - -.. note:: This may take 5 -- 10 minutes to run to completion. - -This command will execute the instructions in OpenMC's ``Dockerfile`` to -build a Docker image with OpenMC installed. The image includes OpenMC with -MPICH and parallel HDF5 in the ``/opt/openmc`` directory, and -`Miniconda3 `_ with all of the Python -pre-requisites (NumPy, SciPy, Pandas, etc.) installed. The -`NJOY2016 `_ codebase is installed in -``/opt/NJOY2016`` to support full functionality and testing of the -``openmc.data`` Python module. The publicly available nuclear data libraries -necessary to run OpenMC's test suite -- including NNDC and WMP cross sections -and ENDF data -- are in the ``/opt/openmc/data directory``, and the -corresponding :envvar:`OPENMC_CROSS_SECTIONS`, -:envvar:`OPENMC_MULTIPOLE_LIBRARY`, and :envvar:`OPENMC_ENDF_DATA` -environment variables are initialized. - -After building the Docker image, you can run the following to see the names of -all images on your machine, including ``debian/openmc:latest``: - -.. code-block:: sh - - docker image ls - -Now you can run the following to create a `Docker container`_ called -``my_openmc`` based on the ``debian/openmc:latest`` image: - -.. code-block:: sh - - docker run -it --name=my_openmc debian/openmc:latest - -This command will open an interactive shell running from within the -Docker container where you have access to use OpenMC. - -.. note:: The ``docker run`` command supports many - `options `_ - for spawning containers -- including `mounting volumes`_ from the - host filesystem -- which many users will find useful. - -.. _Docker image: https://docs.docker.com/engine/reference/commandline/images/ -.. _Docker container: https://www.docker.com/resources/what-container -.. _options: https://docs.docker.com/engine/reference/commandline/run/ -.. _mounting volumes: https://docs.docker.com/storage/volumes/ diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst deleted file mode 100644 index d100fdcdf..000000000 --- a/docs/source/devguide/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _devguide: - -================= -Developer's Guide -================= - -Welcome to the OpenMC Developer's Guide! This guide documents how contributions -are made to OpenMC, what style rules exist for the code, how to run tests, and -other related topics. - -.. toctree:: - :numbered: - :maxdepth: 2 - - contributing - workflow - styleguide - tests - user-input - docbuild - docker diff --git a/docs/source/devguide/styleguide.rst b/docs/source/devguide/styleguide.rst deleted file mode 100644 index 562b75e89..000000000 --- a/docs/source/devguide/styleguide.rst +++ /dev/null @@ -1,241 +0,0 @@ -.. _devguide_styleguide: - -====================== -Style Guide for OpenMC -====================== - -In order to keep the OpenMC code base consistent in style, this guide specifies -a number of rules which should be adhered to when modified existing code or -adding new code in OpenMC. - ---- -C++ ---- - -Indentation ------------ - -Use two spaces per indentation level. - -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++14 standard. - -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.) - -Do not use C-style casting. Always use the C++-style casts ``static_cast``, -``const_cast``, or ``reinterpret_cast``. (See `ES.49 `_) - -Source Files ------------- - -Use a ``.cpp`` suffix for code files and ``.h`` for header files. - -Header files should always use include guards with the following style (See -`SF.8 `_): - -.. code-block:: C++ - - #ifndef OPENMC_MODULE_NAME_H - #define OPENMC_MODULE_NAME_H - - namespace openmc { - ... - content - ... - } - - #endif // OPENMC_MODULE_NAME_H - -Avoid hidden dependencies by always including a related header file first, -followed by C/C++ library includes, other library includes, and then local -includes. For example: - -.. code-block:: C++ - - // foo.cpp - #include "foo.h" - - #include - #include - #include - - #include "hdf5.h" - #include "pugixml.hpp" - - #include "error.h" - #include "random_lcg.h" - -Naming ------- - -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 member variables 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). Data members of -classes (but not structs) additionally have trailing underscores (e.g., -``a_class_member_``). - -The following conventions are used for variables with short names: - -- ``d`` stands for "distance" -- ``E`` stands for "energy" -- ``p`` stands for "particle" -- ``r`` stands for "position" -- ``rx`` stands for "reaction" -- ``u`` stands for "direction" -- ``xs`` stands for "cross section" - -All classes and non-member functions should be declared within the ``openmc`` -namespace. Global variables must be declared in a namespace nested within the -``openmc`` namespace. The following sub-namespaces are in use: - -- ``openmc::data``: Fundamental nuclear data (cross sections, multigroup data, - decay constants, etc.) -- ``openmc::model``: Variables related to geometry, materials, and tallies -- ``openmc::settings``: Global settings / options -- ``openmc::simulation``: Variables used only during a simulation - -Accessors and mutators (get and set functions) may be named like -variables. These often correspond to actual member variables, but this is not -required. For example, ``int count()`` and ``void set_count(int count)``. - -Variables declared constexpr or const that have static storage duration (exist -for the duration of the program) should be upper-case with underscores, -e.g., ``SQRT_PI``. - -Use C++-style declarator layout (see `NL.18 -`_): -pointer and reference operators in declarations should be placed adject to the -base type rather than the variable name. Avoid declaring multiple names in a -single declaration to avoid confusion: - -.. code-block:: C++ - - T* p; // good - T& p; // good - T *p; // bad - T* p, q; // misleading - -Curly braces ------------- - -For a class declaration, the opening brace should be on the same line that -lists the name of the class. - -.. code-block:: C++ - - class Matrix { - ... - }; - -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 or two lines, 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;} - - 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(); - -Documentation -------------- - -Classes, structs, and functions are to be annotated for the `Doxygen -`_ documentation generation tool. Use the ``\`` form of -Doxygen commands, e.g., ``\brief`` instead of ``@brief``. - ------- -Python ------- - -Style for Python code should follow PEP8_. - -Docstrings for functions and methods should follow numpydoc_ style. - -Python code should work with Python 3.4+. - -Use of third-party Python packages should be limited to numpy_, scipy_, -matplotlib_, pandas_, and h5py_. Use of other third-party packages must be -implemented as optional dependencies rather than required dependencies. - -Prefer pathlib_ when working with filesystem paths over functions in the os_ -module or other standard-library modules. Functions that accept arguments that -represent a filesystem path should work with both strings and Path_ objects. - -.. _C++ Core Guidelines: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines -.. _PEP8: https://www.python.org/dev/peps/pep-0008/ -.. _numpydoc: https://numpydoc.readthedocs.io/en/latest/format.html -.. _numpy: https://numpy.org/ -.. _scipy: https://www.scipy.org/ -.. _matplotlib: https://matplotlib.org/ -.. _pandas: https://pandas.pydata.org/ -.. _h5py: https://www.h5py.org/ -.. _pathlib: https://docs.python.org/3/library/pathlib.html -.. _os: https://docs.python.org/3/library/os.html -.. _Path: https://docs.python.org/3/library/pathlib.html#pathlib.Path diff --git a/docs/source/devguide/tests.rst b/docs/source/devguide/tests.rst deleted file mode 100644 index b26f5c762..000000000 --- a/docs/source/devguide/tests.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. _devguide_tests: - -========== -Test Suite -========== - -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. - -Prerequisites -------------- - -- The test suite relies on the third-party `pytest `_ - 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] - -- The test suite requires a specific set of cross section data in order for - tests to pass. A download URL for the data that OpenMC expects can be found - within ``tools/ci/download-xs.sh``. -- In addition to the HDF5 data, some tests rely on ENDF files. A download URL - for those can also be found in ``tools/ci/download-xs.sh``. -- Some tests require `NJOY `_ to preprocess - cross section data. The test suite assumes that you have an ``njoy`` - executable available on your :envvar:`PATH`. - -Running Tests -------------- - -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 `_ plugin -installed and run:: - - pytest --cov=../openmc --cov-report=html - -Generating XML Inputs ---------------------- - -Many of the regression tests rely on the Python API to build an appropriate -model. However, it can sometimes be desirable to work directly with the XML -input files rather than having to run a script in order to run the problem/test. -To build the input files for a test without actually running the test, you can -run:: - - pytest --build-inputs - -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. diff --git a/docs/source/devguide/user-input.rst b/docs/source/devguide/user-input.rst deleted file mode 100644 index db0bcdad8..000000000 --- a/docs/source/devguide/user-input.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. _devguide_user_input: - -========================= -Making User Input Changes -========================= - -Users are encouraged to use OpenMC's :ref:`pythonapi` to build XML files that -the OpenMC solver then reads during the initialization phase. Thus, to modify, -add, or remove user input options, changes must be made both within the Python -API and the C++ source that reads XML files produced by the Python API. The -following steps should be followed to make changes to user input: - -1. Determine the Python class you need to change. For example, if you are adding - a new setting, you probably want to change the :class:`openmc.Settings` - class. If you are adding a new surface type, you would need to create a - subclass of :class:`openmc.Surface`. - -2. To add a new option, the class will need a `property attribute`_. For - example, if you wanted to add a "fast_mode" setting, you would need two - methods that look like: - - .. code-block:: python - - @property - def fast_mode(self): - ... - - @fast_mode.setter - def fast_mode(self, fast_mode): - ... - -3. Make sure that when an instance of the class is exported to XML (usually - through a ``export_to_xml()`` or ``to_xml_element()`` method), a new element - is written to the appropriate file. OpenMC uses the - :mod:`xml.etree.ElementTree` API, so refer to the documentation of that - module for guidance on creating elements/attributes. - -4. Make sure that your input can be categorized as one of the datatypes from - `XML Schema Part 2`_ and that parsing of the data appropriately reflects - this. For example, for a boolean_ value, true can be represented either by - "true" or by "1". - -5. Now that you're done with the Python side, you need to make modifications to - the C++ codebase. Make appropriate changes in source files (e.g., - settings.cpp). You should use convenience functions defined by - xml_interface.cpp. - -6. If you've made changes in the geometry or materials, make sure they are - written out to the statepoint or summary files and that the - :class:`openmc.StatePoint` and :class:`openmc.Summary` classes read them in. - -7. Finally, a set of `RELAX NG`_ schemas exists that enables validation of input - files. You should modify the RELAX NG schema for the file you changed. The - easiest way to do this is to change the `compact syntax`_ file - (e.g. ``src/relaxng/geometry.rnc``) and then convert it to regular XML syntax - using trang_:: - - trang geometry.rnc geometry.rng - -For most user input additions and changes, it is simple enough to follow a -"monkey see, monkey do" approach. When in doubt, contact your nearest OpenMC -developer or send a message to the `developers mailing list`_. - - -.. _property attribute: https://docs.python.org/3.6/library/functions.html#property -.. _XML Schema Part 2: http://www.w3.org/TR/xmlschema-2/ -.. _boolean: http://www.w3.org/TR/xmlschema-2/#boolean -.. _RELAX NG: http://relaxng.org/ -.. _compact syntax: http://relaxng.org/compact-tutorial-20030326.html -.. _trang: http://www.thaiopensource.com/relaxng/trang.html -.. _developers mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-dev diff --git a/docs/source/devguide/workflow.rst b/docs/source/devguide/workflow.rst deleted file mode 100644 index 037b8b68a..000000000 --- a/docs/source/devguide/workflow.rst +++ /dev/null @@ -1,132 +0,0 @@ -.. _devguide_workflow: - -==================== -Development Workflow -==================== - -Anyone wishing to make contributions to OpenMC should be fully acquianted and -comfortable working with git_ and GitHub_. We assume here that you have git -installed on your system, have a GitHub account, and have setup SSH keys to be -able to create/push to repositories on GitHub. - -Overview --------- - -Development of OpenMC relies heavily on branching; specifically, we use a -branching model sometimes referred to as `git flow`_. If you plan to contribute -to OpenMC development, we highly recommend that you read the linked blog post to -get a sense of how the branching model works. There are two main branches that -always exist: *master* and *develop*. The *master* branch is a stable branch -that contains the latest release of the code. The *develop* branch is where any -ongoing development takes place prior to a release and is not guaranteed to be -stable. When the development team decides that a release should occur, the -*develop* branch is merged into *master*. - -All new features, enhancements, and bug fixes should be developed on a branch -that branches off of *develop*. When the feature is completed, a `pull request`_ -is initiated on GitHub that is then reviewed by a committer. If the pull request -is satisfactory, it is then merged into *develop*. Note that a committer may not -review their own pull request (i.e., an independent code review is required). - -Code Review Criteria --------------------- - -In order to be considered suitable for inclusion in the *develop* branch, the -following criteria must be satisfied for all proposed changes: - -- Changes have a clear purpose and are useful. -- Compiles and passes all tests under multiple build configurations (This is - checked by Travis CI). -- If appropriate, test cases are added to regression or unit test suites. -- No memory leaks (checked with valgrind_). -- Conforms to the OpenMC `style guide`_. -- No degradation of performance or greatly increased memory usage. This is not a - hard rule -- in certain circumstances, a performance loss might be acceptable - if there are compelling reasons. -- New features/input are documented. -- No unnecessary external software dependencies are introduced. - -Contributing ------------- - -Now that you understand the basic development workflow, let's discuss how an -individual to contribute to development. Note that this would apply to both new -features and bug fixes. The general steps for contributing are as follows: - -1. Fork the main openmc repository from `openmc-dev/openmc`_. This will create a - repository with the same name under your personal account. As such, you can - commit to it as you please without disrupting other developers. - - .. image:: ../_images/fork.png - -2. Clone your fork of OpenMC and create a branch that branches off of *develop*: - - .. code-block:: sh - - git clone git@github.com:yourusername/openmc.git - cd openmc - git checkout -b newbranch develop - -3. Make your changes on the new branch that you intend to have included in - *develop*. If you have made other changes that should not be merged back, - ensure that those changes are made on a different branch. - -4. Issue a pull request from GitHub and select the *develop* branch of - openmc-dev/openmc as the target. - - At a minimum, you should describe what the changes you've made are and why - you are making them. If the changes are related to an oustanding issue, make - sure it is cross-referenced. - -5. A committer will review your pull request based on the criteria - above. Any issues with the pull request can be discussed directly on the pull - request page itself. - -6. After the pull request has been thoroughly vetted, it is merged back into the - *develop* branch of openmc-dev/openmc. - -Private Development -------------------- - -While the process above depends on the fork of the OpenMC repository being -publicly available on GitHub, you may also wish to do development on a private -repository for research or commercial purposes. The proper way to do this is to -create a complete copy of the OpenMC repository (not a fork from GitHub). The -private repository can then either be stored just locally or in conjunction with -a private repository on Github (this requires a `paid plan`_). Alternatively, -`Bitbucket`_ offers private repositories for free. If you want to merge some -changes you've made in your private repository back to openmc-dev/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 -`_ 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 -.. _valgrind: http://valgrind.org/ -.. _style guide: https://docs.openmc.org/en/latest/devguide/styleguide.html -.. _pull request: https://help.github.com/articles/using-pull-requests -.. _openmc-dev/openmc: https://github.com/openmc-dev/openmc -.. _paid plan: https://github.com/plans -.. _Bitbucket: https://bitbucket.org -.. _pip: https://pip.pypa.io/en/stable/ diff --git a/docs/source/examples/cad-geom.rst b/docs/source/examples/cad-geom.rst deleted file mode 100644 index c5251c7ca..000000000 --- a/docs/source/examples/cad-geom.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_cad-geom: - -========================== -Using CAD-Based Geometries -========================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/cad-based-geometry.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/candu.rst b/docs/source/examples/candu.rst deleted file mode 100644 index 463a3c76e..000000000 --- a/docs/source/examples/candu.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_candu: - -======================= -Modeling a CANDU Bundle -======================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/candu.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/expansion-filters.rst b/docs/source/examples/expansion-filters.rst deleted file mode 100644 index f06d2bde6..000000000 --- a/docs/source/examples/expansion-filters.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_expansion: - -===================== -Functional Expansions -===================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/expansion-filters.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/hexagonal.rst b/docs/source/examples/hexagonal.rst deleted file mode 100644 index 8955fdb3f..000000000 --- a/docs/source/examples/hexagonal.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_hexagonal: - -=========================== -Modeling Hexagonal Lattices -=========================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/hexagonal-lattice.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst deleted file mode 100644 index 529f9427b..000000000 --- a/docs/source/examples/index.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. _examples: - -======== -Examples -======== - -The following series of `Jupyter `_ Notebooks provide -examples for how to use various features of OpenMC by leveraging the -:ref:`pythonapi`. - -------------- -General Usage -------------- - -.. toctree:: - :maxdepth: 1 - - pincell - post-processing - pandas-dataframes - tally-arithmetic - expansion-filters - search - nuclear-data - nuclear-data-resonance-covariance - cad-geom - pincell-depletion - --------- -Geometry --------- - -.. toctree:: - :maxdepth: 1 - - hexagonal - triso - candu - ------------------------------------- -Multi-Group Cross Section Generation ------------------------------------- - -.. toctree:: - :maxdepth: 1 - - mgxs-part-i - mgxs-part-ii - mgxs-part-iii - mdgxs-part-i - mdgxs-part-ii - ----------------- -Multi-Group Mode ----------------- - -.. toctree:: - :maxdepth: 1 - - mg-mode-part-i - mg-mode-part-ii - mg-mode-part-iii diff --git a/docs/source/examples/mdgxs-part-i.rst b/docs/source/examples/mdgxs-part-i.rst deleted file mode 100644 index 2899f126b..000000000 --- a/docs/source/examples/mdgxs-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mdgxs_part_i: - -=================================================================== -Multi-Group (Delayed) Cross Section Generation Part I: Introduction -=================================================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mdgxs-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mdgxs-part-ii.rst b/docs/source/examples/mdgxs-part-ii.rst deleted file mode 100644 index c5d52df62..000000000 --- a/docs/source/examples/mdgxs-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mdgxs_part_ii: - -========================================================================= -Multi-Group (Delayed) Cross Section Generation Part II: Advanced Features -========================================================================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mdgxs-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-i.rst b/docs/source/examples/mg-mode-part-i.rst deleted file mode 100644 index e54c21c2f..000000000 --- a/docs/source/examples/mg-mode-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_i: - -===================================== -Multi-Group Mode Part I: Introduction -===================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-ii.rst b/docs/source/examples/mg-mode-part-ii.rst deleted file mode 100644 index 9b4e574ae..000000000 --- a/docs/source/examples/mg-mode-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_ii: - -============================================================= -Multi-Group Mode Part II: MGXS Library Generation With OpenMC -============================================================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-iii.rst b/docs/source/examples/mg-mode-part-iii.rst deleted file mode 100644 index 86657c967..000000000 --- a/docs/source/examples/mg-mode-part-iii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_iii: - -==================================================== -Multi-Group Mode Part III: Advanced Feature Showcase -==================================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-iii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-i.rst b/docs/source/examples/mgxs-part-i.rst deleted file mode 100644 index d956e7261..000000000 --- a/docs/source/examples/mgxs-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_i: - -========================= -MGXS Part I: Introduction -========================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-ii.rst b/docs/source/examples/mgxs-part-ii.rst deleted file mode 100644 index 64efc5752..000000000 --- a/docs/source/examples/mgxs-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_ii: - -=============================== -MGXS Part II: Advanced Features -=============================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-iii.rst b/docs/source/examples/mgxs-part-iii.rst deleted file mode 100644 index 12f326529..000000000 --- a/docs/source/examples/mgxs-part-iii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_iii: - -======================== -MGXS Part III: Libraries -======================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-iii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/nuclear-data-resonance-covariance.rst b/docs/source/examples/nuclear-data-resonance-covariance.rst deleted file mode 100644 index 4b505c9a5..000000000 --- a/docs/source/examples/nuclear-data-resonance-covariance.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_nuclear_data_resonance_covariance: - -================================== -Nuclear Data: Resonance Covariance -================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/nuclear-data-resonance-covariance.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/nuclear-data.rst b/docs/source/examples/nuclear-data.rst deleted file mode 100644 index 15dfbde18..000000000 --- a/docs/source/examples/nuclear-data.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_nuclear_data: - -============ -Nuclear Data -============ - -.. only:: html - - .. notebook:: ../../../examples/jupyter/nuclear-data.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pandas-dataframes.rst b/docs/source/examples/pandas-dataframes.rst deleted file mode 100644 index 701f1630c..000000000 --- a/docs/source/examples/pandas-dataframes.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _examples_pandas: - -================= -Pandas Dataframes -================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pandas-dataframes.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pincell-depletion.rst b/docs/source/examples/pincell-depletion.rst deleted file mode 100644 index 348f3c6b9..000000000 --- a/docs/source/examples/pincell-depletion.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _notebook_depletion: - -================= -Pincell Depletion -================= - - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pincell_depletion.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pincell.rst b/docs/source/examples/pincell.rst deleted file mode 100644 index 0f149107c..000000000 --- a/docs/source/examples/pincell.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_pincell: - -=================== -Modeling a Pin-Cell -=================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pincell.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/post-processing.rst b/docs/source/examples/post-processing.rst deleted file mode 100644 index 09c4454e7..000000000 --- a/docs/source/examples/post-processing.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_post_processing: - -=============== -Post Processing -=============== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/post-processing.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/search.rst b/docs/source/examples/search.rst deleted file mode 100644 index 1d56ff53a..000000000 --- a/docs/source/examples/search.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_search: - -================== -Criticality Search -================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/search.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/tally-arithmetic.rst b/docs/source/examples/tally-arithmetic.rst deleted file mode 100644 index 7e653e8ff..000000000 --- a/docs/source/examples/tally-arithmetic.rst +++ /dev/null @@ -1,11 +0,0 @@ -================ -Tally Arithmetic -================ - -.. only:: html - - .. notebook:: ../../../examples/jupyter/tally-arithmetic.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/triso.rst b/docs/source/examples/triso.rst deleted file mode 100644 index 98f2f1643..000000000 --- a/docs/source/examples/triso.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_triso: - -======================== -Modeling TRISO Particles -======================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/triso.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index 198a9429e..000000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,48 +0,0 @@ -=========================== -The OpenMC Monte Carlo Code -=========================== - -OpenMC is a community-developed Monte Carlo neutron and photon transport -simulation code. It is capable of performing fixed source, k-eigenvalue, and -subcritical multiplication calculations on models built using either a -constructive solid geometry or CAD representation. OpenMC supports both -continuous-energy and multigroup transport. The continuous-energy particle -interaction data is based on a native HDF5 format that can be generated from ACE -files produced by NJOY. Parallelism is enabled via a hybrid MPI and OpenMP -programming model. - -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 `_. - -.. 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 `_," - *Ann. Nucl. Energy*, **82**, 90--97 (2015). - -.. only:: html - - -------- - Contents - -------- - -.. toctree:: - :maxdepth: 1 - - quickinstall - examples/index - releasenotes/index - methods/index - usersguide/index - devguide/index - pythonapi/index - capi/index - io_formats/index - publications - license diff --git a/docs/source/io_formats/cross_sections.rst b/docs/source/io_formats/cross_sections.rst deleted file mode 100644 index 9f0759a3a..000000000 --- a/docs/source/io_formats/cross_sections.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. _io_cross_sections: - -============================================ -Cross Sections Listing -- cross_sections.xml -============================================ - -.. _directory_element: - ------------------------ -```` Element ------------------------ - -The ```` element specifies a root directory to which the path for all -files listed in a :ref:`library_element` are given relative to. This element has -no attributes or sub-elements; the directory should be given within the text -node. For example, - -.. code-block:: xml - - /opt/data/cross_sections/ - -.. _library_element: - ---------------------- -```` Element ---------------------- - -The ```` element indicates where an HDF5 data file is located, whether -it contains incident neutron, incident photon, thermal scattering, or windowed -multipole data, and what materials are listed within. It has the following -attributes: - - :materials: - - A space-separated list of nuclides or thermal scattering tables. For - example, - - .. code-block:: xml - - - - - Often, just a single nuclide or thermal scattering table is contained in a - given file. - - :path: - Path to the HDF5 file. If the :ref:`directory_element` is specified, the - path is relative to the directory given. Otherwise, it is relative to the - directory containing the ``cross_sections.xml`` file. - - :type: - The type of data contained in the file. Accepted values are 'neutron', - 'thermal', 'photon', and 'wmp'. - -.. _depletion_element: - ------------------------------ -```` Element ------------------------------ - -The ```` element indicates the location of the depletion chain file. -This file contains information describing how nuclides decay and transmute to other -nuclides through the depletion process. This element has a single attribute, ``path``, -pointing to the location of the chain file. - -.. code-block:: xml - - - -The structure of the depletion chain file is explained in :ref:`io_depletion_chain`. diff --git a/docs/source/io_formats/data_wmp.rst b/docs/source/io_formats/data_wmp.rst deleted file mode 100644 index 8d7cf6ba0..000000000 --- a/docs/source/io_formats/data_wmp.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _io_data_wmp: - -================================= -Windowed Multipole Library Format -================================= - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file - - **version** (*int[2]*) -- Major and minor version of the data - -**//** - -:Datasets: - - - **broaden_poly** (*int[]*) - If 1, Doppler broaden curve fit for window with corresponding index. - If 0, do not. - - **curvefit** (*double[][][]*) - Curve fit coefficients. Indexed by (reaction type, coefficient index, - window index). - - **data** (*complex[][]*) - Complex poles and residues. Each pole has a corresponding set of - residues. For example, the :math:`i`-th pole and corresponding residues - are stored as - - .. math:: - \text{data}[:,i] = [\text{pole},~\text{residue}_1,~\text{residue}_2, - ~\ldots] - - The residues are in the order: scattering, absorption, fission. Complex - numbers are stored by forming a type with ":math:`r`" and ":math:`i`" - identifiers, similar to how `h5py`_ does it. - - **E_max** (*double*) - Highest energy the windowed multipole part of the library is valid for. - - **E_min** (*double*) - Lowest energy the windowed multipole part of the library is valid for. - - **spacing** (*double*) - .. math:: - \frac{\sqrt{E_{max}} - \sqrt{E_{min}}}{n_w} - - Where :math:`E_{max}` is the maximum energy the windows go up to. - :math:`E_{min}` is the minimum energy, and :math:`n_w` is the number of - windows, given by ``windows``. - - **sqrtAWR** (*double*) - Square root of the atomic weight ratio. - - **windows** (*int[][]*) - The poles to start from and end at for each window. windows[i, 0] and - windows[i, 1] are, respectively, the indexes (1-based) of the first and - last pole in window i. - -.. _h5py: http://docs.h5py.org/en/latest/ diff --git a/docs/source/io_formats/depletion_chain.rst b/docs/source/io_formats/depletion_chain.rst deleted file mode 100644 index b0dd72eb9..000000000 --- a/docs/source/io_formats/depletion_chain.rst +++ /dev/null @@ -1,102 +0,0 @@ -.. _io_depletion_chain: - -============================ -Depletion Chain -- chain.xml -============================ - -A depletion chain file has a ```` root element with one or more -```` child elements. The decay, reaction, and fission product data for -each nuclide appears as child elements of ````. - ---------------------- -```` Element ---------------------- - -The ```` 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 -````. For each reaction present, a :ref:`io_chain_reaction` appears as -a child of ````. If the nuclide is fissionable, a :ref:`io_chain_nfy` -appears as well. - -.. _io_chain_decay: - -------------------- -```` Element -------------------- - -The ```` 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: - ----------------------- -```` Element ----------------------- - -The ```` 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: - ------------------------------------- -```` Element ------------------------------------- - -The ```` 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 diff --git a/docs/source/io_formats/depletion_results.rst b/docs/source/io_formats/depletion_results.rst deleted file mode 100644 index de28b0477..000000000 --- a/docs/source/io_formats/depletion_results.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. _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[][][2]*) -- k-eigenvalues at each - time/stage. This array has shape (number of timesteps, number of - stages, value). The last axis contains the eigenvalue and the - associated uncertainty - - **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. - - **depletion time** (*double[]*) -- Average process time in [s] - spent depleting a material across all burnable materials and, - if applicable, MPI processes. - -**/materials//** - -:Attributes: - **index** (*int*) -- Index used in results for this material - - **volume** (*double*) -- Volume of this material in [cm^3] - -**/nuclides//** - -: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//** - -:Attributes: - **index** (*int*) -- Index user in results for this reaction - -.. note:: - - The reaction rates for some isotopes not originally present may - be non-zero, but should be negligible compared to other atoms. - This can be controlled by changing the - :class:`openmc.deplete.Operator` ``dilute_initial`` attribute. diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst deleted file mode 100644 index 617ac6e87..000000000 --- a/docs/source/io_formats/geometry.rst +++ /dev/null @@ -1,372 +0,0 @@ -.. _io_geometry: - -====================================== -Geometry Specification -- geometry.xml -====================================== - -.. _surface_element: - ---------------------- -```` Element ---------------------- - -Each ```` element can have the following attributes or sub-elements: - - :id: - A unique integer that can be used to identify the surface. - - *Default*: None - - :name: - An optional string name to identify the surface in summary output - files. This string is limited to 52 characters for formatting purposes. - - *Default*: "" - - :type: - The type of the surfaces. This can be "x-plane", "y-plane", "z-plane", - "plane", "x-cylinder", "y-cylinder", "z-cylinder", "sphere", "x-cone", - "y-cone", "z-cone", or "quadric". - - *Default*: None - - :coeffs: - The corresponding coefficients for the given type of surface. See below for - a list a what coefficients to specify for a given surface - - *Default*: None - - :boundary: - The boundary condition for the surface. This can be "transmission", - "vacuum", "reflective", or "periodic". Periodic boundary conditions can - only be applied to x-, y-, and z-planes. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. Specify which - planes are periodic and the code will automatically identify which planes - are paired together. - - *Default*: "transmission" - - :periodic_surface_id: - If a periodic boundary condition is applied, this attribute identifies the - ``id`` of the corresponding periodic sufrace. - -The following quadratic surfaces can be modeled: - - :x-plane: - A plane perpendicular to the x axis, i.e. a surface of the form :math:`x - - x_0 = 0`. The coefficients specified are ":math:`x_0`". - - :y-plane: - A plane perpendicular to the y axis, i.e. a surface of the form :math:`y - - y_0 = 0`. The coefficients specified are ":math:`y_0`". - - :z-plane: - A plane perpendicular to the z axis, i.e. a surface of the form :math:`z - - z_0 = 0`. The coefficients specified are ":math:`z_0`". - - :plane: - An arbitrary plane of the form :math:`Ax + By + Cz = D`. The coefficients - specified are ":math:`A \: B \: C \: D`". - - :x-cylinder: - An infinite cylinder whose length is parallel to the x-axis. This is a - quadratic surface of the form :math:`(y - y_0)^2 + (z - z_0)^2 = R^2`. The - coefficients specified are ":math:`y_0 \: z_0 \: R`". - - :y-cylinder: - An infinite cylinder whose length is parallel to the y-axis. This is a - quadratic surface of the form :math:`(x - x_0)^2 + (z - z_0)^2 = R^2`. The - coefficients specified are ":math:`x_0 \: z_0 \: R`". - - :z-cylinder: - An infinite cylinder whose length is parallel to the z-axis. This is a - quadratic surface of the form :math:`(x - x_0)^2 + (y - y_0)^2 = R^2`. The - coefficients specified are ":math:`x_0 \: y_0 \: R`". - - :sphere: - A sphere of the form :math:`(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = - R^2`. The coefficients specified are ":math:`x_0 \: y_0 \: z_0 \: R`". - - :x-cone: - A cone parallel to the x-axis of the form :math:`(y - y_0)^2 + (z - z_0)^2 = - R^2 (x - x_0)^2`. The coefficients specified are ":math:`x_0 \: y_0 \: z_0 - \: R^2`". - - :y-cone: - A cone parallel to the y-axis of the form :math:`(x - x_0)^2 + (z - z_0)^2 = - R^2 (y - y_0)^2`. The coefficients specified are ":math:`x_0 \: y_0 \: z_0 - \: R^2`". - - :z-cone: - A cone parallel to the x-axis of the form :math:`(x - x_0)^2 + (y - y_0)^2 = - R^2 (z - z_0)^2`. The coefficients specified are ":math:`x_0 \: y_0 \: z_0 - \: R^2`". - - :quadric: - A general quadric surface of the form :math:`Ax^2 + By^2 + Cz^2 + Dxy + - Eyz + Fxz + Gx + Hy + Jz + K = 0` The coefficients specified are ":math:`A - \: B \: C \: D \: E \: F \: G \: H \: J \: K`". - -.. _cell_element: - ------------------- -```` Element ------------------- - -Each ```` element can have the following attributes or sub-elements: - - :id: - A unique integer that can be used to identify the cell. - - *Default*: None - - :name: - An optional string name to identify the cell in summary output files. - This string is limmited to 52 characters for formatting purposes. - - *Default*: "" - - :universe: - The ``id`` of the universe that this cell is contained in. - - *Default*: 0 - - :fill: - The ``id`` of the universe that fills this cell. - - .. note:: If a fill is specified, no material should be given. - - *Default*: None - - :material: - The ``id`` of the material that this cell contains. If the cell should - contain no material, this can also be set to "void". A list of materials - can be specified for the "distributed material" feature. This will give each - unique instance of the cell its own material. - - .. note:: If a material is specified, no fill should be given. - - *Default*: None - - :region: - A Boolean expression of half-spaces that defines the spatial region which - the cell occupies. Each half-space is identified by the unique ID of the - surface prefixed by `-` or `+` to indicate that it is the negative or - positive half-space, respectively. The `+` sign for a positive half-space - can be omitted. Valid Boolean operators are parentheses, union `|`, - complement `~`, and intersection. Intersection is implicit and indicated by - the presence of whitespace. The order of operator precedence is parentheses, - complement, intersection, and then union. - - As an example, the following code gives a cell that is the union of the - negative half-space of surface 3 and the complement of the intersection of - the positive half-space of surface 5 and the negative half-space of surface - 2: - - .. code-block:: xml - - - - .. note:: The ``region`` attribute/element can be omitted to make a cell - fill its entire universe. - - *Default*: A region filling all space. - - :temperature: - The temperature of the cell in Kelvin. If windowed-multipole data is - avalable, this temperature will be used to Doppler broaden some cross - sections in the resolved resonance region. A list of temperatures can be - specified for the "distributed temperature" feature. This will give each - unique instance of the cell its own temperature. - - *Default*: If a material default temperature is supplied, it is used. In the - absence of a material default temperature, the :ref:`global default - temperature ` is used. - - :rotation: - If the cell is filled with a universe, this element specifies the angles in - degrees about the x, y, and z axes that the filled universe should be - rotated. Should be given as three real numbers. For example, if you wanted - to rotate the filled universe by 90 degrees about the z-axis, the cell - element would look something like: - - .. code-block:: xml - - - - The rotation applied is an intrinsic rotation whose Tait-Bryan angles are - given as those specified about the x, y, and z axes respectively. That is to - say, if the angles are :math:`(\phi, \theta, \psi)`, then the rotation - matrix applied is :math:`R_z(\psi) R_y(\theta) R_x(\phi)` or - - .. math:: - - \left [ \begin{array}{ccc} \cos\theta \cos\psi & -\cos\phi \sin\psi + - \sin\phi \sin\theta \cos\psi & \sin\phi \sin\psi + \cos\phi \sin\theta - \cos\psi \\ \cos\theta \sin\psi & \cos\phi \cos\psi + \sin\phi \sin\theta - \sin\psi & -\sin\phi \cos\psi + \cos\phi \sin\theta \sin\psi \\ - -\sin\theta & \sin\phi \cos\theta & \cos\phi \cos\theta \end{array} - \right ] - - *Default*: None - - :translation: - If the cell is filled with a universe, this element specifies a vector that - is used to translate (shift) the universe. Should be given as three real - numbers. - - .. note:: Any translation operation is applied after a rotation, if also - specified. - - *Default*: None - - ---------------------- -```` Element ---------------------- - -The ```` can be used to represent repeating structures (e.g. fuel pins -in an assembly) or other geometry which fits onto a rectilinear grid. Each cell -within the lattice is filled with a specified universe. A ```` accepts -the following attributes or sub-elements: - - :id: - A unique integer that can be used to identify the lattice. - - :name: - An optional string name to identify the lattice in summary output - files. This string is limited to 52 characters for formatting purposes. - - *Default*: "" - - :dimension: - Two or three integers representing the number of lattice cells in the x- and - y- (and z-) directions, respectively. - - *Default*: None - - :lower_left: - The coordinates of the lower-left corner of the lattice. If the lattice is - two-dimensional, only the x- and y-coordinates are specified. - - *Default*: None - - :pitch: - If the lattice is 3D, then three real numbers that express the distance - between the centers of lattice cells in the x-, y-, and z- directions. If - the lattice is 2D, then omit the third value. - - *Default*: None - - :outer: - The unique integer identifier of a universe that will be used to fill all - space outside of the lattice. The universe will be tiled repeatedly as if - it were placed in a lattice of infinite size. This element is optional. - - *Default*: An error will be raised if a particle leaves a lattice with no - outer universe. - - :universes: - A list of the universe numbers that fill each cell of the lattice. - - *Default*: None - -Here is an example of a properly defined 2d rectangular lattice: - -.. code-block:: xml - - - -1.5 -1.5 - 1.0 1.0 - - 2 2 2 - 2 1 2 - 2 2 2 - - - -------------------------- -```` Element -------------------------- - -The ```` can be used to represent repeating structures (e.g. fuel -pins in an assembly) or other geometry which naturally fits onto a hexagonal -grid or hexagonal prism grid. Each cell within the lattice is filled with a -specified universe. This lattice uses the "flat-topped hexagon" scheme where two -of the six edges are perpendicular to the y-axis. A ```` accepts -the following attributes or sub-elements: - - :id: - A unique integer that can be used to identify the lattice. - - :name: - An optional string name to identify the hex_lattice in summary output - files. This string is limited to 52 characters for formatting purposes. - - *Default*: "" - - :n_rings: - An integer representing the number of radial ring positions in the xy-plane. - Note that this number includes the degenerate center ring which only has one - element. - - *Default*: None - - :n_axial: - An integer representing the number of positions along the z-axis. This - element is optional. - - *Default*: None - - :orientation: - The orientation of the hexagonal lattice. The string "x" indicates that two - sides of the lattice are parallel to the x-axis, whereas the string "y" - indicates that two sides are parallel to the y-axis. - - *Default*: "y" - - :center: - The coordinates of the center of the lattice. If the lattice does not have - axial sections then only the x- and y-coordinates are specified. - - *Default*: None - - :pitch: - If the lattice is 3D, then two real numbers that express the distance - between the centers of lattice cells in the xy-plane and along the z-axis, - respectively. If the lattice is 2D, then omit the second value. - - *Default*: None - - :outer: - The unique integer identifier of a universe that will be used to fill all - space outside of the lattice. The universe will be tiled repeatedly as if - it were placed in a lattice of infinite size. This element is optional. - - *Default*: An error will be raised if a particle leaves a lattice with no - outer universe. - - :universes: - A list of the universe numbers that fill each cell of the lattice. - - *Default*: None - -Here is an example of a properly defined 2d hexagonal lattice: - -.. code-block:: xml - - -
0.0 0.0
- 1.0 - - 202 - 202 202 - 202 202 202 - 202 202 - 202 101 202 - 202 202 - 202 202 202 - 202 202 - 202 - -
diff --git a/docs/source/io_formats/index.rst b/docs/source/io_formats/index.rst deleted file mode 100644 index 7ae22c0a3..000000000 --- a/docs/source/io_formats/index.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _io_file_formats: - -========================== -File Format Specifications -========================== - -.. _io_file_formats_input: - ------------ -Input Files ------------ - -.. toctree:: - :numbered: - :maxdepth: 1 - - geometry - materials - settings - tallies - plots - ----------- -Data Files ----------- - -.. toctree:: - :numbered: - :maxdepth: 1 - - cross_sections - depletion_chain - nuclear_data - mgxs_library - data_wmp - ------------- -Output Files ------------- - -.. toctree:: - :numbered: - :maxdepth: 1 - - statepoint - source - summary - depletion_results - particle_restart - track - voxel - volume diff --git a/docs/source/io_formats/materials.rst b/docs/source/io_formats/materials.rst deleted file mode 100644 index ac2cfe271..000000000 --- a/docs/source/io_formats/materials.rst +++ /dev/null @@ -1,126 +0,0 @@ -.. _io_materials: - -======================================== -Materials Specification -- materials.xml -======================================== - -.. _cross_sections: - ----------------------------- -```` Element ----------------------------- - -The ```` element has no attributes and simply indicates the path -to an XML cross section listing file (usually named cross_sections.xml). If this -element is absent from the settings.xml file, the -:envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used to find the -path to the XML cross section listing when in continuous-energy mode, and the -:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable will be used in -multi-group mode. - -.. _material: - ----------------------- -```` Element ----------------------- - -Each ``material`` element can have the following attributes or sub-elements: - - :id: - A unique integer that can be used to identify the material. - - :name: - An optional string name to identify the material in summary output - files. This string is limited to 52 characters for formatting purposes. - - *Default*: "" - - :depletable: - Boolean value indicating whether the material is depletable. - - :volume: - Volume of the material in cm^3. - - :temperature: - Temperature of the material in Kelvin. - - *Default*: If a material default temperature is not given and a cell - temperature is not specified, the :ref:`global default temperature - ` is used. - - :density: - An element with attributes/sub-elements called ``value`` and ``units``. The - ``value`` attribute is the numeric value of the density while the ``units`` - can be "g/cm3", "kg/m3", "atom/b-cm", "atom/cm3", or "sum". The "sum" unit - indicates that values appearing in ``ao`` or ``wo`` attributes for ```` - and ```` sub-elements are to be interpreted as absolute nuclide/element - densities in atom/b-cm or g/cm3, and the total density of the material is - taken as the sum of all nuclides/elements. The "macro" unit is used with - a ``macroscopic`` quantity to indicate that the density is already included - in the library and thus not needed here. However, if a value is provided - for the ``value``, then this is treated as a number density multiplier on - the macroscopic cross sections in the multi-group data. This can be used, - for example, when perturbing the density slightly. - - *Default*: None - - .. note:: A ``macroscopic`` quantity can not be used in conjunction with a - ``nuclide``, ``element``, or ``sab`` quantity. - - :nuclide: - An element with attributes/sub-elements called ``name``, and ``ao`` - or ``wo``. The ``name`` attribute is the name of the cross-section for a - desired nuclide. Finally, the ``ao`` and ``wo`` attributes specify the atom or - weight percent of that nuclide within the material, respectively. One - example would be as follows: - - .. code-block:: xml - - - - - .. note:: If one nuclide is specified in atom percent, all others must also - be given in atom percent. The same applies for weight percentages. - - *Default*: None - - :sab: - Associates an S(a,b) table with the material. This element has an - attribute/sub-element called ``name``. The ``name`` attribute - is the name of the S(a,b) table that should be associated with the material. - There is also an optional ``fraction`` element which indicates what fraction - of the relevant nuclides will be affected by the S(a,b) table (e.g. which - fraction of a material is crystalline versus amorphous). ``fraction`` - defaults to unity. - - *Default*: None - - .. 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 - specific macroscopic cross sections instead of always providing nuclide - specific data like in the continuous-energy case. To that end, the - macroscopic element has one attribute/sub-element called ``name``. - The ``name`` attribute is the name of the cross-section for a - desired nuclide. One example would be as follows: - - .. code-block:: xml - - - - .. note:: This element is only used in the multi-group :ref:`energy_mode`. - - *Default*: None diff --git a/docs/source/io_formats/mgxs_library.rst b/docs/source/io_formats/mgxs_library.rst deleted file mode 100644 index 4129ed4ba..000000000 --- a/docs/source/io_formats/mgxs_library.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. _io_mgxs_library: - -======================================== -Multi-Group Cross Section Library Format -======================================== - -OpenMC can be run in continuous-energy mode or multi-group mode, provided the -nuclear data is available. In continuous-energy mode, the -``cross_sections.xml`` file contains necessary meta-data for each dataset, -including the name and a file system location where the complete library -can be found. In multi-group mode, the multi-group meta-data and the -nuclear data itself is contained within an ``mgxs.h5`` file. This portion of -the manual describes the format of the multi-group data library required -to be used in the ``mgxs.h5`` file. - -The multi-group library is provided in the HDF5_ format. This library must -provide some meta-data about the library itself (such as the number of -energy groups, delayed groups, and the energy group structure, etc.) as -well as the actual cross section data itself for each of the necessary -nuclides or materials. - -The current version of the multi-group library file format is 1.0. - -.. _HDF5: http://www.hdfgroup.org/HDF5/ - -.. _mgxs_lib_spec: - --------------------------- -MGXS Library Specification --------------------------- - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file; - for this library it will be 'mgxs'. - - **version** (*int[2]*) -- Major and minor version of the - multi-group library file format. - - **energy_groups** (*int*) -- Number of energy groups - - **delayed_groups** (*int*) -- Number of delayed groups (optional) - - **group structure** (*double[]*) -- Monotonically increasing - list of group boundaries, in units of eV. The length of this - array should be the number of groups plus 1. - -**//** - -The data within contains the temperature-dependent multi-group -data for the nuclide or material that it represents. - -:Attributes: - **atomic_weight_ratio** (*double*) -- The atomic weight ratio - (optional, i.e. it is not meaningful for material-wise data). - - **fissionable** (*bool*) -- Whether the dataset is fissionable - (True) or not (False). - - **representation** (*char[]*) -- The method used to generate and - represent the multi-group cross sections. That is, whether they - were generated with scalar flux weighting (or reduced to a - similar representation) and thus are angle-independent, or if the - data was generated with angular dependent fluxes and thus the - data is angle-dependent. Valid values are either "isotropic" or - "angle". - - **num_azimuthal** (*int*) -- Number of equal width angular bins - that the azimuthal angular domain is subdivided if the - `representation` attribute is "angle". This parameter is - ignored otherwise. - - **num_polar** (*int*) -- Number of equal width angular bins - that the polar angular domain is subdivided if the - `representation` attribute is "angle". This parameter is - ignored otherwise. - - **scatter_format** (*char[]*) -- The representation of the - scattering angular distribution. The options are either - "legendre", "histogram", or "tabular". If not provided, the - default of "legendre" will be assumed. - - **order** (*int*) -- Either the Legendre order, number of bins, - or number of points (depending on the value of `scatter_format`) - used to describe the angular distribution associated with each - group-to-group transfer probability. - - **scatter_shape** (*char[]*) -- The shape of the provided - scatter and multiplicity matrix. The values provided are strings - describing the ordering the scattering array is provided in - row-major (i.e., C/C++ and Python) indexing. Valid values are - "[Order][G][G']" or "[Order][G'][G]" where "G'" denotes the - secondary/outgoing energy groups, "G" denotes the incoming - energy groups, and "Order" is the angular distribution index. - This value is not required; if not the default value of - "[Order][G][G']" will be assumed. - -**//kTs/** - -:Datasets: - - **K** (*double*) -- kT values (in eV) for each temperature - TTT (in Kelvin), rounded to the nearest integer - -**//K/** - -Temperature-dependent data, provided for temperature K. - -:Datasets: - **total** (*double[]* or *double[][][]*) -- Total cross section. - This is a 1-D vector if `representation` is "isotropic", or a 3-D - vector if `representation` is "angle" with dimensions of - [polar][azimuthal][groups]. - - **absorption** (*double[]* or *double[][][]*) -- Absorption - cross section. - This is a 1-D vector if `representation` is "isotropic", or a 3-D - vector if `representation` is "angle" with dimensions of - [groups][azimuthal][polar]. - - **fission** (*double[]* or *double[][][]*) -- Fission - cross section. - This is a 1-D vector if `representation` is "isotropic", or a 3-D - vector if `representation` is "angle" with dimensions of - [polar][azimuthal][groups]. This is only required if the dataset - is fissionable and fission-tallies are expected to be used. - - **kappa-fission** (*double[]* or *double[][][]*) -- Kappa-Fission - (energy-release from fission) cross section. - This is a 1-D vector if `representation` is "isotropic", or a 3-D - vector if `representation` is "angle" with dimensions of - [polar][azimuthal][groups]. This is only required if the dataset - is fissionable and fission-tallies are expected to be used. - - **chi** (*double[]* or *double[][][]*) -- Fission neutron energy - spectra. - This is a 1-D vector if `representation` is "isotropic", or a 3-D - vector if `representation` is "angle" with dimensions of - [polar][azimuthal][groups]. This is only required if the dataset - is fissionable and fission-tallies are expected to be used. - - **nu-fission** (*double[]* to *double[][][][]*) -- Nu-Fission - cross section. - If **chi** is provided, then `nu-fission` has the same - dimensionality as `fission`. If **chi** is not provided, then - the `nu-fission` data must represent the fission neutron energy - spectra as well and thus will have one additional dimension - for the outgoing energy group. In this case, `nu-fission` has the - same dimensionality as `multiplicity matrix`. - - **inverse-velocity** (*double[]* or *double[][][]*) -- - Average inverse velocity for each of the groups in the library. - This dataset is optional. This is a 1-D vector if `representation` - is "isotropic", or a 3-D vector if `representation` is "angle" - with dimensions of [polar][azimuthal][groups]. - -**//K/scatter_data/** - -Data specific to neutron scattering for the temperature K - -:Datasets: - **g_min** (*int[]* or *int[][][]*) -- - Minimum (most energetic) groups with non-zero values of - the scattering matrix provided. If `scatter_shape` is - "[Order][G][G']" then `g_min` will describe the minimum values - of "G'" for each "G"; if `scatter_shape` is "[Order][G'][G]" - then `g_min` will describe the minimum values of "G" for each "G'". - These group numbers use the standard - ordering where the fastest neutron energy group is group 1 while - the slowest neutron energy group is group G. - The dimensionality of `g_min` is: - `g_min[g]`, or `g_min[num_polar][num_azimuthal][g]`. - The former is used when `representation` is "isotropic", and the - latter when `representation` is "angle". - - **g_max** (*int[]* or *int[][][]*) -- - Similar to `g_min`, except this dataset describes the maximum - (least energetic) groups with non-zero values of - the scattering matrix. - - **scatter_matrix** (*double[]*) -- Flattened representation of the - scattering moment matrices. The pre-flattened array corresponds to - the shape provied in `scatter_shape`, but if `representation` is - "angle" the dimensionality in `scatter_shape` is prepended by - "[num_polar][num_azimuthal]" dimensions. The right-most energy - group dimension will only include the entries between `g_min` and - `g_max`. - dimension has a dimensionality of `g_min` to `g_max`. - - **multiplicity_matrix** (*double[]*) -- Flattened representation of - the scattering moment matrices. This dataset provides the code with - a scaling factor to account for neutrons being produced in (n,xn) - reactions. This is assumed isotropic and therefore is not repeated - for every Legendre moment or histogram/tabular bin. This dataset is - optional, if it is not provided no multiplication (i.e., values of - 1.0) will be assumed. - The pre-flattened array is shapes consistent with `scatter_matrix` - except the "[Order]" dimension in `scatter_shape` is ignored since - this data is assumed isotropic. diff --git a/docs/source/io_formats/nuclear_data.rst b/docs/source/io_formats/nuclear_data.rst deleted file mode 100644 index ef61604cb..000000000 --- a/docs/source/io_formats/nuclear_data.rst +++ /dev/null @@ -1,592 +0,0 @@ -.. _io_nuclear_data: - -========================= -Nuclear Data File Formats -========================= - ---------------------- -Incident Neutron Data ---------------------- - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file - - **version** (*int[2]*) -- Major and minor version of the data - -**//** - -:Attributes: - **Z** (*int*) -- Atomic number - - **A** (*int*) -- Mass number. For a natural element, A=0 is given. - - **metastable** (*int*) -- Metastable state (0=ground, 1=first - excited, etc.) - - **atomic_weight_ratio** (*double*) -- Mass in units of neutron masses - - **n_reaction** (*int*) -- Number of reactions - -:Datasets: - - **energy** (*double[]*) -- Energies in [eV] at which cross sections - are tabulated - -**//kTs/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Datasets: - - **K** (*double*) -- kT values in [eV] for each temperature - TTT (in Kelvin) - -**//reactions/reaction_/** - -:Attributes: - **mt** (*int*) -- ENDF MT reaction number - - **label** (*char[]*) -- Name of the reaction - - **Q_value** (*double*) -- Q value in eV - - **center_of_mass** (*int*) -- Whether the reference frame for - scattering is center-of-mass (1) or laboratory (0) - - **n_product** (*int*) -- Number of reaction products - - **redundant** (*int*) -- Whether reaction is redundant - -**//reactions/reaction_/K/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Datasets: - - **xs** (*double[]*) -- Cross section values tabulated against the - nuclide energy grid for temperature TTT (in Kelvin) - - :Attributes: - - **threshold_idx** (*int*) -- Index on the energy - grid that the reaction threshold corresponds to for - temperature TTT (in Kelvin) - -**//reactions/reaction_/product_/** - - Reaction product data is described in :ref:`product`. - -**//urr/K/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Attributes: - **interpolation** (*int*) -- interpolation scheme - - **inelastic** (*int*) -- flag indicating inelastic scattering - - **other_absorb** (*int*) -- flag indicating other absorption - - **factors** (*int*) -- flag indicating whether tables are - absolute or multipliers - -:Datasets: - **energy** (*double[]*) -- Energy at which probability tables exist - - **table** (*double[][][]*) -- Probability tables - -**//total_nu/** - - This special product is used to define the total number of neutrons produced - from fission. It is formatted as a reaction product, described in - :ref:`product`. - -**//fission_energy_release/** - -:Datasets: - **fragments** (:ref:`function <1d_functions>`) -- Energy - released in the form of fragments as a function of incident - neutron energy. - - **prompt_neutrons** (:ref:`function <1d_functions>`) -- Energy - released in the form of prompt neutrons as a function of incident - neutron energy. - - **delayed_neutrons** (:ref:`function <1d_functions>`) -- Energy - released in the form of delayed neutrons as a function of incident - neutron energy. - - **prompt_photons** (:ref:`function <1d_functions>`) -- Energy - released in the form of prompt photons as a function of incident - neutron energy. - - **delayed_photons** (:ref:`function <1d_functions>`) -- Energy - released in the form of delayed photons as a function of incident - neutron energy. - - **betas** (:ref:`function <1d_functions>`) -- Energy released in - the form of betas as a function of incident neutron energy. - - **neutrinos** (:ref:`function <1d_functions>`) -- Energy released - in the form of neutrinos as a function of incident neutron energy. - - **q_prompt** (:ref:`function <1d_functions>`) -- The prompt fission - Q-value (fragments + prompt neutrons + prompt photons - incident - energy) - - **q_recoverable** (:ref:`function <1d_functions>`) -- The - recoverable fission Q-value (Q_prompt + delayed neutrons + delayed - photons + betas) - --------------------- -Incident Photon Data --------------------- - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file - - **version** (*int[2]*) -- Major and minor version of the data - -**//** - -:Attributes: - **Z** (*int*) -- Atomic number - -:Datasets: - - **energy** (*double[]*) -- Energies in [eV] at which cross sections - are tabulated - -**//bremsstrahlung/** - -:Attributes: - **I** (*double*) -- Mean excitation energy in [eV] - -:Datasets: - **electron_energy** (*double[]*) -- Incident electron energy in [eV] - - **photon_energy** (*double[]*) -- Outgoing photon energy as - fraction of incident electron energy - - **dcs** (*double[][]*) -- Bremsstrahlung differential cross section - at each incident energy in [mb/eV] - - **ionization_energy** (*double[]*) -- Ionization potential of each - subshell in [eV] - - **num_electrons** (*int[]*) -- Number of electrons per subshell, - with conduction electrons indicated by a negative value - -**//coherent/** - -:Datasets: - **xs** (*double[]*) -- Coherent scattering cross section in [b] - - **integrated_scattering_factor** (:ref:`tabulated <1d_tabulated>`) - -- Integrated coherent scattering form factor - - **anomalous_real** (:ref:`tabulated <1d_tabulated>`) -- Real part - of the anomalous scattering factor - - **anomalous_imag** (:ref:`tabulated <1d_tabulated>`) -- Imaginary - part of the anomalous scattering factor - -**//compton_profiles/** - -:Datasets: - **binding_energy** (*double[]*) -- Binding energy for each subshell in [eV] - - **num_electrons** (*double[]*) -- Number of electrons in each subshell - - **pz** (*double[]*) -- Projection of the electron momentum on the - scattering vector in units of :math:`me^2 / \hbar` where :math:`m` - is the electron rest mass and :math:`e` is the electron charge - - **J** (*double[][]*) -- Compton profile for each subshell in units - of :math:`\hbar / (me^2)` - -**//heating/** - -:Datasets: - **xs** (*double[]*) -- Total heating cross section in [b-eV] - -**//incoherent/** - -:Datasets: - **xs** (*double[]*) -- Incoherent scattering cross section in [b] - - **scattering_factor** (:ref:`tabulated <1d_tabulated>`) -- - -**//pair_production_electron/** - -:Datasets: - **xs** (*double[]*) -- Pair production (electron field) cross section in [b] - -**//pair_production_nuclear/** - -:Datasets: - **xs** (*double[]*) -- Pair production (nuclear field) cross section in [b] - -**//photoelectric/** - -:Datasets: - **xs** (*double[]*) -- Total photoionization cross section in [b] - -**//subshells/** - -:Attributes: - **designators** (*char[][]*) -- Designator for each shell, e.g. 'M2' - -**//subshells//** - -:Attributes: - **binding_energy** (*double*) -- Binding energy of the subshell in [eV] - - **num_electrons** (*double*) -- Number of electrons in the subshell - -:Datasets: - **transitions** (*double[][]*) -- Atomic relaxation data - - **xs** (*double[]*) -- Photoionization cross section for subshell - in [b] tabulated against the main energy grid - - :Attributes: - - **threshold_idx** (*int*) -- Index on the energy - grid of the reaction threshold - -------------------------------- -Thermal Neutron Scattering Data -------------------------------- - -**/** - -:Attributes: - - **version** (*int[2]*) -- Major and minor version of the data - -**//** - -:Attributes: - **atomic_weight_ratio** (*double*) -- Mass in units of neutron masses - - **energy_max** (*double*) -- Maximum energy in [eV] - - **nuclides** (*char[][]*) -- Names of nuclides for which the - thermal scattering data applies to - -**//kTs/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Datasets: - - **K** (*double*) -- kT values (in eV) for each temperature - TTT (in Kelvin) - -**//elastic/K/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Datasets: - - **xs** (:ref:`function <1d_functions>`) -- Thermal elastic - scattering cross section for temperature TTT (in Kelvin) - -:Groups: - - **distribution** -- Format for angle-energy distributions are - detailed in :ref:`angle_energy`. - -**//inelastic/K/** - -K is the temperature in Kelvin, rounded to the nearest integer, of the -temperature-dependent data set. For example, the data set corresponding to -300 Kelvin would be located at `300K`. - -:Datasets: - - **xs** (:ref:`function <1d_functions>`) -- Thermal inelastic - scattering cross section for temperature TTT (in Kelvin) - -:Groups: - - **distribution** -- Format for angle-energy distributions are - detailed in :ref:`angle_energy`. - -.. _product: - ------------------ -Reaction Products ------------------ - -:Object type: Group -:Attributes: - **particle** (*char[]*) -- Type of particle - - **emission_mode** (*char[]*) -- Emission mode (prompt, delayed, - total) - - **decay_rate** (*double*) -- Rate of decay in inverse seconds - - **n_distribution** (*int*) -- Number of angle/energy - distributions -:Datasets: - - **yield** (:ref:`function <1d_functions>`) -- Energy-dependent - yield of the product. - -:Groups: - - **distribution_** -- Formats for angle-energy distributions are - detailed in :ref:`angle_energy`. When multiple angle-energy - distributions occur, one dataset also may appear for each - distribution: - - :Datasets: - - **applicability** (:ref:`function <1d_functions>`) -- - Probability of selecting this distribution as a function - of incident energy - -.. _1d_functions: - -------------------------- -One-dimensional Functions -------------------------- - -Scalar ------- - -:Object type: Dataset -:Datatype: *double* -:Attributes: - **type** (*char[]*) -- 'constant' - -.. _1d_tabulated: - -Tabulated ---------- - -:Object type: Dataset -:Datatype: *double[2][]* -:Description: x-values are listed first followed by corresponding y-values -:Attributes: - **type** (*char[]*) -- 'Tabulated1D' - - **breakpoints** (*int[]*) -- Region breakpoints - - **interpolation** (*int[]*) -- Region interpolation codes - -.. _1d_polynomial: - -Polynomial ----------- - -:Object type: Dataset -:Datatype: *double[]* -:Description: Polynomial coefficients listed in order of increasing power -:Attributes: - **type** (*char[]*) -- 'Polynomial' - -Coherent elastic scattering ---------------------------- - -:Object type: Dataset -:Datatype: *double[2][]* -:Description: The first row lists Bragg edges and the second row lists structure - factor cumulative sums. -:Attributes: - **type** (*char[]*) -- 'CoherentElastic' - -Incoherent elastic scattering ------------------------------ - -:Object type: Dataset -:Datatype: *double[2]* -:Description: The first value is the characteristic bound cross section in [b] - and the second value is the Debye-Waller integral in - [eV\ :math:`^{-1}`]. -:Attributes: - **type** (*char[]*) -- 'IncoherentElastic' - -.. _angle_energy: - --------------------------- -Angle-Energy Distributions --------------------------- - -Uncorrelated Angle-Energy -------------------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'uncorrelated' -:Datasets: - **angle/energy** (*double[]*) -- energies at which angle distributions exist - - **angle/mu** (*double[3][]*) -- tabulated angular distributions for - each energy. The first row gives :math:`\mu` values, the second row - gives the probability density, and the third row gives the - cumulative distribution. - - :Attributes: - **offsets** (*int[]*) -- indices indicating where - each angular distribution starts - - **interpolation** (*int[]*) -- interpolation code - for each angular distribution - -:Groups: - **energy/** (:ref:`energy distribution `) - -.. _correlated_angle_energy: - -Correlated Angle-Energy ------------------------ - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'correlated' -:Datasets: - **energy** (*double[]*) -- Incoming energies at which distributions exist - - :Attributes: - - **interpolation** (*double[2][]*) -- Breakpoints and - interpolation codes for incoming energy regions - - - **energy_out** (*double[5][]*) -- Distribution of outgoing energies - corresponding to each incoming energy. The distributions are - flattened into a single array; the start of a given distribution - can be determined using the ``offsets`` attribute. The first row - gives outgoing energies, the second row gives the probability - density, the third row gives the cumulative distribution, the - fourth row gives interpolation codes for angular distributions, and - the fifth row gives offsets for angular distributions. - - :Attributes: - **offsets** (*double[]*) -- Offset for each - distribution - - **interpolation** (*int[]*) -- Interpolation code - for each distribution - - **n_discrete_lines** (*int[]*) -- Number of discrete - lines in each distribution - - - **mu** (*double[3][]*) -- Distribution of angular cosines - corresponding to each pair of incoming and outgoing energies. The - distributions are flattened into a single array; the start of a - given distribution can be determined using offsets in the fifth row - of the ``energy_out`` dataset. The first row gives angular cosines, - the second row gives the probability density, and the third row - gives the cumulative distribution. - -Kalbach-Mann ------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'kalbach-mann' -:Datasets: - **energy** (*double[]*) -- Incoming energies at which distributions exist - - :Attributes: - - **interpolation** (*double[2][]*) -- Breakpoints and - interpolation codes for incoming energy regions - - - **distribution** (*double[5][]*) -- Distribution of outgoing - energies and angles corresponding to each incoming energy. The - distributions are flattened into a single array; the start of a - given distribution can be determined using the ``offsets`` - attribute. The first row gives outgoing energies, the second row - gives the probability density, the third row gives the cumulative - distribution, the fourth row gives Kalbach-Mann precompound - factors, and the fifth row gives Kalbach-Mann angular distribution - slopes. - - :Attributes: - **offsets** (*double[]*) -- Offset for each - distribution - - **interpolation** (*int[]*) -- Interpolation code - for each distribution - - **n_discrete_lines** (*int[]*) -- Number of discrete - lines in each distribution - -N-Body Phase Space ------------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'nbody' - - **total_mass** (*double*) -- Total mass of product particles - - **n_particles** (*int*) -- Number of product particles - - **atomic_weight_ratio** (*double*) -- Atomic weight ratio of the - target nuclide in neutron masses - - **q_value** (*double*) -- Q value for the reaction in eV - -Coherent Elastic ----------------- - -This angle-energy distribution is used specifically for coherent elastic thermal -neutron scattering. - -:Object type: Group -:Attributes: - **type** (*char[]*) -- "coherent_elastic" -:Hard link: - **xs** -- Link to the coherent elastic scattering cross section - -Incoherent Elastic ------------------- - -This angle-energy distribution is used specifically for incoherent elastic -thermal neutron scattering (derived from an ENDF file directly). - -:Object type: Group -:Attributes: - **type** (*char[]*) -- "incoherent_elastic" -:Datasets: - - **debye_waller** (*double*) -- Debye-Waller integral in - [eV\ :math:`^{-1}`] - -Incoherent Elastic (Discrete) ------------------------------ - -This angle-energy distribution is used for discretized incoherent elastic -thermal neutron scattering distributions that are present in ACE files. - -:Object type: Group -:Attributes: - **type** (*char[]*) -- "incoherent_elastic_discrete" -:Datasets: - - **mu_out** (*double[][]*) -- Equiprobable discrete outgoing - angles for each incident neutron energy tabulated - -Incoherent Inelastic --------------------- - -This angle-energy distribution is used specifically for (continuous) incoherent -inelastic thermal neutron scattering. - -:Object type: Group -:Attributes: - **type** (*char[]*) -- "incoherent_inelastic" -:Datasets: The datasets for this angle-energy distribution are the same as for - :ref:`correlated angle-energy distributions - `. - -Incoherent Inelastic (Discrete) -------------------------------- - -This angle-energy distribution is used specifically for incoherent inelastic -thermal neutron scattering where the distributions have been discretized into -equiprobable bins. - -:Object type: Group -:Attributes: - **type** (*char[]*) -- "incoherent_inelastic_discrete" -:Datasets: - **energy_out** (*double[][]*) -- Distribution of outgoing - energies for each incoming energy. - - **mu_out** (*double[][][]*) -- Distribution of scattering cosines - for each pair of incoming and outgoing energies. - - **skewed** (*int8_t*) -- Whether discrete angles are equi-probable - (0) or have a skewed distribution (1). - -.. _energy_distribution: - --------------------- -Energy Distributions --------------------- - -Maxwell -------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'maxwell' - - **u** (*double*) -- Restriction energy in eV -:Datasets: - - **theta** (:ref:`tabulated <1d_tabulated>`) -- Maxwellian - temperature as a function of energy - -Evaporation ------------ - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'evaporation' - - **u** (*double*) -- Restriction energy in eV -:Datasets: - - **theta** (:ref:`tabulated <1d_tabulated>`) -- Evaporation - temperature as a function of energy - -Watt Fission Spectrum ---------------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'watt' - - **u** (*double*) -- Restriction energy in eV -:Datasets: - **a** (:ref:`tabulated <1d_tabulated>`) -- Watt parameter :math:`a` - as a function of incident energy - - **b** (:ref:`tabulated <1d_tabulated>`) -- Watt parameter :math:`b` - as a function of incident energy - -Madland-Nix ------------ - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'watt' - - **efl** (*double*) -- Average energy of light fragment in eV - - **efh** (*double*) -- Average energy of heavy fragment in eV - -Discrete Photon ---------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'discrete_photon' - - **primary_flag** (*int*) -- Whether photon is a primary - - **energy** (*double*) -- Photon energy in eV - - **atomic_weight_ratio** (*double*) -- Atomic weight ratio of - target nuclide in neutron masses - -Level Inelastic ---------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'level' - - **threshold** (*double*) -- Energy threshold in the laboratory - system in eV - - **mass_ratio** (*double*) -- :math:`(A/(A + 1))^2` - -Continuous Tabular ------------------- - -:Object type: Group -:Attributes: - **type** (*char[]*) -- 'continuous' -:Datasets: - **energy** (*double[]*) -- Incoming energies at which distributions exist - - :Attributes: - - **interpolation** (*double[2][]*) -- Breakpoints and - interpolation codes for incoming energy regions - - - **distribution** (*double[3][]*) -- Distribution of outgoing - energies corresponding to each incoming energy. The distributions - are flattened into a single array; the start of a given - distribution can be determined using the ``offsets`` attribute. The - first row gives outgoing energies, the second row gives the - probability density, and the third row gives the cumulative - distribution. - - :Attributes: - **offsets** (*double[]*) -- Offset for each - distribution - - **interpolation** (*int[]*) -- Interpolation code - for each distribution - - **n_discrete_lines** (*int[]*) -- Number of discrete - lines in each distribution diff --git a/docs/source/io_formats/particle_restart.rst b/docs/source/io_formats/particle_restart.rst deleted file mode 100644 index 6ebf7e7ba..000000000 --- a/docs/source/io_formats/particle_restart.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _io_particle_restart: - -============================ -Particle Restart File Format -============================ - -The current version of the particle restart file format is 2.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the particle - restart file format. - - **openmc_version** (*int[3]*) -- Major, minor, and release - version number for OpenMC. - - **git_sha1** (*char[40]*) -- Git commit SHA-1 hash. - -:Datasets: - **current_batch** (*int*) -- The number of batches already - simulated. - - **generations_per_batch** (*int*) -- Number of generations per - batch. - - **current_generation** (*int*) -- The number of generations already - simulated. - - **n_particles** (*int8_t*) -- Number of particles used per - generation. - - **run_mode** (*char[]*) -- Run mode used, either 'fixed source', - 'eigenvalue', or 'particle restart'. - - **id** (*int8_t*) -- Unique identifier of the particle. - - **weight** (*double*) -- Weight of the particle. - - **energy** (*double*) -- Energy of the particle in eV for - continuous-energy mode, or the energy group of the particle for - multi-group mode. - - **xyz** (*double[3]*) -- Position of the particle. - - **uvw** (*double[3]*) -- Direction of the particle. diff --git a/docs/source/io_formats/plots.rst b/docs/source/io_formats/plots.rst deleted file mode 100644 index 966d2b802..000000000 --- a/docs/source/io_formats/plots.rst +++ /dev/null @@ -1,192 +0,0 @@ -.. _io_plots: - -============================================ -Geometry Plotting Specification -- plots.xml -============================================ - -Basic plotting capabilities are available in OpenMC by creating a plots.xml file -and subsequently running with the ``--plot`` command-line flag. The root element -of the plots.xml is simply ```` and any number output plots can be -defined with ```` sub-elements. Two plot types are currently implemented -in openMC: - -* ``slice`` 2D pixel plot along one of the major axes. Produces a PPM image - file. -* ``voxel`` 3D voxel data dump. Produces a binary file containing voxel xyz - position and cell or material id. - - ------------------- -```` Element ------------------- - -Each plot is specified by a combination of the following attributes or -sub-elements: - - :id: - The unique ``id`` of the plot. - - *Default*: None - Required entry - - :filename: - Filename for the output plot file. - - *Default*: "plot" - - :color_by: - Keyword for plot coloring. This can be either "cell" or "material", which - colors regions by cells and materials, respectively. For voxel plots, this - determines which id (cell or material) is associated with each position. - - *Default*: "cell" - - :level: - Universe depth to plot at (optional). This parameter controls how many - universe levels deep to pull cell and material ids from when setting plot - colors. If a given location does not have as many levels as specified, - colors will be taken from the lowest level at that location. For example, if - ``level`` is set to zero colors will be taken from top-level (universe zero) - cells only. However, if ``level`` is set to 1 colors will be taken from - cells in universes that fill top-level fill-cells, and from top-level cells - that contain materials. - - *Default*: Whatever the deepest universe is in the model - - :origin: - Specifies the (x,y,z) coordinate of the center of the plot. Should be three - floats separated by spaces. - - *Default*: None - Required entry - - :width: - Specifies the width of the plot along each of the basis directions. Should - be two or three floats separated by spaces for 2D plots and 3D plots, - respectively. - - *Default*: None - Required entry - - :type: - Keyword for type of plot to be produced. Currently only "slice" and "voxel" - plots are implemented. The "slice" plot type creates 2D pixel maps saved in - the PPM file format. PPM files can be displayed in most viewers (e.g. the - default Gnome viewer, IrfanView, etc.). The "voxel" plot type produces a - binary datafile containing voxel grid positioning and the cell or material - (specified by the ``color`` tag) at the center of each voxel. These - datafiles can be processed into VTK files using the :ref:`scripts_voxel` - script provided with OpenMC, and subsequently viewed with a 3D viewer such - as VISIT or Paraview. See the :ref:`io_voxel` for information about the - datafile structure. - - .. note:: Since the PPM format is saved without any kind of compression, - the resulting file sizes can be quite large. Saving the image in - the PNG format can often times reduce the file size by orders of - magnitude without any loss of image quality. Likewise, - high-resolution voxel files produced by OpenMC can be quite large, - but the equivalent VTK files will be significantly smaller. - - *Default*: "slice" - -```` elements of ``type`` "slice" and "voxel" must contain the ``pixels`` -attribute or sub-element: - - :pixels: - Specifies the number of pixels or voxels to be used along each of the basis - directions for "slice" and "voxel" plots, respectively. Should be two or - three integers separated by spaces. - - .. warning:: The ``pixels`` input determines the output file size. For the - PPM format, 10 million pixels will result in a file just under - 30 MB in size. A 10 million voxel binary file will be around - 40 MB. - - .. warning:: If the aspect ratio defined in ``pixels`` does not match the - aspect ratio defined in ``width`` the plot may appear stretched - or squeezed. - - .. warning:: Geometry features along a basis direction smaller than - ``width``/``pixels`` along that basis direction may not appear - in the plot. - - *Default*: None - Required entry for "slice" and "voxel" plots - -```` elements of ``type`` "slice" can also contain the following -attributes or sub-elements. These are not used in "voxel" plots: - - :basis: - Keyword specifying the plane of the plot for "slice" type plots. Can be - one of: "xy", "xz", "yz". - - *Default*: "xy" - - :background: - Specifies the RGB color of the regions where no OpenMC cell can be found. - Should be three integers separated by spaces. - - *Default*: 0 0 0 (black) - - :color: - Any number of this optional tag may be included in each ```` element, - which can override the default random colors for cells or materials. Each - ``color`` element must contain ``id`` and ``rgb`` sub-elements. - - :id: - Specifies the cell or material unique id for the color specification. - - :rgb: - Specifies the custom color for the cell or material. Should be 3 integers - separated by spaces. - - As an example, if your plot is colored by material and you want material 23 - to be blue, the corresponding ``color`` element would look like: - - .. code-block:: xml - - - - *Default*: None - - :mask: - The special ``mask`` sub-element allows for the selective plotting of *only* - user-specified cells or materials. Only one ``mask`` element is allowed per - ``plot`` element, and it must contain as attributes or sub-elements a - background masking color and a list of cells or materials to plot: - - :components: - List of unique ``id`` numbers of the cells or materials to plot. Should be - any number of integers separated by spaces. - - :background: - Color to apply to all cells or materials not in the ``components`` list of - cells or materials to plot. This overrides any ``color`` color - specifications. - - *Default*: 255 255 255 (white) - - :meshlines: - The ``meshlines`` sub-element allows for plotting the boundaries of a - regular mesh on top of a plot. Only one ``meshlines`` element is allowed per - ``plot`` element, and it must contain as attributes or sub-elements a mesh - type and a linewidth. Optionally, a color may be specified for the overlay: - - :meshtype: - The type of the mesh to be plotted. Valid options are "tally", "entropy", - "ufs", and "cmfd". If plotting "tally" meshes, the id of the mesh to plot - must be specified with the ``id`` sub-element. - - :id: - A single integer id number for the mesh specified on ``tallies.xml`` that - should be plotted. This element is only required for ``meshtype="tally"``. - - :linewidth: - A single integer number of pixels of linewidth to specify for the mesh - boundaries. Specifying this as 0 indicates that lines will be 1 pixel - thick, specifying 1 indicates 3 pixels thick, specifying 2 indicates - 5 pixels thick, etc. - - :color: - Specifies the custom color for the meshlines boundaries. Should be 3 - integers separated by whitespace. This element is optional. - - *Default*: 0 0 0 (black) - - *Default*: None diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst deleted file mode 100644 index fb55f9e51..000000000 --- a/docs/source/io_formats/settings.rst +++ /dev/null @@ -1,864 +0,0 @@ -.. _io_settings: - -====================================== -Settings Specification -- settings.xml -====================================== - -All simulation parameters and miscellaneous options are specified in the -settings.xml file. - ---------------------- -```` Element ---------------------- - -The ```` element indicates the total number of batches to execute, -where each batch corresponds to a tally realization. In a fixed source -calculation, each batch consists of a number of source particles. In an -eigenvalue calculation, each batch consists of one or many fission source -iterations (generations), where each generation itself consists of a number of -source neutrons. - - *Default*: None - ----------------------------------- -```` Element ----------------------------------- - -The ```` element has no attributes and has an accepted -value of "true" or "false". If set to "true", uncertainties on tally results -will be reported as the half-width of the 95% two-sided confidence interval. If -set to "false", uncertainties on tally results will be reported as the sample -standard deviation. - - *Default*: false - -------------------------------------- -```` Element -------------------------------------- - -The ```` element indicates whether fission neutrons -should be created or not. If this element is set to "true", fission neutrons -will be created; otherwise the fission is treated as capture and no fission -neutron will be created. Note that this option is only applied to fixed source -calculation. For eigenvalue calculation, fission will always be treated as real -fission. - - *Default*: true - --------------------- -```` Element --------------------- - -The ```` element indicates two kinds of cutoffs. The first is the weight -cutoff used below which particles undergo Russian roulette. Surviving particles -are assigned a user-determined weight. Note that weight cutoffs and Russian -rouletting are not turned on by default. The second is the energy cutoff which -is used to kill particles under certain energy. The energy cutoff should not be -used unless you know particles under the energy are of no importance to results -you care. This element has the following attributes/sub-elements: - - :weight: - The weight below which particles undergo Russian roulette. - - *Default*: 0.25 - - :weight_avg: - The weight that is assigned to particles that are not killed after Russian - roulette. - - *Default*: 1.0 - - :energy_neutron: - The energy under which neutrons will be killed. - - *Default*: 0.0 - - :energy_photon: - The energy under which photons will be killed. - - *Default*: 1000.0 - - :energy_electron: - The energy under which electrons will be killed. - - *Default*: 0.0 - - :energy_positron: - The energy under which positrons will be killed. - - *Default*: 0.0 - --------------------------------- -```` Element --------------------------------- - -When the DAGMC mode is enabled, the OpenMC geometry will be read from the file -``dagmc.h5m``. If a :ref:`geometry.xml ` file is present with -``dagmc`` set to ``true``, it will be ignored. - --------------------------------- -```` Element --------------------------------- - -When photon transport is enabled, the ```` element tells -OpenMC whether to deposit all energy from electrons locally (``led``) or create -secondary bremsstrahlung photons (``ttb``). - - *Default*: ttb - -.. _energy_mode: - -------------------------- -```` Element -------------------------- - -The ```` element tells OpenMC if the run-mode should be -continuous-energy or multi-group. Options for entry are: ``continuous-energy`` -or ``multi-group``. - - *Default*: continuous-energy - --------------------------- -```` Element --------------------------- - -The ```` element indicates the ID of a mesh that is to be used for -calculating Shannon entropy. The mesh should cover all possible fissionable -materials in the problem and is specified using a :ref:`mesh_element`. - ------------------------------------ -```` Element ------------------------------------ - -The ```` element indicates the number of total fission -source iterations per batch for an eigenvalue calculation. This element is -ignored for all run modes other than "eigenvalue". - - *Default*: 1 - ----------------------- -```` Element ----------------------- - -The ```` element indicates the number of inactive batches used in a -k-eigenvalue calculation. In general, the starting fission source iterations in -an eigenvalue calculation can not be used to contribute to tallies since the -fission source distribution and eigenvalue are generally not converged -immediately. This element is ignored for all run modes other than "eigenvalue". - - *Default*: 0 - --------------------------- -```` Element --------------------------- - -The ```` element (ignored for all run modes other than -"eigenvalue".) specifies a precision trigger on the combined -:math:`k_{eff}`. The trigger is a convergence criterion on the uncertainty of -the estimated eigenvalue. It has the following attributes/sub-elements: - - :type: - The type of precision trigger. Accepted options are "variance", "std_dev", - and "rel_err". - - :variance: - Variance of the batch mean :math:`\sigma^2` - - :std_dev: - Standard deviation of the batch mean :math:`\sigma` - - :rel_err: - Relative error of the batch mean :math:`\frac{\sigma}{\mu}` - - *Default*: None - - :threshold: - The precision trigger's convergence criterion for the - combined :math:`k_{eff}`. - - *Default*: None - - .. note:: See section on the :ref:`trigger` for more information. - ---------------------------- -```` Element ---------------------------- - -The ```` element indicates the number of bins to use for the -logarithmic-mapped energy grid. Using more bins will result in energy grid -searches over a smaller range at the expense of more memory. The default is -based on the recommended value in LA-UR-14-24530_. - - *Default*: 8000 - - .. note:: This element is not used in the multi-group :ref:`energy_mode`. - -.. _LA-UR-14-24530: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-14-24530.pdf - ---------------------------- -```` Element ---------------------------- - -The ```` element allows the user to set a maximum scattering order -to apply to every nuclide/material in the problem. That is, if the data -library has :math:`P_3` data available, but ```` was set to ``1``, -then, OpenMC will only use up to the :math:`P_1` data. - - *Default*: Use the maximum order in the data library - - .. note:: This element is not used in the continuous-energy - :ref:`energy_mode`. - -.. _mesh_element: - ------------------- -```` Element ------------------- - -The ```` element describes a mesh that is used either for calculating -Shannon entropy, applying the uniform fission site method, or in tallies. For -Shannon entropy meshes, the mesh should cover all possible fissionable materials -in the problem. It has the following attributes/sub-elements: - - :id: - A unique integer that is used to identify the mesh. - - :dimension: - The number of mesh cells in the x, y, and z directions, respectively. - - *Default*: If this tag is not present, the number of mesh cells is - automatically determined by the code. - - :lower_left: - The Cartesian coordinates of the lower-left corner of the mesh. - - *Default*: None - - :upper_right: - The Cartesian coordinates of the upper-right corner of the mesh. - - *Default*: None - ------------------------ -```` Element ------------------------ - -The ```` element has no attributes and has an accepted value of -"true" or "false". If set to "true", all user-defined tallies and global tallies -will not be reduced across processors in a parallel calculation. This means that -the accumulate score in one batch on a single processor is considered as an -independent realization for the tally random variable. For a problem with large -tally data, this option can significantly improve the parallel efficiency. - - *Default*: false - --------------------- -```` Element --------------------- - -The ```` element determines what output files should be written to disk -during the run. The sub-elements are described below, where "true" will write -out the file and "false" will not. - - :summary: - Writes out an HDF5 summary file describing all of the user input files that - were read in. - - *Default*: true - - :tallies: - Write out an ASCII file of tally results. - - *Default*: true - - .. note:: The tally results will always be written to a binary/HDF5 state - point file. - - :path: - Absolute or relative path where all output files should be written to. The - specified path must exist or else OpenMC will abort. - - *Default*: Current working directory - ------------------------ -```` Element ------------------------ - -This element indicates the number of neutrons to simulate per fission source -iteration when a k-eigenvalue calculation is performed or the number of -particles per batch for a fixed source simulation. - - *Default*: None - ------------------------------- -```` Element ------------------------------- - -The ```` element determines whether photon transport is -enabled. This element has no attributes or sub-elements and can be set to -either "false" or "true". - - *Default*: false - ---------------------- -```` Element ---------------------- - -The ```` element determines whether probability tables should be used -in the unresolved resonance range if available. This element has no attributes -or sub-elements and can be set to either "false" or "true". - - *Default*: true - - .. note:: This element is not used in the multi-group :ref:`energy_mode`. - ----------------------------------- -```` Element ----------------------------------- - -The ``resonance_scattering`` element indicates to OpenMC that a method be used -to properly account for resonance elastic scattering (typically for nuclides -with Z > 40). This element can contain one or more of the following attributes -or sub-elements: - - :enable: - Indicates whether a resonance elastic scattering method should be turned - on. Accepts values of "true" or "false". - - *Default*: If the ```` element is present, "true". - - :method: - - Which resonance elastic scattering method is to be applied: "rvs" (relative - velocity sampling) or "dbrc" (Doppler broadening rejection correction). - Descriptions of each of these methods are documented here_. - - .. _here: https://doi.org/10.1016/j.anucene.2017.12.044 - - *Default*: "rvs" - - :energy_min: - The energy in eV above which the resonance elastic scattering method should - be applied. - - *Default*: 0.01 eV - - :energy_max: - The energy in eV below which the resonance elastic scattering method should - be applied. - - *Default*: 1000.0 eV - - :nuclides: - - A list of nuclides to which the resonance elastic scattering method should - be applied. - - *Default*: If ```` is present but the ```` - sub-element is not given, the method is applied to all nuclides with 0 K - elastic scattering data present. - - .. note:: If the ``resonance_scattering`` element is not given, the free gas, - constant cross section scattering model, which has historically been - used by Monte Carlo codes to sample target velocities, is used to - treat the target motion of all nuclides. If - ``resonance_scattering`` is present, the constant cross section - method is applied below ``energy_min`` and the target-at-rest - (asymptotic) kernel is used above ``energy_max``. - - .. note:: This element is not used in the multi-group :ref:`energy_mode`. - ----------------------- -```` Element ----------------------- - -The ```` element indicates which run mode should be used when OpenMC -is executed. This element has no attributes or sub-elements and can be set to -"eigenvalue", "fixed source", "plot", "volume", or "particle restart". - - *Default*: None - ------------------- -```` Element ------------------- - -The ``seed`` element is used to set the seed used for the linear congruential -pseudo-random number generator. - - *Default*: 1 - --------------------- -```` Element --------------------- - -The ``source`` element gives information on an external source distribution to -be used either as the source for a fixed source calculation or the initial -source guess for criticality calculations. Multiple ```` elements may be -specified to define different source distributions. Each one takes the following -attributes/sub-elements: - - :strength: - The strength of the source. If multiple sources are present, the source - strength indicates the relative probability of choosing one source over the - other. - - *Default*: 1.0 - - :particle: - The source particle type, either ``neutron`` or ``photon``. - - *Default*: neutron - - :file: - If this attribute is given, it indicates that the source is to be read from - a binary source file whose path is given by the value of this element. Note, - the number of source sites needs to be the same as the number of particles - simulated in a fission source generation. - - *Default*: None - - :space: - An element specifying the spatial distribution of source sites. This element - has the following attributes: - - :type: - The type of spatial distribution. Valid options are "box", "fission", - "point", and "cartesian". A "box" spatial distribution has coordinates - sampled uniformly in a parallelepiped. A "fission" spatial distribution - samples locations from a "box" distribution but only locations in - fissionable materials are accepted. A "point" spatial distribution has - coordinates specified by a triplet. An "cartesian" spatial distribution - specifies independent distributions of x-, y-, and z-coordinates. - - *Default*: None - - :parameters: - For a "box" or "fission" spatial distribution, ``parameters`` should be - given as six real numbers, the first three of which specify the lower-left - corner of a parallelepiped and the last three of which specify the - upper-right corner. Source sites are sampled uniformly through that - parallelepiped. - - For a "point" spatial distribution, ``parameters`` should be given as - three real numbers which specify the (x,y,z) location of an isotropic - point source. - - For an "cartesian" distribution, no parameters are specified. Instead, - the ``x``, ``y``, and ``z`` elements must be specified. - - *Default*: None - - :x: - For an "cartesian" distribution, this element specifies the distribution - of x-coordinates. The necessary sub-elements/attributes are those of a - univariate probability distribution (see the description in - :ref:`univariate`). - - :y: - For an "cartesian" distribution, this element specifies the distribution - of y-coordinates. The necessary sub-elements/attributes are those of a - univariate probability distribution (see the description in - :ref:`univariate`). - - :z: - For an "cartesian" distribution, this element specifies the distribution - of z-coordinates. The necessary sub-elements/attributes are those of a - univariate probability distribution (see the description in - :ref:`univariate`). - - :angle: - An element specifying the angular distribution of source sites. This element - has the following attributes: - - :type: - The type of angular distribution. Valid options are "isotropic", - "monodirectional", and "mu-phi". The angle of the particle emitted from a - source site is isotropic if the "isotropic" option is given. The angle of - the particle emitted from a source site is the direction specified in the - ``reference_uvw`` element/attribute if "monodirectional" option is - given. The "mu-phi" option produces directions with the cosine of the - polar angle and the azimuthal angle explicitly specified. - - *Default*: isotropic - - :reference_uvw: - The direction from which the polar angle is measured. Represented by the - x-, y-, and z-components of a unit vector. For a monodirectional - distribution, this defines the direction of all sampled particles. - - :mu: - An element specifying the distribution of the cosine of the polar - angle. Only relevant when the type is "mu-phi". The necessary - sub-elements/attributes are those of a univariate probability distribution - (see the description in :ref:`univariate`). - - :phi: - An element specifying the distribution of the azimuthal angle. Only - relevant when the type is "mu-phi". The necessary sub-elements/attributes - are those of a univariate probability distribution (see the description in - :ref:`univariate`). - - :energy: - An element specifying the energy distribution of source sites. The necessary - sub-elements/attributes are those of a univariate probability distribution - (see the description in :ref:`univariate`). - - *Default*: Watt spectrum with :math:`a` = 0.988 MeV and :math:`b` = - 2.249 MeV :sup:`-1` - - :write_initial: - An element specifying whether to write out the initial source bank used at - the beginning of the first batch. The output file is named - "initial_source.h5" - - *Default*: false - -.. _univariate: - -Univariate Probability Distributions -++++++++++++++++++++++++++++++++++++ - -Various components of a source distribution involve probability distributions of -a single random variable, e.g. the distribution of the energy, the distribution -of the polar angle, and the distribution of x-coordinates. Each of these -components supports the same syntax with an element whose tag signifies the -variable and whose sub-elements/attributes are as follows: - -:type: - The type of the distribution. Valid options are "uniform", "discrete", - "tabular", "maxwell", and "watt". The "uniform" option produces variates - sampled from a uniform distribution over a finite interval. The "discrete" - option produces random variates that can assume a finite number of values - (i.e., a distribution characterized by a probability mass function). The - "tabular" option produces random variates sampled from a tabulated - distribution where the density function is either a histogram or - linearly-interpolated between tabulated points. The "watt" option produces - random variates is sampled from a Watt fission spectrum (only used for - energies). The "maxwell" option produce variates sampled from a Maxwell - fission spectrum (only used for energies). - - *Default*: None - -:parameters: - For a "uniform" distribution, ``parameters`` should be given as two real - numbers :math:`a` and :math:`b` that define the interval :math:`[a,b]` over - which random variates are sampled. - - For a "discrete" or "tabular" distribution, ``parameters`` provides the - :math:`(x,p)` pairs defining the discrete/tabular distribution. All :math:`x` - points are given first followed by corresponding :math:`p` points. - - For a "watt" distribution, ``parameters`` should be given as two real numbers - :math:`a` and :math:`b` that parameterize the distribution :math:`p(x) dx = c - e^{-x/a} \sinh \sqrt{b \, x} dx`. - - For a "maxwell" distribution, ``parameters`` should be given as one real - number :math:`a` that parameterizes the distribution :math:`p(x) dx = c x - e^{-x/a} dx`. - - .. note:: The above format should be used even when using the multi-group - :ref:`energy_mode`. -:interpolation: - For a "tabular" distribution, ``interpolation`` can be set to "histogram" or - "linear-linear" thereby specifying how tabular points are to be interpolated. - - *Default*: histogram - -------------------------- -```` Element -------------------------- - -The ```` element indicates at what batches a state point file -should be written. A state point file can be used to restart a run or to get -tally results at any batch. The default behavior when using this tag is to -write out the source bank in the state_point file. This behavior can be -customized by using the ```` element. This element has the -following attributes/sub-elements: - - :batches: - A list of integers separated by spaces indicating at what batches a state - point file should be written. - - *Default*: Last batch only - --------------------------- -```` Element --------------------------- - -The ```` element indicates at what batches the source bank -should be written. The source bank can be either written out within a state -point file or separately in a source point file. This element has the following -attributes/sub-elements: - - :batches: - A list of integers separated by spaces indicating at what batches a state - point file should be written. It should be noted that if the ``separate`` - attribute is not set to "true", this list must be a subset of state point - batches. - - *Default*: Last batch only - - :separate: - If this element is set to "true", a separate binary source point file will - be written. Otherwise, the source sites will be written in the state point - directly. - - *Default*: false - - :write: - If this element is set to "false", source sites are not written - to the state point or source point file. This can substantially reduce the - size of state points if large numbers of particles per batch are used. - - *Default*: true - - :overwrite_latest: - If this element is set to "true", a source point file containing - the source bank will be written out to a separate file named - ``source.binary`` or ``source.h5`` depending on if HDF5 is enabled. - This file will be overwritten at every single batch so that the latest - source bank will be available. It should be noted that a user can set both - this element to "true" and specify batches to write a permanent source bank. - - *Default*: false - ------------------------------- -```` Element ------------------------------- - -The ```` element has no attributes and has an accepted value -of "true" or "false". If set to "true", this option will enable the use of -survival biasing, otherwise known as implicit capture or absorption. - - *Default*: false - -.. _tabular_legendre: - ---------------------------------- -```` Element ---------------------------------- - -The optional ```` element specifies how the multi-group -Legendre scattering kernel is represented if encountered in a multi-group -problem. Specifically, the options are to either convert the Legendre -expansion to a tabular representation or leave it as a set of Legendre -coefficients. Converting to a tabular representation will cost memory but can -allow for a decrease in runtime compared to leaving as a set of Legendre -coefficients. This element has the following attributes/sub-elements: - - :enable: - This attribute/sub-element denotes whether or not the conversion of a - Legendre scattering expansion to the tabular format should be performed or - not. A value of “true” means the conversion should be performed, “false” - means it will not. - - *Default*: true - - :num_points: - If the conversion is to take place the number of tabular points is - required. This attribute/sub-element allows the user to set the desired - number of points. - - *Default*: 33 - - .. note:: This element is only used in the multi-group :ref:`energy_mode`. - -.. _temperature_default: - ---------------------------------- -```` Element ---------------------------------- - -The ```` element specifies a default temperature in Kelvin -that is to be applied to cells in the absence of an explicit cell temperature or -a material default temperature. - - *Default*: 293.6 K - -.. _temperature_method: - --------------------------------- -```` Element --------------------------------- - -The ```` element has an accepted value of "nearest" or -"interpolation". A value of "nearest" indicates that for each -cell, the nearest temperature at which cross sections are given is to be -applied, within a given tolerance (see :ref:`temperature_tolerance`). A value of -"interpolation" indicates that cross sections are to be linear-linear -interpolated between temperatures at which nuclear data are present (see -:ref:`temperature_treatment`). - - *Default*: "nearest" - -.. _temperature_multipole: - ------------------------------------ -```` Element ------------------------------------ - -The ```` element toggles the windowed multipole -capability on or off. If this element is set to "True" and the relevant data is -available, OpenMC will use the windowed multipole method to evaluate and Doppler -broaden cross sections in the resolved resonance range. This override other -methods like "nearest" and "interpolation" in the resolved resonance range. - - *Default*: False - -------------------------------- -```` Element -------------------------------- - -The ```` element specifies a minimum and maximum temperature -in Kelvin above and below which cross sections should be loaded for all nuclides -and thermal scattering tables. This can be used for multi-physics simulations -where the temperatures might change from one iteration to the next. - - *Default*: None - -.. _temperature_tolerance: - ------------------------------------ -```` Element ------------------------------------ - -The ```` element specifies a tolerance in Kelvin that is -to be applied when the "nearest" temperature method is used. For example, if a -cell temperature is 340 K and the tolerance is 15 K, then the closest -temperature in the range of 325 K to 355 K will be used to evaluate cross -sections. - - *Default*: 10 K - -.. _trace: - -------------------- -```` Element -------------------- - -The ```` element can be used to print out detailed information about a -single particle during a simulation. This element should be followed by three -integers: the batch number, generation number, and particle number. - - *Default*: None - -.. _track: - -------------------- -```` Element -------------------- - -The ```` element specifies particles for which OpenMC will output binary -files describing particle position at every step of its transport. This element -should be followed by triplets of integers. Each triplet describes one -particle. The integers in each triplet specify the batch number, generation -number, and particle number, respectively. - - *Default*: None - -.. _trigger: - -------------------------- -```` Element -------------------------- - -OpenMC includes tally precision triggers which allow the user to define -uncertainty thresholds on :math:`k_{eff}` in the ```` subelement -of ``settings.xml``, and/or tallies in ``tallies.xml``. When using triggers, -OpenMC will run until it completes as many batches as defined by ````. -At this point, the uncertainties on all tallied values are computed and compared -with their corresponding trigger thresholds. If any triggers have not been met, -OpenMC will continue until either all trigger thresholds have been satisfied or -```` has been reached. - -The ```` element provides an active "toggle switch" for tally -precision trigger(s), the maximum number of batches and the batch interval. It -has the following attributes/sub-elements: - - :active: - This determines whether or not to use trigger(s). Trigger(s) are used when - this tag is set to "true". - - :max_batches: - This describes the maximum number of batches allowed when using trigger(s). - - .. note:: When max_batches is set, the number of ``batches`` shown in the - ```` element represents minimum number of batches to - simulate when using the trigger(s). - - :batch_interval: - This tag describes the number of batches in between convergence checks. - OpenMC will check if the trigger has been reached at each batch defined - by ``batch_interval`` after the minimum number of batches is reached. - - .. note:: If this tag is not present, the ``batch_interval`` is predicted - dynamically by OpenMC for each convergence check. The predictive - model assumes no correlation between fission sources - distributions from batch-to-batch. This assumption is reasonable - for fixed source and small criticality calculations, but is very - optimistic for highly coupled full-core reactor problems. - - ------------------------- -```` Element ------------------------- - -The ```` element indicates the ID of a mesh that is used for -re-weighting source sites at every generation based on the uniform fission site -methodology described in Kelly et al., "MC21 Analysis of the Nuclear Energy -Agency Monte Carlo Performance Benchmark Problem," Proceedings of *Physor 2012*, -Knoxville, TN (2012). The mesh should cover all possible fissionable materials -in the problem and is specified using a :ref:`mesh_element`. - -.. _verbosity: - ------------------------ -```` Element ------------------------ - -The ```` element tells the code how much information to display to -the standard output. A higher verbosity corresponds to more information being -displayed. The text of this element should be an integer between between 1 -and 10. The verbosity levels are defined as follows: - - :1: don't display any output - :2: only show OpenMC logo - :3: all of the above + headers - :4: all of the above + results - :5: all of the above + file I/O - :6: all of the above + timing statistics and initialization messages - :7: all of the above + :math:`k` by generation - :9: all of the above + indicate when each particle starts - :10: all of the above + event information - - *Default*: 7 - -------------------------- -```` Element -------------------------- - -The ```` element indicates that a stochastic volume calculation -should be run at the beginning of the simulation. This element has the following -sub-elements/attributes: - - :cells: - The unique IDs of cells for which the volume should be estimated. - - *Default*: None - - :samples: - The number of samples used to estimate volumes. - - *Default*: None - - :lower_left: - The lower-left Cartesian coordinates of a bounding box that is used to - sample points within. - - *Default*: None - - :upper_right: - The upper-right Cartesian coordinates of a bounding box that is used to - sample points within. - - *Default*: None diff --git a/docs/source/io_formats/source.rst b/docs/source/io_formats/source.rst deleted file mode 100644 index 6058241e1..000000000 --- a/docs/source/io_formats/source.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _io_source: - -================== -Source File Format -================== - -Normally, source data is stored in a state point file. However, it is possible -to request that the source be written separately, in which case the format used -is that documented here. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - -:Datasets: - - - **source_bank** (Compound type) -- Source bank information for each - particle. The compound type has fields ``wgt``, ``xyz``, ``uvw``, - ``E``, ``delayed_group``, and ``particle``, which represent the - weight, position, direction, energy, energy group, delayed group, - and type of the source particle, respectively. diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst deleted file mode 100644 index 9156e848f..000000000 --- a/docs/source/io_formats/statepoint.rst +++ /dev/null @@ -1,159 +0,0 @@ -.. _io_statepoint: - -======================= -State Point File Format -======================= - -The current version of the statepoint file format is 17.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the - statepoint file format. - - **openmc_version** (*int[3]*) -- Major, minor, and release - version number for OpenMC. - - **git_sha1** (*char[40]*) -- Git commit SHA-1 hash. - - **date_and_time** (*char[]*) -- Date and time the summary was - written. - - **path** (*char[]*) -- Path to directory containing input files. - - **tallies_present** (*int*) -- Flag indicating whether tallies - are present (1) or not (0). - - **source_present** (*int*) -- Flag indicating whether the source - bank is present (1) or not (0). - -:Datasets: - **seed** (*int8_t*) -- Pseudo-random number generator seed. - - **energy_mode** (*char[]*) -- Energy mode of the run, either - 'continuous-energy' or 'multi-group'. - - **run_mode** (*char[]*) -- Run mode used, either 'eigenvalue' or - 'fixed source'. - - **n_particles** (*int8_t*) -- Number of particles used per generation. - - **n_batches** (*int*) -- Number of batches to simulate. - - **current_batch** (*int*) -- The number of batches already simulated. - - **n_inactive** (*int*) -- Number of inactive batches. Only present - when `run_mode` is 'eigenvalue'. - - **generations_per_batch** (*int*) -- Number of generations per - batch. Only present when `run_mode` is 'eigenvalue'. - - **k_generation** (*double[]*) -- k-effective for each generation - simulated. - - **entropy** (*double[]*) -- Shannon entropy for each generation - simulated. - - **k_col_abs** (*double*) -- Sum of product of collision/absorption - estimates of k-effective. - - **k_col_tra** (*double*) -- Sum of product of - collision/track-length estimates of k-effective. - - **k_abs_tra** (*double*) -- Sum of product of - absorption/track-length estimates of k-effective. - - **k_combined** (*double[2]*) -- Mean and standard deviation of a - combined estimate of k-effective. - - **n_realizations** (*int*) -- Number of realizations for global - tallies. - - **global_tallies** (*double[][2]*) -- Accumulated sum and - sum-of-squares for each global tally. - - **source_bank** (Compound type) -- Source bank information for each - particle. The compound type has fields ``wgt``, ``xyz``, ``uvw``, - ``E``, ``g``, and ``delayed_group``, which represent the weight, - position, direction, energy, energy group, and delayed_group of the - source particle, respectively. Only present when `run_mode` is - 'eigenvalue'. - -**/tallies/** - -:Attributes: - **n_tallies** (*int*) -- Number of user-defined tallies. - - **ids** (*int[]*) -- User-defined unique ID of each tally. - -**/tallies/meshes/** - -:Attributes: - **n_meshes** (*int*) -- Number of meshes in the problem. - - **ids** (*int[]*) -- User-defined unique ID of each mesh. - -**/tallies/meshes/mesh /** - -:Datasets: - **type** (*char[]*) -- Type of mesh. - - **dimension** (*int*) -- Number of mesh cells in each dimension. - - **lower_left** (*double[]*) -- Coordinates of lower-left corner of - mesh. - - **upper_right** (*double[]*) -- Coordinates of upper-right corner - of mesh. - - **width** (*double[]*) -- Width of each mesh cell in each - dimension. - -**/tallies/filters/** - -:Attributes: - **n_filters** (*int*) -- Number of filters in the problem. - - **ids** (*int[]*) -- User-defined unique ID of each filter. - -**/tallies/filters/filter /** - -:Datasets: - **type** (*char[]*) -- Type of the j-th filter. Can be 'universe', - 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', - 'energyout', 'distribcell', 'mu', 'polar', 'azimuthal', - 'delayedgroup', or 'energyfunction'. - - **n_bins** (*int*) -- Number of bins for the j-th filter. Not - present for 'energyfunction' filters. - - **bins** (*int[]* or *double[]*) -- Value for each filter bin of - this type. Not present for 'energyfunction' filters. - - **energy** (*double[]*) -- Energy grid points for energyfunction - interpolation. Only used for 'energyfunction' filters. - - **y** (*double[]*) -- Interpolant values for energyfunction - interpolation. Only used for 'energyfunction' filters. - -**/tallies/derivatives/derivative /** - -:Datasets: - **independent variable** (*char[]*) -- Independent variable of - tally derivative. - - **material** (*int*) -- ID of the perturbed material. - - **nuclide** (*char[]*) -- Alias of the perturbed nuclide. - - **estimator** (*char[]*) -- Type of tally estimator, either - 'analog', 'tracklength', or 'collision'. - -**/tallies/tally /** - -:Attributes: - - **internal** (*int*) -- Flag indicating the presence of tally - data (0) or absence of tally data (1). All user defined - tallies will have a value of 0 unless otherwise instructed. - -:Datasets: - **n_realizations** (*int*) -- Number of realizations. - - **n_filters** (*int*) -- Number of filters used. - - **filters** (*int[]*) -- User-defined unique IDs of the filters on - the tally - - **nuclides** (*char[][]*) -- Array of nuclides to tally. Note that - if no nuclide is specified in the user input, a single 'total' - nuclide appears here. - - **derivative** (*int*) -- ID of the derivative applied to the - tally. - - **n_score_bins** (*int*) -- Number of scoring bins for a single - nuclide. - - **score_bins** (*char[][]*) -- Values of specified scores. - - **results** (*double[][][2]*) -- Accumulated sum and sum-of-squares - for each bin of the i-th tally. The first dimension represents - combinations of filter bins, the second dimensions represents - scoring bins, and the third dimension has two entries for the sum - and the sum-of-squares. - -**/runtime/** - -All values are given in seconds and are measured on the master process. - -:Datasets: - **total initialization** (*double*) -- Time spent reading inputs, - allocating arrays, etc. - - **reading cross sections** (*double*) -- Time spent loading cross - section libraries (this is a subset of initialization). - - **simulation** (*double*) -- Time spent between initialization and - finalization. - - **transport** (*double*) -- Time spent transporting particles. - - **inactive batches** (*double*) -- Time spent in the inactive - batches (including non-transport activities like communcating - sites). - - **active batches** (*double*) -- Time spent in the active batches - (including non-transport activities like communicating sites). - - **synchronizing fission bank** (*double*) -- Time spent sampling - source particles from fission sites and communicating them to other - processes for load balancing. - - **sampling source sites** (*double*) -- Time spent sampling source - particles from fission sites. - - **SEND-RECV source sites** (*double*) -- Time spent communicating - source sites between processes for load balancing. - - **accumulating tallies** (*double*) -- Time spent communicating - tally results and evaluating their statistics. diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst deleted file mode 100644 index cf0eca4aa..000000000 --- a/docs/source/io_formats/summary.rst +++ /dev/null @@ -1,143 +0,0 @@ -.. _io_summary: - -=================== -Summary File Format -=================== - -The current version of the summary file format is 6.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the summary - file format. - - **openmc_version** (*int[3]*) -- Major, minor, and release - version number for OpenMC. - - **git_sha1** (*char[40]*) -- Git commit SHA-1 hash. - - **date_and_time** (*char[]*) -- Date and time the summary was - written. - -**/geometry/** - -:Attributes: - **n_cells** (*int*) -- Number of cells in the problem. - - **n_surfaces** (*int*) -- Number of surfaces in the problem. - - **n_universes** (*int*) -- Number of unique universes in the - problem. - - **n_lattices** (*int*) -- Number of lattices in the problem. - - **dagmc** (*int*) -- Indicates that a DAGMC geometry was used - if present. - -**/geometry/cells/cell /** - -:Datasets: - **name** (*char[]*) -- User-defined name of the cell. - - **universe** (*int*) -- Universe assigned to the cell. If none is - specified, the default universe (0) is assigned. - - **fill_type** (*char[]*) -- Type of fill for the cell. Can be - 'material', 'universe', or 'lattice'. - - **material** (*int* or *int[]*) -- Unique ID of the material(s) - assigned to the cell. This dataset is present only if fill_type is - set to 'normal'. The value '-1' signifies void material. The data - is an array if the cell uses distributed materials, otherwise it is - a scalar. - - **temperature** (*double[]*) -- Temperature of the cell in Kelvin. - - **translation** (*double[3]*) -- Translation applied to the fill - universe. This dataset is present only if fill_type is set to - 'universe'. - - **rotation** (*double[3]*) -- Angles in degrees about the x-, y-, - and z-axes for which the fill universe should be rotated. This - dataset is present only if fill_type is set to 'universe'. - - **lattice** (*int*) -- Unique ID of the lattice which fills the - cell. Only present if fill_type is set to 'lattice'. - - **region** (*char[]*) -- Region specification for the cell. - -**/geometry/surfaces/surface /** - -:Datasets: - **name** (*char[]*) -- Name of the surface. - - **type** (*char[]*) -- Type of the surface. Can be 'x-plane', - 'y-plane', 'z-plane', 'plane', 'x-cylinder', 'y-cylinder', - 'z-cylinder', 'sphere', 'x-cone', 'y-cone', 'z-cone', or 'quadric'. - - **coefficients** (*double[]*) -- Array of coefficients that define - the surface. See :ref:`surface_element` for what coefficients are - defined for each surface type. - - **boundary_condition** (*char[]*) -- Boundary condition applied to - the surface. Can be 'transmission', 'vacuum', 'reflective', or - 'periodic'. - -**/geometry/universes/universe /** - -:Datasets: - - **cells** (*int[]*) -- Array of unique IDs of cells that appear in - the universe. - -**/geometry/lattices/lattice /** - -:Datasets: - **name** (*char[]*) -- Name of the lattice. - - **type** (*char[]*) -- Type of the lattice, either 'rectangular' or - 'hexagonal'. - - **pitch** (*double[]*) -- Pitch of the lattice in centimeters. - - **outer** (*int*) -- Outer universe assigned to lattice cells - outside the defined range. - - **universes** (*int[][][]*) -- Three-dimensional array of universes - assigned to each cell of the lattice. - - **dimension** (*int[]*) -- The number of lattice cells in each - direction. This dataset is present only when the 'type' dataset is - set to 'rectangular'. - - **lower_left** (*double[]*) -- The coordinates of the lower-left - corner of the lattice. This dataset is present only when the 'type' - dataset is set to 'rectangular'. - - **n_rings** (*int*) -- Number of radial ring positions in the - xy-plane. This dataset is present only when the 'type' dataset is - set to 'hexagonal'. - - **n_axial** (*int*) -- Number of lattice positions along the - z-axis. This dataset is present only when the 'type' dataset is set - to 'hexagonal'. - - **center** (*double[]*) -- Coordinates of the center of the - lattice. This dataset is present only when the 'type' dataset is - set to 'hexagonal'. - -**/materials/** - -:Attributes: - **n_materials** (*int*) -- Number of materials in the problem. - - -**/materials/material /** - -:Datasets: - **name** (*char[]*) -- Name of the material. - - **atom_density** (*double[]*) -- Total atom density of the material - in atom/b-cm. - - **nuclides** (*char[][]*) -- Array of nuclides present in the - material, e.g., 'U235'. This data set is only present if nuclides - are used. - - **nuclide_densities** (*double[]*) -- Atom density of each nuclide. - This data set is only present if 'nuclides' data set is present. - - **macroscopics** (*char[][]*) -- Array of macroscopic data sets - present in the material. This dataset is only present if - macroscopic data sets are used in multi-group mode. - - **sab_names** (*char[][]*) -- Names of - S(:math:`\alpha,\beta`) tables assigned to the material. - -:Attributes: - **volume** (*double[]*) -- Volume of this material [cm^3]. Only - present if ``volume`` supplied - - **temperature** (*double[]*) -- Temperature of this material [K]. - Only present in ``temperature`` supplied - - **depletable** (*int[]*) -- ``1`` if the material can be depleted, - ``0`` otherwise. Always present - -**/nuclides/** - -:Attributes: - **n_nuclides** (*int*) -- Number of nuclides in the problem. - -:Datasets: - **names** (*char[][]*) -- Names of nuclides. - - **awrs** (*float[]*) -- Atomic weight ratio of each nuclide. - -**/macroscopics/** - -:Attributes: - - **n_macroscopics** (*int*) -- Number of macroscopic data sets - in the problem. - -:Datasets: - **names** (*char[][]*) -- Names of the macroscopic data sets. - -**/tallies/tally /** - -:Datasets: - **name** (*char[]*) -- Name of the tally. diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst deleted file mode 100644 index 0e1cd16f4..000000000 --- a/docs/source/io_formats/tallies.rst +++ /dev/null @@ -1,391 +0,0 @@ -.. _io_tallies: - -==================================== -Tallies Specification -- tallies.xml -==================================== - -The tallies.xml file allows the user to tell the code what results he/she is -interested in, e.g. the fission rate in a given cell or the current across a -given surface. There are two pieces of information that determine what -quantities should be scored. First, one needs to specify what region of phase -space should count towards the tally and secondly, the actual quantity to be -scored also needs to be specified. The first set of parameters we call *filters* -since they effectively serve to filter events, allowing some to score and -preventing others from scoring to the tally. - -The structure of tallies in OpenMC is flexible in that any combination of -filters can be used for a tally. The following types of filter are available: -cell, universe, material, surface, birth region, pre-collision energy, -post-collision energy, and an arbitrary structured mesh. - -The five valid elements in the tallies.xml file are ````, ````, -````, ````, and ````. - -.. _tally: - -------------------- -```` Element -------------------- - -The ```` element accepts the following sub-elements: - - :name: - An optional string name to identify the tally in summary output - files. This string is limited to 52 characters for formatting purposes. - - *Default*: "" - - :filters: - A space-separated list of the IDs of ``filter`` elements. - - :nuclides: - If specified, the scores listed will be for particular nuclides, not the - summation of reactions from all nuclides. The format for nuclides should be - [Atomic symbol]-[Mass number], e.g. "U-235". The reaction rate for all - nuclides can be obtained with "total". For example, to obtain the reaction - rates for U-235, Pu-239, and all nuclides in a material, this element should - be: - - .. code-block:: xml - - U-235 Pu-239 total - - *Default*: total - - :estimator: - The estimator element is used to force the use of either ``analog``, - ``collision``, or ``tracklength`` tally estimation. ``analog`` is generally - the least efficient though it can be used with every score type. - ``tracklength`` is generally the most efficient, but neither ``tracklength`` - nor ``collision`` can be used to score a tally that requires post-collision - information. For example, a scattering tally with outgoing energy filters - cannot be used with ``tracklength`` or ``collision`` because the code will - not know the outgoing energy distribution. - - *Default*: ``tracklength`` but will revert to ``analog`` if necessary. - - :scores: - A space-separated list of the desired responses to be accumulated. A full - list of valid scores can be found in the :ref:`user's guide - `. - - :trigger: - Precision trigger applied to all filter bins and nuclides for this tally. - It must specify the trigger's type, threshold and scores to which it will - be applied. It has the following attributes/sub-elements: - - :type: - The type of the trigger. Accepted options are "variance", "std_dev", - and "rel_err". - - :variance: - Variance of the batch mean :math:`\sigma^2` - - :std_dev: - Standard deviation of the batch mean :math:`\sigma` - - :rel_err: - Relative error of the batch mean :math:`\frac{\sigma}{\mu}` - - *Default*: None - - :threshold: - The precision trigger's convergence criterion for tallied values. - - *Default*: None - - :scores: - The score(s) in this tally to which the trigger should be applied. - - .. note:: The ``scores`` in ``trigger`` must have been defined in - ``scores`` in ``tally``. An optional "all" may be used to - select all scores in this tally. - - *Default*: "all" - - :derivative: - The id of a ``derivative`` element. This derivative will be applied to all - scores in the tally. Differential tallies are currently only implemented - for collision and analog estimators. - - *Default*: None - - --------------------- -```` Element --------------------- - -Filters can be used to modify tally behavior. Most tallies (e.g. ``cell``, -``energy``, and ``material``) restrict the tally so that only particles -within certain regions of phase space contribute to the tally. Others -(e.g. ``delayedgroup`` and ``energyfunction``) can apply some other function -to the scored values. The ``filter`` element has the following -attributes/sub-elements: - - :type: - The type of the filter. Accepted options are "cell", "cellfrom", - "cellborn", "surface", "material", "universe", "energy", "energyout", "mu", - "polar", "azimuthal", "mesh", "distribcell", "delayedgroup", - "energyfunction", and "particle". - - :bins: - A description of the bins for each type of filter can be found in - :ref:`filter_types`. - - :energy: - ``energyfunction`` filters multiply tally scores by an arbitrary - function. The function is described by a piecewise linear-linear set of - (energy, y) values. This entry specifies the energy values. The function - will be evaluated as zero outside of the bounds of this energy grid. - (Only used for ``energyfunction`` filters) - - :y: - ``energyfunction`` filters multiply tally scores by an arbitrary - function. The function is described by a piecewise linear-linear set of - (energy, y) values. This entry specifies the y values. (Only used - for ``energyfunction`` filters) - -.. _filter_types: - -Filter Types -++++++++++++ - -For each filter type, the following table describes what the ``bins`` attribute -should be set to: - -:cell: - A list of unique IDs for cells in which the tally should be - accumulated. - -:surface: - This filter allows the tally to be scored when crossing a surface. A list of - surface IDs should be given. By default, net currents are tallied, and to - tally a partial current from one cell to another, this should be used in - combination with a cell or cell_from filter that defines the other cell. - This filter should not be used in combination with a meshfilter. - -:cellfrom: - This filter allows the tally to be scored when crossing a surface and the - particle came from a specified cell. A list of cell IDs should be - given. - To tally a partial current from a cell to another, this filter should be - used in combination with a cell filter, to define the other cell. - This filter should not be used in combination with a meshfilter. - -:cellborn: - This filter allows the tally to be scored to only when particles were - originally born in a specified cell. A list of cell IDs should be - given. - -:material: - A list of unique IDs for materials in which the tally should be accumulated. - -:universe: - A list of unique IDs for universes in which the tally should be accumulated. - -:energy: - In continuous-energy mode, this filter should be provided as a - monotonically increasing list of bounding **pre-collision** energies - for a number of groups. For example, if this filter is specified as - - .. code-block:: xml - - - - then two energy bins will be created, one with energies between 0 and - 1 MeV and the other with energies between 1 and 20 MeV. - - In multi-group mode the bins provided must match group edges - defined in the multi-group library. - -:energyout: - In continuous-energy mode, this filter should be provided as a - monotonically increasing list of bounding **post-collision** energies - for a number of groups. For example, if this filter is specified as - - .. code-block:: xml - - - - then two post-collision energy bins will be created, one with - energies between 0 and 1 MeV and the other with energies between - 1 and 20 MeV. - - In multi-group mode the bins provided must match group edges - defined in the multi-group library. - -:mu: - A monotonically increasing list of bounding **post-collision** cosines - of the change in a particle's angle (i.e., :math:`\mu = \hat{\Omega} - \cdot \hat{\Omega}'`), which represents a portion of the possible - values of :math:`[-1,1]`. For example, spanning all of :math:`[-1,1]` - with five equi-width bins can be specified as: - - .. code-block:: xml - - - - Alternatively, if only one value is provided as a bin, OpenMC will - interpret this to mean the complete range of :math:`[-1,1]` should - be automatically subdivided in to the provided value for the bin. - That is, the above example of five equi-width bins spanning - :math:`[-1,1]` can be instead written as: - - .. code-block:: xml - - - -:polar: - A monotonically increasing list of bounding particle polar angles - which represents a portion of the possible values of :math:`[0,\pi]`. - For example, spanning all of :math:`[0,\pi]` with five equi-width - bins can be specified as: - - .. code-block:: xml - - - - Alternatively, if only one value is provided as a bin, OpenMC will - interpret this to mean the complete range of :math:`[0,\pi]` should - be automatically subdivided in to the provided value for the bin. - That is, the above example of five equi-width bins spanning - :math:`[0,\pi]` can be instead written as: - - .. code-block:: xml - - - -:azimuthal: - A monotonically increasing list of bounding particle azimuthal angles - which represents a portion of the possible values of :math:`[-\pi,\pi)`. - For example, spanning all of :math:`[-\pi,\pi)` with two equi-width - bins can be specified as: - - .. code-block:: xml - - - - Alternatively, if only one value is provided as a bin, OpenMC will - interpret this to mean the complete range of :math:`[-\pi,\pi)` should - be automatically subdivided in to the provided value for the bin. - That is, the above example of five equi-width bins spanning - :math:`[-\pi,\pi)` can be instead written as: - - .. code-block:: xml - - - -:mesh: - The unique ID of a structured mesh to be tallied over. - -:distribcell: - The single cell which should be tallied uniquely for all instances. - - .. note:: The distribcell filter will take a single cell ID and will tally - each unique occurrence of that cell separately. This filter will not - accept more than one cell ID. It is not recommended to combine this - filter with a cell or mesh filter. - -:delayedgroup: - A list of delayed neutron precursor groups for which the tally should - be accumulated. For instance, to tally to all 6 delayed groups in the - ENDF/B-VII.1 library the filter is specified as: - - .. code-block:: xml - - - -:energyfunction: - ``energyfunction`` filters do not use the ``bins`` entry. Instead - they use ``energy`` and ``y``. - -:particle: - A list of integers indicating the type of particles to tally ('neutron' = 1, - 'photon' = 2, 'electron' = 3, 'positron' = 4). - ------------------- -```` Element ------------------- - -If a structured mesh is desired as a filter for a tally, it must be specified in -a separate element with the tag name ````. This element has the following -attributes/sub-elements: - - :type: - The type of structured mesh. This can be either "regular" or "rectilinear". - - :dimension: - The number of mesh cells in each direction. (For regular mesh only.) - - :lower_left: - The lower-left corner of the structured mesh. If only two coordinates are - given, it is assumed that the mesh is an x-y mesh. (For regular mesh only.) - - :upper_right: - The upper-right corner of the structured mesh. If only two coordinates are - given, it is assumed that the mesh is an x-y mesh. (For regular mesh only.) - - :width: - The width of mesh cells in each direction. (For regular mesh only.) - - :x_grid: - The mesh divisions along the x-axis. (For rectilinear mesh only.) - - :y_grid: - The mesh divisions along the y-axis. (For rectilinear mesh only.) - - :z_grid: - The mesh divisions along the z-axis. (For rectilinear mesh only.) - - .. note:: - One of ```` or ```` must be specified, but not both - (even if they are consistent with one another). - ------------------------- -```` Element ------------------------- - -OpenMC can take the first-order derivative of many tallies with respect to -material perturbations. It works by propagating a derivative through the -transport equation. Essentially, OpenMC keeps track of how each particle's -weight would change as materials are perturbed, and then accounts for that -weight change in the tallies. Note that this assumes material perturbations are -small enough not to change the distribution of fission sites. This element has -the following attributes/sub-elements: - - :id: - A unique integer that can be used to identify the derivative. - - :variable: - The independent variable of the derivative. Accepted options are "density", - "nuclide_density", and "temperature". A "density" derivative will give the - derivative with respect to the density of the material in [g / cm^3]. A - "nuclide_density" derivative will give the derivative with respect to the - density of a particular nuclide in units of [atom / b / cm]. A - "temperature" derivative is with respect to a material temperature in units - of [K]. The temperature derivative requires windowed multipole to be - turned on. Note also that the temperature derivative only accounts for - resolved resonance Doppler broadening. It does not account for thermal - expansion, S(a, b) scattering, resonance scattering, or unresolved Doppler - broadening. - - :material: - The perturbed material. (Necessary for all derivative types) - - :nuclide: - The perturbed nuclide. (Necessary only for "nuclide_density") - ------------------------------ -```` Element ------------------------------ - -In cases where the user needs to specify many different tallies each of which -are spatially separate, this tag can be used to cut down on some of the tally -overhead. The effect of assuming all tallies are spatially separate is that once -one tally is scored to, the same event is assumed not to score to any other -tallies. This element should be followed by "true" or "false". - - .. warning:: If used incorrectly, the assumption that all tallies are - spatially separate can lead to incorrect results. - - *Default*: false diff --git a/docs/source/io_formats/track.rst b/docs/source/io_formats/track.rst deleted file mode 100644 index c617cd73e..000000000 --- a/docs/source/io_formats/track.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _io_track: - -================= -Track File Format -================= - -The current revision of the particle track file format is 2.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the track - file format. - - **n_particles** (*int*) -- Number of particles for which tracks - are recorded. - - **n_coords** (*int[]*) -- Number of coordinates for each - particle. - -:Datasets: - - **coordinates_** (*double[][3]*) -- (x,y,z) coordinates for the - *i*-th particle. diff --git a/docs/source/io_formats/volume.rst b/docs/source/io_formats/volume.rst deleted file mode 100644 index 456a06eef..000000000 --- a/docs/source/io_formats/volume.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _io_volume: - -================== -Volume File Format -================== - -The current version of the volume file format is 1.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the summary - file format. - - **openmc_version** (*int[3]*) -- Major, minor, and release - version number for OpenMC. - - **git_sha1** (*char[40]*) -- Git commit SHA-1 hash. - - **date_and_time** (*char[]*) -- Date and time the summary was - written. - - **domain_type** (*char[]*) -- The type of domain for which - volumes are calculated, either 'cell', 'material', or 'universe'. - - **samples** (*int*) -- Number of samples - - **lower_left** (*double[3]*) -- Lower-left coordinates of - bounding box - - **upper_right** (*double[3]*) -- Upper-right coordinates of - bounding box - -**/domain_/** - -:Datasets: - **volume** (*double[2]*) -- Calculated volume and its uncertainty - in cubic centimeters - - **nuclides** (*char[][]*) -- Names of nuclides identified in the - domain - - **atoms** (*double[][2]*) -- Total number of atoms of each nuclide - and its uncertainty diff --git a/docs/source/io_formats/voxel.rst b/docs/source/io_formats/voxel.rst deleted file mode 100644 index 52ae78aaa..000000000 --- a/docs/source/io_formats/voxel.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. _io_voxel: - -====================== -Voxel Plot File Format -====================== - -The current version of the voxel file format is 1.0. - -**/** - -:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. - - **version** (*int[2]*) -- Major and minor version of the voxel - file format. - - **openmc_version** (*int[3]*) -- Major, minor, and release - version number for OpenMC. - - **git_sha1** (*char[40]*) -- Git commit SHA-1 hash. - - **date_and_time** (*char[]*) -- Date and time the summary was - written. - - **num_voxels** (*int[3]*) -- Number of voxels in the x-, y-, and - z- directions. - - **voxel_width** (*double[3]*) -- Width of a voxel in centimeters. - - **lower_left** (*double[3]*) -- Cartesian coordinates of the - lower-left corner of the plot. - -:Datasets: - - **data** (*int[][][]*) -- Data for each voxel that represents a - material or cell ID. diff --git a/docs/source/license.rst b/docs/source/license.rst deleted file mode 100644 index 98f6655bc..000000000 --- a/docs/source/license.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. _license: - -================= -License Agreement -================= - -Copyright © 2011-2019 Massachusetts Institute of Technology and OpenMC contributors - -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 -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/docs/source/methods/cmfd.rst b/docs/source/methods/cmfd.rst deleted file mode 100644 index 344a4cc1a..000000000 --- a/docs/source/methods/cmfd.rst +++ /dev/null @@ -1,569 +0,0 @@ -.. _methods_cmfd: - -================================================================ -Nonlinear Diffusion Acceleration - Coarse Mesh Finite Difference -================================================================ - -This page section discusses how nonlinear diffusion acceleration (NDA) using -coarse mesh finite difference (CMFD) is implemented into OpenMC. Before we get -into the theory, general notation for this section is discussed. - -Note that the methods discussed in this section are written specifically for -continuous-energy mode but equivalent apply to the multi-group mode if the -particle's energy is replaced with the particle's group - --------- -Notation --------- - -Before deriving NDA relationships, notation is explained. If a parameter has a -:math:`\overline{\cdot}`, it is surface area-averaged and if it has a -:math:`\overline{\overline\cdot}`, it is volume-averaged. When describing a -specific cell in the geometry, indices :math:`(i,j,k)` are used which correspond -to directions :math:`(x,y,z)`. In most cases, the same operation is performed in -all three directions. To compactly write this, an arbitrary direction set -:math:`(u,v,w)` that corresponds to cell indices :math:`(l,m,n)` is used. Note -that :math:`u` and :math:`l` do not have to correspond to :math:`x` and -:math:`i`. However, if :math:`u` and :math:`l` correspond to :math:`y` and -:math:`j`, :math:`v` and :math:`w` correspond to :math:`x` and :math:`z` -directions. An example of this is shown in the following expression: - -.. math:: - :label: not1 - - \sum\limits_{u\in(x,y,z)}\left\langle\overline{J}^{u,g}_{l+1/2,m,n} - \Delta_m^v\Delta_n^w\right\rangle - -Here, :math:`u` takes on each direction one at a time. The parameter :math:`J` -is surface area-averaged over the transverse indices :math:`m` and :math:`n` -located at :math:`l+1/2`. Usually, spatial indices are listed as subscripts and -the direction as a superscript. Energy group indices represented by :math:`g` -and :math:`h` are also listed as superscripts here. The group :math:`g` is the -group of interest and, if present, :math:`h` is all groups. Finally, any -parameter surrounded by :math:`\left\langle\cdot\right\rangle` represents a -tally quantity that can be edited from a Monte Carlo (MC) solution. - ------- -Theory ------- - -NDA is a diffusion model that has equivalent physics to a transport model. There -are many different methods that can be classified as NDA. The CMFD method is a -type of NDA that represents second order multigroup diffusion equations on a -coarse spatial mesh. Whether a transport model or diffusion model is used to -represent the distribution of neutrons, these models must satisfy the *neutron -balance equation*. This balance is represented by the following formula for a -specific energy group :math:`g` in cell :math:`(l,m,n)`: - -.. math:: - :label: eq_neut_bal - - \sum\limits_{u\in(x,y,z)}\left(\left\langle\overline{J}^{u,g}_{l+1/2,m,n} - \Delta_m^v\Delta_n^w\right\rangle - - \left\langle\overline{J}^{u,g}_{l-1/2,m,n} - \Delta_m^v\Delta_n^w\right\rangle\right) - + - \left\langle\overline{\overline\Sigma}_{t_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle - = \\ - \sum\limits_{h=1}^G\left\langle - \overline{\overline{\nu_s\Sigma}}_{s_{l,m,n}}^{h\rightarrow - g}\overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w - \right\rangle - + - \frac{1}{k_{eff}}\sum\limits_{h=1}^G - \left\langle\overline{\overline{\nu_f\Sigma}}_{f_{l,m,n}}^{h\rightarrow - g}\overline{\overline\phi}_{l,m,n}^h - \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle. - -In eq. :eq:`eq_neut_bal` the parameters are defined as: - -* :math:`\left\langle\overline{J}^{u,g}_{l\pm - 1/2,m,n}\Delta_m^v\Delta_n^w\right\rangle` --- surface area-integrated net - current over surface :math:`(l\pm 1/2,m,n)` with surface normal in direction - :math:`u` in energy group :math:`g`. By dividing this quantity by the transverse - area, :math:`\Delta_m^v\Delta_n^w`, the surface area-averaged net current can - be computed. -* :math:`\left\langle\overline{\overline\Sigma}_{t_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` - --- volume-integrated total reaction rate over energy group :math:`g`. -* :math:`\left\langle\overline{\overline{\nu_s\Sigma}}_{s_{l,m,n}}^{h\rightarrow - g} - \overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` - --- volume-integrated scattering production rate of neutrons that begin with - energy in group :math:`h` and exit reaction in group :math:`g`. This reaction - rate also includes the energy transfer of reactions (except fission) that - produce multiple neutrons such as (n, 2n); hence, the need for :math:`\nu_s` - to represent neutron multiplicity. -* :math:`k_{eff}` --- core multiplication factor. -* :math:`\left\langle\overline{\overline{\nu_f\Sigma}}_{f_{l,m,n}}^{h\rightarrow - g}\overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` - --- volume-integrated fission production rate of neutrons from fissions in - group :math:`h` that exit in group :math:`g`. - -Each quantity in :math:`\left\langle\cdot\right\rangle` represents a scalar value that -is obtained from an MC tally. A good verification step when using an MC code is -to make sure that tallies satisfy this balance equation within statistics. No -NDA acceleration can be performed if the balance equation is not satisfied. - -There are three major steps to consider when performing NDA: (1) calculation of -macroscopic cross sections and nonlinear parameters, (2) solving an eigenvalue -problem with a system of linear equations, and (3) modifying MC source -distribution to align with the NDA solution on a chosen mesh. This process is -illustrated as a flow chart below. After a batch of neutrons -is simulated, NDA can take place. Each of the steps described above is described -in detail in the following sections. - -.. figure:: ../_images/cmfd_flow.png - :align: center - :figclass: align-center - - Flow chart of NDA process. Note "XS" is used for cross section and "DC" is - used for diffusion coefficient. - -Calculation of Macroscopic Cross Sections ------------------------------------------ - -A diffusion model needs macroscopic cross sections and diffusion coefficients to -solve for multigroup fluxes. Cross sections are derived by conserving reaction -rates predicted by MC tallies. From Eq. :eq:`eq_neut_bal`, total, scattering -production and fission production macroscopic cross sections are needed. They are -defined from MC tallies as follows: - -.. math:: - :label: xs1 - - \overline{\overline\Sigma}_{t_{l,m,n}}^g \equiv - \frac{\left\langle\overline{\overline\Sigma}_{t_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle} - {\left\langle\overline{\overline\phi}_{l,m,n}^g - \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle}, - -.. math:: - :label: xs2 - - \overline{\overline{\nu_s\Sigma}}_{s_{l,m,n}}^{h\rightarrow g} \equiv - \frac{\left\langle\overline{\overline{\nu_s\Sigma}}_{s_{l,m,n}}^{h\rightarrow - g}\overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle} - {\left\langle\overline{\overline\phi}_{l,m,n}^h - \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle} - -and - -.. math:: - :label: xs3 - - \overline{\overline{\nu_f\Sigma}}_{f_{l,m,n}}^{h\rightarrow g} \equiv - \frac{\left\langle\overline{\overline{\nu_f\Sigma}}_{f_{l,m,n}}^{h\rightarrow - g}\overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle} - {\left\langle\overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle}. - -In order to fully conserve neutron balance, leakage rates also need to be -preserved. In standard diffusion theory, leakage rates are represented by -diffusion coefficients. Unfortunately, it is not easy in MC to calculate a -single diffusion coefficient for a cell that describes leakage out of each -surface. Luckily, it does not matter what definition of diffusion coefficient is -used because nonlinear equivalence parameters will correct for this -inconsistency. However, depending on the diffusion coefficient definition -chosen, different convergence properties of NDA equations are observed. -Here, we introduce a diffusion coefficient that is derived for a coarse energy -transport reaction rate. This definition can easily be constructed from -MC tallies provided that angular moments of scattering reaction rates can -be obtained. The diffusion coefficient is defined as follows: - -.. math:: - :label: eq_transD - - \overline{\overline D}_{l,m,n}^g = - \frac{\left\langle\overline{\overline\phi}_{l,m,n}^g - \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle}{3 - \left\langle\overline{\overline\Sigma}_{tr_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g - \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle}, - -where - -.. math:: - :label: xs4 - - \left\langle\overline{\overline\Sigma}_{tr_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle - = - \left\langle\overline{\overline\Sigma}_{t_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle - \\ - - \left\langle\overline{\overline{\nu_s\Sigma}}_{s1_{l,m,n}}^g - \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle. - -Note that the transport reaction rate is calculated from the total reaction rate -reduced by the :math:`P_1` scattering production reaction rate. Equation :eq:`eq_transD` -does not represent the best definition of diffusion coefficients from MC; -however, it is very simple and usually fits into MC tally frameworks -easily. Different methods to calculate more accurate diffusion coefficients can -found in [Herman]_. - -CMFD Equations --------------- - -The first part of this section is devoted to discussing second-order finite -volume discretization of multigroup diffusion equations. This will be followed -up by the formulation of CMFD equations that are used in this NDA -scheme. When performing second-order finite volume discretization of the -diffusion equation, we need information that relates current to flux. In this -numerical scheme, each cell is coupled only to its direct neighbors. Therefore, -only two types of coupling exist: (1) cell-to-cell coupling and (2) -cell-to-boundary coupling. The derivation of this procedure is referred to as -finite difference diffusion equations and can be found in literature such -as [Hebert]_. These current/flux relationships are as follows: - -* cell-to-cell coupling - -.. math:: - :label: eq_cell_cell - - \overline{J}^{u,g}_{l\pm1/2,m,n} = -\frac{2\overline{\overline - D}_{l\pm1,m,n}^g\overline{\overline - D}_{l,m,n}^g}{\overline{\overline D}_{l\pm1,m,n}^g\Delta_l^u + - \overline{\overline - D}_{l,m,n}^g\Delta_{l\pm1}^u} - \left(\pm\overline{\overline{\phi}}_{l\pm1,m,n}^g\mp - \overline{\overline{\phi}}_{l,m,n}^g\right), - -* cell-to-boundary coupling - -.. math:: - :label: eq_cell_bound - - \overline{J}^{u,g}_{l\pm1/2,m,n} = \pm\frac{2\overline{\overline - D}_{l,m,n}^g\left(1 - - \beta_{l\pm1/2,m,n}^{u,g}\right)}{4\overline{\overline - D}_{l,m,n}^g\left(1 + \beta_{l\pm1/2,m,n}^{u,g}\right) + \left(1 - - \beta_{l\pm1/2,m,n}^{u,g}\right)\Delta_l^u}\overline{\overline{\phi}}_{l,m,n}^{g}. - -In Eqs. :eq:`eq_cell_cell` and :eq:`eq_cell_bound`, the :math:`\pm` refers to -left (:math:`-x`) or right (:math:`+x`) surface in the :math:`x` direction, -back (:math:`-y`) or front (:math:`+y`) surface in the :math:`y` direction and -bottom (:math:`-z`) or top (:math:`+z`) surface in the :math:`z` direction. For -cell-to-boundary coupling, a general albedo, :math:`\beta_{l\pm1/2,m,n}^{u,g}`, -is used. The albedo is defined as the ratio of incoming (:math:`-` superscript) -to outgoing (:math:`+` superscript) partial current on any surface represented -as - -.. math:: - :label: eq_albedo - - \beta_{l\pm1/2,m,n}^{u,g} = - \frac{\overline{J}^{u,g-}_{l\pm1/2,m,n}}{\overline{J}^{u,g+}_{l\pm1/2,m,n}}. - -Common boundary conditions are: vacuum (:math:`\beta=0`), reflective -(:math:`\beta=1`) and zero flux (:math:`\beta=-1`). Both eq. :eq:`eq_cell_cell` -and eq. :eq:`eq_cell_bound` can be written in this generic form, - -.. math:: - :label: eq_dtilde - - \overline{J}^{u,g}_{l\pm1/2,m,n} = \widetilde{D}_{l,m,n}^{u,g} \left(\dots\right). - -The parameter :math:`\widetilde{D}_{l,m,n}^{u,g}` represents the linear -coupling term between current and flux. These current relationships can be -sustituted into eq. :eq:`eq_neut_bal` to produce a linear system of multigroup -diffusion equations for each spatial cell and energy group. However, a solution -to these equations is not consistent with a higher order transport solution -unless equivalence factors are present. This is because both the diffusion -approximation, governed by Fick's Law, and spatial trunction error will produce -differences. Therefore, a nonlinear parameter, -:math:`\widehat{D}_{l,m,n}^{u,g}`, is added to eqs. :eq:`eq_cell_cell` and -:eq:`eq_cell_bound`. These equations are, respectively, - -.. math:: - :label: eq_dhat_cell - - \overline{J}^{u,g}_{l\pm1/2,m,n} = -\widetilde{D}_{l,m,n}^{u,g} - \left(\pm\overline{\overline{\phi}}_{l\pm1,m,n}^g\mp - \overline{\overline{\phi}}_{l,m,n}^g\right) + \widehat{D}_{l,m,n}^{u,g} - \left(\overline{\overline{\phi}}_{l\pm1,m,n}^g + - \overline{\overline{\phi}}_{l,m,n}^g\right) - -and - -.. math:: - :label: eq_dhat_bound - - \overline{J}^{u,g}_{l\pm1/2,m,n} = \pm\widetilde{D}_{l,m,n}^{u,g} - \overline{\overline{\phi}}_{l,m,n}^{g} + \widehat{D}_{l,m,n}^{u,g} - \overline{\overline{\phi}}_{l,m,n}^{g}. - -The only unknown in each of these equations is the equivalence parameter. The -current, linear coupling term and flux can either be obtained or derived from -MC tallies. Thus, it is called nonlinear because it is dependent on the flux -which is updated on the next iteration. - -Equations :eq:`eq_dhat_cell` and :eq:`eq_dhat_bound` can be substituted into -eq. :eq:`eq_neut_bal` to create a linear system of equations that is consistent -with transport physics. One example of this equation is written for an -interior cell, - -.. math:: - :label: eq_cmfd_sys - - \sum_{u\in - x,y,x}\frac{1}{\Delta_l^u}\left[\left(-\tilde{D}_{l-1/2,m,n}^{u,g} - - \hat{D}_{l-1/2,m,n}^{u,g}\right)\overline{\overline{\phi}}_{l-1,m,n}^g\right. - \\ + \left(\tilde{D}_{l-1/2,m,n}^{u,g} + - \tilde{D}_{l+1/2,m,n}^{u,g} - \hat{D}_{l-1/2,m,n}^{u,g} + - \hat{D}_{l+1/2,m,n}^{u,g}\right)\overline{\overline{\phi}}_{l,m,n}^g - \\ + - \left. \left(-\tilde{D}_{l+1/2,m,n}^{u,g} + - \hat{D}_{l+1/2,m,n}^{u,g}\right)\overline{\overline{\phi}}_{l+1,m,n}^g - \right] \\ + - \overline{\overline\Sigma}_{t_{l,m,n}}^g\overline{\overline{\phi}}_{l,m,n}^g - - \sum\limits_{h=1}^G\overline{\overline{\nu_s\Sigma}}^{h\rightarrow - g}_{s_{l,m,n}}\overline{\overline{\phi}}_{l,m,n}^h = - \frac{1}{k}\sum\limits_{h=1}^G\overline{\overline{\nu_f\Sigma}}^{h\rightarrow - g}_{f_{l,m,n}}\overline{\overline{\phi}}_{l,m,n}^h. - -It should be noted that before substitution, eq. :eq:`eq_neut_bal` was divided -by the volume of the cell, :math:`\Delta_l^u\Delta_m^v\Delta_n^w`. Equation -:eq:`eq_cmfd_sys` can be represented in operator form as - -.. math:: - :label: eq_CMFDopers - - \mathbb{M}\mathbf{\Phi} = \frac{1}{k}\mathbb{F}\mathbf{\Phi}, - -where :math:`\mathbb{M}` is the neutron loss matrix operator, -:math:`\mathbb{F}` is the neutron production matrix operator, -:math:`\mathbf{\Phi}` is the multigroup flux vector and :math:`k` is the -eigenvalue. This generalized eigenvalue problem is solved to obtain fundamental -mode multigroup fluxes and eigenvalue. In order to produce consistent results -with transport theory from these equations, the neutron balance equation must -have been satisfied by MC tallies. The desire is that CMFD equations will -produce a more accurate source than MC after each fission source generation. - -CMFD Feedback -------------- - -Now that a more accurate representation of the expected source distribution is -estimated from CMFD, it needs to be communicated back to MC. The first step -in this process is to generate a probability mass function that provides -information about how probable it is for a neutron to be born in a given cell -and energy group. This is represented as - -.. math:: - :label: eq_cmfd_psrc - - p_{l,m,n}^g = - \frac{\sum_{h=1}^{G}\overline{\overline{\nu_f\Sigma}}^{h\rightarrow - g}_{f_{l,m,n}}\overline{\overline{\phi}}_{l,m,n}^h\Delta_l^u\Delta_m^v - \Delta_n^w}{\sum_n\sum_m\sum_l\sum_{h=1}^{G}\overline{ - \overline{\nu_f\Sigma}}^{h\rightarrow - g}_{f_{l,m,n}}\overline{\overline{\phi}}_{l,m,n}^h\Delta_l^u\Delta_m^v - \Delta_n^w}. - -This equation can be multiplied by the number of source neutrons to obtain an -estimate of the expected number of neutrons to be born in a given cell and -energy group. This distribution can be compared to the MC source distribution -to generate weight adjusted factors defined as - -.. math:: - :label: eq_waf - - f_{l,m,n}^g = \frac{Np_{l,m,n}^g}{\sum\limits_s w_s};\quad s\in - \left(g,l,m,n\right). - -The MC source distribution is represented on the same coarse mesh as -CMFD by summing all neutrons' weights, :math:`w_s`, in a given cell and -energy group. MC source weights can then be modified by this weight -adjustment factor so that it matches the CMFD solution on the coarse -mesh, - -.. math:: - :label: src_mod - - w^\prime_s = w_s\times f_{l,m,n}^g;\quad s\in \left(g,l,m,n\right). - -It should be noted that heterogeneous information about local coordinates and -energy remain constant throughout this modification process. - ------------------------- -Implementation in OpenMC ------------------------- - -The section describes how CMFD was implemented in OpenMC. Before the simulation -begins, a user sets up a CMFD input file that contains the following basic -information: - -* CMFD mesh (space and energy), -* boundary conditions at edge of mesh (albedos), -* acceleration region (subset of mesh, optional), -* fission source generation (FSG)/batch that CMFD should begin, and -* whether CMFD feedback should be applied. - -It should be noted that for more difficult simulations (e.g., light water -reactors), there are other options available to users such as tally resetting -parameters, effective down-scatter usage, tally estimator, etc. For more -information please see the :class:`openmc.cmfd.CMFDRun` class. - -Of the options described above, the optional acceleration subset region is an -uncommon feature. Because OpenMC only has a structured Cartesian mesh, mesh -cells may overlay regions that don't contain fissionable material and may be so -far from the core that the neutron flux is very low. If these regions were -included in the CMFD solution, bad estimates of diffusion parameters may result -and affect CMFD feedback. To deal with this, a user can carve out an active -acceleration region from their structured Cartesian mesh. This is illustrated -in diagram below. When placing a CMFD mesh over a geometry, the boundary -conditions must be known at the global edges of the mesh. If the geometry is -complex like the one below, one may have to cover the whole geometry including -the reactor pressure vessel because we know that there is a zero incoming -current boundary condition at the outer edge of the pressure vessel. This is -not viable in practice because neutrons in simulations may not reach mesh cells -that are near the pressure vessel. To circumvent this, one can shrink the mesh -to cover just the core region as shown in the diagram. However, one must still -estimate the boundary conditions at the global boundaries, but at these -locations, they are not readily known. In OpenMC, one can carve out the active -core region from the entire structured Cartesian mesh. This is shown in the -diagram below by the darkened region over the core. The albedo boundary -conditions at the active core/reflector boundary can be tallied indirectly -during the MC simulation with incoming and outgoing partial currents. This -allows the user to not have to worry about neutrons producing adequate tallies -in mesh cells far away from the core. - -.. figure:: ../_images/meshfig.png - :align: center - :figclass: align-center - - Diagram of CMFD acceleration mesh - -During an MC simulation, CMFD tallies are accumulated. The basic tallies needed -are listed in Table :ref:`tab_tally`. Each tally is performed on a spatial and -energy mesh basis. The surface area-integrated net current is tallied on every -surface of the mesh. OpenMC tally objects are created by the CMFD code -internally, and cross sections are calculated at each CMFD feedback iteration. -The first CMFD iteration, controlled by the user, occurs just after tallies are -communicated to the master processor. Once tallies are collapsed, cross -sections, diffusion coefficients and equivalence parameters are calculated. This -is performed only on the acceleration region if that option has been activated -by the user. Once all diffusion parameters are calculated, CMFD matrices are -formed where energy groups are the inner most iteration index. In OpenMC, -compressed row storage sparse matrices are used due to the sparsity of CMFD -operators. An example of this sparsity is shown for the 3-D BEAVRS model in -figures :num:`fig-loss` and :num:`fig-prod` [BEAVRS]_. These matrices represent -an assembly radial mesh, 24 cell mesh in the axial direction and two energy -groups. The loss matrix is 99.92% sparse and the production matrix is 99.99% -sparse. Although the loss matrix looks like it is tridiagonal, it is really a -seven banded matrix with a block diagonal matrix for scattering. The production -matrix is a :math:`2\times 2` block diagonal; however, zeros are present because -no fission neutrons appear with energies in the thermal group. - -.. _tab_tally: - -.. table:: OpenMC CMFD tally list - - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | tally | score | filter | - +============================================================================================+================+===========================+ - | \ :math:`\left\langle\overline{\overline\phi}_{l,m,n}^g | flux | mesh, energy | - | \Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` | | | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | \ :math:`\left\langle\overline{\overline\Sigma}_{t_{l,m,n}}^g | total | mesh, energy | - | \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` | | | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | \ :math:`\left\langle\overline{\overline{\nu_s\Sigma}}_{s1_{l,m,n}}^g | nu-scatter-1 | mesh, energy | - | \overline{\overline\phi}_{l,m,n}^g\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` | | | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | \ :math:`\left\langle\overline{\overline{\nu_s\Sigma}}_{s_{l,m,n}}^{h\rightarrow g} | nu-scatter | mesh, energy, energyout | - | \overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` | | | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | \ :math:`\left\langle\overline{\overline{\nu_f\Sigma}}_{f_{l,m,n}}^{h\rightarrow g} | nu-fission | mesh, energy, energyout | - | \overline{\overline\phi}_{l,m,n}^h\Delta_l^u\Delta_m^v\Delta_n^w\right\rangle` | | | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - | \ :math:`\left\langle\overline{J}^{u,g}_{l\pm 1/2,m,n}\Delta_m^v\Delta_n^w\right\rangle` | current | mesh, energy | - +--------------------------------------------------------------------------------------------+----------------+---------------------------+ - -.. _fig-loss: - -.. figure:: ../_images/loss.png - :scale: 50 - - Sparsity of Neutron Loss Operator - -.. _fig-prod: - -.. figure:: ../_images/prod.png - :scale: 50 - - Sparsity of Neutron Production Operator - -To solve the eigenvalue problem with these matrices, different source iteration -and linear solvers can be used. The most common source iteration solver used is -standard power iteration as described in [Gill]_. To accelerate these source -iterations, a Wielandt shift scheme can be used as discussed in [Park]_. PETSc -solvers were first implemented to perform the linear solution in parallel that -occurs once per source iteration. When using PETSc, different types of parallel -linear solvers and preconditioners can be used. By default, OpenMC uses an -incomplete LU preconditioner and a GMRES Krylov solver. After some initial -studies of parallelization with PETSc, it was observed that because CMFD -matrices are very sparse, solution times do not scale well. An additional -Gauss-Seidel linear solver with Chebyshev acceleration was added that is -similar to the one used for CMFD in CASMO [Rhodes]_ and [Smith]_. This solver -was implemented with a custom section for two energy groups. Because energy -group is the inner most index, a block diagonal is formed when using more than -one group. For two groups, it is easy to invert this diagonal analytically -inside the Gauss-Seidel iterative solver. For more than two groups, this -analytic inversion can still be performed, but with more computational effort. -A standard Gauss-Seidel solver is used for more than two groups. - -Besides a power iteration, a Jacobian-free Newton-Krylov method was also -implemented to obtain eigenvalue and multigroup fluxes as described in [Gill]_ -and [Knoll]_. This method is not the primary one used, but has gotten recent -attention due to its coupling advantages to other physics such as thermal -hydraulics. Once multigroup fluxes are obtained, a normalized fission source is -calculated in the code using eq. :eq:`eq_cmfd_psrc` directly. - -The next step in the process is to compute weight adjustment factors. These are -calculated by taking the ratio of the expected number of neutrons from the CMFD -source distribution to the current number of neutrons in each mesh. It is -straightforward to compute the CMFD number of neutrons because it is the -product between the total starting initial weight of neutrons and the CMFD -normalized fission source distribution. To compute the number of neutrons from -the current MC source, OpenMC sums the statistical -weights of neutrons from the source bank on a given spatial and energy mesh. -Once weight adjustment factors were calculated, each neutron's statistical -weight in the source bank was modified according to its location and energy. -Examples of CMFD simulations using OpenMC can be found in [HermanThesis]_. - -.. only:: html - - .. rubric:: References - -.. [BEAVRS] Nick Horelik, Bryan Herman. *Benchmark for Evaluation And Verification of Reactor - Simulations*. Massachusetts Institute of Technology, https://crpg.mit.edu/research/beavrs - , 2013. - -.. [Gill] Daniel F. Gill. *Newton-Krylov methods for the solution of the k-eigenvalue problem in - multigroup neutronics calculations*. Ph.D. thesis, Pennsylvania State University, 2010. - -.. [Hebert] Alain Hebert. *Applied reactor physics*. Presses Internationales Polytechnique, - Montreal, 2009. - -.. [Herman] Bryan R. Herman, Benoit Forget, Kord Smith, and Brian N. Aviles. Improved - diffusion coefficients generated from Monte Carlo codes. In *Proceedings of M&C - 2013*, Sun Valley, ID, USA, May 5 - 9, 2013. - -.. [HermanThesis] Bryan R. Herman. *Monte Carlo and Thermal Hydraulic Coupling using - Low-Order Nonlinear Diffusion Acceleration*. Sc.D. thesis, - Massachusetts Institute of Technology, 2014. - -.. [Knoll] D.A. Knoll, H. Park, and C. Newman. *Acceleration of k-eigenvalue/criticality - calculations using the Jacobian-free Newton-Krylov method*. Nuclear Science and - Engineering, 167:133–140, 2011. - -.. [Park] H. Park, D.A. Knoll, and C.K. Newman. *Nonlinear acceleration of transport - criticality problems*. Nuclear Science and Engineering, 172:52–65, 2012. - -.. [Rhodes] Joel Rhodes and Malte Edenius. *CASMO-4 --- A Fuel Assembly Burnup Program. - User’s Manual*. Studsvik of America, ssp-09/443-u rev 0, proprietary edition, 2001. - -.. [Smith] Kord S Smith and Joel D Rhodes III. *Full-core, 2-D, LWR core calculations with - CASMO-4E*. In Proceedings of PHYSOR 2002, Seoul, Korea, October 7 - 10, 2002. diff --git a/docs/source/methods/cross_sections.rst b/docs/source/methods/cross_sections.rst deleted file mode 100644 index c360805be..000000000 --- a/docs/source/methods/cross_sections.rst +++ /dev/null @@ -1,280 +0,0 @@ -.. _methods_cross_sections: - -============================= -Cross Section Representations -============================= - ----------------------- -Continuous-Energy Data ----------------------- - -In OpenMC, the data governing the interaction of neutrons with various nuclei -for continous-energy problems are represented using an HDF5 format that can be -produced by converting files in the ACE format, which is used by MCNP_ and -Serpent_. ACE-format data can be generated with the NJOY_ nuclear data -processing system, which converts raw `ENDF/B data`_ into linearly-interpolable -data as required by most Monte Carlo codes. Since ACE-format data can be -converted into OpenMC's HDF5 format, it is possible to perform direct comparison -of OpenMC with other codes using the same underlying nuclear data library. - -The ACE format contains continuous-energy cross sections for the following types -of reactions: elastic scattering, fission (or first-chance fission, -second-chance fission, etc.), inelastic scattering, :math:`(n,xn)`, -:math:`(n,\gamma)`, and various other absorption reactions. For those reactions -with one or more neutrons in the exit channel, secondary angle and energy -distributions may be provided. In addition, fissionable nuclides have total, -prompt, and/or delayed :math:`\nu` as a function of energy and neutron precursor -distributions. Many nuclides also have probability tables to be used for -accurate treatment of self-shielding in the unresolved resonance range. For -bound scatterers, separate tables with :math:`S(\alpha,\beta,T)` scattering law -data can be used. - -Energy Grid Methods -------------------- - -The method by which continuous-energy cross sections for each nuclide in a -problem are stored as a function of energy can have a substantial effect on the -performance of a Monte Carlo simulation. Since the ACE format is based on -linearly-interpolable cross sections, each nuclide has cross sections tabulated -over a wide range of energies. Some nuclides may only have a few points -tabulated (e.g. H-1) whereas other nuclides may have hundreds or thousands of -points tabulated (e.g. U-238). - -At each collision, it is necessary to sample the probability of having a -particular type of interaction whether it be elastic scattering, :math:`(n,2n)`, -level inelastic scattering, etc. This requires looking up the microscopic cross -sections for these reactions for each nuclide within the target material. Since -each nuclide has a unique energy grid, it would be necessary to search for the -appropriate index for each nuclide at every collision. This can become a very -time-consuming process, especially if there are many nuclides in a problem as -there would be for burnup calculations. Thus, there is a strong motive to -implement a method of reducing the number of energy grid searches in order to -speed up the calculation. - -Logarithmic Mapping -+++++++++++++++++++ - -To speed up energy grid searches, OpenMC uses a `logarithmic mapping technique`_ -to limit the range of energies that must be searched for each nuclide. The -entire energy range is divided up into equal-lethargy segments, and the bounding -energies of each segment are mapped to bounding indices on each of the nuclide -energy grids. By default, OpenMC uses 8000 equal-lethargy segments as -recommended by Brown. - -Other Methods -+++++++++++++ - -A good survey of other energy grid techniques, including unionized energy grids, -can be found in a paper by Leppanen_. - -.. _windowed_multipole: - -Windowed Multipole Representation ---------------------------------- - -In addition to the usual pointwise representation of cross sections, OpenMC -offers support for a data format called windowed multipole (WMP). This data -format requires less memory than pointwise cross sections, and it allows -on-the-fly Doppler broadening to arbitrary temperature. - -The multipole method was introduced by Hwang_ and the faster windowed multipole -method by Josey_. In the multipole format, cross section resonances are -represented by poles, :math:`p_j`, and residues, :math:`r_j`, in the complex -plane. The 0K cross sections in the resolved resonance region can be computed -by summing up a contribution from each pole: - -.. math:: - \sigma(E, T=0\text{K}) = \frac{1}{E} \sum_j \text{Re} \left[ - \frac{i r_j}{\sqrt{E} - p_j} \right] - -Assuming free-gas thermal motion, cross sections in the multipole form can be -analytically Doppler broadened to give the form: - -.. math:: - \sigma(E, T) = \frac{1}{2 E \sqrt{\xi}} \sum_j \text{Re} \left[r_j - \sqrt{\pi} W_i(z) - \frac{r_j}{\sqrt{\pi}} C \left(\frac{p_j}{\sqrt{\xi}}, - \frac{u}{2 \sqrt{\xi}}\right)\right] -.. math:: - W_i(z) = \frac{i}{\pi} \int_{-\infty}^\infty dt \frac{e^{-t^2}}{z - t} -.. math:: - C \left(\frac{p_j}{\sqrt{\xi}},\frac{u}{2 \sqrt{\xi}}\right) = - 2p_j \int_0^\infty du' \frac{e^{-(u + u')^2/4\xi}}{p_j^2 - u'^2} -.. math:: - z = \frac{\sqrt{E} - p_j}{2 \sqrt{\xi}} -.. math:: - \xi = \frac{k_B T}{4 A} -.. math:: - u = \sqrt{E} - -where :math:`T` is the temperature of the resonant scatterer, :math:`k_B` is the -Boltzmann constant, :math:`A` is the mass of the target nucleus. For -:math:`E \gg k_b T/A`, the :math:`C` integral is approximately zero, simplifying -the cross section to: - -.. math:: - \sigma(E, T) = \frac{1}{2 E \sqrt{\xi}} \sum_j \text{Re} \left[i r_j - \sqrt{\pi} W_i(z)\right] - -The :math:`W_i` integral simplifies down to an analytic form. We define the -Faddeeva function, :math:`W` as: - -.. math:: - W(z) = e^{-z^2} \text{Erfc}(-iz) - -Through this, the integral transforms as follows: - -.. math:: - \text{Im} (z) > 0 : W_i(z) = W(z) -.. math:: - \text{Im} (z) < 0 : W_i(z) = -W(z^*)^* - -There are freely available algorithms_ to evaluate the Faddeeva function. For -many nuclides, the Faddeeva function needs to be evaluated thousands of times to -calculate a cross section. To mitigate that computational cost, the WMP method -only evaluates poles within a certain energy "window" around the incident -neutron energy and accounts for the effect of resonances outside that window -with a polynomial fit. This polynomial fit is then broadened exactly. This -exact broadening can make up for the removal of the :math:`C` integral, as -typically at low energies, only curve fits are used. - -Note that the implementation of WMP in OpenMC currently assumes that inelastic -scattering does not occur in the resolved resonance region. This is usually, -but not always the case. Future library versions may eliminate this issue. - -The data format used by OpenMC to represent windowed multipole data is specified -in :ref:`io_data_wmp` with a publicly available `WMP library`_. - -.. _temperature_treatment: - -Temperature Treatment ---------------------- - -At the beginning of a simulation, OpenMC collects a list of all temperatures -that are present in a model. It then uses this list to determine what cross -sections to load. The data that is loaded depends on what temperature method has -been selected. There are three methods available: - -:Nearest: Cross sections are loaded only if they are within a specified - tolerance of the actual temperatures in the model. - -:Interpolation: Cross sections are loaded at temperatures that bound the actual - temperatures in the model. During transport, cross sections for - each material are calculated using statistical linear-linear - interpolation between bounding temperature. Suppose cross - sections are available at temperatures :math:`T_1, T_2, ..., - T_n` and a material is assigned a temperature :math:`T` where - :math:`T_i < T < T_{i+1}`. Statistical interpolation is applied - as follows: a uniformly-distributed random number of the unit - interval, :math:`\xi`, is sampled. If :math:`\xi < (T - - T_i)/(T_{i+1} - T_i)`, then cross sections at temperature - :math:`T_{i+1}` are used. Otherwise, cross sections at - :math:`T_i` are used. This procedure is applied for pointwise - cross sections in the resolved resonance range, unresolved - resonance probability tables, and :math:`S(\alpha,\beta)` - thermal scattering tables. - -:Multipole: Resolved resonance cross sections are calculated on-the-fly using - techniques/data described in :ref:`windowed_multipole`. Cross - section data is loaded for a single temperature and is used in the - unresolved resonance and fast energy ranges. - ----------------- -Multi-Group Data ----------------- - -The data governing the interaction of particles with various nuclei or materials -are represented using a multi-group library format specific to the OpenMC code. -The format is described in the :ref:`mgxs_lib_spec`. The data itself can be -prepared via traditional paths or directly from a continuous-energy OpenMC -calculation by use of the Python API as is shown in the -:ref:`notebook_mg_mode_part_i` example notebook. This multi-group library -consists of meta-data (such as the energy group structure) and multiple `xsdata` -objects which contains the required microscopic or macroscopic multi-group data. - -At a minimum, the library must contain the absorption cross section -(:math:`\sigma_{a,g}`) and a scattering matrix. If the problem is an eigenvalue -problem then all fissionable materials must also contain either a fission -production matrix cross section (:math:`\nu\sigma_{f,g\rightarrow g'}`), or both -the fission spectrum data (:math:`\chi_{g'}`) and a fission production cross -section (:math:`\nu\sigma_{f,g}`), or, . The library must also contain the -fission cross section (:math:`\sigma_{f,g}`) or the fission energy release cross -section (:math:`\kappa\sigma_{f,g}`) if the associated tallies are required by -the model using the library. - -After a scattering collision, the outgoing particle experiences a change in both -energy and angle. The probability of a particle resulting in a given outgoing -energy group (`g'`) given a certain incoming energy group (`g`) is provided by -the scattering matrix data. The angular information can be expressed either via -Legendre expansion of the particle's change-in-angle (:math:`\mu`), a tabular -representation of the probability distribution function of :math:`\mu`, or a -histogram representation of the same PDF. The formats used to represent these -are described in the :ref:`mgxs_lib_spec`. - -Unlike the continuous-energy mode, the multi-group mode does not explicitly -track particles produced from scattering multiplication (i.e., :math:`(n,xn)`) -reactions. These are instead accounted for by adjusting the weight of the -particle after the collision such that the correct total weight is maintained. -The weight adjustment factor is optionally provided by the `multiplicity` data -which is required to be provided in the form of a group-wise matrix. This data -is provided as a group-wise matrix since the probability of producing multiple -particles in a scattering reaction depends on both the incoming energy, `g`, and -the sampled outgoing energy, `g'`. This data represents the average number of -particles emitted from a scattering reaction, given a scattering reaction has -occurred: - -.. math:: - - multiplicity_{g \rightarrow g'} = \frac{\nu_{scatter}\sigma_{s,g \rightarrow g'}}{ - \sigma_{s,g \rightarrow g'}} - -If this scattering multiplication information is not provided in the library -then no weight adjustment will be performed. This is equivalent to neglecting -any additional particles produced in scattering multiplication reactions. -However, this assumption will result in a loss of accuracy since the total -particle population would not be conserved. This reduction in accuracy due to -the loss in particle conservation can be mitigated by reducing the absorption -cross section as needed to maintain particle conservation. This adjustment can -be done when generating the library, or by OpenMC. To have OpenMC perform the -adjustment, the total cross section (:math:`\sigma_{t,g}`) must be provided. -With this information, OpenMC will then adjust the absorption cross section as -follows: - -.. math:: - - \sigma_{a,g} = \sigma_{t,g} - \sum_{g'}\nu_{scatter}\sigma_{s,g \rightarrow g'} - -The above method is the same as is usually done with most deterministic solvers. -Note that this method is less accurate than using the scattering multiplication -weight adjustment since simply reducing the absorption cross section does not -include any information about the outgoing energy of the particles produced in -these reactions. - -All of the data discussed in this section can be provided to the code -independent of the particle's direction of motion (i.e., isotropic), or the data -can be provided as a tabular distribution of the polar and azimuthal particle -direction angles. The isotropic representation is the most commonly used, -however inaccuracies are to be expected especially near material interfaces -where a material has a very large cross sections relative to the other material -(as can be expected in the resonance range). The angular representation can be -used to minimize this error. - -Finally, the above options for representing the physics do not have to be -consistent across the problem. The number of groups and the structure, however, -does have to be consistent across the data sets. That is to say that each -microscopic or macroscopic data set does not have to apply the same scattering -expansion, treatment of multiplicity or angular representation of the cross -sections. This allows flexibility for the model to use highly anisotropic -scattering information in the water while the fuel can be simulated with linear -or even isotropic scattering. - -.. _logarithmic mapping technique: - https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-14-24530.pdf -.. _Hwang: http://www.ans.org/pubs/journals/nse/a_16381 -.. _Josey: https://doi.org/10.1016/j.jcp.2015.08.013 -.. _WMP Library: https://github.com/mit-crpg/WMP_Library -.. _MCNP: http://mcnp.lanl.gov -.. _Serpent: http://montecarlo.vtt.fi -.. _NJOY: http://t2.lanl.gov/codes.shtml -.. _ENDF/B data: http://www.nndc.bnl.gov/endf -.. _Leppanen: https://doi.org/10.1016/j.anucene.2009.03.019 -.. _algorithms: http://ab-initio.mit.edu/wiki/index.php/Faddeeva_Package diff --git a/docs/source/methods/eigenvalue.rst b/docs/source/methods/eigenvalue.rst deleted file mode 100644 index 41bf86549..000000000 --- a/docs/source/methods/eigenvalue.rst +++ /dev/null @@ -1,161 +0,0 @@ -.. _methods_eigenvalue: - -======================= -Eigenvalue Calculations -======================= - -An eigenvalue calculation, also referred to as a criticality calculation, is a -transport simulation wherein the source of neutrons includes a fissionable -material. Some common eigenvalue calculations include the simulation of nuclear -reactors, spent fuel pools, nuclear weapons, and other fissile systems. The -reason they are called *eigenvalue* calculations is that the transport equation -becomes an eigenvalue equation if a fissionable source is present since then the -source of neutrons will depend on the flux of neutrons itself. Eigenvalue -simulations using Monte Carlo methods are becoming increasingly common with the -advent of high-performance computing. - -This section will explore the theory behind and implementation of eigenvalue -calculations in a Monte Carlo code. - -.. _method-successive-generations: - --------------------------------- -Method of Successive Generations --------------------------------- - -The method used to converge on the fission source distribution in an eigenvalue -calculation, known as the method of successive generations, was first introduced -by [Lieberoth]_. In this method, a finite number of neutron histories, -:math:`N`, are tracked through their lifetime iteratively. If fission occurs, -rather than tracking the resulting fission neutrons, the spatial coordinates of -the fission site, the sampled outgoing energy and direction of the fission -neutron, and the weight of the neutron are stored for use in the subsequent -generation. In OpenMC, the array used for storing the fission site information -is called the *fission bank*. At the end of each fission generation, :math:`N` -source sites for the next generation must be randomly sampled from the :math:`M` -fission sites that were stored to ensure that the neutron population does not -grow exponentially. The sampled source sites are stored in an array called the -*source bank* and can be retrieved during the subsequent generation. - -It's important to recognize that in the method of successive generations, we -must start with some assumption on how the fission source sites are distributed -since the distribution is not known *a priori*. Typically, a user will make a -guess as to what the distribution is -- this guess could be a uniform -distribution over some region of the geometry or simply a point -source. Fortunately, regardless of the choice of initial source distribution, -the method is guaranteed to converge to the true source distribution. Until the -source distribution converges, tallies should not be scored to since they will -otherwise include contributions from an unconverged source distribution. - -The method by which the fission source iterations are parallelized can have a -large impact on the achievable parallel scaling. This topic is discussed at length -in :ref:`fission-bank-algorithms`. - -------------------------- -Source Convergence Issues -------------------------- - -Diagnosing Convergence with Shannon Entropy -------------------------------------------- - -As discussed earlier, it is necessary to converge both :math:`k_{eff}` and the -source distribution before any tallies can begin. Moreover, the convergence rate -of the source distribution is in general slower than that of -:math:`k_{eff}`. One should thus examine not only the convergence of -:math:`k_{eff}` but also the convergence of the source distribution in order to -make decisions on when to start active batches. - -However, the representation of the source distribution makes it a bit more -difficult to analyze its convergence. Since :math:`k_{eff}` is a scalar -quantity, it is easy to simply look at a line plot of :math:`k_{eff}` versus the -number of batches and this should give the user some idea about whether it has -converged. On the other hand, the source distribution at any given batch is a -finite set of coordinates in Euclidean space. In order to analyze the -convergence, we would either need to use a method for assessing convergence of -an N-dimensional quantity or transform our set of coordinates into a scalar -metric. The latter approach has been developed considerably over the last decade -and a method now commonly used in Monte Carlo eigenvalue calculations is to use -a metric called the `Shannon entropy`_, a concept borrowed from information -theory. - -To compute the Shannon entropy of the source distribution, we first need to -discretize the source distribution rather than having a set of coordinates in -Euclidean space. This can be done by superimposing a structured mesh over the -geometry (containing at least all fissionable materials). Then, the fraction of -source sites that are present in each mesh element is counted: - -.. math:: - :label: fraction-source - - S_i = \frac{\text{Source sites in $i$-th mesh element}}{\text{Total number of - source sites}} - -The Shannon entropy is then computed as - -.. math:: - :label: shannon-entropy - - H = - \sum_{i=1}^N S_i \log_2 S_i - -where :math:`N` is the number of mesh elements. With equation -:eq:`shannon-entropy`, we now have a scalar metric that we can use to assess the -convergence of the source distribution by observing line plots of the Shannon -entropy versus the number of batches. - -In recent years, researchers have started looking at ways of automatically -assessing source convergence to relieve the burden on the user of having to look -at plots of :math:`k_{eff}` and the Shannon entropy. A number of methods have -been proposed (see e.g. [Romano]_, [Ueki]_), but each of these is not without -problems. - ---------------------------- -Uniform Fission Site Method ---------------------------- - -Generally speaking, the variance of a Monte Carlo tally will be inversely -proportional to the number of events that score to the tally. In a reactor -problem, this implies that regions with low relative power density will have -higher variance that regions with high relative power density. One method to -circumvent the uneven distribution of relative errors is the uniform fission -site (UFS) method introduced by [Sutton]_. In this method, the portion of the -problem containing fissionable material is subdivided into a number of cells -(typically using a structured mesh). Rather than producing - -.. math:: - - m = \frac{w}{k} \frac{\nu\Sigma_f}{\Sigma_t} - -fission sites at each collision where :math:`w` is the weight of the neutron, -:math:`k` is the previous-generation estimate of the neutron multiplication -factor, :math:`\nu\Sigma_f` is the neutron production cross section, and -:math:`\Sigma_t` is the total cross section, in the UFS method we produce - -.. math:: - - m_{UFS} = \frac{w}{k} \frac{\nu\Sigma_f}{\Sigma_t} \frac{v_i}{s_i} - -fission sites at each collision where :math:`v_i` is the fraction of the total -volume occupied by cell :math:`i` and :math:`s_i` is the fraction of the fission -source contained in cell :math:`i`. To ensure that no bias is introduced, the -weight of each fission site stored in the fission bank is :math:`s_i/v_i` rather -than unity. By ensuring that the expected number of fission sites in each mesh -cell is constant, the collision density across all cells, and hence the variance -of tallies, is more uniform than it would be otherwise. - -.. _Shannon entropy: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-06-3737.pdf - -.. [Lieberoth] J. Lieberoth, "A Monte Carlo Technique to Solve the Static - Eigenvalue Problem of the Boltzmann Transport Equation," *Nukleonik*, **11**, - 213-219 (1968). - -.. [Romano] Paul K. Romano, "Application of the Stochastic Oscillator to Assess - Source Convergence in Monte Carlo Criticality Calculations," - *Proc. International Conference on Mathematics, Computational Methods, and - Reactor Physics*, Saratoga Springs, New York (2009). - -.. [Sutton] Daniel J. Kelly, Thomas M. Sutton, and Stephen C. Wilson, "MC21 - Analysis of the Nuclear Energy Agency Monte Carlo Performance Benchmark - Problem," *Proc. PHYSOR 2012*, Knoxville, Tennessee, Apr. 15--20 (2012). - -.. [Ueki] Taro Ueki, "On-the-Fly Judgments of Monte Carlo Fission Source - Convergence," *Trans. Am. Nucl. Soc.*, **98**, 512 (2008). diff --git a/docs/source/methods/energy_deposition.rst b/docs/source/methods/energy_deposition.rst deleted file mode 100644 index 86dfb9bf9..000000000 --- a/docs/source/methods/energy_deposition.rst +++ /dev/null @@ -1,149 +0,0 @@ -.. _methods_heating: - -============================= -Heating and Energy Deposition -============================= - -As particles traverse a problem, some portion of their energy is deposited at -collision sites. This energy is deposited when charged particles, including -electrons and recoil nuclei, undergo electromagnetic interactions with -surrounding electons and ions. The information describing how much energy -is deposited for a specific reaction is referred to as -"heating numbers" and can be computed using a program like NJOY with the -``heatr`` module. - -These heating rate is the product of reaction-specific coefficients and -a reaction cross section - -.. math:: - - H(E) = \phi(E)\sum_i\rho_i\sum_rk_{i, r}(E), - -and has units energy per time, typically eV / s. -Here, :math:`k_{i, r}` are the KERMA (Kinetic Energy Release in Materials) -[Mack97]_ coefficients for reaction :math:`r` of isotope :math:`i`. -The KERMA coefficients have units energy :math:`\times` cross-section, e.g. -eV-barn, and can be used much like a reaction cross section for the purpose -of tallying energy deposition. - -KERMA coefficients can be computed using the energy-balance method with -a nuclear data processing code like NJOY, which performs the following -iteration over all reactions :math:`r` for all isotopes :math:`i` -requested - -.. math:: - - k_{i, r}(E) = \left(E + Q_{i, r} - \bar{E}_{i, r, n} - - \bar{E}_{i, r, \gamma}\right)\sigma_{i, r}(E), - -removing the energy of neutral particles (neutrons and photons) that are -transported away from the reaction site :math:`\bar{E}`, and the reaction -:math:`Q` value. - -------- -Fission -------- - -During a fission event, there are potentially many secondary particles, and all -must be considered. The total energy released in a fission event is typically -broken up into the following categories: - -- :math:`E_{fr}` - kinetic energy of fission fragments -- :math:`E_{n,p}` - energy of prompt fission neutrons -- :math:`E_{n,d}` - energy of delayed fission neutrons -- :math:`E_{\gamma,p}` - energy of prompt fission photons -- :math:`E_{\gamma,d}` - energy of delayed fission photons -- :math:`E_{\beta}` - energy of released :math:`\beta` particles -- :math:`E_{\nu}` - energy of neutrinos - -These components are defined in MF=1,MT=458 data in a standard ENDF/B-6 formatted -file. All these quantities may depend upon incident neutron energy, -but this dependence is not shown to make the following demonstrations cleaner. -As neutrinos scarcely interact with matter, the recoverable energy from -fission is defined as - -.. math:: - - E_r\equiv E_{fr} + E_{n,p} + E_{n, d} + E_{\gamma, p} - + E_{\gamma, d} + E_{\beta} - -Furthermore, the energy of the secondary neutrons and photons is given as -:math:`E_{n, p}` and :math:`E_{\gamma, p}`, respectively. - -NJOY computes the fission KERMA coefficient using this energy-balance method to be - -.. math:: - - k_{i, f}(E) = \left[E + Q(E) - \bar{E}(E)\right]\sigma_{i, f}(E) - = \left[E_{fr} + E_{\gamma, p}\right]\sigma_{i, j}(E) - -.. note:: - - The energy from delayed neutrons and photons and beta particles is intentionally - left out from the NJOY calculations. - ---------------------- -OpenMC Implementation ---------------------- - -For fissile isotopes, OpenMC makes modifications to the heating reaction to -include all relevant components of fission energy release. These modifications -are made to the total heating reaction, MT=301. Breaking the total heating -KERMA into a fission and non-fission section, one can write - -.. math:: - - k_i(E) = k_{i, nf}(E) + \left[E_{fr}(E) + E_{\gamma, p}\right]\sigma_{i, f}(E) - -OpenMC seeks to modify the total heating data to include energy from -:math:`\beta` particles and, conditionally, delayed photons. This conditional -inclusion depends on the simulation mode: neutron transport, or coupled -neutron-photon transport. The heating due to fission is removed using MT=318 -data, and then re-built using the desired components of fission energy release -from MF=1,MT=458 data. - -Neutron Transport ------------------ - -For this case, OpenMC instructs ``heatr`` to produce heating coefficients -assuming that energy from photons, :math:`E_{\gamma, p}` and -:math:`E_{\gamma, d}`, is deposited at the fission site. -Let :math:`N901` represent the total heating number returned from this ``heatr`` -run with :math:`N918` reflecting fission heating computed from NJOY. -:math:`M901` represent the following modification - -.. math:: - - M901_{i}(E)\equiv N901_{i}(E) - N918_{i}(E) - + \left[E_{i, fr} + E_{i, \beta} + E_{i, \gamma, p} - + E_{i, \gamma, d}\right]\sigma_{i, f}(E). - -This modified heating data is stored as the MT=901 reaction and will be scored -if ``heating-local`` is included in :attr:`openmc.Tally.scores`. - -Coupled neutron-photon transport --------------------------------- - -Here, OpenMC instructs ``heatr`` to assume that energy from photons is not -deposited locally. However, the definitions provided in the NJOY manual -indicate that, regardless of this mode, the prompt photon energy is still -included in :math:`k_{i, f}`, and therefore must be manually removed. -Let :math:`N301` represent the total heating number returned from this -``heatr`` run and :math:`M301` be - -.. math:: - - M301_{i}(E)\equiv N301_{i}(E) - N318_{i}(E) - + \left[E_{i, fr}(E) + E_{i, \beta}(E)\right]\sigma_{i, f}(E). - -This modified heating data is stored as the MT=301 reaction and will be scored -if ``heating`` is included in :attr:`openmc.Tally.scores`. - ----------- -References ----------- - -.. [Mack97] Abdou, M.A., Maynard, C.W., and Wright, R.Q. MACK: computer - program to calculate neutron energy release parameters (fluence-to-kerma - factors) and multigroup neutron reaction cross sections from nuclear data - in ENDF Format. Oak Ridge National Laboratory report ORNL-TM-3994. diff --git a/docs/source/methods/geometry.rst b/docs/source/methods/geometry.rst deleted file mode 100644 index 38d9eb172..000000000 --- a/docs/source/methods/geometry.rst +++ /dev/null @@ -1,967 +0,0 @@ -.. _methods_geometry: - -======== -Geometry -======== - ---------------------------- -Constructive Solid Geometry ---------------------------- - -OpenMC uses a technique known as `constructive solid geometry`_ (CSG) to build -arbitrarily complex three-dimensional models in Euclidean space. In a CSG model, -every unique object is described as the union and/or intersection of -*half-spaces* created by bounding `surfaces`_. Every surface divides all of -space into exactly two half-spaces. We can mathematically define a surface as a -collection of points that satisfy an equation of the form :math:`f(x,y,z) = 0` -where :math:`f(x,y,z)` is a given function. All coordinates for which -:math:`f(x,y,z) < 0` are referred to as the negative half-space (or simply the -*negative side*) and coordinates for which :math:`f(x,y,z) > 0` are referred to -as the positive half-space. - -Let us take the example of a sphere centered at the point :math:`(x_0,y_0,z_0)` -with radius :math:`R`. One would normally write the equation of the sphere as - -.. math:: - :label: sphere-equation - - (x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = R^2 - -By subtracting the right-hand term from both sides of equation -:eq:`sphere-equation`, we can then write the surface equation for the sphere: - -.. math:: - :label: surface-equation-sphere - - f(x,y,z) = (x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0 - -One can confirm that any point inside this sphere will correspond to -:math:`f(x,y,z) < 0` and any point outside the sphere will correspond to -:math:`f(x,y,z) > 0`. - -In OpenMC, every surface defined by the user is assigned an integer to uniquely -identify it. We can then refer to either of the two half-spaces created by a -surface by a combination of the unique ID of the surface and a positive/negative -sign. Figure :num:`fig-halfspace` shows an example of an ellipse with unique ID 1 -dividing space into two half-spaces. - -.. _fig-halfspace: - -.. figure:: ../_images/halfspace.svg - :align: center - :figclass: align-center - - Example of an ellipse and its associated half-spaces. - -References to half-spaces created by surfaces are used to define regions of -space of uniform composition, which are then assigned to *cells*. OpenMC allows -regions to be defined using union, intersection, and complement operators. As in -MCNP_, the intersection operator is implicit as doesn't need to be written in a -region specification. A defined region is then associated with a material -composition in a cell. Figure :num:`fig-union` shows an example of a cell region -defined as the intersection of an ellipse and two planes. - -.. _fig-union: - -.. figure:: ../_images/union.svg - :align: center - :figclass: align-center - - The shaded region represents a cell bounded by three surfaces. - -The ability to form regions based on bounding quadratic surfaces enables OpenMC -to model arbitrarily complex three-dimensional objects. In practice, one is -limited only by the different surface types available in OpenMC. The following -table lists the available surface types, the identifier used to specify them in -input files, the corresponding surface equation, and the input parameters needed -to fully define the surface. - -.. table:: Surface types available in OpenMC. - - +----------------------+------------+------------------------------+-------------------------+ - | Surface | Identifier | Equation | Parameters | - +======================+============+==============================+=========================+ - | Plane perpendicular | x-plane | :math:`x - x_0 = 0` | :math:`x_0` | - | to :math:`x`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Plane perpendicular | y-plane | :math:`y - y_0 = 0` | :math:`y_0` | - | to :math:`y`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Plane perpendicular | z-plane | :math:`z - z_0 = 0` | :math:`z_0` | - | to :math:`z`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Arbitrary plane | plane | :math:`Ax + By + Cz = D` | :math:`A\;B\;C\;D` | - +----------------------+------------+------------------------------+-------------------------+ - | Infinite cylinder | x-cylinder | :math:`(y-y_0)^2 + (z-z_0)^2 | :math:`y_0\;z_0\;R` | - | parallel to | | = R^2` | | - | :math:`x`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Infinite cylinder | y-cylinder | :math:`(x-x_0)^2 + (z-z_0)^2 | :math:`x_0\;z_0\;R` | - | parallel to | | = R^2` | | - | :math:`y`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Infinite cylinder | z-cylinder | :math:`(x-x_0)^2 + (y-y_0)^2 | :math:`x_0\;y_0\;R` | - | parallel to | | = R^2` | | - | :math:`z`-axis | | | | - +----------------------+------------+------------------------------+-------------------------+ - | Sphere | sphere | :math:`(x-x_0)^2 + (y-y_0)^2 | :math:`x_0 \; y_0 \; | - | | | + (z-z_0)^2 = R^2` | z_0 \; R` | - +----------------------+------------+------------------------------+-------------------------+ - | Cone parallel to the | x-cone | :math:`(y-y_0)^2 + (z-z_0)^2 | :math:`x_0 \; y_0 \; | - | :math:`x`-axis | | = R^2(x-x_0)^2` | z_0 \; R^2` | - +----------------------+------------+------------------------------+-------------------------+ - | Cone parallel to the | y-cone | :math:`(x-x_0)^2 + (z-z_0)^2 | :math:`x_0 \; y_0 \; | - | :math:`y`-axis | | = R^2(y-y_0)^2` | z_0 \; R^2` | - +----------------------+------------+------------------------------+-------------------------+ - | Cone parallel to the | z-cone | :math:`(x-x_0)^2 + (y-y_0)^2 | :math:`x_0 \; y_0 \; | - | :math:`z`-axis | | = R^2(z-z_0)^2` | z_0 \; R^2` | - +----------------------+------------+------------------------------+-------------------------+ - | General quadric | quadric | :math:`Ax^2 + By^2 + Cz^2 + | :math:`A \; B \; C \; D | - | surface | | Dxy + Eyz + Fxz + Gx + Hy + | \; E \; F \; G \; H \; | - | | | Jz + K` | J \; K` | - +----------------------+------------+------------------------------+-------------------------+ - -.. _universes: - -Universes ---------- - -OpenMC supports universe-based geometry similar to the likes of MCNP_ and -Serpent_. This capability enables user to model any identical repeated -structures once and then fill them in various spots in the geometry. A -prototypical example of a repeated structure would be a fuel pin within a fuel -assembly or a fuel assembly within a core. - -Each cell in OpenMC can either be filled with a normal material or with a -universe. If the cell is filled with a universe, only the region of the universe -that is within the defined boundaries of the parent cell will be present in the -geometry. That is to say, even though a collection of cells in a universe may -extend to infinity, not all of the universe will be "visible" in the geometry -since it will be truncated by the boundaries of the cell that contains it. - -When a cell is filled with a universe, it is possible to specify that the -universe filling the cell should be rotated and translated. This is done through -the ``rotation`` and ``translation`` attributes on a cell (note though that -these can only be specified on a cell that is filled with another universe, not -a material). - -It is not necessary to use or assign universes in a geometry if there are no -repeated structures. Any cell in the geometry that is not assigned to a -specified universe is automatically part of the *base universe* whose -coordinates are just the normal coordinates in Euclidean space. - -Lattices --------- - -Often times, repeated structures in a geometry occur in a regular pattern such -as a rectangular or hexagonal lattice. In such a case, it would be cumbersome -for a user to have to define the boundaries of each of the cells to be filled -with a universe. Thus, OpenMC provides a lattice capability similar to that used -in MCNP_ and Serpent_. - -The implementation of lattices is similar in principle to universes --- instead -of a cell being filled with a universe, the user can specify that it is filled -with a finite lattice. The lattice is then defined by a two-dimensional array of -universes that are to fill each position in the lattice. A good example of the -use of lattices and universes can be seen in the OpenMC model for the `Monte -Carlo Performance benchmark`_. - ------------------------------------------- -Computing the Distance to Nearest Boundary ------------------------------------------- - -One of the most basic algorithms in any Monte Carlo code is determining the -distance to the nearest surface within a cell. Since each cell is defined by -the surfaces that bound it, if we compute the distance to all surfaces bounding -a cell, we can determine the nearest one. - -With the possibility of a particle having coordinates on multiple levels -(universes) in a geometry, we must exercise care when calculating the distance -to the nearest surface. Each different level of geometry has a set of boundaries -with which the particle's direction of travel may intersect. Thus, it is -necessary to check the distance to the surfaces bounding the cell in each -level. This should be done starting the highest (most global) level going down -to the lowest (most local) level. That ensures that if two surfaces on different -levels are coincident, by default the one on the higher level will be selected -as the nearest surface. Although they are not explicitly defined, it is also -necessary to check the distance to surfaces representing lattice boundaries if a -lattice exists on a given level. - -The following procedure is used to calculate the distance to each bounding -surface. Suppose we have a particle at :math:`(x_0,y_0,z_0)` traveling in the -direction :math:`u_0,v_0,w_0`. To find the distance :math:`d` to a surface -:math:`f(x,y,z) = 0`, we need to solve the equation: - -.. math:: - :label: dist-to-boundary-1 - - f(x_0 + du_0, y_0 + dv_0, z_0 + dw_0) = 0 - -If no solutions to equation :eq:`dist-to-boundary-1` exist or the only solutions -are complex, then the particle's direction of travel will not intersect the -surface. If the solution to equation :eq:`dist-to-boundary-1` is negative, this -means that the surface is "behind" the particle, i.e. if the particle continues -traveling in its current direction, it will not hit the surface. The complete -derivation for different types of surfaces used in OpenMC will be presented in -the following sections. - -Since :math:`f(x,y,z)` in general is quadratic in :math:`x`, :math:`y`, and -:math:`z`, this implies that :math:`f(x_0 + du_0, y + dv_0, z + dw_0)` is -quadratic in :math:`d`. Thus we expect at most two real solutions to -:eq:`dist-to-boundary-1`. If no solutions to :eq:`dist-to-boundary-1` exist or -the only solutions are complex, then the particle's direction of travel will not -intersect the surface. If the solution to :eq:`dist-to-boundary-1` is negative, -this means that the surface is "behind" the particle, i.e. if the particle -continues traveling in its current direction, it will not hit the surface. - -Once a distance has been computed to a surface, we need to check if it is closer -than previously-computed distances to surfaces. Unfortunately, we cannot just -use the minimum function because some of the calculated distances, which should -be the same in theory (e.g. coincident surfaces), may be slightly different due -to the use of floating-point arithmetic. Consequently, we should first check for -floating-point equality of the current distance calculated and the minimum found -thus far. This is done by checking if - -.. math:: - :label: fp-distance - - \frac{| d - d_{min} |}{d_{min}} < \epsilon - -where :math:`d` is the distance to a surface just calculated, :math:`d_{min}` is -the minimum distance found thus far, and :math:`\epsilon` is a small number. In -OpenMC, this parameter is set to :math:`\epsilon = 10^{-14}` since all floating -calculations are done on 8-byte floating point numbers. - -Plane Perpendicular to an Axis ------------------------------- - -The equation for a plane perpendicular to, for example, the x-axis is simply -:math:`x - x_0 = 0`. As such, we need to solve :math:`x + du - x_0 = 0`. The -solution for the distance is - -.. math:: - :label: dist-xplane - - d = \frac{x_0 - x}{u} - -Note that if the particle's direction of flight is parallel to the x-axis, -i.e. :math:`u = 0`, the distance to the surface will be infinity. While the -example here was for a plane perpendicular to the x-axis, the same formula can -be applied for the surfaces :math:`y = y_0` and :math:`z = z_0`. - -Generic Plane -------------- - -The equation for a generic plane is :math:`Ax + By + Cz = D`. Thus, we need to -solve the equation :math:`A(x + du) + B(y + dv) + C(z + dw) = D`. The solution -to this equation for the distance is - -.. math:: - :label: dist-plane - - d = \frac{D - Ax - By - Cz}{Au + Bv + Cw} - -Again, we need to check whether the denominator is zero. If so, this means that -the particle's direction of flight is parallel to the plane and it will -therefore never hit the plane. - -.. _cylinder_distance: - -Cylinder Parallel to an Axis ----------------------------- - -The equation for a cylinder parallel to, for example, the x-axis is :math:`(y - -y_0)^2 + (z - z_0)^2 = R^2`. Thus, we need to solve :math:`(y + dv - y_0)^2 + -(z + dw - z_0)^2 = R^2`. Let us define :math:`\bar{y} = y - y_0` and -:math:`\bar{z} = z - z_0`. We then have - -.. math:: - :label: dist-xcylinder-1 - - (\bar{y} + dv)^2 + (\bar{z} + dw)^2 = R^2 - -Expanding equation :eq:`dist-xcylinder-1` and rearranging terms, we obtain - -.. math:: - :label: dist-xcylinder-2 - - (v^2 + w^2) d^2 + 2 (\bar{y}v + \bar{z}w) d + (\bar{y}^2 + \bar{z}^2 - R^2) - = 0 - -This is a quadratic equation for :math:`d`. To simplify notation, let us define -:math:`a = v^2 + w^2`, :math:`k = \bar{y}v + \bar{z}w`, and :math:`c = -\bar{y}^2 + \bar{z}^2 - R^2`. Thus, the distance is just the solution to -:math:`ad^2 + 2kd + c = 0`: - -.. math:: - :label: dist-xcylinder-3 - - d = \frac{-k \pm \sqrt{k^2 - ac}}{a} - -A few conditions must be checked for. If :math:`a = 0`, this means the particle -is parallel to the cylinder and will thus never intersect it. Also, if -:math:`k^2 - ac < 0`, this means that both solutions to the quadratic are -complex. In physical terms, this means that the ray along which the particle is -traveling does not make any intersections with the cylinder. - -If we do have intersections and :math:`c < 0`, this means that the particle is -inside the cylinder. Thus, one solution should be positive and one should be -negative. Clearly, the positive distance will occur when the sign on the -square root of the discriminant is positive since :math:`a > 0`. - -If we have intersections and :math:`c > 0` this means that the particle is -outside the cylinder. Thus, the solutions to the quadratic are either both -positive or both negative. If they are both positive, the smaller (closer) one -will be the solution with a negative sign on the square root of the -discriminant. - -The same equations and logic here can be used for cylinders that are parallel to -the y- or z-axis with appropriate substitution of constants. - -Sphere ------- - -The equation for a sphere is :math:`(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = -R^2`. Thus, we need to solve the equation - -.. math:: - :label: dist-sphere-1 - - (x + du - x_0)^2 + (y + dv - y_0)^2 + (z + dw - z_0)^2 = R^2 - -Let us define :math:`\bar{x} = x - x_0`, :math:`\bar{y} = y - y_0`, and -:math:`\bar{z} = z - z_0`. We then have - -.. math:: - :label: dist-sphere-2 - - (\bar{x} + du)^2 + (\bar{y} + dv)^2 + (\bar{z} - dw)^2 = R^2 - -Expanding equation :eq:`dist-sphere-2` and rearranging terms, we obtain - -.. math:: - :label: dist-sphere-3 - - d^2 + 2 (\bar{x}u + \bar{y}v + \bar{z}w) d + (\bar{x}^2 + \bar{y}^2 + - \bar{z}^2 - R^2) = 0 - -This is a quadratic equation for :math:`d`. To simplify notation, let us define -:math:`k = \bar{x}u + \bar{y}v + \bar{z}w` and :math:`c = \bar{x}^2 + -\bar{y}^2 + \bar{z}^2 - R^2`. Thus, the distance is just the solution to -:math:`d^2 + 2kd + c = 0`: - -.. math:: - :label: dist-sphere-4 - - d = -k \pm \sqrt{k^2 - c} - -If the discriminant :math:`k^2 - c < 0`, this means that both solutions to the -quadratic are complex. In physical terms, this means that the ray along which -the particle is traveling does not make any intersections with the sphere. - -If we do have intersections and :math:`c < 0`, this means that the particle is -inside the sphere. Thus, one solution should be positive and one should be -negative. The positive distance will occur when the sign on the square root of -the discriminant is positive. If we have intersections but :math:`c > 0` this -means that the particle is outside the sphere. The solutions to the quadratic -will then be either both positive or both negative. If they are both positive, -the smaller (closer) one will be the solution with a negative sign on the square -root of the discriminant. - -Cone Parallel to an Axis ------------------------- - -The equation for a cone parallel to, for example, the x-axis is :math:`(y - -y_0)^2 + (z - z_0)^2 = R^2(x - x_0)^2`. Thus, we need to solve :math:`(y + dv - -y_0)^2 + (z + dw - z_0)^2 = R^2(x + du - x_0)^2`. Let us define :math:`\bar{x} = -x - x_0`, :math:`\bar{y} = y - y_0`, and :math:`\bar{z} = z - z_0`. We then have - -.. math:: - :label: dist-xcone-1 - - (\bar{y} + dv)^2 + (\bar{z} + dw)^2 = R^2(\bar{x} + du)^2 - -Expanding equation :eq:`dist-xcone-1` and rearranging terms, we obtain - -.. math:: - :label: dist-xcone-2 - - (v^2 + w^2 - R^2u^2) d^2 + 2 (\bar{y}v + \bar{z}w - R^2\bar{x}u) d + - (\bar{y}^2 + \bar{z}^2 - R^2\bar{x}^2) = 0 - -Defining the terms - -.. math:: - :label: dist-xcone-terms - - a = v^2 + w^2 - R^2u^2 - - k = \bar{y}v + \bar{z}w - R^2\bar{x}u - - c = \bar{y}^2 + \bar{z}^2 - R^2\bar{x}^2 - -we then have the simple quadratic equation :math:`ad^2 + 2kd + c = 0` which can -be solved as described in :ref:`cylinder_distance`. - -General Quadric ---------------- - -The equation for a general quadric surface is :math:`Ax^2 + By^2 + Cz^2 + Dxy + -Eyz + Fxz + Gx + Hy + Jz + K = 0`. Thus, we need to solve the equation - -.. math:: - :label: dist-quadric-1 - - A(x+du)^2 + B(y+dv)^2 + C(z+dw)^2 + D(x+du)(y+dv) + E(y+dv)(z+dw) + \\ - F(x+du)(z+dw) + G(x+du) + H(y+dv) + J(z+dw) + K = 0 - -Expanding equation :eq:`dist-quadric-1` and rearranging terms, we obtain - -.. math:: - :label: dist-quadric-2 - - d^2(uv + vw + uw) + 2d(Aux + Bvy + Cwx + (D(uv + vx) + E(vz + wy) + \\ - F(wx + uz))/2) + (x(Ax + Dy) + y(By + Ez) + z(Cz + Fx)) = 0 - -Defining the terms - -.. math:: - :label: dist-quadric-terms - - a = uv + vw + uw - - k = Aux + Bvy + Cwx + (D(uv + vx) + E(vz + wy) + F(wx + uz))/2 - - c = x(Ax + Dy) + y(By + Ez) + z(Cz + Fx) - -we then have the simple quadratic equation :math:`ad^2 + 2kd + c = 0` which can -be solved as described in :ref:`cylinder_distance`. - -.. _find-cell: - ----------------------------- -Finding a Cell Given a Point ----------------------------- - -Another basic algorithm is to determine which cell contains a given point in the -global coordinate system, i.e. if the particle's position is :math:`(x,y,z)`, -what cell is it currently in. This is done in the following manner in -OpenMC. With the possibility of multiple levels of coordinates, we must perform -a recursive search for the cell. First, we start in the highest (most global) -universe, which we call the base universe, and loop over each cell within -that universe. For each cell, we check whether the specified point is inside the -cell using the algorithm described in :ref:`cell-contains`. If the cell is -filled with a normal material, the search is done and we have identified the -cell containing the point. If the cell is filled with another universe, we then -search all cells within that universe to see if any of them contain the -specified point. If the cell is filled with a lattice, the position within the -lattice is determined, and then whatever universe fills that lattice position is -recursively searched. The search ends once a cell containing a normal material -is found that contains the specified point. - -.. _cell-contains: - ----------------------- -Finding a Lattice Tile ----------------------- - -If a particle is inside a lattice, its position inside the lattice must be -determined before assigning it to a cell. Throughout this section, the -volumetric units of the lattice will be referred to as "tiles". Tiles are -identified by thier indices, and the process of discovering which tile contains -the particle is referred to as "indexing". - -Rectilinear Lattice Indexing ----------------------------- - -Indices are assigned to tiles in a rectilinear lattice based on the tile's -position along the :math:`x`, :math:`y`, and :math:`z` axes. Figure -:num:`fig-rect-lat` maps the indices for a 2D lattice. The indices, (1, 1), -map to the lower-left tile. (5, 1) and (5, 5) map to the lower-right and -upper-right tiles, respectively. - -.. _fig-rect-lat: - -.. figure:: ../_images/rect_lat.svg - :align: center - :figclass: align-center - :width: 400px - - Rectilinear lattice tile indices. - -In general, a lattice tile is specified by the three indices, -:math:`(i_x, i_y, i_z)`. If a particle's current coordinates are -:math:`(x, y, z)` then the indices can be determined from these formulas: - -.. math:: - :label: rect_indexing - - i_x = \left \lceil \frac{x - x_0}{p_0} \right \rceil - - i_y = \left \lceil \frac{y - y_0}{p_1} \right \rceil - - i_z = \left \lceil \frac{z - z_0}{p_2} \right \rceil - -where :math:`(x_0, y_0, z_0)` are the coordinates to the lower-left-bottom -corner of the lattice, and :math:`p_0, p_1, p_2` are the pitches along the -:math:`x`, :math:`y`, and :math:`z` axes, respectively. - -.. _hexagonal_indexing: - -Hexagonal Lattice Indexing --------------------------- - -A skewed coordinate system is used for indexing hexagonal lattice tiles. -Rather than a :math:`y`-axis, another axis is used that is rotated 30 degrees -counter-clockwise from the :math:`y`-axis. This axis is referred to as the -:math:`\alpha`-axis. Figure :num:`fig-hex-lat` shows how 2D hexagonal tiles -are mapped with the :math:`(x, \alpha)` basis. In this system, (0, 0) maps to -the center tile, (0, 2) to the top tile, and (2, -1) to the middle tile on the -right side. - -.. _fig-hex-lat: - -.. figure:: ../_images/hex_lat.svg - :align: center - :figclass: align-center - :width: 400px - - Hexagonal lattice tile indices. - -Unfortunately, the indices cannot be determined with one simple formula as -before. Indexing requires a two-step process, a coarse step which determines a -set of four tiles that contains the particle and a fine step that determines -which of those four tiles actually contains the particle. - -In the first step, indices are found using these formulas: - -.. math:: - :label: hex_indexing - - \alpha = -\frac{x}{\sqrt{3}} + y - - i_x^* = \left \lfloor \frac{x}{p_0 \sqrt{3} / 2} \right \rfloor - - i_\alpha^* = \left \lfloor \frac{\alpha}{p_0} \right \rfloor - -where :math:`p_0` is the lattice pitch (in the :math:`x`-:math:`y` plane). The -true index of the particle could be :math:`(i_x^*, i_\alpha^*)`, -:math:`(i_x^* + 1, i_\alpha^*)`, :math:`(i_x^*, i_\alpha^* + 1)`, or -:math:`(i_x^* + 1, i_\alpha^* + 1)`. - -The second step selects the correct tile from that neighborhood of 4. OpenMC -does this by calculating the distance between the particle and the centers of -each of the 4 tiles, and then picking the closest tile. This works because -regular hexagonal tiles form a Voronoi tessellation which means that all of the -points within a tile are closest to the center of that same tile. - -Indexing along the :math:`z`-axis uses the same method from rectilinear -lattices, i.e. - -.. math:: - :label: hex_indexing_z - - i_z = \left \lceil \frac{z - z_0}{p_2} \right \rceil - ----------------------------------------- -Determining if a Coordinate is in a Cell ----------------------------------------- - -To determine which cell a particle is in given its coordinates, we need to be -able to check whether a given cell contains a point. The algorithm for -determining if a cell contains a point is as follows. For each surface that -bounds a cell, we determine the particle's sense with respect to the surface. As -explained earlier, if we have a point :math:`(x_0,y_0,z_0)` and a surface -:math:`f(x,y,z) = 0`, the point is said to have negative sense if -:math:`f(x_0,y_0,z_0) < 0` and positive sense if :math:`f(x_0,y_0,z_0) > 0`. If -for all surfaces, the sense of the particle with respect to the surface matches -the specified sense that defines the half-space within the cell, then the point -is inside the cell. Note that this algorithm works only for *simple cells* -defined as intersections of half-spaces. - -It may help to illustrate this algorithm using a simple example. Let's say we -have a cell defined as - -.. code-block:: xml - - - - - - -This means that the cell is defined as the intersection of the negative half -space of a sphere, the positive half-space of an x-plane, and the negative -half-space of a y-plane. Said another way, any point inside this cell must -satisfy the following equations - -.. math:: - :label: cell-contains-example - - x^2 + y^2 + z^2 - 10^2 < 0 \\ - x - (-3) > 0 \\ - y - 2 < 0 - -In order to determine if a point is inside the cell, we would substitute its -coordinates into equation :eq:`cell-contains-example`. If the inequalities are -satisfied, than the point is indeed inside the cell. - --------------------------- -Handling Surface Crossings --------------------------- - -A particle will cross a surface if the distance to the nearest surface is closer -than the distance sampled to the next collision. A number of things happen when -a particle hits a surface. First, we need to check if a non-transmissive -boundary condition has been applied to the surface. If a vacuum boundary -condition has been applied, the particle is killed and any surface current -tallies are scored to as needed. If a reflective boundary condition has been -applied to the surface, surface current tallies are scored to and then the -particle's direction is changed according to the procedure in :ref:`reflection`. -Note that the white boundary condition can be considered as the special case of -reflective boundary condition, where the same processing method will be applied to -deal with the surface current tallies scoring, except for determining the -changes of particle's direction according to the procedures in :ref:`white`. - -Next, we need to determine what cell is beyond the surface in the direction of -travel of the particle so that we can evaluate cross sections based on its -material properties. At initialization, a list of neighboring cells is created -for each surface in the problem as described in :ref:`neighbor-lists`. The -algorithm outlined in :ref:`find-cell` is used to find a cell containing the -particle with one minor modification; rather than searching all cells in the -base universe, only the list of neighboring cells is searched. If this search is -unsuccessful, then a search is done over every cell in the base universe. - -.. _neighbor-lists: - ------------------------ -Building Neighbor Lists ------------------------ - -After the geometry has been loaded and stored in memory from an input file, -OpenMC builds a list for each surface containing any cells that are bounded by -that surface in order to speed up processing of surface crossings. The algorithm -to build these lists is as follows. First, we loop over all cells in the -geometry and count up how many times each surface appears in a specification as -bounding a negative half-space and bounding a positive half-space. Two arrays -are then allocated for each surface, one that lists each cell that contains the -negative half-space of the surface and one that lists each cell that contains -the positive half-space of the surface. Another loop is performed over all cells -and the neighbor lists are populated for each surface. - -.. _reflection: - ------------------------------- -Reflective Boundary Conditions ------------------------------- - -If the velocity of a particle is :math:`\mathbf{v}` and it crosses a surface of -the form :math:`f(x,y,z) = 0` with a reflective boundary condition, it can be -shown based on geometric arguments that the velocity vector will then become - -.. math:: - :label: reflection-v - - \mathbf{v'} = \mathbf{v} - 2 (\mathbf{v} \cdot \hat{\mathbf{n}}) - \hat{\mathbf{n}} - -where :math:`\hat{\mathbf{n}}` is a unit vector normal to the surface at the -point of the surface crossing. The rationale for this can be understood by -noting that :math:`(\mathbf{v} \cdot \hat{\mathbf{n}}) \hat{\mathbf{n}}` is the -projection of the velocity vector onto the normal vector. By subtracting two -times this projection, the velocity is reflected with respect to the surface -normal. Since the magnitude of the velocity of the particle will not change as -it undergoes reflection, we can work with the direction of the particle instead, -simplifying equation :eq:`reflection-v` to - -.. math:: - :label: reflection-omega - - \mathbf{\Omega'} = \mathbf{\Omega} - 2 (\mathbf{\Omega} \cdot - \hat{\mathbf{n}}) \hat{\mathbf{n}} - -where :math:`\mathbf{v} = || \mathbf{v} || \mathbf{\Omega}`. The direction of -the surface normal will be the gradient of the surface at the point of crossing, -i.e. :math:`\mathbf{n} = \nabla f(x,y,z)`. Substituting this into equation -:eq:`reflection-omega`, we get - -.. math:: - :label: reflection-omega-2 - - \mathbf{\Omega'} = \mathbf{\Omega} - \frac{2 ( \mathbf{\Omega} \cdot \nabla - f )}{|| \nabla f ||^2} \nabla f - - -If we write the initial and final directions in terms of their vector -components, :math:`\mathbf{\Omega} = (u,v,w)` and :math:`\mathbf{\Omega'} = (u', -v', w')`, this allows us to represent equation :eq:`reflection-omega` as a -series of equations: - -.. math:: - :label: reflection-system - - u' = u - \frac{2 ( \mathbf{\Omega} \cdot \nabla f )}{|| \nabla f ||^2} - \frac{\partial f}{\partial x} \\ - - v' = v - \frac{2 ( \mathbf{\Omega} \cdot \nabla f )}{|| \nabla f ||^2} - \frac{\partial f}{\partial y} \\ - - w' = w - \frac{2 ( \mathbf{\Omega} \cdot \nabla f )}{|| \nabla f ||^2} - \frac{\partial f}{\partial z} - -One can then use equation :eq:`reflection-system` to develop equations for -transforming a particle's direction given the equation of the surface. - -Plane Perpendicular to an Axis ------------------------------- - -For a plane that is perpendicular to an axis, the rule for reflection is almost -so simple that no derivation is needed at all. Nevertheless, we will proceed -with the derivation to confirm that the rules of geometry agree with our -intuition. The gradient of the surface :math:`f(x,y,z) = x - x_0 = 0` is simply -:math:`\nabla f = (1, 0, 0)`. Note that this vector is already normalized, -i.e. :math:`|| \nabla f || = 1`. The second two equations in -:eq:`reflection-system` tell us that :math:`v` and :math:`w` do not change and -the first tell us that - -.. math:: - :label: reflection-xplane - - u' = u - 2u = -u - -We see that reflection for a plane perpendicular to an axis only entails -negating the directional cosine for that axis. - -Generic Plane -------------- - -A generic plane has the form :math:`f(x,y,z) = Ax + By + Cz - D = 0`. Thus, the -gradient to the surface is simply :math:`\nabla f = (A,B,C)` whose norm squared -is :math:`A^2 + B^2 + C^2`. This implies that - -.. math:: - :label: reflection-plane-constant - - \frac{2 (\mathbf{\Omega} \cdot \nabla f)}{|| \nabla f ||^2} = \frac{2(Au + - Bv + Cw)}{A^2 + B^2 + C^2} - -Substituting equation :eq:`reflection-plane-constant` into equation -:eq:`reflection-system` gives us the form of the solution. For example, the -x-component of the reflected direction will be - -.. math:: - :label: reflection-plane - - u' = u - \frac{2A(Au + Bv + Cw)}{A^2 + B^2 + C^2} - - -Cylinder Parallel to an Axis ----------------------------- - -A cylinder parallel to, for example, the x-axis has the form :math:`f(x,y,z) = -(y - y_0)^2 + (z - z_0)^2 - R^2 = 0`. Thus, the gradient to the surface is - -.. math:: - :label: reflection-cylinder-grad - - \nabla f = 2 \left ( \begin{array}{c} 0 \\ y - y_0 \\ z - z_0 \end{array} - \right ) = 2 \left ( \begin{array}{c} 0 \\ \bar{y} \\ \bar{z} \end{array} - \right ) - -where we have introduced the constants :math:`\bar{y}` and -:math:`\bar{z}`. Taking the square of the norm of the gradient, we find that - -.. math:: - :label: reflection-cylinder-norm - - || \nabla f ||^2 = 4 \bar{y}^2 + 4 \bar{z}^2 = 4 R^2 - -This implies that - -.. math:: - :label: reflection-cylinder-constant - - \frac{2 (\mathbf{\Omega} \cdot \nabla f)}{|| \nabla f ||^2} = - \frac{\bar{y}v + \bar{z}w}{R^2} - -Substituting equations :eq:`reflection-cylinder-constant` and -:eq:`reflection-cylinder-grad` into equation :eq:`reflection-system` gives us -the form of the solution. In this case, the x-component will not change. The y- -and z-components of the reflected direction will be - -.. math:: - :label: reflection-cylinder - - v' = v - \frac{2 ( \bar{y}v + \bar{z}w ) \bar{y}}{R^2} \\ - - w' = w - \frac{2 ( \bar{y}v + \bar{z}w ) \bar{z}}{R^2} - - -Sphere ------- - -The surface equation for a sphere has the form :math:`f(x,y,z) = (x - x_0)^2 + -(y - y_0)^2 + (z - z_0)^2 - R^2 = 0`. Thus, the gradient to the surface is - -.. math:: - :label: reflection-sphere-grad - - \nabla f = 2 \left ( \begin{array}{c} x - x_0 \\ y - y_0 \\ z - z_0 - \end{array} \right ) = 2 \left ( \begin{array}{c} \bar{x} \\ \bar{y} \\ - \bar{z} \end{array} \right ) - -where we have introduced the constants :math:`\bar{x}, \bar{y}, \bar{z}`. Taking -the square of the norm of the gradient, we find that - -.. math:: - :label: reflection-sphere-norm - - || \nabla f ||^2 = 4 \bar{x}^2 + 4 \bar{y}^2 + 4 \bar{z}^2 = 4 R^2 - -This implies that - -.. math:: - :label: reflection-sphere-constant - - \frac{2 (\mathbf{\Omega} \cdot \nabla f)}{|| \nabla f ||^2} = - \frac{\bar{x}u + \bar{y}v + \bar{z}w}{R^2} - -Substituting equations :eq:`reflection-sphere-constant` and -:eq:`reflection-sphere-grad` into equation :eq:`reflection-system` gives us the -form of the solution: - -.. math:: - :label: reflection-sphere - - u' = u - \frac{2 ( \bar{x}u + \bar{y}v + \bar{z}w ) \bar{x} }{R^2} \\ - - v' = v - \frac{2 ( \bar{x}u + \bar{y}v + \bar{z}w ) \bar{y} }{R^2} \\ - - w' = w - \frac{2 ( \bar{x}u + \bar{y}v + \bar{z}w ) \bar{z} }{R^2} - -Cone Parallel to an Axis ------------------------- - -A cone parallel to, for example, the z-axis has the form :math:`f(x,y,z) = (x - -x_0)^2 + (y - y_0)^2 - R^2(z - z_0)^2 = 0`. Thus, the gradient to the surface is - -.. math:: - :label: reflection-cone-grad - - \nabla f = 2 \left ( \begin{array}{c} x - x_0 \\ y - y_0 \\ -R^2(z - z_0) - \end{array} \right ) = 2 \left ( \begin{array}{c} \bar{x} \\ \bar{y} \\ - -R^2\bar{z} \end{array} \right ) - -where we have introduced the constants :math:`\bar{x}`, :math:`\bar{y}`, and -:math:`\bar{z}`. Taking the square of the norm of the gradient, we find that - -.. math:: - :label: reflection-cone-norm - - || \nabla f ||^2 = 4 \bar{x}^2 + \bar{y}^2 + 4 R^4 \bar{z}^2 \\ = 4 R^2 - \bar{z}^2 + 4 R^4 \bar{z}^2 \\ = 4 R^2 (1 + R^2) \bar{z}^2 - -This implies that - -.. math:: - :label: reflection-cone-constant - - \frac{2 (\mathbf{\Omega} \cdot \nabla f)}{|| \nabla f ||^2} = - \frac{\bar{x}u + \bar{y}v - R^2\bar{z}w}{R^2 (1 + R^2) \bar{z}^2} - -Substituting equations :eq:`reflection-cone-constant` and -:eq:`reflection-cone-grad` into equation :eq:`reflection-system` gives us the -form of the solution: - -.. math:: - :label: reflection-cone - - u' = u - \frac{2 (\bar{x}u + \bar{y}v - R^2\bar{z}w) \bar{x}}{R^2 (1 + R^2) - \bar{z}^2} - - v' = v - \frac{2 (\bar{x}u + \bar{y}v - R^2\bar{z}w) \bar{y}}{R^2 (1 + R^2) - \bar{z}^2} - - w' = w + \frac{2 (\bar{x}u + \bar{y}v - R^2\bar{z}w)}{R^2 (1 + R^2) \bar{z}} - -General Quadric ---------------- - -A general quadric surface has the form :math:`f(x,y,z) = Ax^2 + By^2 + Cz^2 + -Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0`. Thus, the gradient to the surface is - -.. math:: - :label: reflection-quadric-grad - - \nabla f = \left ( \begin{array}{c} 2Ax + Dy + Fz + G \\ 2By + Dx + Ez + H - \\ 2Cz + Ey + Fx + J \end{array} \right ). - - -.. _white: - -------------------------- -White Boundary Conditions -------------------------- - -The `white boundary condition `_ -is usually applied in deterministic codes, where the particle will hit the -surface and travel back with isotropic angular distribution. The change in -particle's direction is sampled from a cosine distribution instead of uniform. -Figure :num:`fig-cosine-dist` shows an example of cosine-distribution reflection -on the arbitrary surface relative to the surface normal. - -.. _fig-cosine-dist: - -.. figure:: ../_images/cosine-dist.png - :align: center - :figclass: align-center - - Cosine-distribution reflection on an arbitrary surface. - -The probability density function (pdf) for the reflected direction can be -expressed as follows, - -.. math:: - :label: white-reflection-pdf - - f(\mu, \phi) d\mu d\phi = \frac{\mu}{\pi} d\mu d\phi = 2\mu d\mu \frac{d\phi}{2\pi} - -where :math:`\mu = \cos \theta` is the cosine of the polar angle between -reflected direction and the normal to the surface; and :math:`\theta` is the -azimuthal angle in :math:`[0,2\pi]`. We can separate the multivariate -probability density into two separate univariate density functions, one for -the cosine of the polar angle, - -.. math:: - :label: white-reflection-cosine - - f(\mu) = 2\mu - -and one for the azimuthal angle, - -.. math:: - :label: white-reflection-uniform - - f(\phi) = \frac{1}{2\pi}. - -Each of these density functions can be sampled by analytical inversion of the -cumulative distribution distribution, resulting in the following sampling -scheme: - -.. math:: - :label: white-reflection-sqrt-prn - - \mu = \sqrt{\xi_1} \\ - \phi = 2\pi\xi_2 - -where :math:`\xi_1` and :math:`\xi_2` are uniform random numbers on -:math:`[0,1)`. With the sampled values of :math:`\mu` and :math:`\phi`, the -final reflected direction vector can be computed via rotation of the surface -normal using the equations from :ref:`transform-coordinates`. The white boundary -condition can be applied to any kind of surface, as long as the normal to the -surface is known as in :ref:`reflection`. - -.. _constructive solid geometry: https://en.wikipedia.org/wiki/Constructive_solid_geometry -.. _surfaces: https://en.wikipedia.org/wiki/Surface -.. _MCNP: http://mcnp.lanl.gov -.. _Serpent: http://montecarlo.vtt.fi -.. _Monte Carlo Performance benchmark: https://github.com/mit-crpg/benchmarks/tree/master/mc-performance/openmc diff --git a/docs/source/methods/index.rst b/docs/source/methods/index.rst deleted file mode 100644 index 5eff6c50e..000000000 --- a/docs/source/methods/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _methods: - -====================== -Theory and Methodology -====================== - -.. toctree:: - :numbered: - :maxdepth: 3 - - introduction - geometry - cross_sections - random_numbers - neutron_physics - photon_physics - tallies - eigenvalue - parallelization - cmfd - energy_deposition diff --git a/docs/source/methods/introduction.rst b/docs/source/methods/introduction.rst deleted file mode 100644 index adb52c02e..000000000 --- a/docs/source/methods/introduction.rst +++ /dev/null @@ -1,147 +0,0 @@ -.. _methods_introduction: - -============ -Introduction -============ - -The physical process by which a population of particles evolves over time is -governed by a number of `probability distributions`_. For instance, given a -particle traveling through some material, there is a probability distribution -for the distance it will travel until its next collision (an exponential -distribution). Then, when it collides with a nucleus, there is an associated -probability of undergoing each possible reaction with that nucleus. While the -behavior of any single particle is unpredictable, the average behavior of a -large population of particles originating from the same source is well defined. - -If the probability distributions that govern the transport of a particle are -known, the process of single particles randomly streaming and colliding with -nuclei can be simulated directly with computers using a technique known as -`Monte Carlo`_ simulation. If enough particles are simulated this way, the -average behavior can be determined to within arbitrarily small statistical -error, a fact guaranteed by the `central limit theorem`_. To be more precise, -the central limit theorem tells us that the variance of the sample mean of some -physical parameter being estimated with Monte Carlo will be inversely -proportional to the number of realizations, i.e. the number of particles we -simulate: - -.. math:: - - \sigma^2 \propto \frac{1}{N}. - -where :math:`\sigma^2` is the variance of the sample mean and :math:`N` is the -number of realizations. - ------------------------- -Overview of Program Flow ------------------------- - -OpenMC performs a Monte Carlo simulation one particle at a time -- at no point -is more than one particle being tracked on a single program instance. Before any -particles are tracked, the problem must be initialized. This involves the -following steps: - - - Read input files and building data structures for the geometry, materials, - tallies, and other associated variables. - - - Initialize the pseudorandom number generator. - - - Read the contiuous-energy or multi-group cross section data specified in - the problem. - - - If using a special energy grid treatment such as a union energy grid or - lethargy bins, that must be initialized as well in a continuous-energy - problem. - - - In a multi-group problem, individual nuclide cross section information is - combined to produce material-specific cross section data. - - - In a fixed source problem, source sites are sampled from the specified - source. In an eigenvalue problem, source sites are sampled from some - initial source distribution or from a source file. The source sites - consist of coordinates, a direction, and an energy. - -Once initialization is complete, the actual transport simulation can -proceed. The life of a single particle will proceed as follows: - - 1. The particle's properties are initialized from a source site previously - sampled. - - 2. Based on the particle's coordinates, the current cell in which the particle - resides is determined. - - 3. The energy-dependent cross sections for the material that the particle is - currently in are determined. Note that this includes the total - cross section, which is not pre-calculated. - - 4. The distance to the nearest boundary of the particle's cell is determined - based on the bounding surfaces to the cell. - - 5. The distance to the next collision is sampled. If the total material - cross section is :math:`\Sigma_t`, this can be shown to be - - .. math:: - - d = -\frac{\ln \xi}{\Sigma_t} - - where :math:`\xi` is a `pseudorandom number`_ sampled from a uniform - distribution on :math:`[0,1)`. - - 6. If the distance to the nearest boundary is less than the distance to the next - collision, the particle is moved forward to this boundary. Then, the process - is repeated from step 2. If the distance to collision is closer than the - distance to the nearest boundary, then the particle will undergo a collision. - - 7. The material at the collision site may consist of multiple nuclides. First, - the nuclide with which the collision will happen is sampled based on the - total cross sections. If the total cross section of material :math:`i` is - :math:`\Sigma_{t,i}`, then the probability that any nuclide is sampled is - - .. math:: - - P(i) = \frac{\Sigma_{t,i}}{\Sigma_t}. - - Note that the above selection of collided nuclide only applies to - continuous-energy simulations as multi-group simulations use nuclide - data which has already been combined in to material-specific data. - - 8. Once the specific nuclide is sampled, the random samples a reaction for - that nuclide based on the microscopic cross sections. If the microscopic - cross section for some reaction :math:`x` is :math:`\sigma_x` and the total - microscopic cross section for the nuclide is :math:`\sigma_t`, then the - probability that reaction :math:`x` will occur is - - .. math:: - - P(x) = \frac{\sigma_x}{\sigma_t}. - - Since multi-group simulations use material-specific data, the above is - performed with those material multi-group cross sections (i.e., - macroscopic cross sections for the material) instead of microscopic - cross sections for the nuclide). - - 9. If the sampled reaction is elastic or inelastic scattering, the outgoing - energy and angle is sampled from the appropriate distribution. In - continuous-energy simulation, reactions of type :math:`(n,xn)` are treated - as scattering and any additional particles which may be created are added - to a secondary particle bank to be tracked later. In a multi-group - simulation, this secondary bank is not used but the particle weight is - increased accordingly. The original particle then continues from step 3. - If the reaction is absorption or fission, the particle dies and if - necessary, fission sites are created and stored in the fission bank. - -After all particles have been simulated, there are a few final tasks that must -be performed before the run is finished. This include the following: - - - With the accumulated sum and sum of squares for each tally, the sample mean - and its variance is calculated. - - - All tallies and other results are written to disk. - - - If requested, a source file is written to disk. - - - Dynamically-allocated memory should be freed. - -.. _probability distributions: https://en.wikipedia.org/wiki/Probability_distribution -.. _Monte Carlo: https://en.wikipedia.org/wiki/Monte_Carlo_method -.. _central limit theorem: https://en.wikipedia.org/wiki/Central_limit_theorem -.. _pseudorandom number: https://en.wikipedia.org/wiki/Pseudorandom_number_generator diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst deleted file mode 100644 index 384e79bdd..000000000 --- a/docs/source/methods/neutron_physics.rst +++ /dev/null @@ -1,1677 +0,0 @@ -.. _methods_neutron_physics: - -=============== -Neutron Physics -=============== - -There are limited differences between physics treatments used in the -continuous-energy and multi-group modes. If distinctions are necessary, each -of the following sections will provide an explanation of the differences. -Otherwise, replacing any references of the particle's energy (`E`) with -references to the particle's energy group (`g`) will suffice. - ------------------------------------ -Sampling Distance to Next Collision ------------------------------------ - -As a particle travels through a homogeneous material, the probability -distribution function for the distance to its next collision :math:`\ell` is - -.. math:: - :label: distance-pdf - - p(\ell) d\ell = \Sigma_t e^{-\Sigma_t \ell} d\ell - -where :math:`\Sigma_t` is the total macroscopic cross section of the -material. Equation :eq:`distance-pdf` tells us that the further the distance is -to the next collision, the less likely the particle will travel that -distance. In order to sample the probability distribution function, we first -need to convert it to a cumulative distribution function - -.. math:: - :label: distance-cdf - - \int_0^{\ell} d\ell' p(\ell') = \int_0^{\ell} d\ell' \Sigma_t e^{-\Sigma_t - \ell'} = 1 - e^{-\Sigma_t \ell}. - -By setting the cumulative distribution function equal to :math:`\xi`, a random -number on the unit interval, and solving for the distance :math:`\ell`, we -obtain a formula for sampling the distance to next collision: - -.. math:: - :label: sample-distance-1 - - \ell = -\frac{\ln (1 - \xi)}{\Sigma_t}. - -Since :math:`\xi` is uniformly distributed on :math:`[0,1)`, this implies that -:math:`1 - \xi` is also uniformly distributed on :math:`[0,1)` as well. Thus, -the formula usually used to calculate the distance to next collision is - -.. math:: - :label: sample-distance-2 - - \ell = -\frac{\ln \xi}{\Sigma_t} - ----------------------------------------------------- -:math:`(n,\gamma)` and Other Disappearance Reactions ----------------------------------------------------- - -All absorption reactions other than fission do not produce any secondary -neutrons. As a result, these are the easiest type of reactions to handle. When a -collision occurs, the first step is to sample a nuclide within a material. Once -the nuclide has been sampled, then a specific reaction for that nuclide is -sampled. Since the total absorption cross section is pre-calculated at the -beginning of a simulation, the first step in sampling a reaction is to determine -whether a "disappearance" reaction occurs where no secondary neutrons are -produced. This is done by sampling a random number :math:`\xi` on the interval -:math:`[0,1)` and checking whether - -.. math:: - :label: disappearance - - \xi \sigma_t (E) < \sigma_a (E) - \sigma_f (E) - -where :math:`\sigma_t` is the total cross section, :math:`\sigma_a` is the -absorption cross section (this includes fission), and :math:`\sigma_f` is the -total fission cross section. If this condition is met, then the neutron is -killed and we proceed to simulate the next neutron from the source bank. - -No secondary particles from disappearance reactions such as photons or -alpha-particles are produced or tracked. To truly capture the affects of gamma -heating in a problem, it would be necessary to explicitly track photons -originating from :math:`(n,\gamma)` and other reactions. - ------------------- -Elastic Scattering ------------------- - -Note that the multi-group mode makes no distinction between elastic or -inelastic scattering reactions. The specific multi-group scattering -implementation is discussed in the :ref:`multi-group-scatter` section. - -Elastic scattering refers to the process by which a neutron scatters off a -nucleus and does not leave it in an excited. It is referred to as "elastic" -because in the center-of-mass system, the neutron does not actually lose -energy. However, in lab coordinates, the neutron does indeed lose -energy. Elastic scattering can be treated exactly in a Monte Carlo code thanks -to its simplicity. - -Let us discuss how OpenMC handles two-body elastic scattering kinematics. The -first step is to determine whether the target nucleus has any associated -motion. Above a certain energy threshold (400 kT by default), all scattering is -assumed to take place with the target at rest. Below this threshold though, we -must account for the thermal motion of the target nucleus. Methods to sample the -velocity of the target nucleus are described later in section -:ref:`freegas`. For the time being, let us assume that we have sampled the -target velocity :math:`\mathbf{v}_t`. The velocity of the center-of-mass system -is calculated as - -.. math:: - :label: velocity-com - - \mathbf{v}_{cm} = \frac{\mathbf{v}_n + A \mathbf{v}_t}{A + 1} - -where :math:`\mathbf{v}_n` is the velocity of the neutron and :math:`A` is the -atomic mass of the target nucleus measured in neutron masses (commonly referred -to as the *atomic weight ratio*). With the velocity of the center-of-mass -calculated, we can then determine the neutron's velocity in the center-of-mass -system: - -.. math:: - :label: velocity-neutron-com - - \mathbf{V}_n = \mathbf{v}_n - \mathbf{v}_{cm} - -where we have used uppercase :math:`\mathbf{V}` to denote the center-of-mass -system. The direction of the neutron in the center-of-mass system is - -.. math:: - :label: angle-neutron-com - - \mathbf{\Omega}_n = \frac{\mathbf{V}_n}{|| \mathbf{V}_n ||}. - -At low energies, elastic scattering will be isotropic in the center-of-mass -system, but for higher energies, there may be p-wave and higher order scattering -that leads to anisotropic scattering. Thus, in general, we need to sample a -cosine of the scattering angle which we will refer to as :math:`\mu`. For -elastic scattering, the secondary angle distribution is always given in the -center-of-mass system and is sampled according to the procedure outlined in -:ref:`sample-angle`. After the cosine of the angle of scattering has been -sampled, we need to determine the neutron's new direction -:math:`\mathbf{\Omega}'_n` in the center-of-mass system. This is done with the -procedure in :ref:`transform-coordinates`. The new direction is multiplied by -the speed of the neutron in the center-of-mass system to obtain the new velocity -vector in the center-of-mass: - -.. math:: - :label: velocity-neutron-com-2 - - \mathbf{V}'_n = || \mathbf{V}_n || \mathbf{\Omega}'_n. - -Finally, we transform the velocity in the center-of-mass system back to lab -coordinates: - -.. math:: - :label: velocity-neutron-lab - - \mathbf{v}'_n = \mathbf{V}'_n + \mathbf{v}_{cm} - -In OpenMC, the angle and energy of the neutron are stored rather than the -velocity vector itself, so the post-collision angle and energy can be inferred -from the post-collision velocity of the neutron in the lab system. - -For tallies that require the scattering cosine, it is important to store the -scattering cosine in the lab system. If we know the scattering cosine in the -center-of-mass, the scattering cosine in the lab system can be calculated as - -.. math:: - :label: cosine-lab - - \mu_{lab} = \frac{1 + A\mu}{\sqrt{A^2 + 2A\mu + 1}}. - -However, equation :eq:`cosine-lab` is only valid if the target was at rest. When -the target nucleus does have thermal motion, the cosine of the scattering angle -can be determined by simply taking the dot product of the neutron's initial and -final direction in the lab system. - -.. _inelastic-scatter: - --------------------- -Inelastic Scattering --------------------- - -Note that the multi-group mode makes no distinction between elastic or -inelastic scattering reactions. The spceific multi-group scattering -implementation is discussed in the :ref:`multi-group-scatter` section. - -The major algorithms for inelastic scattering were described in previous -sections. First, a scattering cosine is sampled using the algorithms in -:ref:`sample-angle`. Then an outgoing energy is sampled using the algorithms in -:ref:`sample-energy`. If the outgoing energy and scattering cosine were given in -the center-of-mass system, they are transformed to laboratory coordinates using -the algorithm described in :ref:`transform-coordinates`. Finally, the direction -of the particle is changed also using the procedure in -:ref:`transform-coordinates`. - -Although inelastic scattering leaves the target nucleus in an excited state, no -secondary photons from nuclear de-excitation are tracked in OpenMC. - ------------------------- -:math:`(n,xn)` Reactions ------------------------- - -Note that the multi-group mode makes no distinction between elastic or -inelastic scattering reactions. The specific multi-group scattering -implementation is discussed in the :ref:`multi-group-scatter` section. - -These types of reactions are just treated as inelastic scattering and as such -are subject to the same procedure as described in :ref:`inelastic-scatter`. For -reactions with integral multiplicity, e.g., :math:`(n,2n)`, an appropriate -number of secondary neutrons are created. For reactions that have a multiplicity -given as a function of the incoming neutron energy (which occasionally occurs -for MT=5), the weight of the outgoing neutron is multiplied by the multiplicity. - -.. _multi-group-scatter: - ----------------------- -Multi-Group Scattering ----------------------- - -In multi-group mode, a scattering collision requires that the outgoing energy -group of the simulated particle be selected from a probability distribution, -the change-in-angle selected from a probability distribution according to -the outgoing energy group, and finally the particle's weight adjusted again -according to the outgoing energy group. - -The first step in selecting an outgoing energy group for a particle in a given -incoming energy group is to select a random number (:math:`\xi`) between 0 and -1. This number is then compared to the cumulative distribution function -produced from the outgoing group (`g'`) data for the given incoming group (`g`): - -.. math:: - CDF = \sum_{g'=1}^{h}\Sigma_{s,g \rightarrow g'} - -If the scattering data is represented as a Legendre expansion, then the -value of :math:`\Sigma_{s,g \rightarrow g'}` above is the 0th order for the -given group transfer. If the data is provided as tabular or histogram data, then -:math:`\Sigma_{s,g \rightarrow g'}` is the sum of all bins of data for a given -`g` and `g'` pair. - -Now that the outgoing energy is known the change-in-angle, :math:`\mu` can be -determined. If the data is provided as a Legendre expansion, this is done by -rejection sampling of the probability distribution represented by the Legendre -series. For efficiency, the selected values of the PDF (:math:`f(\mu)`) are -chosen to be between 0 and the maximum value of :math:`f(\mu)` in the domain of --1 to 1. Note that this sampling scheme automatically forces negative values of -the :math:`f(\mu)` probability distribution function to be treated as zero -probabilities. - -If the angular data is instead provided as a tabular representation, then the -value of :math:`\mu` is selected as described in the :ref:`angle-tabular` -section with a linear-linear interpolation scheme. - -If the angular data is provided as a histogram representation, then -the value of :math:`\mu` is selected in a similar fashion to that described for -the selection of the outgoing energy (since the energy group representation is -simply a histogram representation) except the CDF is composed of the angular -bins and not the energy groups. However, since we are interested in a specific -value of :math:`\mu` instead of a group, then an angle is selected from a uniform -distribution within from the chosen angular bin. - -The final step in the scattering treatment is to adjust the weight of the -neutron to account for any production of neutrons due to :math:`(n,xn)` -reactions. This data is obtained from the multiplicity data provided in the -multi-group cross section library for the material of interest. -The scaled value will default to 1.0 if no value is provided in the library. - -.. _fission: - -------- -Fission -------- - -While fission is normally considered an absorption reaction, as far as it -concerns a Monte Carlo simulation it actually bears more similarities to -inelastic scattering since fission results in secondary neutrons in the exit -channel. Other absorption reactions like :math:`(n,\gamma)` or -:math:`(n,\alpha)`, on the contrary, produce no neutrons. There are a few other -idiosyncrasies in treating fission. In an eigenvalue calculation, secondary -neutrons from fission are only "banked" for use in the next generation rather -than being tracked as secondary neutrons from elastic and inelastic scattering -would be. On top of this, fission is sometimes broken into first-chance fission, -second-chance fission, etc. The nuclear data file either lists the partial -fission reactions with secondary energy distributions for each one, or a total -fission reaction with a single secondary energy distribution. - -When a fission reaction is sampled in OpenMC (either total fission or, if data -exists, first- or second-chance fission), the following algorithm is used to -create and store fission sites for the following generation. First, the average -number of prompt and delayed neutrons must be determined to decide whether the -secondary neutrons will be prompt or delayed. This is important because delayed -neutrons have a markedly different spectrum from prompt neutrons, one that has a -lower average energy of emission. The total number of neutrons emitted -:math:`\nu_t` is given as a function of incident energy in the ENDF format. Two -representations exist for :math:`\nu_t`. The first is a polynomial of order -:math:`N` with coefficients :math:`c_0,c_1,\dots,c_N`. If :math:`\nu_t` has this -format, we can evaluate it at incoming energy :math:`E` by using the equation - -.. math:: - :label: nu-polynomial - - \nu_t (E) = \sum_{i = 0}^N c_i E^i. - -The other representation is just a tabulated function with a specified -interpolation law. The number of prompt neutrons released per fission event -:math:`\nu_p` is also given as a function of incident energy and can be -specified in a polynomial or tabular format. The number of delayed neutrons -released per fission event :math:`\nu_d` can only be specified in a tabular -format. In practice, we only need to determine :math:`nu_t` and -:math:`nu_d`. Once these have been determined, we can calculated the delayed -neutron fraction - -.. math:: - :label: beta - - \beta = \frac{\nu_d}{\nu_t}. - -We then need to determine how many total neutrons should be emitted from -fission. If no survival biasing is being used, then the number of neutrons -emitted is - -.. math:: - :label: fission-neutrons - - \nu = \frac{w \nu_t}{k_{eff}} - -where :math:`w` is the statistical weight and :math:`k_{eff}` is the effective -multiplication factor from the previous generation. The number of neutrons -produced is biased in this manner so that the expected number of fission -neutrons produced is the number of source particles that we started with in the -generation. Since :math:`\nu` is not an integer, we use the following procedure -to obtain an integral number of fission neutrons to produce. If :math:`\xi > -\nu - \lfloor \nu \rfloor`, then we produce :math:`\lfloor \nu \rfloor` -neutrons. Otherwise, we produce :math:`\lfloor \nu \rfloor + 1` neutrons. Then, -for each fission site produced, we sample the outgoing angle and energy -according to the algorithms given in :ref:`sample-angle` and -:ref:`sample-energy` respectively. If the neutron is to be born delayed, then -there is an extra step of sampling a delayed neutron precursor group since they -each have an associated secondary energy distribution. - -The sampled outgoing angle and energy of fission neutrons along with the -position of the collision site are stored in an array called the fission -bank. In a subsequent generation, these fission bank sites are used as starting -source sites. - -The above description is similar for the multi-group mode except the data are -provided as group-wise data instead of in a continuous-energy format. In this -case, the outgoing energy of the fission neutrons are represented as histograms -by way of either the nu-fission matrix or chi vector. - ------------------------------------- -Secondary Angle-Energy Distributions ------------------------------------- - -Note that this section is specific to continuous-energy mode since the -multi-group scattering process has already been described including the -secondary energy and angle sampling. - -For a reaction with secondary products, it is necessary to determine the -outgoing angle and energy of the products. For any reaction other than elastic -and level inelastic scattering, the outgoing energy must be determined based on -tabulated or parameterized data. The `ENDF-6 Format`_ specifies a variety of -ways that the secondary energy distribution can be represented. ENDF File 5 -contains uncorrelated energy distribution whereas ENDF File 6 contains -correlated energy-angle distributions. The ACE format specifies its own -representations based loosely on the formats given in ENDF-6. OpenMC's HDF5 -nuclear data files use a combination of ENDF and ACE distributions; in this -section, we will describe how the outgoing angle and energy of secondary -particles are sampled. - -One of the subtleties in the nuclear data format is the fact that a single -reaction product can have multiple angle-energy distributions. This is mainly -useful for reactions with multiple products of the same type in the exit channel -such as :math:`(n,2n)` or :math:`(n,3n)`. In these types of reactions, each -neutron is emitted corresponding to a different excitation level of the compound -nucleus, and thus in general the neutrons will originate from different energy -distributions. If multiple angle-energy distributions are present, they are -assigned incoming-energy-dependent probabilities that can then be used to -randomly select one. - -Once a distribution has been selected, the procedure for determining the -outgoing angle and energy will depend on the type of the distribution. - -Uncorrelated Angle-Energy Distributions ---------------------------------------- - -The first set of distributions we will look at are uncorrelated angle-energy -distributions, where angle and energy are specified separately. For these -distributions, OpenMC first samples the angular distribution as described -:ref:`sample-angle` and then samples an energy as described in -:ref:`sample-energy`. - -.. _sample-angle: - -Sampling Angular Distributions -++++++++++++++++++++++++++++++ - -For elastic scattering, it is only necessary to specific a secondary angle -distribution since the outgoing energy can be determined analytically. Other -reactions may also have separate secondary angle and secondary energy -distributions that are uncorrelated. In these cases, the secondary angle -distribution is represented as either - -- An isotropic angular distribution, -- A tabular distribution. - -Isotropic Angular Distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In the first case, no data is stored in the nuclear data file, and the cosine of -the scattering angle is simply calculated as - -.. math:: - :label: isotropic-angle - - \mu = 2\xi - 1 - -where :math:`\mu` is the cosine of the scattering angle and :math:`\xi` is a -random number sampled uniformly on :math:`[0,1)`. - -.. _angle-tabular: - -Tabular Angular Distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this case, we have a table of cosines and their corresponding values for a -probability distribution function and cumulative distribution function. For each -incoming neutron energy :math:`E_i`, let us call :math:`p_{i,j}` the j-th value -in the probability distribution function and :math:`c_{i,j}` the j-th value in -the cumulative distribution function. We first find the interpolation factor on -the incoming energy grid: - -.. math:: - :label: interpolation-factor - - f = \frac{E - E_i}{E_{i+1} - E_i} - -where :math:`E` is the incoming energy of the particle. Then, statistical -interpolation is performed to choose between using the cosines and distribution -functions corresponding to energy :math:`E_i` and :math:`E_{i+1}`. Let -:math:`\ell` be the chosen table where :math:`\ell = i` if :math:`\xi_1 > f` and -:math:`\ell = i + 1` otherwise, where :math:`\xi_1` is a random number. Another -random number :math:`\xi_2` is used to sample a scattering cosine bin :math:`j` -using the cumulative distribution function: - -.. math:: - :label: sample-cdf - - c_{\ell,j} < \xi_2 < c_{\ell,j+1} - -The final scattering cosine will depend on whether histogram or linear-linear -interpolation is used. In general, we can write the cumulative distribution -function as - -.. math:: - :label: cdf - - c(\mu) = \int_{-1}^\mu p(\mu') d\mu' - -where :math:`c(\mu)` is the cumulative distribution function and :math:`p(\mu)` -is the probability distribution function. Since we know that -:math:`c(\mu_{\ell,j}) = c_{\ell,j}`, this implies that for :math:`\mu > -\mu_{\ell,j}`, - -.. math:: - :label: cdf-2 - - c(\mu) = c_{\ell,j} + \int_{\mu_{\ell,j}}^{\mu} p(\mu') d\mu' - -For histogram interpolation, we have that :math:`p(\mu') = p_{\ell,j}` for -:math:`\mu_{\ell,j} \le \mu' < \mu_{\ell,j+1}`. Thus, after integrating -:eq:`cdf-2` we have that - -.. math:: - :label: cumulative-dist-histogram - - c(\mu) = c_{\ell,j} + (\mu - \mu_{\ell,j}) p_{\ell,j} = \xi_2 - -Solving for the scattering cosine, we obtain the final form for histogram -interpolation: - -.. math:: - :label: cosine-histogram - - \mu = \mu_{\ell,j} + \frac{\xi_2 - c_{\ell,j}}{p_{\ell,j}}. - -For linear-linear interpolation, we represent the function :math:`p(\mu')` as a -first-order polynomial in :math:`\mu'`. If we interpolate between successive -values on the probability distribution function, we know that - -.. math:: - :label: pdf-interpolation - - p(\mu') - p_{\ell,j} = \frac{p_{\ell,j+1} - p_{\ell,j}}{\mu_{\ell,j+1} - - \mu_{\ell,j}} (\mu' - \mu_{\ell,j}) - -Solving for :math:`p(\mu')` in equation :eq:`pdf-interpolation` and inserting it -into equation :eq:`cdf-2`, we obtain - -.. math:: - :label: cdf-linlin - - c(\mu) = c_{\ell,j} + \int_{\mu_{\ell,j}}^{\mu} \left [ \frac{p_{\ell,j+1} - - p_{\ell,j}}{\mu_{\ell,j+1} - \mu_{\ell,j}} (\mu' - \mu_{\ell,j}) + - p_{\ell,j} \right ] d\mu'. - -Let us now make a change of variables using - -.. math:: - :label: introduce-eta - - \eta = \frac{p_{\ell,j+1} - p_{\ell,j}}{\mu_{\ell,j+1} - \mu_{\ell,j}} - (\mu' - \mu_{\ell,j}) + p_{\ell,j}. - -Equation :eq:`cdf-linlin` then becomes - -.. math:: - :label: cdf-linlin-eta - - c(\mu) = c_{\ell,j} + \frac{1}{m} \int_{p_{\ell,j}}^{m(\mu - \mu_{\ell,j}) + - p_{\ell,j}} \eta \, d\eta - -where we have used - -.. math:: - :label: slope - - m = \frac{p_{\ell,j+1} - p_{\ell,j}}{\mu_{\ell,j+1} - \mu_{\ell,j}}. - -Integrating equation :eq:`cdf-linlin-eta`, we have - -.. math:: - :label: cdf-linlin-integrated - - c(\mu) = c_{\ell,j} + \frac{1}{2m} \left ( \left [ m (\mu - \mu_{\ell,j} ) + - p_{\ell,j} \right ]^2 - p_{\ell,j}^2 \right ) = \xi_2 - -Solving for :math:`\mu`, we have the final form for the scattering cosine using -linear-linear interpolation: - -.. math:: - :label: cosine-linlin - - \mu = \mu_{\ell,j} + \frac{1}{m} \left ( \sqrt{p_{\ell,j}^2 + 2 m (\xi_2 - - c_{\ell,j} )} - p_{\ell,j} \right ) - -.. _sample-energy: - -Sampling Energy Distributions -+++++++++++++++++++++++++++++ - -Inelastic Level Scattering -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It can be shown (see Foderaro_) that in inelastic level scattering, the outgoing -energy of the neutron :math:`E'` can be related to the Q-value of the reaction -and the incoming energy: - -.. math:: - :label: level-scattering - - E' = \left ( \frac{A}{A+1} \right )^2 \left ( E - \frac{A + 1}{A} Q \right ) - -where :math:`A` is the mass of the target nucleus measured in neutron masses. - -.. _continuous-tabular: - -Continuous Tabular Distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In a continuous tabular distribution, a tabulated energy distribution is -provided for each of a set of incoming energies. While the representation itself -is simple, the complexity lies in how one interpolates between incident as well -as outgoing energies on such a table. If one performs simple interpolation -between tables for neighboring incident energies, it is possible that the -resulting energies would violate laws governing the kinematics, i.e., the -outgoing energy may be outside the range of available energy in the reaction. - -To avoid this situation, the accepted practice is to use a process known as -`scaled interpolation`_. First, we find the tabulated incident energies which -bound the actual incoming energy of the particle, i.e., find :math:`i` such that -:math:`E_i < E < E_{i+1}` and calculate the interpolation factor :math:`f` via -:eq:`interpolation-factor`. Then, we interpolate between the minimum and maximum -energies of the outgoing energy distributions corresponding to :math:`E_i` and -:math:`E_{i+1}`: - -.. math:: - :label: continuous-minmax - - E_{min} = E_{i,1} + f ( E_{i+1,1} - E_{i,1} ) \\ - E_{max} = E_{i,M} + f ( E_{i+1,M} - E_{i,M} ) - -where :math:`E_{min}` and :math:`E_{max}` are the minimum and maximum outgoing -energies of a scaled distribution, :math:`E_{i,j}` is the j-th outgoing energy -corresponding to the incoming energy :math:`E_i`, and :math:`M` is the number of -outgoing energy bins. - -Next, statistical interpolation is performed to choose between using the -outgoing energy distributions corresponding to energy :math:`E_i` and -:math:`E_{i+1}`. Let :math:`\ell` be the chosen table where :math:`\ell = i` if -:math:`\xi_1 > f` and :math:`\ell = i + 1` otherwise, and :math:`\xi_1` is a -random number. For each incoming neutron energy :math:`E_i`, let us call -:math:`p_{i,j}` the j-th value in the probability distribution function, -:math:`c_{i,j}` the j-th value in the cumulative distribution function, and -:math:`E_{i,j}` the j-th outgoing energy. We then sample an outgoing energy bin -:math:`j` using the cumulative distribution function: - -.. math:: - :label: continuous-sample-cdf - - c_{\ell,j} < \xi_2 < c_{\ell,j+1} - -where :math:`\xi_2` is a random number sampled uniformly on :math:`[0,1)`. At -this point, we need to interpolate between the successive values on the outgoing -energy distribution using either histogram or linear-linear interpolation. The -formulas for these can be derived along the same lines as those found in -:ref:`angle-tabular`. For histogram interpolation, the interpolated outgoing -energy on the :math:`\ell`-th distribution is - -.. math:: - :label: energy-histogram - - \hat{E} = E_{\ell,j} + \frac{\xi_2 - c_{\ell,j}}{p_{\ell,j}}. - -If linear-linear interpolation is to be used, the outgoing energy on the -:math:`\ell`-th distribution is - -.. math:: - :label: energy-linlin - - \hat{E} = E_{\ell,j} + \frac{E_{\ell,j+1} - E_{\ell,j}}{p_{\ell,j+1} - - p_{\ell,j}} \left ( \sqrt{p_{\ell,j}^2 + 2 \frac{p_{\ell,j+1} - - p_{\ell,j}}{E_{\ell,j+1} - E_{\ell,j}} ( \xi_2 - c_{\ell,j} )} - p_{\ell,j} - \right ). - -Since this outgoing energy may violate reaction kinematics, we then scale it to -minimum and maximum energies calculated in equation :eq:`continuous-minmax` to -get the final outgoing energy: - -.. math:: - :label: continuous-eout - - E' = E_{min} + \frac{\hat{E} - E_{\ell,1}}{E_{\ell,M} - E_{\ell,1}} - (E_{max} - E_{min}) - -where :math:`E_{min}` and :math:`E_{max}` are defined the same as in equation -:eq:`continuous-minmax`. - -.. _maxwell: - -Maxwell Fission Spectrum -^^^^^^^^^^^^^^^^^^^^^^^^ - -One representation of the secondary energies for neutrons from fission is the -so-called Maxwell spectrum. A probability distribution for the Maxwell spectrum -can be written in the form - -.. math:: - :label: maxwell-spectrum - - p(E') dE' = c E'^{1/2} e^{-E'/T(E)} dE' - -where :math:`E` is the incoming energy of the neutron and :math:`T` is the -so-called nuclear temperature, which is a function of the incoming energy of the -neutron. The ENDF format contains a list of nuclear temperatures versus incoming -energies. The nuclear temperature is interpolated between neighboring incoming -energies using a specified interpolation law. Once the temperature :math:`T` is -determined, we then calculate a candidate outgoing energy based on rule C64 in -the `Monte Carlo Sampler`_: - -.. math:: - :label: maxwell-E-candidate - - E' = -T \left [ \log (\xi_1) + \log (\xi_2) \cos^2 \left ( \frac{\pi - \xi_3}{2} \right ) \right ] - -where :math:`\xi_1, \xi_2, \xi_3` are random numbers sampled on the unit -interval. The outgoing energy is only accepted if - -.. math:: - :label: maxwell-restriction - - 0 \le E' \le E - U - -where :math:`U` is called the restriction energy and is specified in the ENDF -data. If the outgoing energy is rejected, it is resampled using equation -:eq:`maxwell-E-candidate`. - -Evaporation Spectrum -^^^^^^^^^^^^^^^^^^^^ - -Evaporation spectra are primarily used in compound nucleus processes where a -secondary particle can "evaporate" from the compound nucleus if it has -sufficient energy. The probability distribution for an evaporation spectrum can -be written in the form - -.. math:: - :label: evaporation-spectrum - - p(E') dE' = c E' e^{-E'/T(E)} dE' - -where :math:`E` is the incoming energy of the neutron and :math:`T` is the -nuclear temperature, which is a function of the incoming energy of the -neutron. The ENDF format contains a list of nuclear temperatures versus incoming -energies. The nuclear temperature is interpolated between neighboring incoming -energies using a specified interpolation law. Once the temperature :math:`T` is -determined, we then calculate a candidate outgoing energy based on the algorithm -given in LA-UR-14-27694_: - -.. math:: - :label: evaporation-E - - E' = -T \log ((1 - g\xi_1)(1 - g\xi_2)) - -where :math:`g = 1 - e^{-w}`, :math:`w = (E - U)/T`, :math:`U` is the -restriction energy, and :math:`\xi_1, \xi_2` are random numbers sampled on the -unit interval. The outgoing energy is only accepted according to the restriction -energy as in equation :eq:`maxwell-restriction`. This algorithm has a much -higher rejection efficiency than the standard technique, i.e. rule C45 in the -`Monte Carlo Sampler`_. - -Energy-Dependent Watt Spectrum -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The probability distribution for a `Watt fission spectrum`_ can be written in -the form - -.. math:: - :label: watt-spectrum - - p(E') dE' = c e^{-E'/a(E)} \sinh \sqrt{b(E) \, E'} dE' - -where :math:`a` and :math:`b` are parameters for the distribution and are given -as tabulated functions of the incoming energy of the neutron. These two -parameters are interpolated on the incoming energy grid using a specified -interpolation law. Once the parameters have been determined, we sample a -Maxwellian spectrum with nuclear temperature :math:`a` using the algorithm -described in :ref:`maxwell` to get an energy :math:`W`. Then, the outgoing -energy is calculated as - -.. math:: - :label: watt-E - - E' = W + \frac{a^2 b}{4} + (2\xi - 1) \sqrt{a^2 b W} - -where :math:`\xi` is a random number sampled on the interval :math:`[0,1)`. The -outgoing energy is only accepted according to a specified restriction energy -:math:`U` as defined in equation :eq:`maxwell-restriction`. - -A derivation of the algorithm described here can be found in a paper by Romano_. - -Product Angle-Energy Distributions ----------------------------------- - -If the secondary distribution for a product was given in file 6 in ENDF, the -angle and energy are correlated with one another and cannot be sampled -separately. Several representations exist in ENDF/ACE for correlated -angle-energy distributions. - -Kalbach-Mann Correlated Scattering -++++++++++++++++++++++++++++++++++ - -This law is very similar to the uncorrelated continuous tabular energy -distribution except now the outgoing angle of the neutron is correlated to the -outgoing energy and is not sampled from a separate distribution. For each -incident neutron energy :math:`E_i` tabulated, there is an array of precompound -factors :math:`R_{i,j}` and angular distribution slopes :math:`A_{i,j}` -corresponding to each outgoing energy bin :math:`j` in addition to the outgoing -energies and distribution functions as in :ref:`continuous-tabular`. - -The calculation of the outgoing energy of the neutron proceeds exactly the same -as in the algorithm described in :ref:`continuous-tabular`. In that algorithm, -we found an interpolation factor :math:`f`, statistically sampled an incoming -energy bin :math:`\ell`, and sampled an outgoing energy bin :math:`j` based on -the tabulated cumulative distribution function. Once the outgoing energy has -been determined with equation :eq:`continuous-eout`, we then need to calculate -the outgoing angle based on the tabulated Kalbach-Mann parameters. These -parameters themselves are subject to either histogram or linear-linear -interpolation on the outgoing energy grid. For histogram interpolation, the -parameters are - -.. math:: - :label: KM-parameters-histogram - - R = R_{\ell,j} \\ - A = A_{\ell,j}. - -If linear-linear interpolation is specified, the parameters are - -.. math:: - :label: KM-parameters-linlin - - R = R_{\ell,j} + \frac{\hat{E} - E_{\ell,j}}{E_{\ell,j+1} - E_{\ell,j}} ( - R_{\ell,j+1} - R_{\ell,j} ) \\ - A = A_{\ell,j} + \frac{\hat{E} - E_{\ell,j}}{E_{\ell,j+1} - E_{\ell,j}} ( - A_{\ell,j+1} - A_{\ell,j} ) - -where :math:`\hat{E}` is defined in equation :eq:`energy-linlin`. With the -parameters determined, the probability distribution function for the cosine of -the scattering angle is - -.. math:: - :label: KM-pdf-angle - - p(\mu) d\mu = \frac{A}{2 \sinh (A)} \left [ \cosh (A\mu) + R \sinh (A\mu) - \right ] d\mu. - -The rules for sampling this probability distribution function can be derived -based on rules C39 and C40 in the `Monte Carlo Sampler`_. First, we sample two -random numbers :math:`\xi_3, \xi_4` on the unit interval. If :math:`\xi_3 > R` -then the outgoing angle is - -.. math:: - :label: KM-angle-1 - - \mu = \frac{1}{A} \ln \left ( T + \sqrt{T^2 + 1} \right ) - -where :math:`T = (2 \xi_4 - 1) \sinh (A)`. If :math:`\xi_3 \le R`, then the -outgoing angle is - -.. math:: - :label: KM-angle-2 - - \mu = \frac{1}{A} \ln \left ( \xi_4 e^A + (1 - \xi_4) e^{-A} \right ). - -.. _correlated-energy-angle: - -Correlated Energy and Angle Distribution -++++++++++++++++++++++++++++++++++++++++ - -This distribution is very similar to a Kalbach-Mann distribution in the sense -that the outgoing angle of the neutron is correlated to the outgoing energy and -is not sampled from a separate distribution. In this case though, rather than -being determined from an analytical distribution function, the cosine of the -scattering angle is determined from a tabulated distribution. For each incident -energy :math:`i` and outgoing energy :math:`j`, there is a tabulated angular -distribution. - -The calculation of the outgoing energy of the neutron proceeds exactly the same -as in the algorithm described in :ref:`continuous-tabular`. In that algorithm, -we found an interpolation factor :math:`f`, statistically sampled an incoming -energy bin :math:`\ell`, and sampled an outgoing energy bin :math:`j` based on -the tabulated cumulative distribution function. Once the outgoing energy has -been determined with equation :eq:`continuous-eout`, we then need to decide -which angular distribution to use. If histogram interpolation was used on the -outgoing energy bins, then we use the angular distribution corresponding to -incoming energy bin :math:`\ell` and outgoing energy bin :math:`j`. If -linear-linear interpolation was used on the outgoing energy bins, then we use -the whichever angular distribution was closer to the sampled value of the -cumulative distribution function for the outgoing energy. The actual algorithm -used to sample the chosen tabular angular distribution has been previously -described in :ref:`angle-tabular`. - -N-Body Phase Space Distribution -+++++++++++++++++++++++++++++++ - -Reactions in which there are more than two products of similar masses are -sometimes best treated by using what's known as an N-body phase -distribution. This distribution has the following probability density function -for outgoing energy and angle of the :math:`i`-th particle in the center-of-mass -system: - -.. math:: - :label: n-body-pdf - - p_i(\mu, E') dE' d\mu = C_n \sqrt{E'} (E_i^{max} - E')^{(3n/2) - 4} dE' d\mu - -where :math:`n` is the number of outgoing particles, :math:`C_n` is a -normalization constant, :math:`E_i^{max}` is the maximum center-of-mass energy -for particle :math:`i`, and :math:`E'` is the outgoing energy. We see in -equation :eq:`n-body-pdf` that the angle is simply isotropic in the -center-of-mass system. The algorithm for sampling the outgoing energy is based -on algorithms R28, C45, and C64 in the `Monte Carlo Sampler`_. First we -calculate the maximum energy in the center-of-mass using the following equation: - -.. math:: - :label: n-body-emax - - E_i^{max} = \frac{A_p - 1}{A_p} \left ( \frac{A}{A+1} E + Q \right ) - -where :math:`A_p` is the total mass of the outgoing particles in neutron masses, -:math:`A` is the mass of the original target nucleus in neutron masses, and -:math:`Q` is the Q-value of the reaction. Next we sample a value :math:`x` from -a Maxwell distribution with a nuclear temperature of one using the algorithm -outlined in :ref:`maxwell`. We then need to determine a value :math:`y` that -will depend on how many outgoing particles there are. For :math:`n = 3`, we -simply sample another Maxwell distribution with unity nuclear temperature. For -:math:`n = 4`, we use the equation - -.. math:: - :label: n-body-y4 - - y = -\ln ( \xi_1 \xi_2 \xi_3 ) - -where :math:`\xi_i` are random numbers sampled on the interval -:math:`[0,1)`. For :math:`n = 5`, we use the equation - -.. math:: - :label: n-body-y5 - - y = -\ln ( \xi_1 \xi_2 \xi_3 \xi_4 ) - \ln ( \xi_5 ) \cos^2 \left ( - \frac{\pi}{2} \xi_6 \right ) - -After :math:`x` and :math:`y` have been determined, the outgoing energy is then -calculated as - -.. math:: - :label: n-body-energy - - E' = \frac{x}{x + y} E_i^{max} - -There are two important notes to make regarding the N-body phase space -distribution. First, the documentation (and code) for MCNP5-1.60 has a mistake -in the algorithm for :math:`n = 4`. That being said, there are no existing -nuclear data evaluations which use an N-body phase space distribution with -:math:`n = 4`, so the error would not affect any calculations. In the -ENDF/B-VII.1 nuclear data evaluation, only one reaction uses an N-body phase -space distribution at all, the :math:`(n,2n)` reaction with H-2. - -.. _transform-coordinates: - -------------------------------------- -Transforming a Particle's Coordinates -------------------------------------- - -Since all the multi-group data exists in the laboratory frame of reference, this -section does not apply to the multi-group mode. - -Once the cosine of the scattering angle :math:`\mu` has been sampled either from -a angle distribution or a correlated angle-energy distribution, we are still -left with the task of transforming the particle's coordinates. If the outgoing -energy and scattering cosine were given in the center-of-mass system, then we -first need to transform these into the laboratory system. The relationship -between the outgoing energy in center-of-mass and laboratory is - -.. math:: - :label: energy-com-to-lab - - E' = E'_{cm} + \frac{E + 2\mu_{cm} (A + 1) \sqrt{EE'_{cm}}}{(A+1)^2}. - -where :math:`E'_{cm}` is the outgoing energy in the center-of-mass system, -:math:`\mu_{cm}` is the scattering cosine in the center-of-mass system, -:math:`E'` is the outgoing energy in the laboratory system, and :math:`E` is the -incident neutron energy. The relationship between the scattering cosine in -center-of-mass and laboratory is - -.. math:: - :label: angle-com-to-lab - - \mu = \mu_{cm} \sqrt{\frac{E'_{cm}}{E'}} + \frac{1}{A + 1} - \sqrt{\frac{E}{E'}} - -where :math:`\mu` is the scattering cosine in the laboratory system. The -scattering cosine still only tells us the cosine of the angle between the -original direction of the particle and the new direction of the particle. If we -express the pre-collision direction of the particle as :math:`\mathbf{\Omega} = -(u,v,w)` and the post-collision direction of the particle as -:math:`\mathbf{\Omega}' = (u',v',w')`, it is possible to relate the pre- and -post-collision components. We first need to uniformly sample an azimuthal angle -:math:`\phi` in :math:`[0, 2\pi)`. After the azimuthal angle has been sampled, -the post-collision direction is calculated as - -.. math:: - :label: post-collision-angle - - u' = \mu u + \frac{\sqrt{1 - \mu^2} ( uw \cos\phi - v \sin\phi )}{\sqrt{1 - - w^2}} \\ - - v' = \mu v + \frac{\sqrt{1 - \mu^2} ( vw \cos\phi + u \sin\phi )}{\sqrt{1 - - w^2}} \\ - - w' = \mu w - \sqrt{1 - \mu^2} \sqrt{1 - w^2} \cos\phi. - -.. _freegas: - ------------------------------------------- -Effect of Thermal Motion on Cross Sections ------------------------------------------- - -Since all the multi-group data should be generated with thermal scattering -treatments already, this section does not apply to the multi-group mode. - -When a neutron scatters off of a nucleus, it may often be assumed that the -target nucleus is at rest. However, the target nucleus will have motion -associated with its thermal vibration, even at absolute zero (This is due to the -zero-point energy arising from quantum mechanical considerations). Thus, the -velocity of the neutron relative to the target nucleus is in general not the -same as the velocity of the neutron entering the collision. - -The effect of the thermal motion on the interaction probability can be written -as - -.. math:: - :label: doppler-broaden - - v_n \bar{\sigma} (v_n, T) = \int d\mathbf{v}_T v_r \sigma(v_r) - M (\mathbf{v}_T) - -where :math:`v_n` is the magnitude of the velocity of the neutron, -:math:`\bar{\sigma}` is an effective cross section, :math:`T` is the temperature -of the target material, :math:`\mathbf{v}_T` is the velocity of the target -nucleus, :math:`v_r = || \mathbf{v}_n - \mathbf{v}_T ||` is the magnitude of the -relative velocity, :math:`\sigma` is the cross section at 0 K, and :math:`M -(\mathbf{v}_T)` is the probability distribution for the target nucleus velocity -at temperature :math:`T` (a Maxwellian). In a Monte Carlo code, one must account -for the effect of the thermal motion on both the integrated cross section as -well as secondary angle and energy distributions. For integrated cross sections, -it is possible to calculate thermally-averaged cross sections by applying a -kernel Doppler broadening algorithm to data at 0 K (or some temperature lower -than the desired temperature). The most ubiquitous algorithm for this purpose is -the `SIGMA1 method`_ developed by Red Cullen and subsequently refined by -others. This method is used in the NJOY_ and PREPRO_ data processing codes. - -The effect of thermal motion on secondary angle and energy distributions can be -accounted for on-the-fly in a Monte Carlo simulation. We must first qualify -where it is actually used however. All threshold reactions are treated as being -independent of temperature, and therefore they are not Doppler broadened in NJOY -and no special procedure is used to adjust the secondary angle and energy -distributions. The only non-threshold reactions with secondary neutrons are -elastic scattering and fission. For fission, it is assumed that the neutrons are -emitted isotropically (this is not strictly true, but is nevertheless a good -approximation). This leaves only elastic scattering that needs a special thermal -treatment for secondary distributions. - -Fortunately, it is possible to directly sample the velocity of the target -nuclide and then use it directly in the kinematic calculations. However, this -calculation is a bit more nuanced than it might seem at first glance. One might -be tempted to simply sample a Maxwellian distribution for the velocity of the -target nuclide. Careful inspection of equation :eq:`doppler-broaden` however -tells us that target velocities that produce relative velocities which -correspond to high cross sections will have a greater contribution to the -effective reaction rate. This is most important when the velocity of the -incoming neutron is close to a resonance. For example, if the neutron's velocity -corresponds to a trough in a resonance elastic scattering cross section, a very -small target velocity can cause the relative velocity to correspond to the peak -of the resonance, thus making a disproportionate contribution to the reaction -rate. The conclusion is that if we are to sample a target velocity in the Monte -Carlo code, it must be done in such a way that preserves the thermally-averaged -reaction rate as per equation :eq:`doppler-broaden`. - -The method by which most Monte Carlo codes sample the target velocity for use in -elastic scattering kinematics is outlined in detail by [Gelbard]_. The -derivation here largely follows that of Gelbard. Let us first write the reaction -rate as a function of the velocity of the target nucleus: - -.. math:: - :label: reaction-rate - - R(\mathbf{v}_T) = || \mathbf{v}_n - \mathbf{v}_T || \sigma ( || - \mathbf{v}_n - \mathbf{v}_T || ) M ( \mathbf{v}_T ) - -where :math:`R` is the reaction rate. Note that this is just the right-hand side -of equation :eq:`doppler-broaden`. Based on the discussion above, we want to -construct a probability distribution function for sampling the target velocity -to preserve the reaction rate -- this is different from the overall probability -distribution function for the target velocity, :math:`M ( \mathbf{v}_T )`. This -probability distribution function can be found by integrating equation -:eq:`reaction-rate` to obtain a normalization factor: - -.. math:: - :label: target-pdf-1 - - p( \mathbf{v}_T ) d\mathbf{v}_T = \frac{R(\mathbf{v}_T) d\mathbf{v}_T}{\int - d\mathbf{v}_T \, R(\mathbf{v}_T)} - -Let us call the normalization factor in the denominator of equation -:eq:`target-pdf-1` :math:`C`. - - -Constant Cross Section Model ----------------------------- - -It is often assumed that :math:`\sigma (v_r)` is constant over the range of -relative velocities of interest. This is a good assumption for almost all cases -since the elastic scattering cross section varies slowly with velocity for light -nuclei, and for heavy nuclei where large variations can occur due to resonance -scattering, the moderating effect is rather small. Nonetheless, this assumption -may cause incorrect answers in systems with low-lying resonances that can cause -a significant amount of up-scatter that would be ignored by this assumption -(e.g. U-238 in commercial light-water reactors). We will revisit this assumption -later in :ref:`energy_dependent_xs_model`. For now, continuing with the -assumption, we write :math:`\sigma (v_r) = \sigma_s` which simplifies -:eq:`target-pdf-1` to - -.. math:: - :label: target-pdf-2 - - p( \mathbf{v}_T ) d\mathbf{v}_T = \frac{\sigma_s}{C} || \mathbf{v}_n - - \mathbf{v}_T || M ( \mathbf{v}_T ) d\mathbf{v}_T - -The Maxwellian distribution in velocity is - -.. math:: - :label: maxwellian-velocity - - M (\mathbf{v}_T) = \left ( \frac{m}{2\pi kT} \right )^{3/2} \exp \left ( - \frac{-m || \mathbf{v}_T^2 ||}{2kT} \right ) - -where :math:`m` is the mass of the target nucleus and :math:`k` is Boltzmann's -constant. Notice here that the term in the exponential is dependent only on the -speed of the target, not on the actual direction. Thus, we can change the -Maxwellian into a distribution for speed rather than velocity. The differential -element of velocity is - -.. math:: - :label: differential-velocity - - d\mathbf{v}_T = v_T^2 dv_T d\mu d\phi - -Let us define the Maxwellian distribution in speed as - -.. math:: - :label: maxwellian-speed - - M (v_T) dv_T = \int_{-1}^1 d\mu \int_{0}^{2\pi} d\phi \, dv_T \, v_T^2 - M(\mathbf{v}_T) = \sqrt{ \frac{2}{\pi} \left ( \frac{m}{kT} \right )^3} - v_T^2 \exp \left ( \frac{-m v_T}{2kT} \right ) dv_T. - -To simplify things a bit, we'll define a parameter - -.. math:: - :label: maxwellian-beta - - \beta = \sqrt{\frac{m}{2kT}}. - -Substituting equation :eq:`maxwellian-beta` into equation -:eq:`maxwellian-speed`, we obtain - -.. math:: - :label: maxwellian-speed2 - - M (v_T) dv_T = \frac{4}{\sqrt{\pi}} \beta^3 v_T^2 \exp \left ( -\beta^2 - v_T^2 \right ) dv_T. - -Now, changing variables in equation :eq:`target-pdf-2` by using the result from -equation :eq:`maxwellian-speed`, our new probability distribution function is - -.. math:: - :label: target-pdf-3 - - p( v_T, \mu ) dv_T d\mu = \frac{4\sigma_s}{\sqrt{\pi}C'} || \mathbf{v}_n - - \mathbf{v}_T || \beta^3 v_T^2 \exp \left ( -\beta^2 v_T^2 \right ) dv_T d\mu - -Again, the Maxwellian distribution for the speed of the target nucleus has no -dependence on the angle between the neutron and target velocity vectors. Thus, -only the term :math:`|| \mathbf{v}_n - \mathbf{v}_T ||` imposes any constraint -on the allowed angle. Our last task is to take that term and write it in terms -of magnitudes of the velocity vectors and the angle rather than the vectors -themselves. We can establish this relation based on the law of cosines which -tells us that - -.. math:: - :label: lawcosine - - 2 v_n v_T \mu = v_n^2 + v_T^2 - v_r^2. - -Thus, we can infer that - -.. math:: - :label: change-terms - - || \mathbf{v}_n - \mathbf{v}_T || = || \mathbf{v}_r || = v_r = \sqrt{v_n^2 + - v_T^2 - 2v_n v_T \mu}. - -Inserting equation :eq:`change-terms` into :eq:`target-pdf-3`, we obtain - -.. math:: - :label: target-pdf-4 - - p( v_T, \mu ) dv_T d\mu = \frac{4\sigma_s}{\sqrt{\pi}C'} \sqrt{v_n^2 + - v_T^2 - 2v_n v_T \mu} \beta^3 v_T^2 \exp \left ( -\beta^2 v_T^2 \right ) - dv_T d\mu - -This expression is still quite formidable and does not lend itself to any -natural sampling scheme. We can divide this probability distribution into two -parts as such: - -.. math:: - :label: divide-pdf - - \begin{aligned} - p(v_T, \mu) &= f_1(v_T, \mu) f_2(v_T) \\ - f_1(v_T, \mu) &= \frac{4\sigma_s}{\sqrt{\pi} C'} \frac{ \sqrt{v_n^2 + - v_T^2 - 2v_n v_T \mu}}{v_n + v_T} \\ - f_2(v_T) &= (v_n + v_T) \beta^3 v_T^2 \exp \left ( -\beta^2 v_T^2 \right ). - \end{aligned} - -In general, any probability distribution function of the form :math:`p(x) = -f_1(x) f_2(x)` with :math:`f_1(x)` bounded can be sampled by sampling -:math:`x'` from the distribution - -.. math:: - :label: freegas-f2 - - q(x) dx = \frac{f_2(x) dx}{\int f_2(x) dx} - -and accepting it with probability - -.. math:: - :label: freegas-accept - - p_{accept} = \frac{f_1(x')}{\max f_1(x)} - -The reason for dividing and multiplying the terms by :math:`v_n + v_T` is to -ensure that the first term is bounded. In general, :math:`|| \mathbf{v}_n - -\mathbf{v}_T ||` can take on arbitrarily large values, but if we divide it by -its maximum value :math:`v_n + v_T`, then it ensures that the function will be -bounded. We now must come up with a sampling scheme for equation -:eq:`freegas-f2`. To determine :math:`q(v_T)`, we need to integrate :math:`f_2` -in equation :eq:`divide-pdf`. Doing so we find that - -.. math:: - :label: integrate-f2 - - \int_0^{\infty} dv_T (v_n + v_T) \beta^3 v_T^2 \exp \left ( -\beta^2 v_T^2 - \right ) = \frac{1}{4\beta} \left ( \sqrt{\pi} \beta v_n + 2 \right ). - -Thus, we need to sample the probability distribution function - -.. math:: - :label: freegas-f2-2 - - q(v_T) dv_T = \left ( \frac{4\beta^2 v_n v_T^2}{\sqrt{\pi} \beta v_n + 2} + - \frac{4\beta^4 v_T^3}{\sqrt{\pi} \beta v_n + 2} \right ) exp \left ( - -\beta^2 v_T^2 \right ). - -Now, let us do a change of variables with the following definitions - -.. math:: - :label: beta-to-x - - x = \beta v_T \\ - y = \beta v_n. - -Substituting equation :eq:`beta-to-x` into equation :eq:`freegas-f2-2` along -with :math:`dx = \beta dv_T` and doing some crafty rearranging of terms yields - -.. math:: - :label: freegas-f2-3 - - q(x) dx = \left [ \left ( \frac{\sqrt{\pi} y}{\sqrt{\pi} y + 2} \right ) - \frac{4}{\sqrt{\pi}} x^2 e^{-x^2} + \left ( \frac{2}{\sqrt{\pi} y + 2} - \right ) 2x^3 e^{-x^2} \right ] dx. - -It's important to make note of the following two facts. First, the terms outside -the parentheses are properly normalized probability distribution functions that -can be sampled directly. Secondly, the terms inside the parentheses are always -less than unity. Thus, the sampling scheme for :math:`q(x)` is as follows. We -sample a random number :math:`\xi_1` on the interval :math:`[0,1)` and if - -.. math:: - :label: freegas-alpha - - \xi_1 < \frac{2}{\sqrt{\pi} y + 2} - -then we sample the probability distribution :math:`2x^3 e^{-x^2}` for :math:`x` -using rule C49 in the `Monte Carlo Sampler`_ which we can then use to determine -the speed of the target nucleus :math:`v_T` from equation -:eq:`beta-to-x`. Otherwise, we sample the probability distribution -:math:`\frac{4}{\sqrt{\pi}} x^2 e^{-x^2}` for :math:`x` using rule C61 in the -`Monte Carlo Sampler`_. - -With a target speed sampled, we must then decide whether to accept it based on -the probability in equation :eq:`freegas-accept`. The cosine can be sampled -isotropically as :math:`\mu = 2\xi_2 - 1` where :math:`\xi_2` is a random number -on the unit interval. Since the maximum value of :math:`f_1(v_T, \mu)` is -:math:`4\sigma_s / \sqrt{\pi} C'`, we then sample another random number -:math:`\xi_3` and accept the sampled target speed and cosine if - -.. math:: - :label: freegas-accept-2 - - \xi_3 < \frac{\sqrt{v_n^2 + v_T^2 - 2 v_n v_T \mu}}{v_n + v_T}. - -If is not accepted, then we repeat the process and resample a target speed and -cosine until a combination is found that satisfies equation -:eq:`freegas-accept-2`. - -.. _energy_dependent_xs_model: - -Energy-Dependent Cross Section Model ------------------------------------- - -As was noted earlier, assuming that the elastic scattering cross section is -constant in :eq:`reaction-rate` is not strictly correct, especially when -low-lying resonances are present in the cross sections for heavy nuclides. To -correctly account for energy dependence of the scattering cross section entails -performing another rejection step. The most common method is to sample -:math:`\mu` and :math:`v_T` as in the constant cross section approximation and -then perform a rejection on the ratio of the 0 K elastic scattering cross -section at the relative velocity to the maximum 0 K elastic scattering cross -section over the range of velocities considered: - -.. math:: - :label: dbrc - - p_{dbrc} = \frac{\sigma_s(v_r)}{\sigma_{s,max}} - -where it should be noted that the maximum is taken over the range :math:`[v_n - -4/\beta, 4_n + 4\beta]`. This method is known as Doppler broadening rejection -correction (DBRC) and was first introduced by `Becker et al.`_. OpenMC has an -implementation of DBRC as well as an accelerated sampling method that samples the `relative velocity`_ directly. - -.. _Becker et al.: https://doi.org/10.1016/j.anucene.2008.12.001 -.. _relative velocity: https://doi.org/10.1016/j.anucene.2017.12.044 - -.. _sab_tables: - ------------- -|sab| Tables ------------- - -Note that |sab| tables are only applicable to continuous-energy transport. - -For neutrons with thermal energies, generally less than 4 eV, the kinematics of -scattering can be affected by chemical binding and crystalline effects of the -target molecule. If these effects are not accounted for in a simulation, the -reported results may be highly inaccurate. There is no general analytic -treatment for the scattering kinematics at low energies, and thus when nuclear -data is processed for use in a Monte Carlo code, special tables are created that -give cross sections and secondary angle/energy distributions for thermal -scattering that account for thermal binding effects. These tables are mainly -used for moderating materials such as light or heavy water, graphite, hydrogen -in ZrH, beryllium, etc. - -The theory behind |sab| is rooted in quantum mechanics and is quite -complex. Those interested in first principles derivations for formulae relating -to |sab| tables should be referred to the excellent books by [Williams]_ and -[Squires]_. For our purposes here, we will focus only on the use of already -processed data as it appears in the ACE format. - -Each |sab| table can contain the following: - -- Thermal inelastic scattering cross section; -- Thermal elastic scattering cross section; -- Correlated energy-angle distributions for thermal inelastic and elastic - scattering. - -Note that when we refer to "inelastic" and "elastic" scattering now, we are -actually using these terms with respect to the *scattering system*. Thermal -inelastic scattering means that the scattering system is left in an excited -state; no particular nucleus is left in an excited state as would be the case -for inelastic level scattering. In a crystalline material, the excitation of the -scattering could correspond to the production of phonons. In a molecule, it -could correspond to the excitation of rotational or vibrational modes. - -Both thermal elastic and thermal inelastic scattering are generally divided into -incoherent and coherent parts. Coherent elastic scattering refers to scattering -in crystalline solids like graphite or beryllium. These cross sections are -characterized by the presence of *Bragg edges* that relate to the crystal -structure of the scattering material. Incoherent elastic scattering refers to -scattering in hydrogenous solids such as polyethylene. As it occurs in ACE data, -thermal inelastic scattering includes both coherent and incoherent effects and -is dominant for most other materials including hydrogen in water. - -Calculating Integrated Cross Sections -------------------------------------- - -The first aspect of using |sab| tables is calculating cross sections to replace -the data that would normally appear on the incident neutron data, which do not -account for thermal binding effects. For incoherent elastic and inelastic -scattering, the cross sections are stored as linearly interpolable functions on -a specified energy grid. For coherent elastic data, the cross section can be -expressed as - -.. math:: - :label: coherent-elastic-xs - - \sigma(E) = \frac{\sigma_c}{E} \sum_{E_i < E} f_i e^{-4WE_i} - -where :math:`\sigma_c` is the effective bound coherent scattering cross section, -:math:`W` is the effective Debye-Waller coefficient, :math:`E_i` are the -energies of the Bragg edges, and :math:`f_i` are related to crystallographic -structure factors. Since the functional form of the cross section is just 1/E -and the proportionality constant changes only at Bragg edges, the -proportionality constants are stored and then the cross section can be -calculated analytically based on equation :eq:`coherent-elastic-xs`. - -Outgoing Angle for Coherent Elastic Scattering ----------------------------------------------- - -Another aspect of using |sab| tables is determining the outgoing energy and -angle of the neutron after scattering. For incoherent and coherent elastic -scattering, the energy of the neutron does not actually change, but the angle -does change. For coherent elastic scattering, the angle will depend on which -Bragg edge scattered the neutron. The probability that edge :math:`i` will -scatter then neutron is given by - -.. math:: - :label: coherent-elastic-probability - - \frac{f_i e^{-4WE_i}}{\sum_j f_j e^{-4WE_j}}. - -After a Bragg edge has been sampled, the cosine of the angle of scattering is -given analytically by - -.. math:: - :label: coherent-elastic-angle - - \mu = 1 - \frac{E_i}{E} - -where :math:`E_i` is the energy of the Bragg edge that scattered the neutron. - -Outgoing Angle for Incoherent Elastic Scattering ------------------------------------------------- - -For incoherent elastic scattering, the probability distribution for the cosine -of the angle of scattering is represent as a series of equally-likely discrete -cosines :math:`\mu_{i,j}` for each incoming energy :math:`E_i` on the thermal -elastic energy grid. First the outgoing angle bin :math:`j` is sampled. Then, if -the incoming energy of the neutron satisfies :math:`E_i < E < E_{i+1}` the final -cosine is - -.. math:: - :label: incoherent-elastic-angle - - \mu = \mu_{i,j} + f (\mu_{i+1,j} - \mu_{i,j}) - -where the interpolation factor is defined as - -.. math:: - :label: sab-interpolation-factor - - f = \frac{E - E_i}{E_{i+1} - E_i}. - -Outgoing Energy and Angle for Inelastic Scattering --------------------------------------------------- - -Each |sab| table provides a correlated angle-energy secondary distribution for -neutron thermal inelastic scattering. There are three representations used -in the ACE thermal scattering data: equiprobable discrete outgoing -energies, non-uniform yet still discrete outgoing energies, and continuous -outgoing energies with corresponding probability and cumulative distribution -functions provided in tabular format. These three representations all -represent the angular distribution in a common format, using a series of -discrete equiprobable outgoing cosines. - -Equi-Probable Outgoing Energies -+++++++++++++++++++++++++++++++ - -If the thermal data was processed with :math:`iwt = 1` in NJOY, then the -outgoing energy spectra is represented in the ACE data as a set of discrete and -equiprobable outgoing energies. The procedure to determine the outgoing energy -and angle is as such. First, the interpolation factor is determined from -equation :eq:`sab-interpolation-factor`. Then, an outgoing energy bin is -sampled from a uniform distribution and then interpolated between values -corresponding to neighboring incoming energies: - -.. math:: - :label: inelastic-energy - - E = E_{i,j} + f (E_{i+1,j} - E_{i,j}) - -where :math:`E_{i,j}` is the j-th outgoing energy corresponding to the i-th -incoming energy. For each combination of incoming and outgoing energies, there -is a series equiprobable outgoing cosines. An outgoing cosine bin is sampled -uniformly and then the final cosine is interpolated on the incoming energy grid: - -.. math:: - :label: inelastic-angle - - \mu = \mu_{i,j,k} + f (\mu_{i+1,j,k} - \mu_{i,j,k}) - -where :math:`\mu_{i,j,k}` is the k-th outgoing cosine corresponding to the j-th -outgoing energy and the i-th incoming energy. - -Skewed Equi-Probable Outgoing Energies -++++++++++++++++++++++++++++++++++++++ - -If the thermal data was processed with :math:`iwt=0` in NJOY, then the -outgoing energy spectra is represented in the ACE data according to the -following: the first and last outgoing energies have a relative probability of -1, the second and second-to-last energies have a relative probability of 4, and -all other energies have a relative probability of 10. The procedure to -determine the outgoing energy and angle is similar to the method discussed -above, except that the sampled probability distribution is now skewed -accordingly. - -Continuous Outgoing Energies -++++++++++++++++++++++++++++ - -If the thermal data was processed with :math:`iwt=2` in NJOY, then the outgoing -energy spectra is represented by a continuous outgoing energy spectra in tabular -form with linear-linear interpolation. The sampling of the outgoing energy -portion of this format is very similar to :ref:`correlated-energy-angle`, but -the sampling of the correlated angle is performed as it was in the other two -representations discussed in this sub-section. In the Law 61 algorithm, we -found an interpolation factor :math:`f`, statistically sampled an incoming -energy bin :math:`\ell`, and sampled an outgoing energy bin :math:`j` based on -the tabulated cumulative distribution function. Once the outgoing energy has -been determined with equation :eq:`continuous-eout`, we then need to decide -which angular distribution data to use. Like the linear-linear interpolation -case in Law 61, the angular distribution closest to the sampled value of the -cumulative distribution function for the outgoing energy is utilized. The -actual algorithm utilized to sample the outgoing angle is shown in equation -:eq:`inelastic-angle`. - -.. _probability_tables: - ----------------------------------------------- -Unresolved Resonance Region Probability Tables ----------------------------------------------- - -Note that unresolved resonance treatments are only applicable to -continuous-energy transport. - -In the unresolved resonance energy range, resonances may be so closely spaced -that it is not possible for experimental measurements to resolve all -resonances. To properly account for self-shielding in this energy range, OpenMC -uses the `probability table method`_. For most thermal reactors, the use -of probability tables will not significantly affect problem results. However, -for some fast reactors and other problems with an appreciable flux spectrum in -the unresolved resonance range, not using probability tables may lead to -incorrect results. - -Probability tables in the ACE format are generated from the UNRESR module in -NJOY following the method of Levitt. A similar method employed for the RACER and -MC21_ Monte Carlo codes is described in a paper by `Sutton and Brown`_. For the -discussion here, we will focus only on use of the probability table table as it -appears in the ACE format. - -Each probability table for a nuclide contains the following information at a -number of incoming energies within the unresolved resonance range: - -- Cumulative probabilities for cross section bands; -- Total cross section (or factor) in each band; -- Elastic scattering cross section (or factor) in each band; -- Fission cross section (or factor) in each band; -- :math:`(n,\gamma)` cross section (or factor) in each band; and -- Neutron heating number (or factor) in each band. - -It should be noted that unresolved resonance probability tables affect only -integrated cross sections and no extra data need be given for secondary -angle/energy distributions. Secondary distributions for elastic and inelastic -scattering would be specified whether or not probability tables were present. - -The procedure for determining cross sections in the unresolved range using -probability tables is as follows. First, the bounding incoming energies are -determined, i.e. find :math:`i` such that :math:`E_i < E < E_{i+1}`. We then -sample a cross section band :math:`j` using the cumulative probabilities for -table :math:`i`. This allows us to then calculate the elastic, fission, and -capture cross sections from the probability tables interpolating between -neighboring incoming energies. If interpolation is specified, then -the cross sections are calculated as - -.. math:: - :label: ptables-linlin - - \sigma = \sigma_{i,j} + f (\sigma_{i+1,j} - \sigma{i,j}) - -where :math:`\sigma_{i,j}` is the j-th band cross section corresponding to the -i-th incoming neutron energy and :math:`f` is the interpolation factor defined -in the same manner as :eq:`sab-interpolation-factor`. If logarithmic -interpolation is specified, the cross sections are calculated as - -.. math:: - :label: ptables-loglog - - \sigma = \exp \left ( \log \sigma_{i,j} + f \log - \frac{\sigma_{i+1,j}}{\sigma_{i,j}} \right ) - -where the interpolation factor is now defined as - -.. math:: - :label: log-interpolation-factor - - f = \frac{\log \frac{E}{E_i}}{\log \frac{E_{i+1}}{E_i}}. - -A flag is also present in the probability table that specifies whether an -inelastic cross section should be calculated. If so, this is done from a normal -reaction cross section (either MT=51 or a special MT). Finally, if the -cross sections defined are above are specified to be factors and not true -cross sections, they are multiplied by the underlying smooth cross section in -the unresolved range to get the actual cross sections. Lastly, the total cross -section is calculated as the sum of the elastic, fission, capture, and inelastic -cross sections. - ------------------------------ -Variance Reduction Techniques ------------------------------ - -Survival Biasing ----------------- - -In problems with highly absorbing materials, a large fraction of neutrons may be -killed through absorption reactions, thus leading to tallies with very few -scoring events. To remedy this situation, an algorithm known as *survival -biasing* or *implicit absorption* (or sometimes *implicit capture*, even though -this is a misnomer) is commonly used. - -In survival biasing, absorption reactions are prohibited from occurring and -instead, at every collision, the weight of neutron is reduced by probability of -absorption occurring, i.e. - -.. math:: - :label: survival-biasing-weight - - w' = w \left ( 1 - \frac{\sigma_a (E)}{\sigma_t (E)} \right ) - -where :math:`w'` is the weight of the neutron after adjustment and :math:`w` is -the weight of the neutron before adjustment. A few other things need to be -handled differently if survival biasing is turned on. Although fission reactions -never actually occur with survival biasing, we still need to create fission -sites to serve as source sites for the next generation in the method of -successive generations. The algorithm for sampling fission sites is the same as -that described in :ref:`fission`. The only difference is in equation -:eq:`fission-neutrons`. We now need to produce - -.. math:: - :label: fission-neutrons-survival - - \nu = \frac{w}{k} \frac{\nu_t \sigma_f(E)}{\sigma_t (E)} - -fission sites, where :math:`w` is the weight of the neutron before being -adjusted. One should note this is just the expected number of neutrons produced -*per collision* rather than the expected number of neutrons produced given that -fission has already occurred. - -Additionally, since survival biasing can reduce the weight of the neutron to -very low values, it is always used in conjunction with a weight cutoff and -Russian rouletting. Two user adjustable parameters :math:`w_c` and :math:`w_s` -are given which are the weight below which neutrons should undergo Russian -roulette and the weight should they survive Russian roulette. The algorithm for -Russian rouletting is as follows. After a collision if :math:`w < w_c`, then the -neutron is killed with probability :math:`1 - w/w_s`. If it survives, the weight -is set equal to :math:`w_s`. One can confirm that the average weight following -Russian roulette is simply :math:`w`, so the game can be considered "fair". By -default, the cutoff weight in OpenMC is :math:`w_c = 0.25` and the survival -weight is :math:`w_s = 1.0`. These parameters vary from one Monte Carlo code to -another. - -.. only:: html - - .. rubric:: References - -.. [Gelbard] Ely M. Gelbard, "Epithermal Scattering in VIM," FRA-TM-123, Argonne - National Laboratory (1979). - -.. [Squires] G. L. Squires, *Introduction to the Theory of Thermal Neutron - Scattering*, Cambridge University Press (1978). - -.. [Williams] M. M. R. Williams, *The Slowing Down and Thermalization of - Neutrons*, North-Holland Publishing Co., Amsterdam (1966). **Note:** This - book can be obtained for free from the OECD_. - -.. |sab| replace:: S(:math:`\alpha,\beta,T`) - -.. _SIGMA1 method: https://doi.org/10.13182/NSE76-1 - -.. _scaled interpolation: http://www.ans.org/pubs/journals/nse/a_26575 - -.. _probability table method: https://doi.org/10.13182/NSE72-3 - -.. _Watt fission spectrum: https://doi.org/10.1103/PhysRev.87.1037 - -.. _Foderaro: http://hdl.handle.net/1721.1/1716 - -.. _OECD: http://www.oecd-nea.org/tools/abstract/detail/NEA-1792 - -.. _NJOY: https://www.njoy21.io/NJOY2016/ - -.. _PREPRO: http://www-nds.iaea.org/ndspub/endf/prepro/ - -.. _ENDF-6 Format: https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf - -.. _Monte Carlo Sampler: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721.pdf - -.. _LA-UR-14-27694: http://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-UR-14-27694 - -.. _MC21: http://www.osti.gov/bridge/servlets/purl/903083-HT5p1o/903083.pdf - -.. _Romano: https://doi.org/10.1016/j.cpc.2014.11.001 - -.. _Sutton and Brown: http://www.osti.gov/bridge/product.biblio.jsp?osti_id=307911 - -.. _lectures: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-05-4983.pdf - -.. _MCNP Manual: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-03-1987.pdf diff --git a/docs/source/methods/parallelization.rst b/docs/source/methods/parallelization.rst deleted file mode 100644 index 5bf090a2b..000000000 --- a/docs/source/methods/parallelization.rst +++ /dev/null @@ -1,650 +0,0 @@ -.. _methods_parallel: - -=============== -Parallelization -=============== - -Due to the computationally-intensive nature of Monte Carlo methods, there has -been an ever-present interest in parallelizing such simulations. Even in the -`first paper`_ on the Monte Carlo method, John Metropolis and Stanislaw Ulam -recognized that solving the Boltzmann equation with the Monte Carlo method could -be done in parallel very easily whereas the deterministic counterparts for -solving the Boltzmann equation did not offer such a natural means of -parallelism. With the introduction of `vector computers`_ in the early 1970s, -general-purpose parallel computing became a reality. In 1972, Troubetzkoy et -al. designed a Monte Carlo code to be run on the first vector computer, the -ILLIAC-IV [Troubetzkoy]_. The general principles from that work were later -refined and extended greatly through the `work of Forrest Brown`_ in the -1980s. However, as Brown's work shows, the `single-instruction multiple-data`_ -(SIMD) parallel model inherent to vector processing does not lend itself to the -parallelism on particles in Monte Carlo simulations. Troubetzkoy et -al. recognized this, remarking that "the order and the nature of these physical -events have little, if any, correlation from history to history," and thus -following independent particle histories simultaneously using a SIMD model is -difficult. - -The difficulties with vector processing of Monte Carlo codes led to the adoption -of the `single program multiple data`_ (SPMD) technique for parallelization. In -this model, each different process tracks a particle independently of other -processes, and between fission source generations the processes communicate data -through a `message-passing interface`_. This means of parallelism was enabled by -the introduction of message-passing standards in the late 1980s and early 1990s -such as PVM_ and MPI_. The SPMD model proved much easier to use in practice and -took advantage of the inherent parallelism on particles rather than -instruction-level parallelism. As a result, it has since become ubiquitous for -Monte Carlo simulations of transport phenomena. - -Thanks to the particle-level parallelism using SPMD techniques, extremely high -parallel efficiencies could be achieved in Monte Carlo codes. Until the last -decade, even the most demanding problems did not require transmitting large -amounts of data between processors, and thus the total amount of time spent on -communication was not significant compared to the amount of time spent on -computation. However, today's computing power has created a demand for -increasingly large and complex problems, requiring a greater number of particles -to obtain decent statistics (and convergence in the case of criticality -calculations). This results in a correspondingly higher amount of communication, -potentially degrading the parallel efficiency. Thus, while Monte Carlo -simulations may seem `embarrassingly parallel`_, obtaining good parallel scaling -with large numbers of processors can be quite difficult to achieve in practice. - -.. _fission-bank-algorithms: - ------------------------ -Fission Bank Algorithms ------------------------ - -Master-Slave Algorithm ----------------------- - -Monte Carlo particle transport codes commonly implement a SPMD model by having -one master process that controls the scheduling of work and the remaining -processes wait to receive work from the master, process the work, and then send -their results to the master at the end of the simulation (or a source iteration -in the case of an eigenvalue calculation). This idea is illustrated in -:ref:`figure-master-slave`. - -.. _figure-master-slave: - -.. figure:: ../_images/master-slave.png - :align: center - :figclass: align-center - - Communication pattern in master-slave algorithm. - -Eigenvalue calculations are slightly more difficult to parallelize than fixed -source calculations since it is necessary to converge on the fission source -distribution and eigenvalue before tallying. In the -:ref:`method-successive-generations`, to ensure that the results are -reproducible, one must guarantee that the process by which fission sites are -randomly sampled does not depend on the number of processors. What is typically -done is the following: - - 1. Each compute node sends_ its fission bank sites to a master process; - - 2. The master process sorts or orders the fission sites based on a unique - identifier; - - 3. The master process samples :math:`N` fission sites from the ordered array - of :math:`M` sites; and - - 4. The master process broadcasts_ all the fission sites to the compute - nodes. - -The first and last steps of this process are the major sources of communication -overhead between cycles. Since the master process must receive :math:`M` fission -sites from the compute nodes, the first step is necessarily serial. This step -can be completed in :math:`O(M)` time. The broadcast step can benefit from -parallelization through a tree-based algorithm. Despite this, the communication -overhead is still considerable. - -To see why this is the case, it is instructive to look at a hypothetical -example. Suppose that a calculation is run with :math:`N = 10,000,000` neutrons -across 64 compute nodes. On average, :math:`M = 10,000,000` fission sites will -be produced. If the data for each fission site consists of a spatial location -(three 8 byte real numbers) and a unique identifier (one 4 byte integer), the -memory required per site is 28 bytes. To broadcast 10,000,000 source sites to 64 -nodes will thus require transferring 17.92 GB of data. Since each compute node -does not need to keep every source site in memory, one could modify the -algorithm from a broadcast to a scatter_. However, for practical reasons -(e.g. work self-scheduling), this is normally not done in production Monte Carlo -codes. - -.. _nearest-neighbors-algorithm: - -Nearest Neighbors Algorithm ---------------------------- - -To reduce the amount of communication required in a fission bank synchronization -algorithm, it is desirable to move away from the typical master-slave algorithm -to an algorithm whereby the compute nodes communicate with one another only as -needed. This concept is illustrated in :ref:`figure-nearest-neighbor`. - -.. _figure-nearest-neighbor: - -.. figure:: ../_images/nearest-neighbor.png - :align: center - :figclass: align-center - - Communication pattern in nearest neighbor algorithm. - -Since the source sites for each cycle are sampled from the fission sites banked -from the previous cycle, it is a common occurrence for a fission site to be -banked on one compute node and sent back to the master only to get sent back to -the same compute node as a source site. As a result, much of the communication -inherent in the algorithm described previously is entirely unnecessary. By -keeping the fission sites local, having each compute node sample fission sites, -and sending sites between nodes only as needed, one can cut down on most of the -communication. One algorithm to achieve this is as follows: - - 1. An exclusive scan is performed on the number of sites banked, and the - total number of fission bank sites is broadcasted to all compute nodes. By - picturing the fission bank as one large array distributed across multiple - nodes, one can see that this step enables each compute node to determine the - starting index of fission bank sites in this array. Let us call the starting - and ending indices on the :math:`i`-th node :math:`a_i` and :math:`b_i`, - respectively; - - 2. Each compute node samples sites at random from the fission bank using the - same starting seed. A separate array on each compute node is created that - consists of sites that were sampled local to that node, i.e. if the index of - the sampled site is between :math:`a_i` and :math:`b_i`, it is set aside; - - 3. If any node sampled more than :math:`N/p` fission sites where :math:`p` - is the number of compute nodes, the extra sites are put in a separate array - and sent to all other compute nodes. This can be done efficiently using the - allgather_ collective operation; - - 4. The extra sites are divided among those compute nodes that sampled fewer - than :math:`N/p` fission sites. - -However, even this algorithm exhibits more communication than necessary since -the allgather will send fission bank sites to nodes that don't necessarily -need any extra sites. - -One alternative is to replace the allgather with a series of sends. If -:math:`a_i` is less than :math:`iN/p`, then send :math:`iN/p - a_i` sites to the -left adjacent node. Similarly, if :math:`a_i` is greater than :math:`iN/p`, then -receive :math:`a_i - iN/p` from the left adjacent node. This idea is applied to -the fission bank sites at the end of each node's array as well. If :math:`b_i` -is less than :math:`(i+1)N/p`, then receive :math:`(i+1)N/p - b_i` sites from -the right adjacent node. If :math:`b_i` is greater than :math:`(i+1)N/p`, then -send :math:`b_i - (i+1)N/p` sites to the right adjacent node. Thus, each compute -node sends/receives only two messages under normal circumstances. - -The following example illustrates how this algorithm works. Let us suppose we -are simulating :math:`N = 1000` neutrons across four compute nodes. For this -example, it is instructive to look at the state of the fission bank and source -bank at several points in the algorithm: - - 1. The beginning of a cycle where each node has :math:`N/p` source sites; - - 2. The end of a cycle where each node has accumulated fission sites; - - 3. After sampling, where each node has some amount of source sites usually - not equal to :math:`N/p`; - - 4. After redistribution, each node again has :math:`N/p` source sites for - the next cycle; - -At the end of each cycle, each compute node needs 250 fission bank sites to -continue on the next cycle. Let us suppose that :math:`p_0` produces 270 fission -banks sites, :math:`p_1` produces 230, :math:`p_2` produces 290, and :math:`p_3` -produces 250. After each node samples from its fission bank sites, let's assume -that :math:`p_0` has 260 source sites, :math:`p_1` has 215, :math:`p_2` has 280, -and :math:`p_3` has 245. Note that the total number of sampled sites is 1000 as -needed. For each node to have the same number of source sites, :math:`p_0` needs -to send its right-most 10 sites to :math:`p_1`, and :math:`p_2` needs to send -its left-most 25 sites to :math:`p_1` and its right-most 5 sites to -:math:`p_3`. A schematic of this example is shown in -:ref:`figure-neighbor-example`. The data local to each node is given a different -hatching, and the cross-hatched regions represent source sites that are -communicated between adjacent nodes. - -.. _figure-neighbor-example: - -.. figure:: ../_images/nearest-neighbor-example.png - :align: center - :figclass: align-center - - Example of nearest neighbor algorithm. - -.. _master-slave-cost: - -Cost of Master-Slave Algorithm ------------------------------- - -While the prior considerations may make it readily apparent that the novel -algorithm should outperform the traditional algorithm, it is instructive to look -at the total communication cost of the novel algorithm relative to the -traditional algorithm. This is especially so because the novel algorithm does -not have a constant communication cost due to stochastic fluctuations. Let us -begin by looking at the cost of communication in the traditional algorithm - -As discussed earlier, the traditional algorithm is composed of a series of sends -and typically a broadcast. To estimate the communication cost of the algorithm, -we can apply a simple model that captures the essential features. In this model, -we assume that the time that it takes to send a message between two nodes is -given by :math:`\alpha + (sN)\beta`, where :math:`\alpha` is the time it takes -to initiate the communication (commonly called the latency_), :math:`\beta` is -the transfer time per unit of data (commonly called the bandwidth_), :math:`N` -is the number of fission sites, and :math:`s` is the size in bytes of each -fission site. - -The first step of the traditional algorithm is to send :math:`p` messages to the -master node, each of size :math:`sN/p`. Thus, the total time to send these -messages is - -.. math:: - :label: t-send - - t_{\text{send}} = p\alpha + sN\beta. - -Generally, the best parallel performance is achieved in a weak scaling scheme -where the total number of histories is proportional to the number of -processors. However, we see that when :math:`N` is proportional to :math:`p`, -the time to send these messages increases proportionally with :math:`p`. - -Estimating the time of the broadcast is complicated by the fact that different -MPI implementations may use different algorithms to perform collective -communications. Worse yet, a single implementation may use a different algorithm -depending on how many nodes are communicating and the size of the message. Using -multiple algorithms allows one to minimize latency for small messages and -minimize bandwidth for long messages. - -We will focus here on the implementation of broadcast in the MPICH2_ -implementation. For short messages, MPICH2 uses a `binomial tree`_ algorithm. In -this algorithm, the root process sends the data to one node in the first step, -and then in the subsequent, both the root and the other node can send the data -to other nodes. Thus, it takes a total of :math:`\lceil \log_2 p \rceil` steps -to complete the communication. The time to complete the communication is - -.. math:: - :label: t-short - - t_{\text{short}} = \lceil \log_2 p \rceil \left ( \alpha + sN\beta \right ). - -This algorithm works well for short messages since the latency term scales -logarithmically with the number of nodes. However, for long messages, an -algorithm that has lower bandwidth has been proposed by Barnett_ and implemented -in MPICH2. Rather than using a binomial tree, the broadcast is divided into a -scatter and an allgather. The time to complete the scatter is :math:` \log_2 p -\: \alpha + \frac{p-1}{p} N\beta` using a binomial tree algorithm. The allgather -is performed using a ring algorithm that completes in :math:`p-1) \alpha + -\frac{p-1}{p} N\beta`. Thus, together the time to complete the broadcast is - -.. math:: - :label: t-broadcast - - t_{\text{long}} = \left ( \log_2 p + p - 1 \right ) \alpha + 2 \frac{p-1}{p} - sN\beta. - -The fission bank data will generally exceed the threshold for switching from -short to long messages (typically 8 kilobytes), and thus we will use the -equation for long messages. Adding equations :eq:`t-send` and :eq:`t-broadcast`, -the total cost of the series of sends and the broadcast is - -.. math:: - :label: t-old - - t_{\text{old}} = \left ( \log_2 p + 2p - 1 \right ) \alpha + \frac{3p-2}{p} - sN\beta. - -Cost of Nearest Neighbor Algorithm ----------------------------------- - -With the communication cost of the traditional fission bank algorithm -quantified, we now proceed to discuss the communicatin cost of the proposed -algorithm. Comparing the cost of communication of this algorithm with the -traditional algorithm is not trivial due to fact that the cost will be a -function of how many fission sites are sampled on each node. If each node -samples exactly :math:`N/p` sites, there will not be communication between nodes -at all. However, if any one node samples more or less than :math:`N/p` sites, -the deviation will result in communication between logically adjacent nodes. To -determine the expected deviation, one can analyze the process based on the -fundamentals of the Monte Carlo process. - -The steady-state neutron transport equation for a multiplying medium can be -written in the form of an eigenvalue problem, - -.. math:: - :label: NTE - - S(\mathbf{r})= \frac{1}{k} \int F(\mathbf{r}' \rightarrow - \mathbf{r})S(\mathbf{r}')\: d\mathbf{r}, - -where :math:`\mathbf{r}` is the spatial coordinates of the neutron, -:math:`S(\mathbf{r})` is the source distribution defined as the expected number -of neutrons born from fission per unit phase-space volume at :math:`\mathbf{r}`, -:math:`F( \mathbf{r}' \rightarrow \mathbf{r})` is the expected number of -neutrons born from fission per unit phase space volume at :math:`\mathbf{r}` -caused by a neutron at :math:`\mathbf{r}`, and :math:`k` is the eigenvalue. The -fundamental eigenvalue of equation :eq:`NTE` is known as :math:`k_{eff}`, but -for simplicity we will simply refer to it as :math:`k`. - -In a Monte Carlo criticality simulation, the power iteration method is applied -iteratively to obtain stochastic realizations of the source distribution and -estimates of the :math:`k`-eigenvalue. Let us define :math:`\hat{S}^{(m)}` to be -the realization of the source distribution at cycle :math:`m` and -:math:`\hat{\epsilon}^{(m)}` be the noise arising from the stochastic nature of -the tracking process. We can write the stochastic realization in terms of the -fundamental source distribution and the noise component as (see `Brissenden and -Garlick`_): - -.. math:: - :label: source - - \hat{S}^{(m)}(\mathbf{r})= N S(\mathbf{r}) + \sqrt{N} - \hat{\epsilon}^{(m)}(\mathbf{r}), - -where :math:`N` is the number of particle histories per cycle. Without loss of -generality, we shall drop the superscript notation indicating the cycle as it is -understood that the stochastic realization is at a particular cycle. The -expected value of the stochastic source distribution is simply - -.. math:: - :label: expected-value-source - - E \left[ \hat{S}(\mathbf{r})\right] = N S (\mathbf{r}) - -since :math:`E \left[ \hat{\epsilon}(\mathbf{r})\right] = 0`. The noise in the -source distribution is due only to :math:`\hat{\epsilon}(\mathbf{r})` and thus -the variance of the source distribution will be - -.. math:: - :label: var-source - - \text{Var} \left[ \hat{S}(\mathbf{r})\right] = N \text{Var} \left[ - \hat{\epsilon}(\mathbf{r}) \right]. - -Lastly, the stochastic and true eigenvalues can be written as integrals over all -phase space of the stochastic and true source distributions, respectively, as - -.. math:: - :label: k-to-source - - \hat{k} = \frac{1}{N} \int \hat{S}(\mathbf{r}) \: d\mathbf{r} \quad - \text{and} \quad k = \int S(\mathbf{r}) \: d\mathbf{r}, - -noting that :math:`S(\mathbf{r})` is :math:`O(1)`. One should note that the -expected value :math:`k` calculated by Monte Carlo power iteration (i.e. the -method of successive generations) will be biased from the true fundamental -eigenvalue of equation :eq:`NTE` by :math:`O(1/N)` (see `Brissenden and -Garlick`_), but we will assume henceforth that the number of particle histories -per cycle is sufficiently large to neglect this bias. - -With this formalism, we now have a framework within which we can determine the -properties of the distribution of expected number of fission sites. The explicit -form of the source distribution can be written as - -.. math:: - :label: source-explicit - - \hat{S}(\mathbf{r}) = \sum_{i=1}^{M} w_i \delta( \mathbf{r} - \mathbf{r}_i ) - -where :math:`\mathbf{r}_i` is the spatial location of the :math:`i`-th fission -site, :math:`w_i` is the statistical weight of the fission site at -:math:`\mathbf{r}_i`, and :math:`M` is the total number of fission sites. It is -clear that the total weight of the fission sites is simply the integral of the -source distribution. Integrating equation :eq:`source` over all space, we obtain - -.. math:: - :label: source-integrated - - \int \hat{S}(\mathbf{r}) \: d\mathbf{r} = N \int S(\mathbf{r}) \: - d\mathbf{r} + \sqrt{N} \int \hat{\epsilon}(\mathbf{r}) \: d\mathbf{r} . - -Substituting the expressions for the stochastic and true eigenvalues from -equation :eq:`k-to-source`, we can relate the stochastic eigenvalue to the -integral of the noise component of the source distribution as - -.. math:: - :label: noise-integeral - - N\hat{k} = Nk + \sqrt{N} \int \hat{\epsilon}(\mathbf{r}) \: d\mathbf{r}. - -Since the expected value of :math:`\hat{\epsilon}` is zero, the expected value -of its integral will also be zero. We thus see that the variance of the integral -of the source distribution, i.e. the variance of the total weight of fission -sites produced, is directly proportional to the variance of the integral of the -noise component. Let us call this term :math:`\sigma^2` for simplicity: - -.. math:: - :label: variance-sigma2 - - \text{Var} \left[ \int \hat{S}(\mathbf{r}) \right ] = N \sigma^2. - -The actual value of :math:`\sigma^2` will depend on the physical nature of the -problem, whether variance reduction techniques are employed, etc. For instance, -one could surmise that for a highly scattering problem, :math:`\sigma^2` would -be smaller than for a highly absorbing problem since more collisions will lead -to a more precise estimate of the source distribution. Similarly, using implicit -capture should in theory reduce the value of :math:`\sigma^2`. - -Let us now consider the case where the :math:`N` total histories are divided up -evenly across :math:`p` compute nodes. Since each node simulates :math:`N/p` -histories, we can write the source distribution as - -.. math:: - :label: source-node - - \hat{S}_i(\mathbf{r})= \frac{N}{p} S(\mathbf{r}) + \sqrt{\frac{N}{p}} - \hat{\epsilon}_i(\mathbf{r}) \quad \text{for} \quad i = 1, \dots, p - -Integrating over all space and simplifying, we can obtain an expression for the -eigenvalue on the :math:`i`-th node: - -.. math:: - :label: k-i-hat - - \hat{k}_i = k + \sqrt{\frac{p}{N}} \int \hat{\epsilon}_i(\mathbf{r}) \: - d\mathbf{r}. - -It is easy to show from this expression that the stochastic realization of the -global eigenvalue is merely the average of these local eigenvalues: - -.. math:: - :label: average-k-as-sum - - \hat{k} = \frac{1}{p} \sum_{i=1}^p \hat{k}_i. - -As was mentioned earlier, at the end of each cycle one must sample :math:`N` -sites from the :math:`M` sites that were created. Thus, the source for the next -cycle can be seen as the fission source from the current cycle divided by the -stochastic realization of the eigenvalue since it is clear from equation -:eq:`k-to-source` that :math:`\hat{k} = M/N`. Similarly, the number of sites -sampled on each compute node that will be used for the next cycle is - -.. math:: - :label: sites-per-node - - M_i = \frac{1}{\hat{k}} \int \hat{S}_i(\mathbf{r}) \: d\mathbf{r} = - \frac{N}{p} \frac{\hat{k}_i}{\hat{k}}. - -While we know conceptually that each compute node will under normal -circumstances send two messages, many of these messages will overlap. Rather -than trying to determine the actual communication cost, we will instead attempt -to determine the maximum amount of data being communicated from one node to -another. At any given cycle, the number of fission sites that the :math:`j`-th -compute node will send or receive (:math:`\Lambda_j`) is - -.. math:: - :label: Lambda - - \Lambda_j = \left | \sum_{i=1}^j M_i - \frac{jN}{p} \right |. - -Noting that :math:`jN/p` is the expected value of the summation, we can write -the expected value of :math:`\Lambda_j` as the mean absolute deviation of the -summation: - -.. math:: - :label: mean-dev-lambda - - E \left [ \Lambda_j \right ] = E \left [ \left | \sum_{i=1}^j M_i - - \frac{jN}{p} \right | \right ] = \text{MD} \left [ \sum_{i=1}^j M_i \right ] - -where :math:`\text{MD}` indicates the mean absolute deviation of a random -variable. The mean absolute deviation is an alternative measure of variability. - -In order to ascertain any information about the mean deviation of :math:`M_i`, -we need to know the nature of its distribution. Thus far, we have said nothing -of the distributions of the random variables in question. The total number of -fission sites resulting from the tracking of :math:`N` neutrons can be shown to -be normally distributed via the :ref:`central-limit-theorem` (provided that -:math:`N` is sufficiently large) since the fission sites resulting from each -neutron are "sampled" from independent, identically-distributed random -variables. Thus, :math:`\hat{k}` and :math:`\int \hat{S} (\mathbf{r}) \: -d\mathbf{r}` will be normally distributed as will the individual estimates of -these on each compute node. - -Next, we need to know what the distribution of :math:`M_i` in equation -:eq:`sites-per-node` is or, equivalently, how :math:`\hat{k}_i / \hat{k}` is -distributed. The distribution of a ratio of random variables is not easy to -calculate analytically, and it is not guaranteed that the ratio distribution is -normal if the numerator and denominator are normally distributed. For example, -if :math:`X` is a standard normal distribution and :math:`Y` is also standard -normal distribution, then the ratio :math:`X/Y` has the standard `Cauchy -distribution`_. The reader should be reminded that the Cauchy distribution has -no defined mean or variance. That being said, Geary_ has shown that, for the -case of two normal distributions, if the denominator is unlikely to assume -values less than zero, then the ratio distribution is indeed approximately -normal. In our case, :math:`\hat{k}` absolutely cannot assume a value less than -zero, so we can be reasonably assured that the distribution of :math:`M_i` will -be normal. - -For a normal distribution with mean :math:`\mu` and distribution function -:math:`f(x)`, it can be shown that - -.. math:: - :label: mean-dev-to-stdev - - \int_{-\infty}^{\infty} f(x) \left | x - \mu \right | \: dx = - \sqrt{\frac{2}{\pi} \int_{-\infty}^{\infty} f(x) \left ( x - \mu \right )^2 - \: dx} - -and thus the mean absolute deviation is :math:`\sqrt{2/\pi}` times the standard -deviation. Therefore, to evaluate the mean absolute deviation of :math:`M_i`, we -need to first determine its variance. Substituting equation -:eq:`average-k-as-sum` into equation :eq:`sites-per-node`, we can rewrite -:math:`M_i` solely in terms of :math:`\hat{k}_1, \dots, \hat{k}_p`: - -.. math:: - :label: M-i - - M_i = \frac{N \hat{k}_i}{\sum\limits_{j=1}^p \hat{k}_j}. - -Since we know the variance of :math:`\hat{k}_i`, we can use the error -propagation law to determine the variance of :math:`M_i`: - -.. math:: - :label: M-variance - - \text{Var} \left [ M_i \right ] = \sum_{j=1}^p \left ( \frac{\partial - M_i}{\partial \hat{k}_j} \right )^2 \text{Var} \left [ \hat{k}_j \right ] + - \sum\limits_{j \neq m} \sum\limits_{m=1}^p \left ( \frac{\partial - M_i}{\partial \hat{k}_j} \right ) \left ( \frac{\partial M_i}{\partial - \hat{k}_m} \right ) \text{Cov} \left [ \hat{k}_j, \hat{k}_m \right ] - -where the partial derivatives are evaluated at :math:`\hat{k}_j = k`. Since -:math:`\hat{k}_j` and :math:`\hat{k}_m` are independent if :math:`j \neq m`, -their covariance is zero and thus the second term cancels out. Evaluating the -partial derivatives, we obtain - -.. math:: - :label: M-variance-2 - - \text{Var} \left [ M_i \right ] = \left ( \frac{N(p-1)}{kp^2} \right )^2 - \frac{p\sigma^2}{N} + \sum_{j \neq i} \left ( \frac{-N}{kp^2} \right )^2 - \frac{p\sigma^2}{N} = \frac{N(p-1)}{k^2p^2} \sigma^2. - -Through a similar analysis, one can show that the variance of -:math:`\sum_{i=1}^j M_i` is - -.. math:: - :label: sum-M-variance - - \text{Var} \left [ \sum_{i=1}^j M_i \right ] = \frac{Nj(p-j)}{k^2p^2} - \sigma^2 - -Thus, the expected amount of communication on node :math:`j`, i.e. the mean -absolute deviation of :math:`\sum_{i=1}^j M_i` is proportional to - -.. math:: - :label: communication-cost - - E \left [ \Lambda_j \right ] = \sqrt{\frac{2Nj(p-j)\sigma^2}{\pi k^2p^2}}. - -This formula has all the properties that one would expect based on intuition: - - 1. As the number of histories increases, the communication cost on each node - increases as well; - - 2. If :math:`p=1`, i.e. if the problem is run on only one compute node, the - variance will be zero. This reflects the fact that exactly :math:`N` sites - will be sampled if there is only one node. - - 3. For :math:`j=p`, the variance will be zero. Again, this says that when - you sum the number of sites from each node, you will get exactly :math:`N` - sites. - -We can determine the node that has the highest communication cost by -differentiating equation :eq:`communication-cost` with respect to :math:`j`, -setting it equal to zero, and solving for :math:`j`. Doing so yields -:math:`j_{\text{max}} = p/2`. Interestingly, substituting :math:`j = p/2` in -equation :eq:`communication-cost` shows us that the maximum communication cost -is actually independent of the number of nodes: - -.. math:: - :label: maximum-communication - - E \left [ \Lambda_{j_{\text{max}}} \right ] = \sqrt{ \frac{N\sigma^2}{2\pi - k^2}}. - -.. only:: html - - .. rubric:: References - -.. [Troubetzkoy] E. Troubetzkoy, H. Steinberg, and M. Kalos, "Monte Carlo - Radiation Penetration Calculations on a Parallel Computer," - *Trans. Am. Nucl. Soc.*, **17**, 260 (1973). - -.. _first paper: https://doi.org/10.2307/2280232 - -.. _work of Forrest Brown: http://hdl.handle.net/2027.42/24996 - -.. _Brissenden and Garlick: https://doi.org/10.1016/0306-4549(86)90095-2 - -.. _MPICH2: http://www.mcs.anl.gov/mpi/mpich - -.. _binomial tree: https://www.mcs.anl.gov/~thakur/papers/ijhpca-coll.pdf - -.. _Geary: https://doi.org/10.2307/2342070 - -.. _Barnett: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.7772 - -.. _single-instruction multiple-data: https://en.wikipedia.org/wiki/SIMD - -.. _vector computers: https://en.wikipedia.org/wiki/Vector_processor - -.. _single program multiple data: https://en.wikipedia.org/wiki/SPMD - -.. _message-passing interface: https://en.wikipedia.org/wiki/Message_Passing_Interface - -.. _PVM: http://www.csm.ornl.gov/pvm/pvm_home.html - -.. _MPI: http://www.mcs.anl.gov/research/projects/mpi/ - -.. _embarrassingly parallel: https://en.wikipedia.org/wiki/Embarrassingly_parallel - -.. _sends: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Send.html - -.. _broadcasts: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Bcast.html - -.. _scatter: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Scatter.html - -.. _allgather: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Allgather.html - -.. _Cauchy distribution: https://en.wikipedia.org/wiki/Cauchy_distribution - -.. _latency: https://en.wikipedia.org/wiki/Latency_(engineering)#Packet-switched_networks - -.. _bandwidth: https://en.wikipedia.org/wiki/Bandwidth_(computing) diff --git a/docs/source/methods/photon_physics.rst b/docs/source/methods/photon_physics.rst deleted file mode 100644 index f9bdcfa1c..000000000 --- a/docs/source/methods/photon_physics.rst +++ /dev/null @@ -1,1072 +0,0 @@ -.. _methods_photon_physics: - -============== -Photon Physics -============== - -Photons, being neutral particles, behave much in the same manner as neutrons, -traveling in straight lines and experiencing occasional collisions that change -their energy and direction. Photons undergo four basic interactions as they pass -through matter: coherent (Rayleigh) scattering, incoherent (Compton) scattering, -photoelectric effect, and pair/triplet production. Photons with energy in the -MeV range may also undergo photonuclear reactions with an atomic nucleus. In -addition to these primary interaction mechanisms, all processes other than -coherent scattering can result in the excitation/ionization of atoms. The -de-excitation of these atoms can result in the emission of electrons and -photons. Electrons themselves also can produce photons by means of -bremsstrahlung radiation. - -------------------- -Photon Interactions -------------------- - -Coherent (Rayleigh) Scattering ------------------------------- - -The elastic scattering of a photon off a free charged particle is known as -Thomson scattering. The differential cross section is independent of the energy -of the incident photon. For scattering off a free electron, the differential -cross section is - -.. math:: - :label: thomson - - \frac{d\sigma}{d\mu} = \pi r_e^2 ( 1 + \mu^2 ) - -where :math:`\mu` is the cosine of the scattering angle and :math:`r_e` is the -classical electron radius. Thomson scattering can generally occur when the -photon energy is much less than the rest mass energy of the particle. - -In practice, most elastic scattering of photons off electrons happens not with -free electrons but those bound in atoms. This process is known as Rayleigh -scattering. The radiation scattered off of individual bound electrons combines -coherently, and thus Rayleigh scattering is also known as coherent -scattering. Even though conceptually we think of the photon interacting with a -single electron, because the wave functions combine constructively it is really -as though the photon is interacting with the entire atom. - -The differential cross section for Rayleigh scattering is given by - -.. math:: - :label: coherent-xs - - \begin{aligned} - \frac{d\sigma(E,E',\mu)}{d\mu} &= \pi r_e^2 ( 1 + \mu^2 )~\left| F(x,Z) - + F' + iF'' \right|^2 \\ - &= \pi r_e^2 ( 1 + \mu^2 ) \left [ ( F(x,Z) - + F'(E) )^2 + F''(E)^2 \right ] - \end{aligned} - -where :math:`F(x,Z)` is a form factor as a function of the momentum transfer -:math:`x` and the atomic number :math:`Z` and the term :math:`F' + iF''` -accounts for `anomalous scattering`_ which can occur near absorption edges. In -a Monte Carlo simulation, when coherent scattering occurs, we only need to -sample the scattering angle using the differential cross section in -:eq:`coherent-xs` since the energy of the photon does not change. In OpenMC, -anomalous scattering is ignored such that the differential cross section -becomes - -.. math:: - :label: coherent-xs-openmc - - \frac{d\sigma(E,E',\mu)}{d\mu} = \pi r_e^2 ( 1 + \mu^2 ) F(x, Z)^2 - -To construct a proper probability density, we need to normalize the -differential cross section in :eq:`coherent-xs-openmc` by the integrated -coherent scattering cross section: - -.. math:: - :label: coherent-pdf-1 - - p(\mu) d\mu = \frac{\pi r_e^2}{\sigma(E)} ( 1 + \mu^2 ) F(x, Z)^2 d\mu. - -Since the form factor is given in terms of the momentum transfer, it is more -convenient to change variables of the probability density to :math:`x^2`. The -momentum transfer is traditionally expressed as - -.. math:: - :label: momentum-transfer - - x = a k \sqrt{1 - \mu} - -where :math:`k` is the ratio of the photon energy to the electron rest -mass, and the coefficient :math:`a` can be shown to be - -.. math:: - :label: omega - - a = \frac{m_e c^2}{\sqrt{2}hc} \approx 2.914329\times10^{-9}~\text{m} - -where :math:`m_e` is the mass of the electron, :math:`c` is the speed of light -in a vacuum, and :math:`h` is Planck's constant. Using :eq:`momentum-transfer`, -we have :math:`\mu = 1 - [x/(ak)]^2` and :math:`d\mu/dx^2 = --1/(ak)^2`. The probability density in :math:`x^2` is - -.. math:: - :label: coherent-pdf-x2 - - p(x^2) dx^2 = p(\mu) \left | \frac{d\mu}{dx^2} \right | dx^2 = \frac{2\pi - r_e^2 A(\bar{x}^2,Z)}{(ak)^2 \sigma(E)} \left ( - \frac{1 + \mu^2}{2} \right ) \left ( \frac{F(x, Z)^2}{A(\bar{x}^2, Z)} \right ) dx^2 - -where :math:`\bar{x}` is the maximum value of :math:`x` that occurs for -:math:`\mu=-1`, - -.. math:: - :label: xmax - - \bar{x} = a k \sqrt{2} = \frac{m_e c^2}{hc} k, - -and :math:`A(x^2, Z)` is the integral of the square of the form factor: - -.. math:: - :label: coherent-int-ff - - A(x^2, Z) = \int_0^{x^2} F(x,Z)^2 dx^2. - -As you see, we have multiplied and divided the probability density by the -integral of the squared form factor so that the density in :eq:`coherent-pdf-x2` -is expressed as the product of two separate densities in parentheses. In OpenMC, -a table of :math:`A(x^2, Z)` versus :math:`x^2` is pre-generated and used at -run-time to do a table search on the cumulative distribution function: - -.. math:: - :label: coherent-form-factor-cdf - - \frac{\int_0^{x^2} F(x,Z)^2 dx^2}{\int_0^{\bar{x}^2} F(x,Z)^2 dx^2} - -Once a trial :math:`x^2` value has been selected, we can calculate :math:`\mu` -and perform rejection sampling using the Thomson scattering differential cross -section. The complete algorithm is as follows: - -1. Determine :math:`\bar{x}^2` using :eq:`xmax`. - -2. Determine :math:`A_{max} = A(\bar{x}^2, Z)` using the pre-generated - tabulated data. - -3. Sample the cumulative density by calculating :math:`A' = \xi_1 A_{max}` where - :math:`\xi_1` is a uniformly distributed random number. - -4. Perform a binary search to determine the value of :math:`x^2` which satisfies - :math:`A(x^2, Z) = A'`. - -5. By combining :eq:`momentum-transfer` and :eq:`xmax`, calculate :math:`\mu = - 1 - 2x^2/\bar{x}^2`. - -6. If :math:`\xi_2 < (1 + \mu^2)/2`, accept :math:`\mu`. Otherwise, repeat the - sampling at step 3. - -.. _incoherent-sampling: - -Incoherent (Compton) Scattering -------------------------------- - -Before we noted that the Thomson cross section gives the behavior for photons -scattering off of free electrons valid at low energies. The formula for photon -scattering off of free electrons that is valid for all energies can be found -using quantum electrodynamics and is known as the Klein-Nishina_ formula after -the two authors who discovered it: - -.. math:: - :label: klein-nishina - - \frac{d\sigma_{KN}}{d\mu} = \pi r_e^2 \left ( \frac{k'}{k} \right)^2 \left - [ \frac{k'}{k} + \frac{k}{k'} + \mu^2 - 1 \right ] - -where :math:`k` and :math:`k'` are the ratios of the incoming and exiting -photon energies to the electron rest mass energy equivalent (0.511 MeV), -respectively. Although it appears that the outgoing energy and angle are -separate, there is actually a one-to-one relationship between them such that -only one needs to be sampled: - -.. math:: - :label: compton-energy-angle - - k' = \frac{k}{1 + k(1 - \mu)}. - -Note that when :math:`k'/k` goes to one, i.e., scattering is elastic, the -Klein-Nishina cross section becomes identical to the Thomson cross section. In -general though, the scattering is inelastic and is known as Compton scattering. -When a photon interacts with a bound electron in an atom, the Klein-Nishina -formula must be modified to account for the binding effects. As in the case of -coherent scattering, this is done by means of a form factor. The differential -cross section for incoherent scattering is given by - -.. math:: - :label: incoherent-xs - - \frac{d\sigma}{d\mu} = \frac{d\sigma_{KN}}{d\mu} S(x,Z) = \pi r_e^2 \left ( - \frac{k'}{k} \right )^2 \left [ \frac{k'}{k} + \frac{k}{k'} + \mu^2 - 1 - \right ] S(x,Z) - -where :math:`S(x,Z)` is the form factor. The approach in OpenMC is to first -sample the Klein-Nishina cross section and then perform rejection sampling on -the form factor. As in other codes, `Kahn's rejection method`_ is used for -:math:`k < 3` and a direct method by Koblinger_ is used for :math:`k \ge 3`. -The complete algorithm is as follows: - -1. If :math:`k < 3`, sample :math:`\mu` from the Klein-Nishina cross section - using Kahn's rejection method. Otherwise, use Koblinger's direct method. - -2. Calculate :math:`x` and :math:`\bar{x}` using :eq:`momentum-transfer` and - :eq:`xmax`, respectively. - -3. If :math:`\xi < S(x, Z)/S(\bar{x}, Z)`, accept :math:`\mu`. Otherwise repeat - from step 1. - -Doppler Energy Broadening -+++++++++++++++++++++++++ - -Bound electrons are not at rest but have a momentum distribution that will -cause the energy of the scattered photon to be Doppler broadened. More tightly -bound electrons have a wider momentum distribution, so the energy spectrum of -photons scattering off inner shell electrons will be broadened the most. -In addition, scattering from bound electrons places a limit on the maximum -scattered photon energy: - -.. math:: - :label: max-energy-out - - E'_{\text{max}} = E - E_{b,i}, - -where :math:`E_{b,i}` is the binding energy of the :math:`i`-th subshell. - -Compton profiles :math:`J_i(p_z)` are used to account for the binding effects. -The quantity :math:`p_z = {\bf p} \cdot {\bf q}/q` is the projection of the -initial electron momentum on :math:`{\bf q}`, where the scattering vector -:math:`{\bf q} = {\bf p} - {\bf p'}` is the momentum gained by the photon, -:math:`{\bf p}` is the initial momentum of the electron, and :math:`{\bf p'}` -is the momentum of the scattered electron. Applying the conservation of energy -and momentum, :math:`p_z` can be written in terms of the photon energy and -scattering angle: - -.. math:: - :label: pz - - p_z = \frac{E - E' - EE'(1 - \mu)/(m_e c^2)}{-\alpha \sqrt{E^2 + E'^2 - - 2EE'\mu}}, - -where :math:`\alpha` is the fine structure constant. The maximum momentum -transferred, :math:`p_{z,\text{max}}`, can be calculated from :eq:`pz` using -:math:`E' = E'_{\text{max}}`. The Compton profile of the :math:`i`-th electron -subshell is defined as - -.. math:: - :label: compton-profile - - J_i(p_z) = \int \int \rho_i({\bf p}) dp_x dp_y, - -where :math:`\rho_i({\bf p})` is the initial electron momentum distribution. -:math:`J_i(p_z)` can be interpreted as the probability density function of -:math:`p_z`. - -The Doppler broadened energy of the Compton-scattered photon can be sampled by -selecting an electron shell, sampling a value of :math:`p_z` using the Compton -profile, and calculating the scattered photon energy. The theory and methods -used to do this are described in detail in LA-UR-04-0487_ and LA-UR-04-0488_. -The sampling algorithm is summarized below: - -1. Sample :math:`\mu` from :eq:`incoherent-xs` using the algorithm described in - :ref:`incoherent-sampling`. - -2. Sample the electron subshell :math:`i` using the number of electrons per - shell as the probability mass function. - -3. Sample :math:`p_z` using :math:`J_i(p_z)` as the PDF. - -4. Calculate :math:`E'` by solving :eq:`pz` for :math:`E'` using the sampled - value of :math:`p_z`. - -5. If :math:`p_z < p_{z,\text{max}}` for shell :math:`i`, accept :math:`E'`. - Otherwise repeat from step 2. - -Compton Electrons -+++++++++++++++++ - -Because the Compton-scattered photons can transfer a large fraction of their -energy to the kinetic energy of the recoil electron, which may in turn go on to -lose its energy as bremsstrahlung radiation, it is necessary to accurately -model the angular and energy distributions of Compton electrons. The energy of -the recoil electron ejected from the :math:`i`-th subshell is given by - -.. math:: - :label: compton-electron-energy - - E_{-} = E - E' - E_{b,i}. - -The direction of the electron is assumed to be in the direction of the momentum -transfer, with the cosine of the polar angle given by - -.. math:: - :label: compton-electron-mu - - \mu_{-} = \frac{E - E'\mu}{\sqrt{E^2 +E'^2 - 2EE'\mu}} - -and the azimuthal angle :math:`\phi_{-} = \phi + \pi`, where :math:`\phi` is -the azimuthal angle of the photon. The vacancy left by the ejected electron is -filled through atomic relaxation. - -Photoelectric Effect --------------------- - -In the photoelectric effect, the incident photon is absorbed by an atomic -electron, which is then emitted from the :math:`i`-th shell with kinetic energy - -.. math:: - :label: photoelectron-kinetic-energy - - E_{-} = E - E_{b,i}. - -Photoelectric emission is only possible when the photon energy exceeds the -binding energy of the shell. These binding energies are often referred to as -edge energies because the otherwise continuously decreasing cross section has -discontinuities at these points, creating the characteristic sawtooth shape. -The photoelectric effect dominates at low energies and is more important for -heavier elements. - -When simulating the photoelectric effect, the first step is to sample the -electron shell. The shell :math:`i` where the ionization occurs can be -considered a discrete random variable with probability mass function - -.. math:: - :label: photoelectron-shell-pdf - - p_i = \frac{\sigma_{\text{pe},i}}{\sigma_{\text{pe}}}, - -where :math:`\sigma_{\text{pe},i}` is the cross section of the :math:`i`-th -shell, and the total photoelectric cross section of the atom, -:math:`\sigma_{\text{pe}}`, is the sum over the shell cross sections. Once the -shell has been sampled, the energy of the photoelectron is calculated using -:eq:`photoelectron-kinetic-energy`. - -To determine the direction of the photoelectron, we implement the method -described in Kaltiaisenaho_, which models the angular distribution of the -photoelectrons using the K-shell cross section derived by Sauter (K-shell -electrons are the most tightly bound, and they contribute the most to -:math:`\sigma_{\text{pe}}`). The non-relativistic Sauter distribution for -unpolarized photons can be approximated as - -.. math:: - :label: sauter - - \frac{d\sigma_{\text{pe}}}{d\mu_{-}} \propto - \frac{1 - \mu_{-}^2}{(1 - \beta_{-} \mu_{-})^4}, - -where :math:`\beta_{-}` is the ratio of the velocity of the electron to the -speed of light, - -.. math:: - :label: beta-2 - - \beta_{-} = \frac{\sqrt{(E_{-}(E_{-} + 2m_e c^2)}}{E_{-} + m_e c^2}. - -To sample :math:`\mu_{-}` from the Sauter distribution, we first express -:eq:`sauter` in the form: - -.. math:: - :label: photoelectron-mu-pdf - - f(\mu_{-}) = \frac{3}{2} \psi(\mu_{-}) g(\mu_{-}), - -where - -.. math:: - :label: mu-pdf-factors - - \begin{aligned} - \psi(\mu_{-}) &= \frac{(1 - \beta_{-}^2)(1 - \mu_{-}^2)}{(1 - - \beta_{-}\mu_{-})^2}, \\ - g(\mu_{-}) &= \frac{1 - \beta_{-}^2}{2 (1 - \beta_{-}\mu_{-})^2}. - \end{aligned} - -In the interval :math:`[-1, 1]`, :math:`g(\mu_{-})` is a normalized PDF and -:math:`\psi(\mu_{-})` satisfies the condition :math:`0 < \psi(\mu_{-}) < 1`. -The following algorithm can now be used to sample :math:`\mu_{-}`: - -1. Using the inverse transform method, sample :math:`\mu_{-}` from - :math:`g(\mu_{-})` using the sampling formula - - .. math:: - - \mu_{-} = \frac{2\xi_1 + \beta_{-} - 1}{2\beta_{-}\xi_1 - \beta_{-} + 1}. - -2. If :math:`\xi_2 \le \psi(\mu_{-})`, accept :math:`\mu_{-}`. Otherwise, - repeat the sampling from step 1. - -The azimuthal angle is sampled uniformly on :math:`[0, 2\pi)`. - -The atom is left in an excited state with a vacancy in the :math:`i`-th shell -and decays to its ground state through a cascade of transitions that produce -fluorescent photons and Auger electrons. - -Pair Production ---------------- - -In electron-positron pair production, a photon is absorbed in the vicinity of -an atomic nucleus or an electron and an electron and positron are created. Pair -production is the dominant interaction with matter at high photon energies and -is more important for high-Z elements. When it takes place in the field of a -nucleus, energy is essentially conserved among the incident photon and the -resulting charged particles. Therefore, in order for pair production to occur, -the photon energy must be greater than the sum of the rest mass energies of the -electron and positron, i.e., :math:`E_{\text{threshold,pp}} = 2 m_e c^2 = -1.022` MeV. - -The photon can also interact in the field of an atomic electron. This process -is referred to as "triplet production" because the target electron is ejected -from the atom and three charged particles emerge from the interaction. In this -case, the recoiling electron also absorbs some energy, so the energy threshold -for triplet production is greater than that of pair production from atomic -nuclei, with :math:`E_{\text{threshold,tp}} = 4 m_e c^2 = 2.044` MeV. The ratio -of the triplet production cross section to the pair production cross section is -approximately 1/Z, so triplet production becomes increasingly unimportant for -high-Z elements. Though it can be significant in lighter elements, the momentum -of the recoil electron becomes negligible in the energy regime where pair -production dominates. For our purposes, it is a good approximation to treat -triplet production as pair production and only simulate the electron-positron -pair. - -Accurately modeling the creation of electron-positron pair is important because -the charged particles can go on to lose much of their energy as bremsstrahlung -radiation, and the subsequent annihilation of the positron with an electron -produces two additional photons. We sample the energy and direction of the -charged particles using a semiempirical model described in Salvat_. The -Bethe-Heitler differential cross section, given by - -.. math:: - :label: bethe-heitler - - \frac{d\sigma_{\text{pp}}}{d\epsilon} = \alpha r_e^2 Z^2 - \left[ (\epsilon^2 + (1-\epsilon)^2) (\Phi_1 - 4f_C) + - \frac{2}{3}\epsilon(1-\epsilon)(\Phi_2 - 4f_C) \right], - -is used as a starting point, where :math:`\alpha` is the fine structure -constant, :math:`f_C` is the Coulomb correction function, :math:`\Phi_1` and -:math:`\Phi_2` are screening functions, and :math:`\epsilon = (E_{-} + m_e -c^2)/E` is the electron reduced energy (i.e., the fraction of the photon energy -given to the electron). :math:`\epsilon` can take values between -:math:`\epsilon_{\text{min}} = k^{-1}` (when the kinetic energy of the electron -is zero) and :math:`\epsilon_{\text{max}} = 1 - k^{-1}` (when the kinetic -energy of the positron is zero). - -The Coulomb correction, given by - -.. math:: - :label: coulomb-correction - - \begin{aligned} - f_C = \alpha^{2}Z^{2} \big[&(1 + \alpha^{2}Z^{2})^{-1} + 0.202059 - - 0.03693\alpha^{2}Z^{2} + 0.00835\alpha^{4}Z^{4} \\ - &- 0.00201\alpha^{6}Z^{6} + 0.00049\alpha^{8}Z^{8} - - 0.00012\alpha^{10}Z^{10} + 0.00003\alpha^{12}Z^{12}\big] - \end{aligned} - -is introduced to correct for the fact that the Bethe-Heitler differential cross -section was derived using the Born approximation, which treats the Coulomb -interaction as a small perturbation. - -The screening functions :math:`\Phi_1` and :math:`\Phi_2` account for the -screening of the Coulomb field of the atomic nucleus by outer electrons. Since -they are given by integrals which include the atomic form factor, they must be -computed numerically for a realistic form factor. However, by assuming -exponential screening and using a simplified form factor, analytical -approximations of the screening functions can be derived: - -.. math:: - :label: screening-functions - - \begin{aligned} - \Phi_1 &= 2 - 2\ln(1 + b^2) - 4b\arctan(b^{-1}) + 4\ln(Rm_{e}c/\hbar) \\ - \Phi_2 &= \frac{4}{3} - 2\ln(1 + b^2) + 2b^2 \left[ 4 - 4b\arctan(b^{-1}) - - 3\ln(1 + b^{-2}) \right] + 4\ln(Rm_{e}c/\hbar) - \end{aligned} - -where - -.. math:: - :label: b - - b = \frac{Rm_{e}c}{2k\epsilon(1 - \epsilon)\hbar}. - -and :math:`R` is the screening radius. - -The differential cross section in :eq:`bethe-heitler` with the approximations -described above will not be accurate at low energies: the lower boundary of -:math:`\epsilon` will be shifted above :math:`\epsilon_{\text{min}}` and the -upper boundary of :math:`\epsilon` will be shifted below -:math:`\epsilon_{\text{max}}`. To offset this behavior, a correcting factor -:math:`F_0(k, Z)` is used: - -.. math:: - :label: correcting-factor - - \begin{aligned} - F_0(k, Z) =~& (0.1774 + 12.10\alpha Z - 11.18\alpha^{2}Z^{2})(2/k)^{1/2} \\ - &+ (8.523 + 73.26\alpha Z - 44.41\alpha^{2}Z^{2})(2/k) \\ - &- (13.52 + 121.1\alpha Z - 96.41\alpha^{2}Z^{2})(2/k)^{3/2} \\ - &+ (8.946 + 62.05\alpha Z - 63.41\alpha^{2}Z^{2})(2/k)^{2}. - \end{aligned} - -To aid sampling, the differential cross section used to sample :math:`\epsilon` -(minus the normalization constant) can now be expressed in the form - -.. math:: - :label: pp-pdf - - \frac{d\sigma_{\text{pp}}}{d\epsilon} = - u_1 \frac{\phi_1(\epsilon)}{\phi_1(1/2)} \pi_1(\epsilon) - + u_2 \frac{\phi_2(\epsilon)}{\phi_2(1/2)} \pi_2(\epsilon) - -where - -.. math:: - :label: u - - \begin{aligned} - u_1 &= \frac{2}{3} \left(\frac{1}{2} - \frac{1}{k}\right)^2 \phi_1(1/2), \\ - u_2 &= \phi_2(1/2), - \end{aligned} - -.. math:: - :label: phi - - \begin{aligned} - \phi_1(\epsilon) &= \frac{1}{2}(3\Phi_1 - \Phi_2) - 4f_{C}(Z) + F_0(k, Z), \\ - \phi_2(\epsilon) &= \frac{1}{4}(3\Phi_1 + \Phi_2) - 4f_{C}(Z) + F_0(k, Z), - \end{aligned} - -and - -.. math:: - :label: pi - - \begin{aligned} - \pi_1(\epsilon) &= \frac{3}{2} \left(\frac{1}{2} - \frac{1}{k}\right)^{-3} - \left(\frac{1}{2} - \epsilon\right)^2, \\ - \pi_2(\epsilon) &= \frac{1}{2} \left(\frac{1}{2} - \frac{1}{k}\right)^{-1}. - \end{aligned} - -The functions in :eq:`phi` are non-negative and maximum at :math:`\epsilon = -1/2`. In the interval :math:`(\epsilon_{\text{min}}, \epsilon_{\text{max}})`, -the functions in :eq:`pi` are normalized PDFs and -:math:`\phi_i(\epsilon)/\phi_i(1/2)` satisfies the condition :math:`0 < -\phi_i(\epsilon)/\phi_i(1/2) < 1`. The following algorithm can now be used to -sample the reduced electron energy :math:`\epsilon`: - -1. Sample :math:`i` according to the point probabilities - :math:`p(i=1) = u_1/(u_1 + u_2)` and :math:`p(i=2) = u_2/(u_1 + u_2)`. - -2. Using the inverse transform method, sample :math:`\epsilon` from - :math:`\pi_i(\epsilon)` using the sampling formula - - .. math:: - - \begin{aligned} - \epsilon &= \frac{1}{2} + \left(\frac{1}{2} - \frac{1}{k}\right) - (2\xi_1 - 1)^{1/3} ~~~~&\text{if}~~ i = 1 \\ - \epsilon &= \frac{1}{k} + \left(\frac{1}{2} - - \frac{1}{k}\right) 2\xi_1 ~~~~&\text{if}~~ i = 2. - \end{aligned} - -3. If :math:`\xi_2 \le \phi_i(\epsilon)/\phi_i(1/2)`, accept - :math:`\epsilon`. Otherwise, repeat the sampling from step 1. - -Because charged particles have a much smaller range than the mean free path of -photons and because they immediately undergo multiple scattering events which -randomize their direction, it is sufficient to use a simplified model to sample -the direction of the electron and positron. The cosines of the polar angles are -sampled using the leading order term of the Sauter–Gluckstern–Hull -distribution, - -.. math:: - :label: sauter-gluckstern-hull - - p(\mu_{\pm}) = C(1 - \beta_{\pm}\mu_{\pm})^{-2}, - -where :math:`C` is a normalization constant and :math:`\beta_{\pm}` is the -ratio of the velocity of the charged particle to the speed of light given in -:eq:`beta-2`. - -The inverse transform method is used to sample :math:`\mu_{-}` and -:math:`\mu_{+}` from :eq:`sauter-gluckstern-hull`, using the sampling formula - -.. math:: - :label: sample-mu - - \mu_{\pm} = \frac{2\xi - 1 + \beta_{\pm}}{(2\xi - 1)\beta_{\pm} + 1}. - -The azimuthal angles for the electron and positron are sampled independently -and uniformly on :math:`[0, 2\pi)`. - -------------------- -Secondary Processes -------------------- - -New photons may be produced in secondary processes related to the main photon -interactions discussed above. A Compton-scattered photon transfers a portion of -its energy to the kinetic energy of the recoil electron, which in turn may lose -the energy as bremsstrahlung radiation. The vacancy left in the shell by the -ejected electron is filled through atomic relaxation, creating a shower of -electrons and fluorescence photons. Similarly, the vacancy left by the electron -emitted in the photoelectric effect is filled through atomic relaxation. Pair -production generates an electron and a positron, both of which can emit -bremsstrahlung radiation before the positron eventually collides with an -electron, resulting in annihilation of the pair and the creation of two -additional photons. - -Atomic Relaxation ------------------ - -When an electron is ejected from an atom and a vacancy is left in an inner -shell, an electron from a higher energy level will fill the vacancy. This -results in either a radiative transition, in which a photon with a -characteristic energy (fluorescence photon) is emitted, or non-radiative -transition, in which an electron from a shell that is farther out (Auger -electron) is emitted. If a non-radiative transition occurs, the new vacancy is -filled in the same manner, and as the process repeats a shower of photons and -electrons can be produced. - -The energy of a fluorescence photon is the equal to the energy difference -between the transition states, i.e., - -.. math:: - :label: fluorescence-photon-energy - - E = E_{b,v} - E_{b,i}, - -where :math:`E_{b,v}` is the binding energy of the vacancy shell and -:math:`E_{b,i}` is the binding energy of the shell from which the electron -transitioned. The energy of an Auger electron is given by - -.. math:: - :label: auger-electron-energy - - E_{-} = E_{b,v} - E_{b,i} - E_{b,a}, - -where :math:`E_{b,a}` is the binding energy of the shell from which the Auger -electron is emitted. While Auger electrons are low-energy so their range and -bremsstrahlung yield is small, fluorescence photons can travel far before -depositing their energy, so the relaxation process should be modeled in detail. - -Transition energies and probabilities are needed for each subshell to simulate -atomic relaxation. Starting with the initial shell vacancy, the following -recursive algorithm is used to fill vacancies and create fluorescence photons -and Auger electrons: - -1. If there are no transitions for the vacancy shell, create a fluorescence - photon assuming it is from a captured free electron and terminate. - -2. Sample a transition using the transition probabilities for the vacancy - shell as the probability mass function. - -3. Create either a fluorescence photon or Auger electron, sampling the - direction of the particle isotropically. - -4. If a non-radiative transition occurred, repeat from step 1 for the vacancy - left by the emitted Auger electron. - -5. Repeat from step 1 for vacancy left by the transition electron. - -Electron-Positron Annihilation ------------------------------- - -When a positron collides with an electron, both particles are annihilated and -generally two photons with equal energy are created. If the kinetic energy of -the positron is high enough, the two photons can have different energies, and -the higher-energy photon is emitted preferentially in the direction of flight -of the positron. It is also possible to produce a single photon if the -interaction occurs with a bound electron, and in some cases three (or, rarely, -even more) photons can be emitted. However, the annihilation cross section is -largest for low-energy positrons, and as the positron energy decreases, the -angular distribution of the emitted photons becomes isotropic. - -In OpenMC, we assume the most likely case in which a low-energy positron (which -has already lost most of its energy to bremsstrahlung radiation) interacts with -an electron which is free and at rest. Two photons with energy equal to the -electron rest mass energy :math:`m_e c^2 = 0.511` MeV are emitted isotropically -in opposite directions. - -Bremsstrahlung --------------- - -When a charged particle is decelerated in the field of an atom, some of its -kinetic energy is converted into electromagnetic radiation known as -bremsstrahlung, or 'braking radiation'. In each event, an electron or positron -with kinetic energy :math:`T` generates a photon with an energy :math:`E` -between :math:`0` and :math:`T`. Bremsstrahlung is described by a cross section -that is differential in photon energy, in the direction of the emitted photon, -and in the final direction of the charged particle. However, in Monte Carlo -simulations it is typical to integrate over the angular variables to obtain a -single differential cross section with respect to photon energy, which is often -expressed in the form - -.. math:: - :label: bremsstrahlung-dcs - - \frac{d\sigma_{\text{br}}}{dE} = \frac{Z^2}{\beta^2} \frac{1}{E} - \chi(Z, T, \kappa), - -where :math:`\kappa = E/T` is the reduced photon energy and :math:`\chi(Z, T, -\kappa)` is the scaled bremsstrahlung cross section, which is experimentally -measured. - -Because electrons are attracted to atomic nuclei whereas positrons are -repulsed, the cross section for positrons is smaller, though it approaches that -of electrons in the high energy limit. To obtain the positron cross section, we -multiply :eq:`bremsstrahlung-dcs` by the :math:`\kappa`-independent factor used -in Salvat_, - -.. math:: - :label: positron-factor - - \begin{aligned} - F_{\text{p}}(Z,T) = - & 1 - \text{exp}(-1.2359\times 10^{-1}t + 6.1274\times 10^{-2}t^2 - 3.1516\times 10^{-2}t^3 \\ - & + 7.7446\times 10^{-3}t^4 - 1.0595\times 10^{-3}t^5 + 7.0568\times 10^{-5}t^6 \\ - & - 1.8080\times 10^{-6}t^7), - \end{aligned} - -where - -.. math:: - :label: positron-factor-t - - t = \ln\left(1 + \frac{10^6}{Z^2}\frac{T}{\text{m}_\text{e}c^2} \right). - -:math:`F_{\text{p}}(Z,T)` is the ratio of the radiative stopping powers for -positrons and electrons. Stopping power describes the average energy loss per -unit path length of a charged particle as it passes through matter: - -.. math:: - :label: stopping-power - - -\frac{dT}{ds} = n \int E \frac{d\sigma}{dE} dE \equiv S(T), - -where :math:`n` is the number density of the material and :math:`d\sigma/dE` is -the cross section differential in energy loss. The total stopping power -:math:`S(T)` can be separated into two components: the radiative stopping -power :math:`S_{\text{rad}}(T)`, which refers to energy loss due to -bremsstrahlung, and the collision stopping power :math:`S_{\text{col}}(T)`, -which refers to the energy loss due to inelastic collisions with bound -electrons in the material that result in ionization and excitation. The -radiative stopping power for electrons is given by - -.. math:: - :label: radiative-stopping-power - - S_{\text{rad}}(T) = n \frac{Z^2}{\beta^2} T \int_0^1 \chi(Z,T,\kappa) - d\kappa. - - -To obtain the radiative stopping power for positrons, -:eq:`radiative-stopping-power` is multiplied by :eq:`positron-factor`. - -While the models for photon interactions with matter described above can safely -assume interactions occur with free atoms, sampling the target atom based on -the macroscopic cross sections, molecular effects cannot necessarily be -disregarded for charged particle treatment. For compounds and mixtures, the -bremsstrahlung cross section is calculated using Bragg's additivity rule as - -.. math:: - :label: material-bremsstrahlung-dcs - - \frac{d\sigma_{\text{br}}}{dE} = \frac{1}{\beta^2 E} \sum_i \gamma_i Z^2_i - \chi(Z_i, T, \kappa), - -where the sum is over the constituent elements and :math:`\gamma_i` is the -atomic fraction of the :math:`i`-th element. Similarly, the radiative stopping -power is calculated using Bragg's additivity rule as - -.. math:: - :label: material-radiative-stopping-power - - S_{\text{rad}}(T) = \sum_i w_i S_{\text{rad},i}(T), - -where :math:`w_i` is the mass fraction of the :math:`i`-th element and -:math:`S_{\text{rad},i}(T)` is found for element :math:`i` using -:eq:`radiative-stopping-power`. The collision stopping power, however, is a -function of certain quantities such as the mean excitation energy :math:`I` and -the density effect correction :math:`\delta_F` that depend on molecular -properties. These quantities cannot simply be summed over constituent elements -in a compound, but should instead be calculated for the material. The Bethe -formula can be used to find the collision stopping power of the material: - -.. math:: - :label: material-collision-stopping-power - - S_{\text{col}}(T) = \frac{2 \pi r_e^2 m_e c^2}{\beta^2} N_A \frac{Z}{A_M} - [\ln(T^2/I^2) + \ln(1 + \tau/2) + F(\tau) - \delta_F(T)], - -where :math:`N_A` is Avogadro's number, :math:`A_M` is the molar mass, -:math:`\tau = T/m_e`, and :math:`F(\tau)` depends on the particle type. For -electrons, - -.. math:: - :label: F-electron - - F_{-}(\tau) = (1 - \beta^2)[1 + \tau^2/8 - (2\tau + 1) \ln2], - -while for positrons - -.. math:: - :label: F-positron - - F_{+}(\tau) = 2\ln2 - (\beta^2/12)[23 + 14/(\tau + 2) + 10/(\tau + 2)^2 + - 4/(\tau + 2)^3]. - -The density effect correction :math:`\delta_F` takes into account the reduction -of the collision stopping power due to the polarization of the material the -charged particle is passing through by the electric field of the particle. -It can be evaluated using the method described by Sternheimer_, where the -equation for :math:`\delta_F` is - -.. math:: - :label: density-effect-correction - - \delta_F(\beta) = \sum_{i=1}^n f_i \ln[(l_i^2 + l^2)/l_i^2] - - l^2(1-\beta^2). - -Here, :math:`f_i` is the oscillator strength of the :math:`i`-th transition, -given by :math:`f_i = n_i/Z`, where :math:`n_i` is the number of electrons in -the :math:`i`-th subshell. The frequency :math:`l` is the solution of the -equation - -.. math:: - :label: density-effect-l - - \frac{1}{\beta^2} - 1 = \sum_{i=1}^{n} \frac{f_i}{\bar{\nu}_i^2 + l^2}, - -where :math:`\bar{v}_i` is defined as - -.. math:: - :label: density-effect-nubar - - \bar{\nu}_i = h\nu_i \rho / h\nu_p. - -The plasma energy :math:`h\nu_p` of the medium is given by - -.. math:: - :label: plasma-frequency - - h\nu_p = \sqrt{\frac{(hc)^2 r_e \rho_m N_A Z}{\pi A}}, - -where :math:`A` is the atomic weight and :math:`\rho_m` is the density of the -material. In :eq:`density-effect-nubar`, :math:`h\nu_i` is the oscillator -energy, and :math:`\rho` is an adjustment factor introduced to give agreement -between the experimental values of the oscillator energies and the mean -excitation energy. The :math:`l_i` in :eq:`density-effect-correction` are -defined as - -.. math:: - :label: density-effect-li - - \begin{aligned} - l_i &= (\bar{\nu}_i^2 + 2/3f_i)^{1/2} ~~~~&\text{for}~~ \bar{\nu}_i > 0 \\ - l_n &= f_n^{1/2} ~~~~&\text{for}~~ \bar{\nu}_n = 0, - \end{aligned} - -where the second case applies to conduction electrons. For a conductor, -:math:`f_n` is given by :math:`n_c/Z`, where :math:`n_c` is the effective -number of conduction electrons, and :math:`v_n = 0`. The adjustment factor -:math:`\rho` is determined using the equation for the mean excitation energy: - -.. math:: - :label: mean-excitation-energy - - \ln I = \sum_{i=1}^{n-1} f_i \ln[(h\nu_i\rho)^2 + 2/3f_i(h\nu_p)^2]^{1/2} + - f_n \ln (h\nu_pf_n^{1/2}). - -.. _ttb: - -Thick-Target Bremsstrahlung Approximation -+++++++++++++++++++++++++++++++++++++++++ - -Since charged particles lose their energy on a much shorter distance scale than -neutral particles, not much error should be introduced by neglecting to -transport electrons. However, the bremsstrahlung emitted from high energy -electrons and positrons can travel far from the interaction site. Thus, even -without a full electron transport mode it is necessary to model bremsstrahlung. -We use a thick-target bremsstrahlung (TTB) approximation based on the models in -Salvat_ and Kaltiaisenaho_ for generating bremsstrahlung photons, which assumes -the charged particle loses all its energy in a single homogeneous material -region. - -To model bremsstrahlung using the TTB approximation, we need to know the number -of photons emitted by the charged particle and the energy distribution of the -photons. These quantities can be calculated using the continuous slowing down -approximation (CSDA). The CSDA assumes charged particles lose energy -continuously along their trajectory with a rate of energy loss equal to the -total stopping power, ignoring fluctuations in the energy loss. The -approximation is useful for expressing average quantities that describe how -charged particles slow down in matter. For example, the CSDA range approximates -the average path length a charged particle travels as it slows to rest: - -.. math:: - :label: csda-range - - R(T) = \int^T_0 \frac{dT'}{S(T')}. - -Actual path lengths will fluctuate around :math:`R(T)`. The average number of -photons emitted per unit path length is given by the inverse bremsstrahlung -mean free path: - -.. math:: - :label: inverse-bremsstrahlung-mfp - - \lambda_{\text{br}}^{-1}(T,E_{\text{cut}}) - = n\int_{E_{\text{cut}}}^T\frac{d\sigma_{\text{br}}}{dE}dE - = n\frac{Z^2}{\beta^2}\int_{\kappa_{\text{cut}}}^1\frac{1}{\kappa} - \chi(Z,T,\kappa)d\kappa. - -The lower limit of the integral in :eq:`inverse-bremsstrahlung-mfp` is non-zero -because the bremsstrahlung differential cross section diverges for small photon -energies but is finite for photon energies above some cutoff energy -:math:`E_{\text{cut}}`. The mean free path -:math:`\lambda_{\text{br}}^{-1}(T,E_{\text{cut}})` is used to calculate the -photon number yield, defined as the average number of photons emitted with -energy greater than :math:`E_{\text{cut}}` as the charged particle slows down -from energy :math:`T` to :math:`E_{\text{cut}}`. The photon number yield is -given by - -.. math:: - :label: photon-number-yield - - Y(T,E_{\text{cut}}) = \int^{R(T)}_{R(E_{\text{cut}})} - \lambda_{\text{br}}^{-1}(T',E_{\text{cut}})ds = \int_{E_{\text{cut}}}^T - \frac{\lambda_{\text{br}}^{-1}(T',E_{\text{cut}})}{S(T')}dT'. - -:math:`Y(T,E_{\text{cut}})` can be used to construct the energy spectrum of -bremsstrahlung photons: the number of photons created with energy between -:math:`E_1` and :math:`E_2` by a charged particle with initial kinetic energy -:math:`T` as it comes to rest is given by :math:`Y(T,E_1) - Y(T,E_2)`. - -To simulate the emission of bremsstrahlung photons, the total stopping power -and bremsstrahlung differential cross section for positrons and electrons must -be calculated for a given material using :eq:`material-bremsstrahlung-dcs` and -:eq:`material-radiative-stopping-power`. These quantities are used to build the -tabulated bremsstrahlung energy PDF and CDF for that material for each incident -energy :math:`T_k` on the energy grid. The following algorithm is then applied -to sample the photon energies: - -1. For an incident charged particle with energy :math:`T`, sample the number of - emitted photons as - - .. math:: - - N = \lfloor Y(T,E_{\text{cut}}) + \xi_1 \rfloor. - -2. Rather than interpolate the PDF between indices :math:`k` and :math:`k+1` - for which :math:`T_k < T < T_{k+1}`, which is computationally expensive, use - the composition method and sample from the PDF at either :math:`k` or - :math:`k+1`. Using linear interpolation on a logarithmic scale, the PDF can - be expressed as - - .. math:: - - p_{\text{br}}(T,E) = \pi_k p_{\text{br}}(T_k,E) + \pi_{k+1} - p_{\text{br}}(T_{k+1},E), - - where the interpolation weights are - - .. math:: - - \pi_k = \frac{\ln T_{k+1} - \ln T}{\ln T_{k+1} - \ln T_k},~~~ - \pi_{k+1} = \frac{\ln T - \ln T_k}{\ln T_{k+1} - \ln T_k}. - - Sample either the index :math:`i = k` or :math:`i = k+1` according to the - point probabilities :math:`\pi_{k}` and :math:`\pi_{k+1}`. - -3. Determine the maximum value of the CDF :math:`P_{\text{br,max}}`. - -3. Sample the photon energies using the inverse transform method with the - tabulated CDF :math:`P_{\text{br}}(T_i, E)` i.e., - - .. math:: - - E = E_j \left[ (1 + a_j) \frac{\xi_2 P_{\text{br,max}} - - P_{\text{br}}(T_i, E_j)} {E_j p_{\text{br}}(T_i, E_j)} + 1 - \right]^{\frac{1}{1 + a_j}} - - where the interpolation factor :math:`a_j` is given by - - .. math:: - - a_j = \frac{\ln p_{\text{br}}(T_i,E_{j+1}) - \ln p_{\text{br}}(T_i,E_j)} - {\ln E_{j+1} - \ln E_j} - - and :math:`P_{\text{br}}(T_i, E_j) \le \xi_2 P_{\text{br,max}} \le - P_{\text{br}}(T_i, E_{j+1})`. - -We ignore the range of the electron or positron, i.e., the bremsstrahlung -photons are produced in the same location that the charged particle was -created. The direction of the photons is assumed to be the same as the -direction of the incident charged particle, which is a reasonable approximation -at higher energies when the bremsstrahlung radiation is emitted at small -angles. - ------------------ -Photon Production ------------------ - -In coupled neutron-photon transport, a source neutron is tracked, and photons -produced from neutron reactions are transported after the neutron's history has -terminated. Since these secondary photons form the photon source for the -problem, it is important to correctly describe their energy and angular -distributions as the accuracy of the calculation relies on the accuracy of this -source. The photon production cross section for a particular reaction :math:`i` -and incident neutron energy :math:`E` is defined as - -.. math:: - :label: photon-production-xs - - \sigma_{\gamma, i}(E) = y_i(E)\sigma_i(E), - -where :math:`y_i(E)` is the photon yield corresponding to an incident neutron -reaction having cross section :math:`\sigma_i(E)`. - -The yield of photons during neutron transport is determined as the sum of the -photon yields from each individual reaction. In OpenMC, production of photons -is treated in an average sense. That is, the total photon production cross -section is used at a collision site to determine how many photons to produce -rather than the photon production from the reaction that actually took place. -This is partly done for convenience but also because the use of variance -reduction techniques such as implicit capture make it difficult in practice to -directly sample photon production from individual reactions. - -In OpenMC, secondary photons are created after a nuclide has been sampled in a -neutron collision. The expected number of photons produced is - -.. math:: - :label: expected-number-photons - - n = w\frac{\sigma_{\gamma}(E)}{\sigma_T(E)}, - -where :math:`w` is the weight of the neutron, :math:`\sigma_{\gamma}` is the -photon production cross section for the sampled nuclide, and :math:`\sigma_T` -is the total cross section for the nuclide. :math:`\lfloor n \rfloor` photons -are created with an additional photon produced with probability :math:`n - -\lfloor n \rfloor`. Next, a reaction is sampled for each secondary photon. The -probability of sampling the :math:`i`-th reaction is given by -:math:`\sigma_{\gamma, i}(E)/\sum_j\sigma_{\gamma, j}(E)`, where -:math:`\sum_j\sigma_{\gamma, j} = \sigma_{\gamma}` is the total photon -production cross section. The secondary angle and energy distributions -associated with the reaction are used to sample the angle and energy of the -emitted photon. - -.. _Koblinger: https://doi.org/10.13182/NSE75-A26663 - -.. _anomalous scattering: http://pd.chem.ucl.ac.uk/pdnn/diff1/anomscat.htm - -.. _Kahn's rejection method: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/aecu-3259_kahn.pdf - -.. _Klein-Nishina: https://en.wikipedia.org/wiki/Klein%E2%80%93Nishina_formula - -.. _LA-UR-04-0487: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-04-0487.pdf - -.. _LA-UR-04-0488: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-04-0488.pdf - -.. _Kaltiaisenaho: https://aaltodoc.aalto.fi/bitstream/handle/123456789/21004/master_Kaltiaisenaho_Toni_2016.pdf - -.. _Salvat: http://www.oecd-nea.org/globalsearch/download.php?doc=77434 - -.. _Sternheimer: https://doi.org/10.1103/PhysRevB.26.6067 diff --git a/docs/source/methods/random_numbers.rst b/docs/source/methods/random_numbers.rst deleted file mode 100644 index 0cefc9156..000000000 --- a/docs/source/methods/random_numbers.rst +++ /dev/null @@ -1,72 +0,0 @@ -.. _methods_random_numbers: - -======================== -Random Number Generation -======================== - -In order to sample probability distributions, one must be able to produce random -numbers. The standard technique to do this is to generate numbers on the -interval :math:`[0,1)` from a deterministic sequence that has properties that -make it appear to be random, e.g. being uniformly distributed and not exhibiting -correlation between successive terms. Since the numbers produced this way are -not truly "random" in a strict sense, they are typically referred to as -pseudorandom numbers, and the techniques used to generate them are pseudorandom -number generators (PRNGs). Numbers sampled on the unit interval can then be -transformed for the purpose of sampling other continuous or discrete probability -distributions. - ------------------------------- -Linear Congruential Generators ------------------------------- - -There are a great number of algorithms for generating random numbers. One of the -simplest and commonly used algorithms is called a `linear congruential -generator`_. We start with a random number *seed* :math:`\xi_0` and a sequence -of random numbers can then be generated using the following recurrence relation: - -.. math:: - :label: lcg - - \xi_{i+1} = g \xi_i + c \mod M - -where :math:`g`, :math:`c`, and :math:`M` are constants. The choice of these -constants will have a profound effect on the quality and performance of the -generator, so they should not be chosen arbitrarily. As Donald Knuth stated in -his seminal work *The Art of Computer Programming*, "random numbers should not -be generated with a method chosen at random. Some theory should be used." -Typically, :math:`M` is chosen to be a power of two as this enables :math:`x -\mod M` to be performed using the bitwise AND operator with a bit mask. The -constants for the linear congruential generator used by default in OpenMC are -:math:`g = 2806196910506780709`, :math:`c = 1`, and :math:`M = 2^{63}` (see -`L'Ecuyer`_). - -Skip-ahead Capability ---------------------- - -One of the important capabilities for a random number generator is to be able to -skip ahead in the sequence of random numbers. Without this capability, it would -be very difficult to maintain reproducibility in a parallel calculation. If we -want to skip ahead :math:`N` random numbers and :math:`N` is large, the cost of -sampling :math:`N` random numbers to get to that position may be prohibitively -expensive. Fortunately, algorithms have been developed that allow us to skip -ahead in :math:`O(\log_2 N)` operations instead of :math:`O(N)`. One algorithm -to do so is described in a paper by Brown_. This algorithm relies on the following -relationship: - -.. math:: - :label: lcg-skipahead - - \xi_{i+k} = g^k \xi_i + c \frac{g^k - 1}{g - 1} \mod M - -Note that equation :eq:`lcg-skipahead` has the same general form as equation :eq:`lcg`, so -the idea is to determine the new multiplicative and additive constants in -:math:`O(\log_2 N)` operations. - -.. only:: html - - .. rubric:: References - - -.. _L'Ecuyer: https://doi.org/10.1090/S0025-5718-99-00996-5 -.. _Brown: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/anl-rn-arb-stride.pdf -.. _linear congruential generator: https://en.wikipedia.org/wiki/Linear_congruential_generator diff --git a/docs/source/methods/tallies.rst b/docs/source/methods/tallies.rst deleted file mode 100644 index d67584622..000000000 --- a/docs/source/methods/tallies.rst +++ /dev/null @@ -1,515 +0,0 @@ -.. _methods_tallies: - -======= -Tallies -======= - -Note that the methods discussed in this section are written specifically for -continuous-energy mode but equivalent apply to the multi-group mode if the -particle's energy is replaced with the particle's group - ------------------- -Filters and Scores ------------------- - -The tally capability in OpenMC takes a similar philosophy as that employed in -the MC21_ Monte Carlo code to give maximum flexibility in specifying tallies -while still maintaining scalability. Any tally in a Monte Carlo simulation can -be written in the following form: - -.. math:: - :label: tally-integral - - X = \underbrace{\int d\mathbf{r} \int d\mathbf{\Omega} \int - dE}_{\text{filters}} \underbrace{f(\mathbf{r}, \mathbf{\Omega}, - E)}_{\text{scores}} \psi (\mathbf{r}, \mathbf{\Omega}, E) - - -A user can specify one or more filters which identify which regions of phase -space should score to a given tally (the limits of integration as shown in -equation :eq:`tally-integral`) as well as the scoring function (:math:`f` in -equation :eq:`tally-integral`). For example, if the desired tally was the -:math:`(n,\gamma)` reaction rate in a fuel pin, the filter would specify the -cell which contains the fuel pin and the scoring function would be the radiative -capture macroscopic cross section. The following quantities can be scored in -OpenMC: flux, total reaction rate, scattering reaction rate, neutron production -from scattering, higher scattering moments, :math:`(n,xn)` reaction rates, -absorption reaction rate, fission reaction rate, neutron production rate from -fission, and surface currents. The following variables can be used as filters: -universe, material, cell, birth cell, surface, mesh, pre-collision energy, -post-collision energy, polar angle, azimuthal angle, and the cosine of the -change-in-angle due to a scattering event. - -With filters for pre- and post-collision energy and scoring functions for -scattering and fission production, it is possible to use OpenMC to generate -cross sections with user-defined group structures. These multigroup cross -sections can subsequently be used in deterministic solvers such as coarse mesh -finite difference (CMFD) diffusion. - ------------------------------- -Using Maps for Filter-Matching ------------------------------- - -Some Monte Carlo codes suffer severe performance penalties when tallying a large -number of quantities. Care must be taken to ensure that a tally system scales -well with the total number of tally bins. In OpenMC, a mapping technique is used -that allows for a fast determination of what tally/bin combinations need to be -scored to a given particle's phase space coordinates. For each discrete filter -variable, a list is stored that contains the tally/bin combinations that could -be scored to for each value of the filter variable. If a particle is in cell -:math:`n`, the mapping would identify what tally/bin combinations specify cell -:math:`n` for the cell filter variable. In this manner, it is not necessary to -check the phase space variables against each tally. Note that this technique -only applies to discrete filter variables and cannot be applied to energy, -angle, or change-in-angle bins. For these filters, it is necessary to perform -a binary search on the specified energy grid. - ------------------------------------------ -Volume-Integrated Flux and Reaction Rates ------------------------------------------ - -One quantity we may wish to compute during the course of a Monte Carlo -simulation is the flux or a reaction rate integrated over a finite volume. The -volume may be a particular cell, a collection of cells, or the entire -geometry. There are various methods by which we can estimate reaction rates - -Analog Estimator ----------------- - -The analog estimator is the simplest type of estimator for reaction rates. The -basic idea is that we simply count the number of actual reactions that take -place and use that as our estimate for the reaction rate. This can be written -mathematically as - -.. math:: - :label: analog-estimator - - R_x = \frac{1}{W} \sum_{i \in A} w_i - -where :math:`R_x` is the reaction rate for reaction :math:`x`, :math:`i` denotes -an index for each event, :math:`A` is the set of all events resulting in -reaction :math:`x`, and :math:`W` is the total starting weight of the particles, -and :math:`w_i` is the pre-collision weight of the particle as it enters event -:math:`i`. One should note that equation :eq:`analog-estimator` is -volume-integrated so if we want a volume-averaged quantity, we need to divided -by the volume of the region of integration. If survival biasing is employed, the -analog estimator cannot be used for any reactions with zero neutrons in the exit -channel. - -Collision Estimator -------------------- - -While the analog estimator is conceptually very simple and easy to implement, it -can suffer higher variance due to the fact low probability events will not occur -often enough to get good statistics if they are being tallied. Thus, it is -desirable to use a different estimator that allows us to score to the tally more -often. One such estimator is the collision estimator. Instead of tallying a -reaction only when it happens, the idea is to make a contribution to the tally -at every collision. - -We can start by writing a formula for the collision estimate of the flux. Since -:math:`R = \Sigma_t \phi` where :math:`R` is the total reaction rate, -:math:`\Sigma_t` is the total macroscopic cross section, and :math:`\phi` is the -scalar flux, it stands to reason that we can estimate the flux by taking an -estimate of the total reaction rate and dividing it by the total macroscopic -cross section. This gives us the following formula: - -.. math:: - :label: collision-estimator-flux - - \phi = \frac{1}{W} \sum_{i \in C} \frac{w_i}{\Sigma_t (E_i)} - -where :math:`W` is again the total starting weight of the particles, :math:`C` -is the set of all events resulting in a collision with a nucleus, and -:math:`\Sigma_t (E)` is the total macroscopic cross section of the target -material at the incoming energy of the particle :math:`E_i`. - -If we multiply both sides of equation :eq:`collision-estimator-flux` by the -macroscopic cross section for some reaction :math:`x`, then we get the collision -estimate for the reaction rate for that reaction: - -.. math:: - :label: collision-estimator - - R_x = \frac{1}{W} \sum_{i \in C} \frac{w_i \Sigma_x (E_i)}{\Sigma_t (E_i)} - -where :math:`\Sigma_x (E_i)` is the macroscopic cross section for reaction -:math:`x` at the incoming energy of the particle :math:`E_i`. In comparison to -equation :eq:`analog-estimator`, we see that the collision estimate will result -in a tally with a larger number of events that score to it with smaller -contributions (since we have multiplied it by :math:`\Sigma_x / \Sigma_t`). - -Track-length Estimator ----------------------- - -One other method we can use to increase the number of events that scores to -tallies is to use an estimator the scores contributions to a tally at every -track for the particle rather than every collision. This is known as a -track-length estimator, sometimes also called a path-length estimator. We first -start with an expression for the volume integrated flux, which can be written as - -.. math:: - :label: flux-integrated - - V \phi = \int d\mathbf{r} \int dE \int d\mathbf{\Omega} \int dt \, - \psi(\mathbf{r}, \mathbf{\hat{\Omega}}, E, t) - -where :math:`V` is the volume, :math:`\psi` is the angular flux, -:math:`\mathbf{r}` is the position of the particle, :math:`\mathbf{\hat{\Omega}}` -is the direction of the particle, :math:`E` is the energy of the particle, and -:math:`t` is the time. By noting that :math:`\psi(\mathbf{r}, -\mathbf{\hat{\Omega}}, E, t) = v n(\mathbf{r}, \mathbf{\hat{\Omega}}, E, t)` -where :math:`n` is the angular neutron density, we can rewrite equation -:eq:`flux-integrated` as - -.. math:: - :label: flux-integrated-2 - - V \phi = \int d\mathbf{r} \int dE \int dt v \int d\mathbf{\Omega} \, n(\mathbf{r}, - \mathbf{\hat{\Omega}}, E, t)). - -Using the relations :math:`N(\mathbf{r}, E, t) = \int d\mathbf{\Omega} -n(\mathbf{r}, \mathbf{\hat{\Omega}}, E, t)` and :math:`d\ell = v \, dt` where -:math:`d\ell` is the differential unit of track length, we then obtain - -.. math:: - :label: track-length-integral - - V \phi = \int d\mathbf{r} \int dE \int d\ell N(\mathbf{r}, E, t). - -Equation :eq:`track-length-integral` indicates that we can use the length of a -particle's trajectory as an estimate for the flux, i.e. the track-length -estimator of the flux would be - -.. math:: - :label: track-length-flux - - \phi = \frac{1}{W} \sum_{i \in T} w_i \ell_i - -where :math:`T` is the set of all the particle's trajectories within the desired -volume and :math:`\ell_i` is the length of the :math:`i`-th trajectory. In the -same vein as equation :eq:`collision-estimator`, the track-length estimate of a -reaction rate is found by multiplying equation :eq:`track-length-flux` by a -macroscopic reaction cross section: - -.. math:: - :label: track-length-estimator - - R_x = \frac{1}{W} \sum_{i \in T} w_i \ell_i \Sigma_x (E_i). - -One important fact to take into consideration is that the use of a track-length -estimator precludes us from using any filter that requires knowledge of the -particle's state following a collision because by definition, it will not have -had a collision at every event. Thus, for tallies with outgoing-energy filters -(which require the post-collision energy), scattering change-in-angle filters, -or for tallies of scattering moments (which require the scattering cosine of -the change-in-angle), we must use an analog estimator. - -.. TODO: Add description of surface current tallies - ----------- -Statistics ----------- - -As was discussed briefly in :ref:`methods_introduction`, any given result from a -Monte Carlo calculation, colloquially known as a "tally", represents an estimate -of the mean of some `random variable`_ of interest. This random variable -typically corresponds to some physical quantity like a reaction rate, a net -current across some surface, or the neutron flux in a region. Given that all -tallies are produced by a `stochastic process`_, there is an associated -uncertainty with each value reported. It is important to understand how the -uncertainty is calculated and what it tells us about our results. To that end, -we will introduce a number of theorems and results from statistics that should -shed some light on the interpretation of uncertainties. - -Law of Large Numbers --------------------- - -The `law of large numbers`_ is an important statistical result that tells us -that the average value of the result a large number of repeated experiments -should be close to the `expected value`_. Let :math:`X_1, X_2, \dots, X_n` be an -infinite sequence of `independent, identically-distributed random variables`_ -with expected values :math:`E(X_1) = E(X_2) = \mu`. One form of the law of large -numbers states that the sample mean :math:`\bar{X_n} = \frac{X_1 + \dots + -X_n}{n}` `converges in probability`_ to the true mean, i.e. for all -:math:`\epsilon > 0` - -.. math:: - - \lim\limits_{n\rightarrow\infty} P \left ( \left | \bar{X}_n - \mu \right | - \ge \epsilon \right ) = 0. - -.. _central-limit-theorem: - -Central Limit Theorem ---------------------- - -The `central limit theorem`_ (CLT) is perhaps the most well-known and ubiquitous -statistical theorem that has far-reaching implications across many -disciplines. The CLT is similar to the law of large numbers in that it tells us -the limiting behavior of the sample mean. Whereas the law of large numbers tells -us only that the value of the sample mean will converge to the expected value of -the distribution, the CLT says that the distribution of the sample mean will -converge to a `normal distribution`_. As we defined before, let :math:`X_1, X_2, -\dots, X_n` be an infinite sequence of independent, identically-distributed -random variables with expected values :math:`E(X_i) = \mu` and variances -:math:`\text{Var} (X_i) = \sigma^2 < \infty`. Note that we don't require that -these random variables take on any particular distribution -- they can be -normal, log-normal, Weibull, etc. The central limit theorem states that as -:math:`n \rightarrow \infty`, the random variable :math:`\sqrt{n} (\bar{X}_n - -\mu)` `converges in distribution`_ to the standard normal distribution: - -.. math:: - :label: central-limit-theorem - - \sqrt{n} \left ( \frac{1}{n} \sum_{i=1}^n X_i - \mu \right ) \xrightarrow{d} - \mathcal{N} (0, \sigma^2) - -Estimating Statistics of a Random Variable ------------------------------------------- - -Mean -++++ - -Given independent samples drawn from a random variable, the sample mean is -simply an estimate of the average value of the random variable. In a Monte Carlo -simulation, the random variable represents physical quantities that we want -tallied. If :math:`X` is the random variable with :math:`N` observations -:math:`x_1, x_2, \dots, x_N`, then an unbiased estimator for the population mean -is the sample mean, defined as - -.. math:: - :label: sample-mean - - \bar{x} = \frac{1}{N} \sum_{i=1}^N x_i. - -Variance -++++++++ - -The variance of a population indicates how spread out different members of the -population are. For a Monte Carlo simulation, the variance of a tally is a -measure of how precisely we know the tally value, with a lower variance -indicating a higher precision. There are a few different estimators for the -population variance. One of these is the second central moment of the -distribution also known as the biased sample variance: - -.. math:: - :label: biased-variance - - s_N^2 = \frac{1}{N} \sum_{i=1}^N \left ( x_i - \bar{x} \right )^2 = \left ( - \frac{1}{N} \sum_{i=1}^N x_i^2 \right ) - \bar{x}^2. - -This estimator is biased because its expected value is actually not equal to the -population variance: - -.. math:: - :label: biased-variance-expectation - - E[s_N^2] = \frac{N - 1}{N} \sigma^2 - -where :math:`\sigma^2` is the actual population variance. As a result, this -estimator should not be used in practice. Instead, one can use `Bessel's -correction`_ to come up with an unbiased sample variance estimator: - -.. math:: - :label: unbiased-variance - - s^2 = \frac{1}{N - 1} \sum_{i=1}^N \left ( x_i - \bar{x} \right )^2 = - \frac{1}{N - 1} \left ( \sum_{i=1}^N x_i^2 - N\bar{x}^2 \right ). - -This is the estimator normally used to calculate sample variance. The final form -in equation :eq:`unbiased-variance` is especially suitable for computation since -we do not need to store the values at every realization of the random variable -as the simulation proceeds. Instead, we can simply keep a running sum and sum of -squares of the values at each realization of the random variable and use that to -calculate the variance. - -Variance of the Mean -++++++++++++++++++++ - -The previous sections discussed how to estimate the mean and variance of a -random variable using statistics on a finite sample. However, we are generally -not interested in the *variance of the random variable* itself; we are more -interested in the *variance of the estimated mean*. The sample mean is the -result of our simulation, and the variance of the sample mean will tell us how -confident we should be in our answers. - -Fortunately, it is quite easy to estimate the variance of the mean if we are -able to estimate the variance of the random variable. We start with the -observation that if we have a series of uncorrelated random variables, we can -write the variance of their sum as the sum of their variances: - -.. math:: - :label: bienayme-formula - - \text{Var} \left ( \sum_{i=1}^N X_i \right ) = \sum_{i=1}^N \text{Var} \left - ( X_i \right ) - -This result is known as the Bienaymé formula. We can use this result to -determine a formula for the variance of the sample mean. Assuming that the -realizations of our random variable are again identical, -independently-distributed samples, then we have that - -.. math:: - :label: sample-variance-mean - - \text{Var} \left ( \bar{X} \right ) = \text{Var} \left ( \frac{1}{N} - \sum_{i=1}^N X_i \right ) = \frac{1}{N^2} \sum_{i=1}^N \text{Var} \left ( - X_i \right ) = \frac{1}{N^2} \left ( N\sigma^2 \right ) = - \frac{\sigma^2}{N}. - -We can combine this result with equation :eq:`unbiased-variance` to come up with -an unbiased estimator for the variance of the sample mean: - -.. math:: - :label: sample-variance-mean-formula - - s_{\bar{X}}^2 = \frac{1}{N - 1} \left ( \frac{1}{N} \sum_{i=1}^N x_i^2 - - \bar{x}^2 \right ). - -At this point, an important distinction should be made between the estimator for -the variance of the population and the estimator for the variance of the -mean. As the number of realizations increases, the estimated variance of the -population based on equation :eq:`unbiased-variance` will tend to the true -population variance. On the other hand, the estimated variance of the mean will -tend to zero as the number of realizations increases. A practical interpretation -of this is that the longer you run a simulation, the better you know your -results. Therefore, by running a simulation long enough, it is possible to -reduce the stochastic uncertainty to arbitrarily low levels. - -Confidence Intervals -++++++++++++++++++++ - -While the sample variance and standard deviation gives us some idea about the -variability of the estimate of the mean of whatever quantities we've tallied, it -does not help us interpret how confidence we should be in the results. To -quantity the reliability of our estimates, we can use `confidence intervals`_ -based on the calculated sample variance. - -A :math:`1-\alpha` confidence interval for a population parameter is defined as -such: if we repeat the same experiment many times and calculate the confidence -interval for each experiment, then :math:`1 - \alpha` percent of the calculated -intervals would encompass the true population parameter. Let :math:`x_1, x_2, -\dots, x_N` be samples from a set of independent, identically-distributed random -variables each with population mean :math:`\mu` and variance -:math:`\sigma^2`. The t-statistic is defined as - -.. math:: - :label: t-statistic - - t = \frac{\bar{x} - \mu}{s/\sqrt{N}} - -where :math:`\bar{x}` is the sample mean from equation :eq:`sample-mean` and -:math:`s` is the standard deviation based on equation -:eq:`unbiased-variance`. If the random variables :math:`X_i` are -normally-distributed, then the t-statistic has a `Student's t-distribution`_ -with :math:`N-1` degrees of freedom. This implies that - -.. math:: - :label: t-probability - - Pr \left ( -t_{1 - \alpha/2, N - 1} \le \frac{\bar{x} - \mu}{s/\sqrt{N}} \le - t_{1 - \alpha/2, N - 1} \right ) = 1 - \alpha - -where :math:`t_{1-\alpha/2, N-1}` is the :math:`1 - \alpha/2` percentile of a -t-distribution with :math:`N-1` degrees of freedom. Thus, the :math:`1 - \alpha` -two sided confidence interval for the sample mean is - -.. math:: - :label: two-sided-ci - - \bar{x} \pm t_{1 - \alpha/2, N-1} \frac{s}{\sqrt{N}}. - -One should be cautioned that equation :eq:`two-sided-ci` only applies if the -*underlying random variables* are normally-distributed. In general, this may not -be true for a tally random variable --- the central limit theorem guarantees -only that the sample mean is normally distributed, not the underlying random -variable. If batching is used, then the underlying random variable, which would -then be the averages from each batch, will be normally distributed as long as -the conditions of the central limit theorem are met. - -Let us now outline the method used to calculate the percentile of the Student's -t-distribution. For one or two degrees of freedom, the percentile can be written -analytically. For one degree of freedom, the t-distribution becomes a standard -`Cauchy distribution`_ whose cumulative distribution function is - -.. math:: - :label: cauchy-cdf - - c(x) = \frac{1}{\pi} \arctan x + \frac{1}{2}. - -Thus, inverting the cumulative distribution function, we find the :math:`x` -percentile of the standard Cauchy distribution to be - -.. math:: - :label: percentile-1 - - t_{x,1} = \tan \left ( \pi \left ( x - \frac{1}{2} \right ) \right ). - -For two degrees of freedom, the cumulative distribution function is the -second-degree polynomial - -.. math:: - :label: t-2-polynomial - - c(x) = \frac{1}{2} + \frac{x}{2\sqrt{x^2 + 2}} - -Solving for :math:`x`, we find the :math:`x` percentile to be - -.. math:: - :label: percentile-2 - - t_{x,2} = \frac{2\sqrt{2} (x - 1/2)}{\sqrt{1 - 4 (x - 1/2)^2}} - -For degrees of freedom greater than two, it is not possible to obtain an -analytical formula for the inverse of the cumulative distribution function. We -must resort to either numerically solving for the inverse or to an -approximation. Approximations for percentiles of the t-distribution have been -found with high levels of accuracy. OpenMC uses the `following approximation`_: - -.. math:: - :label: percentile-n - - t_{x,n} = \sqrt{\frac{n}{n-2}} \left ( z_x + \frac{1}{4} \frac{z_x^3 - - 3z_x}{n-2} + \frac{1}{96} \frac{5z_x^5 - 56z_x^3 + 75z_x}{(n-2)^2} + - \frac{1}{384} \frac{3z_x^7 - 81z_x^5 + 417z_x^3 - 315z_x}{(n-2)^3} \right ) - -where :math:`z_x` is the :math:`x` percentile of the standard normal -distribution. In order to determine an arbitrary percentile of the standard -normal distribution, we use an `unpublished rational approximation`_. After -using the rational approximation, one iteration of Newton's method is applied to -improve the estimate of the percentile. - -.. only:: html - - .. rubric:: References - -.. _following approximation: https://doi.org/10.1080/03610918708812641 - -.. _Bessel's correction: https://en.wikipedia.org/wiki/Bessel's_correction - -.. _random variable: https://en.wikipedia.org/wiki/Random_variable - -.. _stochastic process: https://en.wikipedia.org/wiki/Stochastic_process - -.. _independent, identically-distributed random variables: https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables - -.. _law of large numbers: https://en.wikipedia.org/wiki/Law_of_large_numbers - -.. _expected value: https://en.wikipedia.org/wiki/Expected_value - -.. _converges in probability: https://en.wikipedia.org/wiki/Convergence_of_random_variables#Convergence_in_probability - -.. _normal distribution: https://en.wikipedia.org/wiki/Normal_distribution - -.. _converges in distribution: https://en.wikipedia.org/wiki/Convergence_of_random_variables#Convergence_in_distribution - -.. _confidence intervals: https://en.wikipedia.org/wiki/Confidence_interval - -.. _Student's t-distribution: https://en.wikipedia.org/wiki/Student%27s_t-distribution - -.. _Cauchy distribution: https://en.wikipedia.org/wiki/Cauchy_distribution - -.. _unpublished rational approximation: https://web.archive.org/web/20150926021742/http://home.online.no/~pjacklam/notes/invnorm/ - -.. _MC21: http://www.osti.gov/bridge/servlets/purl/903083-HT5p1o/903083.pdf diff --git a/docs/source/publications.rst b/docs/source/publications.rst deleted file mode 100644 index 24bcc66a1..000000000 --- a/docs/source/publications.rst +++ /dev/null @@ -1,550 +0,0 @@ -.. _publications: - -============ -Publications -============ - ---------- -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 `_," - *Ann. Nucl. Energy*, **82**, 90--97 (2015). - -- Paul K. Romano, Bryan R. Herman, Nicholas E. Horelik, Benoit Forget, Kord - Smith, and Andrew R. Siegel, "Progress and Status of the OpenMC Monte Carlo - Code," *Proc. Int. Conf. Mathematics and Computational Methods Applied to - Nuclear Science and Engineering*, Sun Valley, Idaho, May 5--9 (2013). - -- Paul K. Romano and Benoit Forget, "`The OpenMC Monte Carlo Particle Transport - Code `_," - *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 - `_," *Prog. Nucl. Energy*, - **81**, 43-52 (2015). - -- Daniel J. Kelly, Brian N. Aviles, Paul K. Romano, Bryan R. Herman, - Nicholas E. Horelik, and Benoit Forget, "Analysis of select BEAVRS PWR - benchmark cycle 1 results using MC21 and OpenMC," *Proc. PHYSOR*, Kyoto, - Japan, Sep. 28--Oct. 3 (2014). - -- Bryan R. Herman, Benoit Forget, Kord Smith, Paul K. Romano, Thomas M. Sutton, - Daniel J. Kelly, III, and Brian N. Aviles, "Analysis of tally correlations in - large light water reactors," *Proc. PHYSOR*, Kyoto, Japan, Sep. 28--Oct. 3 - (2014). - -- Nicholas Horelik, Bryan Herman, Benoit Forget, and Kord Smith, "Benchmark for - Evaluation and Validation of Reactor Simulations," - *Proc. Int. Conf. Mathematics and Computational Methods Applied to Nuclear - Science and Engineering*, Sun Valley, Idaho, May 5--9 (2013). - -- Jonathan A. Walsh, Benoit Forget, and Kord S. Smith, "Validation of OpenMC - Reactor Physics Simulations with the B&W 1810 Series Benchmarks," - *Trans. Am. Nucl. Soc.*, **109**, 1301--1304 (2013). - --------------------------- -Coupling and Multi-physics --------------------------- - -- Miriam A. Kreher, Benoit Forget, and Kord Smith, "Single-Batch Monte Carlo - Multiphysics Coupling," *Proc. M&C*, 1789-1797, Portland, Oregon, Aug. 25-29 - (2019). - -- Ze-Long Zhao, Yongwei Yang, and Shuang Hong, "`Application of FLUKA and OpenMC - in coupled physics calculation of target and subcritical reactor for ADS - `_," *Nucl. Sci. Tech.*, **30**: 10 - (2019). - -- April Novak, Paul Romano, Brycen Wendt, Ron Rahaman, Elia Merzari, Leslie - Kerby, Cody Permann, Richard Martineau, and Rachel N. Slaybaugh, "Preliminary - Coupling of OpenMC and Nek5000 within the MOOSE Framework," *Proc. PHYSOR*, - Cancun, Mexico, Apr. 22-26 (2018). - -- Jun Chen, Liangzhi Cao, Chuanqi Zhao, and Zhouyu Liu, "`Development of - Subchannel Code SUBSC for high-fidelity multi-physics coupling application - `_", *Energy Procedia*, **127**, - 264-274 (2017). - -- 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 `_," - *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 `_," *Nucl. Sci. Eng.*, - **185**, 184-193 (2017). - -- Matthew Ellis, Benoit Forget, Kord Smith, and Derek Gaston, "Continuous - Temperature Representation in Coupled OpenMC/MOOSE Simulations," *Proc. PHYSOR - 2016*, Sun Valley, Idaho, May 1-5, 2016. - -- Antonios G. Mylonakis, Melpomeni Varvayanni, and Nicolas Catsaros, - "`Investigating a Matrix-free, Newton-based, Neutron-Monte - Carlo/Thermal-Hydraulic Coupling Scheme - `_", - *Proc. Int. Conf. Nuclear Energy for New Europe*, Portoroz, Slovenia, Sep - .14-17 (2015). - -- Matt Ellis, Benoit Forget, Kord Smith, and Derek Gaston, "Preliminary coupling - of the Monte Carlo code OpenMC and the Multiphysics Object-Oriented Simulation - Environment (MOOSE) for analyzing Doppler feedback in Monte Carlo - simulations," *Proc. Joint Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, - Apr. 19--23 (2015). - -- Bryan R. Herman, Benoit Forget, and Kord Smith, "`Progress toward Monte - Carlo-thermal hydraulic coupling using low-order nonlinear diffusion - acceleration methods `_," - *Ann. Nucl. Energy*, **84**, 63-72 (2015). - -- Bryan R. Herman, Benoit Forget, and Kord Smith, "Utilizing CMFD in OpenMC to - Estimate Dominance Ratio and Adjoint," *Trans. Am. Nucl. Soc.*, **109**, - 1389-1392 (2013). - --------------------------- -Geometry and Visualization --------------------------- - -- Sterling Harper, Paul Romano, Benoit Forget, and Kord Smith, "Efficient - dynamic threadsafe neighbor lists for Monte Carlo ray tracing," *Proc. M&C*, - 918-926, Portland, Oregon, Aug. 25-29 (2019). - -- Jin-Yang Li, Long Gu, Hu-Shan Xu, Nadezha Korepanova, Rui Yu, Yan-Lei Zhu, and - Chang-Ping Qin, "`CAD modeling study on FLUKA and OpenMC for accelerator - driven system simulation `_", - *Ann. Nucl. Energy*, **114**, 329-341 (2018). - -- Logan Abel, William Boyd, Benoit Forget, and Kord Smith, "Interactive - Visualization of Multi-Group Cross Sections on High-Fidelity Spatial Meshes," - *Trans. Am. Nucl. Soc.*, **114**, 391-394 (2016). - -- Derek M. Lax, "`Memory efficient indexing algorithm for physical properties in - OpenMC `_," S. M. Thesis, Massachusetts - Institute of Technology (2015). - -- Derek Lax, William Boyd, Nicholas Horelik, Benoit Forget, and Kord Smith, "A - memory efficient algorithm for classifying unique regions in constructive - solid geometries," *Proc. PHYSOR*, Kyoto, Japan, Sep. 28--Oct. 3 (2014). - -------------- -Miscellaneous -------------- - -- Shikhar Kumar, Benoit Forget, and Kord Smith, "Analysis of fission source - convergence for a 3-D SMR core using functional expansion tallies," *Proc. - M&C*, 937-947, Portland, Oregon, Aug. 25-29 (2019). - -- Faisal Qayyum, Muhammad R. Ali, Awais Zahur, and R. Khan, "`Improvements in - methodology to determine feedback reactivity coefficients - `_," *Nucl. Sci. Tech.*, **30**: 63 - (2019). - -- M. Sajjad, Muhammad Rizwan Ali, M. Naveed Ashraf, Rustam Khan, Tasneem Fatima, - "`KANUPP Reactor Core Model and its Validation - `_," International Conference on - Power Generation Systems and Renewable Energy Technologies, Islamabad, - Pakistan, Sep. 10-12 (2018). - -- Muhammad Waqas Tariq, Muhammad Sohail, and Sikander Majid Mirza, "`Calculation - of Neutronic Parameters using OpenMC for Potential Dispersed Fuels of MNSR - `_," International Conference on - Power Generation Systems and Renewable Energy Technologies, Islamabad, - Pakistan, Sep. 10-12 (2018). - -- Amanda L. Lund and Paul K. Romano, "`Implementation and Validation of Photon - Transport in OpenMC `_", Argonne National - Laboratory, Technical Report ANL/MCS-TM-381 (2018). - -- Bruno Merk, Dzianis Litskevich, R. Gregg, and A. R. Mount, "`Demand driven - salt clean-up in a molten salt fast reactor -- Defining a priority list - `_", *PLOS One*, **13**, - e0192020 (2018). - -- 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 `_," - *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 - Nuclear Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- Antonios G. Mylonakis, M. Varvayanni, D.G.E. Grigoriadis, and N. Catsaros, - "Developing and investigating a pure Monte-Carlo module for transient neutron - transport analysis," *Ann. Nucl. Energy*, **104**, 103-112 (2017). - -- Timothy P. Burke, Brian C. Kiedrowski, William R. Martin, and - Forrest B. Brown, "GPU Acceleration of Kernel Density Estimators in Monte - Carlo Neutron Transport Simulations," *Trans. Am. Nucl. Soc.*, **115**, - 531-534 (2016). - -- Timothy P. Burke, Brian C. Kiedrowski, and William R. Martin, "Cylindrical - Kernel Density Estimators for Monte Carlo Neutron Transport Reactor Physics - Problems," *Trans. Am. Nucl. Soc.*, **115**, 563-566 (2016). - -- Yunzhao Li, Qingming He, Liangzhi Cao, Hongchun Wu, and Tiejun Zu, "`Resonance - Elastic Scattering and Interference Effects Treatments in Subgroup Method - `_," *Nucl. Eng. Tech.*, **48**, - 339-350 (2016). - -- William Boyd, Sterling Harper, and Paul K. Romano, "Equipping OpenMC for the - big data era," *Proc. PHYSOR*, Sun Valley, Idaho, May 1-5, 2016. - -- 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 - `_," *Ann. Nucl. Energy*, - **87**, 601-611 (2016). - -- Qicang Shen, William Boyd, Benoit Forget, and Kord Smith, "Tally precision - triggers for the OpenMC Monte Carlo code," *Trans. Am. Nucl. Soc.*, **112**, - 637-640 (2015). - -- Kyungkwan Noh and Deokjung Lee, "Whole Core Analysis using OpenMC Monte Carlo - Code," *Trans. Kor. Nucl. Soc. Autumn Meeting*, Gyeongju, Korea, - Oct. 24-25, 2013. - -- Timothy P. Burke, Brian C. Kiedrowski, and William R. Martin, "Flux and - Reaction Rate Kernel Density Estimators in OpenMC," *Trans. Am. Nucl. Soc.*, - **109**, 683-686 (2013). - ------------------------------------ -Multigroup Cross Section Generation ------------------------------------ - -- William Boyd, Adam Nelson, Paul K. Romano, Samuel Shaner, Benoit Forget, and - Kord Smith, "`Multigroup Cross-Section Generation with the OpenMC Monte Carlo - Particle Transport Code `_," - *Nucl. Technol.* (2019). - -- William Boyd, Benoit Forget, and Kord Smith, "`A single-step framework to - generate spatially self-shielded multi-group cross sections from Monte Carlo - transport simulations `_," - *Ann. Nucl. Energy*, **125**, 261-271 (2019). - -- Kun Zhuang, Xiaobin Tang, and Liangzhi Cao, "`Development and verification of - a model for generation of MSFR few-group homogenized cross-sections based on a - Monte Carlo code OpenMC `_," - *Ann. Nucl. Energy*, **124**, 187-197 (2019). - -- Changho Lee and Yeon Sang Jung, "Verification of the Cross Section Library - Generated Using OpenMC and MC\ :sup:`2`-3 for PROTEUS," *Proc. PHYSOR*, Cancun, - Mexico, Apr. 22-26 (2018). - -- Zhaoyuan Liu, Kord Smith, Benoit Forget, and Javier Ortensi, "`Cumulative - migration method for computing rigorous diffusion coefficients and transport - cross sections from Monte Carlo - `_," *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 - `_," *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 - `_," - *Nucl. Techniques* **40** (4), 040504 (2017). (in Mandarin) - -- Nicholas E. Stauff, Changho Lee, Paul K. Romano, and Taek K. Kim, - "Verification of Mixed Stochastic/Deterministic Approach for Fast and Thermal - Reactor Analysis," *Proc. ICAPP*, Fukui and Kyoto, Japan, Apr. 24-28, 2017. - -- Zhauyuan Liu, Kord Smith, and Benoit Forget, "Progress of Cumulative Migration - Method for Computing Diffusion Coefficients with OpenMC," - *Proc. Int. Conf. Mathematics & Computational Methods Applied to Nuclear - Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- Geoffrey Gunow, Samuel Shaner, William Boyd, Benoit Forget, and Kord Smith, - "Accuracy and Performance of 3D MOC for Full-Core PWR Problems," - *Proc. Int. Conf. Mathematics & Computational Methods Applied to Nuclear - Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- Tianliang Hu, Liangzhi Cao, Hongchun Wu, and Kun Zhuang, "A coupled neutronics - and thermal-hydraulic modeling approach to the steady-state and dynamic - behavior of MSRs," *Proc. Int. Conf. Mathematics & Computational Methods - Applied to Nuclear Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- William R. D. Boyd, "Reactor Agnostic Multi-Group Cross Section Generation for - Fine-Mesh Deterministic Neutron Transport Simulations," Ph.D. Thesis, - Massachusetts Institute of Technology (2017). - -- Zhaoyuan Liu, Kord Smith, and Benoit Forget, "A Cumulative Migration Method - for Computing Rigorous Transport Cross Sections and Diffusion Coefficients for - LWR Lattices with Monte Carlo," *Proc. PHYSOR*, Sun Valley, Idaho, May - 1-5, 2016. - -- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of - multi-group scattering moments using the NDPP code," *Trans. Am. Nucl. Soc.*, - **113**, 645-648 (2015) - -- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of - multi-group scattering moment matrices," *Trans. Am. Nucl. Soc.*, **110**, - 217-220 (2014). - -- Adam G. Nelson and William R. Martin, "Improved Convergence of Monte Carlo - Generated Multi-Group Scattering Moments," *Proc. Int. Conf. Mathematics and - Computational Methods Applied to Nuclear Science and Engineering*, Sun Valley, - Idaho, May 5--9 (2013). - - ------------------- -Doppler Broadening ------------------- - -- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, and Forrest B. Brown, - "`On-the-fly Doppler broadening of unresolved resonance region cross sections - `_," *Prog. Nucl. Energy*, - **101**, 444-460 (2017). - -- Colin Josey, Pablo Ducru, Benoit Forget, and Kord Smith, "`Windowed multipole - for cross section Doppler broadening - `_," *J. Comput. Phys.*, **307**, - 715-727 (2016). - -- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, and Forrest B. Brown, - "On-the-fly Doppler Broadening of Unresolved Resonance Region Cross Sections - via Probability Band Interpolation," *Proc. PHYSOR*, Sun Valley, Idaho, May - 1-5, 2016. - -- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and - Forrest B. Brown, "`Direct, on-the-fly calculation of unresolved resonance - region cross sections in Monte Carlo simulations - `_," *Proc. Joint Int. Conf. M&C+SNA+MC*, - Nashville, Tennessee, Apr. 19--23 (2015). - -- Colin Josey, Benoit Forget, and Kord Smith, "`Windowed multipole sensitivity - to target accuracy of the optimization procedure - `_," - *J. Nucl. Sci. Technol.*, **52**, 987-992 (2015). - -- Paul K. Romano and Timothy H. Trumbull, "`Comparison of algorithms for Doppler - broadening pointwise tabulated cross sections - `_," *Ann. Nucl. Energy*, - **75**, 358--364 (2015). - -- Tuomas Viitanen, Jaakko Leppanen, and Benoit Forget, "Target motion sampling - temperature treatment technique with track-length esimators in OpenMC -- - Preliminary results," *Proc. PHYSOR*, Kyoto, Japan, Sep. 28--Oct. 3 (2014). - -- Benoit Forget, Sheng Xu, and Kord Smith, "`Direct Doppler broadening in Monte - Carlo simulations using the multipole representation - `_," *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 - `_," - *Proc. Int. Conf. Mathematics & Computational Methods Applied to Nuclear - Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- Vivian Y. Tran, Jonathan A. Walsh, and Benoit Forget, "Treatments for Neutron - Resonance Elastic Scattering Using the Multipole Formalism in Monte Carlo - Codes," *Trans. Am. Nucl. Soc.*, **115**, 1133-1137 (2016). - -- Paul K. Romano and Sterling M. Harper, "Nuclear data processing capabilities - in OpenMC", *Proc. Nuclear Data*, Sep. 11-16, 2016. - -- 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 - `_," *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 - `_", *Comput. Phys. Commun.*, - **196**, 134-142 (2015). - -- Amanda L. Lund, Andrew R. Siegel, Benoit Forget, Colin Josey, and - Paul K. Romano, "Using fractional cascading to accelerate cross section - lookups in Monte Carlo particle transport calculations," *Proc. Joint - Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). - -- Ronald O. Rahaman, Andrew R. Siegel, and Paul K. Romano, "Monte Carlo - performance analysis for varying cross section parameter regimes," - *Proc. Joint Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). - -- Jonathan A. Walsh, Benoit Forget, and Kord S. Smith, "`Accelerated sampling of - the free gas resonance elastic scattering kernel - `_," *Ann. Nucl. Energy*, - **69**, 116--124 (2014). - ------------ -Parallelism ------------ - -- Paul K. Romano and Andrew R. Siegel, "`Limits on the efficiency of event-based - algorithms for Monte Carlo neutron transport - `_," - *Proc. Int. Conf. Mathematics & Computational Methods Applied to Nuclear - Science and Engineering*, Jeju, Korea, Apr. 16-20, 2017. - -- Paul K. Romano, John R. Tramm, and Andrew R. Siegel, "Efficacy of hardware - threading for Monte Carlo particle transport calculations on multi- and - many-core systems," *PHYSOR 2016*, Sun Valley, Idaho, May 1-5, 2016. - -- David Ozog, Allen D. Malony, and Andrew R. Siegel, "A performance analysis of - SIMD algorithms for Monte Carlo simulations of nuclear reactor cores," - *Proc. IEEE Int. Parallel and Distributed Processing Symposium*, Hyderabad, - India, May 25--29 (2015). - -- David Ozog, Allen D. Malony, and Andrew Siegel, "Full-core PWR transport - simulations on Xeon Phi clusters," *Proc. Joint Int. Conf. M&C+SNA+MC*, - Nashville, Tennessee, Apr. 19--23 (2015). - -- Paul K. Romano, Andrew R. Siegel, and Ronald O. Rahaman, "Influence of the - memory subsystem on Monte Carlo code performance," *Proc. Joint - Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015). - -- Hajime Fujita, Nan Dun, Aiman Fang, Zachary A. Rubinstein, Ziming Zheng, Kamil - Iskra, Jeff Hammonds, Anshu Dubey, Pavan Balaji, and Andrew A. Chien, "Using - Global View Resilience (GVR) to add Resilience to Exascale Applications," - *Proc. Supercomputing*, New Orleans, Louisiana, Nov. 16--21, 2014. - -- Nicholas Horelik, Benoit Forget, Kord Smith, and Andrew Siegel, "Domain - decomposition and terabyte tallies with the OpenMC Monte Carlo neutron - transport code," *Proc. PHYSOR*, Kyoto Japan, Sep. 28--Oct. 3 (2014). - -- John R. Tramm, Andrew R. Siegel, Tanzima Islam, and Martin Schulz, "XSBench -- - the development and verification of a performance abstraction for Monte Carlo - reactor analysis," *Proc. PHYSOR*, Kyoto, Japan, Sep 28--Oct. 3, 2014. - -- Nicholas Horelik, Andrew Siegel, Benoit Forget, and Kord Smith, "`Monte Carlo - domain decomposition for robust nuclear reactor analysis - `_," *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 `_," - *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 - `_," *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 `_," *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 - `_," *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 - `_," *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 - `_," *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 `_," *J. Comput. Phys.*, - **235**, 901--911 (2013). - - -- Paul K. Romano and Benoit Forget, "Reducing Parallel Communication in Monte - Carlo Simulations via Batch Statistics," *Trans. Am. Nucl. Soc.*, **107**, - 519--522 (2012). - -- Paul K. Romano and Benoit Forget, "`Parallel Fission Bank Algorithms in Monte - Carlo Criticality Calculations `_," - *Nucl. Sci. Eng.*, **170**, 125--135 (2012). - ---------- -Depletion ---------- - -- Jose L. Salcedo-Perez, Benoit Forget, Kord Smith, and Paul Romano, "Hybrid - tallies to improve performance in depletion Monte Carlo simulations," *Proc. - M&C*, 927-936, Portland, Oregon, Aug. 25-29 (2019). - -- Zhao-Qing Liu, Ze-Long Zhao, Yong-Wei Yang, Yu-Cui Gao, Hai-Yan Meng, and - Qing-Yu Gao, "`Development and validation of depletion code system IMPC-Burnup - for ADS `_," *Nucl. Sci. Tech.*, - **30**: 44 (2019). - -- 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 `_," *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 - `_," *Trans. Am. Nucl. Soc.*, **115**, - 1221-1224 (2016). - -- Anas Gul, K. S. Chaudri, R. Khan, and M. Azeen, "`Development and verification - of LOOP: A Linkage of ORIGEN2.2 and OpenMC - `_," *Ann. Nucl. Energy*, - **99**, 321--327 (2017). - -- Kai Huang, Hongchun Wu, Yunzhao Li, and Liangzhi Cao, "Generalized depletion - chain simplification based of significance analysis," *Proc. PHYSOR*, Sun - Valley, Idaho, May 1-5, 2016. - --------------------- -Sensitivity Analysis --------------------- - -- Abdulla Alhajri and Benoit Forget, "Eigenvalue Sensitivity in Monte Carlo - Simulations to Nuclear Data Parameters using the Multipole Formalism," *Proc. - M&C*, 1895-1906, Portland, Oregon, Aug. 25-29 (2019). - -- Xingjie Peng, Jingang Liang, Benoit Forget, and Kord Smith, "`Calculation of - adjoint-weighted reactor kinetics parameters in OpenMC - `_", *Ann. Nucl. Energy*, - **128**, 231-235 (2019). - -- Zeyun Wu, Jingang Liang, Xingjie Peng, and Hany S. Abdel-Khalik, "`GPT-Free - Sensitivity Analysis for Monte Carlo Models - `_", *Nucl. Technol.* (2019). - -- Xingjie Peng, Jingang Liang, Abdulla Alhajri, Benoit Forget, and Kord Smith, - "`Development of continuous-energy sensitivity analysis capability in OpenMC - `_", *Ann. Nucl. Energy*, - **110**, 362-383 (2017). diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst deleted file mode 100644 index 2c0ac8797..000000000 --- a/docs/source/pythonapi/base.rst +++ /dev/null @@ -1,222 +0,0 @@ ------------------------------------- -:mod:`openmc` -- Basic Functionality ------------------------------------- - -Handling nuclear data ---------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.XSdata - openmc.MGXSLibrary - -Simulation Settings -------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Source - openmc.VolumeCalculation - openmc.Settings - -Material Specification ----------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Nuclide - openmc.Element - openmc.Macroscopic - openmc.Material - openmc.Materials - -Cross sections for nuclides, elements, and materials can be plotted using the -following function: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.plot_xs - -Building geometry ------------------ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Plane - openmc.XPlane - openmc.YPlane - openmc.ZPlane - openmc.XCylinder - openmc.YCylinder - openmc.ZCylinder - openmc.Sphere - openmc.Cone - openmc.XCone - openmc.YCone - openmc.ZCone - openmc.Quadric - openmc.Halfspace - openmc.Intersection - openmc.Union - openmc.Complement - openmc.Cell - openmc.Universe - openmc.RectLattice - openmc.HexLattice - openmc.Geometry - -Many of the above classes are derived from several abstract classes: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Surface - openmc.Region - openmc.Lattice - -.. _pythonapi_tallies: - -Constructing Tallies --------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Filter - openmc.UniverseFilter - openmc.MaterialFilter - openmc.CellFilter - openmc.CellFromFilter - openmc.CellbornFilter - openmc.SurfaceFilter - openmc.MeshFilter - openmc.MeshSurfaceFilter - openmc.EnergyFilter - openmc.EnergyoutFilter - openmc.MuFilter - openmc.PolarFilter - openmc.AzimuthalFilter - openmc.DistribcellFilter - openmc.DelayedGroupFilter - openmc.EnergyFunctionFilter - openmc.LegendreFilter - openmc.SpatialLegendreFilter - openmc.SphericalHarmonicsFilter - openmc.ZernikeFilter - openmc.ZernikeRadialFilter - openmc.ParticleFilter - openmc.RegularMesh - openmc.RectilinearMesh - openmc.Trigger - openmc.TallyDerivative - openmc.Tally - openmc.Tallies - -Geometry Plotting ------------------ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Plot - openmc.Plots - -Running OpenMC --------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.run - openmc.calculate_volumes - openmc.plot_geometry - openmc.plot_inline - openmc.search_for_keff - -Post-processing ---------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.Particle - openmc.StatePoint - openmc.Summary - -The following classes and functions are used for functional expansion reconstruction. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.ZernikeRadial - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.legendre_from_expcoef - - -Various classes may be created when performing tally slicing and/or arithmetic: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.arithmetic.CrossScore - openmc.arithmetic.CrossNuclide - openmc.arithmetic.CrossFilter - openmc.arithmetic.AggregateScore - openmc.arithmetic.AggregateNuclide - openmc.arithmetic.AggregateFilter - -Coarse Mesh Finite Difference Acceleration ------------------------------------------- - -CMFD is implemented in OpenMC and allows users to accelerate fission source -convergence during inactive neutron batches. To use CMFD, the -:class:`openmc.cmfd.CMFDRun` class executes OpenMC through the C API, solving -the CMFD system between fission generations and modifying the source weights. -Note that the :mod:`openmc.cmfd` module is not imported by default with the -:mod:`openmc` namespace and needs to be imported explicitly. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.cmfd.CMFDMesh - openmc.cmfd.CMFDRun - -At the minimum, a CMFD mesh needs to be specified in order to run CMFD. Once the -mesh and other optional properties are set, a simulation can be run with CMFD -turned on using :meth:`openmc.cmfd.CMFDRun.run`. diff --git a/docs/source/pythonapi/capi.rst b/docs/source/pythonapi/capi.rst deleted file mode 100644 index 44094ffd4..000000000 --- a/docs/source/pythonapi/capi.rst +++ /dev/null @@ -1,51 +0,0 @@ ------------------------------------------------------- -:mod:`openmc.lib` -- Python bindings to the C/C++ API ------------------------------------------------------- - -.. automodule:: openmc.lib - -Functions ---------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - 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 -------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - Cell - EnergyFilter - MaterialFilter - Material - MeshFilter - MeshSurfaceFilter - Nuclide - RegularMesh - Tally diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst deleted file mode 100644 index be29d7c0e..000000000 --- a/docs/source/pythonapi/data.rst +++ /dev/null @@ -1,202 +0,0 @@ --------------------------------------------- -:mod:`openmc.data` -- Nuclear Data Interface --------------------------------------------- - -.. module:: openmc.data - -Core Classes ------------- - -The following classes are used for incident neutron data, decay data, fission -and product yields. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - IncidentNeutron - Reaction - Product - FissionEnergyRelease - DataLibrary - Decay - FissionProductYields - WindowedMultipole - ProbabilityTables - -The following classes are used for storing atomic data (incident photon cross -sections, atomic relaxation): - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - IncidentPhoton - PhotonReaction - AtomicRelaxation - - -The following classes are used for storing thermal neutron scattering data: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - ThermalScattering - ThermalScatteringReaction - CoherentElastic - IncoherentElastic - - -Core Functions --------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - atomic_mass - gnd_name - linearize - thin - water_density - zam - -One-dimensional Functions -------------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - Function1D - Tabulated1D - Polynomial - Combination - Sum - Regions1D - ResonancesWithBackground - -Angle-Energy Distributions --------------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - AngleEnergy - KalbachMann - CorrelatedAngleEnergy - UncorrelatedAngleEnergy - NBodyPhaseSpace - LaboratoryAngleEnergy - AngleDistribution - EnergyDistribution - ArbitraryTabulated - GeneralEvaporation - MaxwellEnergy - Evaporation - WattEnergy - MadlandNix - DiscretePhoton - LevelInelastic - ContinuousTabular - CoherentElasticAE - IncoherentElasticAE - IncoherentElasticAEDiscrete - IncoherentInelasticAEDiscrete - -Resonance Data --------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - Resonances - ResonanceRange - SingleLevelBreitWigner - MultiLevelBreitWigner - ReichMoore - RMatrixLimited - ResonanceCovariances - ResonanceCovarianceRange - SingleLevelBreitWignerCovariance - MultiLevelBreitWignerCovariance - ReichMooreCovariance - ParticlePair - SpinGroup - Unresolved - -ACE Format ----------- - -Classes -+++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - ace.Library - ace.Table - -Functions -+++++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - ace.ascii_to_binary - -ENDF Format ------------ - -Classes -+++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - endf.Evaluation - -Functions -+++++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - endf.float_endf - endf.get_cont_record - endf.get_evaluations - endf.get_head_record - endf.get_tab1_record - endf.get_tab2_record - endf.get_text_record - -NJOY Interface --------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - njoy.run - njoy.make_pendf - njoy.make_ace - njoy.make_ace_thermal diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst deleted file mode 100644 index b9970ffb1..000000000 --- a/docs/source/pythonapi/deplete.rst +++ /dev/null @@ -1,205 +0,0 @@ -.. _pythonapi_deplete: - -.. module:: openmc.deplete - ----------------------------------- -:mod:`openmc.deplete` -- Depletion ----------------------------------- - -Primary API ------------ - -The two primary requirements to perform depletion with :mod:`openmc.deplete` -are: - - 1) A transport operator - 2) A time-integration scheme - -The former is responsible for executing a transport code, like OpenMC, -and retaining important information required for depletion. The most common examples -are reaction rates and power normalization data. The latter is responsible for -projecting reaction rates and compositions forward in calendar time across -some step size :math:`\Delta t`, and obtaining new compositions given a power -or power density. The :class:`Operator` is provided to handle communicating with -OpenMC. Several classes are provided that implement different time-integration -algorithms for depletion calculations, which are described in detail in Colin -Josey's thesis, `Development and analysis of high order neutron -transport-depletion coupling algorithms `_. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myintegrator.rst - - PredictorIntegrator - CECMIntegrator - CELIIntegrator - CF4Integrator - EPCRK4Integrator - LEQIIntegrator - SICELIIntegrator - SILEQIIntegrator - -Each of these classes expects a "transport operator" to be passed. An operator -specific to OpenMC is available using the following class: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: mycallable.rst - - Operator - -The :class:`Operator` must also have some knowledge of how nuclides transmute -and decay. This is handled by the :class:`Chain`. - -Minimal Example ---------------- - -A minimal example for performing depletion would be: - -.. code:: - - >>> import openmc - >>> import openmc.deplete - >>> geometry = openmc.Geometry.from_xml() - >>> settings = openmc.Settings.from_xml() - - # Representation of a depletion chain - >>> chain_file = "chain_casl.xml" - >>> operator = openmc.deplete.Operator( - ... geometry, settings, chain_file) - - # Set up 5 time steps of one day each - >>> dt = [24 * 60 * 60] * 5 - >>> power = 1e6 # constant power of 1 MW - - # Deplete using mid-point predictor-corrector - >>> cecm = openmc.deplete.CECMIntegrator( - ... operator, dt, power) - >>> cecm.integrate() - -Internal Classes and Functions ------------------------------- - -When running in parallel using `mpi4py -`_, 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 - -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 - FissionYieldDistribution - FissionYield - -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 - -The following class and functions are used to solve the depletion equations, -with :func:`cram.CRAM48` being the default. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myintegrator.rst - - cram.IPFCramSolver - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - cram.CRAM16 - cram.CRAM48 - cram.deplete - cram.timed_deplete - -The following classes are used to help the :class:`openmc.deplete.Operator` -compute quantities like effective fission yields, reaction rates, and -total system energy. - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - helpers.AveragedFissionYieldHelper - helpers.ChainFissionHelper - helpers.ConstantFissionYieldHelper - helpers.DirectReactionRateHelper - helpers.EnergyScoreHelper - helpers.FissionYieldCutoffHelper - - -Abstract Base Classes ---------------------- - -A good starting point for extending capabilities in :mod:`openmc.deplete` is -to examine the following abstract base classes. Custom classes can -inherit from :class:`abc.TransportOperator` to implement alternative -schemes for collecting reaction rates and other data from a transport code -prior to depleting materials - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: mycallable.rst - - abc.TransportOperator - -The following classes are abstract classes used to pass information from -OpenMC simulations back on to the :class:`abc.TransportOperator` - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - abc.EnergyHelper - abc.FissionYieldHelper - abc.ReactionRateHelper - abc.TalliedFissionYieldHelper - -Custom integrators or depletion solvers can be developed by subclassing from -the following abstract base classes: - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myintegrator.rst - - abc.Integrator - abc.SIIntegrator - abc.DepSystemSolver diff --git a/docs/source/pythonapi/examples.rst b/docs/source/pythonapi/examples.rst deleted file mode 100644 index e7ef523c0..000000000 --- a/docs/source/pythonapi/examples.rst +++ /dev/null @@ -1,25 +0,0 @@ ----------------------------------------- -:mod:`openmc.examples` -- Example Models ----------------------------------------- - -Simple Models -------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.examples.slab_mg - -Reactor Models --------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.examples.pwr_pin_cell - openmc.examples.pwr_assembly - openmc.examples.pwr_core diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst deleted file mode 100644 index 7f67f95ce..000000000 --- a/docs/source/pythonapi/index.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _pythonapi: - -========== -Python API -========== - -OpenMC includes a rich Python API that enables programmatic pre- and -post-processing. The easiest way to begin using the API is to take a look at the -:ref:`examples`. This assumes that you are already familiar with Python and -common third-party packages such as `NumPy `_. If you -have never used Python before, the prospect of learning a new code *and* a -programming language might sound daunting. However, you should keep in mind that -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. -- 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_spheres`) -- 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 -`_ and/or the `Scipy lectures -`_. - -The full API documentation serves to provide more information on a given module -or class. - -.. tip:: Users are strongly encouraged to use the Python API to generate input - files and analyze results. - -.. rubric:: Modules - -.. toctree:: - :maxdepth: 1 - - base - model - examples - deplete - mgxs - stats - data - capi - openmoc diff --git a/docs/source/pythonapi/mgxs.rst b/docs/source/pythonapi/mgxs.rst deleted file mode 100644 index f890bb469..000000000 --- a/docs/source/pythonapi/mgxs.rst +++ /dev/null @@ -1,70 +0,0 @@ ----------------------------------------------------------- -:mod:`openmc.mgxs` -- Multi-Group Cross Section Generation ----------------------------------------------------------- - -Energy Groups -------------- - -Module Variables -++++++++++++++++ - -.. autodata:: openmc.mgxs.GROUP_STRUCTURES - :annotation: - -Classes -+++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.mgxs.EnergyGroups - -Multi-group Cross Sections --------------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclassinherit.rst - - openmc.mgxs.MGXS - openmc.mgxs.AbsorptionXS - openmc.mgxs.CaptureXS - openmc.mgxs.Chi - openmc.mgxs.FissionXS - openmc.mgxs.InverseVelocity - openmc.mgxs.KappaFissionXS - openmc.mgxs.MultiplicityMatrixXS - openmc.mgxs.NuFissionMatrixXS - openmc.mgxs.ScatterXS - openmc.mgxs.ScatterMatrixXS - openmc.mgxs.ScatterProbabilityMatrix - openmc.mgxs.TotalXS - openmc.mgxs.TransportXS - -Multi-delayed-group Cross Sections ----------------------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclassinherit.rst - - openmc.mgxs.MDGXS - openmc.mgxs.ChiDelayed - openmc.mgxs.DelayedNuFissionXS - openmc.mgxs.DelayedNuFissionMatrixXS - openmc.mgxs.Beta - openmc.mgxs.DecayRate - -Multi-group Cross Section Libraries ------------------------------------ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.mgxs.Library diff --git a/docs/source/pythonapi/model.rst b/docs/source/pythonapi/model.rst deleted file mode 100644 index 1091d7cae..000000000 --- a/docs/source/pythonapi/model.rst +++ /dev/null @@ -1,55 +0,0 @@ -------------------------------------- -:mod:`openmc.model` -- Model Building -------------------------------------- - -Convenience Functions ---------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.model.borated_water - openmc.model.cylinder_from_points - openmc.model.hexagonal_prism - openmc.model.rectangular_prism - openmc.model.subdivide - openmc.model.pin - -TRISO Fuel Modeling -------------------- - -Classes -+++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.model.TRISO - -Functions -+++++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.model.create_triso_lattice - openmc.model.pack_spheres - -Model Container ---------------- - -Classes -+++++++ - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.model.Model diff --git a/docs/source/pythonapi/openmoc.rst b/docs/source/pythonapi/openmoc.rst deleted file mode 100644 index 990363268..000000000 --- a/docs/source/pythonapi/openmoc.rst +++ /dev/null @@ -1,24 +0,0 @@ ---------------------------------------------------------- -:mod:`openmc.openmoc_compatible` -- OpenMOC Compatibility ---------------------------------------------------------- - -Core Classes ------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myfunction.rst - - openmc.openmoc_compatible.get_openmoc_material - openmc.openmoc_compatible.get_openmc_material - openmc.openmoc_compatible.get_openmoc_surface - openmc.openmoc_compatible.get_openmc_surface - openmc.openmoc_compatible.get_openmoc_cell - openmc.openmoc_compatible.get_openmc_cell - openmc.openmoc_compatible.get_openmoc_universe - openmc.openmoc_compatible.get_openmc_universe - openmc.openmoc_compatible.get_openmoc_lattice - openmc.openmoc_compatible.get_openmc_lattice - openmc.openmoc_compatible.get_openmoc_geometry - openmc.openmoc_compatible.get_openmc_geometry diff --git a/docs/source/pythonapi/stats.rst b/docs/source/pythonapi/stats.rst deleted file mode 100644 index 6ad0e6b03..000000000 --- a/docs/source/pythonapi/stats.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _pythonapi_stats: - ---------------------------------- -:mod:`openmc.stats` -- Statistics ---------------------------------- - -Univariate Probability Distributions ------------------------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.stats.Univariate - openmc.stats.Discrete - openmc.stats.Uniform - openmc.stats.Maxwell - openmc.stats.Watt - openmc.stats.Tabular - openmc.stats.Legendre - openmc.stats.Mixture - openmc.stats.Normal - openmc.stats.Muir - -Angular Distributions ---------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.stats.UnitSphere - openmc.stats.PolarAzimuthal - openmc.stats.Isotropic - openmc.stats.Monodirectional - -Spatial Distributions ---------------------- - -.. autosummary:: - :toctree: generated - :nosignatures: - :template: myclass.rst - - openmc.stats.Spatial - openmc.stats.CartesianIndependent - openmc.stats.Box - openmc.stats.Point diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst deleted file mode 100644 index 20ecc6373..000000000 --- a/docs/source/quickinstall.rst +++ /dev/null @@ -1,138 +0,0 @@ -.. _quickinstall: - -=================== -Quick Install Guide -=================== - -This quick install guide outlines the basic steps needed to install OpenMC on -your computer. For more detailed instructions on configuring and installing -OpenMC, see :ref:`usersguide_install` in the User's Manual. - ----------------------------------------- -Installing on Linux/Mac with conda-forge ----------------------------------------- - -`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. If -you have `conda` installed on your system, OpenMC can be installed via the -`conda-forge` channel. First, add the `conda-forge` channel with: - -.. code-block:: sh - - conda config --add channels conda-forge - -OpenMC can then be installed with: - -.. code-block:: sh - - conda install openmc - --------------------------------- -Installing on Ubuntu through PPA --------------------------------- - -For users with Ubuntu 15.04 or later, a binary package for OpenMC is available -through a `Personal Package Archive`_ (PPA) and can be installed through the -`APT package manager`_. First, add the following PPA to the repository sources: - -.. code-block:: sh - - sudo apt-add-repository ppa:paulromano/staging - -Next, resynchronize the package index files: - -.. code-block:: sh - - sudo apt update - -Now OpenMC should be recognized within the repository and can be installed: - -.. code-block:: sh - - 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 - -------------------------------------------- -Installing on Linux/Mac/Windows with Docker -------------------------------------------- - -OpenMC can be easily deployed using `Docker `_ on any -Windows, Mac or Linux system. With Docker running, execute the following -command in the shell to download and run a `Docker image`_ with the most recent release of OpenMC from `DockerHub `_ called ``openmc/openmc:v0.10.0``: - -.. code-block:: sh - - docker run openmc/openmc:v0.10.0 - -This will take several minutes to run depending on your internet download speed. The command will place you in an interactive shell running in a `Docker container`_ with OpenMC installed. - -.. note:: The ``docker run`` command supports many `options`_ for spawning - containers -- including `mounting volumes`_ from the host - filesystem -- which many users will find useful. - -.. _Docker image: https://docs.docker.com/engine/reference/commandline/images/ -.. _Docker container: https://www.docker.com/resources/what-container -.. _options: https://docs.docker.com/engine/reference/commandline/run/ -.. _mounting volumes: https://docs.docker.com/storage/volumes/ - ---------------------------------------- -Installing from Source on Ubuntu 15.04+ ---------------------------------------- - -To build OpenMC from source, several :ref:`prerequisites ` are -needed. If you are using Ubuntu 15.04 or higher, all prerequisites can be -installed directly from the package manager. - -.. code-block:: sh - - sudo apt install g++ cmake libhdf5-dev - -After the packages have been installed, follow the instructions below for -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 `gcc `_ compiler suite, -`CMake `_, and `HDF5 `_ -installed, you can download and install OpenMC be entering the following -commands in a terminal: - -.. code-block:: sh - - git clone https://github.com/openmc-dev/openmc.git - cd openmc - mkdir build && cd build - cmake .. - make - sudo make install - -This will build an executable named ``openmc`` and install it (by default in -/usr/local/bin). If you do not have administrator privileges, the cmake command -should specify an installation directory where you have write access, e.g. - -.. code-block:: sh - - cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local .. - -The :mod:`openmc` Python package must be installed separately. The easiest way -to install it is using `pip `_, 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 -`. diff --git a/docs/source/releasenotes/0.10.0.rst b/docs/source/releasenotes/0.10.0.rst deleted file mode 100644 index e847fd0be..000000000 --- a/docs/source/releasenotes/0.10.0.rst +++ /dev/null @@ -1,102 +0,0 @@ -==================== -What's New in 0.10.0 -==================== - -.. currentmodule:: openmc - -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: - -- 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:: - - mat = openmc.Material() - mat.add_nuclide('H1', 1.0) - mat.isotropic = ['H1'] - - To treat all nuclides in a material this way, the - :meth:`Material.make_isotropic_in_lab` method can still be used. - -- The initializers for :class:`openmc.Intersection` and :class:`openmc.Union` - now expect an iterable. - -- Auto-generated unique IDs for classes now start from 1 rather than 10000. - -.. 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 -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions and Mac -OS X. Numerous users have reported working builds on Microsoft Windows, but your -mileage may vary. Memory requirements will vary depending on the size of the -problem at hand (mostly on the number of nuclides and tallies in the problem). - ------------- -New Features ------------- - -- 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 ---------- - -- 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 - -.. _937469: https://github.com/openmc-dev/openmc/commit/937469 -.. _a149ef: https://github.com/openmc-dev/openmc/commit/a149ef -.. _2c9b21: https://github.com/openmc-dev/openmc/commit/2c9b21 -.. _8047f6: https://github.com/openmc-dev/openmc/commit/8047f6 -.. _0beb4c: https://github.com/openmc-dev/openmc/commit/0beb4c -.. _f124be: https://github.com/openmc-dev/openmc/commit/f124be -.. _0c6915: https://github.com/openmc-dev/openmc/commit/0c6915 -.. _61ecb4: https://github.com/openmc-dev/openmc/commit/61ecb4 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Brody Bassett `_ -- `Will Boyd `_ -- `Guillaume Giudicelli `_ -- `Brittany Grayson `_ -- `Sterling Harper `_ -- `Colin Josey `_ -- `Travis Labossiere-Hickman `_ -- `Jingang Liang `_ -- `Alex Lindsay `_ -- `Johnny Liu `_ -- `Amanda Lund `_ -- `April Novak `_ -- `Adam Nelson `_ -- `Jose Salcedo Perez `_ -- `Paul Romano `_ -- `Sam Shaner `_ diff --git a/docs/source/releasenotes/0.11.0.rst b/docs/source/releasenotes/0.11.0.rst deleted file mode 100644 index 221d57658..000000000 --- a/docs/source/releasenotes/0.11.0.rst +++ /dev/null @@ -1,133 +0,0 @@ -==================== -What's New in 0.11.0 -==================== - -.. currentmodule:: openmc - -------- -Summary -------- - -This release of OpenMC adds several major new features: :ref:`depletion -`, photon transport, and support for CAD geometries -through DAGMC. In addition, the core codebase has been rewritten in C++14 (it -was previously written in Fortran 2008). This makes compiling the code -considerably simpler as no Fortran compiler is needed. - -Functional expansion tallies are now supported through several new tally filters -that can be arbitrarily combined: - -- :class:`openmc.LegendreFilter` -- :class:`openmc.SpatialLegendreFilter` -- :class:`openmc.SphericalHarmonicsFilter` -- :class:`openmc.ZernikeFilter` -- :class:`openmc.ZernikeRadialFilter` - -Note that these filters replace the use expansion scores like ``scatter-P1``. -Instead, a normal ``scatter`` score should be used along with a -:class:`openmc.LegendreFilter`. - -The interface for random sphere packing has been significantly improved. A new -:func:`openmc.model.pack_spheres` function takes a region and generates a -random, non-overlapping configuration of spheres within the region. - ------------- -New Features ------------- - -- White boundary conditions can be applied to surfaces -- Support for rectilinear meshes through :class:`openmc.RectilinearMesh`. -- The :class:`Geometry`, :class:`Materials`, and :class:`Settings` classes now - have a ``from_xml`` method that will build an instance from an existing XML - file. -- Predefined energy group structures can be found in - :data:`openmc.mgxs.GROUP_STRUCTURES`. -- New tally scores: ``H1-production``, ``H2-production``, ``H3-production``, - ``He3-production``, ``He4-production``, ``heating``, ``heating-local``, and - ``damage-energy``. -- Switched to cell-based neighor lists (`PR 1140 - `_) -- Two new probability distributions that can be used for source distributions: - :class:`openmc.stats.Normal` and :class:`openmc.stats.Muir` -- The :mod:`openmc.data` module now supports reading and sampling from ENDF File - 32 resonance covariance data (`PR 1024 - `_). -- Several new convenience functions/methods have been added: - - - The :func:`openmc.model.cylinder_from_points` function creates a cylinder - given two points passing through its center and a radius. - - The :meth:`openmc.Plane.from_points` function creates a plane given three - points that pass through it. - - The :func:`openmc.model.pin` function creates a pin cell universe given a - sequence of concentric cylinders and materials. - ------------------- -Python API Changes ------------------- - -- All surface classes now have coefficient arguments given as lowercase names. -- The order of arguments in surface classes has been changed so that - coefficients are the first arguments (rather than the optional surface ID). - This means you can now write:: - - x = openmc.XPlane(5.0, 'reflective') - zc = openmc.ZCylinder(0., 0., 10.) - -- The ``Mesh`` class has been renamed :class:`openmc.RegularMesh`. -- The ``get_rectangular_prism`` function has been renamed - :func:`openmc.model.rectangular_prism`. -- The ``get_hexagonal_prism`` function has been renamed - :func:`openmc.model.hexagonal_prism`. -- Python bindings to the C/C++ API have been move from ``openmc.capi`` to - :mod:`openmc.lib`. - ---------- -Bug Fixes ---------- - -- `Rotate azimuthal distributions correctly for source sampling `_ -- `Fix reading ASCII ACE tables in Python 3 `_ -- `Fix bug for distributed temperatures `_ -- `Fix bug for distance to boundary in complex cells `_ -- `Bug fixes for precursor decay rate tallies `_ -- `Check for invalid surface IDs in region expression `_ -- `Support for 32-bit operating systems `_ -- `Avoid segfault from unused nuclides `_ -- `Avoid overflow when broadcasting tally results `_ - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Brody Bassett `_ -- `Will Boyd `_ -- `Andrew Davis `_ -- `Iurii Drobyshev `_ -- `Guillaume Giudicelli `_ -- `Brittany Grayson `_ -- `Zhuoran Han `_ -- `Sterling Harper `_ -- `Andrew Johnson `_ -- `Colin Josey `_ -- `Shikhar Kumar `_ -- `Travis Labossiere-Hickman `_ -- `Matias Lavista `_ -- `Jingang Liang `_ -- `Alex Lindsay `_ -- `Johnny Liu `_ -- `Amanda Lund `_ -- `Jan Malec `_ -- `Isaac Meyer `_ -- `April Novak `_ -- `Adam Nelson `_ -- `Gavin Ridley `_ -- `Jose Salcedo Perez `_ -- `Paul Romano `_ -- `Sam Shaner `_ -- `Jonathan Shimwell `_ -- `Patrick Shriwise `_ -- `John Tramm `_ -- `Jiankai Yu `_ -- `Xiaokang Zhang `_ diff --git a/docs/source/releasenotes/0.4.0.rst b/docs/source/releasenotes/0.4.0.rst deleted file mode 100644 index b24365669..000000000 --- a/docs/source/releasenotes/0.4.0.rst +++ /dev/null @@ -1,34 +0,0 @@ -=================== -What's New in 0.4.0 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions as well as -Mac OS X. However, it has not been tested yet on any releases of Microsoft -Windows. Memory requirements will vary depending on the size of the problem at -hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- The probability table method for treatment of energy self-shielding in the - unresolved resonance range has been implemented and is now turned on by - default. -- Calculation of Shannon entropy for assessing convergence of the fission source - distribution. -- Ability to compile with the PGI Fortran compiler. -- Ability to run on IBM BlueGene/P machines. -- Completely rewrote how nested universes are handled. Geometry is now much more - robust. - ---------- -Bug Fixes ---------- - -- Many geometry errors have been fixed. The Monte Carlo performance benchmark - can now be successfully run in OpenMC. diff --git a/docs/source/releasenotes/0.4.1.rst b/docs/source/releasenotes/0.4.1.rst deleted file mode 100644 index 4bc3bc658..000000000 --- a/docs/source/releasenotes/0.4.1.rst +++ /dev/null @@ -1,53 +0,0 @@ -=================== -What's New in 0.4.1 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions as well as -Mac OS X. However, it has not been tested yet on any releases of Microsoft -Windows. Memory requirements will vary depending on the size of the problem at -hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- A batching method has been implemented so that statistics can be calculated - based on multiple generations instead of a single generation. This can help to - overcome problems with underpredicted variance in problems where there is - correlation between successive fission source iterations. -- Users now have the option to select a non-unionized energy grid for problems - with many nuclides where the use of a unionized grid is not feasible. -- Improved plotting capability (Nick Horelik). The plotting input is now in - ``plots.xml`` instead of ``plot.xml``. -- Added multiple estimators for k-effective and added a global tally for - leakage. -- Moved cross section-related output into cross_sections.out. -- Improved timing capabilities. -- Can now use more than 2**31 - 1 particles per generation. -- Improved fission bank synchronization method. This also necessitated changing - the source bank to be of type Bank rather than of type Particle. -- Added HDF5 output (not complete yet). -- Major changes to tally implementation. - ---------- -Bug Fixes ---------- - -- `b206a8`_: Fixed subtle error in the sampling of energy distributions. -- `800742`_: Fixed error in sampling of angle and rotating angles. -- `a07c08`_: Fixed bug in linear-linear interpolation during sampling energy. -- `a75283`_: Fixed energy and energyout tally filters to support many bins. -- `95cfac`_: Fixed error in cell neighbor searches. -- `83a803`_: Fixed bug related to probability tables. - -.. _b206a8: https://github.com/openmc-dev/openmc/commit/b206a8 -.. _800742: https://github.com/openmc-dev/openmc/commit/800742 -.. _a07c08: https://github.com/openmc-dev/openmc/commit/a07c08 -.. _a75283: https://github.com/openmc-dev/openmc/commit/a75283 -.. _95cfac: https://github.com/openmc-dev/openmc/commit/95cfac -.. _83a803: https://github.com/openmc-dev/openmc/commit/83a803 diff --git a/docs/source/releasenotes/0.4.2.rst b/docs/source/releasenotes/0.4.2.rst deleted file mode 100644 index 0e28eb6e6..000000000 --- a/docs/source/releasenotes/0.4.2.rst +++ /dev/null @@ -1,54 +0,0 @@ -=================== -What's New in 0.4.2 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Ability to specify void materials. -- Option to not reduce tallies across processors at end of each batch. -- Uniform fission site method for reducing variance on local tallies. -- Reading/writing binary source files. -- Added more messages for or high verbosity. -- Estimator for diffusion coefficient. -- Ability to specify 'point' source type. -- Ability to change random number seed. -- Users can now specify units='sum' on a tag. This tells the code that - the total material density is the sum of the atom fractions listed for each - nuclide on the material. - ---------- -Bug Fixes ---------- - -- a27f8f_: Fixed runtime error bug when using Intel compiler with DEBUG on. -- afe121_: Fixed minor bug in fission bank algorithms. -- e0968e_: Force re-evaluation of cross-sections when each particle is born. -- 298db8_: Fixed bug in surface currents when using energy-in filter. -- 2f3bbe_: Fixed subtle bug in S(a,b) cross section calculation. -- 671f30_: Fixed surface currents on mesh not encompassing geometry. -- b2c40e_: Fixed bug in incoming energy filter for track-length tallies. -- 5524fd_: Mesh filter now works with track-length tallies. -- d050c7_: Added Bessel's correction to make estimate of variance unbiased. -- 2a5b9c_: Fixed regression in plotting. - -.. _a27f8f: https://github.com/openmc-dev/openmc/commit/a27f8f -.. _afe121: https://github.com/openmc-dev/openmc/commit/afe121 -.. _e0968e: https://github.com/openmc-dev/openmc/commit/e0968e -.. _298db8: https://github.com/openmc-dev/openmc/commit/298db8 -.. _2f3bbe: https://github.com/openmc-dev/openmc/commit/2f3bbe -.. _671f30: https://github.com/openmc-dev/openmc/commit/671f30 -.. _b2c40e: https://github.com/openmc-dev/openmc/commit/b2c40e -.. _5524fd: https://github.com/openmc-dev/openmc/commit/5524fd -.. _d050c7: https://github.com/openmc-dev/openmc/commit/d050c7 -.. _2a5b9c: https://github.com/openmc-dev/openmc/commit/2a5b9c diff --git a/docs/source/releasenotes/0.4.3.rst b/docs/source/releasenotes/0.4.3.rst deleted file mode 100644 index 4023cb525..000000000 --- a/docs/source/releasenotes/0.4.3.rst +++ /dev/null @@ -1,51 +0,0 @@ -=================== -What's New in 0.4.3 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Option to report confidence intervals for tally results. -- Rotation and translation for filled cells. -- Ability to explicitly specify for tallies. -- Ability to store state points and use them to restart runs. -- Fixed source calculations (no subcritical multiplication however). -- Expanded options for external source distribution. -- Ability to tally reaction rates for individual nuclides within a material. -- Reduced memory usage by removing redundant storage or some cross-sections. -- 3bd35b_: Log-log interpolation for URR probability tables. -- Support to specify labels on tallies (nelsonag_). - ---------- -Bug Fixes ---------- - -- 33f29a_: Handle negative values in probability table. -- 1c472d_: Fixed survival biasing with probability tables. -- 3c6e80_: Fixed writing tallies with no filters. -- 460ef1_: Invalid results for duplicate tallies. -- 0069d5_: Fixed bug with 0 inactive batches. -- 7af2cf_: Fixed bug in score_analog_tallies. -- 85a60e_: Pick closest angular distribution for law 61. -- 3212f5_: Fixed issue with blank line at beginning of XML files. - -.. _nelsonag: https://github.com/nelsonag -.. _33f29a: https://github.com/openmc-dev/openmc/commit/33f29a -.. _1c472d: https://github.com/openmc-dev/openmc/commit/1c472d -.. _3c6e80: https://github.com/openmc-dev/openmc/commit/3c6e80 -.. _3bd35b: https://github.com/openmc-dev/openmc/commit/3bd35b -.. _0069d5: https://github.com/openmc-dev/openmc/commit/0069d5 -.. _7af2cf: https://github.com/openmc-dev/openmc/commit/7af2cf -.. _460ef1: https://github.com/openmc-dev/openmc/commit/460ef1 -.. _85a60e: https://github.com/openmc-dev/openmc/commit/85a60e -.. _3212f5: https://github.com/openmc-dev/openmc/commit/3212f5 diff --git a/docs/source/releasenotes/0.4.4.rst b/docs/source/releasenotes/0.4.4.rst deleted file mode 100644 index c5201b30f..000000000 --- a/docs/source/releasenotes/0.4.4.rst +++ /dev/null @@ -1,43 +0,0 @@ -=================== -What's New in 0.4.4 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Ability to write state points when using . -- Real-time XML validation in GNU Emacs with RELAX NG schemata. -- Writing state points every n batches with -- Suppress creation of summary.out and cross_sections.out by default with option - to turn them on with tag in settings.xml file. -- Ability to create HDF5 state points. -- Binary source file is now part of state point file by default. -- Enhanced state point usage and added state point Python scripts. -- Turning confidence intervals on affects k-effective. -- Option to specify for tally meshes. - ---------- -Bug Fixes ---------- - -- 4654ee_: Fixed plotting with void cells. -- 7ee461_: Fixed bug with multi-line input using type='word'. -- 792eb3_: Fixed degrees of freedom for confidence intervals. -- 7fd617_: Fixed bug with restart runs in parallel. -- dc4a8f_: Fixed bug with fixed source restart runs. - -.. _4654ee: https://github.com/openmc-dev/openmc/commit/4654ee -.. _7ee461: https://github.com/openmc-dev/openmc/commit/7ee461 -.. _792eb3: https://github.com/openmc-dev/openmc/commit/792eb3 -.. _7fd617: https://github.com/openmc-dev/openmc/commit/7fd617 -.. _dc4a8f: https://github.com/openmc-dev/openmc/commit/dc4a8f diff --git a/docs/source/releasenotes/0.5.0.rst b/docs/source/releasenotes/0.5.0.rst deleted file mode 100644 index aa906a323..000000000 --- a/docs/source/releasenotes/0.5.0.rst +++ /dev/null @@ -1,49 +0,0 @@ -=================== -What's New in 0.5.0 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- All user input options that formerly accepted "off" or "on" should now be - "false" or "true" (the proper XML schema datatype). -- The element is deprecated and was replaced with . -- Added 'events' score that returns number of events that scored to a tally. -- Restructured tally filter implementation and user input. -- Source convergence acceleration via CMFD (implemented with PETSc). -- Ability to read source files in parallel when number of particles is greater - than that number of source sites. -- Cone surface types. - ---------- -Bug Fixes ---------- - -- 737b90_: Coincident surfaces from separate universes / particle traveling - tangent to a surface. -- a819b4_: Output of surface neighbors in summary.out file. -- b11696_: Reading long attribute lists in XML input. -- 2bd46a_: Search for tallying nuclides when no default_xs specified. -- 7a1f08_: Fix word wrapping when writing messages. -- c0e3ec_: Prevent underflow when compiling with MPI=yes and DEBUG=yes. -- 6f8d9d_: Set default tally labels. -- 6a3a5e_: Fix problem with corner-crossing in lattices. - -.. _737b90: https://github.com/openmc-dev/openmc/commit/737b90 -.. _a819b4: https://github.com/openmc-dev/openmc/commit/a819b4 -.. _b11696: https://github.com/openmc-dev/openmc/commit/b11696 -.. _2bd46a: https://github.com/openmc-dev/openmc/commit/2bd46a -.. _7a1f08: https://github.com/openmc-dev/openmc/commit/7a1f08 -.. _c0e3ec: https://github.com/openmc-dev/openmc/commit/c0e3ec -.. _6f8d9d: https://github.com/openmc-dev/openmc/commit/6f8d9d -.. _6a3a5e: https://github.com/openmc-dev/openmc/commit/6a3a5e diff --git a/docs/source/releasenotes/0.5.1.rst b/docs/source/releasenotes/0.5.1.rst deleted file mode 100644 index 26a6927c7..000000000 --- a/docs/source/releasenotes/0.5.1.rst +++ /dev/null @@ -1,43 +0,0 @@ -=================== -What's New in 0.5.1 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Absorption and combined estimators for k-effective. -- Natural elements can now be specified in materials using rather than - . -- Support for multiple S(a,b) tables in a single material (e.g. BeO). -- Test suite using Python nosetests. -- Proper install capability with 'make install'. -- Lattices can now be 2 or 3 dimensions. -- New scatter-PN score type. -- New kappa-fission score type. -- Ability to tally any reaction by specifying MT. - ---------- -Bug Fixes ---------- - -- 94103e_: Two checks for outgoing energy filters. -- e77059_: Fix reaction name for MT=849. -- b0fe88_: Fix distance to surface for cones. -- 63bfd2_: Fix tracklength tallies with cell filter and universes. -- 88daf7_: Fix analog tallies with survival biasing. - -.. _94103e: https://github.com/openmc-dev/openmc/commit/94103e -.. _e77059: https://github.com/openmc-dev/openmc/commit/e77059 -.. _b0fe88: https://github.com/openmc-dev/openmc/commit/b0fe88 -.. _63bfd2: https://github.com/openmc-dev/openmc/commit/63bfd2 -.. _88daf7: https://github.com/openmc-dev/openmc/commit/88daf7 diff --git a/docs/source/releasenotes/0.5.2.rst b/docs/source/releasenotes/0.5.2.rst deleted file mode 100644 index 1a5702895..000000000 --- a/docs/source/releasenotes/0.5.2.rst +++ /dev/null @@ -1,55 +0,0 @@ -=================== -What's New in 0.5.2 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Python script for mesh tally plotting -- Isotopic abundances based on IUPAC 2009 when using -- Particle restart files for debugging -- Code will abort after certain number of lost particles (defaults to 10) -- Region outside lattice can be filled with material (void by default) -- 3D voxel plots -- Full HDF5/PHDF5 support (including support in statepoint.py) -- Cell overlap checking with -g command line flag (or when plotting) - ---------- -Bug Fixes ---------- - -- 7632f3_: Fixed bug in statepoint.py for multiple generations per batch. -- f85ac4_: Fix infinite loop bug in error module. -- 49c36b_: Don't convert surface ids if surface filter is for current tallies. -- 5ccc78_: Fix bug in reassignment of bins for mesh filter. -- b1f52f_: Fixed bug in plot color specification. -- eae7e5_: Fixed many memory leaks. -- 10c1cc_: Minor CMFD fixes. -- afdb50_: Add compatibility for XML comments without whitespace. -- a3c593_: Fixed bug in use of free gas scattering for H-1. -- 3a66e3_: Fixed bug in 2D mesh tally implementation. -- ab0793_: Corrected PETSC_NULL references to their correct types. -- 182ebd_: Use analog estimator with energyout filter. - -.. _7632f3: https://github.com/openmc-dev/openmc/commit/7632f3 -.. _f85ac4: https://github.com/openmc-dev/openmc/commit/f85ac4 -.. _49c36b: https://github.com/openmc-dev/openmc/commit/49c36b -.. _5ccc78: https://github.com/openmc-dev/openmc/commit/5ccc78 -.. _b1f52f: https://github.com/openmc-dev/openmc/commit/b1f52f -.. _eae7e5: https://github.com/openmc-dev/openmc/commit/eae7e5 -.. _10c1cc: https://github.com/openmc-dev/openmc/commit/10c1cc -.. _afdb50: https://github.com/openmc-dev/openmc/commit/afdb50 -.. _a3c593: https://github.com/openmc-dev/openmc/commit/a3c593 -.. _3a66e3: https://github.com/openmc-dev/openmc/commit/3a66e3 -.. _ab0793: https://github.com/openmc-dev/openmc/commit/ab0793 -.. _182ebd: https://github.com/openmc-dev/openmc/commit/182ebd diff --git a/docs/source/releasenotes/0.5.3.rst b/docs/source/releasenotes/0.5.3.rst deleted file mode 100644 index 7b2878d91..000000000 --- a/docs/source/releasenotes/0.5.3.rst +++ /dev/null @@ -1,47 +0,0 @@ -=================== -What's New in 0.5.3 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Output interface enhanced to allow multiple files handles to be opened -- Particle restart file linked to output interface -- Particle restarts and state point restarts are both identified with the -r - command line flag. -- Particle instance no longer global, passed to all physics routines -- Physics routines refactored to rely less on global memory, more arguments - passed in -- CMFD routines refactored and now can compute dominance ratio on the fly -- PETSc 3.4.2 or higher must be used and compiled with fortran datatype support -- Memory leaks fixed except for ones from xml-fortran package -- Test suite enhanced to test output with different compiler options -- Description of OpenMC development workflow added -- OpenMP shared-memory parallelism added -- Special run mode --tallies removed. - ---------- -Bug Fixes ---------- - -- 2b1e8a_: Normalize direction vector after reflecting particle. -- 5853d2_: Set blank default for cross section listing alias. -- e178c7_: Fix infinite loop with words greater than 80 characters in write_message. -- c18a6e_: Check for valid secondary mode on S(a,b) tables. -- 82c456_: Fix bug where last process could have zero particles. - -.. _2b1e8a: https://github.com/openmc-dev/openmc/commit/2b1e8a -.. _5853d2: https://github.com/openmc-dev/openmc/commit/5853d2 -.. _e178c7: https://github.com/openmc-dev/openmc/commit/e178c7 -.. _c18a6e: https://github.com/openmc-dev/openmc/commit/c18a6e -.. _82c456: https://github.com/openmc-dev/openmc/commit/82c456 diff --git a/docs/source/releasenotes/0.5.4.rst b/docs/source/releasenotes/0.5.4.rst deleted file mode 100644 index ed40d29df..000000000 --- a/docs/source/releasenotes/0.5.4.rst +++ /dev/null @@ -1,62 +0,0 @@ -=================== -What's New in 0.5.4 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Source sites outside geometry are resampled -- XML-Fortran backend replaced by FoX XML -- Ability to write particle track files -- Handle lost particles more gracefully (via particle track files) -- Multiple random number generator streams -- Mesh tally plotting utility converted to use Tkinter rather than PyQt -- Script added to download ACE data from NNDC -- Mixed ASCII/binary cross_sections.xml now allowed -- Expanded options for writing source bank -- Re-enabled ability to use source file as starting source -- S(a,b) recalculation avoided when same nuclide and S(a,b) table are accessed - ---------- -Bug Fixes ---------- - -- 32c03c_: Check for valid data in cross_sections.xml -- c71ef5_: Fix bug in statepoint.py -- 8884fb_: Check for all ZAIDs for S(a,b) tables -- b38af0_: Fix XML reading on multiple levels of input -- d28750_: Fix bug in convert_xsdir.py -- cf567c_: ENDF/B-VI data checked for compatibility -- 6b9461_: Fix p_valid sampling inside of sample_energy - -.. _32c03c: https://github.com/openmc-dev/openmc/commit/32c03c -.. _c71ef5: https://github.com/openmc-dev/openmc/commit/c71ef5 -.. _8884fb: https://github.com/openmc-dev/openmc/commit/8884fb -.. _b38af0: https://github.com/openmc-dev/openmc/commit/b38af0 -.. _d28750: https://github.com/openmc-dev/openmc/commit/d28750 -.. _cf567c: https://github.com/openmc-dev/openmc/commit/cf567c -.. _6b9461: https://github.com/openmc-dev/openmc/commit/6b9461 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Nick Horelik `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Tuomas Viitanen `_ -- `Jon Walsh `_ diff --git a/docs/source/releasenotes/0.6.0.rst b/docs/source/releasenotes/0.6.0.rst deleted file mode 100644 index 8d0d2957b..000000000 --- a/docs/source/releasenotes/0.6.0.rst +++ /dev/null @@ -1,57 +0,0 @@ -=================== -What's New in 0.6.0 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Legendre and spherical harmonic expansion tally scores -- CMake is now default build system -- Regression test suite based on CTests and NNDC cross sections -- FoX is now a git submodule -- Support for older cross sections (e.g. MCNP 66c) -- Progress bar for plots -- Expanded support for natural elements via in settings.xml - ---------- -Bug Fixes ---------- - -- 41f7ca_: Fixed erroneous results from survival biasing -- 038736_: Fix tallies over void materials -- 46f9e8_: Check for negative values in probability tables -- d1ca35_: Fixed sampling of angular distribution -- 0291c0_: Fixed indexing error in plotting -- d7a7d0_: Fix bug with specifying xs attribute -- 85b3cb_: Fix out-of-bounds error with OpenMP threading - -.. _41f7ca: https://github.com/openmc-dev/openmc/commit/41f7ca -.. _038736: https://github.com/openmc-dev/openmc/commit/038736 -.. _46f9e8: https://github.com/openmc-dev/openmc/commit/46f9e8 -.. _d1ca35: https://github.com/openmc-dev/openmc/commit/d1ca35 -.. _0291c0: https://github.com/openmc-dev/openmc/commit/0291c0 -.. _d7a7d0: https://github.com/openmc-dev/openmc/commit/d7a7d0 -.. _85b3cb: https://github.com/openmc-dev/openmc/commit/85b3cb - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Nick Horelik `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Jon Walsh `_ diff --git a/docs/source/releasenotes/0.6.1.rst b/docs/source/releasenotes/0.6.1.rst deleted file mode 100644 index c0f11ef68..000000000 --- a/docs/source/releasenotes/0.6.1.rst +++ /dev/null @@ -1,63 +0,0 @@ -=================== -What's New in 0.6.1 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Coarse mesh finite difference (CMFD) acceleration no longer requires PETSc -- Statepoint file numbering is now zero-padded -- Python scripts now compatible with Python 2 or 3 -- Ability to run particle restarts in fixed source calculations -- Capability to filter box source by fissionable materials -- Nuclide/element names are now case insensitive in input files -- Improved treatment of resonance scattering for heavy nuclides - ---------- -Bug Fixes ---------- - -- 03e890_: Check for energy-dependent multiplicities in ACE files -- 4439de_: Fix distance-to-surface calculation for general plane surface -- 5808ed_: Account for differences in URR band probabilities at different energies -- 2e60c0_: Allow zero atom/weight percents in materials -- 3e0870_: Don't use PWD environment variable when setting path to input files -- dc4776_: Handle probability table resampling correctly -- 01178b_: Fix metastables nuclides in NNDC cross_sections.xml file -- 62ec43_: Don't read tallies.xml when OpenMC is run in plotting mode -- 2a95ef_: Prevent segmentation fault on "current" score without mesh filter -- 93e482_: Check for negative values in probability tables - -.. _03e890: https://github.com/openmc-dev/openmc/commit/03e890 -.. _4439de: https://github.com/openmc-dev/openmc/commit/4439de -.. _5808ed: https://github.com/openmc-dev/openmc/commit/5808ed -.. _2e60c0: https://github.com/openmc-dev/openmc/commit/2e60c0 -.. _3e0870: https://github.com/openmc-dev/openmc/commit/3e0870 -.. _dc4776: https://github.com/openmc-dev/openmc/commit/dc4776 -.. _01178b: https://github.com/openmc-dev/openmc/commit/01178b -.. _62ec43: https://github.com/openmc-dev/openmc/commit/62ec43 -.. _2a95ef: https://github.com/openmc-dev/openmc/commit/2a95ef -.. _93e482: https://github.com/openmc-dev/openmc/commit/93e482 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Jon Walsh `_ -- `Will Boyd `_ diff --git a/docs/source/releasenotes/0.6.2.rst b/docs/source/releasenotes/0.6.2.rst deleted file mode 100644 index 9a5400cac..000000000 --- a/docs/source/releasenotes/0.6.2.rst +++ /dev/null @@ -1,56 +0,0 @@ -=================== -What's New in 0.6.2 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Meshline plotting capability -- Support for plotting cells/materials on middle universe levels -- Ability to model cells with no surfaces -- Compatibility with PETSc 3.5 -- Compatability with OpenMPI 1.7/1.8 -- Improved overall performance via logarithmic-mapped energy grid search -- Improved multi-threaded performance with atomic operations -- Support for fixed source problems with fissionable materials - ---------- -Bug Fixes ---------- - -- 26fb93_: Fix problem with -t, --track command-line flag -- 2f07c0_: Improved evaporation spectrum algorithm -- e6abb9_: Fix segfault when tallying in a void material -- 291b45_: Handle metastable nuclides in NNDC data and multiplicities in MT=5 data - -.. _26fb93: https://github.com/openmc-dev/openmc/commit/26fb93 -.. _2f07c0: https://github.com/openmc-dev/openmc/commit/2f07c0 -.. _e6abb9: https://github.com/openmc-dev/openmc/commit/e6abb9 -.. _291b45: https://github.com/openmc-dev/openmc/commit/291b45 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Will Boyd `_ -- `Matt Ellis `_ -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Nicholas Horelik `_ -- `Anton Leontiev `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Jon Walsh `_ -- `John Xia `_ diff --git a/docs/source/releasenotes/0.7.0.rst b/docs/source/releasenotes/0.7.0.rst deleted file mode 100644 index 2a3063a92..000000000 --- a/docs/source/releasenotes/0.7.0.rst +++ /dev/null @@ -1,65 +0,0 @@ -=================== -What's New in 0.7.0 -=================== - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Complete Python API -- Python 3 compatability for all scripts -- All scripts consistently named openmc-* and installed together -- New 'distribcell' tally filter for repeated cells -- Ability to specify outer lattice universe -- XML input validation utility (openmc-validate-xml) -- Support for hexagonal lattices -- Material union energy grid method -- Tally triggers -- Remove dependence on PETSc -- Significant OpenMP performance improvements -- Support for Fortran 2008 MPI interface -- Use of Travis CI for continuous integration -- Simplifications and improvements to test suite - ---------- -Bug Fixes ---------- - -- b5f712_: Fix bug in spherical harmonics tallies -- e6675b_: Ensure all constants are double precision -- 04e2c1_: Fix potential bug in sample_nuclide routine -- 6121d9_: Fix bugs related to particle track files -- 2f0e89_: Fixes for nuclide specification in tallies - -.. _b5f712: https://github.com/openmc-dev/openmc/commit/b5f712 -.. _e6675b: https://github.com/openmc-dev/openmc/commit/e6675b -.. _04e2c1: https://github.com/openmc-dev/openmc/commit/04e2c1 -.. _6121d9: https://github.com/openmc-dev/openmc/commit/6121d9 -.. _2f0e89: https://github.com/openmc-dev/openmc/commit/2f0e89 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Will Boyd `_ -- `Matt Ellis `_ -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Nicholas Horelik `_ -- `Colin Josey `_ -- `William Lyu `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Anthony Scopatz `_ -- `Jon Walsh `_ diff --git a/docs/source/releasenotes/0.7.1.rst b/docs/source/releasenotes/0.7.1.rst deleted file mode 100644 index 01af74239..000000000 --- a/docs/source/releasenotes/0.7.1.rst +++ /dev/null @@ -1,89 +0,0 @@ -=================== -What's New in 0.7.1 -=================== - -This release of OpenMC provides some substantial improvements over version -0.7.0. Non-simple cell regions can now be defined through the ``|`` (union) and -``~`` (complement) operators. Similar changes in the Python API also allow -complex cell regions to be defined. A true secondary particle bank now exists; -this is crucial for photon transport (to be added in the next minor release). A -rich API for multi-group cross section generation has been added via the -``openmc.mgxs`` Python module. - -Various improvements to tallies have also been made. It is now possible to -explicitly specify that a collision estimator be used in a tally. A new -``delayedgroup`` filter and ``delayed-nu-fission`` score allow a user to obtain -delayed fission neutron production rates filtered by delayed group. Finally, the -new ``inverse-velocity`` score may be useful for calculating kinetics -parameters. - -.. caution:: In previous versions, depending on how OpenMC was compiled binary - output was either given in HDF5 or a flat binary format. With this - version, all binary output is now HDF5 which means you **must** - have HDF5 in order to install OpenMC. Please consult the user's - guide for instructions on how to compile with HDF5. - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions, Mac OS X, -and Microsoft Windows 7. Memory requirements will vary depending on the size of -the problem at hand (mostly on the number of nuclides in the problem). - ------------- -New Features ------------- - -- Support for complex cell regions (union and complement operators) -- Generic quadric surface type -- Improved handling of secondary particles -- Binary output is now solely HDF5 -- ``openmc.mgxs`` Python module enabling multi-group cross section generation -- Collision estimator for tallies -- Delayed fission neutron production tallies with ability to filter by delayed - group -- Inverse velocity tally score -- Performance improvements for binary search -- Performance improvements for reaction rate tallies - ---------- -Bug Fixes ---------- - -- 299322_: Bug with material filter when void material present -- d74840_: Fix triggers on tallies with multiple filters -- c29a81_: Correctly handle maximum transport energy -- 3edc23_: Fixes in the nu-scatter score -- 629e3b_: Assume unspecified surface coefficients are zero in Python API -- 5dbe8b_: Fix energy filters for openmc-plot-mesh-tally -- ff66f4_: Fixes in the openmc-plot-mesh-tally script -- 441fd4_: Fix bug in kappa-fission score -- 7e5974_: Allow fixed source simulations from Python API - -.. _299322: https://github.com/openmc-dev/openmc/commit/299322 -.. _d74840: https://github.com/openmc-dev/openmc/commit/d74840 -.. _c29a81: https://github.com/openmc-dev/openmc/commit/c29a81 -.. _3edc23: https://github.com/openmc-dev/openmc/commit/3edc23 -.. _629e3b: https://github.com/openmc-dev/openmc/commit/629e3b -.. _5dbe8b: https://github.com/openmc-dev/openmc/commit/5dbe8b -.. _ff66f4: https://github.com/openmc-dev/openmc/commit/ff66f4 -.. _441fd4: https://github.com/openmc-dev/openmc/commit/441fd4 -.. _7e5974: https://github.com/openmc-dev/openmc/commit/7e5974 - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Will Boyd `_ -- `Sterling Harper `_ -- `Bryan Herman `_ -- `Colin Josey `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Kelly Rowland `_ -- `Sam Shaner `_ -- `Jon Walsh `_ diff --git a/docs/source/releasenotes/0.8.0.rst b/docs/source/releasenotes/0.8.0.rst deleted file mode 100644 index d4f5a878b..000000000 --- a/docs/source/releasenotes/0.8.0.rst +++ /dev/null @@ -1,94 +0,0 @@ -=================== -What's New in 0.8.0 -=================== - -This release of OpenMC includes a few new major features including the -capability to perform neutron transport with multi-group cross section data as -well as experimental support for the windowed multipole method being developed -at MIT. Source sampling options have also been expanded significantly, with the -option to supply arbitrary tabular and discrete distributions for energy, angle, -and spatial coordinates. - -The Python API has been significantly restructured in this release compared to -version 0.7.1. Any scripts written based on the version 0.7.1 API will likely -need to be rewritten. Some of the most visible changes include the following: - -- ``SettingsFile`` is now ``Settings``, ``MaterialsFile`` is now ``Materials``, - and ``TalliesFile`` is now ``Tallies``. -- The ``GeometryFile`` class no longer exists and is replaced by the - ``Geometry`` class which now has an ``export_to_xml()`` method. -- Source distributions are defined using the ``Source`` class and assigned to - the ``Settings.source`` property. -- The ``Executor`` class no longer exists and is replaced by ``openmc.run()`` - and ``openmc.plot_geometry()`` functions. - -The Python API documentation has also been significantly expanded. - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions and Mac -OS X. Numerous users have reported working builds on Microsoft Windows, but your -mileage may vary. Memory requirements will vary depending on the size of the -problem at hand (mostly on the number of nuclides and tallies in the problem). - ------------- -New Features ------------- - -- Multi-group mode -- Vast improvements to the Python API -- Experimental windowed multipole capability -- Periodic boundary conditions -- Expanded source sampling options -- Distributed materials -- Subcritical multiplication support -- Improved method for reproducible URR table sampling -- Refactor of continuous-energy reaction data -- Improved documentation and new Jupyter notebooks - ---------- -Bug Fixes ---------- - -- 70daa7_: Make sure MT=3 cross section is not used -- 40b05f_: Ensure source bank is resampled for fixed source runs -- 9586ed_: Fix two hexagonal lattice bugs -- a855e8_: Make sure graphite models don't error out on max events -- 7294a1_: Fix incorrect check on cmfd.xml -- 12f246_: Ensure number of realizations is written to statepoint -- 0227f4_: Fix bug when sampling multiple energy distributions -- 51deaa_: Prevent segfault when user specifies '18' on tally scores -- fed74b_: Prevent duplicate tally scores -- 8467ae_: Better threshold for allowable lost particles -- 493c6f_: Fix type of return argument for h5pget_driver_f - -.. _70daa7: https://github.com/openmc-dev/openmc/commit/70daa7 -.. _40b05f: https://github.com/openmc-dev/openmc/commit/40b05f -.. _9586ed: https://github.com/openmc-dev/openmc/commit/9586ed -.. _a855e8: https://github.com/openmc-dev/openmc/commit/a855e8 -.. _7294a1: https://github.com/openmc-dev/openmc/commit/7294a1 -.. _12f246: https://github.com/openmc-dev/openmc/commit/12f246 -.. _0227f4: https://github.com/openmc-dev/openmc/commit/0227f4 -.. _51deaa: https://github.com/openmc-dev/openmc/commit/51deaa -.. _fed74b: https://github.com/openmc-dev/openmc/commit/fed74b -.. _8467ae: https://github.com/openmc-dev/openmc/commit/8467ae -.. _493c6f: https://github.com/openmc-dev/openmc/commit/493c6f - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Will Boyd `_ -- `Derek Gaston `_ -- `Sterling Harper `_ -- `Colin Josey `_ -- `Jingang Liang `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Kelly Rowland `_ -- `Sam Shaner `_ diff --git a/docs/source/releasenotes/0.9.0.rst b/docs/source/releasenotes/0.9.0.rst deleted file mode 100644 index 778a7d135..000000000 --- a/docs/source/releasenotes/0.9.0.rst +++ /dev/null @@ -1,150 +0,0 @@ -=================== -What's New in 0.9.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. - -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:: - - energy_filter = openmc.EnergyFilter([0.0, 0.625, 4.0, 1.0e6, 20.0e6]) - -- 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.:: - - plot.colors = { - fuel: 'yellow', - water: 'blue' - } - -- ``make_hexagon_region`` is now :func:`get_hexagonal_prism` -- Several changes in :class:`Settings` attributes: - - - ``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. - -------------------- -System Requirements -------------------- - -There are no special requirements for running the OpenMC code. As of this -release, OpenMC has been tested on a variety of Linux distributions and Mac -OS X. Numerous users have reported working builds on Microsoft Windows, but your -mileage may vary. Memory requirements will vary depending on the size of the -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 `_ -- 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` - ---------- -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 - -.. _c5df6c: https://github.com/openmc-dev/openmc/commit/c5df6c -.. _1cfa39: https://github.com/openmc-dev/openmc/commit/1cfa39 -.. _335359: https://github.com/openmc-dev/openmc/commit/335359 -.. _17c678: https://github.com/openmc-dev/openmc/commit/17c678 -.. _23ec0b: https://github.com/openmc-dev/openmc/commit/23ec0b -.. _7eefb7: https://github.com/openmc-dev/openmc/commit/7eefb7 -.. _7880d4: https://github.com/openmc-dev/openmc/commit/7880d4 -.. _ad2d9f: https://github.com/openmc-dev/openmc/commit/ad2d9f -.. _59fdca: https://github.com/openmc-dev/openmc/commit/59fdca -.. _9eff5b: https://github.com/openmc-dev/openmc/commit/9eff5b -.. _7848a9: https://github.com/openmc-dev/openmc/commit/7848a9 -.. _f139ce: https://github.com/openmc-dev/openmc/commit/f139ce -.. _b8ddfa: https://github.com/openmc-dev/openmc/commit/b8ddfa -.. _ec3cfb: https://github.com/openmc-dev/openmc/commit/ec3cfb -.. _5e9b06: https://github.com/openmc-dev/openmc/commit/5e9b06 -.. _c39990: https://github.com/openmc-dev/openmc/commit/c39990 -.. _c6b67e: https://github.com/openmc-dev/openmc/commit/c6b67e -.. _489540: https://github.com/openmc-dev/openmc/commit/489540 -.. _f0214f: https://github.com/openmc-dev/openmc/commit/f0214f - ------------- -Contributors ------------- - -This release contains new contributions from the following people: - -- `Will Boyd `_ -- `Sterling Harper `_ -- `Qingming He <906459647@qq.com>`_ -- `Colin Josey `_ -- `Travis Labossiere-Hickman `_ -- `Jingang Liang `_ -- `Amanda Lund `_ -- `Adam Nelson `_ -- `Paul Romano `_ -- `Sam Shaner `_ -- `Jon Walsh `_ diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst deleted file mode 100644 index 320ea9ca0..000000000 --- a/docs/source/releasenotes/index.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _releasenotes: - -============= -Release Notes -============= - -.. toctree:: - :maxdepth: 1 - - 0.11.0 - 0.10.0 - 0.9.0 - 0.8.0 - 0.7.1 - 0.7.0 - 0.6.2 - 0.6.1 - 0.6.0 - 0.5.4 - 0.5.3 - 0.5.2 - 0.5.1 - 0.5.0 - 0.4.4 - 0.4.3 - 0.4.2 - 0.4.1 - 0.4.0 diff --git a/docs/source/usersguide/basics.rst b/docs/source/usersguide/basics.rst deleted file mode 100644 index dbf63136c..000000000 --- a/docs/source/usersguide/basics.rst +++ /dev/null @@ -1,190 +0,0 @@ -.. _usersguide_basics: - -====================== -Basics of Using OpenMC -====================== - ----------------- -Creating a Model ----------------- - -When you build and install OpenMC, you will have an :ref:`scripts_openmc` -executable on your system. When you run ``openmc``, the first thing it will do -is look for a set of XML_ files that describe the model you want to -simulation. Three of these files are required and another three are optional, as -described below. - -.. admonition:: Required - :class: error - - :ref:`io_materials` - This file describes what materials are present in the problem and what they - are composed of. Additionally, it indicates where OpenMC should look for a - cross section library. - - :ref:`io_geometry` - This file describes how the materials defined in ``materials.xml`` occupy - regions of space. Physical volumes are defined using constructive solid - geometry, described in detail in :ref:`usersguide_geometry`. - - :ref:`io_settings` - This file indicates what mode OpenMC should be run in, how many particles - to simulate, the source definition, and a whole host of miscellaneous - options. - -.. admonition:: Optional - :class: note - - :ref:`io_tallies` - This file describes what physical quantities should be tallied during the - simulation (fluxes, reaction rates, currents, etc.). - - :ref:`io_plots` - This file gives specifications for producing slice or voxel plots of the - geometry. - -eXtensible Markup Language (XML) --------------------------------- - -Unlike many other Monte Carlo codes which use an arbitrary-format ASCII file -with "cards" to specify a particular geometry, materials, and associated run -settings, the input files for OpenMC are structured in a set of `XML -`_ files. XML, which stands for eXtensible Markup -Language, is a simple format that allows data to be exchanged efficiently -between different programs and interfaces. - -Anyone who has ever seen webpages written in HTML will be familiar with the -structure of XML whereby "tags" enclosed in angle brackets denote that a -particular piece of data will follow. Let us examine the follow example: - -.. code-block:: xml - - - John - Smith - 27 - Health Physicist - - -Here we see that the first tag indicates that the following data will describe a -person. The nested tags *firstname*, *lastname*, *age*, and *occupation* -indicate characteristics about the person being described. - -In much the same way, OpenMC input uses XML tags to describe the geometry, the -materials, and settings for a Monte Carlo simulation. Note that because the XML -files have a well-defined structure, they can be validated using the -:ref:`scripts_validate` script or using :ref:`Emacs nXML mode -`. - -Creating Input Files --------------------- - -.. currentmodule:: openmc - -The most rudimentary option for creating input files is to simply write them -from scratch using the :ref:`XML format specifications -`. This approach will feel familiar to users of other -Monte Carlo codes such as MCNP and Serpent, with the added bonus that the XML -formats feel much more "readable". Alternatively, input files can be generated -using OpenMC's :ref:`Python API `, which is introduced in the -following section. - ----------- -Python API ----------- - -OpenMC's :ref:`Python API ` defines a set of functions and classes -that roughly correspond to elements in the XML files. For example, the -:class:`openmc.Cell` Python class directly corresponds to the -:ref:`cell_element` in XML. Each XML file itself also has a corresponding class: -:class:`openmc.Geometry` for ``geometry.xml``, :class:`openmc.Materials` for -``materials.xml``, :class:`openmc.Settings` for ``settings.xml``, and so on. To -create a model then, one creates instances of these classes and then uses the -``export_to_xml()`` method, e.g., :meth:`Geometry.export_to_xml`. Most scripts -that generate a full model will look something like the following: - -.. code-block:: Python - - # Create materials - materials = openmc.Materials() - ... - materials.export_to_xml() - - # Create geometry - geometry = openmc.Geometry() - ... - geometry.export_to_xml() - - # Assign simulation settings - settings = openmc.Settings() - ... - settings.export_to_xml() - -Once a model has been created and exported to XML, a simulation can be run either -by calling :ref:`scripts_openmc` directly from a shell or by using the -:func:`openmc.run()` function from Python. - -Identifying Objects -------------------- - -In the XML user input files, each object (cell, surface, tally, etc.) has to be -uniquely identified by a positive integer (ID) in the same manner as MCNP and -Serpent. In the Python API, integer IDs can be assigned but it is not strictly -required. When IDs are not explicitly assigned to instances of the OpenMC Python -classes, they will be automatically assigned. - -.. _result_files: - ------------------------------ -Viewing and Analyzing Results ------------------------------ - -After a simulation has been completed by running :ref:`scripts_openmc`, you will -have several output files that were created: - -``tallies.out`` - An ASCII file showing the mean and standard deviation of the mean for any - user-defined tallies. - -``summary.h5`` - An HDF5 file with a complete description of the geometry and materials used in - the simulation. - -``statepoint.#.h5`` - An HDF5 file with the complete results of the simulation, including tallies as - well as the final source distribution. This file can be used both to - view/analyze results as well as restart a simulation if desired. - -For a simple simulation with few tallies, looking at the ``tallies.out`` file -might be sufficient. For anything more complicated (plotting results, finding a -subset of results, etc.), you will likely find it easier to work with the -statepoint file directly using the :class:`openmc.StatePoint` class. For more -details on working with statepoints, see :ref:`usersguide_statepoint`. - --------------- -Physical Units --------------- - -Unless specified otherwise, all length quantities are assumed to be in units of -centimeters, all energy quantities are assumed to be in electronvolts, and all -time quantities are assumed to be in seconds. - -======= ============ ====== -Measure Default unit Symbol -======= ============ ====== -length centimeter cm -energy electronvolt eV -time second s -======= ============ ====== - ------------------------------------- -ERSN-OpenMC Graphical User Interface ------------------------------------- - -A third-party Java-based user-friendly graphical user interface for creating XML -input files called ERSN-OpenMC_ is developed and maintained by members of the -Radiation and Nuclear Systems Group at the Faculty of Sciences Tetouan, Morocco. -The GUI also allows one to automatically download prerequisites for installing and -running OpenMC. - -.. _ERSN-OpenMC: https://github.com/EL-Bakkali-Jaafar/ERSN-OpenMC diff --git a/docs/source/usersguide/beginners.rst b/docs/source/usersguide/beginners.rst deleted file mode 100644 index 85d50a2d4..000000000 --- a/docs/source/usersguide/beginners.rst +++ /dev/null @@ -1,161 +0,0 @@ -.. _usersguide_beginners: - -============================ -A Beginner's Guide to OpenMC -============================ - --------------------- -What does OpenMC do? --------------------- - -In a nutshell, OpenMC simulates neutral particles (presently neutrons and -photons) moving stochastically through an arbitrarily defined model that -represents an real-world experimental setup. The experiment could be as simple -as a sphere of metal or as complicated as a full-scale `nuclear reactor`_. This -is what's known as `Monte Carlo`_ simulation. In the case of a nuclear reactor -model, neutrons are especially important because they are the particles that -induce `fission`_ in isotopes of uranium and other elements. Knowing the -behavior of neutrons allows one to determine how often and where fission -occurs. The amount of energy released is then directly proportional to the -fission reaction rate since most heat is produced by fission. By simulating -many neutrons (millions or billions), it is possible to determine the average -behavior of these neutrons (or the behavior of the energy produced, or any -other quantity one is interested in) very accurately. - -Using Monte Carlo methods to determine the average behavior of various physical -quantities in a system is quite different from other means of solving the same -problem. The other class of methods for determining the behavior of neutrons and -reactions rates is so-called `deterministic`_ methods. In these methods, the -starting point is not randomly simulating particles but rather writing an -equation that describes the average behavior of the particles. The equation that -describes the average behavior of neutrons is called the `neutron transport`_ -equation. This equation is a seven-dimensional equation (three for space, three -for velocity, and one for time) and is very difficult to solve directly. For all -but the simplest problems, it is necessary to make some sort of -`discretization`_. As an example, we can divide up all space into small sections -which are homogeneous and then solve the equation on those small sections. After -these discretizations and various approximations, one can arrive at forms that -are suitable for solution on a computer. Among these are discrete ordinates, -method of characteristics, finite-difference diffusion, and nodal methods. - -So why choose Monte Carlo over deterministic methods? Each method has its pros -and cons. Let us first take a look at few of the salient pros and cons of -deterministic methods: - -- **Pro**: Depending on what method is used, solution can be determined very - quickly. - -- **Pro**: The solution is a global solution, i.e. we know the average behavior - everywhere. - -- **Pro**: Once the problem is converged, the solution is known. - -- **Con**: If the model is complex, it is necessary to do sophisticated mesh - generation. - -- **Con**: It is necessary to generate multi-group cross sections which requires - knowing the solution *a priori*. - -Now let's look at the pros and cons of Monte Carlo methods: - -- **Pro**: No mesh generation is required to build geometry. By using - `constructive solid geometry`_, it's possible to build arbitrarily complex - models with curved surfaces. - -- **Pro**: Monte Carlo methods can be used with either continuous-energy or - multi-group cross sections. - -- **Pro**: Running simulations in parallel is conceptually very simple. - -- **Con**: Because they rely on repeated random sampling, they are - computationally very expensive. - -- **Con**: A simulation doesn't automatically give you the global solution - everywhere -- you have to specifically ask for those quantities you want. - -- **Con**: Even after the problem is converged, it is necessary to simulate - many particles to reduce stochastic uncertainty. - -Because fewer approximations are made in solving a problem by the Monte Carlo -method, it is often seen as a "gold standard" which can be used as a benchmark -for a solution of the same problem by deterministic means. However, it comes at -the expense of a potentially longer simulation. - ------------------ -How does it work? ------------------ - -In order to do anything, the code first needs to have a model of some problem of -interest. This could be a nuclear reactor or any other physical system with -fissioning material. You, as the code user, will need to describe the model so -that the code can do something with it. A basic model consists of a few things: - -- A description of the geometry -- the problem must be split up into regions of - homogeneous material composition. -- For each different material in the problem, a description of what nuclides are - in the material and at what density. -- Various parameters telling the code how many particles to simulate and what - options to use. -- A list of different physical quantities that the code should return at the end - of the simulation. In a Monte Carlo simulation, if you don't ask for anything, - it will not give you any answers (other than a few default quantities). - ------------------------ -What do I need to know? ------------------------ - -If you are starting to work with OpenMC, there are a few things you should be -familiar with. Whether you plan on working in Linux, macOS, or Windows, you -should be comfortable working in a command line environment. There are many -resources online for learning command line environments. If you are using Linux -or Mac OS X (also Unix-derived), `this tutorial -`_ will help you get acquainted with -commonly-used commands. - -To reap the full benefits of OpenMC, you should also have basic proficiency in -the use of `Python `_, as OpenMC includes a rich Python -API that offers many usability improvements over dealing with raw XML input -files. - -OpenMC uses a version control software called `git`_ to keep track of changes to -the code, document bugs and issues, and other development tasks. While you don't -necessarily have to have git installed in order to download and run OpenMC, it -makes it much easier to receive updates if you do have it installed and have a -basic understanding of how it works. There are a list of good `git tutorials`_ -at the git documentation website. The `OpenMC source code`_ and documentation -are hosted at `GitHub`_. In order to receive updates to the code directly, -submit `bug reports`_, and perform other development tasks, you may want to sign -up for a free account on GitHub. Once you have an account, you can follow `these -instructions `_ on how to set up -your computer for using GitHub. - -If you are new to nuclear engineering, you may want to review the NRC's `Reactor -Concepts Manual`_. This manual describes the basics of nuclear power for -electricity generation, the fission process, and the overall systems in a -pressurized or boiling water reactor. Another resource that is a bit more -technical than the Reactor Concepts Manual but still at an elementary level is -the DOE Fundamentals Handbook on Nuclear Physics and Reactor Theory `Volume I`_ -and `Volume II`_. You may also find it helpful to review the following terms: - -- `Neutron cross section`_ -- `Effective multiplication factor`_ -- `Flux`_ - -.. _nuclear reactor: https://en.wikipedia.org/wiki/Nuclear_reactor -.. _Monte Carlo: https://en.wikipedia.org/wiki/Monte_Carlo_method -.. _fission: https://en.wikipedia.org/wiki/Nuclear_fission -.. _deterministic: https://en.wikipedia.org/wiki/Deterministic_algorithm -.. _neutron transport: https://en.wikipedia.org/wiki/Neutron_transport -.. _discretization: https://en.wikipedia.org/wiki/Discretization -.. _constructive solid geometry: https://en.wikipedia.org/wiki/Constructive_solid_geometry -.. _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: 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/openmc-dev/openmc -.. _GitHub: https://github.com/ -.. _bug reports: https://github.com/openmc-dev/openmc/issues -.. _Neutron cross section: https://en.wikipedia.org/wiki/Neutron_cross_section -.. _Effective multiplication factor: https://en.wikipedia.org/wiki/Nuclear_chain_reaction#Effective_neutron_multiplication_factor -.. _Flux: https://en.wikipedia.org/wiki/Neutron_flux diff --git a/docs/source/usersguide/cross_sections.rst b/docs/source/usersguide/cross_sections.rst deleted file mode 100644 index 144b1c152..000000000 --- a/docs/source/usersguide/cross_sections.rst +++ /dev/null @@ -1,267 +0,0 @@ -.. _usersguide_cross_sections: - -=========================== -Cross Section Configuration -=========================== - -In order to run a simulation with OpenMC, you will need cross section data for -each nuclide or material in your problem. OpenMC can be run in continuous-energy -or multi-group mode. - -In continuous-energy mode, OpenMC uses a native `HDF5 -`_ format (see :ref:`io_nuclear_data`) to -store all nuclear data. Pregenerated HDF5 libraries can be found at -https://openmc.org; unless you have specific data needs, it is highly -recommended to use one of the pregenerated libraries. Alternatively, if you have -ACE format data that was produced with NJOY_, such as that distributed with -MCNP_ or Serpent_, it can be converted to the HDF5 format using the :ref:`using -the Python API `. Several sources provide openly available -ACE data including the `ENDF/B`_, JEFF_, and TENDL_ libraries as well as the -`LANL Nuclear Data Team `_. In addition to -tabulated cross sections in the HDF5 files, OpenMC relies on :ref:`windowed -multipole ` data to perform on-the-fly Doppler broadening. - -In multi-group mode, OpenMC utilizes an HDF5-based library format which can be -used to describe nuclide- or material-specific quantities. - ---------------------- -Environment Variables ---------------------- - -When :ref:`scripts_openmc` is run, it will look for several environment -variables that indicate where cross sections can be found. While the location of -cross sections can also be indicated through the -:attr:`openmc.Materials.cross_setion` attribute (or in the :ref:`materials.xml -` file), if you always use the same set of cross section data, it -is often easier to just set an environment variable that will be picked up by -default every time OpenMC is run. The following environment variables are used: - -:envvar:`OPENMC_CROSS_SECTIONS` - Indicates the path to the :ref:`cross_sections.xml ` - summary file that is used to locate HDF5 format cross section libraries if the - user has not specified :attr:`Materials.cross_sections` (equivalently, the - :ref:`cross_sections` in :ref:`materials.xml `). - -:envvar:`OPENMC_MG_CROSS_SECTIONS` - Indicates the path to the an :ref:`HDF5 file ` that contains - multi-group cross sections if the user has not specified - :attr:`Materials.cross_sections` (equivalently, the :ref:`cross_sections` in - :ref:`materials.xml `). - -To set these environment variables persistently, export them from your shell -profile (``.profile`` or ``.bashrc`` in bash_). - -.. _bash: http://www.linuxfromscratch.org/blfs/view/6.3/postlfs/profile.html - --------------------------------- -Continuous-Energy Cross Sections --------------------------------- - -Using Pregenerated Libraries ----------------------------- - -Various evaluated nuclear data libraries have been processed into the HDF5 -format required by OpenMC and can be found at https://openmc.org. You -can find both libraries generated by the OpenMC development team as well as -libraries based on ACE files distributed elsewhere. To use these libraries, -download the archive file, unpack it, and then set your -:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of -the ``cross_sections.xml`` file contained in the unpacked directory. - -.. _create_xs_library: - -Manually Creating a Library from ACE files ------------------------------------------- - -.. currentmodule:: openmc.data - -The scripts described above use the :mod:`openmc.data` module in the Python API -to convert ACE data and create a :ref:`cross_sections.xml ` -file. For those who prefer to use the API directly, the -:class:`openmc.data.IncidentNeutron` and :class:`openmc.data.ThermalScattering` -classes can be used to read ACE data and convert it to HDF5. For -continuous-energy incident neutron data, use the -:meth:`IncidentNeutron.from_ace` class method to read in an existing ACE file -and the :meth:`IncidentNeutron.export_to_hdf5` method to write the data to an -HDF5 file. - -:: - - u235 = openmc.data.IncidentNeutron.from_ace('92235.710nc') - u235.export_to_hdf5('U235.h5') - -If you have multiple ACE files for the same nuclide at different temperatures, -you can use the :meth:`IncidentNeutron.add_temperature_from_ace` method to -append cross sections to an existing :class:`IncidentNeutron` instance:: - - u235 = openmc.data.IncidentNeutron.from_ace('92235.710nc') - for suffix in [711, 712, 713, 714, 715, 716]: - u235.add_temperature_from_ace('92235.{}nc'.format(suffix)) - u235.export_to_hdf5('U235.h5') - -Similar methods exist for thermal scattering data: - -:: - - light_water = openmc.data.ThermalScattering.from_ace('lwtr.20t') - for suffix in range(21, 28): - light_water.add_temperature_from_ace('lwtr.{}t'.format(suffix)) - light_water.export_to_hdf5('lwtr.h5') - -Once you have created corresponding HDF5 files for each of your ACE files, you -can create a library and export it to XML using the -:class:`openmc.data.DataLibrary` class:: - - library = openmc.data.DataLibrary() - library.register_file('U235.h5') - library.register_file('lwtr.h5') - ... - library.export_to_xml() - -At this point, you will have a ``cross_sections.xml`` file that you can use in -OpenMC. - -.. hint:: The :class:`IncidentNeutron` class allows you to view/modify cross - sections, secondary angle/energy distributions, probability tables, - etc. For a more thorough overview of the capabilities of this class, - see the :ref:`notebook_nuclear_data` example notebook. - -Manually Creating a Library from ENDF files -------------------------------------------- - -If you need to create a nuclear data library and you do not already have -suitable ACE files or you need to further customize the data (for example, -adding more temperatures), the :meth:`IncidentNeutron.from_njoy` and -:meth:`ThermalScattering.from_njoy` methods can be used to create data instances -by directly running NJOY_. Both methods require that you pass the name of ENDF -file(s) that are passed on to NJOY. For example, to generate data for Zr-92:: - - zr92 = openmc.data.IncidentNeutron.from_njoy('n-040_Zr_092.endf') - -By default, data is produced at room temperature, 293.6 K. You can also specify -a list of temperatures that you want data at:: - - zr92 = openmc.data.IncidentNeutron.from_njoy( - 'n-040_Zr_092.endf', temperatures=[300., 600., 1000.]) - -The :meth:`IncidentNeutron.from_njoy` method assumes you have an executable -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 -:ref:`create_xs_library`. - -Enabling Resonance Scattering Treatments ----------------------------------------- - -In order for OpenMC to correctly treat elastic scattering in heavy nuclides -where low-lying resonances might be present (see -:ref:`energy_dependent_xs_model`), the elastic scattering cross section at 0 K -must be present. If the data you are using was generated via -:meth:`IncidentNeutron.from_njoy`, you will already have 0 K elastic scattering -cross sections available. Otherwise, to add 0 K elastic scattering cross -sections to an existing :class:`IncidentNeutron` instance, you can use the -:meth:`IncidentNeutron.add_elastic_0K_from_endf` method which requires an ENDF -file for the nuclide you are modifying:: - - u238 = openmc.data.IncidentNeutron.from_hdf5('U238.h5') - u238.add_elastic_0K_from_endf('n-092_U_238.endf') - u238.export_to_hdf5('U238_with_0K.h5') - -With 0 K elastic scattering data present, you can turn on a resonance scattering -method using :attr:`Settings.resonance_scattering`. - -.. note:: The process of reconstructing resonances and generating tabulated 0 K - cross sections can be computationally expensive, especially for - nuclides like U-238 where thousands of resonances are present. Thus, - running the :meth:`IncidentNeutron.add_elastic_0K_from_endf` method - may take several minutes to complete. - -Photon Cross Sections ---------------------- - -Photon interaction data is needed to run OpenMC with photon transport enabled. -Some of this data, namely bremsstrahlung cross sections from `Seltzer and -Berger`_, mean excitation energy from the `NIST ESTAR database`_, and Compton -profiles calculated by `Biggs et al.`_ and available in the Geant4 G4EMLOW data -file, is distributed with OpenMC. The rest is available from the NNDC_, which -provides ENDF data from the photo-atomic and atomic relaxation sublibraries of -the ENDF/B-VII.1 library. - -Most of the pregenerated HDF5 libraries available at https://openmc.org -already have photon interaction data included. If you are building a data -library yourself, it is possible to use the Python API directly to convert -photon interaction data from an ENDF or ACE file to an HDF5 file. The -:class:`openmc.data.IncidentPhoton` class contains an -:meth:`IncidentPhoton.from_ace` method that will generate photon data from an -ACE table and an :meth:`IncidentPhoton.export_to_hdf5` method that writes the -data to an HDF5 file: - -:: - - u = openmc.data.IncidentPhoton.from_ace('92000.12p') - u.export_to_hdf5('U.h5') - -Similarly, the :meth:`IncidentPhoton.from_endf` method can be used to read -photon data from an ENDF file. In this case, both the photo-atomic and atomic -relaxation sublibrary files are required: - -:: - - u = openmc.data.IncidentPhoton.from_endf('photoat-092_U_000.endf', - 'atom-092_U_000.endf') - -Once the HDF5 files have been generated, a library can be created using the -:class:`DataLibrary` class as described in :ref:`create_xs_library`. - ------------------------ -Windowed Multipole Data ------------------------ - -OpenMC is capable of using windowed multipole data for on-the-fly Doppler -broadening. A comprehensive multipole data library containing all nuclides in -ENDF/B-VII.1 is available on `GitHub -`_. To obtain this library, download -and unpack an archive (.zip or .tag.gz) from GitHub. Once unpacked, you can use -the :class:`openmc.data.DataLibrary` class to register the .h5 files as -described in :ref:`create_xs_library`. - -The `official ENDF/B-VII.1 HDF5 library -`_ includes the windowed -multipole library, so if you are using this library, the windowed multipole data -will already be available to you. - --------------------------- -Multi-Group Cross Sections --------------------------- - -Multi-group cross section libraries are generally tailored to the specific -calculation to be performed. Therefore, at this point in time, OpenMC is not -distributed with any pre-existing multi-group cross section libraries. -However, if obtained or generated their own library, the user -should set the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable -to the absolute path of the file library expected to used most frequently. - -For an example of how to create a multi-group library, see -:ref:`notebook_mg_mode_part_i`. - -.. _NJOY: http://www.njoy21.io/ -.. _NNDC: https://www.nndc.bnl.gov/endf -.. _MCNP: https://mcnp.lanl.gov -.. _Serpent: http://montecarlo.vtt.fi -.. _ENDF/B: https://www.nndc.bnl.gov/endf/b7.1/acefiles.html -.. _JEFF: http://www.oecd-nea.org/dbdata/jeff/jeff33/ -.. _TENDL: https://tendl.web.psi.ch/tendl_2017/tendl2017.html -.. _Seltzer and Berger: https://doi.org/10.1016/0092-640X(86)90014-8 -.. _NIST ESTAR database: https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html -.. _Biggs et al.: https://doi.org/10.1016/0092-640X(75)90030-3 diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst deleted file mode 100644 index 9e2693098..000000000 --- a/docs/source/usersguide/depletion.rst +++ /dev/null @@ -1,137 +0,0 @@ -.. _usersguide_depletion: - -========= -Depletion -========= - -OpenMC supports coupled depletion, or burnup, calculations through the -:mod:`openmc.deplete` Python module. OpenMC solves the transport equation to -obtain transmutation reaction rates, and then the reaction rates are used to -solve a set of transmutation equations that determine the evolution of nuclide -densities within a material. The nuclide densities predicted as some future time -are then used to determine updated reaction rates, and the process is repeated -for as many timesteps as are requested. - -The depletion module is designed such that the flux/reaction rate solution (the -transport "operator") is completely isolated from the solution of the -transmutation equations and the method used for advancing time. At present, the -:mod:`openmc.deplete` module offers a single transport operator, -:class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but -in principle additional operator classes based on other transport codes could be -implemented and no changes to the depletion solver itself would be needed. The -operator class requires a :class:`openmc.Geometry` instance and a -:class:`openmc.Settings` instance:: - - geom = openmc.Geometry() - settings = openmc.Settings() - ... - - op = openmc.deplete.Operator(geom, settings) - -:mod:`openmc.deplete` supports multiple time-integration methods for determining -material compositions over time. Each method appears as a different class. -For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation -using the CE/CM algorithm (deplete over a timestep using the middle-of-step -reaction rates). An instance of :class:`openmc.deplete.Operator` is passed to -one of these functions along with the power level and timesteps:: - - power = 1200.0e6 - days = 24*60*60 - timesteps = [10.0*days, 10.0*days, 10.0*days] - openmc.deplete.CECMIntegrator(op, power, timesteps).integrate() - -The coupled transport-depletion problem is executed, and once it is done a -``depletion_results.h5`` file is written. The results can be analyzed using the -:class:`openmc.deplete.ResultsList` class. This class has methods that allow for -easy retrieval of k-effective, nuclide concentrations, and reaction rates over -time:: - - results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") - time, keff = results.get_eigenvalue() - -Note that the coupling between the transport solver and the transmutation solver -happens in-memory rather than by reading/writing files on disk. - -Caveats -======= - -Energy Deposition ------------------ - -The default energy deposition mode, ``"fission-q"``, instructs the -:class:`openmc.deplete.Operator` to normalize reaction rates using the product -of fission reaction rates and fission Q values taken from the depletion chain. -This approach does not consider indirect contributions to energy deposition, -such as neutron heating and energy from secondary photons. In doing this, -the energy deposited during a transport calculation will be lower than expected. -This causes the reaction rates to be over-adjusted to hit the user-specific power, -or power density, leading to an over-depletion of burnable materials. - -There are some remedies. First, the fission Q values can be directly set in a -variety of ways. This requires knowing what the total fission energy release should -be, including indirect components. Some examples are provided below:: - - # use a dictionary of fission_q values - fission_q = {"U235": 202} # energy in MeV - - # create a modified chain and write it to a new file - chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q) - chain.export_to_xml("chain_mod_q.xml") - op = openmc.deplete.Operator(geometry, setting, "chain_mod_q.xml") - - # alternatively, pass the modified fission Q directly to the operator - op = openmc.deplete.Operator(geometry, setting, "chain.xml", - fission_q=fission_q) - - -A more complete way to model the energy deposition is to use the modified heating -reactions described in :ref:`methods_heating`. These values can be used to normalize -reaction rates instead of using the fission reaction rates with:: - - op = openmc.deplete.Operator(geometry, settings, "chain.xml", - energy_mode="energy-deposition") - -These modified heating libraries can be generated by running the latest version -of :meth:`openmc.data.IncidentNeutron.from_njoy`, and will eventually be bundled into -the distributed libraries. - -Local Spectra and Repeated Materials ------------------------------------- - -It is not uncommon to explicitly create a single burnable material across many locations. -From a pure transport perspective, there is nothing wrong with creating a single -3.5 wt.% enriched fuel ``fuel_3``, and placing that fuel in every fuel pin in an assembly -or even full core problem. This certainly expedites the model making process, but can pose -issues with depletion. -Under this setup, :mod:`openmc.deplete` will deplete a single ``fuel_3`` material using -a single set of reaction rates, and produce a single new composition for the next time -step. This can be problematic if the same ``fuel_3`` is used in very different regions -of the problem. - -As an example, consider a full-scale power reactor core with vacuum boundary -conditions, and with fuel pins solely composed of the same ``fuel_3`` material. -The fuel pins towards the center of the problem will surely experience a more intense -neutron flux and greater reaction rates than those towards the edge of the domain. -This indicates that the fuel in the center should be at a more depleted state than -periphery pins, at least for the fist depletion step. -However, without any other instructions, OpenMC will deplete ``fuel_3`` as a single -material, and all of the fuel pins will have an identical composition at the next -transport step. - -This can be countered by instructing the operator to treat repeated instances -of the same material as a unique material definition with:: - - op = openmc.deplete.Operator(geometry, settings, chain_file, - diff_burnable_mats=True) - -For our example problem, this would deplete fuel on the outer region of the problem -with different reaction rates than those in the center. Materials will be depleted -corresponding to their local neutron spectra, and have unique compositions at each -transport step. - - -.. note:: - - This will increase the total memory usage and run time due to an increased - number of tallies and material definitions. - diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst deleted file mode 100644 index dc7dd978e..000000000 --- a/docs/source/usersguide/geometry.rst +++ /dev/null @@ -1,436 +0,0 @@ -.. _usersguide_geometry: - -================= -Defining Geometry -================= - -.. currentmodule:: openmc - --------------------- -Surfaces and Regions --------------------- - -The geometry of a model in OpenMC is defined using `constructive solid -geometry`_ (CSG), also sometimes referred to as combinatorial geometry. CSG -allows a user to create complex regions using Boolean operators (intersection, -union, and complement) on simpler regions. In order to define a region that we -can assign to a cell, we must first define surfaces which bound the region. A -surface is a locus of zeros of a function of Cartesian coordinates -:math:`x,y,z`, e.g. - -- A plane perpendicular to the :math:`x` axis: :math:`x - x_0 = 0` -- A cylinder parallel to the :math:`z` axis: :math:`(x - x_0)^2 + (y - - y_0)^2 - R^2 = 0` -- A sphere: :math:`(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0` - -Defining a surface alone is not sufficient to specify a volume -- in order to -define an actual volume, one must reference the *half-space* of a surface. A -surface half-space is the region whose points satisfy a positive or negative -inequality of the surface equation. For example, for a sphere of radius one -centered at the origin, the surface equation is :math:`f(x,y,z) = x^2 + y^2 + -z^2 - 1 = 0`. Thus, we say that the negative half-space of the sphere, is -defined as the collection of points satisfying :math:`f(x,y,z) < 0`, which one -can reason is the inside of the sphere. Conversely, the positive half-space of -the sphere would correspond to all points outside of the sphere, satisfying -:math:`f(x,y,z) > 0`. - -In the Python API, surfaces are created via subclasses of -:class:`openmc.Surface`. The available surface types and their corresponding -classes are listed in the following table. - -.. table:: Surface types available in OpenMC. - - +----------------------+------------------------------+---------------------------+ - | Surface | Equation | Class | - +======================+==============================+===========================+ - | Plane perpendicular | :math:`x - x_0 = 0` | :class:`openmc.XPlane` | - | to :math:`x`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Plane perpendicular | :math:`y - y_0 = 0` | :class:`openmc.YPlane` | - | to :math:`y`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Plane perpendicular | :math:`z - z_0 = 0` | :class:`openmc.ZPlane` | - | to :math:`z`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Arbitrary plane | :math:`Ax + By + Cz = D` | :class:`openmc.Plane` | - +----------------------+------------------------------+---------------------------+ - | Infinite cylinder | :math:`(y-y_0)^2 + (z-z_0)^2 | :class:`openmc.XCylinder` | - | parallel to | - R^2 = 0` | | - | :math:`x`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Infinite cylinder | :math:`(x-x_0)^2 + (z-z_0)^2 | :class:`openmc.YCylinder` | - | parallel to | - R^2 = 0` | | - | :math:`y`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Infinite cylinder | :math:`(x-x_0)^2 + (y-y_0)^2 | :class:`openmc.ZCylinder` | - | parallel to | - R^2 = 0` | | - | :math:`z`-axis | | | - +----------------------+------------------------------+---------------------------+ - | Sphere | :math:`(x-x_0)^2 + (y-y_0)^2 | :class:`openmc.Sphere` | - | | + (z-z_0)^2 - R^2 = 0` | | - +----------------------+------------------------------+---------------------------+ - | Cone parallel to the | :math:`(y-y_0)^2 + (z-z_0)^2 | :class:`openmc.XCone` | - | :math:`x`-axis | - R^2(x-x_0)^2 = 0` | | - +----------------------+------------------------------+---------------------------+ - | Cone parallel to the | :math:`(x-x_0)^2 + (z-z_0)^2 | :class:`openmc.YCone` | - | :math:`y`-axis | - R^2(y-y_0)^2 = 0` | | - +----------------------+------------------------------+---------------------------+ - | Cone parallel to the | :math:`(x-x_0)^2 + (y-y_0)^2 | :class:`openmc.ZCone` | - | :math:`z`-axis | - R^2(z-z_0)^2 = 0` | | - +----------------------+------------------------------+---------------------------+ - | General quadric | :math:`Ax^2 + By^2 + Cz^2 + | :class:`openmc.Quadric` | - | surface | Dxy + Eyz + Fxz + Gx + Hy + | | - | | Jz + K = 0` | | - +----------------------+------------------------------+---------------------------+ - -Each surface is characterized by several parameters. As one example, the -parameters for a sphere are the :math:`x,y,z` coordinates of the center of the -sphere and the radius of the sphere. All of these parameters can be set either -as optional keyword arguments to the class constructor or via attributes:: - - sphere = openmc.Sphere(r=10.0) - - # This is equivalent - sphere = openmc.Sphere() - sphere.r = 10.0 - -Once a surface has been created, half-spaces can be obtained by applying the -unary ``-`` or ``+`` operators, corresponding to the negative and positive -half-spaces, respectively. For example:: - - >>> sphere = openmc.Sphere(r=10.0) - >>> inside_sphere = -sphere - >>> outside_sphere = +sphere - >>> type(inside_sphere) - - -Instances of :class:`openmc.Halfspace` can be combined together using the -Boolean operators ``&`` (intersection), ``|`` (union), and ``~`` (complement):: - - >>> inside_sphere = -openmc.Sphere() - >>> above_plane = +openmc.ZPlane() - >>> northern_hemisphere = inside_sphere & above_plane - >>> type(northern_hemisphere) - - -For many regions, a bounding-box can be determined automatically:: - - >>> northern_hemisphere.bounding_box - (array([-1., -1., 0.]), array([1., 1., 1.])) - -While a bounding box can be determined for regions involving half-spaces of -spheres, cylinders, and axis-aligned planes, it generally cannot be determined -if the region involves cones, non-axis-aligned planes, or other exotic -second-order surfaces. For example, the :func:`openmc.model.hexagonal_prism` -function returns the interior region of a hexagonal prism; because it is bounded -by a :class:`openmc.Plane`, trying to get its bounding box won't work:: - - >>> hex = openmc.model.hexagonal_prism() - >>> hex.bounding_box - (array([-0.8660254, -inf, -inf]), - array([ 0.8660254, inf, inf])) - -Boundary Conditions -------------------- - -When a surface is created, by default particles that pass through the surface -will consider it to be transmissive, i.e., they pass through the surface -freely. If your model does not extend to infinity in all spatial dimensions, you -may want to specify different behavior for particles passing through a -surface. To specify a vacuum boundary condition, simply change the -:attr:`Surface.boundary_type` attribute to 'vacuum':: - - outer_surface = openmc.Sphere(r=100.0, boundary_type='vacuum') - - # This is equivalent - outer_surface = openmc.Sphere(r=100.0) - outer_surface.boundary_type = 'vacuum' - -Reflective and periodic boundary conditions can be set with the strings -'reflective' and 'periodic'. Vacuum and reflective boundary conditions can be -applied to any type of surface. Periodic boundary conditions can be applied to -pairs of planar surfaces. For axis-aligned planes, matching periodic surfaces -can be determined automatically. For non-axis-aligned planes, it is necessary to -specify pairs explicitly using the :attr:`Surface.periodic_surface` attribute as -in the following example:: - - p1 = openmc.Plane(a=0.3, b=5.0, d=1.0, boundary_type='periodic') - p2 = openmc.Plane(a=0.3, b=5.0, d=-1.0, boundary_type='periodic') - p1.periodic_surface = p2 - -Rotationally-periodic boundary conditions can be specified for a pair of -:class:`XPlane` and :class:`YPlane`; in that case, the -:attr:`Surface.periodic_surface` attribute must be specified manually as well. - -.. caution:: When using rotationally-periodic boundary conditions, your geometry - must be defined in the first quadrant, i.e., above the y-plane and - to the right of the x-plane. - -.. _usersguide_cells: - ------ -Cells ------ - -Once you have a material created and a region of space defined, you need to -define a *cell* that assigns the material to the region. Cells are created using -the :class:`openmc.Cell` class:: - - fuel = openmc.Cell(fill=uo2, region=pellet) - - # This is equivalent - fuel = openmc.Cell() - fuel.fill = uo2 - fuel.region = pellet - -In this example, an instance of :class:`openmc.Material` is assigned to the -:attr:`Cell.fill` attribute. One can also fill a cell with a :ref:`universe -` or :ref:`lattice `. - -The classes :class:`Halfspace`, :class:`Intersection`, :class:`Union`, and -:class:`Complement` and all instances of :class:`openmc.Region` and can be -assigned to the :attr:`Cell.region` attribute. - -.. _usersguide_universes: - ---------- -Universes ---------- - -Similar to MCNP and Serpent, OpenMC is capable of using *universes*, collections -of cells that can be used as repeatable units of geometry. At a minimum, there -must be one "root" universe present in the model. To define a universe, an -instance of :class:`openmc.Universe` is created and then cells can be added -using the :meth:`Universe.add_cells` or :meth:`Universe.add_cell` -methods. Alternatively, a list of cells can be specified in the constructor:: - - universe = openmc.Universe(cells=[cell1, cell2, cell3]) - - # This is equivalent - universe = openmc.Universe() - universe.add_cells([cell1, cell2]) - universe.add_cell(cell3) - -Universes are generally used in three ways: - -1. To be assigned to a :class:`Geometry` object (see - :ref:`usersguide_geom_export`), -2. To be assigned as the fill for a cell via the :attr:`Cell.fill` attribute, - and -3. To be used in a regular arrangement of universes in a :ref:`lattice - `. - -Once a universe is constructed, it can actually be used to determine what cell -or material is found at a given location by using the :meth:`Universe.find` -method, which returns a list of universes, cells, and lattices which are -traversed to find a given point. The last element of that list would contain the -lowest-level cell at that location:: - - >>> universe.find((0., 0., 0.))[-1] - Cell - ID = 10000 - Name = cell 1 - Fill = Material 10000 - Region = -10000 - Rotation = None - Temperature = None - Translation = None - -As you are building a geometry, it is also possible to display a plot of single -universe using the :meth:`Universe.plot` method. This method requires that you -have `matplotlib `_ installed. - -.. _usersguide_lattices: - --------- -Lattices --------- - -Many particle transport models involve repeated structures that occur in a -regular pattern such as a rectangular or hexagonal lattice. In such a case, it -would be cumbersome to have to define the boundaries of each of the cells to be -filled with a universe. OpenMC provides a means to define lattice structures -through the :class:`openmc.RectLattice` and :class:`openmc.HexLattice` classes. - -Rectangular Lattices --------------------- - -A rectangular lattice defines a two-dimensional or three-dimensional array of -universes that are filled into rectangular prisms (lattice elements) each of -which has the same width, length, and height. To completely define a rectangular -lattice, one needs to specify - -- The coordinates of the lower-left corner of the lattice - (:attr:`RectLattice.lower_left`), -- The pitch of the lattice, i.e., the distance between the center of adjacent - lattice elements (:attr:`RectLattice.pitch`), -- What universes should fill each lattice element - (:attr:`RectLattice.universes`), and -- A universe that is used to fill any lattice position outside the well-defined - portion of the lattice (:attr:`RectLattice.outer`). - -For example, to create a 3x3 lattice centered at the origin in which each -lattice element is 5cm by 5cm and is filled by a universe ``u``, one could run:: - - lattice = openmc.RectLattice() - lattice.lower_left = (-7.5, -7.5) - lattice.pitch = (5.0, 5.0) - lattice.universes = [[u, u, u], - [u, u, u], - [u, u, u]] - -Note that because this is a two-dimensional lattice, the lower-left coordinates -and pitch only need to specify the :math:`x,y` values. The order that the -universes appear is such that the first row corresponds to lattice elements with -the highest :math:`y` -value. Note that the :attr:`RectLattice.universes` -attribute expects a doubly-nested iterable of type :class:`openmc.Universe` --- -this can be normal Python lists, as shown above, or a NumPy array can be used as -well:: - - lattice.universes = np.tile(u, (3, 3)) - -For a three-dimensional lattice, the :math:`x,y,z` coordinates of the lower-left -coordinate need to be given and the pitch should also give dimensions for all -three axes. For example, to make a 3x3x3 lattice where the bottom layer is -universe ``u``, the middle layer is universe ``q`` and the top layer is universe -``z`` would look like:: - - lat3d = openmc.RectLattice() - lat3d.lower_left = (-7.5, -7.5, -7.5) - lat3d.pitch = (5.0, 5.0, 5.0) - lat3d.universes = [ - [[u, u, u], - [u, u, u], - [u, u, u]], - [[q, q, q], - [q, q, q], - [q, q, q]], - [[z, z, z], - [z, z, z] - [z, z, z]]] - -Again, using NumPy can make things easier:: - - lat3d.universes = np.empty((3, 3, 3), dtype=openmc.Universe) - lat3d.universes[0, ...] = u - lat3d.universes[1, ...] = q - lat3d.universes[2, ...] = z - -Finally, it's possible to specify that lattice positions that aren't normally -without the bounds of the lattice be filled with an "outer" universe. This -allows one to create a truly infinite lattice if desired. An outer universe is -set with the :attr:`RectLattice.outer` attribute. - -Hexagonal Lattices ------------------- - -OpenMC also allows creation of 2D and 3D hexagonal lattices. Creating a -hexagonal lattice is similar to creating a rectangular lattice with a few -differences: - -- The center of the lattice must be specified (:attr:`HexLattice.center`). -- For a 2D hexagonal lattice, a single value for the pitch should be specified, - although it still needs to appear in a list. For a 3D hexagonal lattice, the - pitch in the radial and axial directions should be given. -- For a hexagonal lattice, the :attr:`HexLattice.universes` attribute cannot be - given as a NumPy array for reasons explained below. -- As with rectangular lattices, the :attr:`HexLattice.outer` attribute will - specify an outer universe. - -For a 2D hexagonal lattice, the :attr:`HexLattice.universes` attribute should be -set to a two-dimensional list of universes filling each lattice element. Each -sub-list corresponds to one ring of universes and is ordered from the outermost -ring to the innermost ring. The universes within each sub-list are ordered from -the "top" (position with greatest y value) and proceed in a clockwise fashion -around the ring. The :meth:`HexLattice.show_indices` static method can be used -to help figure out how to place universes:: - - >>> print(openmc.HexLattice.show_indices(3)) - (0, 0) - (0,11) (0, 1) - (0,10) (1, 0) (0, 2) - (1, 5) (1, 1) - (0, 9) (2, 0) (0, 3) - (1, 4) (1, 2) - (0, 8) (1, 3) (0, 4) - (0, 7) (0, 5) - (0, 6) - - -Note that by default, hexagonal lattices are positioned such that each lattice -element has two faces that are parallel to the :math:`y` axis. As one example, -to create a three-ring lattice centered at the origin with a pitch of 10 cm -where all the lattice elements centered along the :math:`y` axis are filled with -universe ``u`` and the remainder are filled with universe ``q``, the following -code would work:: - - hexlat = openmc.HexLattice() - hexlat.center = (0, 0) - hexlat.pitch = [10] - - outer_ring = [u, q, q, q, q, q, u, q, q, q, q, q] - middle_ring = [u, q, q, u, q, q] - inner_ring = [u] - hexlat.universes = [outer_ring, middle_ring, inner_ring] - -If you need to create a hexagonal boundary (composed of six planar surfaces) for -a hexagonal lattice, :func:`openmc.model.hexagonal_prism` can be used. - -.. _usersguide_geom_export: - --------------------------- -Exporting a Geometry Model --------------------------- - -Once you have finished building your geometry by creating surfaces, cell, and, -if needed, lattices, the last step is to create an instance of -:class:`openmc.Geometry` and export it to an XML file that the -:ref:`scripts_openmc` executable can read using the -:meth:`Geometry.export_to_xml` method. This can be done as follows:: - - geom = openmc.Geometry(root_univ) - geom.export_to_xml() - - # This is equivalent - geom = openmc.Geometry() - geom.root_universe = root_univ - geom.export_to_xml() - -Note that it's not strictly required to manually create a root universe. You can -also pass a list of cells to the :class:`openmc.Geometry` constructor and it -will handle creating the unverse:: - - geom = openmc.Geometry([cell1, cell2, cell3]) - geom.export_to_xml() - -.. _constructive solid geometry: https://en.wikipedia.org/wiki/Constructive_solid_geometry -.. _quadratic surfaces: https://en.wikipedia.org/wiki/Quadric - --------------------------- -Using CAD-based Geometry --------------------------- - -OpenMC relies on the Direct Accelerated Geometry Monte Carlo toolkit (`DAGMC -`_) to represent CAD-based geometry in a -surface mesh format. A DAGMC run can be enabled in OpenMC by setting the -``dagmc`` property to ``True`` in the model Settings either via the Python -:class:`openmc.settings` Python class:: - - settings = openmc.Settings() - settings.dagmc = True - -or in the :ref:`settings.xml ` file:: - - true - -With ``dagmc`` set to true, OpenMC will load the DAGMC model (from a local file -named ``dagmc.h5m``) when initializing a simulation. If a `geometry.xml -<../io_formats/geometry.html>`_ is present as well, it will be ignored. - - **Note:** DAGMC geometries used in OpenMC are currently required to be clean, - meaning that all surfaces have been `imprinted and merged - `_ - successfully and that the model is `watertight - `_. Future - implementations of DAGMC geometry will support small volume overlaps and - un-merged surfaces. diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst deleted file mode 100644 index fab353c77..000000000 --- a/docs/source/usersguide/index.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _usersguide: - -============ -User's Guide -============ - -Welcome to the OpenMC User's Guide! This tutorial will guide you through the -essential aspects of using OpenMC to perform simulations. - -.. toctree:: - :numbered: - :maxdepth: 1 - - beginners - install - cross_sections - basics - materials - geometry - settings - tallies - plots - depletion - scripts - processing - parallel - volume - troubleshoot diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst deleted file mode 100644 index 8ca7e0b35..000000000 --- a/docs/source/usersguide/install.rst +++ /dev/null @@ -1,492 +0,0 @@ -.. _usersguide_install: - -============================== -Installation and Configuration -============================== - -.. currentmodule:: openmc - -.. _install_conda: - ----------------------------------------- -Installing on Linux/Mac with conda-forge ----------------------------------------- - -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 -`_ is a community-led conda channel of -installable packages. For instructions on installing conda, please consult their -`documentation -`_. - -Once you have `conda` installed on your system, add the `conda-forge` channel to -your configuration with: - -.. code-block:: sh - - conda config --add channels conda-forge - -Once the `conda-forge` channel has been enabled, OpenMC can then be installed -with: - -.. code-block:: sh - - conda install openmc - -It is possible to list all of the versions of OpenMC available on your platform with: - -.. code-block:: sh - - conda search openmc --channel conda-forge - -.. _install_ppa: - ------------------------------ -Installing on Ubuntu with PPA ------------------------------ - -For users with Ubuntu 15.04 or later, a binary package for OpenMC is available -through a `Personal Package Archive`_ (PPA) and can be installed through the -`APT package manager`_. First, add the following PPA to the repository sources: - -.. code-block:: sh - - sudo apt-add-repository ppa:paulromano/staging - -Next, resynchronize the package index files: - -.. code-block:: sh - - sudo apt update - -Now OpenMC should be recognized within the repository and can be installed: - -.. code-block:: sh - - 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 - -.. _install_source: - ----------------------- -Installing from Source ----------------------- - -.. _prerequisites: - -Prerequisites -------------- - -.. admonition:: Required - :class: error - - * A C/C++ compiler such as gcc_ - - OpenMC's core codebase is written in C++. The 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++ - - * CMake_ cross-platform build system - - The compiling and linking of source files is handled by CMake in a - platform-independent manner. If you are using Debian or a Debian - derivative such as Ubuntu, you can install CMake using the following - command:: - - sudo apt install cmake - - * HDF5_ Library for portable binary output format - - 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:: - - 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.:: - - CXX=mpicxx.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:: - - CC=mpicc ./configure --enable-parallel - - You may omit ``--enable-parallel`` if you want to compile HDF5_ in serial. - -.. admonition:: Optional - :class: note - - * An MPI implementation for distributed-memory parallel runs - - To compile with support for parallel runs on a distributed-memory - architecture, you will need to have a valid implementation of MPI - installed on your machine. The code has been tested and is known to work - with the latest versions of both OpenMPI_ and MPICH_. OpenMPI and/or MPICH - can be installed on Debian derivatives with:: - - sudo apt install mpich libmpich-dev - sudo apt install openmpi-bin libopenmpi-dev - - * DAGMC_ toolkit for simulation using CAD-based geometries - - OpenMC supports particle tracking in CAD-based geometries via the Direct - Accelerated Geometry Monte Carlo (DAGMC) toolkit (`installation - instructions - `_). For use in - OpenMC, only the ``MOAB_DIR`` and ``BUILD_TALLY`` variables need to be - specified in the CMake configuration step. - - * git_ version control software for obtaining source code - - -.. _gcc: https://gcc.gnu.org/ -.. _CMake: http://www.cmake.org -.. _OpenMPI: http://www.open-mpi.org -.. _MPICH: http://www.mpich.org -.. _HDF5: https://www.hdfgroup.org/solutions/hdf5/ -.. _DAGMC: https://svalinn.github.io/DAGMC/index.html - -Obtaining the Source --------------------- - -All OpenMC source code is hosted on GitHub_. You can download the source code -directly from GitHub or, if you have the git_ version control software installed -on your computer, you can use git to obtain the source code. The latter method -has the benefit that it is easy to receive updates directly from the GitHub -repository. GitHub has a good set of `instructions -`_ for how to set up git to work -with GitHub since this involves setting up ssh_ keys. With git installed and -setup, the following command will download the full source code from the GitHub -repository:: - - git clone https://github.com/openmc-dev/openmc.git - -By default, the cloned repository will be set to the development branch. To -switch to the source of the latest stable release, run the following commands:: - - cd openmc - git checkout master - -.. _GitHub: https://github.com/openmc-dev/openmc -.. _git: https://git-scm.com -.. _ssh: https://en.wikipedia.org/wiki/Secure_Shell - -.. _usersguide_build: - -Build Configuration -------------------- - -Compiling OpenMC with CMake is carried out in two steps. First, ``cmake`` is run -to determine the compiler, whether optional packages (MPI, HDF5) are available, -to generate a list of dependencies between source files so that they may be -compiled in the correct order, and to generate a normal Makefile. The Makefile -is then used by ``make`` to actually carry out the compile and linking -commands. A typical out-of-source build would thus look something like the -following - -.. code-block:: sh - - mkdir build && cd build - cmake .. - make - -Note that first a build directory is created as a subdirectory of the source -directory. The Makefile in the top-level directory will automatically perform an -out-of-source build with default options. - -CMakeLists.txt Options -++++++++++++++++++++++ - -The following options are available in the CMakeLists.txt file: - -debug - Enables debugging when compiling. The flags added are dependent on which - compiler is used. - -profile - Enables profiling using the GNU profiler, gprof. - -optimize - Enables high-optimization using compiler-dependent flags. For gcc and - Intel C++, this compiles with -O3. - -openmp - Enables shared-memory parallelism using the OpenMP API. The C++ compiler - being used must support OpenMP. (Default: on) - -dagmc - Enables use of CAD-based DAGMC_ geometries. Please see the note about DAGMC in - the optional dependencies list for more information on this feature. The - installation directory for DAGMC should also be defined as `DAGMC_ROOT` in the - CMake configuration command. (Default: off) - -coverage - Compile and link code instrumented for coverage analysis. This is typically - used in conjunction with gcov_. - -To set any of these options (e.g. turning on debug mode), the following form -should be used: - -.. code-block:: sh - - cmake -Ddebug=on /path/to/openmc - -.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html - -.. _usersguide_compile_mpi: - -Compiling with MPI -++++++++++++++++++ - -To compile with MPI, set the :envvar:`CXX` environment variable to the path to -the MPI C++ wrapper. For example, in a bash shell: - -.. code-block:: sh - - export CXX=mpicxx - cmake /path/to/openmc - -Note that in many shells, environment variables can be set for a single command, -i.e. - -.. code-block:: sh - - CXX=mpicxx cmake /path/to/openmc - -Selecting HDF5 Installation -+++++++++++++++++++++++++++ - -CMakeLists.txt searches for the ``h5cc`` or ``h5pcc`` HDF5 C wrapper on -your PATH environment variable and subsequently uses it to determine library -locations and compile flags. If you have multiple installations of HDF5 or one -that does not appear on your PATH, you can set the HDF5_ROOT environment -variable to the root directory of the HDF5 installation, e.g. - -.. code-block:: sh - - export HDF5_ROOT=/opt/hdf5/1.8.15 - cmake /path/to/openmc - -This will cause CMake to search first in /opt/hdf5/1.8.15/bin for ``h5cc`` / -``h5pcc`` before it searches elsewhere. As noted above, an environment variable -can typically be set for a single command, i.e. - -.. code-block:: sh - - HDF5_ROOT=/opt/hdf5/1.8.15 cmake /path/to/openmc - -.. _compile_linux: - -Compiling on Linux and Mac OS X -------------------------------- - -To compile OpenMC on Linux or Max OS X, run the following commands from within -the root directory of the source code: - -.. code-block:: sh - - mkdir build && cd build - cmake .. - make - make install - -This will build an executable named ``openmc`` and install it (by default in -/usr/local/bin). If you do not have administrative privileges, you can install -OpenMC locally by specifying an install prefix when running cmake: - -.. code-block:: sh - - cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local .. - -The ``CMAKE_INSTALL_PREFIX`` variable can be changed to any path for which you -have write-access. - -Compiling on Windows 10 ------------------------ - -Recent versions of Windows 10 include a subsystem for Linux that allows one to -run Bash within Ubuntu running in Windows. First, follow the installation guide -`here `_ to get -Bash on Ubuntu on Windows setup. Once you are within bash, obtain the necessary -:ref:`prerequisites ` via ``apt``. Finally, follow the -:ref:`instructions for compiling on linux `. - -Compiling for the Intel Xeon Phi --------------------------------- - -For the second generation Knights Landing architecture, nothing special is -required to compile OpenMC. You may wish to experiment with compiler flags that -control generation of vector instructions to see what configuration gives -optimal performance for your target problem. - -For the first generation Knights Corner architecture, it is necessary to -cross-compile OpenMC. If you are using the Intel compiler, it is necessary to -specify that all objects be compiled with the ``-mmic`` flag as follows: - -.. code-block:: sh - - mkdir build && cd build - CXX=icpc CXXFLAGS=-mmic cmake -Dopenmp=on .. - make - -Note that unless an HDF5 build for the Intel Xeon Phi (Knights Corner) is -already on your target machine, you will need to cross-compile HDF5 for the Xeon -Phi. An `example script`_ to build zlib and HDF5 provides several necessary -workarounds. - -.. _example script: https://github.com/paulromano/install-scripts/blob/master/install-hdf5-mic - -Testing Build -------------- - -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 ` or :ref:`PPA -`, no further steps are necessary in order to use OpenMC's -:ref:`Python API `. However, if you are :ref:`installing from 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 -`_). 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 - - pip install . - -pip will first check that all :ref:`required third-party packages -` have been installed, and if they are not present, -they will be installed by downloading the appropriate packages from the Python -Package Index (`PyPI `_). However, do note that since pip -runs the ``setup.py`` script which requires NumPy, you will have to first -install NumPy: - -.. code-block:: sh - - pip install numpy - -Installing in "Development" Mode --------------------------------- - -If you are primarily doing development with OpenMC, it is strongly recommended -to install the Python package in :ref:`"editable" mode `. - -.. _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. To run simulations in parallel using MPI, it is recommended to -build mpi4py, HDF5, h5py from source, in that order, using the same compilers -as for OpenMC. - -.. admonition:: Required - :class: error - - `NumPy `_ - NumPy is used extensively within the Python API for its powerful - N-dimensional array. - - `SciPy `_ - SciPy's special functions, sparse matrices, and spatial data structures - are used for several optional features in the API. - - `pandas `_ - Pandas is used to generate tally DataFrames as demonstrated in - :ref:`examples_pandas` example notebook. - - `h5py `_ - h5py provides Python bindings to the HDF5 library. Since OpenMC outputs - various HDF5 files, h5py is needed to provide access to data within these - files from Python. - - `Matplotlib `_ - Matplotlib is used to providing plotting functionality in the API like the - :meth:`Universe.plot` method and the :func:`openmc.plot_xs` function. - - `uncertainties `_ - Uncertainties are used for decay data in the :mod:`openmc.data` module. - - `lxml `_ - lxml is used for the :ref:`scripts_validate` script and various other - parts of the Python API. - -.. admonition:: Optional - :class: note - - `mpi4py `_ - 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 `_ - Cython is used for resonance reconstruction for ENDF data converted to - :class:`openmc.data.IncidentNeutron`. - - `vtk `_ - The Python VTK bindings are needed to convert voxel and track files to VTK - format. - - `pytest `_ - The pytest framework is used for unit testing the Python API. - -.. _usersguide_nxml: - ------------------------------------------------------ -Configuring Input Validation with GNU Emacs nXML mode ------------------------------------------------------ - -The `GNU Emacs`_ text editor has a built-in mode that extends functionality for -editing XML files. One of the features in nXML mode is the ability to perform -real-time `validation`_ of XML files against a `RELAX NG`_ schema. The OpenMC -source contains RELAX NG schemas for each type of user input file. In order for -nXML mode to know about these schemas, you need to tell emacs where to find a -"locating files" description. Adding the following lines to your ``~/.emacs`` -file will enable real-time validation of XML input files: - -.. code-block:: common-lisp - - (require 'rng-loc) - (add-to-list 'rng-schema-locating-files "~/openmc/schemas.xml") - -Make sure to replace the last string on the second line with the path to the -schemas.xml file in your own OpenMC source directory. - -.. _GNU Emacs: http://www.gnu.org/software/emacs/ -.. _validation: https://en.wikipedia.org/wiki/XML_validation -.. _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://docs.conda.io/en/latest/ -.. _pip: https://pip.pypa.io/en/stable/ diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst deleted file mode 100644 index 847276848..000000000 --- a/docs/source/usersguide/materials.rst +++ /dev/null @@ -1,177 +0,0 @@ -.. _usersguide_materials: - -.. currentmodule:: openmc - -===================== -Material Compositions -===================== - -Materials in OpenMC are defined as a set of nuclides/elements at specified -densities and are created using the :class:`openmc.Material` class. Once a -material has been instantiated, nuclides can be added with -:meth:`Material.add_nuclide` and elements can be added with -:meth:`Material.add_element`. Densities can be specified using atom fractions or -weight fractions. For example, to create a material and add Gd152 at 0.5 atom -percent, you'd run:: - - mat = openmc.Material() - mat.add_nuclide('Gd152', 0.5, 'ao') - -The third argument to :meth:`Material.add_nuclide` can also be 'wo' for weight -percent. The densities specified for each nuclide/element are relative and are -renormalized based on the total density of the material. The total density is -set using the :meth:`Material.set_density` method. The density can be specified -in gram per cubic centimeter ('g/cm3'), atom per barn-cm ('atom/b-cm'), or -kilogram per cubic meter ('kg/m3'), e.g., - -:: - - mat.set_density('g/cm3', 4.5) - ----------------- -Natural Elements ----------------- - -The :meth:`Material.add_element` method works exactly the same as -:meth:`Material.add_nuclide`, except that instead of specifying a single isotope -of an element, you specify the element itself. For example, - -:: - - mat.add_element('C', 1.0) - -Internally, OpenMC stores data on the atomic masses and natural abundances of -all known isotopes and then uses this data to determine what isotopes should be -added to the material. When the material is later exported to XML for use by the -:ref:`scripts_openmc` executable, you'll see that any natural elements were -expanded to the naturally-occurring isotopes. - -The :meth:`Material.add_element` method can also be used to add uranium at a -specified enrichment through the `enrichment` argument. For example, the -following would add 3.2% enriched uranium to a material:: - - mat.add_element('U', 1.0, enrichment=3.2) - -In addition to U235 and U238, concentrations of U234 and U236 will be present -and are determined through a correlation based on measured data. - -Often, cross section libraries don't actually have all naturally-occurring -isotopes for a given element. For example, in ENDF/B-VII.1, cross section -evaluations are given for O16 and O17 but not for O18. If OpenMC is aware of -what cross sections you will be using (through the -:envvar:`OPENMC_CROSS_SECTIONS` environment variable), it will attempt to only -put isotopes in your model for which you have cross section data. In the case of -oxygen in ENDF/B-VII.1, the abundance of O18 would end up being lumped with O16. - ------------------------ -Thermal Scattering Data ------------------------ - -If you have a moderating material in your model like water or graphite, you -should assign thermal scattering data (so-called :math:`S(\alpha,\beta)`) using -the :meth:`Material.add_s_alpha_beta` method. For example, to model light water, -you would need to add hydrogen and oxygen to a material and then assign the -``c_H_in_H2O`` thermal scattering data:: - - water = openmc.Material() - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - water.set_density('g/cm3', 1.0) - -.. _usersguide_naming: - ------------------- -Naming Conventions ------------------- - -OpenMC uses the GND_ naming convention for nuclides, metastable states, and -compounds: - -:Nuclides: ``SymA`` where "A" is the mass number (e.g., ``Fe56``) -:Elements: ``Sym0`` (e.g., ``Fe0`` or ``C0``) -:Excited states: ``SymA_eN`` (e.g., ``V51_e1`` for the first excited state of - Vanadium-51.) This is only used in decay data. -:Metastable states: ``SymA_mN`` (e.g., ``Am242_m1`` for the first excited state - of Americium-242). -:Compounds: ``c_String_Describing_Material`` (e.g., ``c_H_in_H2O``). Used for - thermal scattering data. - -.. important:: The element syntax, e.g., ``C0``, is only used when the cross - section evaluation is an elemental evaluation, like carbon in - ENDF/B-VII.1! If you are adding an element via - :meth:`Material.add_element`, just use ``Sym``. - -.. _GND: https://www.oecd-nea.org/science/wpec/sg38/Meetings/2016_May/tlh4gnd-main.pdf - ------------ -Temperature ------------ - -Some Monte Carlo codes define temperature implicitly through the cross section -data, which is itself given only at a particular temperature. In OpenMC, the -material definition is decoupled from the specification of temperature. Instead, -temperatures are assigned to :ref:`cells ` -directly. Alternatively, a default temperature can be assigned to a material -that is to be applied to any cell where the material is used. In the absence of -any cell or material temperature specification, a global default temperature can -be set that is applied to all cells and materials. Anytime a material -temperature is specified, it will override the global default -temperature. Similarly, anytime a cell temperatures is specified, it will -override the material or global default temperature. All temperatures should be -given in units of Kelvin. - -To assign a default material temperature, one should use the ``temperature`` -attribute, e.g., - -:: - - hot_fuel = openmc.Material() - hot_fuel.temperature = 1200.0 # temperature in Kelvin - -.. warning:: MCNP_ users should be aware that OpenMC does not use the concept of - cross section suffixes like "71c" or "80c". Temperatures in Kelvin - should be assigned directly per material or per cell using the - :attr:`Material.temperature` or :attr:`Cell.temperature` - attributes, respectively. - --------------------- -Material Collections --------------------- - -The :ref:`scripts_openmc` executable expects to find a ``materials.xml`` file -when it is run. To create this file, one needs to instantiate the -:class:`openmc.Materials` class and add materials to it. The :class:`Materials` -class acts like a list (in fact, it is a subclass of Python's built-in -:class:`list` class), so materials can be added by passing a list to the -constructor, using methods like ``append()``, or through the operator -``+=``. Once materials have been added to the collection, it can be exported -using the :meth:`Materials.export_to_xml` method. - -:: - - materials = openmc.Materials() - materials.append(water) - materials += [uo2, zircaloy] - materials.export_to_xml() - - # This is equivalent - materials = openmc.Materials([water, uo2, zircaloy]) - materials.export_to_xml() - -Cross Sections --------------- - -OpenMC uses a file called :ref:`cross_sections.xml ` to -indicate where cross section data can be found on the filesystem. This file -serves the same role that ``xsdir`` does for MCNP_ or ``xsdata`` does for -Serpent. Information on how to generate a cross section listing file can be -found in :ref:`create_xs_library`. Once you have a cross sections file that has -been generated, you can tell OpenMC to use this file either by setting -:attr:`Materials.cross_sections` or by setting the -:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the path of the -``cross_sections.xml`` file. The former approach would look like:: - - materials.cross_sections = '/path/to/cross_sections.xml' - -.. _MCNP: https://mcnp.lanl.gov/ diff --git a/docs/source/usersguide/parallel.rst b/docs/source/usersguide/parallel.rst deleted file mode 100644 index 1cbb09401..000000000 --- a/docs/source/usersguide/parallel.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. _usersguide_parallel: - -=================== -Running in Parallel -=================== - -If you are running a simulation on a computer with multiple cores, multiple -sockets, or multiple nodes (i.e., a cluster), you can benefit from the fact that -OpenMC is able to use all available hardware resources if configured -correctly. OpenMC is capable of using both distributed-memory (`MPI -`_) and shared-memory (`OpenMP -`_) parallelism. If you are on a single-socket -workstation or a laptop, using shared-memory parallelism is likely -sufficient. On a multi-socket node, cluster, or supercomputer, chances are you -will need to use both distributed-memory (across nodes) and shared-memory -(within a single node) parallelism. - ----------------------------------- -Shared-Memory Parallelism (OpenMP) ----------------------------------- - -When using OpenMP, multiple threads will be launched and each is capable of -simulating a particle independently of all other threads. The primary benefit of -using OpenMP within a node is that it requires very little extra memory per -thread. OpenMP can be turned on or off at configure-time; by default it is -turned on. The only requirement is that the C++ compiler you use must support -the OpenMP 3.1 or higher standard. Most recent compilers do support the use of -OpenMP. - -To specify the number of threads at run-time, you can use the ``threads`` -argument to :func:`openmc.run`:: - - openmc.run(threads=8) - -If you're running :ref:`scripts_openmc` directly from the command line, you can -use the ``-s`` or ``--threads`` command-line argument. Alternatively, you can -use the :envvar:`OMP_NUM_THREADS` environment variable. If you do not specify -the number of threads, the OpenMP library will try to determine how many -hardware threads are available on your system and use that many threads. - -In general, it is recommended to use as many OpenMP threads as you have hardware -threads on your system. Notably, on a system with Intel hyperthreading, the -hyperthreads should be used and can be expected to provide a 10--30% performance -improvement over not using hyperthreads. - ------------------------------------- -Distributed-Memory Parallelism (MPI) ------------------------------------- - -MPI defines a library specification for message-passing between processes. There -are two major implementations of MPI, `OpenMPI `_ and -`MPICH `_. Both implementations are known to work with -OpenMC; there is no obvious reason to prefer one over the other. Building OpenMC -with support for MPI requires that you have one of these implementations -installed on your system. For instructions on obtaining MPI, see -:ref:`prerequisites`. Once you have an MPI implementation installed, compile -OpenMC following :ref:`usersguide_compile_mpi`. - -To run a simulation using MPI, :ref:`scripts_openmc` needs to be called using -the `mpiexec `_ -wrapper. For example, to run OpenMC using 32 processes: - -.. code-block:: sh - - mpiexec -n 32 openmc - -The same thing can be achieved from the Python API by supplying the ``mpi_args`` -argument to :func:`openmc.run`:: - - openmc.run(mpi_args=['mpiexec', '-n', '32']) - ----------------------- -Maximizing Performance ----------------------- - -There are a number of things you can do to ensure that you obtain optimal -performance on a machine when running in parallel: - -- **Use OpenMP within each NUMA node**. Some large server processors have so - many cores that the last level cache is split to reduce memory latency. For - example, the Intel Xeon Haswell-EP_ architecture uses a snoop mode called - *cluster on die* where the L3 cache is split in half. Thus, in general, you - should use one MPI process per socket (and OpenMP within each socket), but for - these large processors, you will want to go one step further and use one - process per NUMA node. The Xeon Phi Knights Landing architecture uses a - similar concept called `sub NUMA clustering - `_. -- **Use a sufficiently large number of particles per generation**. Between - fission generations, a number of synchronization tasks take place. If the - number of particles per generation is too low and you are using many - processes/threads, the synchronization time may become non-negligible. -- **Use hardware threading if available**. -- **Use process binding**. When running with MPI, you should ensure that - processes are bound_ to a specific hardware region. This can be set using the - ``-bind-to`` (MPICH) or ``--bind-to`` (OpenMPI) option to ``mpiexec``. -- **Turn off generation of tallies.out**. For large simulations with millions of - tally bins or more, generating this ASCII file might consume considerable - time. You can turn off generation of ``tallies.out`` via the - :attr:`Settings.output` attribute:: - - settings = openmc.Settings() - settings.output = {'tallies': False} - -.. _Haswell-EP: http://www.anandtech.com/show/8423/intel-xeon-e5-version-3-up-to-18-haswell-ep-cores-/4 -.. _bound: https://wiki.mpich.org/mpich/index.php/Using_the_Hydra_Process_Manager#Process-core_Binding diff --git a/docs/source/usersguide/plots.rst b/docs/source/usersguide/plots.rst deleted file mode 100644 index a10f370d6..000000000 --- a/docs/source/usersguide/plots.rst +++ /dev/null @@ -1,136 +0,0 @@ -.. _usersguide_plots: - -====================== -Geometry Visualization -====================== - -.. currentmodule:: openmc - -OpenMC is capable of producing two-dimensional slice plots of a geometry as well -as three-dimensional voxel plots using the geometry plotting :ref:`run mode -`. The geometry plotting mode relies on the presence of a -:ref:`plots.xml ` file that indicates what plots should be created. To -create this file, one needs to create one or more :class:`openmc.Plot` -instances, add them to a :class:`openmc.Plots` collection, and then use the -:class:`Plots.export_to_xml` method to write the ``plots.xml`` file. - ------------ -Slice Plots ------------ - -.. image:: ../_images/atr.png - :width: 300px - -By default, when an instance of :class:`openmc.Plot` is created, it indicates -that a 2D slice plot should be made. You can specify the origin of the plot -(:attr:`Plot.origin`), the width of the plot in each direction -(:attr:`Plot.width`), the number of pixels to use in each direction -(:attr:`Plot.pixels`), and the basis directions for the plot. For example, to -create a :math:`x` - :math:`z` plot centered at (5.0, 2.0, 3.0) with a width of -(50., 50.) and 400x400 pixels:: - - plot = openmc.Plot() - plot.basis = 'xz' - plot.origin = (5.0, 2.0, 3.0) - plot.width = (50., 50.) - plot.pixels = (400, 400) - -The color of each pixel is determined by placing a particle at the center of -that pixel and using OpenMC's internal ``find_cell`` routine (the same one used -for particle tracking during simulation) to determine the cell and material at -that location. - -.. note:: In this example, pixels are 50/400=0.125 cm wide. Thus, this plot may - miss any features smaller than 0.125 cm, since they could exist - between pixel centers. More pixels can be used to resolve finer - features but will result in larger files. - -By default, a unique color will be assigned to each cell in the geometry. If you -want your plot to be colored by material instead, change the -:attr:`Plot.color_by` attribute:: - - plot.color_by = 'material' - -If you don't like the random colors assigned, you can also indicate that -particular cells/materials should be given colors of your choosing:: - - plot.colors = { - water: 'blue', - clad: 'black' - } - - # This is equivalent - plot.colors = { - water: (0, 0, 255), - clad: (0, 0, 0) - } - -Note that colors can be given as RGB tuples or by a string indicating a valid -`SVG color `_. - -When you're done creating your :class:`openmc.Plot` instances, you need to then -assign them to a :class:`openmc.Plots` collection and export it to XML:: - - plots = openmc.Plots([plot1, plot2, plot3]) - plots.export_to_xml() - - # This is equivalent - plots = openmc.Plots() - plots.append(plot1) - plots += [plot2, plot3] - plots.export_to_xml() - -To actually generate the plots, run the :func:`openmc.plot_geometry` -function. Alternatively, run the :ref:`scripts_openmc` executable with the -``--plot`` command-line flag. When that has finished, you will have one or more -``.ppm`` files, i.e., `portable pixmap -`_ files. On some Linux -distributions, these ``.ppm`` files are natively viewable. If you find that -you're unable to open them on your system (or you don't like the fact that they -are not compressed), you may want to consider converting them to another format. -This is easily accomplished with the ``convert`` command available on most Linux -distributions as part of the `ImageMagick -`_ package. (On Debian -derivatives: ``sudo apt install imagemagick``). Images are then converted like: - -.. code-block:: sh - - convert myplot.ppm myplot.png - -Alternatively, if you're working within a `Jupyter `_ -Notebook or QtConsole, you can use the :func:`openmc.plot_inline` to run OpenMC -in plotting mode and display the resulting plot within the notebook. - -.. _usersguide_voxel: - ------------ -Voxel Plots ------------ - -.. image:: ../_images/3dba.png - :width: 200px - -The :class:`openmc.Plot` class can also be told to generate a 3D voxel plot -instead of a 2D slice plot. Simply change the :attr:`Plot.type` attribute to -'voxel'. In this case, the :attr:`Plot.width` and :attr:`Plot.pixels` attributes -should be three items long, e.g.:: - - vox_plot = openmc.Plot() - vox_plot.type = 'voxel' - vox_plot.width = (100., 100., 50.) - vox_plot.pixels = (400, 400, 200) - -The voxel plot data is written to an :ref:`HDF5 file `. The voxel file -can subsequently be converted into a standard mesh format that can be viewed in -`ParaView `_, `VisIt -`_, etc. This typically -will compress the size of the file significantly. The provided -:ref:`scripts_voxel` script can convert the HDF5 voxel file to VTK formats. Once -processed into a standard 3D file format, colors and masks can be defined using -the stored ID numbers to better explore the geometry. The process for doing this -will depend on the 3D viewer, but should be straightforward. - -.. note:: 3D voxel plotting can be very computer intensive for the viewing - program (Visit, ParaView, etc.) if the number of voxels is large (>10 - million or so). Thus if you want an accurate picture that renders - smoothly, consider using only one voxel in a certain direction. diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst deleted file mode 100644 index 56e3bbc1f..000000000 --- a/docs/source/usersguide/processing.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. _usersguide_processing: - -================================= -Data Processing and Visualization -================================= - -.. currentmodule:: openmc - -This section is intended to explain procedures for carrying out common -post-processing tasks with OpenMC. While several utilities of varying complexity -are provided to help automate the process, the most powerful capabilities for -post-processing derive from use of the :ref:`Python API `. - -.. _usersguide_statepoint: - -------------------------- -Working with State Points -------------------------- - -Tally results are saved in both a text file (tallies.out) as well as an HDF5 -statepoint file. While the tallies.out file may be fine for simple tallies, in -many cases the user requires more information about the tally or the run, or has -to deal with a large number of result values (e.g. for mesh tallies). In these -cases, extracting data from the statepoint file via the :ref:`pythonapi` is the -preferred method of data analysis and visualization. - -Data Extraction ---------------- - -A great deal of information is available in statepoint files (See -:ref:`io_statepoint`), all of which is accessible through the Python -API. The :class:`openmc.StatePoint` class can load statepoints and access data -as requested; it is used in many of the provided plotting utilities, OpenMC's -regression test suite, and can be used in user-created scripts to carry out -manipulations of the data. - -An :ref:`example IPython notebook ` demonstrates how -to extract data from a statepoint using the Python API. - -Plotting in 2D --------------- - -The :ref:`IPython notebook example ` also demonstrates -how to plot a mesh tally in two dimensions using the Python API. One can also -use the :ref:`scripts_plot` script which provides an interactive GUI to explore -and plot mesh tallies for any scores and filter bins. - -.. image:: ../_images/plotmeshtally.png - :width: 400px - -Getting Data into MATLAB ------------------------- - -There is currently no front-end utility to dump tally data to MATLAB files, but -the process is straightforward. First extract the data using the Python API via -``openmc.statepoint`` and then use the `Scipy MATLAB IO routines -`_ to save to a MAT -file. Note that all arrays that are accessible in a statepoint are already in -NumPy arrays that can be reshaped and dumped to MATLAB in one step. - -.. _usersguide_track: - ----------------------------- -Particle Track Visualization ----------------------------- - -.. image:: ../_images/Tracks.png - :width: 400px - -OpenMC can dump particle tracks—the position of particles as they are -transported through the geometry. There are two ways to make OpenMC output -tracks: all particle tracks through a command line argument or specific particle -tracks through settings.xml. - -Running :ref:`scripts_openmc` with the argument ``-t`` or ``--track`` will cause -a track file to be created for every particle transported in the code. Be -careful as this will produce as many files as there are source particles in your -simulation. To identify a specific particle for which a track should be created, -set the :attr:`Settings.track` attribute to a tuple containing the batch, -generation, and particle number of the desired particle. For example, to create -a track file for particle 4 of batch 1 and generation 2:: - - settings = openmc.Settings() - settings.track = (1, 2, 4) - -To specify multiple particles, the length of the iterable should be a multiple -of three, e.g., if we wanted particles 3 and 4 from batch 1 and generation 2:: - - settings.track = (1, 2, 3, 1, 2, 4) - -After running OpenMC, the working directory will contain a file of the form -"track_(batch #)_(generation #)_(particle #).h5" for each particle tracked. -These track files can be converted into VTK poly data files with the -:ref:`scripts_track` script. - ----------------------- -Source Site Processing ----------------------- - -For eigenvalue problems, OpenMC will store information on the fission source -sites in the statepoint file by default. For each source site, the weight, -position, sampled direction, and sampled energy are stored. To extract this data -from a statepoint file, the ``openmc.statepoint`` module can be used. An -:ref:`example IPython notebook ` demontrates how to -analyze and plot source information. diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst deleted file mode 100644 index 388130947..000000000 --- a/docs/source/usersguide/scripts.rst +++ /dev/null @@ -1,257 +0,0 @@ -.. _usersguide_scripts: - -======================= -Executables and Scripts -======================= - -.. _scripts_openmc: - ----------- -``openmc`` ----------- - -Once you have a model built (see :ref:`usersguide_basics`), you can either run -the openmc executable directly from the directory containing your XML input -files, or you can specify as a command-line argument the directory containing -the XML input files. For example, if your XML input files are in the directory -``/home/username/somemodel/``, one way to run the simulation would be: - -.. code-block:: sh - - cd /home/username/somemodel - openmc - -Alternatively, you could run from any directory: - -.. code-block:: sh - - openmc /home/username/somemodel - -Note that in the latter case, any output files will be placed in the present -working directory which may be different from -``/home/username/somemodel``. ``openmc`` accepts the following command line -flags: - --c, --volume Run in stochastic volume calculation mode --g, --geometry-debug Run in geometry debugging mode, where cell overlaps are - checked for after each move of a particle --n, --particles N Use *N* particles per generation or batch --p, --plot Run in plotting mode --r, --restart file Restart a previous run from a state point or a particle - restart file --s, --threads N Run with *N* OpenMP threads --t, --track Write tracks for all particles --v, --version Show version information --h, --help Show help message - -.. note:: If you're using the Python API, :func:`openmc.run` is equivalent to - running ``openmc`` from the command line. - -.. _scripts_ace: - ----------------------- -``openmc-ace-to-hdf5`` ----------------------- - -This script can be used to create HDF5 nuclear data libraries used by OpenMC if -you have existing ACE files. There are four different ways you can specify ACE -libraries that are to be converted: - -1. List each ACE library as a positional argument. This is very useful in - conjunction with the usual shell utilities (``ls``, ``find``, etc.). -2. Use the ``--xml`` option to specify a pre-v0.9 cross_sections.xml file. -3. Use the ``--xsdir`` option to specify a MCNP xsdir file. -4. Use the ``--xsdata`` option to specify a Serpent xsdata file. - -The script does not use any extra information from cross_sections.xml/ xsdir/ -xsdata files to determine whether the nuclide is metastable. Instead, the -``--metastable`` argument can be used to specify whether the ZAID naming convention -follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the MCNP data -convention (essentially the same as NNDC, except that the first metastable state -of Am242 is 95242 and the ground state is 95642). - -The optional ``--fission_energy_release`` argument will accept an HDF5 file -containing a library of fission energy release (ENDF MF=1 MT=458) data. A -library built from ENDF/B-VII.1 data is released with OpenMC and can be found at -openmc/data/fission_Q_data_endb71.h5. This data is necessary for -'fission-q-prompt' and 'fission-q-recoverable' tallies, but is not needed -otherwise. - --h, --help show help message and exit - --d DESTINATION, --destination DESTINATION - Directory to create new library in - --m META, --metastable META - How to interpret ZAIDs for metastable nuclides. META - can be either 'nndc' or 'mcnp'. (default: nndc) - ---xml XML Old-style cross_sections.xml that lists ACE libraries - ---xsdir XSDIR MCNP xsdir file that lists ACE libraries - ---xsdata XSDATA Serpent xsdata file that lists ACE libraries - ---fission_energy_release FISSION_ENERGY_RELEASE - HDF5 file containing fission energy release data - -.. _scripts_compton: - ------------------------ -``openmc-make-compton`` ------------------------ - -This script generates an HDF5 file called ``compton_profiles.h5`` that contains -Compton profile data using an existing data library from `Geant4 -`_. Note that OpenMC includes this data file by default -so it should not be necessary in practice to generate it yourself. - - -.. _scripts_depletion_chain: - -------------------------------- -``openmc-make-depletion-chain`` -------------------------------- - -This script generates a depletion chain file called ``chain_endfb71.xml`` -using ENDF/B-VII.1 nuclear data. If the :envvar:`OPENMC_ENDF_DATA` variable -is not set, and ``"neutron"``, ``"decay"``, ``"nfy"`` directories -do not exist, then ENDF/B-VII.1 data will be downloaded. - -.. _scripts_depletion_chain_casl: - ------------------------------------- -``openmc-make-depletion-chain-casl`` ------------------------------------- - -This script generates a depletion chain called ``chain_casl.xml`` -using ENDF/B-VII.1 nuclear data for a simplified chain. -The nuclides were chosen by CASL-ORIGEN, which can be found in -Appendix A of Kang Seog Kim, `"Specification for the VERA Depletion -Benchmark Suite" `_, -CASL-U-2015-1014-000, Rev. 0, ORNL/TM-2016/53, 2016. -``Te129`` has been added into this chain due to its link to -``I129`` production. - -If the :envvar:`OPENMC_ENDF_DATA` variable is not set, -and ``"neutron"``, ``"decay"``, ``"nfy"`` directories -to not exist, then ENDF/B-VII.1 data will be downloaded. - -.. _scripts_stopping: - -------------------------------- -``openmc-make-stopping-powers`` -------------------------------- - -This script generates an HDF5 file called ``stopping_power.h5`` that contains -radiative and collision stopping powers and mean excitation energy pulled from -the `NIST ESTAR database -`_. Note that OpenMC -includes this data file by default so it should not be necessary in practice to -generate it yourself. - -.. _scripts_plot: - --------------------------- -``openmc-plot-mesh-tally`` --------------------------- - -``openmc-plot-mesh-tally`` provides a graphical user interface for plotting mesh -tallies. The path to the statepoint file can be provided as an optional arugment -(if omitted, a file dialog will be presented). - -.. _scripts_track: - ------------------------ -``openmc-track-to-vtk`` ------------------------ - -This script converts HDF5 :ref:`particle track files ` to VTK -poly data that can be viewed with ParaView or VisIt. The filenames of the -particle track files should be given as posititional arguments. The output -filename can also be changed with the ``-o`` flag: - --o OUT, --out OUT Output VTK poly filename - ------------------------- -``openmc-update-inputs`` ------------------------- - -If you have existing XML files that worked in a previous version of OpenMC that -no longer work with the current version, you can try to update these files using -``openmc-update-inputs``. If any of the given files do not match the most -up-to-date formatting, then they will be automatically rewritten. The old -out-of-date files will not be deleted; they will be moved to a new file with -'.original' appended to their name. - -Formatting changes that will be made: - -geometry.xml - Lattices containing 'outside' attributes/tags will be replaced with lattices - containing 'outer' attributes, and the appropriate cells/universes will be - added. Any 'surfaces' attributes/elements on a cell will be renamed 'region'. - -materials.xml - Nuclide names will be changed from ACE aliases (e.g., Am-242m) to HDF5/GND - names (e.g., Am242_m1). Thermal scattering table names will be changed from - ACE aliases (e.g., HH2O) to HDF5/GND names (e.g., c_H_in_H2O). - ----------------------- -``openmc-update-mgxs`` ----------------------- - -This script updates OpenMC's deprecated multi-group cross section XML files to -the latest HDF5-based format. - --i IN, --input IN Input XML file --o OUT, --output OUT Output file in HDF5 format - -.. _scripts_validate: - ------------------------ -``openmc-validate-xml`` ------------------------ - -Input files can be checked before executing OpenMC using the -``openmc-validate-xml`` script which is installed alongside the Python API. Two -command line arguments can be set when running ``openmc-validate-xml``: - --i, --input-path Location of OpenMC input files. --r, --relaxng-path Location of OpenMC RelaxNG files - -If the RelaxNG path is not set, the script will search for these files because -it expects that the user is either running the script located in the install -directory ``bin`` folder or in ``src/utils``. Once executed, it will match -OpenMC XML files with their RelaxNG schema and check if they are valid. Below -is a table of the messages that will be printed after each file is checked. - -======================== =================================== -Message Description -======================== =================================== -[XML ERROR] Cannot parse XML file. -[NO RELAXNG FOUND] No RelaxNG file found for XML file. -[NOT VALID] XML file does not match RelaxNG. -[VALID] XML file matches RelaxNG. -======================== =================================== - -.. _scripts_voxel: - ---------------------------- -``openmc-voxel-to-vtk`` ---------------------------- - -When OpenMC generates :ref:`voxel plots `, they are in an -:ref:`HDF5 format ` that is not terribly useful by itself. The -``openmc-voxel-to-vtk`` script converts a voxel HDF5 file to a `VTK -`_ file. To run this script, you will need to have the VTK -Python bindings installed. To convert a voxel file, simply provide the path to -the file: - -.. code-block:: sh - - openmc-voxel-to-vtk voxel_1.h5 - -The ``openmc-voxel-to-vtk`` script also takes the following optional -command-line arguments: - --o, --output Path to output VTK file diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst deleted file mode 100644 index 1254c4ed5..000000000 --- a/docs/source/usersguide/settings.rst +++ /dev/null @@ -1,268 +0,0 @@ -.. _usersguide_settings: - -================== -Execution Settings -================== - -.. currentmodule:: openmc - -Once you have created the materials and geometry for your simulation, the last -step to have a complete model is to specify execution settings through the -:class:`openmc.Settings` class. At a minimum, you need to specify a :ref:`source -distribution ` and :ref:`how many particles to run -`. Many other execution settings can be set using the -:class:`openmc.Settings` object, but they are generally optional. - -.. _usersguide_run_modes: - ---------- -Run Modes ---------- - -The :attr:`Settings.run_mode` attribute controls what run mode is used when -:ref:`scripts_openmc` is executed. There are five different run modes that can -be specified: - -'eigenvalue' - Runs a :math:`k` eigenvalue simulation. See :ref:`methods_eigenvalue` for a - full description of eigenvalue calculations. In this mode, the - :attr:`Settings.source` specifies a starting source that is only used for the - first fission generation. - -'fixed source' - Runs a fixed-source calculation with a specified external source, specified in - the :attr:`Settings.source` attribute. - -'volume' - Runs a stochastic volume calculation. - -'plot' - Generates slice or voxel plots (see :ref:`usersguide_plots`). - -'particle restart' - Simulate a single source particle using a particle restart file. - - -So, for example, to specify that OpenMC should be run in fixed source mode, you -would need to instantiate a :class:`openmc.Settings` object and assign the -:attr:`Settings.run_mode` attribute:: - - settings = openmc.Settings() - settings.run_mode = 'fixed source' - -If you don't specify a run mode, the default run mode is 'eigenvalue'. - -.. _usersguide_particles: - -------------------- -Number of Particles -------------------- - -For a fixed source simulation, the total number of source particle histories -simulated is broken up into a number of *batches*, each corresponding to a -:ref:`realization ` of the tally random variables. Thus, you -need to specify both the number of batches (:attr:`Settings.batches`) as well as -the number of particles per batch (:attr:`Settings.particles`). - -For a :math:`k` eigenvalue simulation, particles are grouped into *fission -generations*, as described in :ref:`methods_eigenvalue`. Successive fission -generations can be combined into a batch for statistical purposes. By default, a -batch will consist of only a single fission generation, but this can be changed -with the :attr:`Settings.generations_per_batch` attribute. For problems with a -high dominance ratio, using multiple generations per batch can help reduce -underprediction of variance, thereby leading to more accurate confidence -intervals. Tallies should not be scored to until the source distribution -converges, as described in :ref:`method-successive-generations`, which may take -many generations. To specify the number of batches that should be discarded -before tallies begin to accumulate, use the :attr:`Settings.inactive` attribute. - -The following example shows how one would simulate 10000 particles per -generation, using 10 generations per batch, 150 total batches, and discarding 5 -batches. Thus, a total of 145 active batches (or 1450 generations) will be used -for accumulating tallies. - -:: - - settings.particles = 10000 - settings.generations_per_batch = 10 - settings.batches = 150 - settings.inactive = 5 - -.. _usersguide_source: - ------------------------------ -External Source Distributions ------------------------------ - -External source distributions can be specified through the -:attr:`Settings.source` attribute. If you have a single external source, you can -create an instance of :class:`openmc.Source` and use it to set the -:attr:`Settings.source` attribute. If you have multiple external sources with -varying source strengths, :attr:`Settings.source` should be set to a list of -:class:`openmc.Source` objects. - -The :class:`openmc.Source` class has three main attributes that one can set: -:attr:`Source.space`, which defines the spatial distribution, -:attr:`Source.angle`, which defines the angular distribution, and -:attr:`Source.energy`, which defines the energy distribution. - -The spatial distribution can be set equal to a sub-class of -:class:`openmc.stats.Spatial`; common choices are :class:`openmc.stats.Point` or -:class:`openmc.stats.Box`. To independently specify distributions in the -:math:`x`, :math:`y`, and :math:`z` coordinates, you can use -:class:`openmc.stats.CartesianIndependent`. - -The angular distribution can be set equal to a sub-class of -:class:`openmc.stats.UnitSphere` such as :class:`openmc.stats.Isotropic`, -:class:`openmc.stats.Monodirectional`, or -:class:`openmc.stats.PolarAzimuthal`. By default, if no angular distribution is -specified, an isotropic angular distribution is used. - -The energy distribution can be set equal to any univariate probability -distribution. This could be a probability mass function -(:class:`openmc.stats.Discrete`), a Watt fission spectrum -(:class:`openmc.stats.Watt`), or a tabular distribution -(:class:`openmc.stats.Tabular`). By default, if no energy distribution is -specified, a Watt fission spectrum with :math:`a` = 0.988 MeV and :math:`b` = -2.249 MeV :sup:`-1` is used. - -As an example, to create an isotropic, 10 MeV monoenergetic source uniformly -distributed over a cube centered at the origin with an edge length of 10 cm, one -would run:: - - source = openmc.Source() - source.space = openmc.stats.Box((-5, -5, -5), (5, 5, 5)) - source.angle = openmc.stats.Isotropic() - source.energy = openmc.stats.Discrete([10.0e6], [1.0]) - settings.source = source - -The :class:`openmc.Source` class also has a :attr:`Source.strength` attribute -that indicates the relative strength of a source distribution if multiple are -used. For example, to create two sources, one that should be sampled 70% of the -time and another that should be sampled 30% of the time:: - - src1 = openmc.Source() - src1.strength = 0.7 - ... - - src2 = openmc.Source() - src2.strength = 0.3 - ... - - settings.source = [src1, src2] - -Finally, the :attr:`Source.particle` attribute can be used to indicate the -source should be composed of particles other than neutrons. For example, the -following would generate a photon source:: - - source = openmc.Source() - source.particle = 'photon' - ... - - settings.source = source - -For a full list of all classes related to statistical distributions, see -:ref:`pythonapi_stats`. - ---------------- -Shannon Entropy ---------------- - -To assess convergence of the source distribution, the scalar Shannon entropy -metric is often used in Monte Carlo codes. OpenMC also allows you to calculate -Shannon entropy at each generation over a specified mesh, created using the -:class:`openmc.Mesh` class. After instantiating a :class:`Mesh`, you need to -specify the lower-left coordinates of the mesh (:attr:`Mesh.lower_left`), the -number of mesh cells in each direction (:attr:`Mesh.dimension`) and either the -upper-right coordinates of the mesh (:attr:`Mesh.upper_right`) or the width of -each mesh cell (:attr:`Mesh.width`). Once you have a mesh, simply assign it to -the :attr:`Settings.entropy_mesh` attribute. - -:: - - entropy_mesh = openmc.Mesh() - entropy_mesh.lower_left = (-50, -50, -25) - entropy_mesh.upper_right = (50, 50, 25) - entropy_mesh.dimension = (8, 8, 8) - - settings.entropy_mesh = entropy_mesh - -If you're unsure of what bounds to use for the entropy mesh, you can try getting -a bounding box for the entire geometry using the :attr:`Geometry.bounding_box` -property:: - - geom = openmc.Geometry() - ... - m = openmc.Mesh() - m.lower_left, m.upper_right = geom.bounding_box - m.dimension = (8, 8, 8) - - settings.entropy_mesh = m - ----------------- -Photon Transport ----------------- - -In addition to neutrons, OpenMC is also capable of simulating the passage of -photons through matter. This allows the modeling of photon production from -neutrons as well as pure photon calculations. The -:attr:`Settings.photon_transport` attribute can be used to enable photon -transport:: - - settings.photon_transport = True - -The way in which OpenMC handles secondary charged particles can be specified -with the :attr:`Settings.electron_treatment` attribute. By default, the -:ref:`thick-target bremsstrahlung ` (TTB) approximation is used to generate -bremsstrahlung radiation emitted by electrons and positrons created in photon -interactions. To neglect secondary bremsstrahlung photons and instead deposit -all energy from electrons locally, the local energy deposition option can be -selected:: - - settings.electron_treatment = 'led' - -.. note:: - Some features related to photon transport are not currently implemented, - including: - - * Tallying photon energy deposition. - * Generating a photon source from a neutron calculation that can be used - for a later fixed source photon calculation. - * Photoneutron reactions. - --------------------------- -Generation of Output Files --------------------------- - -A number of attributes of the :class:`openmc.Settings` class can be used to -control what files are output and how often. First, there is the -:attr:`Settings.output` attribute which takes a dictionary having keys -'summary', 'tallies', and 'path'. The first two keys controls whether a -``summary.h5`` and ``tallies.out`` file are written, respectively (see -:ref:`result_files` for a description of those files). By default, output files -are written to the current working directory; this can be changed by setting the -'path' key. For example, if you want to disable the ``tallies.out`` file and -write the ``summary.h5`` to a directory called 'results', you'd specify the -:attr:`Settings.output` dictionary as:: - - settings.output = { - 'tallies': False, - 'path': 'results' - } - -Generation of statepoint and source files is handled separately through the -:attr:`Settings.statepoint` and :attr:`Settings.sourcepoint` attributes. Both of -those attributes expect dictionaries and have a 'batches' key which indicates at -which batches statepoints and source files should be written. Note that by -default, the source is written as part of the statepoint file; this behavior can -be changed by the 'separate' and 'write' keys of the -:attr:`Settings.sourcepoint` dictionary, the first of which indicates whether -the source should be written to a separate file and the second of which -indicates whether the source should be written at all. - -As an example, to write a statepoint file every five batches:: - - settings.batches = n - settings.statepoint = {'batches': range(5, n + 5, 5)} - -.. _NIST ESTAR database: https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html diff --git a/docs/source/usersguide/tallies.rst b/docs/source/usersguide/tallies.rst deleted file mode 100644 index c147858eb..000000000 --- a/docs/source/usersguide/tallies.rst +++ /dev/null @@ -1,310 +0,0 @@ -.. _usersguide_tallies: - -================== -Specifying Tallies -================== - -.. currentmodule:: openmc - -In order to obtain estimates of physical quantities in your simulation, you need -to create one or more tallies using the :class:`openmc.Tally` class. As -explained in detail in the :ref:`theory manual `, tallies -provide estimates of a scoring function times the flux integrated over some -region of phase space, as in: - -.. math:: - - X = \underbrace{\int d\mathbf{r} \int d\mathbf{\Omega} \int - dE}_{\text{filters}} \underbrace{f(\mathbf{r}, \mathbf{\Omega}, - E)}_{\text{scores}} \psi (\mathbf{r}, \mathbf{\Omega}, E) - -Thus, to specify a tally, we need to specify what regions of phase space should -be included when deciding whether to score an event as well as what the scoring -function (:math:`f` in the above equation) should be used. The regions of phase -space are generally called *filters* and the scoring functions are simply -called *scores*. - -The only cases when filters do not correspond directly with the regions of -phase space are when expansion functions are applied in the integrand, such as -for Legendre expansions of the scattering kernel. - -------- -Filters -------- - -To specify the regions of phase space, one must create a -:class:`openmc.Filter`. Since :class:`openmc.Filter` is an abstract class, you -actually need to instantiate one of its sub-classes (for a full listing, see -:ref:`pythonapi_tallies`). For example, to indicate that events that occur in a -given cell should score to the tally, we would create a -:class:`openmc.CellFilter`:: - - cell_filter = openmc.CellFilter([fuel.id, moderator.id, reflector.id]) - -Another commonly used filter is :class:`openmc.EnergyFilter`, which specifies -multiple energy bins over which events should be scored. Thus, if we wanted to -tally events where the incident particle has an energy in the ranges [0 eV, 4 -eV] and [4 eV, 1 MeV], we would do the following:: - - energy_filter = openmc.EnergyFilter([0.0, 4.0, 1.0e6]) - -Energies are specified in eV and need to be monotonically increasing. - -.. caution:: An energy bin between zero and the lowest energy specified is not - included by default as it is in MCNP. - -Once you have created a filter, it should be assigned to a :class:`openmc.Tally` -instance through the :attr:`Tally.filters` attribute:: - - tally.filters.append(cell_filter) - tally.filters.append(energy_filter) - - # This is equivalent - tally.filters = [cell_filter, energy_filter] - -.. note:: You are actually not required to assign any filters to a tally. If you - create a tally with no filters, all events will score to the - tally. This can be useful if you want to know, for example, a reaction - rate over your entire model. - -.. _usersguide_scores: - ------- -Scores ------- - -To specify the scoring functions, a list of strings needs to be given to the -:attr:`Tally.scores` attribute. You can score the flux ('flux'), or a reaction -rate ('total', 'fission', etc.). For example, to tally the elastic scattering -rate and the fission neutron production, you'd assign:: - - tally.scores = ['elastic', 'nu-fission'] - -With no further specification, you will get the total elastic scattering rate -and the total fission neutron production. If you want reaction rates for a -particular nuclide or set of nuclides, you can set the :attr:`Tally.nuclides` -attribute to a list of strings indicating which nuclides. The nuclide names -should follow the same :ref:`naming convention ` as that used -for material specification. If we wanted the reaction rates only for U235 and -U238 (separately), we'd set:: - - tally.nuclides = ['U235', 'U238'] - -You can also list 'all' as a nuclide which will give you a separate reaction -rate for every nuclide in the model. - -The following tables show all valid scores: - -.. table:: **Flux scores: units are particle-cm per source particle.** - - +----------------------+---------------------------------------------------+ - |Score | Description | - +======================+===================================================+ - |flux |Total flux. | - +----------------------+---------------------------------------------------+ - -.. table:: **Reaction scores: units are reactions per source particle.** - - +----------------------+---------------------------------------------------+ - |Score | Description | - +======================+===================================================+ - |absorption |Total absorption rate. This accounts for all | - | |reactions which do not produce secondary neutrons | - | |as well as fission. | - +----------------------+---------------------------------------------------+ - |elastic |Elastic scattering reaction rate. | - +----------------------+---------------------------------------------------+ - |fission |Total fission reaction rate. | - +----------------------+---------------------------------------------------+ - |scatter |Total scattering rate. | - +----------------------+---------------------------------------------------+ - |total |Total reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2nd) |(n,2nd) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2n) |(n,2n) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,3n) |(n,3n) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,na) |(n,n\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,n3a) |(n,n3\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2na) |(n,2n\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,3na) |(n,3n\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,np) |(n,np) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,n2a) |(n,n2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2n2a) |(n,2n2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,nd) |(n,nd) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,nt) |(n,nt) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,nHe-3) |(n,n\ :sup:`3`\ He) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,nd2a) |(n,nd2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,nt2a) |(n,nt2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,4n) |(n,4n) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2np) |(n,2np) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,3np) |(n,3np) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,n2p) |(n,n2p) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,n*X*) |Level inelastic scattering reaction rate. The *X* | - | |indicates what which inelastic level, e.g., (n,n3) | - | |is third-level inelastic scattering. | - +----------------------+---------------------------------------------------+ - |(n,nc) |Continuum level inelastic scattering reaction rate.| - +----------------------+---------------------------------------------------+ - |(n,gamma) |Radiative capture reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,p) |(n,p) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,d) |(n,d) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,t) |(n,t) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,3He) |(n,\ :sup:`3`\ He) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,a) |(n,\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2a) |(n,2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,3a) |(n,3\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,2p) |(n,2p) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,pa) |(n,p\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,t2a) |(n,t2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,d2a) |(n,d2\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,pd) |(n,pd) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,pt) |(n,pt) reaction rate. | - +----------------------+---------------------------------------------------+ - |(n,da) |(n,d\ :math:`\alpha`\ ) reaction rate. | - +----------------------+---------------------------------------------------+ - |*Arbitrary integer* |An arbitrary integer is interpreted to mean the | - | |reaction rate for a reaction with a given ENDF MT | - | |number. | - +----------------------+---------------------------------------------------+ - -.. table:: **Particle production scores: units are particles produced per - source particles.** - - +----------------------+---------------------------------------------------+ - |Score | Description | - +======================+===================================================+ - |delayed-nu-fission |Total production of delayed neutrons due to | - | |fission. | - +----------------------+---------------------------------------------------+ - |prompt-nu-fission |Total production of prompt neutrons due to | - | |fission. | - +----------------------+---------------------------------------------------+ - |nu-fission |Total production of neutrons due to fission. | - +----------------------+---------------------------------------------------+ - |nu-scatter |This score is similar in functionality to the | - | |``scatter`` score except the total production of | - | |neutrons due to scattering is scored vice simply | - | |the scattering rate. This accounts for | - | |multiplicity from (n,2n), (n,3n), and (n,4n) | - | |reactions. | - +----------------------+---------------------------------------------------+ - |H1-production |Total production of H1. | - +----------------------+---------------------------------------------------+ - |H2-production |Total production of H2 (deuterium). | - +----------------------+---------------------------------------------------+ - |H3-production |Total production of H3 (tritium). | - +----------------------+---------------------------------------------------+ - |He3-production |Total production of He3. | - +----------------------+---------------------------------------------------+ - |He4-production |Total production of He4 (alpha particles). | - +----------------------+---------------------------------------------------+ - -.. table:: **Miscellaneous scores: units are indicated for each.** - - +----------------------+---------------------------------------------------+ - |Score | Description | - +======================+===================================================+ - |current |Used in combination with a meshsurface filter: | - | |Partial currents on the boundaries of each cell in | - | |a mesh. It may not be used in conjunction with any | - | |other score. Only energy and mesh filters may be | - | |used. | - | |Used in combination with a surface filter: | - | |Net currents on any surface previously defined in | - | |the geometry. It may be used along with any other | - | |filter, except meshsurface filters. | - | |Surfaces can alternatively be defined with cell | - | |from and cell filters thereby resulting in tallying| - | |partial currents. | - | |Units are particles per source particle. | - +----------------------+---------------------------------------------------+ - |events |Number of scoring events. Units are events per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |inverse-velocity |The flux-weighted inverse velocity where the | - | |velocity is in units of centimeters per second. | - +----------------------+---------------------------------------------------+ - |heating |Total nuclear heating in units of eV per source | - | |particle. For neutrons, this corresponds to MT=301 | - | |produced by NJOY's HEATR module while for photons, | - | |this is tallied from either direct photon energy | - | |deposition (analog estimator) or pre-generated | - | |photon heating number. See :ref:`methods_heating` | - +----------------------+---------------------------------------------------+ - |heating-local |Total nuclear heating in units of eV per source | - | |particle assuming energy from secondary photons is | - | |deposited locally. Note that this score should only| - | |be used for incident neutrons. See | - | |:ref:`methods_heating`. | - +----------------------+---------------------------------------------------+ - |kappa-fission |The recoverable energy production rate due to | - | |fission. The recoverable energy is defined as the | - | |fission product kinetic energy, prompt and delayed | - | |neutron kinetic energies, prompt and delayed | - | |:math:`\gamma`-ray total energies, and the total | - | |energy released by the delayed :math:`\beta` | - | |particles. The neutrino energy does not contribute | - | |to this response. The prompt and delayed | - | |:math:`\gamma`-rays are assumed to deposit their | - | |energy locally. Units are eV per source particle. | - +----------------------+---------------------------------------------------+ - |fission-q-prompt |The prompt fission energy production rate. This | - | |energy comes in the form of fission fragment | - | |nuclei, prompt neutrons, and prompt | - | |:math:`\gamma`-rays. This value depends on the | - | |incident energy and it requires that the nuclear | - | |data library contains the optional fission energy | - | |release data. Energy is assumed to be deposited | - | |locally. Units are eV per source particle. | - +----------------------+---------------------------------------------------+ - |fission-q-recoverable |The recoverable fission energy production rate. | - | |This energy comes in the form of fission fragment | - | |nuclei, prompt and delayed neutrons, prompt and | - | |delayed :math:`\gamma`-rays, and delayed | - | |:math:`\beta`-rays. This tally differs from the | - | |kappa-fission tally in that it is dependent on | - | |incident neutron energy and it requires that the | - | |nuclear data library contains the optional fission | - | |energy release data. Energy is assumed to be | - | |deposited locally. Units are eV per source | - | |paticle. | - +----------------------+---------------------------------------------------+ - |decay-rate |The delayed-nu-fission-weighted decay rate where | - | |the decay rate is in units of inverse seconds. | - +----------------------+---------------------------------------------------+ - |damage-energy |Damage energy production in units of eV per source | - | |particle. This corresponds to MT=444 produced by | - | |NJOY's HEATR module. | - +----------------------+---------------------------------------------------+ diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst deleted file mode 100644 index 2be94f6a8..000000000 --- a/docs/source/usersguide/troubleshoot.rst +++ /dev/null @@ -1,104 +0,0 @@ -.. _usersguide_troubleshoot: - -=============== -Troubleshooting -=============== - -------------------------- -Problems with Compilation -------------------------- - -If you are experiencing problems trying to compile OpenMC, first check if the -error you are receiving is among the following options. - -------------------------- -Problems with Simulations -------------------------- - -Segmentation Fault -****************** - -A segmentation fault occurs when the program tries to access a variable in -memory that was outside the memory allocated for the program. The best way to -debug a segmentation fault is to re-compile OpenMC with debug options turned -on. Create a new build directory and type the following commands: - -.. code-block:: sh - - mkdir build-debug && cd build-debug - cmake -Ddebug=on /path/to/openmc - make - -Now when you re-run your problem, it should report exactly where the program -failed. If after reading the debug output, you are still unsure why the program -failed, send an email to the OpenMC User's Group `mailing list`_. - -ERROR: No cross_sections.xml file was specified in settings.xml or in the OPENMC_CROSS_SECTIONS environment variable. -********************************************************************************************************************* - -OpenMC needs to know where to find cross section data for each nuclide. -Information on what data is available and in what files is summarized in a -cross_sections.xml file. You need to tell OpenMC where to find the -cross_sections.xml file either with the :ref:`cross_sections` in settings.xml or -with the :envvar:`OPENMC_CROSS_SECTIONS` environment variable. It is recommended -to add a line in your ``.profile`` or ``.bash_profile`` setting the -:envvar:`OPENMC_CROSS_SECTIONS` environment variable. - -Geometry Debugging -****************** - -Overlapping Cells -^^^^^^^^^^^^^^^^^ - -For fast run times, normal simulations do not check if the geometry is -incorrectly defined to have overlapping cells. This can lead to incorrect -results that may or may not be obvious when there are errors in the geometry -input file. The built-in 2D and 3D plotters will check for cell overlaps at -the center of every pixel or voxel position they process, however this might -not be a sufficient check to ensure correctly defined geometry. For instance, -if an overlap is of small aspect ratio, the plotting resolution might not be -high enough to produce any pixels in the overlapping area. - -To reliably validate a geometry input, it is best to run the problem in -geometry debugging mode with the ``-g``, ``-geometry-debug``, or -``--geometry-debug`` command-line options. This will enable checks for -overlapping cells at every move of esch simulated particle. Depending on the -complexity of the geometry input file, this could add considerable overhead to -the run (these runs can still be done in parallel). As a result, for this run -mode the user will probably want to run fewer particles than a normal -simulation run. In this case it is important to be aware of how much coverage -each area of the geometry is getting. For instance, if certain regions do not -have many particles travelling through them there will not be many locations -where overlaps are checked for in that region. The user should refer to the -output after a geometry debug run to see how many checks were performed in each -cell, and then adjust the number of starting particles or starting source -distributions accordingly to achieve good coverage. - -ERROR: After particle __ crossed surface __ it could not be located in any cell and it did not leak. -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This error can arise either if a problem is specified with no boundary -conditions or if there is an error in the geometry itself. First check to ensure -that all of the outer surfaces of your geometry have been given vacuum or -reflective boundary conditions. If proper boundary conditions have been applied -and you still receive this error, it means that a surface/cell/lattice in your -geometry has been specified incorrectly or is missing. - -The best way to debug this error is to turn on a trace for the particle getting -lost. After the error message, the code will display what batch, generation, and -particle number caused the error. In your settings.xml, add a :ref:`trace` -followed by the batch, generation, and particle number. This will give you -detailed output every time that particle enters a cell, crosses a boundary, or -has a collision. For example, if you received this error at cycle 5, generation -1, particle 4032, you would enter: - -.. code-block:: xml - - 5 1 4032 - -For large runs it is often advantageous to run only the offending particle by -using particle restart mode with the ``-s``, ``-particle``, or ``--particle`` -command-line options in conjunction with the particle restart files that are -created when particles are lost with this error. - -.. _mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-users diff --git a/docs/source/usersguide/volume.rst b/docs/source/usersguide/volume.rst deleted file mode 100644 index e4bdbf715..000000000 --- a/docs/source/usersguide/volume.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _usersguide_volume: - -============================== -Stochastic Volume Calculations -============================== - -.. currentmodule:: openmc - -OpenMC has a capability to stochastically determine volumes of cells, materials, -and universes. The method works by overlaying a bounding box, sampling points -from within the box, and seeing what fraction of points were found in a desired -domain. The benefit of doing this stochastically (as opposed to equally-spaced -points), is that it is possible to give reliable error estimates on each -stochastic quantity. - -To specify that a volume calculation be run, you first need to create an -instance of :class:`openmc.VolumeCalculation`. The constructor takes a list of -cells, materials, or universes; the number of samples to be used; and the -lower-left and upper-right Cartesian coordinates of a bounding box that encloses -the specified domains:: - - lower_left = (-0.62, -0.62, -50.) - upper_right = (0.62, 0.62, 50.) - vol_calc = openmc.VolumeCalculation([fuel, clad, moderator], 1000000, - lower_left, upper_right) - -For domains contained within regions that have simple definitions, OpenMC can -sometimes automatically determine a bounding box. In this case, the last two -arguments are not necessary. For example, - -:: - - sphere = openmc.Sphere(r=10.0) - cell = openm.Cell(region=-sphere) - vol_calc = openmc.VolumeCalculation([cell], 1000000) - -Of course, the volumes that you *need* this capability for are often the ones -with complex definitions. - -Once you have one or more :class:`openmc.VolumeCalculation` objects created, you -can then assign then to :attr:`Settings.volume_calculations`:: - - settings = openmc.Settings() - settings.volume_calculations = [cell_vol_calc, mat_vol_calc] - -To execute the volume calculations, one can either set :attr:`Settings.run_mode` -to 'volume' and run :func:`openmc.run`, or alternatively run -:func:`openmc.calculate_volumes` which doesn't require that -:attr:`Settings.run_mode` be set. - -When your volume calculations have finished, you can load the results using the -:meth:`VolumeCalculation.load_results` method on an existing object. If you -don't have an existing :class:`VolumeCalculation` object, you can create one and -load results simultaneously using the :meth:`VolumeCalculation.from_hdf5` class -method:: - - vol_calc = openmc.VolumeCalculation(...) - ... - openmc.calculate_volumes() - vol_calc.load_results('volume_1.h5') - - # ..or we can create a new object - vol_calc = openmc.VolumeCalculation.from_hdf5('volume_1.h5') - -After the results are loaded, volume estimates will be stored in -:attr:`VolumeCalculation.volumes`. There is also a -:attr:`VolumeCalculation.atoms_dataframe` attribute that shows stochastic -estimates of the number of atoms of each type of nuclide within the specified -domains along with their uncertainties. diff --git a/docs/sphinxext/LICENSE b/docs/sphinxext/LICENSE deleted file mode 100644 index 2d508d2be..000000000 --- a/docs/sphinxext/LICENSE +++ /dev/null @@ -1,68 +0,0 @@ -The file notebook_sphinxext.py was derived from code in PyNE and yt. - -PyNE has the following license: - -------------------------------------------------------------------------------- -Copyright 2011-2015, the PyNE Development Team. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE PYNE DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of the stakeholders of the PyNE project or the employers of PyNE developers. -------------------------------------------------------------------------------- - -yt has the following license: - -------------------------------------------------------------------------------- -yt is licensed under the terms of the Modified BSD License (also known as New -or Revised BSD), as follows: - -Copyright (c) 2013-, yt Development Team -Copyright (c) 2006-2013, Matthew Turk - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -Neither the name of the yt Development Team nor the names of its -contributors may be used to endorse or promote products derived from this -software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- diff --git a/docs/sphinxext/notebook_sphinxext.py b/docs/sphinxext/notebook_sphinxext.py deleted file mode 100644 index eab93cc8a..000000000 --- a/docs/sphinxext/notebook_sphinxext.py +++ /dev/null @@ -1,117 +0,0 @@ -import sys -import os.path -import re -import time -from docutils import io, nodes, statemachine, utils -try: - from docutils.utils.error_reporting import ErrorString # the new way -except ImportError: - from docutils.error_reporting import ErrorString # the old way -from docutils.parsers.rst import Directive, convert_directive_function -from docutils.parsers.rst import directives, roles, states -from docutils.parsers.rst.roles import set_classes -from docutils.transforms import misc - -from nbconvert import html - - -class Notebook(Directive): - """Use nbconvert to insert a notebook into the environment. - This is based on the Raw directive in docutils - """ - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - has_content = False - - def run(self): - # check if raw html is supported - if not self.state.document.settings.raw_enabled: - raise self.warning('"%s" directive disabled.' % self.name) - - # set up encoding - attributes = {'format': 'html'} - encoding = self.options.get( - 'encoding', self.state.document.settings.input_encoding) - e_handler = self.state.document.settings.input_encoding_error_handler - - # get path to notebook - source_dir = os.path.dirname( - os.path.abspath(self.state.document.current_source)) - nb_path = os.path.normpath(os.path.join(source_dir, - self.arguments[0])) - nb_path = utils.relative_path(None, nb_path) - - # convert notebook to html - exporter = html.HTMLExporter(template_file='full') - output, resources = exporter.from_filename(nb_path) - header = output.split('', 1)[1].split('',1)[0] - body = output.split('', 1)[1].split('',1)[0] - - # add HTML5 scoped attribute to header style tags - header = header.replace(''] - lines.append(header) - lines.append(body) - lines.append('') - text = '\n'.join(lines) - - # add dependency - self.state.document.settings.record_dependencies.add(nb_path) - attributes['source'] = nb_path - - # create notebook node - nb_node = notebook('', text, **attributes) - (nb_node.source, nb_node.line) = \ - self.state_machine.get_source_and_line(self.lineno) - - return [nb_node] - - -class notebook(nodes.raw): - pass - - -def visit_notebook_node(self, node): - self.visit_raw(node) - - -def depart_notebook_node(self, node): - self.depart_raw(node) - - -def setup(app): - app.add_node(notebook, - html=(visit_notebook_node, depart_notebook_node)) - - app.add_directive('notebook', Notebook) diff --git a/examples/jupyter/c5g7.h5 b/examples/jupyter/c5g7.h5 deleted file mode 100644 index b3dea952b..000000000 Binary files a/examples/jupyter/c5g7.h5 and /dev/null differ diff --git a/examples/jupyter/cad-based-geometry.ipynb b/examples/jupyter/cad-based-geometry.ipynb deleted file mode 100644 index b13c010cb..000000000 --- a/examples/jupyter/cad-based-geometry.ipynb +++ /dev/null @@ -1,764 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this notebook we'll be exploring how to use CAD-based geometries in OpenMC via the [DagMC](https://svalinn.github.io/DAGMC/index.html) toolkit. The models we'll be using in this notebook have already been created using [Trelis](https://www.csimsoft.com/trelis) and faceted into a surface mesh represented as `.h5m` files in the [Mesh Oriented DatABase](https://press3.mcs.anl.gov/sigma/moab-library/) format. We'll be retrieving these files using the function below.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import urllib.request\n", - "\n", - "fuel_pin_url = 'https://tinyurl.com/y3ugwz6w' # 1.2 MB\n", - "teapot_url = 'https://tinyurl.com/y4mcmc3u' # 29 MB\n", - "\n", - "def download(url):\n", - " \"\"\"\n", - " Helper function for retrieving dagmc models\n", - " \"\"\"\n", - " u = urllib.request.urlopen(url)\n", - " \n", - " if u.status != 200:\n", - " raise RuntimeError(\"Failed to download file.\")\n", - " \n", - " # save file as dagmc.h5m\n", - " with open(\"dagmc.h5m\", 'wb') as f:\n", - " f.write(u.read())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook is intended to demonstrate how DagMC problems are run in OpenMC. For more information on how DagMC models are created, please refer to the [DagMC User's Guide](https://svalinn.github.io/DAGMC/usersguide/index.html).\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# CAD-Based Geometry in OpenMC using [DagMC](https://svalinn.github.io/DAGMC/)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "from IPython.display import Image\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To start, we'll be using a simple U235 fuel pin surrounded by a water moderator, so let's create those materials." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - " # materials\n", - "u235 = openmc.Material(name=\"fuel\")\n", - "u235.add_nuclide('U235', 1.0, 'ao')\n", - "u235.set_density('g/cc', 11)\n", - "u235.id = 40\n", - "\n", - "water = openmc.Material(name=\"water\")\n", - "water.add_nuclide('H1', 2.0, 'ao')\n", - "water.add_nuclide('O16', 1.0, 'ao')\n", - "water.set_density('g/cc', 1.0)\n", - "water.add_s_alpha_beta('c_H_in_H2O')\n", - "water.id = 41\n", - "\n", - "mats = openmc.Materials([u235, water])\n", - "mats.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's get our DAGMC geometry. We'll be using prefabricated models in this notebook. For information on how to create your own DAGMC models, you can refer to the instructions [here](https://svalinn.github.io/DAGMC/usersguide/trelis_workflow.html)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's download the DAGMC model. These models come in the form of triangle surface meshes stored using the the Mesh Oriented datABase ([MOAB](https://press3.mcs.anl.gov/sigma/moab-library/)) in an HDF5 file with the extension `.h5m`. An example of a coarse triangle mesh looks like:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": { - "image/png": { - "width": 350 - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "Image(\"./images/cylinder_mesh.png\", width=350)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we'll need to grab some pre-made DagMC models." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "download(fuel_pin_url)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC expects that the model has the name \"dagmc.h5m\" so we'll name the file that and indicate to OpenMC that a DAGMC geometry is being used by setting the `settings.dagmc` attribute to `True`." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.dagmc = True\n", - "settings.batches = 10\n", - "settings.inactive = 2\n", - "settings.particles = 5000\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Unlike conventional geometries in OpenMC, we really have no way of knowing what our model looks like at this point. Thankfully DagMC geometries can be plotted just like any other OpenMC geometry to give us an idea of what we're now working with.\n", - "\n", - "Note that material assignments have already been applied to this model. Materials can be assigned either using ids or names of materials in the `materials.xml` file. It is recommended that material names are used for assignment for readability." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "p = openmc.Plot()\n", - "p.width = (25.0, 25.0)\n", - "p.pixels = (400, 400)\n", - "p.color_by = 'material'\n", - "p.colors = {u235: 'yellow', water: 'blue'}\n", - "openmc.plot_inline(p)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we've had a chance to examine the model a bit, we can finish applying our settings and add a source." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "settings.source = openmc.Source(space=openmc.stats.Box([-4., -4., -4.],\n", - " [ 4., 4., 4.]))\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tallies work in the same way when using DAGMC geometries too. We'll add a tally on the fuel cell here." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "tally = openmc.Tally()\n", - "tally.scores = ['total']\n", - "tally.filters = [openmc.CellFilter(1)]\n", - "tallies = openmc.Tallies([tally])\n", - "tallies.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Note:** Applying tally filters in DagMC models requires prior knowledge of the model. Here, we know that the fuel cell's volume ID in the CAD sofware is 1. To identify cells without use of CAD software, load them into the [OpenMC plotter](https://github.com/openmc/plotter) where cell, material, and volume IDs can be identified for native both OpenMC and DagMC geometries." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we're ready to run the simulation just like any other OpenMC run." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 2c0b16e73d5d81a2f849f4e2bfae5eb5319f2417\n", - " Date/Time | 2019-06-18 08:54:17\n", - " OpenMP Threads | 2\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading DAGMC geometry...\n", - "Loading file dagmc.h5m\n", - "Initializing the GeomQueryTool...\n", - "Using faceting tolerance: 0.0001\n", - "Building OBB Tree...\n", - " Reading U235 from /home/shriwise/opt/openmc/xs/nndc_hdf5/U235.h5\n", - " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", - " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", - " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.15789\n", - " 2/1 1.05169\n", - " 3/1 1.00736\n", - " 4/1 0.97863 0.99300 +/- 0.01436\n", - " 5/1 0.95316 0.97972 +/- 0.01566\n", - " 6/1 0.95079 0.97248 +/- 0.01322\n", - " 7/1 0.96879 0.97175 +/- 0.01027\n", - " 8/1 0.94253 0.96688 +/- 0.00970\n", - " 9/1 0.97406 0.96790 +/- 0.00826\n", - " 10/1 0.97362 0.96862 +/- 0.00719\n", - " Creating state point statepoint.10.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 2.4575e-01 seconds\n", - " Reading cross sections = 1.3129e-01 seconds\n", - " Total time in simulation = 1.6897e+00 seconds\n", - " Time in transport only = 1.6829e+00 seconds\n", - " Time in inactive batches = 3.1605e-01 seconds\n", - " Time in active batches = 1.3737e+00 seconds\n", - " Time synchronizing fission bank = 2.8739e-03 seconds\n", - " Sampling source sites = 2.5550e-03 seconds\n", - " SEND/RECV source sites = 2.8512e-04 seconds\n", - " Time accumulating tallies = 7.8450e-06 seconds\n", - " Total time for finalization = 1.7404e-04 seconds\n", - " Total time elapsed = 1.9588e+00 seconds\n", - " Calculation Rate (inactive) = 31640.8 particles/second\n", - " Calculation Rate (active) = 29119.1 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 0.97020 +/- 0.00750\n", - " k-effective (Track-length) = 0.96862 +/- 0.00719\n", - " k-effective (Absorption) = 0.95742 +/- 0.00791\n", - " Combined k-effective = 0.96203 +/- 0.00898\n", - " Leakage Fraction = 0.57677 +/- 0.00317\n", - "\n" - ] - } - ], - "source": [ - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## More Complicated Geometry" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Neat! But this pincell is something we could've done with CSG. Let's take a look at something more complex. We'll download a pre-built model of the [Utah teapot](https://en.wikipedia.org/wiki/Utah_teapot) and use it here." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "download(teapot_url)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 12, - "metadata": { - "image/jpeg": { - "width": 600 - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "Image(\"./images/teapot.jpg\", width=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our teapot is made out of iron, so we'll want to create that material and make sure it is in our `materials.xml` file." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "iron = openmc.Material(name=\"iron\")\n", - "iron.add_nuclide(\"Fe54\", 0.0564555822608)\n", - "iron.add_nuclide(\"Fe56\", 0.919015287728)\n", - "iron.add_nuclide(\"Fe57\", 0.0216036861685)\n", - "iron.add_nuclide(\"Fe58\", 0.00292544384231)\n", - "iron.set_density(\"g/cm3\", 7.874)\n", - "mats = openmc.Materials([iron, water])\n", - "mats.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make sure we've updated the file correctly, let's make a plot of the teapot." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "p = openmc.Plot()\n", - "p.basis = 'xz'\n", - "p.origin = (0.0, 0.0, 0.0)\n", - "p.width = (30.0, 20.0)\n", - "p.pixels = (450, 300)\n", - "p.color_by = 'material'\n", - "p.colors = {iron: 'gray', water: 'blue'}\n", - "openmc.plot_inline(p)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we start to see some of the advantages CAD geometries provide. This particular file was pulled from the [GrabCAD](https://grabcad.com/library) and pushed through the DAGMC workflow without modification (other than the addition of material assignments). It would take a considerable amount of time to create a model like this using CSG!" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "p.width = (18.0, 6.0)\n", - "p.basis = 'xz'\n", - "p.origin = (10.0, 0.0, 5.0)\n", - "p.pixels = (600, 200)\n", - "p.color_by = 'material'\n", - "openmc.plot_inline(p)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's brew some tea! ... using a very hot neutron source. We'll use some well-placed point sources distributed throughout the model." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.dagmc = True\n", - "settings.batches = 10\n", - "settings.particles = 5000\n", - "settings.run_mode = \"fixed source\"\n", - "\n", - "src_locations = ((-4.0, 0.0, -2.0),\n", - " ( 4.0, 0.0, -2.0),\n", - " ( 4.0, 0.0, -6.0),\n", - " (-4.0, 0.0, -6.0),\n", - " (10.0, 0.0, -4.0),\n", - " (-8.0, 0.0, -4.0))\n", - "\n", - "# we'll use the same energy for each source\n", - "src_e = openmc.stats.Discrete(x=[12.0,], p=[1.0,])\n", - "\n", - "# create source for each location\n", - "sources = []\n", - "for loc in src_locations:\n", - " src_pnt = openmc.stats.Point(xyz=loc)\n", - " src = openmc.Source(space=src_pnt, energy=src_e)\n", - " sources.append(src)\n", - "\n", - "src_str = 1.0 / len(sources)\n", - "for source in sources:\n", - " source.strength = src_str\n", - "\n", - "settings.source = sources\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "...and setup a couple mesh tallies. One for the kettle, and one for the water inside." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "mesh = openmc.RegularMesh()\n", - "mesh.dimension = (120, 1, 40)\n", - "mesh.lower_left = (-20.0, 0.0, -10.0)\n", - "mesh.upper_right = (20.0, 1.0, 4.0)\n", - "\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "pot_filter = openmc.CellFilter([1])\n", - "pot_tally = openmc.Tally()\n", - "pot_tally.filters = [mesh_filter, pot_filter]\n", - "pot_tally.scores = ['flux']\n", - "\n", - "water_filter = openmc.CellFilter([5])\n", - "water_tally = openmc.Tally()\n", - "water_tally.filters = [mesh_filter, water_filter]\n", - "water_tally.scores = ['flux']\n", - "\n", - "\n", - "tallies = openmc.Tallies([pot_tally, water_tally])\n", - "tallies.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 2c0b16e73d5d81a2f849f4e2bfae5eb5319f2417\n", - " Date/Time | 2019-06-18 08:54:35\n", - " OpenMP Threads | 2\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading DAGMC geometry...\n", - "Loading file dagmc.h5m\n", - "Initializing the GeomQueryTool...\n", - "Using faceting tolerance: 0.001\n", - "Building OBB Tree...\n", - " Reading Fe54 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe54.h5\n", - " Reading Fe56 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe56.h5\n", - " Reading Fe57 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe57.h5\n", - " Reading Fe58 from /home/shriwise/opt/openmc/xs/nndc_hdf5/Fe58.h5\n", - " Reading H1 from /home/shriwise/opt/openmc/xs/nndc_hdf5/H1.h5\n", - " Reading O16 from /home/shriwise/opt/openmc/xs/nndc_hdf5/O16.h5\n", - " Reading c_H_in_H2O from /home/shriwise/opt/openmc/xs/nndc_hdf5/c_H_in_H2O.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for Fe58\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ===============> FIXED SOURCE TRANSPORT SIMULATION <===============\n", - "\n", - " Simulating batch 1\n", - " Simulating batch 2\n", - " Simulating batch 3\n", - " Simulating batch 4\n", - " Simulating batch 5\n", - " Simulating batch 6\n", - " Simulating batch 7\n", - " Simulating batch 8\n", - " Simulating batch 9\n", - " Simulating batch 10\n", - " Creating state point statepoint.10.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 4.9659e+00 seconds\n", - " Reading cross sections = 6.3783e-01 seconds\n", - " Total time in simulation = 1.5112e+01 seconds\n", - " Time in transport only = 1.4102e+01 seconds\n", - " Time in active batches = 1.5112e+01 seconds\n", - " Time accumulating tallies = 2.8790e-04 seconds\n", - " Total time for finalization = 3.2375e-02 seconds\n", - " Total time elapsed = 2.0224e+01 seconds\n", - " Calculation Rate (active) = 3308.59 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " Leakage Fraction = 0.62594 +/- 0.00117\n", - "\n" - ] - } - ], - "source": [ - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the performance is significantly lower than our pincell model due to the increased complexity of the model, but it allows us to examine tally results like these:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "sp = openmc.StatePoint(\"statepoint.10.h5\")\n", - "\n", - "water_tally = sp.get_tally(scores=['flux'], id=water_tally.id)\n", - "water_flux = water_tally.mean\n", - "water_flux.shape = (40, 120)\n", - "water_flux = water_flux[::-1, :]\n", - "\n", - "pot_tally = sp.get_tally(scores=['flux'], id=pot_tally.id)\n", - "pot_flux = pot_tally.mean\n", - "pot_flux.shape = (40, 120)\n", - "pot_flux = pot_flux[::-1, :]\n", - "\n", - "del sp" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABA4AAADHCAYAAACZdhEvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nO3debSkV1nv8d9TVWfqOZ1OmkwkZAAMcBPmoEyXgERE411XASeCgnGpLMErSoB1Fa94RRQRBbyGKUG8zC7hKqKICXNCEghDJjKPnU6n08PpPn2mquf+UdWn3uepfqtOnalOd38/a2Wldr3Tfne9p87uffbzbHN3AQAAAAAAHEpl0BUAAAAAAACrFwMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHwBHMzJ5vZvctw3nvMrMXLvV5AQAA5svMrjSz1wy6HsDRgIEDYIDyP8DN7BVmtsvMnjePYzt+WZqZm9mZS1S3y8xs2sz2Ff57+VKcGwAADJ6ZvcnM/jW9d2vJe6+Yx/neamYfXeI6vtXMZlJ/5PeX8hoAemPgAFglzOwiSe+V9JPu/uVB16flHe6+rvDfJwZdIQAAsGS+IulHzawqSWZ2gqQhSU9O753Z2ndZmVmtZNMnUn/kHctdFwARAwfAKmBmvy7pnZJe7O7fKLx/npl9w8x2m9l3zez5rff/RNJzJL2nNfL+HjM7+Av9u2WzA8zsRDP7jJntMLM7zey3l6Dul5nZ2wrlufAIMzvDzB4xs6cUrr/j4H0AAICBukbNgYJzW+XnSLpC0i3pvdvd/QFJMrN3m9m9ZrbXzK4zs+e03r9A0pslvbzVD/lu6/2NZvZBM9tmZveb2dsKgxKvMrOvm9m7zGynpLcu9EbybAczO601E7NmZpvN7D4z+6nWtnVmdpuZvXKh1wOONgwcAIP3G5L+l6Tz3f3ag2+a2UmS/kXS2yRtlvQGSZ8xs+Pc/S2Svirpta2R99e6+3Nbh55zqNkBZlaR9P8kfVfSSZLOl/R6M3vxct2Yu98u6Y2SPmpmayR9WNLl7n7lcl0TAADMj7tPS7pa0sE+xHPV7F98Lb1XnG1wjZqDCpsl/V9JnzKzUXf/gqT/rfbsgHNa+18maVbNWQtPlvTjkoqhls+UdIekrZL+ZCnv7yB3f0TSr0p6v5kdL+ldkq53948sx/WAIxEDB8DgvUjSVZK+n97/JUmfd/fPu3vD3b8o6VpJL1ngdZ4u6Th3/1/uPu3ud0h6v6RuMYtvaM122G1mDy/kou7+fkm3qdkxOUHSWxZyHgAAsCy+rPYgwXPUHDj4anpvLoTS3T/q7jvdfdbd3ylpRNLjDnViM9uqZr/l9e6+390fUvMf7cW+xwPu/jet8x0oqePLCv2R3WZ2Yr836e7/LulTkr7UqtOv93sO4GjGwAEweL8h6bGSPmBmVnj/VEk/V/xFKenZav7jeyFOlXRiOt+b1RzhL/MX7r6p9d+WBV5Xag5QPFHS37j71CLOAwAAltZXJD3bzDar+QeGWyV9Q83cB5vV/P09N+PAzN5gZjeZ2Z5WX2KjpLI+wqlqhkJsK/Q9/k7S8YV97p1HHT9Z6I9sOhg2sQCXqnk/l7n7zgWeAzgqMXAADN52NcMGniPpfYX375X09+kX5Vp3f3tru/d5nXsl3ZnOt97dFzqD4aD9ktYUyo8qbjSzdZL+StIHJb211QkBAACrwzfV/Mf/r0n6uiS5+15JD7Tee8Dd75SkVj6D35f0MknHuPsmSXskHfzDR+6b3CtpStKWQt9jg7s/obBPv/2ZMr36I1U1Bw4+Iuk3l2oVKuBowcABsAq0Rs7Pl3SBmb2r9fZHJf2Umb3YzKpmNtpKPHhya/t2SaenUx3qvYO+JWnczN5oZmOtcz7RzJ6+yOpfL+klrcRDj5L0+rT93ZKudffXqJmz4f8s8noAAGCJtMIDrpX0P9QMUTjoa633ivkN1quZr2CHpJqZ/YGkDYXt2yWd1sqrJHffJunfJb3TzDaYWaWVOLnnstMLcL2k55rZo81so6Q3pe1vVnOQ4lcl/bmkjxxM0gigNwYOgFXC3e+R9AJJP2tmf+ru90q6UM1fdDvUHLX/PbV/bt/d2neXmf116723Srq8NR3wZen8dUkvVTOh0Z2SHpb0ATX/yrAYf69mwsW71OwczCVlNLMLJV2gZjiG1OyAPMXMfnGR1wQAAEvny2qGD3yt8N5XW+8VBw7+TdIXJP1Q0t2SJhVDDT7V+v9OM/t26/UrJQ1LulHSLkmf1sLDLku1ckF9QtL3JF0n6Z8PbjOzp6rZB3llqz/0Z2oOIlyy1PUAjlTmvlSzgwAAAAAAwJGGGQcAAAAAAKAUAwcAAAAAAKAUAwcAAAAAAKDUogYOzOwCM7vFzG4zM5KLAACAFUd/BACA5bXg5Iit5Ut+KOlFku6TdI2kn3f3G5euegAAAOXojwAAsPxqizj2GZJuc/c7JMnMPq7m0nGlv6iHbcRHtXYRlwQA4Mgzqf2a9ikbdD0OU/RHAABYAt36I4sZODhJcd3W+yQ9s9sBo1qrZ9r5i7gkAABHnqv9S4OuwuGM/ggAAEugW39kMQMH82JmF0u6WJJGtWa5LwcAANCB/ggAAAu3mIGD+yWdUiif3HovcPdLJV0qSRts88ISKgAlKmvanT9bMxa22chIKDd274nl/fuXr2I4LFRGR2P5uC1xh5QDxvftm3tdT88TgIGhPwIAwDJbzKoK10g6y8weY2bDkl4h6XNLUy0AAIB5oT8CAMAyW/CMA3efNbPXSvo3SVVJH3L3G5asZgAAAD3QHwEAYPktKseBu39e0ueXqC4AAAB9oz8CAMDyWvbkiMCiVKqhWP2RM0O5cdtd7V3XpaW1Uny6nbg1br/1jkVXD4e3xrmPDWXbuS/usHs8FL3emHtdOffsuO2m22N5amoJaggAAAAM3mJyHAAAAAAAgCMcAwcAAAAAAKAUoQpY1aqPPyOU/fa7Y7kwHXz2rnu6nsue+oR47h85K5TrN926kCriMFJ9XAx12b8lLsc4etX35n2uys0x1KVy2imhXL/ltj5rdwQyi2UvXwEvL41pw8OhXB+PYSPdzgUAAIClxYwDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHWFVqp58Wyj49E8qNyckFn9uvuyGU6ws+Ew5XOe/A6C0LP1d+Fmt741KOlfXr4/45Rv9oVFxetRF/AhvpZ115OUtL49zOTzAAAMBKYcYBAAAAAAAoxcABAAAAAAAoxcABAAAAAAAoRY6Dw1kxXliSvNF+neOBk+oxG+OhOb44bJsOZctrsyeWYrs1O9t+feymsKmxcU0oT6+La7dXvnJ912sBq8Xs9h2h3PjRJ4Vy5WtHwbPc47sh5zWY9zaJnAYAAAADxIwDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHq4iNjIRyZVPMQ6ADcd14d4/7r1vb3rY5Hmt798dzVWIsckfegkphTGlmNmzy0ZiHwPL2VE/btGHu9cSZW8K2A8fGPA3r70lrt6d7BFatFKM/fP+uUPYNG0K5vnfvsldpudnQcNftPjPddXv3k6fvJL4LAAAABoYZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DlZYNcU5a2x07qWtGQubfM1oKHfkKRgfj/uvLRw/FWOLG8esC+XK+IG4fX28dn1tO9+CV2Os8dAjE7Ee0zPxXCcfF6+1r523YHZNHKuqpKXZq1fdEMpENeNwNXv3faFcffwZcYcbD/8cBzmHQc7T0iHnLQgn8+5lAAAADAwzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHCyzymjMU6CTHxXLhfwAjXUxz4BNxdwBsydtjsc2jgnF2kN72oWZ2bjveMyP4I0YP2wTMedBrbh9Np2rFh+bHIlcuWcy1bOdyGD9V/eETfUzTojnWsy678Bq0ogJPGw85gax/HOUf85Wo0o1FK0Scxb41JS6KuYt6JbvAAAAAKsKMw4AAAAAAEApBg4AAAAAAEApQhWWWGX9+lDOSyzann2h3DhuU/vYB3fGbXvjcos2Hafx56nNh8FEZ1XOPTuUqzfeFcppdUbgiNHYHcN07OwzQ9m/d/NKVmfeKmvXtl9viN9v9Ud2xZ37CbdguUUAAIDDBjMOAAAAAABAKQYOAAAAAABAqZ4DB2b2ITN7yMx+UHhvs5l90cxubf3/mG7nAAAAWAz6IwAADM58chxcJuk9kj5SeO8SSV9y97eb2SWt8huXvnqHH095COzErXF7NY7V2LaH517Pbn9o+So2SIUl3LwW77+xd+9K1wYYiMZ4zFni60ZCuVJYnnE1Lc1YrEv94Ufitj6XT7WR9j3n70pyHmAeLhP9EQAABqLnjAN3/4qkR9LbF0q6vPX6ckk/s8T1AgAAmEN/BACAwVlojoOt7r6t9fpBSVu77QwAALAM6I8AALACFp0c0d1dUukcUzO72MyuNbNrZzS12MsBAAB0oD8CAMDymU+Og0PZbmYnuPs2MztBUmlwvrtfKulSSdpgm4/4INbKSIxbVsppkGP8bRXFMi+X2qknz71u3HJ32HbEPxBAidrt2+Ibjztj7mX9hltWuDblrFrIUdKI31fVTRtD2adnQrkxOZW2F/IakNMAS4P+CBbGLJXT39K8ETcXvgt7n7vH3+Uq8dqW6xL2Tefqtq/U+d3aKNxHPlcj3qN3HJvKhTbxvC2xSvd6Fo/P+3acO30WuX17XavbsR3yZ1Pr459KqX07cvl0U6/Hco/nsWv75/bqF7+fUWKhMw4+J+mi1uuLJH12aaoDAAAwb/RHAABYAfNZjvFjkr4p6XFmdp+ZvVrS2yW9yMxulfTCVhkAAGBZ0B8BAGBwes6/cfefL9l0/hLXBQAA4JDojwAAMDgLzXGAErZ+XXxj7/64PcUwze7as9xVWnkp/q6+ud0mfufdeW/gqFTfHkOxZ59wytzr2g0rXZu2jrwFM+28BpWx0bgt5TTo0C0u1VM8JwCsIBsejuWcOyDlNLCh2GX2enkcea9z5Th6pTj6cHyOsa/1yLUwm2PlC+dKses+E7/DO/JupT5r8Z5zf7Zf3bISWKNHjH5He6acB8U265EfoSOnwdBQ+bXSM6D8DORcDROTKtUjx5nn7alNQvvn9ujx2XQ8uzl/wlGQfw0Ls+hVFQAAAAAAwJGLgQMAAAAAAFCKgQMAAAAAAFCKHAdLbPb+B0K5uuXYULaxsVCurF0z97oxPr58FVtB1bMfG9/YMzH3kqhm4NBq+9rrPeefofqNP1y261bWrg1lS2XtL+RpyetG5zXAU1xkXve817rfALCcbKid1yB/P9lwim3vFQuftxfi6q2Wv/tSfHrOW5DzJxSPz9+jIykfQj3lLUj5FUK+gJn0HZ3vOeWt8anpUDYrHF9N95+/33O9+4ib76hXLznGv6g2Es9dyZ9rKufPoliXnOOgh45rFdrfc56L1H6Wt6fPzovnzjkh8nVzzo2U68Is3XOxLo1V1HPvkq8DK4MZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DpZYZc2a+MZxm0Mxx/ja5FS7cITkOLjvxTGvwwl/dfWAagIcPuzbN829fuTlTwvbNt64dNfJOQ101qmh6HfdH7eH9bDj91dj3/5Q7shpkNeSXk2xkgCOOsXY+fx91fvglDtgJMXhF78r874pXt17xcqPtHMxNMbidRrDsd71se7nqk62v3er+6bixumU8yDHvuc8BoUcCD4d8x/Iusec2+hofGOmcHyv/Dc5n0SuV5fP0sbSdVP8f8dnkfJTNEbb2+trhsM2r8bPtTITcw1Uh1IejUJ722Rqv5TDoCOHkMXPLly53iPfUM5xkKXf1VZoE58a4O/tbvXukbcBy4MZBwAAAAAAoBQDBwAAAAAAoBShCkusMRmnEtXSVCQfi8vC+Antaf2ViYmwrbE/TgNerarHxnAMS6vCMD0Z6K04tXB6Q5yCl5d1rT+8c97nrZ51eijvOfe4UN7ww73d67Wv/HsoT7+trI3Lzebpp/W93a8FAEupY9nD4jT1vNxdng6flgTsmO49EqetdyyBFw+O5RzWNZrCEQpLLjZSKMLUMXHfyY1pOnyasT2yp90HG6nFetR2T8Z65CUqU5+22AYdSw2me/TJeO6O9i5eK0ca5M8thzJ0LI1Z/tl0hCLkUIXc9ik0ZHZtuzxxfNzmqQlGd8f+7lBq78qB9o1W63kJxXRPsyl8IO4dwxHSs9sxwT+HIuTQjtRGVmjvRjq2n2U1+1bpHj5U7HN0hEISurAimHEAAAAAAABKMXAAAAAAAABKMXAAAAAAAABKkeNgqaV4ft+bllgcjTFxM5vbyzcO6ZS47/duXtKqLZe9//WsUH7UVfsGVBPgyLDp1pgb5YVX3hnKn3jHi0N572kpNrIQ2rfhjhhHuemHaQnFO+Pyi/Wc06BLjpKO+OGh+P3WIKcBgAHK31HF5Rg74ujzsUN5ucWUlyCVQ+x8jrfOyzEOx2sXcxpIMa/B1KZYj/ET074/viuUDxyI38Prr0jLhBfYdFo+8MBM3KEjj0GjfFteyjG1r+eY/i5L7XXkLKh2zxHR8dkUP+eUqyLLn0Uxp4Ek7T213Z47nxdzPlRq8Z43XRmXftxwd9xeKSxtmHMvVPJyjLl90z1acbnGWsrbkPNJzKZyzg+QFdrXRlJutn5zHBTzYuQcGt1ykOhQSzq329PSI9CxL5YFMw4AAAAAAEApBg4AAAAAAEApBg4AAAAAAEApchwss8aeGONbHYvrnA8XYn8mTt0Ytq3ZFtdbr+/YscS1Wxq7fyHmNFj3sltCmZVUgf4M/cd1ofyeK18Uyn5ejOU74ctxDPiYax5s75u+g+qPxHjY+iLWOu6IH14XY2l9lX5nAThCpdh4Wxu/k2y4EP+f46urKb465zDIcfe5XIxZb6R4/h719ByjXtjeqOV946n++AmfDeVRi3kK3vj1X2tfNoeMj8R7rMzGeltuEy/Evuf7zzHmFnMFmGK93MtzHHToyBmR/u6Zcx4UzabcYyPd/+lTH47nnlnbvvb7fuwfuh77pm+8OpTzZ1ds78pkatuR1F5TKd9ER16H8t/dlnMF5Gc9t2fuBxT2z89ANeVmKOYdkNSRz6OrdKznPBnp58iLVSGlwUAw4wAAAAAAAJRi4AAAAAAAAJRi4AAAAAAAAJQix8Eyy+ud+v6JUC6uKVydirE8s2eeGMrViXhsY39ab32FVLccG8pPP/GeUH6g3zVeAXR11muv7mv/lfoJtI0bVuhKANCb1VKceDGngSQV+lw+krZ1xHnHmPIcg96Rx6BYzPsmjdHY/W4Mx2vVR9p/16vMxnqN7Irlt/zdq0K5Oh2vNbKnvb/1ymmTY8pTXL3VC9vzueqpPTpyHqT8E8VCjt/vkU/CR9NnlxXq5ikmP99TbntLtzW2s31fl7z71fPeV5KsnnYoNl/Ka2EHUrx/yi1guX2LuQRynoGcf0jJTMqf0C0HQv6cq/39zdknp9qnzbkXUv4Jm4kPr9fTtYrPVH5mchs4SRCWAzMOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKXIcrLD67t2hXJlqx/6MpJi4R54ScwlUT3lSKG+84vZ47hVaM338OWeG8s3XxO1nqb94bACHiRRnOvPYk0K5dt0tK1kbAAgqY6PxjdGRUCzGuzfWp31zHH1aj97ymvOVFGMdKpKOTbHunuP98/r1hf29GvcdGY+x29XpFDeeqjWyp72/5bQDsyluPucWSNcO8e459r0jFj5VJOc8KG5Pse8d50psJmXy6ZYDIf+JNN2T53QKqU1GdrVfD+2P2xpD8eDagbi9Oh3LlZlCG+T8Bzl3QCU/jznnQeFcub06Psd87pQjIrd/4ficI6JDPneuS/H4/LnlPCH5mammnBHFy+TnydO5sCyYcQAAAAAAAEr1HDgws1PM7Aozu9HMbjCz17Xe32xmXzSzW1v/P2b5qwsAAI5G9EcAABic+YQqzEr6XXf/tpmtl3SdmX1R0qskfcnd325ml0i6RNIbl6+qR4g0hcen20uPVHbtDds2fzseuu+xsS904KmnhfLYnRvnXtdvuW0Rlexuz0Wxnqe9Z82yXQvA6lHdtCmUPU3dbaQlY4ElRn8EXdna2B/pWIpvrD1FuzEaw0OnN6alHNNU8o5p59N5Ocb2/pU03T0v+Zenx+ewiErh2sO74/TuPD2+MpX6lbV88vbL6mRa/i5Pl0+6hTLkts1L7XWEJuQp7MX9K3nBwI4FBKO0jF9xmc3Oc3f/G2lug9qBeO5GcTnMyXhsx+eW2stmyp8R69U+Wdq/2P6WY1B6hS7kZRFz+xc/27RvYzgtJTqW/imZIzAmCkssTkyFbR3hP6lstfL78Bz20Kv9sCR6zjhw923u/u3W63FJN0k6SdKFki5v7Xa5pJ9ZrkoCAICjG/0RAAAGp68cB2Z2mqQnS7pa0lZ339ba9KCkrUtaMwAAgEOgPwIAwMqa98CBma2T9BlJr3f3MFfd3V0dk1PmjrvYzK41s2tnNHWoXQAAAOaF/ggAACtvXssxmtmQmr+k/8Hd/7H19nYzO8Hdt5nZCZIeOtSx7n6ppEslaYNtJgAl8dl2jM7sQw+HbbWhGLM1tn0slPc9OsbyTZ+zpb3viRviub5xQ7zu1MI7Tb985rdC+UtXxtwLfMjAEaSw5Ni+554VNq39z5tCmcWQsNzojyDIsdsjcZk5T3kMZte3l2ecPC4u1bh/a/e/pa15OH7DDe9NyyJOtPtzDXWPIc9LLOaOU1iOcbj70o6WV0VMceKVmULuhRxz35FaINVzKOZmCFtzjHmWcwt0+xdHPdUrx6vX0jJ9OadB1ke8e14K05VzSLQ/Z6+lz3UoL5kYy9WOHAflvyU72noqtW9eqrBwro58EzkHRL5WXkIxf+6FPAaechrMbIg/Y/sf1f2zWH9P+1pDKQeE52VIZ+M9eyPldZgufBY5RwRWxHxWVTBJH5R0k7v/ZWHT5yRd1Hp9kaTPLn31AAAA6I8AADBI85lx8GOSflnS983s+tZ7b5b0dkmfNLNXS7pb0suWp4oAAAD0RwAAGJSeAwfu/jWVr4ty/tJWBwAAoBP9EQAABmdeOQ6wQlIsz+z920K5OhnzEqyfOT6Ux09fN/d695kxdk9nPiUUj//6zlCu3/jDeVfz6WN3hvJ/zK6f97EADi8P/eYz514fc3P8DmqMj690dQBgjuW47x7r1xdj1CeOi9G6f/yGD4fypspEKL/2L18bT51DrAu5BTpi25Oca8DzcFghB0LOh9CopTj6qe55C6xQr3wdyzunGHSb6RJH3tG2KUZ/eqb82B7nyp+jp9wVPWP4i/kVUl4B65GaIeeQaBSeGUu5GCo5Rj/ll8ifndfa/+yq5lwVua1zHoKcU6J47ZxPIn82PXIadFyrsL0+Ej/Xia0xp8FL33hlKI/XR0P5629r9yEsPV+1R9I997gPFfMaNMhxMAh9LccIAAAAAACOLgwcAAAAAACAUgwcAAAAAACAUuQ4WM1S/E59x45Qrqb1TsfWP2bu9exozHEwuSXGCd3z01tC2S+M5dM+fHv7XA9uD9suffB5qaK7BODIMHv+U0N5Yms7jvL4912fdweAwelY2z6vC59yCVTafaFKCsF/3bdeEcojI3GH4ZxKIF+rGHJ+IPbPGiOxu51zDTRGcq6Gwrlmcox+jptP5Uoqe/H4+PdCy7kYOmLy0/6T5XkLeuUdyJ+NivXMuSmGYntZiu/3tL0jFj5cJ95DzjuglGtAuT1rffyNNadqyNcq5pvI5835EnLOg3yPxXLK49B5rtR+KR+FcrlwvvycKxU/+I3nxmtNx3qePNs+oDKZ8jTketfjPfuBybj7ZCxj5THjAAAAAAAAlGLgAAAAAAAAlGLgAAAAAAAAlCLHwWGsvivmFhj6VnuN9XWVHwnbRsZj/NLuM+JHP7M+nvvGt55aKJ0atv3hsf8Uyh/TifOpLoBVwIbieth3/c+Y02Bqa4xBfPzrvjP3usG6yQBWs7wefd5ciLFe+1Dct/ovcf15WSxbPcZjV2ZSHHmOBS9KMec5vr2R4uqL+RIaVr5N6syX0FHOcfbFc002SrdJnTkiQl6CFDffU46jL+ZEGB4Km3Kehtz2HTkRchsVYuc9H5qupVStjvYttF/+nCopP0J9KJ6seiD+zuz2jHTkk5hO7ZvvuVDOOQw68iHknAepPT3lpygeXZmK516zPea5ePS/xHvOz8zow+28BJX9MUeBTU6HcmP/RCxPxDIGjxkHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFDkOjiDFWKDaFd8O24b/y+NDeWbNxlDefmqMf3rWk26de3386HjYdlxtb7oyOQ6A1WrqJU8P5Xe+972h/IpPxRwHj/ut74RyY7bPOFYAWCk5ZnwqxkxbivUudnor0zGuuzYR8780Um6AxlCKQc9h9jON0m35WvUcz57PNdt+ozES9805DBpD8Y2cH0CFPAb5r4UduQRSe3XG3ZfnROi4biXFvufPqhh3n2L0reNcqR45Rj9XppDjQJX4uXqPPBj1kVjvYo6D+mjcNpPavnYg1qsxHK9VKdxzIyVXqE7EZ9erOXdAl3wJqX3C/UudOQ/y9lwufByVyXjs8NT+UB5KeR0s51PYd6DwOuUwGN8Xy/vjubH6MOMAAAAAAACUYuAAAAAAAACUIlThSJWmCjW+e1MoH3Pf5lAe2XNGKF9lj517fe45d4RtZ295OJStFh8jZ2ozsKyqx8af3x0//bhQfu8f/PXc63tn4s/vm1/+6lA+/VvfDOUuC4oBwKriszOpnKZz5yXsittmUqjC3qlQzlPaG2Opy5yW4qtOtc/XsSRins6djq3MxKnis4Up8Y2ReLJ6mv4+tT5ur8YZ76oWjh/ZHe+54x7TlPZKbr9CvTuWSOw1HT7/dukWMpCm6fecWp9DG4YKn1W6TH4mGik0YXYslddUCttS++TursWLDe0tD+3omNKfl77sOKB8Wc2e+/ZavjIv51gMfeiyVO1lzuIAABEcSURBVKOkzmU502fT2L1n7nU9L6/Y5ecTqxMzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHByl6jsfCeWRz+8K5cc+cPbc61tfeFbY9jsv/e+hPP7fTgvldZ+6eglqCOCgvKTilR94fyiff+O6UH7Lqy6ee135clxeUfr+ktYNAAYmxUj75GQo2/BQLO9vLw2nsZG4bTYte5iWIsxLKnbEZxfj//Of5fJyjGvjEoGaSfkSCjHoeVm+qS0xynzfKd3j7kd3tF8P7UvLLaYlJ3vF2Vsxfj3Fsncst5jzEHSLZ88x+T3i5lVLORDycoTF86VtHctG5ltOp5pe335j/LTueQbW35U+x8n0DBWW2bQDKT9HzjswGXNudCi253Q8V2cOiB7LNWbF/espL0bKY1Z/ZHc6d/o5wRGFGQcAAAAAAKAUAwcAAAAAAKAUAwcAAAAAAKAUOQ7QlOMEv3PD3OsTU4j0nu/HeOsHXxzjss78dI/1YwF0l2Idz/iDm0L5J5/+klCu3X9POkEuA8CRr7E/rhPfkeOgPlR4HeO8fd1Y3PdAirPPcfXpeFULf4vL4f3D3fMl1Efiub24ew7/XxvfuPnX3qduznnHb7avMxqPrU6m8kTKWzCd2qDYn7Me+RJynoKs2F6zKS4+xdV3xOhnHTH7hfZMeRsqM7E8Mxr/KdSoxfuY3Nwuf/FX3xG2HVeNeTLO+9PXhbI9GGtVvLbNxHu0qelY7pUzIrdZF55zIGR95CWo79qz4GNx+GPGAQAAAAAAKMXAAQAAAAAAKMXAAQAAAAAAKEWOA/Rt+AvXhPIpFnMe7HzNeaF87Pu/uex1Ao4k913yrFDe/b4Y67jpfn6mAKBDirdu7N0XypV1a9uFlH/J9qYY8pzTYCoWfahLF7ra/e9yHfHttbi/Fapi9VjP4fFYPuujv5EqFoub9rbfqO2P91g7kOqR8jbka6sQd285xj7ns8rtl3MeFMspX0K/cj6AYky/pc/JZ2O9KjlXheL20Z3tc7/go7+XLhyLx+xNbZDbpFDuaNtebZDzPHi7/frOYZDzJ+ScEsVdp9KDT06DoxozDgAAAAAAQKmeAwdmNmpm3zKz75rZDWb2R633H2NmV5vZbWb2CTMbXv7qAgCAoxH9EQAABmc+Mw6mJL3A3c+RdK6kC8zsPEl/Juld7n6mpF2SXr181QQAAEc5+iMAAAxIzxwH7u6SDgaJDbX+c0kvkPQLrfcvl/RWSX+79FXEajfyrzHnwczLYo4De/qT5l77Nd9fkToBh5vG854893rtAymnwUfIaQDQH0G/fGY6lg+0/16WI8o9xX13RJynGHRTitkvxMp7ynGQcwf46FAoV1LOAy/kPLAUJ79mR6zH0ER5fgRJqk2036hNxutUplOOg1QPpdj5cB+NnBugh5z3oXiunAsg8dnY1pbj/eupnoX8Cp4/t3SP1X3xGRlJt1WZbtdtZDxe11M1hsbjuYf2xXpXDhTKKeeD5RwQuX1zHodim+S8AzlngeX8COl5TO3rheM95zjAUW1eOQ7MrGpm10t6SNIXJd0uabf7XGaO+ySdtDxVBAAAoD8CAMCgzGvgwN3r7n6upJMlPUPS4+d7ATO72MyuNbNrZ3JKWgAAgHmiPwIAwGD0taqCu++WdIWkZ0naZGYHQx1OlnR/yTGXuvvT3P1pQxpZVGUBAADojwAAsLJ65jgws+Mkzbj7bjMbk/QiNRMRXSHpZyV9XNJFkj67nBXF4WPdp64O5R0Xt3MeHFs7J2yzb353ReoErDbVs04P5QOb2jGvx1xOTgMgoz+CxWpMTs69zrkDKiNxMMlz3HgtdpnNUxe6UOyIVy/E3DdPnmL6LV67Otk+vlGLf+OrpZj9ofEUn16J26tT7fuoTOacBd69nO9jMTkOOuLu2/X06Wl1le45729DMWdE11Ple0p/Qq3tnYybpwofbGrbnD+hMp3zFqQcErNd2i+XU36JrnkgUv6DjnwInj/HlFMjtUnODQIc1HPgQNIJki43s6qaP16fdPd/NrMbJX3czN4m6TuSPriM9QQAAEc3+iMAAAzIfFZV+J6kJx/i/TvUjC8EAABYVvRHAAAYnPnMOAD6k6ZTbbn0qrnX+37umWFbdWvs643907eWr17AADWefW4oT22MUyvHPsuzDwArJS8z18jLMXoMH8hT3L2awg8Kyw1aCmvI/aIcJpGXKrTClHcbjufKSzd2nDtvL0yn79iWlonsmMY/W77Mn+dt3iN0IV0r3HOeap/ljGy99i9cy+pp2n0KN7CptGTnyHAoV2fL78tr5Z/boeoZ2jeHbqT27GjfFDrjOZQh7JvqnJ6RHOqRl2MEyvSVHBEAAAAAABxdGDgAAAAAAAClGDgAAAAAAAClyHGA5VeIrVr3yavCpsq5Z4fyrl88L5Q3fuyaeK68PBKwWlRivOvUTzwllNfcuSfu/rUfLnuVAADzk5eg8xSDXhkbDeUYKa8Q4++W/i6XcwmkZfxs34G4fzEOfybmw7FKj7/5pXpbMc4+51boVc7L9hXj7lNcfI6Tt5S3wXMb1AvLMebrphh9G0r/XMn5JnJ+hUL753oo56ZIOnJZjLVzXVjO05CW2ezIEZHvq0tego6cBjnvQM6JUGyj/Dn1yGnQdWlHoAtmHAAAAAAAgFIMHAAAAAAAgFIMHAAAAAAAgFLkOMBANa6/MZQ333dsKN/9xmeG8il/Hte6Z+1ZrBrPeEIorrn27lCub39oJWsDAFiMlFOpMTERypWRkVAuxs6HvAJpmyR5pSNDQlSIWbd6zK2gHLOf5Vj5Qix8jqPviP9PfOJA1+3hXClvg3eJ55ckty5t0BGjn86Vj52K+xfvyxspp8FMOlet+z+FrNgEOX9EPrZXvYu5GHK+hJSnwXvkS+jYHrZNl24DFoMZBwAAAAAAoBQDBwAAAAAAoBQDBwAAAAAAoBQ5DrCq1B/eGcqn/Md4KPvTzg7lyvdum3ud4w+BpVaMZ6w+amvY5rfdH8r5WQYAHMZyjHnOsVSMWa+mPAMpx4GmYwy6DZV3x31yMr5h6W9+KTa+Q46lLx460/1YT/dczJfQ0R45/j/nPMjn6ibniOiRE8JyDolQl5RnIO1rqd6ZT02VHqv82fTgXT6LDqleuf3CPfZ6BoAlwowDAAAAAABQioEDAAAAAABQioEDAAAAAABQihwHWNX8mu+HcuWJj4/bzz597vXEKWvDtv2PiuNijVqMkRvbGWPCDmxp7z+2I24bfSTGMk4cP5TOHeu9blt7f0/Dc6PbUy6GStyhsidut7372udaH+9Ru1MOiBRvl2MMi3GCjf1xfebKunjujjWrx+Ja0rY21aV4rR6xjI1jNsTymtiexXqOn7ombKpNxc/Gypcyblal8NnkZ2BoPMYQTm+MH+TQ/rh9zW272ue694GwjRwbAHD06MhxUNyWwuqVfxfnPAUH8mYr3zfrFf9fuHZfeQakjlwDVm3XJcfr5xwHfV0px+jne67nzSl/Qrc8BflcM/Fz89x+Ob9CN30eW6xnz3vo97MCVgAzDgAAAAAAQCkGDgAAAAAAQCkGDgAAAAAAQClyHOCw0vjBzaXb1lybyn2ee9P69XOvc7x/NrZhXSj7SJc1mEdi/H59LMXz59jHRswlUC3E4/nIcDz0uGNieefudK4Un7iu3SqW4hMt3VMlxd9ZbpPZFM84NqIyNhnXrK5MpFwMjRTfWIjt23hDOnZ8f+l1JMkLOSEkyQvrZTf2dz92uOvWjjBLAAB6y/Hq3v23SQ75X9Sll+5UnbkblssKts+gHAn3gKMPMw4AAAAAAEApBg4AAAAAAEApQhWAlsb4+CFfH9K2hV+n12hdnlbYY7XB/uwo39Tznnc+spQ1WTBm9wEAAAArixkHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACgFAMHAAAAAACglLnnVeOX8WJmOyTdLWmLpIdX7MKHP9qrP7RXf2iv/tBe/aG95udUdz9u0JU4WtAfWTDaqz+0V39or/7QXv2hveantD+yogMHcxc1u9bdn7biFz5M0V79ob36Q3v1h/bqD+2F1Yznsz+0V39or/7QXv2hvfpDey0eoQoAAAAAAKAUAwcAAAAAAKDUoAYOLh3QdQ9XtFd/aK/+0F79ob36Q3thNeP57A/t1R/aqz+0V39or/7QXos0kBwHAAAAAADg8ECoAgAAAAAAKLWiAwdmdoGZ3WJmt5nZJSt57cOBmZ1iZleY2Y1mdoOZva71/mYz+6KZ3dr6/zGDrutqYmZVM/uOmf1zq/wYM7u69Zx9wsyGB13H1cLMNpnZp83sZjO7ycyexfNVzsx+p/Wz+AMz+5iZjfJ8RWb2ITN7yMx+UHjvkM+UNf11q+2+Z2ZPGVzNcTSjP9Id/ZGFoT8yf/RH+kN/pDf6I8tvxQYOzKwq6b2SfkLS2ZJ+3szOXqnrHyZmJf2uu58t6TxJv9Vqo0skfcndz5L0pVYZba+TdFOh/GeS3uXuZ0raJenVA6nV6vRuSV9w98dLOkfNduP5OgQzO0nSb0t6mrs/UVJV0ivE85VdJumC9F7ZM/UTks5q/XexpL9doToCc+iPzAv9kYWhPzJ/9Efmif7IvF0m+iPLaiVnHDxD0m3ufoe7T0v6uKQLV/D6q567b3P3b7dej6v5JXqSmu10eWu3yyX9zGBquPqY2cmSflLSB1plk/QCSZ9u7UJ7tZjZRknPlfRBSXL3aXffLZ6vbmqSxsysJmmNpG3i+Qrc/SuSHklvlz1TF0r6iDddJWmTmZ2wMjUF5tAf6YH+SP/oj8wf/ZEFoT/SA/2R5beSAwcnSbq3UL6v9R4OwcxOk/RkSVdL2uru21qbHpS0dUDVWo3+StLvS2q0ysdK2u3us60yz1nbYyTtkPTh1lTKD5jZWvF8HZK73y/pLyTdo+Yv6D2SrhPP13yUPVP8HsBqwHPYB/oj80Z/ZP7oj/SB/sii0B9ZQiRHXIXMbJ2kz0h6vbvvLW7z5jIYLIUhycxeKukhd79u0HU5TNQkPUXS37r7kyXtV5oGyPPV1oqDu1DNDs6JktaqcwoceuCZAg5f9Efmh/5I3+iP9IH+yNLgmVq8lRw4uF/SKYXyya33UGBmQ2r+kv4Hd//H1tvbD06faf3/oUHVb5X5MUk/bWZ3qTnV9AVqxsxtak3lknjOiu6TdJ+7X90qf1rNX9w8X4f2Qkl3uvsOd5+R9I9qPnM8X72VPVP8HsBqwHM4D/RH+kJ/pD/0R/pDf2Th6I8soZUcOLhG0lmtDKDDaib1+NwKXn/Va8XDfVDSTe7+l4VNn5N0Uev1RZI+u9J1W43c/U3ufrK7n6bm8/Sf7v6Lkq6Q9LOt3WivFnd/UNK9Zva41lvnS7pRPF9l7pF0npmtaf1sHmwvnq/eyp6pz0l6ZSub8XmS9hSmEAIrhf5ID/RH+kN/pD/0R/pGf2Th6I8sIWvO2lihi5m9RM0YsKqkD7n7n6zYxQ8DZvZsSV+V9H21Y+TerGZc4SclPVrS3ZJe5u45+cdRzcyeL+kN7v5SMztdzRH/zZK+I+mX3H1qkPVbLczsXDUTNw1LukPSr6g5gMjzdQhm9keSXq5mhvHvSHqNmjFwPF8tZvYxSc+XtEXSdkl/KOmfdIhnqtXheY+aUywnJP2Ku187iHrj6EZ/pDv6IwtHf2R+6I/0h/5Ib/RHlt+KDhwAAAAAAIDDC8kRAQAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAKQYOAAAAAABAqf8PQX3FyrAi+8wAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "from matplotlib import pyplot as plt\n", - "fig = plt.figure(figsize=(18, 16))\n", - "\n", - "sub_plot1 = plt.subplot(121, title=\"Kettle Flux\")\n", - "sub_plot1.imshow(pot_flux)\n", - "\n", - "sub_plot2 = plt.subplot(122, title=\"Water Flux\")\n", - "sub_plot2.imshow(water_flux)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/candu.ipynb b/examples/jupyter/candu.ipynb deleted file mode 100644 index 672d56f89..000000000 --- a/examples/jupyter/candu.ipynb +++ /dev/null @@ -1,1115 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this example, we will create a typical CANDU bundle with rings of fuel pins. At present, OpenMC does not have a specialized lattice for this type of fuel arrangement, so we must resort to manual creation of the array of fuel pins." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "from math import pi, sin, cos\n", - "import numpy as np\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's begin by creating the materials that will be used in our model." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "fuel = openmc.Material(name='fuel')\n", - "fuel.add_element('U', 1.0)\n", - "fuel.add_element('O', 2.0)\n", - "fuel.set_density('g/cm3', 10.0)\n", - "\n", - "clad = openmc.Material(name='zircaloy')\n", - "clad.add_element('Zr', 1.0)\n", - "clad.set_density('g/cm3', 6.0)\n", - "\n", - "heavy_water = openmc.Material(name='heavy water')\n", - "heavy_water.add_nuclide('H2', 2.0)\n", - "heavy_water.add_nuclide('O16', 1.0)\n", - "heavy_water.add_s_alpha_beta('c_D_in_D2O')\n", - "heavy_water.set_density('g/cm3', 1.1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our materials created, we'll now define key dimensions in our model. These dimensions are taken from the example in section 11.1.3 of the [Serpent manual](http://montecarlo.vtt.fi/download/Serpent_manual.pdf)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Outer radius of fuel and clad\n", - "r_fuel = 0.6122\n", - "r_clad = 0.6540\n", - "\n", - "# Pressure tube and calendria radii\n", - "pressure_tube_ir = 5.16890\n", - "pressure_tube_or = 5.60320\n", - "calendria_ir = 6.44780\n", - "calendria_or = 6.58750\n", - "\n", - "# Radius to center of each ring of fuel pins\n", - "ring_radii = np.array([0.0, 1.4885, 2.8755, 4.3305])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To begin creating the bundle, we'll first create annular regions completely filled with heavy water and add in the fuel pins later. The radii that we've specified above correspond to the center of each ring. We actually need to create cylindrical surfaces at radii that are half-way between the centers." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# These are the surfaces that will divide each of the rings\n", - "radial_surf = [openmc.ZCylinder(r=r) for r in\n", - " (ring_radii[:-1] + ring_radii[1:])/2]\n", - "\n", - "water_cells = []\n", - "for i in range(ring_radii.size):\n", - " # Create annular region\n", - " if i == 0:\n", - " water_region = -radial_surf[i]\n", - " elif i == ring_radii.size - 1:\n", - " water_region = +radial_surf[i-1]\n", - " else:\n", - " water_region = +radial_surf[i-1] & -radial_surf[i]\n", - " \n", - " water_cells.append(openmc.Cell(fill=heavy_water, region=water_region))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's see what our geometry looks like so far. In order to plot the geometry, we create a universe that contains the annular water cells and then use the `Universe.plot()` method. While we're at it, we'll set some keyword arguments that can be reused for later plots." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_args = {'width': (2*calendria_or, 2*calendria_or)}\n", - "bundle_universe = openmc.Universe(cells=water_cells)\n", - "bundle_universe.plot(**plot_args)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to create a universe that contains a fuel pin. Note that we don't actually need to put water outside of the cladding in this universe because it will be truncated by a higher universe." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "surf_fuel = openmc.ZCylinder(r=r_fuel)\n", - "\n", - "fuel_cell = openmc.Cell(fill=fuel, region=-surf_fuel)\n", - "clad_cell = openmc.Cell(fill=clad, region=+surf_fuel)\n", - "\n", - "pin_universe = openmc.Universe(cells=(fuel_cell, clad_cell))" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQEAAAD8CAYAAAB3lxGOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAC0lJREFUeJzt3VuopeV9x/Hvr2Nsp9GJFB0sztCxNaZMc0DZkQZp2kQJxojelGJoQk0uhoZGDAjigV4WStMmERJaNmpuMiDBmCYEc1BygF44zWg01hkTRNI4omguykgzRKb+e7HWwKjb2YPr2e/a4//7AWHWYZ7nQff6+rxrrf2+qSok9fVby16ApOUyAlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjttGZNm67bizO3LmFrq4cXnqSOHczJPXUoEOHM7W/7qX5YytdTB/331xpN+rocDUnNGQGrOCEjNGQGpuSERSHJWknuSPJHkYJL3jRhX0sYb9enA7cB3quovk5wO/O6gcSVtsIUjkORtwPuB6wCq6iXgpUXHlTSNEYcD5wMvAF9O8pMkdyR564BxJU1gRAROAy4G/rWqLgL+F7j51U9KsifJ/iT7OXJ4wLSSRhgRgUPAoaraN799D7MovEJVrVbVSlWtsHXbgGkljbBwBKrqOeDpJO+Y33UZcGDRcSVNY9SnA9cDe+efDDwFfGLQuJI22JAIVNUjwMqIsSRNy28MSs0ZAak5IyA1ZwSk5oyA1JwRkJozAlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNWcEpOaMgNScEZCaMwJSc0ZAam5YBJJsmV+V+FujxpS08UbuBG4ADg4cT9IEhkQgyQ7gI8AdI8aTNJ1RO4EvADcBLw8aT9JEFo5AkquA56vqoXWetyfJ/iT7OXJ40WklDTJiJ3ApcHWSXwB3Ax9M8pVXP6mqVqtqpapW2LptwLSSRlg4AlV1S1XtqKpdwLXA96vqYwuvTNIk/J6A1NxpIwerqh8CPxw5pqSN5U5Aas4ISM0ZAak5IyA1ZwSk5oyA1JwRkJozAlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNWcEpOaMgNScEZCaMwJScyMuSLozyQ+SHEjyeJIbRixM0jRGXIHoKHBjVT2c5EzgoST3V9WBAWNL2mAjLkj6bFU9PP/zi8BB4LxFx5U0jaHvCSTZBVwE7Bs5rqSNMywCSc4AvgZ8pqoOr/H4niT7k+znyGselrQkQyKQ5C3MArC3qu5d6zlVtVpVK1W1wtZtI6aVNMCITwcC3AkcrKrPLb4kSVMasRO4FPg48MEkj8z/uXLAuJImsPBHhFX1H0AGrEXSEviNQak5IyA1ZwSk5oyA1JwRkJozAlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNTfiCkR6E/rrK3//hI/vve/ZiVaijeZOQK+xXgBO9jk6NbgTEPDGXtTH/x13BqcudwJSc0ZAas4IaMjxve8RnLpGXYvwiiQ/S/JkkptHjKlpjHzxGoJT04hrEW4BvgR8GNgNfDTJ7kXHlTSNETuBS4Anq+qpqnoJuBu4ZsC4kiYwIgLnAU8fd/vQ/D5Jp4DJ3hhMsifJ/iT7OXJ4qmklrWNEBJ4Bdh53e8f8vleoqtWqWqmqFbZuGzCtpBFGRODHwNuTnJ/kdOBa4JsDxpU0gYW/NlxVR5N8GvgusAW4q6oeX3hlkiYx5D2Bqrqvqi6sqj+qqn8YMaamMfI7//7+wKnJbwxqyIvXAJy6jIDUnBGQmvN8AgJeuZ0/2d8B8BDgzcGdgF7jZF7cBuDNw52A1uSLvA93AlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNWcEpOaMgNScEZCaMwJSc0ZAam6hCCT5bJInkvw0ydeTnDVqYZKmsehO4H7gnVX1buDnwC2LL0nSlBaKQFV9r6qOzm8+yOyKxJJOISPfE/gk8O2B40mawLqnHE/yAHDuGg/dVlXfmD/nNuAosPcE4+wB9gBwxjlvZK2SNsC6Eaiqy0/0eJLrgKuAy6qqTjDOKrAKkO0XvO7zJE1roYuPJLkCuAn486r69ZglSZrSou8JfBE4E7g/ySNJ/m3AmiRNaKGdQFVdMGohkpbDbwxKzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNWcEpOaMgNScEZCaMwJSc0ZAas4ISM0ZAak5IyA1ZwSk5oyA1JwRkJozAlJzRkBqbkgEktyYpJKcPWI8SdNZOAJJdgIfAn65+HIkTW3ETuDzzC5K6pWGpVPQQhFIcg3wTFU9Omg9kia27gVJkzwAnLvGQ7cBtzI7FFhXkj3AHgDOOOfkVyhpQ60bgaq6fK37k7wLOB94NAnADuDhJJdU1XNrjLMKrAJk+wUeOkibxBu+NHlVPQZsP3Y7yS+Alar61YB1SZqI3xOQmnvDO4FXq6pdo8aSNB13AlJzRkBqzghIzRkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGrOCEjNGQGpOSMgNWcEpOaMgNScEZCaMwJSc0ZAas4ISM0ZAak5IyA1ZwSk5oyA1JwRkJpbOAJJrk/yRJLHk/zTiEVJms5CVyBK8gHgGuA9VfWbJNvX+zuSNpdFdwKfAv6xqn4DUFXPL74kSVNaNAIXAn+WZF+SHyV574hFSZrOuocDSR4Azl3jodvmf//3gD8F3gt8NckfVlWtMc4eYA8AZ5yzwJIljbRuBKrq8td7LMmngHvnL/r/TPIycDbwwhrjrAKrANl+wWsiIWk5Fj0c+HfgAwBJLgROB3616KIkTWehTweAu4C7kvwX8BLwN2sdCkjavBaKQFW9BHxs0FokLYHfGJSaMwJSc0ZAas4ISM0ZAam5LOMTvSQvAP99Ek89m+V/78A1uIZTcQ1/UFUn9dXcpUTgZCXZX1UrrsE1uIaNW4OHA1JzRkBqbrNHYHXZC8A1HOMaZt50a9jU7wlI2nibfScgaYNt+ghslhOZJrkxSSU5ewlzf3b+7+CnSb6e5KwJ574iyc+SPJnk5qnmPW7+nUl+kOTA/GfghqnXcNxatiT5SZJvLWn+s5LcM/9ZOJjkfSPG3dQReNWJTP8E+OclrWMn8CHgl8uYH7gfeGdVvRv4OXDLFJMm2QJ8CfgwsBv4aJLdU8x9nKPAjVW1m9kZrP5uCWs45gbg4JLmBrgd+E5V/THwnlFr2dQRYPOcyPTzwE3AUt5AqarvVdXR+c0HgR0TTX0J8GRVPTX/tfG7mUV5MlX1bFU9PP/zi8x+8M+bcg0ASXYAHwHumHru+fxvA94P3AmzX+Ovqv8ZMfZmj8DST2Sa5Brgmap6dOq5X8cngW9PNNd5wNPH3T7EEl6AxyTZBVwE7FvC9F9g9j+Cl5cwN8D5zE7b9+X5IckdSd46YuBFzyy0sFEnMt3ANdzK7FBgQ51oDVX1jflzbmO2Pd670evZbJKcAXwN+ExVHZ547quA56vqoSR/MeXcxzkNuBi4vqr2JbkduBn4+xEDL9WoE5luxBqSvItZgR9NArNt+MNJLqmq56ZYw3FruQ64CrhswlO4PQPsPO72jvl9k0ryFmYB2FtV9049P3ApcHWSK4HfAbYl+UpVTXlWrUPAoao6tgu6h1kEFrbZDweWeiLTqnqsqrZX1a6q2sXsP8TFowOwniRXMNuKXl1Vv55w6h8Db09yfpLTgWuBb044P5nV907gYFV9bsq5j6mqW6pqx/xn4Frg+xMHgPnP3NNJ3jG/6zLgwIixl74TWIcnMp35IvDbwP3zHcmDVfW3Gz1pVR1N8mngu8AW4K6qenyj532VS4GPA48leWR+361Vdd/E69gMrgf2zoP8FPCJEYP6jUGpuc1+OCBpgxkBqTkjIDVnBKTmjIDUnBGQmjMCUnNGQGru/wH1K+f9naPQrwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "pin_universe.plot(**plot_args)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code below works through each ring to create a cell containing the fuel pin universe. As each fuel pin is created, we modify the region of the water cell to include everything outside the fuel pin." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "num_pins = [1, 6, 12, 18]\n", - "angles = [0, 0, 15, 0]\n", - "\n", - "for i, (r, n, a) in enumerate(zip(ring_radii, num_pins, angles)):\n", - " for j in range(n):\n", - " # Determine location of center of pin\n", - " theta = (a + j/n*360.) * pi/180.\n", - " x = r*cos(theta)\n", - " y = r*sin(theta)\n", - " \n", - " pin_boundary = openmc.ZCylinder(x0=x, y0=y, r=r_clad)\n", - " water_cells[i].region &= +pin_boundary\n", - " \n", - " # Create each fuel pin -- note that we explicitly assign an ID so \n", - " # that we can identify the pin later when looking at tallies\n", - " pin = openmc.Cell(fill=pin_universe, region=-pin_boundary)\n", - " pin.translation = (x, y, 0)\n", - " pin.id = (i + 1)*100 + j\n", - " bundle_universe.add_cell(pin)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "bundle_universe.plot(**plot_args)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Looking pretty good! Finally, we create cells for the pressure tube and calendria and then put our bundle in the middle of the pressure tube." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "pt_inner = openmc.ZCylinder(r=pressure_tube_ir)\n", - "pt_outer = openmc.ZCylinder(r=pressure_tube_or)\n", - "calendria_inner = openmc.ZCylinder(r=calendria_ir)\n", - "calendria_outer = openmc.ZCylinder(r=calendria_or, boundary_type='vacuum')\n", - "\n", - "bundle = openmc.Cell(fill=bundle_universe, region=-pt_inner)\n", - "pressure_tube = openmc.Cell(fill=clad, region=+pt_inner & -pt_outer)\n", - "v1 = openmc.Cell(region=+pt_outer & -calendria_inner)\n", - "calendria = openmc.Cell(fill=clad, region=+calendria_inner & -calendria_outer)\n", - "\n", - "root_universe = openmc.Universe(cells=[bundle, pressure_tube, v1, calendria])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's look at the final product. We'll export our geometry and materials and then use `plot_inline()` to get a nice-looking plot." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "geom = openmc.Geometry(root_universe)\n", - "geom.export_to_xml()\n", - "\n", - "mats = openmc.Materials(geom.get_all_materials().values())\n", - "mats.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = openmc.Plot.from_geometry(geom)\n", - "p.color_by = 'material'\n", - "p.colors = {\n", - " fuel: 'black',\n", - " clad: 'silver',\n", - " heavy_water: 'blue'\n", - "}\n", - "p.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Interpreting Results\n", - "\n", - "One of the difficulties of a geometry like this is identifying tally results when there was no lattice involved. To address this, we specifically gave an ID to each fuel pin of the form 100\\*ring + azimuthal position. Consequently, we can use a distribcell tally and then look at our `DataFrame` which will show these cell IDs." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.particles = 1000\n", - "settings.batches = 20\n", - "settings.inactive = 10\n", - "settings.source = openmc.Source(space=openmc.stats.Point())\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "fuel_tally = openmc.Tally()\n", - "fuel_tally.filters = [openmc.DistribcellFilter(fuel_cell)]\n", - "fuel_tally.scores = ['flux']\n", - "\n", - "tallies = openmc.Tallies([fuel_tally])\n", - "tallies.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "openmc.run(output=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The return code of `0` indicates that OpenMC ran successfully. Now let's load the statepoint into a `openmc.StatePoint` object and use the `Tally.get_pandas_dataframe(...)` method to see our results." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "sp = openmc.StatePoint('statepoint.{}.h5'.format(settings.batches))" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
level 1level 2level 3distribcellnuclidescoremeanstd. dev.
univcellunivcellunivcell
idididididid
03441100250totalflux0.2078050.007037
13441200251totalflux0.1971970.005272
23441201252totalflux0.1903100.007816
33441202253totalflux0.1947360.006469
43441203254totalflux0.1910970.006431
53441204255totalflux0.1899100.004891
63441205256totalflux0.1822030.003851
73441300257totalflux0.1659220.005815
83441301258totalflux0.1689330.008300
93441302259totalflux0.1595870.003085
1034413032510totalflux0.1591580.005910
1134413042511totalflux0.1485370.005308
1234413052512totalflux0.1509450.006654
1334413062513totalflux0.1542370.003665
1434413072514totalflux0.1658880.004733
1534413082515totalflux0.1567770.006540
1634413092516totalflux0.1652770.005935
1734413102517totalflux0.1565280.005732
1834413112518totalflux0.1596100.004584
1934414002519totalflux0.0965970.004466
2034414012520totalflux0.1182140.005451
2134414022521totalflux0.1061670.004722
2234414032522totalflux0.1108140.004208
2334414042523totalflux0.1123190.005079
2434414052524totalflux0.1102320.004153
2534414062525totalflux0.0999670.005085
2634414072526totalflux0.0954440.003615
2734414082527totalflux0.0926200.003997
2834414092528totalflux0.0955170.004022
2934414102529totalflux0.1137370.009530
3034414112530totalflux0.1083680.007241
3134414122531totalflux0.1069900.005716
3234414132532totalflux0.1120500.005002
3334414142533totalflux0.1150540.006239
3434414152534totalflux0.1143940.004919
3534414162535totalflux0.1143520.005322
3634414172536totalflux0.1108900.005051
\n", - "
" - ], - "text/plain": [ - " level 1 level 2 level 3 distribcell nuclide score mean \\\n", - " univ cell univ cell univ cell \n", - " id id id id id id \n", - "0 3 44 1 100 2 5 0 total flux 2.08e-01 \n", - "1 3 44 1 200 2 5 1 total flux 1.97e-01 \n", - "2 3 44 1 201 2 5 2 total flux 1.90e-01 \n", - "3 3 44 1 202 2 5 3 total flux 1.95e-01 \n", - "4 3 44 1 203 2 5 4 total flux 1.91e-01 \n", - "5 3 44 1 204 2 5 5 total flux 1.90e-01 \n", - "6 3 44 1 205 2 5 6 total flux 1.82e-01 \n", - "7 3 44 1 300 2 5 7 total flux 1.66e-01 \n", - "8 3 44 1 301 2 5 8 total flux 1.69e-01 \n", - "9 3 44 1 302 2 5 9 total flux 1.60e-01 \n", - "10 3 44 1 303 2 5 10 total flux 1.59e-01 \n", - "11 3 44 1 304 2 5 11 total flux 1.49e-01 \n", - "12 3 44 1 305 2 5 12 total flux 1.51e-01 \n", - "13 3 44 1 306 2 5 13 total flux 1.54e-01 \n", - "14 3 44 1 307 2 5 14 total flux 1.66e-01 \n", - "15 3 44 1 308 2 5 15 total flux 1.57e-01 \n", - "16 3 44 1 309 2 5 16 total flux 1.65e-01 \n", - "17 3 44 1 310 2 5 17 total flux 1.57e-01 \n", - "18 3 44 1 311 2 5 18 total flux 1.60e-01 \n", - "19 3 44 1 400 2 5 19 total flux 9.66e-02 \n", - "20 3 44 1 401 2 5 20 total flux 1.18e-01 \n", - "21 3 44 1 402 2 5 21 total flux 1.06e-01 \n", - "22 3 44 1 403 2 5 22 total flux 1.11e-01 \n", - "23 3 44 1 404 2 5 23 total flux 1.12e-01 \n", - "24 3 44 1 405 2 5 24 total flux 1.10e-01 \n", - "25 3 44 1 406 2 5 25 total flux 1.00e-01 \n", - "26 3 44 1 407 2 5 26 total flux 9.54e-02 \n", - "27 3 44 1 408 2 5 27 total flux 9.26e-02 \n", - "28 3 44 1 409 2 5 28 total flux 9.55e-02 \n", - "29 3 44 1 410 2 5 29 total flux 1.14e-01 \n", - "30 3 44 1 411 2 5 30 total flux 1.08e-01 \n", - "31 3 44 1 412 2 5 31 total flux 1.07e-01 \n", - "32 3 44 1 413 2 5 32 total flux 1.12e-01 \n", - "33 3 44 1 414 2 5 33 total flux 1.15e-01 \n", - "34 3 44 1 415 2 5 34 total flux 1.14e-01 \n", - "35 3 44 1 416 2 5 35 total flux 1.14e-01 \n", - "36 3 44 1 417 2 5 36 total flux 1.11e-01 \n", - "\n", - " std. dev. \n", - " \n", - " \n", - "0 7.04e-03 \n", - "1 5.27e-03 \n", - "2 7.82e-03 \n", - "3 6.47e-03 \n", - "4 6.43e-03 \n", - "5 4.89e-03 \n", - "6 3.85e-03 \n", - "7 5.82e-03 \n", - "8 8.30e-03 \n", - "9 3.09e-03 \n", - "10 5.91e-03 \n", - "11 5.31e-03 \n", - "12 6.65e-03 \n", - "13 3.67e-03 \n", - "14 4.73e-03 \n", - "15 6.54e-03 \n", - "16 5.94e-03 \n", - "17 5.73e-03 \n", - "18 4.58e-03 \n", - "19 4.47e-03 \n", - "20 5.45e-03 \n", - "21 4.72e-03 \n", - "22 4.21e-03 \n", - "23 5.08e-03 \n", - "24 4.15e-03 \n", - "25 5.08e-03 \n", - "26 3.62e-03 \n", - "27 4.00e-03 \n", - "28 4.02e-03 \n", - "29 9.53e-03 \n", - "30 7.24e-03 \n", - "31 5.72e-03 \n", - "32 5.00e-03 \n", - "33 6.24e-03 \n", - "34 4.92e-03 \n", - "35 5.32e-03 \n", - "36 5.05e-03 " - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "t = sp.get_tally()\n", - "t.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can see that in the 'level 2' column, the 'cell id' tells us how each row corresponds to a ring and azimuthal position." - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/chain_simple.xml b/examples/jupyter/chain_simple.xml deleted file mode 120000 index 8b1b45535..000000000 --- a/examples/jupyter/chain_simple.xml +++ /dev/null @@ -1 +0,0 @@ -/home/romano/openmc/tests/chain_simple.xml \ No newline at end of file diff --git a/examples/jupyter/expansion-filters.ipynb b/examples/jupyter/expansion-filters.ipynb deleted file mode 100644 index 69d315e24..000000000 --- a/examples/jupyter/expansion-filters.ipynb +++ /dev/null @@ -1,463 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC's general tally system accommodates a wide range of tally *filters*. While most filters are meant to identify regions of phase space that contribute to a tally, there are a special set of functional expansion filters that will multiply the tally by a set of orthogonal functions, e.g. Legendre polynomials, so that continuous functions of space or angle can be reconstructed from the tallied moments.\n", - "\n", - "In this example, we will determine the spatial dependence of the flux along the $z$ axis by making a Legendre polynomial expansion. Let us represent the flux along the z axis, $\\phi(z)$, by the function\n", - "\n", - "$$ \\phi(z') = \\sum\\limits_{n=0}^N a_n P_n(z') $$\n", - "\n", - "where $z'$ is the position normalized to the range [-1, 1]. Since $P_n(z')$ are known functions, our only task is to determine the expansion coefficients, $a_n$. By the orthogonality properties of the Legendre polynomials, one can deduce that the coefficients, $a_n$, are given by\n", - "\n", - "$$ a_n = \\frac{2n + 1}{2} \\int_{-1}^1 dz' P_n(z') \\phi(z').$$\n", - "\n", - "Thus, the problem reduces to finding the integral of the flux times each Legendre polynomial -- a problem which can be solved by using a Monte Carlo tally. By using a Legendre polynomial filter, we obtain stochastic estimates of these integrals for each polynomial order." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import openmc\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To begin, let us first create a simple model. The model will be a slab of fuel material with reflective boundaries conditions in the x- and y-directions and vacuum boundaries in the z-direction. However, to make the distribution slightly more interesting, we'll put some B4C in the middle of the slab." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# Define fuel and B4C materials\n", - "fuel = openmc.Material()\n", - "fuel.add_element('U', 1.0, enrichment=4.5)\n", - "fuel.add_nuclide('O16', 2.0)\n", - "fuel.set_density('g/cm3', 10.0)\n", - "\n", - "b4c = openmc.Material()\n", - "b4c.add_element('B', 4.0)\n", - "b4c.add_element('C', 1.0)\n", - "b4c.set_density('g/cm3', 2.5)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Define surfaces used to construct regions\n", - "zmin, zmax = -10., 10.\n", - "box = openmc.model.rectangular_prism(10., 10., boundary_type='reflective')\n", - "bottom = openmc.ZPlane(z0=zmin, boundary_type='vacuum')\n", - "boron_lower = openmc.ZPlane(z0=-0.5)\n", - "boron_upper = openmc.ZPlane(z0=0.5)\n", - "top = openmc.ZPlane(z0=zmax, boundary_type='vacuum')\n", - "\n", - "# Create three cells and add them to geometry\n", - "fuel1 = openmc.Cell(fill=fuel, region=box & +bottom & -boron_lower)\n", - "absorber = openmc.Cell(fill=b4c, region=box & +boron_lower & -boron_upper)\n", - "fuel2 = openmc.Cell(fill=fuel, region=box & +boron_upper & -top)\n", - "geom = openmc.Geometry([fuel1, absorber, fuel2])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the starting source, we'll use a uniform distribution over the entire box geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "spatial_dist = openmc.stats.Box(*geom.bounding_box)\n", - "settings.source = openmc.Source(space=spatial_dist)\n", - "settings.batches = 210\n", - "settings.inactive = 10\n", - "settings.particles = 1000" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Defining the tally is relatively straightforward. One simply needs to list 'flux' as a score and then add an expansion filter. For this case, we will want to use the `SpatialLegendreFilter` class which multiplies tally scores by Legendre polynomials evaluated on normalized spatial positions along an axis." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a flux tally\n", - "flux_tally = openmc.Tally()\n", - "flux_tally.scores = ['flux']\n", - "\n", - "# Create a Legendre polynomial expansion filter and add to tally\n", - "order = 8\n", - "expand_filter = openmc.SpatialLegendreFilter(order, 'z', zmin, zmax)\n", - "flux_tally.filters.append(expand_filter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The last thing we need to do is create a `Tallies` collection and export the entire model, which we'll do using the `Model` convenience class." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "tallies = openmc.Tallies([flux_tally])\n", - "model = openmc.model.Model(geometry=geom, settings=settings, tallies=tallies)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Running a simulation is now as simple as calling the `run()` method of `Model`." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.3016877031715249+/-0.0006126949350699303" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model.run(output=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the run is finished, we need to load the results from the statepoint file." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "with openmc.StatePoint('statepoint.210.h5') as sp:\n", - " df = sp.tallies[flux_tally.id].get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We've used the `get_pandas_dataframe()` method that returns tally data as a Pandas dataframe. Let's see what the raw data looks like." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
spatiallegendrenuclidescoremeanstd. dev.
0P0totalflux36.4348280.076755
1P1totalflux0.0217970.043545
2P2totalflux-4.3808920.025739
3P3totalflux0.0014480.020740
4P4totalflux-0.2954390.014215
5P5totalflux0.0035140.012017
6P6totalflux0.1052130.010103
7P7totalflux0.0025950.009265
8P8totalflux-0.0961970.007513
\n", - "
" - ], - "text/plain": [ - " spatiallegendre nuclide score mean std. dev.\n", - "0 P0 total flux 3.64e+01 7.68e-02\n", - "1 P1 total flux 2.18e-02 4.35e-02\n", - "2 P2 total flux -4.38e+00 2.57e-02\n", - "3 P3 total flux 1.45e-03 2.07e-02\n", - "4 P4 total flux -2.95e-01 1.42e-02\n", - "5 P5 total flux 3.51e-03 1.20e-02\n", - "6 P6 total flux 1.05e-01 1.01e-02\n", - "7 P7 total flux 2.60e-03 9.27e-03\n", - "8 P8 total flux -9.62e-02 7.51e-03" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since the expansion coefficients are given as\n", - "\n", - "$$ a_n = \\frac{2n + 1}{2} \\int_{-1}^1 dz' P_n(z') \\phi(z')$$\n", - "\n", - "we just need to multiply the Legendre moments by $(2n + 1)/2$." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "n = np.arange(order + 1)\n", - "a_n = (2*n + 1)/2 * df['mean']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To plot the flux distribution, we can use the `numpy.polynomial.Legendre` class which represents a truncated Legendre polynomial series. Since we really want to plot $\\phi(z)$ and not $\\phi(z')$ we first need to perform a change of variables. Since\n", - "\n", - "$$ \\lvert \\phi(z) dz \\rvert = \\lvert \\phi(z') dz' \\rvert $$\n", - "\n", - "and, for this case, $z = 10z'$, it follows that\n", - "\n", - "$$ \\phi(z) = \\frac{\\phi(z')}{10} = \\sum_{n=0}^N \\frac{a_n}{10} P_n(z'). $$" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "phi = np.polynomial.Legendre(a_n/10, domain=(zmin, zmax))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's plot it and see how our flux looks!" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "z = np.linspace(zmin, zmax, 1000)\n", - "plt.plot(z, phi(z))\n", - "plt.xlabel('Z position [cm]')\n", - "plt.ylabel('Flux [n/src]')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you might expect, we get a rough cosine shape but with a flux depression in the middle due to the boron slab that we introduced. To get a more accurate distribution, we'd likely need to use a higher order expansion.\n", - "\n", - "One more thing we can do is confirm that integrating the distribution gives us the same value as the first moment (since $P_0(z') = 1$). This can easily be done by numerically integrating using the trapezoidal rule:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "36.434786672754925" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.trapz(phi(z), z)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition to being able to tally Legendre moments, there are also functional expansion filters available for spherical harmonics (`SphericalHarmonicsFilter`) and Zernike polynomials over a unit disk (`ZernikeFilter`). A separate `LegendreFilter` class can also be used for determining Legendre scattering moments (i.e., an expansion of the scattering cosine, $\\mu$)." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/hexagonal-lattice.ipynb b/examples/jupyter/hexagonal-lattice.ipynb deleted file mode 100644 index e0a48e236..000000000 --- a/examples/jupyter/hexagonal-lattice.ipynb +++ /dev/null @@ -1,372 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this example, we will create a hexagonal lattice and show how the orientation can be changed via the cell rotation property. Let's first just set up some materials and universes that we will use to fill the lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import openmc" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "fuel = openmc.Material(name='fuel')\n", - "fuel.add_nuclide('U235', 1.0)\n", - "fuel.set_density('g/cm3', 10.0)\n", - "\n", - "fuel2 = openmc.Material(name='fuel2')\n", - "fuel2.add_nuclide('U238', 1.0)\n", - "fuel2.set_density('g/cm3', 10.0)\n", - "\n", - "water = openmc.Material(name='water')\n", - "water.add_nuclide('H1', 2.0)\n", - "water.add_nuclide('O16', 1.0)\n", - "water.set_density('g/cm3', 1.0)\n", - "\n", - "mats = openmc.Materials((fuel, fuel2, water))\n", - "mats.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we will set up two universes that represent pin-cells: one with a small pin and one with a big pin. Since we will be using these universes in a lattice, it's always a good idea to have an \"outer\" universe as well that is applied outside the defined lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "r_pin = openmc.ZCylinder(r=0.25)\n", - "fuel_cell = openmc.Cell(fill=fuel, region=-r_pin)\n", - "water_cell = openmc.Cell(fill=water, region=+r_pin)\n", - "pin_universe = openmc.Universe(cells=(fuel_cell, water_cell))\n", - "\n", - "r_big_pin = openmc.ZCylinder(r=0.5)\n", - "fuel2_cell = openmc.Cell(fill=fuel2, region=-r_big_pin)\n", - "water2_cell = openmc.Cell(fill=water, region=+r_big_pin)\n", - "big_pin_universe = openmc.Universe(cells=(fuel2_cell, water2_cell))\n", - "\n", - "all_water_cell = openmc.Cell(fill=water)\n", - "outer_universe = openmc.Universe(cells=(all_water_cell,))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's create a hexagonal lattice using the `HexLattice` class:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "lat = openmc.HexLattice()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We need to set the `center` of the lattice, the `pitch`, an `outer` universe (which is applied to all lattice elements outside of those that are defined), and a list of `universes`. Let's start with the easy ones first. Note that for a 2D lattice, we only need to specify a single number for the pitch." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "lat.center = (0., 0.)\n", - "lat.pitch = (1.25,)\n", - "lat.outer = outer_universe" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to set the `universes` property on our lattice. It needs to be set to a list of lists of Universes, where each list of Universes corresponds to a ring of the lattice. The rings are ordered from outermost to innermost, and within each ring the indexing starts at the \"top\". To help visualize the proper indices, we can use the `show_indices()` helper method." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (0, 0)\n", - " (0,11) (0, 1)\n", - "(0,10) (1, 0) (0, 2)\n", - " (1, 5) (1, 1)\n", - "(0, 9) (2, 0) (0, 3)\n", - " (1, 4) (1, 2)\n", - "(0, 8) (1, 3) (0, 4)\n", - " (0, 7) (0, 5)\n", - " (0, 6)\n" - ] - } - ], - "source": [ - "print(lat.show_indices(num_rings=3))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's set up a lattice where the first element in each ring is the big pin universe and all other elements are regular pin universes. From the diagram above, we see that the outer ring has 12 elements, the middle ring has 6, and the innermost degenerate ring has a single element." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "HexLattice\n", - "\tID =\t4\n", - "\tName =\t\n", - "\tOrientation =\ty\n", - "\t# Rings =\t3\n", - "\t# Axial =\tNone\n", - "\tCenter =\t(0.0, 0.0)\n", - "\tPitch =\t(1.25,)\n", - "\tOuter =\t3\n", - "\tUniverses \n", - " 2\n", - " 1 1\n", - "1 2 1\n", - " 1 1\n", - "1 2 1\n", - " 1 1\n", - "1 1 1\n", - " 1 1\n", - " 1\n" - ] - } - ], - "source": [ - "outer_ring = [big_pin_universe] + [pin_universe]*11\n", - "middle_ring = [big_pin_universe] + [pin_universe]*5\n", - "inner_ring = [big_pin_universe]\n", - "lat.universes = [outer_ring, middle_ring, inner_ring]\n", - "print(lat)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's put our lattice inside a circular cell that will serve as the top-level cell for our geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "outer_surface = openmc.ZCylinder(r=4.0, boundary_type='vacuum')\n", - "main_cell = openmc.Cell(fill=lat, region=-outer_surface)\n", - "geom = openmc.Geometry([main_cell])\n", - "geom.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's create a plot to see what our geometry looks like." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = openmc.Plot.from_geometry(geom)\n", - "p.color_by = 'material'\n", - "p.colors = colors = {\n", - " water: 'blue',\n", - " fuel: 'olive',\n", - " fuel2: 'yellow'\n", - "}\n", - "p.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, if we wanted to simulate the model, we would need to create an instance of `openmc.Settings`, export it to XML, and run." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Lattice orientation\n", - "\n", - "Now let's say we want our hexagonal lattice orientated such that two sides of the lattice are parallel to the x-axis. This can be achieved by two means: either we can rotate the cell that contains the lattice, or we can can change the `HexLattice.orientation` attribute. By default, the `orientation` is set to \"y\", indicating that two sides of the lattice are parallel to the y-axis, but we can also change it to \"x\" to make them parallel to the x-axis." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Change the orientation of the lattice and re-export the geometry\n", - "lat.orientation = 'x'\n", - "geom.export_to_xml()\n", - "\n", - "# Run OpenMC in plotting mode\n", - "p.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When we change the orientation to 'x', you can see that the first universe in each ring starts to the right along the x-axis. As before, the universes are defined in a clockwise fashion around each ring. To see the proper indices for a hexagonal lattice in this orientation, we can again call `show_indices` but pass an extra orientation argument:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (0, 8) (0, 9) (0,10)\n", - "\n", - " (0, 7) (1, 4) (1, 5) (0,11)\n", - "\n", - "(0, 6) (1, 3) (2, 0) (1, 0) (0, 0)\n", - "\n", - " (0, 5) (1, 2) (1, 1) (0, 1)\n", - "\n", - " (0, 4) (0, 3) (0, 2)\n" - ] - } - ], - "source": [ - "print(lat.show_indices(3, orientation='x'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Hexagonal prisms\n", - "\n", - "OpenMC also contains a convenience function that can create a hexagonal prism representing the interior region of six surfaces defining a hexagon. This can be useful as a bounding surface of a hexagonal lattice. For example, if we wanted the outer boundary of our geometry to be hexagonal, we could change the `region` of the main cell:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "main_cell.region = openmc.model.hexagonal_prism(\n", - " edge_length=3*lat.pitch[0],\n", - " orientation='x',\n", - " boundary_type='vacuum'\n", - ")\n", - "geom.export_to_xml()\n", - "\n", - "# Run OpenMC in plotting mode\n", - "p.color_by = 'cell'\n", - "p.to_ipython_image()" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/images/cylinder_mesh.png b/examples/jupyter/images/cylinder_mesh.png deleted file mode 100644 index cd9638060..000000000 Binary files a/examples/jupyter/images/cylinder_mesh.png and /dev/null differ diff --git a/examples/jupyter/images/mdgxs.png b/examples/jupyter/images/mdgxs.png deleted file mode 100644 index b93d0f042..000000000 Binary files a/examples/jupyter/images/mdgxs.png and /dev/null differ diff --git a/examples/jupyter/images/mgxs.png b/examples/jupyter/images/mgxs.png deleted file mode 100644 index 3946a5b3c..000000000 Binary files a/examples/jupyter/images/mgxs.png and /dev/null differ diff --git a/examples/jupyter/images/teapot.jpg b/examples/jupyter/images/teapot.jpg deleted file mode 100644 index 382e8838f..000000000 Binary files a/examples/jupyter/images/teapot.jpg and /dev/null differ diff --git a/examples/jupyter/mdgxs-part-i.ipynb b/examples/jupyter/mdgxs-part-i.ipynb deleted file mode 100644 index 239b0f2df..000000000 --- a/examples/jupyter/mdgxs-part-i.ipynb +++ /dev/null @@ -1,1494 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This IPython Notebook introduces the use of the `openmc.mgxs` module to calculate multi-energy-group and multi-delayed-group cross sections for an infinite homogeneous medium. In particular, this Notebook introduces the the following features:\n", - "\n", - "* Creation of multi-delayed-group cross sections for an **infinite homogeneous medium**\n", - "* Calculation of delayed neutron precursor concentrations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Introduction to Multi-Delayed-Group Cross Sections (MDGXS)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Many Monte Carlo particle transport codes, including OpenMC, use continuous-energy nuclear cross section data. However, most deterministic neutron transport codes use *multi-group cross sections* defined over discretized energy bins or *energy groups*. Furthermore, kinetics calculations typically separate out parameters that involve delayed neutrons into prompt and delayed components and further subdivide delayed components by delayed groups. An example is the energy spectrum for prompt and delayed neutrons for U-235 and Pu-239 computed for a light water reactor spectrum." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": { - "image/png": { - "width": 350 - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import Image\n", - "Image(filename='images/mdgxs.png', width=350)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A variety of tools employing different methodologies have been developed over the years to compute multi-group cross sections for certain applications, including NJOY (LANL), MC$^2$-3 (ANL), and Serpent (VTT). The `openmc.mgxs` Python module is designed to leverage OpenMC's tally system to calculate multi-group cross sections with arbitrary energy discretizations and different delayed group models (e.g. 6, 7, or 8 delayed group models) for fine-mesh heterogeneous deterministic neutron transport applications.\n", - "\n", - "Before proceeding to illustrate how one may use the `openmc.mgxs` module, it is worthwhile to define the general equations used to calculate multi-energy-group and multi-delayed-group cross sections. This is only intended as a brief overview of the methodology used by `openmc.mgxs` - we refer the interested reader to the large body of literature on the subject for a more comprehensive understanding of this complex topic." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Introductory Notation\n", - "The continuous real-valued microscopic cross section may be denoted $\\sigma_{n,x}(\\mathbf{r}, E)$ for position vector $\\mathbf{r}$, energy $E$, nuclide $n$ and interaction type $x$. Similarly, the scalar neutron flux may be denoted by $\\Phi(\\mathbf{r},E)$ for position $\\mathbf{r}$ and energy $E$. **Note**: Although nuclear cross sections are dependent on the temperature $T$ of the interacting medium, the temperature variable is neglected here for brevity." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Spatial and Energy Discretization\n", - "The energy domain for critical systems such as thermal reactors spans more than 10 orders of magnitude of neutron energies from 10$^{-5}$ - 10$^7$ eV. The multi-group approximation discretization divides this energy range into one or more energy groups. In particular, for $G$ total groups, we denote an energy group index $g$ such that $g \\in \\{1, 2, ..., G\\}$. The energy group indices are defined such that the smaller group the higher the energy, and vice versa. The integration over neutron energies across a discrete energy group is commonly referred to as **energy condensation**.\n", - "\n", - "The delayed neutrons created from fissions are created from > 30 delayed neutron precursors. Modeling each of the delayed neutron precursors is possible, but this approach has not recieved much attention due to large uncertainties in certain precursors. Therefore, the delayed neutrons are often combined into \"delayed groups\" that have a set time constant, $\\lambda_d$. Some cross section libraries use the same group time constants for all nuclides (e.g. JEFF 3.1) while other libraries use different time constants for all nuclides (e.g. ENDF/B-VII.1). Multi-delayed-group cross sections can either be created with the entire delayed group set, a subset of delayed groups, or integrated over all delayed groups.\n", - "\n", - "Multi-group cross sections are computed for discretized spatial zones in the geometry of interest. The spatial zones may be defined on a structured and regular fuel assembly or pin cell mesh, an arbitrary unstructured mesh or the constructive solid geometry used by OpenMC. For a geometry with $K$ distinct spatial zones, we designate each spatial zone an index $k$ such that $k \\in \\{1, 2, ..., K\\}$. The volume of each spatial zone is denoted by $V_{k}$. The integration over discrete spatial zones is commonly referred to as **spatial homogenization**." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### General Scalar-Flux Weighted MDGXS\n", - "The multi-group cross sections computed by `openmc.mgxs` are defined as a *scalar flux-weighted average* of the microscopic cross sections across each discrete energy group. This formulation is employed in order to preserve the reaction rates within each energy group and spatial zone. In particular, spatial homogenization and energy condensation are used to compute the general multi-group cross section. For instance, the delayed-nu-fission multi-energy-group and multi-delayed-group cross section, $\\nu_d \\sigma_{f,x,k,g}$, can be computed as follows:\n", - "\n", - "$$\\nu_d \\sigma_{n,x,k,g} = \\frac{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\nu_d \\sigma_{f,x}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n", - "\n", - "This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for only the delayed-nu-fission and delayed neutron fraction reaction type at the moment. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](https://docs.openmc.org/en/stable/usersguide/tallies.html#filters) on the energy range and spatial zone (material, cell, universe, or mesh) define the bounds of integration for both numerator and denominator." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Multi-Group Prompt and Delayed Fission Spectrum\n", - "The energy spectrum of neutrons emitted from fission is denoted by $\\chi_{n}(\\mathbf{r},E' \\rightarrow E'')$ for incoming and outgoing energies $E'$ and $E''$, respectively. Unlike the multi-group cross sections $\\sigma_{n,x,k,g}$ considered up to this point, the fission spectrum is a probability distribution and must sum to unity. The outgoing energy is typically much less dependent on the incoming energy for fission than for scattering interactions. As a result, it is common practice to integrate over the incoming neutron energy when computing the multi-group fission spectrum. The fission spectrum may be simplified as $\\chi_{n}(\\mathbf{r},E)$ with outgoing energy $E$.\n", - "\n", - "Computing the cumulative energy spectrum of emitted neutrons, $\\chi_{n}(\\mathbf{r},E)$, has been presented in the `mgxs-part-i.ipynb` notebook. Here, we will present the energy spectrum of prompt and delayed emission neutrons, $\\chi_{n,p}(\\mathbf{r},E)$ and $\\chi_{n,d}(\\mathbf{r},E)$, respectively. Unlike the multi-group cross sections defined up to this point, the multi-group fission spectrum is weighted by the fission production rate rather than the scalar flux. This formulation is intended to preserve the total fission production rate in the multi-group deterministic calculation. In order to mathematically define the multi-group fission spectrum, we denote the microscopic fission cross section as $\\sigma_{n,f}(\\mathbf{r},E)$ and the average number of neutrons emitted from fission interactions with nuclide $n$ as $\\nu_{n,p}(\\mathbf{r},E)$ and $\\nu_{n,d}(\\mathbf{r},E)$ for prompt and delayed neutrons, respectively. The multi-group fission spectrum $\\chi_{n,k,g,d}$ is then the probability of fission neutrons emitted into energy group $g$ and delayed group $d$. There are not prompt groups, so inserting $p$ in place of $d$ just denotes all prompt neutrons. \n", - "\n", - "Similar to before, spatial homogenization and energy condensation are used to find the multi-energy-group and multi-delayed-group fission spectrum $\\chi_{n,k,g,d}$ as follows:\n", - "\n", - "$$\\chi_{n,k,g',d} = \\frac{\\int_{E_{g'}}^{E_{g'-1}}\\mathrm{d}E''\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\chi_{n,d}(\\mathbf{r},E'\\rightarrow E'')\\nu_{n,d}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\nu_{n,d}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}$$\n", - "\n", - "The fission production-weighted multi-energy-group and multi-delayed-group fission spectrum for delayed neutrons is computed using OpenMC tallies with energy in, energy out, and delayed group filters. Alternatively, the delayed group filter can be omitted to compute the fission spectrum integrated over all delayed groups.\n", - "\n", - "This concludes our brief overview on the methodology to compute multi-energy-group and multi-delayed-group cross sections. The following sections detail more concretely how users may employ the `openmc.mgxs` module to power simulation workflows requiring multi-group cross sections for downstream deterministic calculations." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import openmc\n", - "import openmc.mgxs as mgxs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. Let's create a material for the homogeneous medium." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "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.03)\n", - "inf_medium.add_nuclide('O16', 0.015)\n", - "inf_medium.add_nuclide('U235', 0.0001)\n", - "inf_medium.add_nuclide('U238', 0.007)\n", - "inf_medium.add_nuclide('Pu239', 0.00003)\n", - "inf_medium.add_nuclide('Zr90', 0.002)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our material, we can now create a `Materials` object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials collection and export to XML\n", - "materials_file = openmc.Materials([inf_medium])\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a simple square cell with reflective boundary conditions to simulate an infinite homogeneous medium. The first step is to create the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate boundary Planes\n", - "min_x = openmc.XPlane(boundary_type='reflective', x0=-0.63)\n", - "max_x = openmc.XPlane(boundary_type='reflective', x0=0.63)\n", - "min_y = openmc.YPlane(boundary_type='reflective', y0=-0.63)\n", - "max_y = openmc.YPlane(boundary_type='reflective', y0=0.63)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now create a cell that is defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Cell\n", - "cell = openmc.Cell(cell_id=1, name='cell')\n", - "\n", - "# Register bounding Surfaces with the Cell\n", - "cell.region = +min_x & -max_x & +min_y & -max_y\n", - "\n", - "# Fill the Cell with the Material\n", - "cell.fill = inf_medium" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "openmc_geometry = openmc.Geometry([cell])\n", - "\n", - "# Export to \"geometry.xml\"\n", - "openmc_geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 50\n", - "inactive = 10\n", - "particles = 5000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': True}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we are ready to generate multi-group cross sections! First, let's define a 100-energy-group structure and 1-energy-group structure using the built-in `EnergyGroups` class. We will also create a 6-delayed-group list." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 100-group EnergyGroups object\n", - "energy_groups = mgxs.EnergyGroups()\n", - "energy_groups.group_edges = np.logspace(-3, 7.3, 101)\n", - "\n", - "# Instantiate a 1-group EnergyGroups object\n", - "one_group = mgxs.EnergyGroups()\n", - "one_group.group_edges = np.array([energy_groups.group_edges[0], energy_groups.group_edges[-1]])\n", - "\n", - "delayed_groups = list(range(1,7))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now use the `EnergyGroups` object and delayed group list, along with our previously created materials and geometry, to instantiate some `MGXS` objects from the `openmc.mgxs` module. In particular, the following are subclasses of the generic and abstract `MGXS` class:\n", - "\n", - "* `TotalXS`\n", - "* `TransportXS`\n", - "* `AbsorptionXS`\n", - "* `CaptureXS`\n", - "* `FissionXS`\n", - "* `NuFissionMatrixXS`\n", - "* `KappaFissionXS`\n", - "* `ScatterXS`\n", - "* `ScatterMatrixXS`\n", - "* `Chi`\n", - "* `InverseVelocity`\n", - "\n", - "A separate abstract `MDGXS` class is used for cross-sections and parameters that involve delayed neutrons. The subclasses of `MDGXS` include:\n", - "\n", - "* `DelayedNuFissionXS`\n", - "* `ChiDelayed`\n", - "* `Beta`\n", - "* `DecayRate`\n", - "\n", - "These classes provide us with an interface to generate the tally inputs as well as perform post-processing of OpenMC's tally data to compute the respective multi-group cross sections. \n", - "\n", - "In this case, let's create the multi-group chi-prompt, chi-delayed, and prompt-nu-fission cross sections with our 100-energy-group structure and multi-group delayed-nu-fission and beta cross sections with our 100-energy-group and 6-delayed-group structures. \n", - "\n", - "The prompt chi and nu-fission data can actually be gathered using the `Chi` and `FissionXS` classes, respectively, by passing in a value of `True` for the optional `prompt` parameter upon initialization." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a few different sections\n", - "chi_prompt = mgxs.Chi(domain=cell, groups=energy_groups, by_nuclide=True, prompt=True)\n", - "prompt_nu_fission = mgxs.FissionXS(domain=cell, groups=energy_groups, by_nuclide=True, nu=True, prompt=True)\n", - "chi_delayed = mgxs.ChiDelayed(domain=cell, energy_groups=energy_groups, by_nuclide=True)\n", - "delayed_nu_fission = mgxs.DelayedNuFissionXS(domain=cell, energy_groups=energy_groups, delayed_groups=delayed_groups, by_nuclide=True)\n", - "beta = mgxs.Beta(domain=cell, energy_groups=energy_groups, delayed_groups=delayed_groups, by_nuclide=True)\n", - "decay_rate = mgxs.DecayRate(domain=cell, energy_groups=one_group, delayed_groups=delayed_groups, by_nuclide=True)\n", - "\n", - "chi_prompt.nuclides = ['U235', 'Pu239']\n", - "prompt_nu_fission.nuclides = ['U235', 'Pu239']\n", - "chi_delayed.nuclides = ['U235', 'Pu239']\n", - "delayed_nu_fission.nuclides = ['U235', 'Pu239']\n", - "beta.nuclides = ['U235', 'Pu239']\n", - "decay_rate.nuclides = ['U235', 'Pu239']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each multi-group cross section object stores its tallies in a Python dictionary called `tallies`. We can inspect the tallies in the dictionary for our `Decay Rate` object as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "OrderedDict([('delayed-nu-fission', Tally\n", - " \tID =\t1\n", - " \tName =\t\n", - " \tFilters =\tCellFilter, DelayedGroupFilter, EnergyFilter\n", - " \tNuclides =\tU235 Pu239 \n", - " \tScores =\t['delayed-nu-fission']\n", - " \tEstimator =\ttracklength), ('decay-rate', Tally\n", - " \tID =\t2\n", - " \tName =\t\n", - " \tFilters =\tCellFilter, DelayedGroupFilter, EnergyFilter\n", - " \tNuclides =\tU235 Pu239 \n", - " \tScores =\t['decay-rate']\n", - " \tEstimator =\ttracklength)])" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "decay_rate.tallies" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `Beta` object includes tracklength tallies for the 'nu-fission' and 'delayed-nu-fission' scores in the 100-energy-group and 6-delayed-group structure in cell 1. Now that each `MGXS` and `MDGXS` object contains the tallies that it needs, we must add these tallies to a `Tallies` object to generate the \"tallies.xml\" input file for OpenMC." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=4.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=6.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=5.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=8.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=14.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Instantiate an empty Tallies object\n", - "tallies_file = openmc.Tallies()\n", - "\n", - "# Add chi-prompt tallies to the tallies file\n", - "tallies_file += chi_prompt.tallies.values()\n", - "\n", - "# Add prompt-nu-fission tallies to the tallies file\n", - "tallies_file += prompt_nu_fission.tallies.values()\n", - "\n", - "# Add chi-delayed tallies to the tallies file\n", - "tallies_file += chi_delayed.tallies.values()\n", - "\n", - "# Add delayed-nu-fission tallies to the tallies file\n", - "tallies_file += delayed_nu_fission.tallies.values()\n", - "\n", - "# Add beta tallies to the tallies file\n", - "tallies_file += beta.tallies.values()\n", - "\n", - "# Add decay rate tallies to the tallies file\n", - "tallies_file += decay_rate.tallies.values()\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 06:56:34\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading Pu239 from /opt/data/hdf5/nndc_hdf5_v15/Pu239.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for H1\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.21670\n", - " 2/1 1.24155\n", - " 3/1 1.21924\n", - " 4/1 1.22486\n", - " 5/1 1.21719\n", - " 6/1 1.24330\n", - " 7/1 1.22322\n", - " 8/1 1.24133\n", - " 9/1 1.21840\n", - " 10/1 1.25141\n", - " 11/1 1.21217\n", - " 12/1 1.25625 1.23421 +/- 0.02204\n", - " 13/1 1.22056 1.22966 +/- 0.01351\n", - " 14/1 1.21757 1.22664 +/- 0.01002\n", - " 15/1 1.24571 1.23045 +/- 0.00865\n", - " 16/1 1.26489 1.23619 +/- 0.00910\n", - " 17/1 1.22323 1.23434 +/- 0.00791\n", - " 18/1 1.26108 1.23768 +/- 0.00762\n", - " 19/1 1.23145 1.23699 +/- 0.00676\n", - " 20/1 1.23548 1.23684 +/- 0.00605\n", - " 21/1 1.20446 1.23390 +/- 0.00621\n", - " 22/1 1.20533 1.23152 +/- 0.00615\n", - " 23/1 1.22520 1.23103 +/- 0.00568\n", - " 24/1 1.18367 1.22765 +/- 0.00625\n", - " 25/1 1.23614 1.22821 +/- 0.00585\n", - " 26/1 1.23746 1.22879 +/- 0.00550\n", - " 27/1 1.23626 1.22923 +/- 0.00518\n", - " 28/1 1.21334 1.22835 +/- 0.00497\n", - " 29/1 1.25169 1.22958 +/- 0.00486\n", - " 30/1 1.25579 1.23089 +/- 0.00479\n", - " 31/1 1.23828 1.23124 +/- 0.00457\n", - " 32/1 1.26911 1.23296 +/- 0.00468\n", - " 33/1 1.20090 1.23157 +/- 0.00469\n", - " 34/1 1.28606 1.23384 +/- 0.00503\n", - " 35/1 1.23129 1.23374 +/- 0.00483\n", - " 36/1 1.22535 1.23341 +/- 0.00465\n", - " 37/1 1.20367 1.23231 +/- 0.00461\n", - " 38/1 1.22886 1.23219 +/- 0.00444\n", - " 39/1 1.24056 1.23248 +/- 0.00429\n", - " 40/1 1.25038 1.23307 +/- 0.00419\n", - " 41/1 1.21504 1.23249 +/- 0.00410\n", - " 42/1 1.20762 1.23171 +/- 0.00404\n", - " 43/1 1.20597 1.23093 +/- 0.00399\n", - " 44/1 1.24424 1.23133 +/- 0.00389\n", - " 45/1 1.24767 1.23179 +/- 0.00381\n", - " 46/1 1.22998 1.23174 +/- 0.00370\n", - " 47/1 1.26195 1.23256 +/- 0.00369\n", - " 48/1 1.23146 1.23253 +/- 0.00359\n", - " 49/1 1.22059 1.23222 +/- 0.00351\n", - " 50/1 1.24724 1.23260 +/- 0.00345\n", - " Creating state point statepoint.50.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 4.7388e-01 seconds\n", - " Reading cross sections = 4.4709e-01 seconds\n", - " Total time in simulation = 3.9290e+01 seconds\n", - " Time in transport only = 3.9005e+01 seconds\n", - " Time in inactive batches = 1.4079e+00 seconds\n", - " Time in active batches = 3.7882e+01 seconds\n", - " Time synchronizing fission bank = 1.8814e-02 seconds\n", - " Sampling source sites = 1.6376e-02 seconds\n", - " SEND/RECV source sites = 2.3626e-03 seconds\n", - " Time accumulating tallies = 8.3299e-04 seconds\n", - " Total time for finalization = 1.1533e-02 seconds\n", - " Total time elapsed = 3.9783e+01 seconds\n", - " Calculation Rate (inactive) = 35514.2 particles/second\n", - " Calculation Rate (active) = 5279.54 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.23256 +/- 0.00308\n", - " k-effective (Track-length) = 1.23260 +/- 0.00345\n", - " k-effective (Absorption) = 1.23111 +/- 0.00186\n", - " Combined k-effective = 1.23135 +/- 0.00184\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the last statepoint file\n", - "sp = openmc.StatePoint('statepoint.50.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. By default, a `Summary` object is automatically linked when a `StatePoint` is loaded. This is necessary for the `openmc.mgxs` module to properly process the tally data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the `StatePoint` into each object as follows and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the tallies from the statepoint into each MGXS object\n", - "chi_prompt.load_from_statepoint(sp)\n", - "prompt_nu_fission.load_from_statepoint(sp)\n", - "chi_delayed.load_from_statepoint(sp)\n", - "delayed_nu_fission.load_from_statepoint(sp)\n", - "beta.load_from_statepoint(sp)\n", - "decay_rate.load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Voila! Our multi-group cross sections are now ready to rock 'n roll!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Extracting and Storing MGXS Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's first inspect our delayed-nu-fission section by printing it to the screen after condensing the cross section down to one group." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[[5.14223507e-06, 1.16426087e-06]],\n", - "\n", - " [[2.65426350e-05, 7.58220468e-06]],\n", - "\n", - " [[2.53399053e-05, 5.73796202e-06]],\n", - "\n", - " [[5.68141581e-05, 1.04757933e-05]],\n", - "\n", - " [[2.32930026e-05, 5.45658817e-06]],\n", - "\n", - " [[9.75735783e-06, 1.65150949e-06]]])" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "delayed_nu_fission.get_condensed_xs(one_group).get_xs()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since the `openmc.mgxs` module uses [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](http://pandas.pydata.org/) `DataFrame` of the multi-group cross section data." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
celldelayedgroupgroup innuclidemeanstd. dev.
198111U2359.345817e-086.616216e-08
199111Pu2391.574816e-081.114955e-08
398121U2354.824023e-073.415087e-07
399121Pu2391.025593e-077.261101e-08
598131U2354.605432e-073.260339e-07
599131Pu2397.761348e-085.494962e-08
798141U2351.032576e-067.309948e-07
799141Pu2391.416989e-071.003215e-07
998151U2354.233415e-072.996976e-07
999151Pu2397.380753e-085.225504e-08
\n", - "
" - ], - "text/plain": [ - " cell delayedgroup group in nuclide mean std. dev.\n", - "198 1 1 1 U235 9.345817e-08 6.616216e-08\n", - "199 1 1 1 Pu239 1.574816e-08 1.114955e-08\n", - "398 1 2 1 U235 4.824023e-07 3.415087e-07\n", - "399 1 2 1 Pu239 1.025593e-07 7.261101e-08\n", - "598 1 3 1 U235 4.605432e-07 3.260339e-07\n", - "599 1 3 1 Pu239 7.761348e-08 5.494962e-08\n", - "798 1 4 1 U235 1.032576e-06 7.309948e-07\n", - "799 1 4 1 Pu239 1.416989e-07 1.003215e-07\n", - "998 1 5 1 U235 4.233415e-07 2.996976e-07\n", - "999 1 5 1 Pu239 7.380753e-08 5.225504e-08" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = delayed_nu_fission.get_pandas_dataframe()\n", - "df.head(10)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
celldelayedgroupgroup innuclidemeanstd. dev.
0111U2350.0133360.000061
1111Pu2390.0132710.000053
2121U2350.0327390.000149
3121Pu2390.0308810.000123
4131U2350.1207800.000549
5131Pu2390.1133700.000451
6141U2350.3027800.001378
7141Pu2390.2925000.001163
8151U2350.8494900.003865
9151Pu2390.8574900.003411
10161U2352.8530000.012980
11161Pu2392.7297000.010858
\n", - "
" - ], - "text/plain": [ - " cell delayedgroup group in nuclide mean std. dev.\n", - "0 1 1 1 U235 0.013336 0.000061\n", - "1 1 1 1 Pu239 0.013271 0.000053\n", - "2 1 2 1 U235 0.032739 0.000149\n", - "3 1 2 1 Pu239 0.030881 0.000123\n", - "4 1 3 1 U235 0.120780 0.000549\n", - "5 1 3 1 Pu239 0.113370 0.000451\n", - "6 1 4 1 U235 0.302780 0.001378\n", - "7 1 4 1 Pu239 0.292500 0.001163\n", - "8 1 5 1 U235 0.849490 0.003865\n", - "9 1 5 1 Pu239 0.857490 0.003411\n", - "10 1 6 1 U235 2.853000 0.012980\n", - "11 1 6 1 Pu239 2.729700 0.010858" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = decay_rate.get_pandas_dataframe()\n", - "df.head(12)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each multi-group cross section object can be easily exported to a variety of file formats, including CSV, Excel, and LaTeX for storage or data processing." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "beta.export_xs_data(filename='beta', format='excel')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following code snippet shows how to export the chi-prompt and chi-delayed `MGXS` to the same HDF5 binary data store." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "chi_prompt.build_hdf5_store(filename='mdgxs', append=True)\n", - "chi_delayed.build_hdf5_store(filename='mdgxs', append=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Tally Arithmetic to Compute the Delayed Neutron Precursor Concentrations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta`, `DelayedNuFissionXS`, and `DecayRate` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n", - "\n", - "$$\\frac{\\partial}{\\partial t} C_{k,d} (t) = \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t)\\Phi(\\mathbf{r},E',t) - \\lambda_{d} C_{k,d} (t) $$\n", - "\n", - "$$C_{k,d} (t=0) = \\frac{1}{\\lambda_{d}} \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t=0) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t=0)\\Phi(\\mathbf{r},E',t=0) $$\n", - "\n", - "First, let's investigate the decay rates for U235 and Pu235. The fraction of the delayed neutron precursors remaining as a function of time after fission for each delayed group and fissioning isotope have been plotted below." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Get the decay rate data\n", - "dr_tally = decay_rate.xs_tally\n", - "dr_u235 = dr_tally.get_values(nuclides=['U235']).flatten()\n", - "dr_pu239 = dr_tally.get_values(nuclides=['Pu239']).flatten()\n", - "\n", - "# Compute the exponential decay of the precursors\n", - "time = np.logspace(-3,3)\n", - "dr_u235_points = np.exp(-np.outer(dr_u235, time))\n", - "dr_pu239_points = np.exp(-np.outer(dr_pu239, time))\n", - "\n", - "# Create a plot of the fraction of the precursors remaining as a f(time)\n", - "colors = ['b', 'g', 'r', 'c', 'm', 'k']\n", - "legend = []\n", - "fig = plt.figure(figsize=(8,6))\n", - "for g,c in enumerate(colors):\n", - " plt.semilogx(time, dr_u235_points [g,:], color=c, linestyle='--', linewidth=3)\n", - " plt.semilogx(time, dr_pu239_points[g,:], color=c, linestyle=':' , linewidth=3)\n", - " legend.append('U-235 $t_{1/2}$ = ' + '{0:1.2f} seconds'.format(np.log(2) / dr_u235[g]))\n", - " legend.append('Pu-239 $t_{1/2}$ = ' + '{0:1.2f} seconds'.format(np.log(2) / dr_pu239[g]))\n", - "\n", - "plt.title('Delayed Neutron Precursor Decay Rates')\n", - "plt.xlabel('Time (s)')\n", - "plt.ylabel('Fraction Remaining')\n", - "plt.legend(legend, loc=1, bbox_to_anchor=(1.55, 0.95))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's compute the initial concentration of the delayed neutron precursors:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
celldelayedgroupnuclidescoremeanstd. dev.
011U235(((delayed-nu-fission / nu-fission) * (delayed...8.779139e-084.658590e-10
111Pu239(((delayed-nu-fission / nu-fission) * (delayed...7.149814e-093.559010e-11
212U235(((delayed-nu-fission / nu-fission) * (delayed...9.527880e-075.055905e-09
312Pu239(((delayed-nu-fission / nu-fission) * (delayed...1.303159e-076.486820e-10
413U235(((delayed-nu-fission / nu-fission) * (delayed...2.353903e-071.249083e-09
513Pu239(((delayed-nu-fission / nu-fission) * (delayed...2.032895e-081.011928e-10
614U235(((delayed-nu-fission / nu-fission) * (delayed...4.720191e-072.504737e-09
714Pu239(((delayed-nu-fission / nu-fission) * (delayed...2.626309e-081.307315e-10
815U235(((delayed-nu-fission / nu-fission) * (delayed...2.827915e-081.500614e-10
915Pu239(((delayed-nu-fission / nu-fission) * (delayed...2.430587e-091.209889e-11
1016U235(((delayed-nu-fission / nu-fission) * (delayed...1.477530e-097.840413e-12
1116Pu239(((delayed-nu-fission / nu-fission) * (delayed...6.994312e-113.481605e-13
\n", - "
" - ], - "text/plain": [ - " cell delayedgroup nuclide \\\n", - "0 1 1 U235 \n", - "1 1 1 Pu239 \n", - "2 1 2 U235 \n", - "3 1 2 Pu239 \n", - "4 1 3 U235 \n", - "5 1 3 Pu239 \n", - "6 1 4 U235 \n", - "7 1 4 Pu239 \n", - "8 1 5 U235 \n", - "9 1 5 Pu239 \n", - "10 1 6 U235 \n", - "11 1 6 Pu239 \n", - "\n", - " score mean std. dev. \n", - "0 (((delayed-nu-fission / nu-fission) * (delayed... 8.78e-08 4.66e-10 \n", - "1 (((delayed-nu-fission / nu-fission) * (delayed... 7.15e-09 3.56e-11 \n", - "2 (((delayed-nu-fission / nu-fission) * (delayed... 9.53e-07 5.06e-09 \n", - "3 (((delayed-nu-fission / nu-fission) * (delayed... 1.30e-07 6.49e-10 \n", - "4 (((delayed-nu-fission / nu-fission) * (delayed... 2.35e-07 1.25e-09 \n", - "5 (((delayed-nu-fission / nu-fission) * (delayed... 2.03e-08 1.01e-10 \n", - "6 (((delayed-nu-fission / nu-fission) * (delayed... 4.72e-07 2.50e-09 \n", - "7 (((delayed-nu-fission / nu-fission) * (delayed... 2.63e-08 1.31e-10 \n", - "8 (((delayed-nu-fission / nu-fission) * (delayed... 2.83e-08 1.50e-10 \n", - "9 (((delayed-nu-fission / nu-fission) * (delayed... 2.43e-09 1.21e-11 \n", - "10 (((delayed-nu-fission / nu-fission) * (delayed... 1.48e-09 7.84e-12 \n", - "11 (((delayed-nu-fission / nu-fission) * (delayed... 6.99e-11 3.48e-13 " - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use tally arithmetic to compute the precursor concentrations\n", - "precursor_conc = beta.get_condensed_xs(one_group).xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True) * \\\n", - " delayed_nu_fission.get_condensed_xs(one_group).xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True) / \\\n", - " decay_rate.xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True)\n", - "\n", - "# Get the Pandas DataFrames for inspection\n", - "precursor_conc.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can plot the delayed neutron fractions for each nuclide." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Beta (U-235) : 0.006504 +/- 0.000007\n", - "Beta (Pu-239): 0.002245 +/- 0.000002\n" - ] - }, - { - "data": { - "text/plain": [ - "(0, 7)" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "energy_filter = [f for f in beta.xs_tally.filters if type(f) is openmc.EnergyFilter]\n", - "beta_integrated = beta.get_condensed_xs(one_group).xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True)\n", - "beta_u235 = beta_integrated.get_values(nuclides=['U235'])\n", - "beta_pu239 = beta_integrated.get_values(nuclides=['Pu239'])\n", - "\n", - "# Reshape the betas\n", - "beta_u235.shape = (beta_u235.shape[0])\n", - "beta_pu239.shape = (beta_pu239.shape[0])\n", - "\n", - "df = beta_integrated.summation(filter_type=openmc.DelayedGroupFilter, remove_filter=True).get_pandas_dataframe()\n", - "print('Beta (U-235) : {:.6f} +/- {:.6f}'.format(df[df['nuclide'] == 'U235']['mean'][0], df[df['nuclide'] == 'U235']['std. dev.'][0]))\n", - "print('Beta (Pu-239): {:.6f} +/- {:.6f}'.format(df[df['nuclide'] == 'Pu239']['mean'][1], df[df['nuclide'] == 'Pu239']['std. dev.'][1]))\n", - "\n", - "beta_u235 = np.append(beta_u235[0], beta_u235)\n", - "beta_pu239 = np.append(beta_pu239[0], beta_pu239)\n", - "\n", - "# Create a step plot for the MGXS\n", - "plt.plot(np.arange(0.5, 7.5, 1), beta_u235, drawstyle='steps', color='b', linewidth=3)\n", - "plt.plot(np.arange(0.5, 7.5, 1), beta_pu239, drawstyle='steps', color='g', linewidth=3)\n", - "\n", - "plt.title('Delayed Neutron Fraction (beta)')\n", - "plt.xlabel('Delayed Group')\n", - "plt.ylabel('Beta(fraction total neutrons)')\n", - "plt.legend(['U-235', 'Pu-239'])\n", - "plt.xlim([0,7])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also plot the energy spectrum for fission emission of prompt and delayed neutrons." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1000.0, 20000000.0)" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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Hox/75XHAyeJyE9xXCB3FJE6VZ3uLaSq5UA5QGFhYYMNI7t376ampoavv07k/dlIVzp37szBBx/MPvvsk2pRDKNNk0xlsRLoLyL9cJTEOByX1glR1YnBcxGZjBPqcHrsGtGpqakhNzeXvLw8JBQ4zsgUVJUtW7ZQU1NDv379Ui2OYbRpkjYN5Uaqmgo8hxPU5ClVXSMiN4jIGAAROU5EanBiO88WkTUtKcPXX39N9+7dTVFkKCJC9+7dbWRoGGlAUvdZqOpSHBfX3rTrPecrqR9oJ1obj+LEkW4SpigyG/v+Wp7yqnIuW3JZ6DqnYw6BkQFKTyhNoVRGupOuBu6soLq6mkGDBtVLCwQCzJo1q0HZjRs3csopp3DMMccwcOBA7rrrrlDeb37zG4YMGUJ+fj6nn346tbVOkLWKigr2228/8vPzyc/P54Ybbkgo06OPPsrUqXH3N/oq01zy8vL49NNPk3qPtkDZq2Xk3pKLzJSoR96deVR/Vh23jbpddQSWB1pFXiNzMWWRJnTo0IGysjLWrl3La6+9xn333cfatc7+xV/84he89dZbrFq1itGjR9dTCieddBKrVq1i1apVXH/99bGaN7KUwPIAdbvqYuZv37WdsU+NpejRorjtxGvDMMCURdrQq1cvhg0bBkBubi5HH300mzY5i8e6desWKvfll182emrmkUceYcCAAQwfPpxXXnkllP7JJ58wduxYjjvuOI477rh6eUEWL17MiBEjOPbYY/n+97/PRx99xN69e+nfvz/B5cp79+7liCOO4JNPPonZ5pYtWzj99NMZOHAgl1xyCebtuGVI9JDfumMr67esp3hAcSitpKAEnaHoDPsODP+0KWURCICIv6OkpGH9kpL6ZQKB5MhZXV3Nm2++yYgRI0Jp1113HYcccghz586tN7JYsWIFQ4cO5ayzzmLNmobrAzZv3syMGTN45ZVXePnll0OjFYArr7ySn//856xcuZKnn36aSy65pEH9E088kddee40333yTcePGcdttt9GuXTsuuOAC5s6dC8Df//53hg4dSo8ePWK2OXPmTE488UTWrFnDD3/4Q/773/+2WH8ZDkEFEHlsv3a72SOMZmPBj5JIrBFAvJFBXV0dY8eO5c4776w3orjpppu46aabuOWWW7j33nuZOXMmw4YNY8OGDeTk5LB06VLOOecc3n23fvC6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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "chi_d_u235 = np.squeeze(chi_delayed.get_xs(nuclides=['U235'], order_groups='decreasing'))\n", - "chi_d_pu239 = np.squeeze(chi_delayed.get_xs(nuclides=['Pu239'], order_groups='decreasing'))\n", - "chi_p_u235 = np.squeeze(chi_prompt.get_xs(nuclides=['U235'], order_groups='decreasing'))\n", - "chi_p_pu239 = np.squeeze(chi_prompt.get_xs(nuclides=['Pu239'], order_groups='decreasing'))\n", - "\n", - "chi_d_u235 = np.append(chi_d_u235 , chi_d_u235[0])\n", - "chi_d_pu239 = np.append(chi_d_pu239, chi_d_pu239[0])\n", - "chi_p_u235 = np.append(chi_p_u235 , chi_p_u235[0])\n", - "chi_p_pu239 = np.append(chi_p_pu239, chi_p_pu239[0])\n", - "\n", - "# Create a step plot for the MGXS\n", - "plt.semilogx(energy_groups.group_edges, chi_d_u235 , drawstyle='steps', color='b', linestyle='--', linewidth=3)\n", - "plt.semilogx(energy_groups.group_edges, chi_d_pu239, drawstyle='steps', color='g', linestyle='--', linewidth=3)\n", - "plt.semilogx(energy_groups.group_edges, chi_p_u235 , drawstyle='steps', color='b', linestyle=':', linewidth=3)\n", - "plt.semilogx(energy_groups.group_edges, chi_p_pu239, drawstyle='steps', color='g', linestyle=':', linewidth=3)\n", - "\n", - "plt.title('Energy Spectrum for Fission Neutrons')\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Fraction on emitted neutrons')\n", - "plt.legend(['U-235 delayed', 'Pu-239 delayed', 'U-235 prompt', 'Pu-239 prompt'],loc=2)\n", - "plt.xlim(1.0e3, 20.0e6)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mdgxs-part-ii.ipynb b/examples/jupyter/mdgxs-part-ii.ipynb deleted file mode 100644 index 77b5b5525..000000000 --- a/examples/jupyter/mdgxs-part-ii.ipynb +++ /dev/null @@ -1,1178 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This IPython Notebook illustrates the use of the **`openmc.mgxs.Library`** class. The `Library` class is designed to automate the calculation of multi-group cross sections for use cases with one or more domains, cross section types, and/or nuclides. In particular, this Notebook illustrates the following features:\n", - "\n", - "* Calculation of multi-energy-group and multi-delayed-group cross sections for a **fuel assembly**\n", - "* Automated creation, manipulation and storage of `MGXS` with **`openmc.mgxs.Library`**\n", - "* Steady-state pin-by-pin **delayed neutron fractions (beta)** for each delayed group.\n", - "* Generation of surface currents on the interfaces and surfaces of a Mesh." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import math\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "import openmc\n", - "import openmc.mgxs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem: fuel, water, and cladding." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6 enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "water.add_nuclide('B10', 8.0042e-6)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a `Materials` object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a materials collection and export to XML\n", - "materials = openmc.Materials((fuel, water, zircaloy))\n", - "materials.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a square array of fuel pins and control rod guide tubes for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(r=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "min_x = openmc.XPlane(x0=-10.71, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+10.71, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-10.71, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=+10.71, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-10., boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=+10., boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "fuel_pin_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "fuel_pin_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "fuel_pin_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "fuel_pin_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Likewise, we can construct a control rod guide tube with the same surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a control rod guide tube\n", - "guide_tube_universe = openmc.Universe(name='Guide Tube')\n", - "\n", - "# Create guide tube Cell\n", - "guide_tube_cell = openmc.Cell(name='Guide Tube Water')\n", - "guide_tube_cell.fill = water\n", - "guide_tube_cell.region = -fuel_outer_radius\n", - "guide_tube_universe.add_cell(guide_tube_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='Guide Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "guide_tube_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='Guide Tube Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "guide_tube_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel assembly Lattice\n", - "assembly = openmc.RectLattice(name='1.6% Fuel Assembly')\n", - "assembly.pitch = (1.26, 1.26)\n", - "assembly.lower_left = [-1.26 * 17. / 2.0] * 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we create a NumPy array of fuel pin and guide tube universes for the lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Create array indices for guide tube locations in lattice\n", - "template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8,\n", - " 11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11])\n", - "template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8,\n", - " 8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14])\n", - "\n", - "# Create universes array with the fuel pin and guide tube universes\n", - "universes = np.tile(fuel_pin_universe, (17,17))\n", - "universes[template_x, template_y] = guide_tube_universe\n", - "\n", - "# Store the array of universes in the lattice\n", - "assembly.universes = universes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell', fill=assembly)\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and export to XML\n", - "geometry = openmc.Geometry(root_universe)\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 50\n", - "inactive = 10\n", - "particles = 2500\n", - "\n", - "# Instantiate a Settings object\n", - "settings = openmc.Settings()\n", - "settings.batches = batches\n", - "settings.inactive = inactive\n", - "settings.particles = particles\n", - "settings.output = {'tallies': False}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-10.71, -10.71, -10, 10.71, 10.71, 10.]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us also create a plot to verify that our fuel assembly geometry was created successfully." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Plot our geometry\n", - "plot = openmc.Plot.from_geometry(geometry)\n", - "plot.pixels = (250, 250)\n", - "plot.color_by = 'material'\n", - "openmc.plot_inline(plot)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see from the plot, we have a nice array of fuel and guide tube pin cells with fuel, cladding, and water!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create an MGXS Library" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we are ready to generate multi-group cross sections! First, let's define a 20-energy-group and 1-energy-group." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 20-group EnergyGroups object\n", - "energy_groups = openmc.mgxs.EnergyGroups()\n", - "energy_groups.group_edges = np.logspace(-3, 7.3, 21)\n", - "\n", - "# Instantiate a 1-group EnergyGroups object\n", - "one_group = openmc.mgxs.EnergyGroups()\n", - "one_group.group_edges = np.array([energy_groups.group_edges[0], energy_groups.group_edges[-1]])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we will instantiate an `openmc.mgxs.Library` for the energy and delayed groups with our the fuel assembly geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=1.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=5.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=6.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=17.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=23.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Instantiate a tally mesh \n", - "mesh = openmc.RegularMesh(mesh_id=1)\n", - "mesh.dimension = [17, 17, 1]\n", - "mesh.lower_left = [-10.71, -10.71, -10000.]\n", - "mesh.width = [1.26, 1.26, 20000.]\n", - "\n", - "# Initialize an 20-energy-group and 6-delayed-group MGXS Library\n", - "mgxs_lib = openmc.mgxs.Library(geometry)\n", - "mgxs_lib.energy_groups = energy_groups\n", - "mgxs_lib.num_delayed_groups = 6\n", - "\n", - "# Specify multi-group cross section types to compute\n", - "mgxs_lib.mgxs_types = ['total', 'transport', 'nu-scatter matrix', 'kappa-fission', 'inverse-velocity', 'chi-prompt',\n", - " 'prompt-nu-fission', 'chi-delayed', 'delayed-nu-fission', 'beta']\n", - "\n", - "# Specify a \"mesh\" domain type for the cross section tally filters\n", - "mgxs_lib.domain_type = 'mesh'\n", - "\n", - "# Specify the mesh domain over which to compute multi-group cross sections\n", - "mgxs_lib.domains = [mesh]\n", - "\n", - "# Construct all tallies needed for the multi-group cross section library\n", - "mgxs_lib.build_library()\n", - "\n", - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "mgxs_lib.add_to_tallies_file(tallies_file, merge=True)\n", - "\n", - "# Instantiate a current tally\n", - "mesh_filter = openmc.MeshSurfaceFilter(mesh)\n", - "current_tally = openmc.Tally(name='current tally')\n", - "current_tally.scores = ['current']\n", - "current_tally.filters = [mesh_filter]\n", - "\n", - "# Add current tally to the tallies file\n", - "tallies_file.append(current_tally)\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we can run OpenMC to generate the cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-18 22:07:58\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading B10 from /opt/data/hdf5/nndc_hdf5_v15/B10.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.03852\n", - " 2/1 0.99743\n", - " 3/1 1.02987\n", - " 4/1 1.04397\n", - " 5/1 1.06262\n", - " 6/1 1.06657\n", - " 7/1 0.98574\n", - " 8/1 1.04364\n", - " 9/1 1.01253\n", - " 10/1 1.02094\n", - " 11/1 0.99586\n", - " 12/1 1.00508 1.00047 +/- 0.00461\n", - " 13/1 1.05292 1.01795 +/- 0.01769\n", - " 14/1 1.04732 1.02530 +/- 0.01450\n", - " 15/1 1.04886 1.03001 +/- 0.01218\n", - " 16/1 1.00948 1.02659 +/- 0.01052\n", - " 17/1 1.02644 1.02657 +/- 0.00889\n", - " 18/1 1.03080 1.02710 +/- 0.00772\n", - " 19/1 1.00018 1.02411 +/- 0.00743\n", - " 20/1 1.05668 1.02736 +/- 0.00740\n", - " 21/1 1.01160 1.02593 +/- 0.00685\n", - " 22/1 1.04334 1.02738 +/- 0.00642\n", - " 23/1 1.03105 1.02766 +/- 0.00591\n", - " 24/1 1.01174 1.02653 +/- 0.00559\n", - " 25/1 0.99844 1.02465 +/- 0.00553\n", - " 26/1 1.02241 1.02451 +/- 0.00517\n", - " 27/1 1.02904 1.02478 +/- 0.00487\n", - " 28/1 1.02132 1.02459 +/- 0.00459\n", - " 29/1 1.01384 1.02402 +/- 0.00438\n", - " 30/1 1.03891 1.02477 +/- 0.00422\n", - " 31/1 1.04092 1.02553 +/- 0.00409\n", - " 32/1 1.00058 1.02440 +/- 0.00406\n", - " 33/1 0.99940 1.02331 +/- 0.00403\n", - " 34/1 0.98362 1.02166 +/- 0.00420\n", - " 35/1 1.05358 1.02294 +/- 0.00422\n", - " 36/1 0.99923 1.02202 +/- 0.00416\n", - " 37/1 1.08491 1.02435 +/- 0.00463\n", - " 38/1 1.01838 1.02414 +/- 0.00447\n", - " 39/1 0.98567 1.02281 +/- 0.00451\n", - " 40/1 1.05047 1.02374 +/- 0.00445\n", - " 41/1 1.01993 1.02361 +/- 0.00431\n", - " 42/1 1.01223 1.02326 +/- 0.00419\n", - " 43/1 1.06259 1.02445 +/- 0.00423\n", - " 44/1 1.01993 1.02432 +/- 0.00411\n", - " 45/1 0.99233 1.02340 +/- 0.00409\n", - " 46/1 0.98532 1.02234 +/- 0.00411\n", - " 47/1 1.02513 1.02242 +/- 0.00400\n", - " 48/1 1.01637 1.02226 +/- 0.00390\n", - " 49/1 1.03215 1.02251 +/- 0.00381\n", - " 50/1 1.01826 1.02241 +/- 0.00371\n", - " Creating state point statepoint.50.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 4.2397e-01 seconds\n", - " Reading cross sections = 4.0321e-01 seconds\n", - " Total time in simulation = 2.0407e+01 seconds\n", - " Time in transport only = 2.0154e+01 seconds\n", - " Time in inactive batches = 1.0937e+00 seconds\n", - " Time in active batches = 1.9314e+01 seconds\n", - " Time synchronizing fission bank = 7.8056e-03 seconds\n", - " Sampling source sites = 6.7223e-03 seconds\n", - " SEND/RECV source sites = 9.5783e-04 seconds\n", - " Time accumulating tallies = 9.2006e-02 seconds\n", - " Total time for finalization = 1.0890e-02 seconds\n", - " Total time elapsed = 2.0869e+01 seconds\n", - " Calculation Rate (inactive) = 22858.4 particles/second\n", - " Calculation Rate (active) = 5177.70 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.02207 +/- 0.00343\n", - " k-effective (Track-length) = 1.02241 +/- 0.00371\n", - " k-effective (Absorption) = 1.02408 +/- 0.00356\n", - " Combined k-effective = 1.02306 +/- 0.00307\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the last statepoint file\n", - "sp = openmc.StatePoint('statepoint.50.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by the `Library`. We simply have to load the tallies from the statepoint into the `Library` and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize MGXS Library with OpenMC statepoint data\n", - "mgxs_lib.load_from_statepoint(sp)\n", - "\n", - "# Extrack the current tally separately\n", - "current_tally = sp.get_tally(name='current tally')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Using Tally Arithmetic to Compute the Delayed Neutron Precursor Concentrations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta` and `DelayedNuFissionXS` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n", - "\n", - "$$\\frac{\\partial}{\\partial t} C_{k,d} (t) = \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t)\\Phi(\\mathbf{r},E',t) - \\lambda_{d} C_{k,d} (t) $$\n", - "\n", - "$$C_{k,d} (t=0) = \\frac{1}{\\lambda_{d}} \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t=0) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t=0)\\Phi(\\mathbf{r},E',t=0) $$" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
mesh 1delayedgroupnuclidescoremeanstd. dev.
xyz
01111total(((delayed-nu-fission / nu-fission) * (delayed...0.0000992.275247e-05
11112total(((delayed-nu-fission / nu-fission) * (delayed...0.0012602.852271e-04
21113total(((delayed-nu-fission / nu-fission) * (delayed...0.0008001.795615e-04
31114total(((delayed-nu-fission / nu-fission) * (delayed...0.0006301.397151e-04
41115total(((delayed-nu-fission / nu-fission) * (delayed...0.0000234.861639e-06
51116total(((delayed-nu-fission / nu-fission) * (delayed...0.0000023.879558e-07
62111total(((delayed-nu-fission / nu-fission) * (delayed...0.0000912.062544e-05
72112total(((delayed-nu-fission / nu-fission) * (delayed...0.0011622.584797e-04
82113total(((delayed-nu-fission / nu-fission) * (delayed...0.0007371.626991e-04
92114total(((delayed-nu-fission / nu-fission) * (delayed...0.0005811.265708e-04
\n", - "
" - ], - "text/plain": [ - " mesh 1 delayedgroup nuclide \\\n", - " x y z \n", - "0 1 1 1 1 total \n", - "1 1 1 1 2 total \n", - "2 1 1 1 3 total \n", - "3 1 1 1 4 total \n", - "4 1 1 1 5 total \n", - "5 1 1 1 6 total \n", - "6 2 1 1 1 total \n", - "7 2 1 1 2 total \n", - "8 2 1 1 3 total \n", - "9 2 1 1 4 total \n", - "\n", - " score mean std. dev. \n", - " \n", - "0 (((delayed-nu-fission / nu-fission) * (delayed... 0.000099 2.275247e-05 \n", - "1 (((delayed-nu-fission / nu-fission) * (delayed... 0.001260 2.852271e-04 \n", - "2 (((delayed-nu-fission / nu-fission) * (delayed... 0.000800 1.795615e-04 \n", - "3 (((delayed-nu-fission / nu-fission) * (delayed... 0.000630 1.397151e-04 \n", - "4 (((delayed-nu-fission / nu-fission) * (delayed... 0.000023 4.861639e-06 \n", - "5 (((delayed-nu-fission / nu-fission) * (delayed... 0.000002 3.879558e-07 \n", - "6 (((delayed-nu-fission / nu-fission) * (delayed... 0.000091 2.062544e-05 \n", - "7 (((delayed-nu-fission / nu-fission) * (delayed... 0.001162 2.584797e-04 \n", - "8 (((delayed-nu-fission / nu-fission) * (delayed... 0.000737 1.626991e-04 \n", - "9 (((delayed-nu-fission / nu-fission) * (delayed... 0.000581 1.265708e-04 " - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Set the time constants for the delayed precursors (in seconds^-1)\n", - "precursor_halflife = np.array([55.6, 24.5, 16.3, 2.37, 0.424, 0.195])\n", - "precursor_lambda = math.log(2.0) / precursor_halflife\n", - "\n", - "beta = mgxs_lib.get_mgxs(mesh, 'beta')\n", - "\n", - "# Create a tally object with only the delayed group filter for the time constants\n", - "beta_filters = [f for f in beta.xs_tally.filters if type(f) is not openmc.DelayedGroupFilter]\n", - "lambda_tally = beta.xs_tally.summation(nuclides=beta.xs_tally.nuclides)\n", - "for f in beta_filters:\n", - " lambda_tally = lambda_tally.summation(filter_type=type(f), remove_filter=True) * 0. + 1.\n", - "\n", - "# Set the mean of the lambda tally and reshape to account for nuclides and scores\n", - "lambda_tally._mean = precursor_lambda\n", - "lambda_tally._mean.shape = lambda_tally.std_dev.shape\n", - "\n", - "# Set a total nuclide and lambda score\n", - "lambda_tally.nuclides = [openmc.Nuclide(name='total')]\n", - "lambda_tally.scores = ['lambda']\n", - "\n", - "delayed_nu_fission = mgxs_lib.get_mgxs(mesh, 'delayed-nu-fission')\n", - "\n", - "# Use tally arithmetic to compute the precursor concentrations\n", - "precursor_conc = beta.xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True) * \\\n", - " delayed_nu_fission.xs_tally.summation(filter_type=openmc.EnergyFilter, remove_filter=True) / lambda_tally\n", - " \n", - "# The difference is a derived tally which can generate Pandas DataFrames for inspection\n", - "precursor_conc.get_pandas_dataframe().head(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another useful feature of the Python API is the ability to extract the surface currents for the interfaces and surfaces of a mesh. We can inspect the currents for the mesh by getting the pandas dataframe." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
mesh 1nuclidescoremeanstd. dev.
xyzsurf
0111x-min outtotalcurrent0.000000.000000
1111x-min intotalcurrent0.000000.000000
2111x-max outtotalcurrent0.032450.000677
3111x-max intotalcurrent0.031800.000659
4111y-min outtotalcurrent0.000000.000000
5111y-min intotalcurrent0.000000.000000
6111y-max outtotalcurrent0.030720.000677
7111y-max intotalcurrent0.031040.000652
8111z-min outtotalcurrent0.000000.000000
9111z-min intotalcurrent0.000000.000000
\n", - "
" - ], - "text/plain": [ - " mesh 1 nuclide score mean std. dev.\n", - " x y z surf \n", - "0 1 1 1 x-min out total current 0.00000 0.000000\n", - "1 1 1 1 x-min in total current 0.00000 0.000000\n", - "2 1 1 1 x-max out total current 0.03245 0.000677\n", - "3 1 1 1 x-max in total current 0.03180 0.000659\n", - "4 1 1 1 y-min out total current 0.00000 0.000000\n", - "5 1 1 1 y-min in total current 0.00000 0.000000\n", - "6 1 1 1 y-max out total current 0.03072 0.000677\n", - "7 1 1 1 y-max in total current 0.03104 0.000652\n", - "8 1 1 1 z-min out total current 0.00000 0.000000\n", - "9 1 1 1 z-min in total current 0.00000 0.000000" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "current_tally.get_pandas_dataframe().head(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cross Section Visualizations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition to inspecting the data in the tallies by getting the pandas dataframe, we can also plot the tally data on the domain mesh. Below is the delayed neutron fraction tallied in each mesh cell for each delayed group." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Beta - delayed group 6')" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Extract the energy-condensed delayed neutron fraction tally\n", - "beta_by_group = beta.get_condensed_xs(one_group).xs_tally.summation(filter_type='energy', remove_filter=True)\n", - "beta_by_group.mean.shape = (17, 17, 6)\n", - "beta_by_group.mean[beta_by_group.mean == 0] = np.nan\n", - "\n", - "# Plot the betas\n", - "plt.figure(figsize=(18,9))\n", - "fig = plt.subplot(231)\n", - "plt.imshow(beta_by_group.mean[:,:,0], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 1')\n", - "\n", - "fig = plt.subplot(232)\n", - "plt.imshow(beta_by_group.mean[:,:,1], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 2')\n", - "\n", - "fig = plt.subplot(233)\n", - "plt.imshow(beta_by_group.mean[:,:,2], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 3')\n", - "\n", - "fig = plt.subplot(234)\n", - "plt.imshow(beta_by_group.mean[:,:,3], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 4')\n", - "\n", - "fig = plt.subplot(235)\n", - "plt.imshow(beta_by_group.mean[:,:,4], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 5')\n", - "\n", - "fig = plt.subplot(236)\n", - "plt.imshow(beta_by_group.mean[:,:,5], interpolation='none', cmap='jet')\n", - "plt.colorbar()\n", - "plt.title('Beta - delayed group 6')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mg-mode-part-i.ipynb b/examples/jupyter/mg-mode-part-i.ipynb deleted file mode 100644 index 23227b1ed..000000000 --- a/examples/jupyter/mg-mode-part-i.ipynb +++ /dev/null @@ -1,701 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This Notebook illustrates the usage of OpenMC's multi-group calculational mode with the Python API. This example notebook creates and executes the 2-D [C5G7](https://www.oecd-nea.org/science/docs/2003/nsc-doc2003-16.pdf) benchmark model using the `openmc.MGXSLibrary` class to create the supporting data library on the fly." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Generate MGXS Library" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import os\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import matplotlib.colors as colors\n", - "import numpy as np\n", - "\n", - "import openmc\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now create the multi-group library using data directly from Appendix A of the [C5G7](https://www.oecd-nea.org/science/docs/2003/nsc-doc2003-16.pdf) benchmark documentation. All of the data below will be created at 294K, consistent with the benchmark.\n", - "\n", - "This notebook will first begin by setting the group structure and building the groupwise data for UO2. As you can see, the cross sections are input in the order of increasing groups (or decreasing energy).\n", - "\n", - "*Note*: The C5G7 benchmark uses transport-corrected cross sections. So the total cross section we input here will technically be the transport cross section." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Create a 7-group structure with arbitrary boundaries (the specific boundaries are unimportant)\n", - "groups = openmc.mgxs.EnergyGroups(np.logspace(-5, 7, 8))\n", - "\n", - "uo2_xsdata = openmc.XSdata('uo2', groups)\n", - "uo2_xsdata.order = 0\n", - "\n", - "# When setting the data let the object know you are setting the data for a temperature of 294K.\n", - "uo2_xsdata.set_total([1.77949E-1, 3.29805E-1, 4.80388E-1, 5.54367E-1,\n", - " 3.11801E-1, 3.95168E-1, 5.64406E-1], temperature=294.)\n", - "\n", - "uo2_xsdata.set_absorption([8.0248E-03, 3.7174E-3, 2.6769E-2, 9.6236E-2,\n", - " 3.0020E-02, 1.1126E-1, 2.8278E-1], temperature=294.)\n", - "uo2_xsdata.set_fission([7.21206E-3, 8.19301E-4, 6.45320E-3, 1.85648E-2,\n", - " 1.78084E-2, 8.30348E-2, 2.16004E-1], temperature=294.)\n", - "\n", - "uo2_xsdata.set_nu_fission([2.005998E-2, 2.027303E-3, 1.570599E-2, 4.518301E-2,\n", - " 4.334208E-2, 2.020901E-1, 5.257105E-1], temperature=294.)\n", - "\n", - "uo2_xsdata.set_chi([5.87910E-1, 4.11760E-1, 3.39060E-4, 1.17610E-7,\n", - " 0.00000E-0, 0.00000E-0, 0.00000E-0], temperature=294.)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now add the scattering matrix data. \n", - "\n", - "*Note*: Most users familiar with deterministic transport libraries are already familiar with the idea of entering one scattering matrix for every order (i.e. scattering order as the outer dimension). However, the shape of OpenMC's scattering matrix entry is instead [Incoming groups, Outgoing Groups, Scattering Order] to best enable other scattering representations. We will follow the more familiar approach in this notebook, and then use numpy's `numpy.rollaxis` function to change the ordering to what we need (scattering order on the inner dimension)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# The scattering matrix is ordered with incoming groups as rows and outgoing groups as columns\n", - "# (i.e., below the diagonal is up-scattering).\n", - "scatter_matrix = \\\n", - " [[[1.27537E-1, 4.23780E-2, 9.43740E-6, 5.51630E-9, 0.00000E-0, 0.00000E-0, 0.00000E-0],\n", - " [0.00000E-0, 3.24456E-1, 1.63140E-3, 3.14270E-9, 0.00000E-0, 0.00000E-0, 0.00000E-0],\n", - " [0.00000E-0, 0.00000E-0, 4.50940E-1, 2.67920E-3, 0.00000E-0, 0.00000E-0, 0.00000E-0],\n", - " [0.00000E-0, 0.00000E-0, 0.00000E-0, 4.52565E-1, 5.56640E-3, 0.00000E-0, 0.00000E-0],\n", - " [0.00000E-0, 0.00000E-0, 0.00000E-0, 1.25250E-4, 2.71401E-1, 1.02550E-2, 1.00210E-8],\n", - " [0.00000E-0, 0.00000E-0, 0.00000E-0, 0.00000E-0, 1.29680E-3, 2.65802E-1, 1.68090E-2],\n", - " [0.00000E-0, 0.00000E-0, 0.00000E-0, 0.00000E-0, 0.00000E-0, 8.54580E-3, 2.73080E-1]]]\n", - "scatter_matrix = np.array(scatter_matrix)\n", - "scatter_matrix = np.rollaxis(scatter_matrix, 0, 3)\n", - "uo2_xsdata.set_scatter_matrix(scatter_matrix, temperature=294.)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the UO2 data has been created, we can move on to the remaining materials using the same process.\n", - "\n", - "However, we will actually skip repeating the above for now. Our simulation will instead use the `c5g7.h5` file that has already been created using exactly the same logic as above, but for the remaining materials in the benchmark problem.\n", - "\n", - "For now we will show how you would use the `uo2_xsdata` information to create an `openmc.MGXSLibrary` object and write to disk." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Initialize the library\n", - "mg_cross_sections_file = openmc.MGXSLibrary(groups)\n", - "\n", - "# Add the UO2 data to it\n", - "mg_cross_sections_file.add_xsdata(uo2_xsdata)\n", - "\n", - "# And write to disk\n", - "mg_cross_sections_file.export_to_hdf5('mgxs.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Generate 2-D C5G7 Problem Input Files" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "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 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 specify 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", - "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." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# For every cross section data set in the library, assign an openmc.Macroscopic object to a material\n", - "materials = {}\n", - "for xs in ['uo2', 'mox43', 'mox7', 'mox87', 'fiss_chamber', 'guide_tube', 'water']:\n", - " materials[xs] = openmc.Material(name=xs)\n", - " materials[xs].set_density('macro', 1.)\n", - " materials[xs].add_macroscopic(xs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can go ahead and produce a `materials.xml` file for use by OpenMC" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Instantiate a Materials collection, register all Materials, and export to XML\n", - "materials_file = openmc.Materials(materials.values())\n", - "\n", - "# Set the location of the cross sections file to our pre-written set\n", - "materials_file.cross_sections = 'c5g7.h5'\n", - "\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our next step will be to create the geometry information needed for our assembly and to write that to the `geometry.xml` file.\n", - "\n", - "We will begin by defining the surfaces, cells, and universes needed for each of the individual fuel pins, guide tubes, and fission chambers." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create the surface used for each pin\n", - "pin_surf = openmc.ZCylinder(x0=0, y0=0, R=0.54, name='pin_surf')\n", - "\n", - "# Create the cells which will be used to represent each pin type.\n", - "cells = {}\n", - "universes = {}\n", - "for material in materials.values():\n", - " # Create the cell for the material inside the cladding\n", - " cells[material.name] = openmc.Cell(name=material.name)\n", - " # Assign the half-spaces to the cell\n", - " cells[material.name].region = -pin_surf\n", - " # Register the material with this cell\n", - " cells[material.name].fill = material\n", - " \n", - " # Repeat the above for the material outside the cladding (i.e., the moderator)\n", - " cell_name = material.name + '_moderator'\n", - " cells[cell_name] = openmc.Cell(name=cell_name)\n", - " cells[cell_name].region = +pin_surf\n", - " cells[cell_name].fill = materials['water']\n", - " \n", - " # Finally add the two cells we just made to a Universe object\n", - " universes[material.name] = openmc.Universe(name=material.name)\n", - " universes[material.name].add_cells([cells[material.name], cells[cell_name]])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "The next step is to take our universes (representing the different pin types) and lay them out in a lattice to represent the assembly types" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "lattices = {}\n", - "\n", - "# Instantiate the UO2 Lattice\n", - "lattices['UO2 Assembly'] = openmc.RectLattice(name='UO2 Assembly')\n", - "lattices['UO2 Assembly'].dimension = [17, 17]\n", - "lattices['UO2 Assembly'].lower_left = [-10.71, -10.71]\n", - "lattices['UO2 Assembly'].pitch = [1.26, 1.26]\n", - "u = universes['uo2']\n", - "g = universes['guide_tube']\n", - "f = universes['fiss_chamber']\n", - "lattices['UO2 Assembly'].universes = \\\n", - " [[u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, u, u, g, u, u, g, u, u, g, u, u, u, u, u],\n", - " [u, u, u, g, u, u, u, u, u, u, u, u, u, g, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, g, u, u, g, u, u, g, u, u, g, u, u, g, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, g, u, u, g, u, u, f, u, u, g, u, u, g, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, g, u, u, g, u, u, g, u, u, g, u, u, g, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, g, u, u, u, u, u, u, u, u, u, g, u, u, u],\n", - " [u, u, u, u, u, g, u, u, g, u, u, g, u, u, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u],\n", - " [u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u]]\n", - " \n", - "# Create a containing cell and universe\n", - "cells['UO2 Assembly'] = openmc.Cell(name='UO2 Assembly')\n", - "cells['UO2 Assembly'].fill = lattices['UO2 Assembly']\n", - "universes['UO2 Assembly'] = openmc.Universe(name='UO2 Assembly')\n", - "universes['UO2 Assembly'].add_cell(cells['UO2 Assembly'])\n", - "\n", - "# Instantiate the MOX Lattice\n", - "lattices['MOX Assembly'] = openmc.RectLattice(name='MOX Assembly')\n", - "lattices['MOX Assembly'].dimension = [17, 17]\n", - "lattices['MOX Assembly'].lower_left = [-10.71, -10.71]\n", - "lattices['MOX Assembly'].pitch = [1.26, 1.26]\n", - "m = universes['mox43']\n", - "n = universes['mox7']\n", - "o = universes['mox87']\n", - "g = universes['guide_tube']\n", - "f = universes['fiss_chamber']\n", - "lattices['MOX Assembly'].universes = \\\n", - " [[m, m, m, m, m, m, m, m, m, m, m, m, m, m, m, m, m],\n", - " [m, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, m],\n", - " [m, n, n, n, n, g, n, n, g, n, n, g, n, n, n, n, m],\n", - " [m, n, n, g, n, o, o, o, o, o, o, o, n, g, n, n, m],\n", - " [m, n, n, n, o, o, o, o, o, o, o, o, o, n, n, n, m],\n", - " [m, n, g, o, o, g, o, o, g, o, o, g, o, o, g, n, m],\n", - " [m, n, n, o, o, o, o, o, o, o, o, o, o, o, n, n, m],\n", - " [m, n, n, o, o, o, o, o, o, o, o, o, o, o, n, n, m],\n", - " [m, n, g, o, o, g, o, o, f, o, o, g, o, o, g, n, m],\n", - " [m, n, n, o, o, o, o, o, o, o, o, o, o, o, n, n, m],\n", - " [m, n, n, o, o, o, o, o, o, o, o, o, o, o, n, n, m],\n", - " [m, n, g, o, o, g, o, o, g, o, o, g, o, o, g, n, m],\n", - " [m, n, n, n, o, o, o, o, o, o, o, o, o, n, n, n, m],\n", - " [m, n, n, g, n, o, o, o, o, o, o, o, n, g, n, n, m],\n", - " [m, n, n, n, n, g, n, n, g, n, n, g, n, n, n, n, m],\n", - " [m, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, m],\n", - " [m, m, m, m, m, m, m, m, m, m, m, m, m, m, m, m, m]]\n", - " \n", - "# Create a containing cell and universe\n", - "cells['MOX Assembly'] = openmc.Cell(name='MOX Assembly')\n", - "cells['MOX Assembly'].fill = lattices['MOX Assembly']\n", - "universes['MOX Assembly'] = openmc.Universe(name='MOX Assembly')\n", - "universes['MOX Assembly'].add_cell(cells['MOX Assembly'])\n", - " \n", - "# Instantiate the reflector Lattice\n", - "lattices['Reflector Assembly'] = openmc.RectLattice(name='Reflector Assembly')\n", - "lattices['Reflector Assembly'].dimension = [1,1]\n", - "lattices['Reflector Assembly'].lower_left = [-10.71, -10.71]\n", - "lattices['Reflector Assembly'].pitch = [21.42, 21.42]\n", - "lattices['Reflector Assembly'].universes = [[universes['water']]]\n", - "\n", - "# Create a containing cell and universe\n", - "cells['Reflector Assembly'] = openmc.Cell(name='Reflector Assembly')\n", - "cells['Reflector Assembly'].fill = lattices['Reflector Assembly']\n", - "universes['Reflector Assembly'] = openmc.Universe(name='Reflector Assembly')\n", - "universes['Reflector Assembly'].add_cell(cells['Reflector Assembly'])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "Let's now create the core layout in a 3x3 lattice where each lattice position is one of the assemblies we just defined.\n", - "\n", - "After that we can create the final cell to contain the entire core." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "lattices['Core'] = openmc.RectLattice(name='3x3 core lattice')\n", - "lattices['Core'].dimension= [3, 3]\n", - "lattices['Core'].lower_left = [-32.13, -32.13]\n", - "lattices['Core'].pitch = [21.42, 21.42]\n", - "r = universes['Reflector Assembly']\n", - "u = universes['UO2 Assembly']\n", - "m = universes['MOX Assembly']\n", - "lattices['Core'].universes = [[u, m, r],\n", - " [m, u, r],\n", - " [r, r, r]]\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "min_x = openmc.XPlane(x0=-32.13, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+32.13, boundary_type='vacuum')\n", - "min_y = openmc.YPlane(y0=-32.13, boundary_type='vacuum')\n", - "max_y = openmc.YPlane(y0=+32.13, boundary_type='reflective')\n", - "\n", - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell')\n", - "root_cell.fill = lattices['Core']\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(name='root universe', universe_id=0)\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we commit to the geometry, we should view it using the Python API's plotting capability" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "root_universe.plot(origin=(0., 0., 0.), width=(3 * 21.42, 3 * 21.42), pixels=(500, 500),\n", - " color_by='material')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OK, it looks pretty good, let's go ahead and write the file" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "geometry = openmc.Geometry(root_universe)\n", - "\n", - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now create the tally file information. The tallies will be set up to give us the pin powers in this notebook. We will do this with a mesh filter, with one mesh cell per pin." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "tallies_file = openmc.Tallies()\n", - "\n", - "# Instantiate a tally Mesh\n", - "mesh = openmc.RegularMesh()\n", - "mesh.dimension = [17 * 2, 17 * 2]\n", - "mesh.lower_left = [-32.13, -10.71]\n", - "mesh.upper_right = [+10.71, +32.13]\n", - "\n", - "# Instantiate tally Filter\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='mesh tally')\n", - "tally.filters = [mesh_filter]\n", - "tally.scores = ['fission']\n", - "\n", - "# Add tally to collection\n", - "tallies_file.append(tally)\n", - "\n", - "# Export all tallies to a \"tallies.xml\" file\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters for the `settings.xml` file. Note the use of the `energy_mode` attribute of our `settings_file` object. This is used to tell OpenMC that we intend to run in multi-group mode instead of the default continuous-energy mode. If we didn't specify this but our cross sections file was not a continuous-energy data set, then OpenMC would complain.\n", - "\n", - "This will be a relatively coarse calculation with only 500,000 active histories. A benchmark-fidelity run would of course require many more!" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 150\n", - "inactive = 50\n", - "particles = 5000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "\n", - "# Tell OpenMC this is a multi-group problem\n", - "settings_file.energy_mode = 'multi-group'\n", - "\n", - "# Set the verbosity to 6 so we dont see output for every batch\n", - "settings_file.verbosity = 6\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-32.13, -10.71, -1e50, 10.71, 32.13, 1e50]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Tell OpenMC we want to run in eigenvalue mode\n", - "settings_file.run_mode = 'eigenvalue'\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's go ahead and execute the simulation! You'll notice that the output for multi-group mode is exactly the same as for continuous-energy. The differences are all under the hood." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | 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 | 966169de084fcfda3a5aaca3edc0065c8caf6bbc\n", - " Date/Time | 2017-03-09 08:18:02\n", - " OpenMP Threads | 8\n", - "\n", - " Reading settings XML file...\n", - " Reading geometry XML file...\n", - " Reading materials XML file...\n", - " Reading cross sections HDF5 file...\n", - " Reading tallies XML file...\n", - " Loading cross section data...\n", - " Loading uo2 data...\n", - " Loading mox43 data...\n", - " Loading mox7 data...\n", - " Loading mox87 data...\n", - " Loading fiss_chamber data...\n", - " Loading guide_tube data...\n", - " Loading water data...\n", - " Building neighboring cells lists for each surface...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Creating state point statepoint.150.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 1.3630E-01 seconds\n", - " Reading cross sections = 3.0827E-02 seconds\n", - " Total time in simulation = 8.9648E+00 seconds\n", - " Time in transport only = 8.2752E+00 seconds\n", - " Time in inactive batches = 2.4798E+00 seconds\n", - " Time in active batches = 6.4849E+00 seconds\n", - " Time synchronizing fission bank = 1.4553E-02 seconds\n", - " Sampling source sites = 1.0318E-02 seconds\n", - " SEND/RECV source sites = 4.0840E-03 seconds\n", - " Time accumulating tallies = 4.2427E-04 seconds\n", - " Total time for finalization = 1.7081E-02 seconds\n", - " Total time elapsed = 9.1340E+00 seconds\n", - " Calculation Rate (inactive) = 1.00813E+05 neutrons/second\n", - " Calculation Rate (active) = 77101.8 neutrons/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.18880 +/- 0.00179\n", - " k-effective (Track-length) = 1.18853 +/- 0.00244\n", - " k-effective (Absorption) = 1.18601 +/- 0.00111\n", - " Combined k-effective = 1.18628 +/- 0.00111\n", - " Leakage Fraction = 0.00175 +/- 0.00006\n", - "\n" - ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Results Visualization\n", - "\n", - "Now that we have run the simulation, let's look at the fission rate and flux tallies that we tallied." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Load the last statepoint file and keff value\n", - "sp = openmc.StatePoint('statepoint.' + str(batches) + '.h5')\n", - "\n", - "# Get the OpenMC pin power tally data\n", - "mesh_tally = sp.get_tally(name='mesh tally')\n", - "fission_rates = mesh_tally.get_values(scores=['fission'])\n", - "\n", - "# Reshape array to 2D for plotting\n", - "fission_rates.shape = mesh.dimension\n", - "\n", - "# Normalize to the average pin power\n", - "fission_rates /= np.mean(fission_rates[fission_rates > 0.])\n", - "\n", - "# Force zeros to be NaNs so their values are not included when matplotlib calculates\n", - "# the color scale\n", - "fission_rates[fission_rates == 0.] = np.nan\n", - "\n", - "# Plot the pin powers and the fluxes\n", - "plt.figure()\n", - "plt.imshow(fission_rates, interpolation='none', cmap='jet', origin='lower')\n", - "plt.colorbar()\n", - "plt.title('Pin Powers')\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There we have it! We have just successfully run the C5G7 benchmark model!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/mg-mode-part-ii.ipynb b/examples/jupyter/mg-mode-part-ii.ipynb deleted file mode 100644 index 85a8d7367..000000000 --- a/examples/jupyter/mg-mode-part-ii.ipynb +++ /dev/null @@ -1,1539 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The previous Notebook in this series used multi-group mode to perform a calculation with previously defined cross sections. However, in many circumstances the multi-group data is not given and one must instead generate the cross sections for the specific application (or at least verify the use of cross sections from another application). \n", - "\n", - "This Notebook illustrates the use of the openmc.mgxs.Library class specifically for the calculation of MGXS to be used in OpenMC's multi-group mode. This example notebook is therefore very similar to the MGXS Part III notebook, except OpenMC is used as the multi-group solver instead of OpenMOC.\n", - "\n", - "During this process, this notebook will illustrate the following features:\n", - "\n", - " - Calculation of multi-group cross sections for a fuel assembly\n", - " - Automated creation and storage of MGXS with openmc.mgxs.Library\n", - " - Steady-state pin-by-pin fission rates comparison between continuous-energy and multi-group OpenMC.\n", - " - Modification of the scattering data in the library to show the flexibility of the multi-group solver\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import os\n", - "\n", - "import openmc\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will begin by creating three materials for the fuel, water, and cladding of the fuel pins." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "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_element('U', 1., enrichment=1.6)\n", - "fuel.add_element('O', 2.)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_element('Zr', 1.)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_element('H', 4.9457e-2)\n", - "water.add_element('O', 2.4732e-2)\n", - "water.add_element('B', 8.0042e-6)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a Materials object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials object\n", - "materials_file = openmc.Materials((fuel, zircaloy, water))\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a square array of fuel pins and control rod guide tubes for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "# The x0 and y0 parameters (0. and 0.) are the default values for an\n", - "# openmc.ZCylinder object. We could therefore leave them out to no effect\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, R=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "min_x = openmc.XPlane(x0=-10.71, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+10.71, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-10.71, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=+10.71, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-10., boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=+10., boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "fuel_pin_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "fuel_pin_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "fuel_pin_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "fuel_pin_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Likewise, we can construct a control rod guide tube with the same surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a control rod guide tube\n", - "guide_tube_universe = openmc.Universe(name='Guide Tube')\n", - "\n", - "# Create guide tube Cell\n", - "guide_tube_cell = openmc.Cell(name='Guide Tube Water')\n", - "guide_tube_cell.fill = water\n", - "guide_tube_cell.region = -fuel_outer_radius\n", - "guide_tube_universe.add_cell(guide_tube_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='Guide Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "guide_tube_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='Guide Tube Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "guide_tube_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel assembly Lattice\n", - "assembly = openmc.RectLattice(name='1.6% Fuel Assembly')\n", - "assembly.pitch = (1.26, 1.26)\n", - "assembly.lower_left = [-1.26 * 17. / 2.0] * 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we create a NumPy array of fuel pin and guide tube universes for the lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Create array indices for guide tube locations in lattice\n", - "template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8,\n", - " 11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11])\n", - "template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8,\n", - " 8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14])\n", - "\n", - "# Initialize an empty 17x17 array of the lattice universes\n", - "universes = np.empty((17, 17), dtype=openmc.Universe)\n", - "\n", - "# Fill the array with the fuel pin and guide tube universes\n", - "universes[:, :] = fuel_pin_universe\n", - "universes[template_x, template_y] = guide_tube_universe\n", - "\n", - "# Store the array of universes in the lattice\n", - "assembly.universes = universes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell')\n", - "root_cell.fill = assembly\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(name='root universe', universe_id=0)\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before proceeding lets check the geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "root_universe.plot(origin=(0., 0., 0.), width=(21.42, 21.42), pixels=(500, 500), color_by='material')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Looks good!\n", - "\n", - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root universe\n", - "geometry = openmc.Geometry(root_universe)\n", - "\n", - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 600\n", - "inactive = 50\n", - "particles = 3000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': False}\n", - "settings_file.run_mode = 'eigenvalue'\n", - "settings_file.verbosity = 4\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-10.71, -10.71, -10, 10.71, 10.71, 10.]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Create an MGXS Library\n", - "\n", - "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in EnergyGroups class." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 2-group EnergyGroups object\n", - "groups = openmc.mgxs.EnergyGroups([0., 0.625, 20.0e6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we will instantiate an openmc.mgxs.Library for the energy groups with our the fuel assembly geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize a 2-group MGXS Library for OpenMC\n", - "mgxs_lib = openmc.mgxs.Library(geometry)\n", - "mgxs_lib.energy_groups = groups" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we must specify to the Library which types of cross sections to compute. OpenMC's multi-group mode can accept isotropic flux-weighted cross sections or angle-dependent cross sections, as well as supporting anisotropic scattering represented by either Legendre polynomials, histogram, or tabular angular distributions. We will create the following multi-group cross sections needed to run an OpenMC simulation to verify the accuracy of our cross sections: \"total\", \"absorption\", \"nu-fission\", '\"fission\", \"nu-scatter matrix\", \"multiplicity matrix\", and \"chi\".\n", - "\n", - "The \"multiplicity matrix\" type is a relatively rare cross section type. This data is needed to provide OpenMC's multi-group mode with additional information needed to accurately treat scattering multiplication (i.e., (n,xn) reactions)), including how this multiplication varies depending on both incoming and outgoing neutron energies." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Specify multi-group cross section types to compute\n", - "mgxs_lib.mgxs_types = ['total', 'absorption', 'nu-fission', 'fission',\n", - " 'nu-scatter matrix', 'multiplicity matrix', 'chi']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we must specify the type of domain over which we would like the `Library` to compute multi-group cross sections. The domain type corresponds to the type of tally filter to be used in the tallies created to compute multi-group cross sections. At the present time, the `Library` supports \"material\", \"cell\", \"universe\", and \"mesh\" domain types. In this simple example, we wish to compute multi-group cross sections only for each material and therefore will use a \"material\" domain type.\n", - "\n", - "**NOTE:** By default, the `Library` class will instantiate `MGXS` objects for each and every domain (material, cell, universe, or mesh) in the geometry of interest. However, one may specify a subset of these domains to the `Library.domains` property." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Specify a \"cell\" domain type for the cross section tally filters\n", - "mgxs_lib.domain_type = \"material\"\n", - "\n", - "# Specify the cell domains over which to compute multi-group cross sections\n", - "mgxs_lib.domains = geometry.get_all_materials().values()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will instruct the library to not compute cross sections on a nuclide-by-nuclide basis, and instead to focus on generating material-specific macroscopic cross sections.\n", - "\n", - "**NOTE:** The default value of the `by_nuclide` parameter is `False`, so the following step is not necessary but is included for illustrative purposes." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# Do not compute cross sections on a nuclide-by-nuclide basis\n", - "mgxs_lib.by_nuclide = False" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we will set the scattering order that we wish to use. For this problem we will use P3 scattering. A warning is expected telling us that the default behavior (a P0 correction on the scattering data) is over-ridden by our choice of using a Legendre expansion to treat anisotropic scattering." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/nelsonag/git/openmc/openmc/mgxs/library.py:412: RuntimeWarning: The P0 correction will be ignored since the scattering order 0 is greater than zero\n", - " warn(msg, RuntimeWarning)\n" - ] - } - ], - "source": [ - "# Set the Legendre order to 3 for P3 scattering\n", - "mgxs_lib.legendre_order = 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the `Library` has been setup let's verify that it contains the types of cross sections which meet the needs of OpenMC's multi-group solver. Note that this step is done automatically when writing the Multi-Group Library file later in the process (as part of `mgxs_lib.write_mg_library()`), but it is a good practice to also run this before spending all the time running OpenMC to generate the cross sections.\n", - "\n", - "If no error is raised, then we have a good set of data." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "# Check the library - if no errors are raised, then the library is satisfactory.\n", - "mgxs_lib.check_library_for_openmc_mgxs()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Great, now we can use the `Library` to construct the tallies needed to compute all of the requested multi-group cross sections in each domain." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "# Construct all tallies needed for the multi-group cross section library\n", - "mgxs_lib.build_library()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The tallies can now be exported to a \"tallies.xml\" input file for OpenMC.\n", - "\n", - "**NOTE:** At this point the `Library` has constructed nearly 100 distinct Tally objects. The overhead to tally in OpenMC scales as O(N) for N tallies, which can become a bottleneck for large tally datasets. To compensate for this, the Python API's `Tally`, `Filter` and `Tallies` classes allow for the smart merging of tallies when possible. The `Library` class supports this runtime optimization with the use of the optional `merge` parameter (`False` by default) for the `Library.add_to_tallies_file(...)` method, as shown below." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "mgxs_lib.add_to_tallies_file(tallies_file, merge=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition, we instantiate a fission rate mesh tally that we will eventually use to compare with the corresponding multi-group results." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=66.\n", - " warn(msg, IDWarning)\n", - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=11.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Instantiate a tally Mesh\n", - "mesh = openmc.RegularMesh()\n", - "mesh.dimension = [17, 17]\n", - "mesh.lower_left = [-10.71, -10.71]\n", - "mesh.upper_right = [+10.71, +10.71]\n", - "\n", - "# Instantiate tally Filter\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='mesh tally')\n", - "tally.filters = [mesh_filter]\n", - "tally.scores = ['fission']\n", - "\n", - "# Add tally to collection\n", - "tallies_file.append(tally, merge=True)\n", - "\n", - "# Export all tallies to a \"tallies.xml\" file\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "Time to run the calculation and get our results!" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2018 Massachusetts Institute of Technology\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.10.0\n", - " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", - " Date/Time | 2018-04-22 15:02:43\n", - " OpenMP Threads | 8\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.16513 +/- 0.00090\n", - " k-effective (Track-length) = 1.16337 +/- 0.00104\n", - " k-effective (Absorption) = 1.16479 +/- 0.00080\n", - " Combined k-effective = 1.16460 +/- 0.00068\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make sure the results we need are available after running the multi-group calculation, we will now rename the statepoint and summary files." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], - "source": [ - "# Move the statepoint File\n", - "ce_spfile = './statepoint_ce.h5'\n", - "os.rename('statepoint.' + str(batches) + '.h5', ce_spfile)\n", - "# Move the Summary file\n", - "ce_sumfile = './summary_ce.h5'\n", - "os.rename('summary.h5', ce_sumfile)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tally Data Processing\n", - "\n", - "Our simulation ran successfully and created statepoint and summary output files. Let's begin by loading the StatePoint file." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the statepoint file\n", - "sp = openmc.StatePoint(ce_spfile, autolink=False)\n", - "\n", - "# Load the summary file in its new location\n", - "su = openmc.Summary(ce_sumfile)\n", - "sp.link_with_summary(su)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by the `Library`. We simply have to load the tallies from the statepoint into the `Library` and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize MGXS Library with OpenMC statepoint data\n", - "mgxs_lib.load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step will be to prepare the input for OpenMC to use our newly created multi-group data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multi-Group OpenMC Calculation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now use the `Library` to produce a multi-group cross section data set for use by the OpenMC multi-group solver. \n", - "Note that since this simulation included so few histories, it is reasonable to expect some data has not had any scores, and thus we could see division by zero errors. This will show up as a runtime warning in the following step. The `Library` class is designed to gracefully handle these scenarios." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a MGXS File which can then be written to disk\n", - "mgxs_file = mgxs_lib.create_mg_library(xs_type='macro', xsdata_names=['fuel', 'zircaloy', 'water'])\n", - "\n", - "# Write the file to disk using the default filename of \"mgxs.h5\"\n", - "mgxs_file.export_to_hdf5()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC's multi-group mode uses the same input files as does the continuous-energy mode (materials, geometry, settings, plots, and tallies file). Differences would include the use of a flag to tell the code to use multi-group transport, a location of the multi-group library file, and any changes needed in the materials.xml and geometry.xml files to re-define materials as necessary. The materials and geometry file changes could be necessary if materials or their nuclide/element/macroscopic constituents need to be renamed.\n", - "\n", - "In this example we have created macroscopic cross sections (by material), and thus we will need to change the material definitions accordingly.\n", - "\n", - "First we will create the new materials.xml file." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=1.\n", - " warn(msg, IDWarning)\n", - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=3.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Re-define our materials to use the multi-group macroscopic data\n", - "# instead of the continuous-energy data.\n", - "\n", - "# 1.6% enriched fuel UO2\n", - "fuel_mg = openmc.Material(name='UO2', material_id=1)\n", - "fuel_mg.add_macroscopic('fuel')\n", - "\n", - "# cladding\n", - "zircaloy_mg = openmc.Material(name='Clad', material_id=2)\n", - "zircaloy_mg.add_macroscopic('zircaloy')\n", - "\n", - "# moderator\n", - "water_mg = openmc.Material(name='Water', material_id=3)\n", - "water_mg.add_macroscopic('water')\n", - "\n", - "# Finally, instantiate our Materials object\n", - "materials_file = openmc.Materials((fuel_mg, zircaloy_mg, water_mg))\n", - "\n", - "# Set the location of the cross sections file\n", - "materials_file.cross_sections = 'mgxs.h5'\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "No geometry file neeeds to be written as the continuous-energy file is correctly defined for the multi-group case as well." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we can make the changes we need to the simulation parameters.\n", - "These changes are limited to telling OpenMC to run a multi-group vice contrinuous-energy calculation." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "# Set the energy mode\n", - "settings_file.energy_mode = 'multi-group'\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lets clear the tallies file so it doesn't include tallies for re-generating a multi-group library, but then put back in a tally for the fission mesh." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "\n", - "# Add fission and flux mesh to tally for plotting using the same mesh we've already defined\n", - "mesh_tally = openmc.Tally(name='mesh tally')\n", - "mesh_tally.filters = [openmc.MeshFilter(mesh)]\n", - "mesh_tally.scores = ['fission']\n", - "tallies_file.append(mesh_tally)\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Before running the calculation let's visually compare a subset of the newly-generated multi-group cross section data to the continuous-energy data. We will do this using the cross section plotting functionality built-in to the OpenMC Python API." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# First lets plot the fuel data\n", - "# We will first add the continuous-energy data\n", - "fig = openmc.plot_xs(fuel, ['total'])\n", - "\n", - "# We will now add in the corresponding multi-group data and show the result\n", - "openmc.plot_xs(fuel_mg, ['total'], plot_CE=False, mg_cross_sections='mgxs.h5', axis=fig.axes[0])\n", - "fig.axes[0].legend().set_visible(False)\n", - "plt.show()\n", - "plt.close()\n", - "\n", - "# Then repeat for the zircaloy data\n", - "fig = openmc.plot_xs(zircaloy, ['total'])\n", - "openmc.plot_xs(zircaloy_mg, ['total'], plot_CE=False, mg_cross_sections='mgxs.h5', axis=fig.axes[0])\n", - "fig.axes[0].legend().set_visible(False)\n", - "plt.show()\n", - "plt.close()\n", - "\n", - "# And finally repeat for the water data\n", - "fig = openmc.plot_xs(water, ['total'])\n", - "openmc.plot_xs(water_mg, ['total'], plot_CE=False, mg_cross_sections='mgxs.h5', axis=fig.axes[0])\n", - "fig.axes[0].legend().set_visible(False)\n", - "plt.show()\n", - "plt.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, the problem is set up and we can run the multi-group calculation." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2018 Massachusetts Institute of Technology\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.10.0\n", - " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", - " Date/Time | 2018-04-22 15:04:03\n", - " OpenMP Threads | 8\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.16541 +/- 0.00086\n", - " k-effective (Track-length) = 1.16590 +/- 0.00096\n", - " k-effective (Absorption) = 1.16469 +/- 0.00046\n", - " Combined k-effective = 1.16480 +/- 0.00045\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run the Multi-Group OpenMC Simulation\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Results Comparison\n", - "Now we can compare the multi-group and continuous-energy results.\n", - "\n", - "We will begin by loading the multi-group statepoint file we just finished writing and extracting the calculated keff." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "# Move the StatePoint File\n", - "mg_spfile = './statepoint_mg.h5'\n", - "os.rename('statepoint.' + str(batches) + '.h5', mg_spfile)\n", - "# Move the Summary file\n", - "mg_sumfile = './summary_mg.h5'\n", - "os.rename('summary.h5', mg_sumfile)\n", - "\n", - "# Rename and then load the last statepoint file and keff value\n", - "mgsp = openmc.StatePoint(mg_spfile, autolink=False)\n", - "\n", - "# Load the summary file in its new location\n", - "mgsu = openmc.Summary(mg_sumfile)\n", - "mgsp.link_with_summary(mgsu)\n", - "\n", - "# Get keff\n", - "mg_keff = mgsp.k_combined" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we can load the continuous-energy eigenvalue for comparison." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "ce_keff = sp.k_combined" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lets compare the two eigenvalues, including their bias" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Continuous-Energy keff = 1.164600+/-0.000677\n", - "Multi-Group keff = 1.164805+/-0.000448\n", - "bias [pcm]: -20.4\n" - ] - } - ], - "source": [ - "bias = 1.0E5 * (ce_keff - mg_keff)\n", - "\n", - "print('Continuous-Energy keff = {0:1.6f}'.format(ce_keff))\n", - "print('Multi-Group keff = {0:1.6f}'.format(mg_keff))\n", - "print('bias [pcm]: {0:1.1f}'.format(bias.nominal_value))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This shows a small but nontrivial pcm bias between the two methods. Some degree of mismatch is expected simply to the very few histories being used in these example problems. An additional mismatch is always inherent in the practical application of multi-group theory due to the high degree of approximations inherent in that method." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Pin Power Visualizations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we will visualize the pin power results obtained from both the Continuous-Energy and Multi-Group OpenMC calculations.\n", - "\n", - "First, we extract volume-integrated fission rates from the Multi-Group calculation's mesh fission rate tally for each pin cell in the fuel assembly." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "# Get the OpenMC fission rate mesh tally data\n", - "mg_mesh_tally = mgsp.get_tally(name='mesh tally')\n", - "mg_fission_rates = mg_mesh_tally.get_values(scores=['fission'])\n", - "\n", - "# Reshape array to 2D for plotting\n", - "mg_fission_rates.shape = (17,17)\n", - "\n", - "# Normalize to the average pin power\n", - "mg_fission_rates /= np.mean(mg_fission_rates[mg_fission_rates > 0.])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now do the same for the Continuous-Energy results." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "# Get the OpenMC fission rate mesh tally data\n", - "ce_mesh_tally = sp.get_tally(name='mesh tally')\n", - "ce_fission_rates = ce_mesh_tally.get_values(scores=['fission'])\n", - "\n", - "# Reshape array to 2D for plotting\n", - "ce_fission_rates.shape = (17,17)\n", - "\n", - "# Normalize to the average pin power\n", - "ce_fission_rates /= np.mean(ce_fission_rates[ce_fission_rates > 0.])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can easily use Matplotlib to visualize the two fission rates side-by-side." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Force zeros to be NaNs so their values are not included when matplotlib calculates\n", - "# the color scale\n", - "ce_fission_rates[ce_fission_rates == 0.] = np.nan\n", - "mg_fission_rates[mg_fission_rates == 0.] = np.nan\n", - "\n", - "# Plot the CE fission rates in the left subplot\n", - "fig = plt.subplot(121)\n", - "plt.imshow(ce_fission_rates, interpolation='none', cmap='jet')\n", - "plt.title('Continuous-Energy Fission Rates')\n", - "\n", - "# Plot the MG fission rates in the right subplot\n", - "fig2 = plt.subplot(122)\n", - "plt.imshow(mg_fission_rates, interpolation='none', cmap='jet')\n", - "plt.title('Multi-Group Fission Rates')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "These figures really indicate that more histories are probably necessary when trying to achieve a fully converged solution, but hey, this is good enough for our example!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Scattering Anisotropy Treatments\n", - "\n", - "We will next show how we can work with the scattering angular distributions. OpenMC's MG solver has the capability to use group-to-group angular distributions which are represented as any of the following: a truncated Legendre series of up to the 10th order, a histogram distribution, and a tabular distribution. Any combination of these representations can be used by OpenMC during the transport process, so long as all constituents of a given material use the same representation. This means it is possible to have water represented by a tabular distribution and fuel represented by a Legendre if so desired.\n", - "\n", - "*Note*: To have the highest runtime performance OpenMC natively converts Legendre series to a tabular distribution before the transport begins. This default functionality can be turned off with the `tabular_legendre` element of the `settings.xml` file (or for the Python API, the `openmc.Settings.tabular_legendre` attribute).\n", - "\n", - "This section will examine the following:\n", - "- Re-run the MG-mode calculation with P0 scattering everywhere using the `openmc.Settings.max_order` attribute\n", - "- Re-run the problem with only the water represented with P3 scattering and P0 scattering for the remaining materials using the Python API's ability to convert between formats." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Global P0 Scattering\n", - "First we begin by re-running with P0 scattering (i.e., isotropic) everywhere. If a global maximum order is requested, the most effective way to do this is to use the `max_order` attribute of our `openmc.Settings` object." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [], - "source": [ - "# Set the maximum scattering order to 0 (i.e., isotropic scattering)\n", - "settings_file.max_order = 0\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can re-run OpenMC to obtain our results" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2018 Massachusetts Institute of Technology\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.10.0\n", - " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", - " Date/Time | 2018-04-22 15:04:39\n", - " OpenMP Threads | 8\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.16379 +/- 0.00090\n", - " k-effective (Track-length) = 1.16469 +/- 0.00101\n", - " k-effective (Absorption) = 1.16315 +/- 0.00052\n", - " Combined k-effective = 1.16335 +/- 0.00050\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run the Multi-Group OpenMC Simulation\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And then get the eigenvalue differences from the Continuous-Energy and P3 MG solution" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "P3 bias [pcm]: -20.4\n", - "P0 bias [pcm]: 125.1\n" - ] - } - ], - "source": [ - "# Move the statepoint File\n", - "mgp0_spfile = './statepoint_mg_p0.h5'\n", - "os.rename('statepoint.' + str(batches) + '.h5', mgp0_spfile)\n", - "# Move the Summary file\n", - "mgp0_sumfile = './summary_mg_p0.h5'\n", - "os.rename('summary.h5', mgp0_sumfile)\n", - "\n", - "# Load the last statepoint file and keff value\n", - "mgsp_p0 = openmc.StatePoint(mgp0_spfile, autolink=False)\n", - "\n", - "# Get keff\n", - "mg_p0_keff = mgsp_p0.k_combined\n", - "\n", - "bias_p0 = 1.0E5 * (ce_keff - mg_p0_keff)\n", - "\n", - "print('P3 bias [pcm]: {0:1.1f}'.format(bias.nominal_value))\n", - "print('P0 bias [pcm]: {0:1.1f}'.format(bias_p0.nominal_value))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mixed Scattering Representations\n", - "OpenMC's Multi-Group mode also includes a feature where not every data in the library is required to have the same scattering treatment. For example, we could represent the water with P3 scattering, and the fuel and cladding with P0 scattering. This series will show how this can be done.\n", - "\n", - "First we will convert the data to P0 scattering, unless its water, then we will leave that as P3 data." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [], - "source": [ - "# Convert the zircaloy and fuel data to P0 scattering\n", - "for i, xsdata in enumerate(mgxs_file.xsdatas):\n", - " if xsdata.name != 'water':\n", - " mgxs_file.xsdatas[i] = xsdata.convert_scatter_format('legendre', 0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also use whatever scattering format that we want for the materials in the library. As an example, we will take this P0 data and convert zircaloy to a histogram anisotropic scattering format and the fuel to a tabular anisotropic scattering format" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "# Convert the formats as discussed\n", - "for i, xsdata in enumerate(mgxs_file.xsdatas):\n", - " if xsdata.name == 'zircaloy':\n", - " mgxs_file.xsdatas[i] = xsdata.convert_scatter_format('histogram', 2)\n", - " elif xsdata.name == 'fuel':\n", - " mgxs_file.xsdatas[i] = xsdata.convert_scatter_format('tabular', 2)\n", - " \n", - "mgxs_file.export_to_hdf5('mgxs.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally we will re-set our `max_order` parameter of our `openmc.Settings` object to our maximum order so that OpenMC will use whatever scattering data is available in the library.\n", - "\n", - "After we do this we can re-run the simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2018 Massachusetts Institute of Technology\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.10.0\n", - " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", - " Date/Time | 2018-04-22 15:05:16\n", - " OpenMP Threads | 8\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.16471 +/- 0.00093\n", - " k-effective (Track-length) = 1.16412 +/- 0.00106\n", - " k-effective (Absorption) = 1.16449 +/- 0.00050\n", - " Combined k-effective = 1.16441 +/- 0.00049\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "settings_file.max_order = None\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()\n", - "\n", - "# Run the Multi-Group OpenMC Simulation\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For a final step we can again obtain the eigenvalue differences from this case and compare with the same from the P3 MG solution" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "P3 bias [pcm]: -20.4\n", - "Mixed Scattering bias [pcm]: 19.5\n" - ] - } - ], - "source": [ - "# Load the last statepoint file and keff value\n", - "mgsp_mixed = openmc.StatePoint('./statepoint.' + str(batches) + '.h5')\n", - "\n", - "mg_mixed_keff = mgsp_mixed.k_combined\n", - "bias_mixed = 1.0E5 * (ce_keff - mg_mixed_keff)\n", - "\n", - "print('P3 bias [pcm]: {0:1.1f}'.format(bias.nominal_value))\n", - "print('Mixed Scattering bias [pcm]: {0:1.1f}'.format(bias_mixed.nominal_value))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Our tests in this section showed the flexibility of data formatting within OpenMC's multi-group mode: every material can be represented with its own format with the approximations that make the most sense. Now, as you'll see above, the runtimes from our P3, P0, and mixed cases are not significantly different and therefore this might not be a useful strategy for multi-group Monte Carlo. However, this capability provides a useful benchmark for the accuracy hit one may expect due to these scattering approximations before implementing this generality in a deterministic solver where the runtime savings are more significant.\n", - "\n", - "**NOTE**: The biases obtained above with P3, P0, and mixed representations do not necessarily reflect the inherent accuracies of the options. These cases were *not* run with a sufficient number of histories to truly differentiate methods improvement from statistical noise." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.7" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mg-mode-part-iii.ipynb b/examples/jupyter/mg-mode-part-iii.ipynb deleted file mode 100644 index e953d64d3..000000000 --- a/examples/jupyter/mg-mode-part-iii.ipynb +++ /dev/null @@ -1,1425 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This Notebook illustrates the use of the the more advanced features of OpenMC's multi-group mode and the openmc.mgxs.Library class. During this process, this notebook will illustrate the following features:\n", - "\n", - " - Calculation of multi-group cross sections for a simplified BWR 8x8 assembly with isotropic and angle-dependent MGXS.\n", - " - Automated creation and storage of MGXS with openmc.mgxs.Library\n", - " - Fission rate comparison between continuous-energy and the two multi-group OpenMC cases.\n", - "\n", - "To avoid focusing on unimportant details, the BWR assembly in this notebook is greatly simplified. The descriptions which follow will point out some areas of simplification." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import openmc\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will be running a rodded 8x8 assembly with Gadolinia fuel pins. Let's start by creating the materials that we will use later.\n", - "\n", - "Material Definition Simplifications:\n", - "\n", - "- This model will be run at room temperature so the NNDC ENDF-B/VII.1 data set can be used but the water density will be representative of a module with around 20% voiding. This water density will be non-physically used in all regions of the problem.\n", - "- Steel is composed of more than just iron, but we will only treat it as such here." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "materials = {}\n", - "\n", - "# Fuel\n", - "materials['Fuel'] = openmc.Material(name='Fuel')\n", - "materials['Fuel'].set_density('g/cm3', 10.32)\n", - "materials['Fuel'].add_element('O', 2)\n", - "materials['Fuel'].add_element('U', 1, enrichment=3.)\n", - "\n", - "# Gadolinia bearing fuel\n", - "materials['Gad'] = openmc.Material(name='Gad')\n", - "materials['Gad'].set_density('g/cm3', 10.23)\n", - "materials['Gad'].add_element('O', 2)\n", - "materials['Gad'].add_element('U', 1, enrichment=3.)\n", - "materials['Gad'].add_element('Gd', .02)\n", - "\n", - "# Zircaloy\n", - "materials['Zirc2'] = openmc.Material(name='Zirc2')\n", - "materials['Zirc2'].set_density('g/cm3', 6.55)\n", - "materials['Zirc2'].add_element('Zr', 1)\n", - "\n", - "# Boiling Water\n", - "materials['Water'] = openmc.Material(name='Water')\n", - "materials['Water'].set_density('g/cm3', 0.6)\n", - "materials['Water'].add_element('H', 2)\n", - "materials['Water'].add_element('O', 1)\n", - "\n", - "# Boron Carbide for the Control Rods\n", - "materials['B4C'] = openmc.Material(name='B4C')\n", - "materials['B4C'].set_density('g/cm3', 0.7 * 2.52)\n", - "materials['B4C'].add_element('B', 4)\n", - "materials['B4C'].add_element('C', 1)\n", - "\n", - "# Steel \n", - "materials['Steel'] = openmc.Material(name='Steel')\n", - "materials['Steel'].set_density('g/cm3', 7.75)\n", - "materials['Steel'].add_element('Fe', 1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now create a Materials object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials object\n", - "materials_file = openmc.Materials(materials.values())\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. The first step is to define some constants which will be used to set our dimensions and then we can start creating the surfaces and regions for the problem, the 8x8 lattice, the rods and the control blade.\n", - "\n", - "Before proceeding let's discuss some simplifications made to the problem geometry:\n", - "- To enable the use of an equal-width mesh for running the multi-group calculations, the intra-assembly gap was increased to the same size as the pitch of the 8x8 fuel lattice\n", - "- The can is neglected\n", - "- The pin-in-water geometry for the control blade is ignored and instead the blade is a solid block of B4C\n", - "- Rounded corners are ignored\n", - "- There is no cladding for the water rod" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Set constants for the problem and assembly dimensions\n", - "fuel_rad = 0.53213\n", - "clad_rad = 0.61341\n", - "Np = 8\n", - "pin_pitch = 1.6256\n", - "length = float(Np + 2) * pin_pitch\n", - "assembly_width = length - 2. * pin_pitch\n", - "rod_thick = 0.47752 / 2. + 0.14224\n", - "rod_span = 7. * pin_pitch\n", - "\n", - "surfaces = {}\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "surfaces['Global x-'] = openmc.XPlane(0., boundary_type='reflective')\n", - "surfaces['Global x+'] = openmc.XPlane(length, boundary_type='reflective')\n", - "surfaces['Global y-'] = openmc.YPlane(0., boundary_type='reflective')\n", - "surfaces['Global y+'] = openmc.YPlane(length, boundary_type='reflective')\n", - "\n", - "# Create cylinders for the fuel and clad\n", - "surfaces['Fuel Radius'] = openmc.ZCylinder(r=fuel_rad)\n", - "surfaces['Clad Radius'] = openmc.ZCylinder(r=clad_rad)\n", - "\n", - "surfaces['Assembly x-'] = openmc.XPlane(pin_pitch)\n", - "surfaces['Assembly x+'] = openmc.XPlane(length - pin_pitch)\n", - "surfaces['Assembly y-'] = openmc.YPlane(pin_pitch)\n", - "surfaces['Assembly y+'] = openmc.YPlane(length - pin_pitch)\n", - "\n", - "# Set surfaces for the control blades\n", - "surfaces['Top Blade y-'] = openmc.YPlane(length - rod_thick)\n", - "surfaces['Top Blade x-'] = openmc.XPlane(pin_pitch)\n", - "surfaces['Top Blade x+'] = openmc.XPlane(rod_span)\n", - "surfaces['Left Blade x+'] = openmc.XPlane(rod_thick)\n", - "surfaces['Left Blade y-'] = openmc.YPlane(length - rod_span)\n", - "surfaces['Left Blade y+'] = openmc.YPlane(9. * pin_pitch)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now construct regions with these surfaces before we use those to create cells" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Set regions for geometry building\n", - "regions = {}\n", - "regions['Global'] = \\\n", - " (+surfaces['Global x-'] & -surfaces['Global x+'] &\n", - " +surfaces['Global y-'] & -surfaces['Global y+'])\n", - "regions['Assembly'] = \\\n", - " (+surfaces['Assembly x-'] & -surfaces['Assembly x+'] &\n", - " +surfaces['Assembly y-'] & -surfaces['Assembly y+'])\n", - "regions['Fuel'] = -surfaces['Fuel Radius']\n", - "regions['Clad'] = +surfaces['Fuel Radius'] & -surfaces['Clad Radius']\n", - "regions['Water'] = +surfaces['Clad Radius']\n", - "regions['Top Blade'] = \\\n", - " (+surfaces['Top Blade y-'] & -surfaces['Global y+']) & \\\n", - " (+surfaces['Top Blade x-'] & -surfaces['Top Blade x+'])\n", - "regions['Top Steel'] = \\\n", - " (+surfaces['Global x-'] & -surfaces['Top Blade x-']) & \\\n", - " (+surfaces['Top Blade y-'] & -surfaces['Global y+'])\n", - "regions['Left Blade'] = \\\n", - " (+surfaces['Left Blade y-'] & -surfaces['Left Blade y+']) & \\\n", - " (+surfaces['Global x-'] & -surfaces['Left Blade x+'])\n", - "regions['Left Steel'] = \\\n", - " (+surfaces['Left Blade y+'] & -surfaces['Top Blade y-']) & \\\n", - " (+surfaces['Global x-'] & -surfaces['Left Blade x+'])\n", - "regions['Corner Blade'] = \\\n", - " regions['Left Steel'] | regions['Top Steel']\n", - "regions['Water Fill'] = \\\n", - " regions['Global'] & ~regions['Assembly'] & \\\n", - " ~regions['Top Blade'] & ~regions['Left Blade'] &\\\n", - " ~regions['Corner Blade']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will begin building the 8x8 assembly. To do that we will have to build the cells and universe for each pin type (fuel, gadolinia-fuel, and water)." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "universes = {}\n", - "cells = {}\n", - "\n", - "for name, mat, in zip(['Fuel Pin', 'Gd Pin'],\n", - " [materials['Fuel'], materials['Gad']]):\n", - " universes[name] = openmc.Universe(name=name)\n", - " cells[name] = openmc.Cell(name=name)\n", - " cells[name].fill = mat\n", - " cells[name].region = regions['Fuel']\n", - " universes[name].add_cell(cells[name])\n", - " \n", - " cells[name + ' Clad'] = openmc.Cell(name=name + ' Clad')\n", - " cells[name + ' Clad'].fill = materials['Zirc2']\n", - " cells[name + ' Clad'].region = regions['Clad']\n", - " universes[name].add_cell(cells[name + ' Clad'])\n", - " \n", - " cells[name + ' Water'] = openmc.Cell(name=name + ' Water')\n", - " cells[name + ' Water'].fill = materials['Water']\n", - " cells[name + ' Water'].region = regions['Water']\n", - " universes[name].add_cell(cells[name + ' Water'])\n", - "\n", - "universes['Hole'] = openmc.Universe(name='Hole')\n", - "cells['Hole'] = openmc.Cell(name='Hole')\n", - "cells['Hole'].fill = materials['Water']\n", - "universes['Hole'].add_cell(cells['Hole'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's use this pin information to create our 8x8 assembly." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel assembly Lattice\n", - "universes['Assembly'] = openmc.RectLattice(name='Assembly')\n", - "universes['Assembly'].pitch = (pin_pitch, pin_pitch)\n", - "universes['Assembly'].lower_left = [pin_pitch, pin_pitch]\n", - "\n", - "f = universes['Fuel Pin']\n", - "g = universes['Gd Pin']\n", - "h = universes['Hole']\n", - "\n", - "lattices = [[f, f, f, f, f, f, f, f],\n", - " [f, f, f, f, f, f, f, f],\n", - " [f, f, f, g, f, g, f, f],\n", - " [f, f, g, h, h, f, g, f],\n", - " [f, f, f, h, h, f, f, f],\n", - " [f, f, g, f, f, f, g, f],\n", - " [f, f, f, g, f, g, f, f],\n", - " [f, f, f, f, f, f, f, f]]\n", - "\n", - "# Store the array of lattice universes\n", - "universes['Assembly'].universes = lattices\n", - "\n", - "cells['Assembly'] = openmc.Cell(name='Assembly')\n", - "cells['Assembly'].fill = universes['Assembly']\n", - "cells['Assembly'].region = regions['Assembly']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So far we have the rods and water within the assembly , but we still need the control blade and the water which fills the rest of the space. We will create those cells now" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# The top portion of the blade, poisoned with B4C\n", - "cells['Top Blade'] = openmc.Cell(name='Top Blade')\n", - "cells['Top Blade'].fill = materials['B4C']\n", - "cells['Top Blade'].region = regions['Top Blade']\n", - "\n", - "# The left portion of the blade, poisoned with B4C\n", - "cells['Left Blade'] = openmc.Cell(name='Left Blade')\n", - "cells['Left Blade'].fill = materials['B4C']\n", - "cells['Left Blade'].region = regions['Left Blade']\n", - "\n", - "# The top-left corner portion of the blade, with no poison\n", - "cells['Corner Blade'] = openmc.Cell(name='Corner Blade')\n", - "cells['Corner Blade'].fill = materials['Steel']\n", - "cells['Corner Blade'].region = regions['Corner Blade']\n", - "\n", - "# Water surrounding all other cells and our assembly\n", - "cells['Water Fill'] = openmc.Cell(name='Water Fill')\n", - "cells['Water Fill'].fill = materials['Water']\n", - "cells['Water Fill'].region = regions['Water Fill']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create our root universe and fill it with the cells just defined." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Universe\n", - "universes['Root'] = openmc.Universe(name='root universe', universe_id=0)\n", - "universes['Root'].add_cells([cells['Assembly'], cells['Top Blade'],\n", - " cells['Corner Blade'], cells['Left Blade'],\n", - " cells['Water Fill']])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What do you do after you create your model? Check it! We will use the plotting capabilities of the Python API to do this for us.\n", - "\n", - "When doing so, we will coloring by material with fuel being red, gadolinia-fuel as yellow, zirc cladding as a light grey, water as blue, B4C as black and steel as a darker gray." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "universes['Root'].plot(origin=(length / 2., length / 2., 0.),\n", - " pixels=(500, 500), width=(length, length),\n", - " color_by='material',\n", - " colors={materials['Fuel']: (1., 0., 0.),\n", - " materials['Gad']: (1., 1., 0.),\n", - " materials['Zirc2']: (0.5, 0.5, 0.5),\n", - " materials['Water']: (0.0, 0.0, 1.0),\n", - " materials['B4C']: (0.0, 0.0, 0.0),\n", - " materials['Steel']: (0.4, 0.4, 0.4)})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Looks pretty good to us!\n", - "\n", - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root universe\n", - "geometry = openmc.Geometry(universes['Root'])\n", - "\n", - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters, including how to run the model and what we want to learn from the model (i.e., define the tallies). We will start with our simulation parameters in the next block.\n", - "\n", - "This will include setting the run strategy, telling OpenMC not to bother creating a `tallies.out` file, and limiting the verbosity of our output to just the header and results to not clog up our notebook with results from each batch." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 1000\n", - "inactive = 20\n", - "particles = 1000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': False}\n", - "settings_file.verbosity = 4\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [pin_pitch, pin_pitch, 10, length - pin_pitch, length - pin_pitch, 10]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Create an MGXS Library\n", - "\n", - "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in EnergyGroups class." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 2-group EnergyGroups object\n", - "groups = openmc.mgxs.EnergyGroups()\n", - "groups.group_edges = np.array([0., 0.625, 20.0e6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we will instantiate an openmc.mgxs.Library for the energy groups with our the problem geometry. This library will use the default setting of isotropically-weighting the multi-group cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize a 2-group Isotropic MGXS Library for OpenMC\n", - "iso_mgxs_lib = openmc.mgxs.Library(geometry)\n", - "iso_mgxs_lib.energy_groups = groups" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we must specify to the Library which types of cross sections to compute. OpenMC's multi-group mode can accept isotropic flux-weighted cross sections or angle-dependent cross sections, as well as supporting anisotropic scattering represented by either Legendre polynomials, histogram, or tabular angular distributions. \n", - "\n", - "Just like before, we will create the following multi-group cross sections needed to run an OpenMC simulation to verify the accuracy of our cross sections: \"total\", \"absorption\", \"nu-fission\", '\"fission\", \"nu-scatter matrix\", \"multiplicity matrix\", and \"chi\".\n", - "\"multiplicity matrix\" is needed to provide OpenMC's multi-group mode with additional information needed to accurately treat scattering multiplication (i.e., (n,xn) reactions)) explicitly." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Specify multi-group cross section types to compute\n", - "iso_mgxs_lib.mgxs_types = ['total', 'absorption', 'nu-fission', 'fission',\n", - " 'nu-scatter matrix', 'multiplicity matrix', 'chi']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we must specify the type of domain over which we would like the `Library` to compute multi-group cross sections. The domain type corresponds to the type of tally filter to be used in the tallies created to compute multi-group cross sections. At the present time, the `Library` supports \"material\" \"cell\", \"universe\", and \"mesh\" domain types. \n", - "\n", - "For the sake of example we will use a mesh to gather our cross sections. This mesh will be set up so there is one mesh bin for every pin cell." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a tally Mesh\n", - "mesh = openmc.RegularMesh()\n", - "mesh.dimension = [10, 10]\n", - "mesh.lower_left = [0., 0.]\n", - "mesh.upper_right = [length, length]\n", - "\n", - "# Specify a \"mesh\" domain type for the cross section tally filters\n", - "iso_mgxs_lib.domain_type = \"mesh\"\n", - "\n", - "# Specify the mesh over which to compute multi-group cross sections\n", - "iso_mgxs_lib.domains = [mesh]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we will set the scattering treatment that we wish to use.\n", - "\n", - "In the [mg-mode-part-ii](mg-mode-part-ii.html) notebook, the cross sections were generated with a typical P3 scattering expansion in mind. Now, however, we will use a more advanced technique: OpenMC will directly provide us a histogram of the change-in-angle (i.e., $\\mu$) distribution.\n", - "\n", - "Where as in the [mg-mode-part-ii](mg-mode-part-ii.html) notebook, all that was required was to set the `legendre_order` attribute of `mgxs_lib`, here we have only slightly more work: we have to tell the Library that we want to use a histogram distribution (as it is not the default), and then tell it the number of bins.\n", - "\n", - "For this problem we will use 11 bins." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# Set the scattering format to histogram and then define the number of bins\n", - "\n", - "# Avoid a warning that corrections don't make sense with histogram data\n", - "iso_mgxs_lib.correction = None\n", - "# Set the histogram data\n", - "iso_mgxs_lib.scatter_format = 'histogram'\n", - "iso_mgxs_lib.histogram_bins = 11" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Ok, we made our isotropic library with histogram-scattering!\n", - "\n", - "Now why don't we go ahead and create a library to do the same, but with angle-dependent MGXS. That is, we will avoid making the isotropic flux weighting approximation and instead just store a cross section for every polar and azimuthal angle pair.\n", - "\n", - "To do this with the Python API and OpenMC, all we have to do is set the number of polar and azimuthal bins. Here we only need to set the number of bins, the API will convert all of angular space into equal-width bins for us.\n", - "\n", - "Since this problem is symmetric in the z-direction, we only need to concern ourselves with the azimuthal variation here. We will use eight angles.\n", - "\n", - "Ok, we will repeat all the above steps for a new library object, but will also set the number of azimuthal bins at the end." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "# Let's repeat all of the above for an angular MGXS library so we can gather\n", - "# that in the same continuous-energy calculation\n", - "angle_mgxs_lib = openmc.mgxs.Library(geometry)\n", - "angle_mgxs_lib.energy_groups = groups\n", - "angle_mgxs_lib.mgxs_types = ['total', 'absorption', 'nu-fission', 'fission',\n", - " 'nu-scatter matrix', 'multiplicity matrix', 'chi']\n", - "\n", - "angle_mgxs_lib.domain_type = \"mesh\"\n", - "angle_mgxs_lib.domains = [mesh]\n", - "angle_mgxs_lib.correction = None\n", - "angle_mgxs_lib.scatter_format = 'histogram'\n", - "angle_mgxs_lib.histogram_bins = 11\n", - "\n", - "# Set the angular bins to 8\n", - "angle_mgxs_lib.num_azimuthal = 8" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that our libraries have been setup, let's make sure they contain the types of cross sections which meet the needs of OpenMC's multi-group solver. Note that this step is done automatically when writing the Multi-Group Library file later in the process (as part of the `mgxs_lib.write_mg_library()`), but it is a good practice to also run this before spending all the time running OpenMC to generate the cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "# Check the libraries - if no errors are raised, then the library is satisfactory.\n", - "iso_mgxs_lib.check_library_for_openmc_mgxs()\n", - "angle_mgxs_lib.check_library_for_openmc_mgxs()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lastly, we use our two `Library` objects to construct the tallies needed to compute all of the requested multi-group cross sections in each domain.\n", - "\n", - "We expect a warning here telling us that the default Legendre order is not meaningful since we are using histogram scattering." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mgxs/mgxs.py:4144: UserWarning: The legendre order will be ignored since the scatter format is set to histogram\n", - " warnings.warn(msg)\n" - ] - } - ], - "source": [ - "# Construct all tallies needed for the multi-group cross section library\n", - "iso_mgxs_lib.build_library()\n", - "angle_mgxs_lib.build_library()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The tallies within the libraries can now be exported to a \"tallies.xml\" input file for OpenMC." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "iso_mgxs_lib.add_to_tallies_file(tallies_file, merge=True)\n", - "angle_mgxs_lib.add_to_tallies_file(tallies_file, merge=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition, we instantiate a fission rate mesh tally for eventual comparison of results." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=1.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=11.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=21.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=22.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=12.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=18.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Instantiate tally Filter\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='mesh tally')\n", - "tally.filters = [mesh_filter]\n", - "tally.scores = ['fission']\n", - "\n", - "# Add tally to collection\n", - "tallies_file.append(tally, merge=True)\n", - "\n", - "# Export all tallies to a \"tallies.xml\" file\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "Time to run the calculation and get our results!" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | ed7123f4e7ce7b097c4b2bfb0ef5283eaa8afaea\n", - " Date/Time | 2019-10-04 10:54:35\n", - " OpenMP Threads | 4\n", - "\n", - " Minimum neutron data temperature: 294.000000 K\n", - " Maximum neutron data temperature: 294.000000 K\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 0.83866 +/- 0.00102\n", - " k-effective (Track-length) = 0.83799 +/- 0.00118\n", - " k-effective (Absorption) = 0.83968 +/- 0.00103\n", - " Combined k-effective = 0.83900 +/- 0.00085\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make the files available and not be over-written when running the multi-group calculation, we will now rename the statepoint and summary files." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], - "source": [ - "# Move the StatePoint File\n", - "ce_spfile = './statepoint_ce.h5'\n", - "os.rename('statepoint.' + str(batches) + '.h5', ce_spfile)\n", - "# Move the Summary file\n", - "ce_sumfile = './summary_ce.h5'\n", - "os.rename('summary.h5', ce_sumfile)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tally Data Processing\n", - "\n", - "Our simulation ran successfully and created statepoint and summary output files. Let's begin by loading the StatePoint file, but not automatically linking the summary file." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the statepoint file, but not the summary file, as it is a different filename than expected.\n", - "sp = openmc.StatePoint(ce_spfile, autolink=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the `openmc.Library` to properly process the tally data. We first create a `Summary` object and link it with the statepoint. Normally this would not need to be performed, but since we have renamed our summary file to avoid conflicts with the Multi-Group calculation's summary file, we will load this in explicitly." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "su = openmc.Summary(ce_sumfile)\n", - "sp.link_with_summary(su)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed. To create our libraries we simply have to load the tallies from the statepoint into each `Library` and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize MGXS Library with OpenMC statepoint data\n", - "iso_mgxs_lib.load_from_statepoint(sp)\n", - "angle_mgxs_lib.load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step will be to prepare the input for OpenMC to use our newly created multi-group data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Isotropic Multi-Group OpenMC Calculation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now use the `Library` to produce the isotropic multi-group cross section data set for use by the OpenMC multi-group solver. \n", - "\n", - "If the model to be run in multi-group mode is the same as the continuous-energy mode, the `openmc.mgxs.Library` class has the ability to directly create the multi-group geometry, materials, and multi-group library for us. \n", - "Note that this feature is only useful if the MG model is intended to replicate the CE geometry - it is not useful if the CE library is not the same geometry (like it would be for generating MGXS from a generic spectral region).\n", - "\n", - "This method creates and assigns the materials automatically, including creating a geometry which is equivalent to our mesh cells for which the cross sections were derived." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Allow the API to create our Library, materials, and geometry file\n", - "iso_mgxs_file, materials_file, geometry_file = iso_mgxs_lib.create_mg_mode()\n", - "\n", - "# Tell the materials file what we want to call the multi-group library\n", - "materials_file.cross_sections = 'mgxs.h5'\n", - "\n", - "# Write our newly-created files to disk\n", - "iso_mgxs_file.export_to_hdf5('mgxs.h5')\n", - "materials_file.export_to_xml()\n", - "geometry_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we can make the changes we need to the settings file.\n", - "These changes are limited to telling OpenMC to run a multi-group calculation and provide the location of our multi-group cross section file." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "# Set the energy mode\n", - "settings_file.energy_mode = 'multi-group'\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's clear up the tallies file so it doesn't include all the extra tallies for re-generating a multi-group library" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "\n", - "# Add our fission rate mesh tally\n", - "tallies_file.append(tally)\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before running the calculation let's look at our meshed model. It might not be interesting, but let's take a look anyways." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "geometry_file.root_universe.plot(origin=(length / 2., length / 2., 0.),\n", - " pixels=(300, 300), width=(length, length),\n", - " color_by='material')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, we see a 10x10 grid with a different color for every material, sounds good!\n", - "\n", - "At this point, the problem is set up and we can run the multi-group calculation." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | ed7123f4e7ce7b097c4b2bfb0ef5283eaa8afaea\n", - " Date/Time | 2019-10-04 10:56:58\n", - " OpenMP Threads | 4\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 0.82471 +/- 0.00104\n", - " k-effective (Track-length) = 0.82466 +/- 0.00103\n", - " k-effective (Absorption) = 0.82482 +/- 0.00075\n", - " Combined k-effective = 0.82477 +/- 0.00068\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Execute the Isotropic MG OpenMC Run\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we go the angle-dependent case, let's save the StatePoint and Summary files so they don't get over-written" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "# Move the StatePoint File\n", - "iso_mg_spfile = './statepoint_mg_iso.h5'\n", - "os.rename('statepoint.' + str(batches) + '.h5', iso_mg_spfile)\n", - "# Move the Summary file\n", - "iso_mg_sumfile = './summary_mg_iso.h5'\n", - "os.rename('summary.h5', iso_mg_sumfile)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Angle-Dependent Multi-Group OpenMC Calculation\n", - "\n", - "Let's now run the calculation with the angle-dependent multi-group cross sections. This process will be the exact same as above, except this time we will use the angle-dependent Library as our starting point.\n", - "\n", - "We do not need to re-write the materials, geometry, or tallies file to disk since they are the same as for the isotropic case." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Let's repeat for the angle-dependent case\n", - "angle_mgxs_lib.load_from_statepoint(sp)\n", - "angle_mgxs_file, materials_file, geometry_file = angle_mgxs_lib.create_mg_mode()\n", - "angle_mgxs_file.export_to_hdf5()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, the problem is set up and we can run the multi-group calculation." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | ed7123f4e7ce7b097c4b2bfb0ef5283eaa8afaea\n", - " Date/Time | 2019-10-04 10:57:24\n", - " OpenMP Threads | 4\n", - "\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 0.83564 +/- 0.00103\n", - " k-effective (Track-length) = 0.83572 +/- 0.00104\n", - " k-effective (Absorption) = 0.83478 +/- 0.00073\n", - " Combined k-effective = 0.83504 +/- 0.00066\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Execute the angle-dependent OpenMC Run\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Results Comparison\n", - "In this section we will compare the eigenvalues and fission rate distributions of the continuous-energy, isotropic multi-group and angle-dependent multi-group cases.\n", - "\n", - "We will begin by loading the multi-group statepoint files, first the isotropic, then angle-dependent. The angle-dependent was not renamed, so we can autolink its summary." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the isotropic statepoint file\n", - "iso_mgsp = openmc.StatePoint(iso_mg_spfile, autolink=False)\n", - "iso_mgsum = openmc.Summary(iso_mg_sumfile)\n", - "iso_mgsp.link_with_summary(iso_mgsum)\n", - "\n", - "# Load the angle-dependent statepoint file\n", - "angle_mgsp = openmc.StatePoint('statepoint.' + str(batches) + '.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Eigenvalue Comparison\n", - "Next, we can load the eigenvalues for comparison and do that comparison" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "ce_keff = sp.k_combined\n", - "iso_mg_keff = iso_mgsp.k_combined\n", - "angle_mg_keff = angle_mgsp.k_combined\n", - "\n", - "# Find eigenvalue bias\n", - "iso_bias = 1.0e5 * (ce_keff - iso_mg_keff)\n", - "angle_bias = 1.0e5 * (ce_keff - angle_mg_keff)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's compare the eigenvalues in units of pcm" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Isotropic to CE Bias [pcm]: 1423.5\n", - "Angle to CE Bias [pcm]: 396.6\n" - ] - } - ], - "source": [ - "print('Isotropic to CE Bias [pcm]: {0:1.1f}'.format(iso_bias.nominal_value))\n", - "print('Angle to CE Bias [pcm]: {0:1.1f}'.format(angle_bias.nominal_value))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see a large reduction in error by switching to the usage of angle-dependent multi-group cross sections! \n", - "\n", - "Of course, this rodded and partially voided BWR problem was chosen specifically to exacerbate the angular variation of the reaction rates (and thus cross sections). Such improvements should not be expected in every case, especially if localized absorbers are not present.\n", - "\n", - "It is important to note that both eigenvalues can be improved by the application of finer geometric or energetic discretizations, but this shows that the angle discretization may be a factor for consideration.\n", - "\n", - "## Fission Rate Distribution Comparison\n", - "Next we will visualize the mesh tally results obtained from our three cases.\n", - "\n", - "This will be performed by first obtaining the one-group fission rate tally information from our state point files. After we have this information we will re-shape the data to match the original mesh laydown. We will then normalize, and finally create side-by-side plots of all." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "sp_files = [sp, iso_mgsp, angle_mgsp]\n", - "titles = ['Continuous-Energy', 'Isotropic Multi-Group',\n", - " 'Angle-Dependent Multi-Group']\n", - "fiss_rates = []\n", - "fig = plt.figure(figsize=(12, 6))\n", - "for i, (case, title) in enumerate(zip(sp_files, titles)):\n", - " # Get our mesh tally information\n", - " mesh_tally = case.get_tally(name='mesh tally')\n", - " fiss_rates.append(mesh_tally.get_values(scores=['fission']))\n", - " \n", - " # Reshape the array\n", - " fiss_rates[-1].shape = mesh.dimension\n", - " \n", - " # Normalize the fission rates\n", - " fiss_rates[-1] /= np.mean(fiss_rates[-1][fiss_rates[-1] > 0.])\n", - " \n", - " # Set 0s to NaNs so they show as white\n", - " fiss_rates[-1][fiss_rates[-1] == 0.] = np.nan\n", - "\n", - " fig = plt.subplot(1, len(titles), i + 1)\n", - " # Plot only the fueled regions\n", - " plt.imshow(fiss_rates[-1][1:-1, 1:-1], cmap='jet', origin='lower',\n", - " vmin=0.4, vmax=4.)\n", - " plt.title(title + '\\nFission Rates')" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "With this colormap, dark blue is the lowest power and dark red is the highest power.\n", - "\n", - "We see general agreement between the fission rate distributions, but it looks like there may be less of a gradient near the rods in the continuous-energy and angle-dependent MGXS cases than in the isotropic MGXS case. \n", - "\n", - "To better see the differences, let's plot ratios of the fission powers for our two multi-group cases compared to the continuous-energy case t" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Calculate and plot the ratios of MG to CE for each of the 2 MG cases\n", - "ratios = []\n", - "fig, axes = plt.subplots(figsize=(12, 6), nrows=1, ncols=2)\n", - "for i, (case, title, axis) in enumerate(zip(sp_files[1:], titles[1:], axes.flat)):\n", - " # Get our ratio relative to the CE (in fiss_ratios[0])\n", - " ratios.append(np.divide(fiss_rates[i + 1], fiss_rates[0]))\n", - " \n", - " # Plot only the fueled regions\n", - " im = axis.imshow(ratios[-1][1:-1, 1:-1], cmap='bwr', origin='lower',\n", - " vmin = 0.9, vmax = 1.1)\n", - " axis.set_title(title + '\\nFission Rates Relative\\nto Continuous-Energy')\n", - " \n", - "# Add a color bar\n", - "fig.subplots_adjust(right=0.8)\n", - "cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])\n", - "fig.colorbar(im, cax=cbar_ax)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With this ratio its clear that the errors are significantly worse in the isotropic case. These errors are conveniently located right where the most anisotropy is espected: by the control blades and by the Gd-bearing pins!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mgxs-part-i.ipynb b/examples/jupyter/mgxs-part-i.ipynb deleted file mode 100644 index 264f8967c..000000000 --- a/examples/jupyter/mgxs-part-i.ipynb +++ /dev/null @@ -1,1138 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This IPython Notebook introduces the use of the `openmc.mgxs` module to calculate multi-group cross sections for an infinite homogeneous medium. In particular, this Notebook introduces the the following features:\n", - "\n", - "* **General equations** for scalar-flux averaged multi-group cross sections\n", - "* Creation of multi-group cross sections for an **infinite homogeneous medium**\n", - "* Use of **tally arithmetic** to manipulate multi-group cross sections" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Introduction to Multi-Group Cross Sections (MGXS)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Many Monte Carlo particle transport codes, including OpenMC, use continuous-energy nuclear cross section data. However, most deterministic neutron transport codes use *multi-group cross sections* defined over discretized energy bins or *energy groups*. An example of U-235's continuous-energy fission cross section along with a 16-group cross section computed for a light water reactor spectrum is displayed below." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\ncdttt+F//ud/nOZ5//33YTab8cYbb+Dxxx9HTEwMWrZsiW+++QaAfReJ3r17o2XLlrj99tthtVox\nbdo0dO/eHQCglEKvXr0wevRol9e32Wxo1aoV5s6d6/PyerIMM2bMwPXr15GVleXy+PXr11fOQ0QU\nLLhlmohIg7KyMpSVlTlNM5lMLluId+7ciX/84x/4/e9/j7CwMKxcuRLjx4/Hl19+WTnIPXbsGIYO\nHYpu3brhv//7v9G+fXvs3r0bjz32GPLy8rBkyRKn51y8eDGGDh2KNWvWwGw2o127dlizZg3+7d/+\nDf/yL/+CVatWobCwEBkZGbh+/TpMJlNl37x587BgwQJ8/fXX6NmzZ+Vzbty4EcXFxT4Ppj1dhvvu\nuw9du3bFa6+95vRa5eXl2LRpE+Lj42vcfYaIyDCKiIj8Zv369cpkMtV4a9asmdO8JpNJdejQQdls\ntspply5dUk2aNFHPP/985bT7779fdenSRRUXFzs9ft68eSokJEQVFhYqpZR67733lMlkUiNGjHCa\nr7y8XLVv317Fx8c7TT937pxq3ry56t69e+W0oqIiFRERodLT053mve2229R9991X67KfPn1amUwm\n9frrr7vcV9cyXLlypXJaRkaGMplM6tChQ5XTduzYoUwmk3r11VdrfO27775bxcXF1dpHRKQDd/Mg\nItJg06ZN+Mc//uF0O3DggMt899xzD8LCwip/jo6ORnR0NM6dOwcAuHbtGv73f/8X48ePR8uWLSu3\neJeVlWHMmDG4du0aPv74Y6fn/NWvfuX085dffolLly5h4sSJTtM7d+6MhIQEp2kWiwXTpk3Dhg0b\ncPXqVQDA3//+dxw/ftznrdLeLkNaWhrMZjNee+21ymnr169HeHg4HnroIZ8aiIh04WCaiEiD2NhY\n3HHHHU63QYMGuczXpk0bl2ktWrTAjz/+CADIz89HeXk5Vq9ejebNmzvdkpKSYDKZkJeX5/T4Dh06\nOP2cn58PALjllltcXis6Otpl2rx581BUVFS53/KLL76ILl264MEHH/Rw6Z15sgyORsA+yB85ciT+\n/Oc/o7S0FHl5edixYwdSUlKcfvEgIgoG3GeaiCiIRUVFoUmTJpg6dSoeffTRGufp1q2b08+OfaAd\nHAP277//3uWxNU3r2bMnxowZg5deegmjR49GTk4Oli9f7vK8OpdhxowZ2LNnD7Kzs3HhwgWUlZVh\n+vTpPr0+EZFOHEwTEQWx0NBQ3HPPPcjNzUVcXByaNWvm9XP07dsX7du3x1/+8hcsWLCgcvq5c+ew\nf/9+dOrUyeUx8+fPx/33349//dd/RfPmzTFr1qyALsO4cePQpk0bvPbaa7h48SL69OnjsksKEVEw\n4GCaiEiDI0eO4MaNGy7Te/bsibZt29b6WFXtWlqrVq3CsGHDMHz4cMyePRtdu3ZFcXExvv76a+zY\nsQN///vfa30+k8mEjIwMPPLII0hJSUFaWhoKCwuxfPlydOzYEWaz6x5/o0aNQmxsLN5//31MmTKl\nzua6eLsMzZo1w69//WusWrUKALBixYp6vT4RkS4cTBMR+ZFjV4i0tLQa71u7dm2duytU350iNjYW\nubm5WL58OX73u9/hhx9+QGRkJHr37o2xY8fW+liHWbNmwWQyYeXKlZgwYQK6d++O3/72t8jOzsb5\n8+drfMzEiRORkZFRr3NL+7IMDjNmzMCqVavQtGlTTJ06td4NREQ68HLiRESNVGFhIXr37o0JEybg\nT3/6k8v9d955J5o1a+ZythB3HJcTX7duHaZMmYKmTfVvr1FKoby8HPfddx8KCgpw5MgR7a9JRFQV\nz+ZBRNQIXLp0CfPmzcP27dvxf//3f9i4cSPuuecelJSUYP78+ZXzFRcXY//+/XjyySdx6NAhPPnk\nk16/1owZM9C8eXNs377dn4tQo/Hjx6N58+b48MMPfT5AkoioPrhlmoioESgsLMTUqVPx6aefoqCg\nAKGhoYiPj0dGRgYGDx5cOd/777+Pe++9F23btsXcuXNdrq5Ym9LSUqctw7feeisiIyP9uhzVnTp1\nCoWFhQCAkJAQxMbGan09IqLqOJgmIiIiIvIRd/MgIiIiIvIRB9NERERERD7iYJqIiIiIyEccTBMR\nERER+YiDaSIiIiIiH3EwTURERETkIw6miYiIiIh8xME0EREREZGPOJgmIiIiIvLR/wcwWUbzha5y\njwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": { - "image/png": { - "width": 350 - } - }, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import Image\n", - "Image(filename='images/mgxs.png', width=350)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A variety of tools employing different methodologies have been developed over the years to compute multi-group cross sections for certain applications, including NJOY (LANL), MC$^2$-3 (ANL), and Serpent (VTT). The `openmc.mgxs` Python module is designed to leverage OpenMC's tally system to calculate multi-group cross sections with arbitrary energy discretizations for fine-mesh heterogeneous deterministic neutron transport applications.\n", - "\n", - "Before proceeding to illustrate how one may use the `openmc.mgxs` module, it is worthwhile to define the general equations used to calculate multi-group cross sections. This is only intended as a brief overview of the methodology used by `openmc.mgxs` - we refer the interested reader to the large body of literature on the subject for a more comprehensive understanding of this complex topic." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Introductory Notation\n", - "The continuous real-valued microscopic cross section may be denoted $\\sigma_{n,x}(\\mathbf{r}, E)$ for position vector $\\mathbf{r}$, energy $E$, nuclide $n$ and interaction type $x$. Similarly, the scalar neutron flux may be denoted by $\\Phi(\\mathbf{r},E)$ for position $\\mathbf{r}$ and energy $E$. **Note**: Although nuclear cross sections are dependent on the temperature $T$ of the interacting medium, the temperature variable is neglected here for brevity." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Spatial and Energy Discretization\n", - "The energy domain for critical systems such as thermal reactors spans more than 10 orders of magnitude of neutron energies from 10$^{-5}$ - 10$^7$ eV. The multi-group approximation discretization divides this energy range into one or more energy groups. In particular, for $G$ total groups, we denote an energy group index $g$ such that $g \\in \\{1, 2, ..., G\\}$. The energy group indices are defined such that the smaller group the higher the energy, and vice versa. The integration over neutron energies across a discrete energy group is commonly referred to as **energy condensation**.\n", - "\n", - "Multi-group cross sections are computed for discretized spatial zones in the geometry of interest. The spatial zones may be defined on a structured and regular fuel assembly or pin cell mesh, an arbitrary unstructured mesh or the constructive solid geometry used by OpenMC. For a geometry with $K$ distinct spatial zones, we designate each spatial zone an index $k$ such that $k \\in \\{1, 2, ..., K\\}$. The volume of each spatial zone is denoted by $V_{k}$. The integration over discrete spatial zones is commonly referred to as **spatial homogenization**." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### General Scalar-Flux Weighted MGXS\n", - "The multi-group cross sections computed by `openmc.mgxs` are defined as a *scalar flux-weighted average* of the microscopic cross sections across each discrete energy group. This formulation is employed in order to preserve the reaction rates within each energy group and spatial zone. In particular, spatial homogenization and energy condensation are used to compute the general multi-group cross section $\\sigma_{n,x,k,g}$ as follows:\n", - "\n", - "$$\\sigma_{n,x,k,g} = \\frac{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\sigma_{n,x}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n", - "\n", - "This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for most multi-group cross sections, including total, absorption, and fission reaction types. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](http://openmc.readthedocs.io/en/latest/usersguide/tallies.html#filters) on the energy range and spatial zone (material, cell or universe) define the bounds of integration for both numerator and denominator." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Multi-Group Scattering Matrices\n", - "The general multi-group cross section $\\sigma_{n,x,k,g}$ is a vector of $G$ values for each energy group $g$. The equation presented above only discretizes the energy of the incoming neutron and neglects the outgoing energy of the neutron (if any). Hence, this formulation must be extended to account for the outgoing energy of neutrons in the discretized scattering matrix cross section used by deterministic neutron transport codes. \n", - "\n", - "We denote the incoming and outgoing neutron energy groups as $g$ and $g'$ for the microscopic scattering matrix cross section $\\sigma_{n,s}(\\mathbf{r},E)$. As before, spatial homogenization and energy condensation are used to find the multi-group scattering matrix cross section $\\sigma_{n,s,k,g \\to g'}$ as follows:\n", - "\n", - "$$\\sigma_{n,s,k,g\\rightarrow g'} = \\frac{\\int_{E_{g'}}^{E_{g'-1}}\\mathrm{d}E''\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\sigma_{n,s}(\\mathbf{r},E'\\rightarrow E'')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n", - "\n", - "This scalar flux-weighted multi-group microscopic scattering matrix is computed using OpenMC tallies with both energy in and energy out filters." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Multi-Group Fission Spectrum\n", - "The energy spectrum of neutrons emitted from fission is denoted by $\\chi_{n}(\\mathbf{r},E' \\rightarrow E'')$ for incoming and outgoing energies $E'$ and $E''$, respectively. Unlike the multi-group cross sections $\\sigma_{n,x,k,g}$ considered up to this point, the fission spectrum is a probability distribution and must sum to unity. The outgoing energy is typically much less dependent on the incoming energy for fission than for scattering interactions. As a result, it is common practice to integrate over the incoming neutron energy when computing the multi-group fission spectrum. The fission spectrum may be simplified as $\\chi_{n}(\\mathbf{r},E)$ with outgoing energy $E$.\n", - "\n", - "Unlike the multi-group cross sections defined up to this point, the multi-group fission spectrum is weighted by the fission production rate rather than the scalar flux. This formulation is intended to preserve the total fission production rate in the multi-group deterministic calculation. In order to mathematically define the multi-group fission spectrum, we denote the microscopic fission cross section as $\\sigma_{n,f}(\\mathbf{r},E)$ and the average number of neutrons emitted from fission interactions with nuclide $n$ as $\\nu_{n}(\\mathbf{r},E)$. The multi-group fission spectrum $\\chi_{n,k,g}$ is then the probability of fission neutrons emitted into energy group $g$. \n", - "\n", - "Similar to before, spatial homogenization and energy condensation are used to find the multi-group fission spectrum $\\chi_{n,k,g}$ as follows:\n", - "\n", - "$$\\chi_{n,k,g'} = \\frac{\\int_{E_{g'}}^{E_{g'-1}}\\mathrm{d}E''\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\chi_{n}(\\mathbf{r},E'\\rightarrow E'')\\nu_{n}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\nu_{n}(\\mathbf{r},E')\\sigma_{n,f}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}$$\n", - "\n", - "The fission production-weighted multi-group fission spectrum is computed using OpenMC tallies with both energy in and energy out filters.\n", - "\n", - "This concludes our brief overview on the methodology to compute multi-group cross sections. The following sections detail more concretely how users may employ the `openmc.mgxs` module to power simulation workflows requiring multi-group cross sections for downstream deterministic calculations." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import openmc\n", - "import openmc.mgxs as mgxs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We being by creating a material for the homogeneous medium." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Instantiate a Material and register the Nuclides\n", - "inf_medium = openmc.Material(name='moderator')\n", - "inf_medium.set_density('g/cc', 5.)\n", - "inf_medium.add_nuclide('H1', 0.028999667)\n", - "inf_medium.add_nuclide('O16', 0.01450188)\n", - "inf_medium.add_nuclide('U235', 0.000114142)\n", - "inf_medium.add_nuclide('U238', 0.006886019)\n", - "inf_medium.add_nuclide('Zr90', 0.002116053)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our material, we can now create a `Materials` object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Instantiate a Materials collection and export to XML\n", - "materials_file = openmc.Materials([inf_medium])\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a simple square cell with reflective boundary conditions to simulate an infinite homogeneous medium. The first step is to create the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Instantiate boundary Planes\n", - "min_x = openmc.XPlane(boundary_type='reflective', x0=-0.63)\n", - "max_x = openmc.XPlane(boundary_type='reflective', x0=0.63)\n", - "min_y = openmc.YPlane(boundary_type='reflective', y0=-0.63)\n", - "max_y = openmc.YPlane(boundary_type='reflective', y0=0.63)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now create a cell that is defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Cell\n", - "cell = openmc.Cell(cell_id=1, name='cell')\n", - "\n", - "# Register bounding Surfaces with the Cell\n", - "cell.region = +min_x & -max_x & +min_y & -max_y\n", - "\n", - "# Fill the Cell with the Material\n", - "cell.fill = inf_medium" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root universe and add our square cell to it." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Create root universe\n", - "root_universe = openmc.Universe(name='root universe', cells=[cell])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "openmc_geometry = openmc.Geometry(root_universe)\n", - "\n", - "# Export to \"geometry.xml\"\n", - "openmc_geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 50\n", - "inactive = 10\n", - "particles = 2500\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': True}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in `EnergyGroups` class." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 2-group EnergyGroups object\n", - "groups = mgxs.EnergyGroups()\n", - "groups.group_edges = np.array([0., 0.625, 20.0e6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now use the `EnergyGroups` object, along with our previously created materials and geometry, to instantiate some `MGXS` objects from the `openmc.mgxs` module. In particular, the following are subclasses of the generic and abstract `MGXS` class:\n", - "\n", - "* `TotalXS`\n", - "* `TransportXS`\n", - "* `AbsorptionXS`\n", - "* `CaptureXS`\n", - "* `FissionXS`\n", - "* `KappaFissionXS`\n", - "* `ScatterXS`\n", - "* `ScatterMatrixXS`\n", - "* `Chi`\n", - "* `ChiPrompt`\n", - "* `InverseVelocity`\n", - "* `PromptNuFissionXS`\n", - "\n", - "Of course, we are aware that the fission cross section (`FissionXS`) can sometimes be paired with the fission neutron multiplication to become $\\nu\\sigma_f$. This can be accomodated in to the `FissionXS` class by setting the `nu` parameter to `True` as shown below.\n", - "\n", - "Additionally, scattering reactions (like (n,2n)) can also be defined to take in to account the neutron multiplication to become $\\nu\\sigma_s$. This can be accomodated in the the transport (`TransportXS`), scattering (`ScatterXS`), and scattering-matrix (`ScatterMatrixXS`) cross sections types by setting the `nu` parameter to `True` as shown below.\n", - "\n", - "These classes provide us with an interface to generate the tally inputs as well as perform post-processing of OpenMC's tally data to compute the respective multi-group cross sections. In this case, let's create the multi-group total, absorption and scattering cross sections with our 2-group structure." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a few different sections\n", - "total = mgxs.TotalXS(domain=cell, groups=groups)\n", - "absorption = mgxs.AbsorptionXS(domain=cell, groups=groups)\n", - "scattering = mgxs.ScatterXS(domain=cell, groups=groups)\n", - "\n", - "# Note that if we wanted to incorporate neutron multiplication in the\n", - "# scattering cross section we would write the previous line as:\n", - "# scattering = mgxs.ScatterXS(domain=cell, groups=groups, nu=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each multi-group cross section object stores its tallies in a Python dictionary called `tallies`. We can inspect the tallies in the dictionary for our `Absorption` object as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "OrderedDict([('flux', Tally\n", - " \tID =\t1\n", - " \tName =\t\n", - " \tFilters =\tCellFilter, EnergyFilter\n", - " \tNuclides =\ttotal \n", - " \tScores =\t['flux']\n", - " \tEstimator =\ttracklength), ('absorption', Tally\n", - " \tID =\t2\n", - " \tName =\t\n", - " \tFilters =\tCellFilter, EnergyFilter\n", - " \tNuclides =\ttotal \n", - " \tScores =\t['absorption']\n", - " \tEstimator =\ttracklength)])" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "absorption.tallies" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `Absorption` object includes tracklength tallies for the 'absorption' and 'flux' scores in the 2-group structure in cell 1. Now that each `MGXS` object contains the tallies that it needs, we must add these tallies to a `Tallies` object to generate the \"tallies.xml\" input file for OpenMC." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "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", - "\n", - "# Add total tallies to the tallies file\n", - "tallies_file += total.tallies.values()\n", - "\n", - "# Add absorption tallies to the tallies file\n", - "tallies_file += absorption.tallies.values()\n", - "\n", - "# Add scattering tallies to the tallies file\n", - "tallies_file += scattering.tallies.values()\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | 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.9.0\n", - " Git SHA1 | 9b7cebf7bc34d60e0f1750c3d6cb103df11e8dc4\n", - " Date/Time | 2017-12-04 20:56:46\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings 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 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", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k \n", - " ========= ======== ==================== \n", - " 1/1 1.11184 \n", - " 2/1 1.15820 \n", - " 3/1 1.18468 \n", - " 4/1 1.17492 \n", - " 5/1 1.19645 \n", - " 6/1 1.18436 \n", - " 7/1 1.14070 \n", - " 8/1 1.15150 \n", - " 9/1 1.19202 \n", - " 10/1 1.17677 \n", - " 11/1 1.20272 \n", - " 12/1 1.21366 1.20819 +/- 0.00547\n", - " 13/1 1.15906 1.19181 +/- 0.01668\n", - " 14/1 1.14687 1.18058 +/- 0.01629\n", - " 15/1 1.14570 1.17360 +/- 0.01442\n", - " 16/1 1.13480 1.16713 +/- 0.01343\n", - " 17/1 1.17680 1.16852 +/- 0.01144\n", - " 18/1 1.16866 1.16853 +/- 0.00990\n", - " 19/1 1.19253 1.17120 +/- 0.00913\n", - " 20/1 1.18124 1.17220 +/- 0.00823\n", - " 21/1 1.19206 1.17401 +/- 0.00766\n", - " 22/1 1.17681 1.17424 +/- 0.00700\n", - " 23/1 1.17634 1.17440 +/- 0.00644\n", - " 24/1 1.13659 1.17170 +/- 0.00654\n", - " 25/1 1.17144 1.17169 +/- 0.00609\n", - " 26/1 1.20649 1.17386 +/- 0.00610\n", - " 27/1 1.11238 1.17024 +/- 0.00678\n", - " 28/1 1.18911 1.17129 +/- 0.00647\n", - " 29/1 1.14681 1.17000 +/- 0.00626\n", - " 30/1 1.12152 1.16758 +/- 0.00641\n", - " 31/1 1.12729 1.16566 +/- 0.00639\n", - " 32/1 1.15399 1.16513 +/- 0.00612\n", - " 33/1 1.13547 1.16384 +/- 0.00599\n", - " 34/1 1.17723 1.16440 +/- 0.00576\n", - " 35/1 1.09296 1.16154 +/- 0.00622\n", - " 36/1 1.19621 1.16287 +/- 0.00612\n", - " 37/1 1.12560 1.16149 +/- 0.00605\n", - " 38/1 1.17872 1.16211 +/- 0.00586\n", - " 39/1 1.17721 1.16263 +/- 0.00568\n", - " 40/1 1.13724 1.16178 +/- 0.00555\n", - " 41/1 1.18526 1.16254 +/- 0.00542\n", - " 42/1 1.13779 1.16177 +/- 0.00531\n", - " 43/1 1.15066 1.16143 +/- 0.00516\n", - " 44/1 1.12174 1.16026 +/- 0.00514\n", - " 45/1 1.17478 1.16068 +/- 0.00501\n", - " 46/1 1.14146 1.16014 +/- 0.00489\n", - " 47/1 1.20464 1.16135 +/- 0.00491\n", - " 48/1 1.15119 1.16108 +/- 0.00479\n", - " 49/1 1.17938 1.16155 +/- 0.00468\n", - " 50/1 1.15798 1.16146 +/- 0.00457\n", - " Creating state point statepoint.50.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\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", - " k-effective (Collision) = 1.15984 +/- 0.00411\n", - " k-effective (Track-length) = 1.16146 +/- 0.00457\n", - " k-effective (Absorption) = 1.16177 +/- 0.00380\n", - " Combined k-effective = 1.16105 +/- 0.00364\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the last statepoint file\n", - "sp = openmc.StatePoint('statepoint.50.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. By default, a `Summary` object is automatically linked when a `StatePoint` is loaded. This is necessary for the `openmc.mgxs` module to properly process the tally data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the `StatePoint` into each object as follows and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the tallies from the statepoint into each MGXS object\n", - "total.load_from_statepoint(sp)\n", - "absorption.load_from_statepoint(sp)\n", - "scattering.load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Voila! Our multi-group cross sections are now ready to rock 'n roll!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Extracting and Storing MGXS Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's first inspect our total cross section by printing it to the screen." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi-Group XS\n", - "\tReaction Type =\ttotal\n", - "\tDomain Type =\tcell\n", - "\tDomain ID =\t1\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t6.81e-01 +/- 2.69e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t1.40e+00 +/- 5.93e-01%\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "total.print_xs()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since the `openmc.mgxs` module uses [tally arithmetic](http://openmc.readthedocs.io/en/latest/examples/tally-arithmetic.html) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](http://pandas.pydata.org/) `DataFrame` of the multi-group cross section data." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellgroup innuclidemeanstd. dev.
111total0.6677870.001802
012total1.2920130.007642
\n", - "
" - ], - "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "1 1 1 total 0.667787 0.001802\n", - "0 1 2 total 1.292013 0.007642" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = scattering.get_pandas_dataframe()\n", - "df.head(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each multi-group cross section object can be easily exported to a variety of file formats, including CSV, Excel, and LaTeX for storage or data processing." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "absorption.export_xs_data(filename='absorption-xs', format='excel')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following code snippet shows how to export all three `MGXS` to the same HDF5 binary data store." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "total.build_hdf5_store(filename='mgxs', append=True)\n", - "absorption.build_hdf5_store(filename='mgxs', append=True)\n", - "scattering.build_hdf5_store(filename='mgxs', append=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comparing MGXS with Tally Arithmetic" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](http://openmc.readthedocs.io/en/latest/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to confirm that the `TotalXS` is equal to the sum of the `AbsorptionXS` and `ScatterXS` objects." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01total(((total / flux) - (absorption / flux)) - (sca...-1.110223e-150.011292
110.6252.000000e+07total(((total / flux) - (absorption / flux)) - (sca...7.771561e-160.002570
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide \\\n", - "0 1 0.00e+00 6.25e-01 total \n", - "1 1 6.25e-01 2.00e+07 total \n", - "\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... 7.77e-16 2.57e-03 " - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use tally arithmetic to compute the difference between the total, absorption and scattering\n", - "difference = total.xs_tally - absorption.xs_tally - scattering.xs_tally\n", - "\n", - "# The difference is a derived tally which can generate Pandas DataFrames for inspection\n", - "difference.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can use tally arithmetic to compute the ratio of `AbsorptionXS` and `ScatterXS` to the `TotalXS`." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01total((absorption / flux) / (total / flux))0.0761150.000649
110.6252.000000e+07total((absorption / flux) / (total / flux))0.0192630.000095
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide \\\n", - "0 1 0.00e+00 6.25e-01 total \n", - "1 1 6.25e-01 2.00e+07 total \n", - "\n", - " score mean std. dev. \n", - "0 ((absorption / flux) / (total / flux)) 7.61e-02 6.49e-04 \n", - "1 ((absorption / flux) / (total / flux)) 1.93e-02 9.46e-05 " - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use tally arithmetic to compute the absorption-to-total MGXS ratio\n", - "absorption_to_total = absorption.xs_tally / total.xs_tally\n", - "\n", - "# The absorption-to-total ratio is a derived tally which can generate Pandas DataFrames for inspection\n", - "absorption_to_total.get_pandas_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01total((scatter / flux) / (total / flux))0.9238850.007736
110.6252.000000e+07total((scatter / flux) / (total / flux))0.9807370.003737
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide \\\n", - "0 1 0.00e+00 6.25e-01 total \n", - "1 1 6.25e-01 2.00e+07 total \n", - "\n", - " score mean std. dev. \n", - "0 ((scatter / flux) / (total / flux)) 9.24e-01 7.74e-03 \n", - "1 ((scatter / flux) / (total / flux)) 9.81e-01 3.74e-03 " - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use tally arithmetic to compute the scattering-to-total MGXS ratio\n", - "scattering_to_total = scattering.xs_tally / total.xs_tally\n", - "\n", - "# The scattering-to-total ratio is a derived tally which can generate Pandas DataFrames for inspection\n", - "scattering_to_total.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lastly, we sum the derived scatter-to-total and absorption-to-total ratios to confirm that they sum to unity." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01total(((absorption / flux) / (total / flux)) + ((sc...1.00.007763
110.6252.000000e+07total(((absorption / flux) / (total / flux)) + ((sc...1.00.003739
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide \\\n", - "0 1 0.00e+00 6.25e-01 total \n", - "1 1 6.25e-01 2.00e+07 total \n", - "\n", - " score mean std. dev. \n", - "0 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 7.76e-03 \n", - "1 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 3.74e-03 " - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use tally arithmetic to ensure that the absorption- and scattering-to-total MGXS ratios sum to unity\n", - "sum_ratio = absorption_to_total + scattering_to_total\n", - "\n", - "# The sum ratio is a derived tally which can generate Pandas DataFrames for inspection\n", - "sum_ratio.get_pandas_dataframe()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mgxs-part-ii.ipynb b/examples/jupyter/mgxs-part-ii.ipynb deleted file mode 100644 index 9e5cde42d..000000000 --- a/examples/jupyter/mgxs-part-ii.ipynb +++ /dev/null @@ -1,2744 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This IPython Notebook illustrates the use of the `openmc.mgxs` module to calculate multi-group cross sections for a heterogeneous fuel pin cell geometry. In particular, this Notebook illustrates the following features:\n", - "\n", - "* Creation of multi-group cross sections on a **heterogeneous geometry**\n", - "* Calculation of cross sections on a **nuclide-by-nuclide basis**\n", - "* The use of **[tally precision triggers](http://docs.openmc.org/en/latest/io_formats/settings.html#trigger-element)** with multi-group cross sections\n", - "* Built-in features for **energy condensation** in downstream data processing\n", - "* The use of the **`openmc.data`** module to plot continuous-energy vs. multi-group cross sections\n", - "* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n", - "\n", - "**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system in order to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "plt.style.use('seaborn-dark')\n", - "\n", - "import openmoc\n", - "\n", - "import openmc\n", - "import openmc.mgxs as mgxs\n", - "import openmc.data\n", - "from openmc.openmoc_compatible import get_openmoc_geometry\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. We'll create three distinct materials for water, clad and fuel." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6% enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our materials, we can now create a `Materials` object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials collection\n", - "materials_file = openmc.Materials([fuel, water, zircaloy])\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.45720)\n", - "\n", - "# Create box to surround the geometry\n", - "box = openmc.model.rectangular_prism(1.26, 1.26, boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "pin_cell_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "pin_cell_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius & box\n", - "pin_cell_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry with the pin cell universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "openmc_geometry = openmc.Geometry(pin_cell_universe)\n", - "\n", - "# Export to \"geometry.xml\"\n", - "openmc_geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we must define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 10,000 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 50\n", - "inactive = 10\n", - "particles = 10000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': True}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Activate tally precision triggers\n", - "settings_file.trigger_active = True\n", - "settings_file.trigger_max_batches = settings_file.batches * 4\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we are finally ready to make use of the `openmc.mgxs` module to generate multi-group cross sections! First, let's define \"coarse\" 2-group and \"fine\" 8-group structures using the built-in `EnergyGroups` class." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a \"coarse\" 2-group EnergyGroups object\n", - "coarse_groups = mgxs.EnergyGroups([0., 0.625, 20.0e6])\n", - "\n", - "# Instantiate a \"fine\" 8-group EnergyGroups object\n", - "fine_groups = mgxs.EnergyGroups([0., 0.058, 0.14, 0.28,\n", - " 0.625, 4.0, 5.53e3, 821.0e3, 20.0e6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we will instantiate a variety of `MGXS` objects needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we define transport, fission, nu-fission, nu-scatter and chi cross sections for each of the three cells in the fuel pin with the 8-group structure as our energy groups." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Extract all Cells filled by Materials\n", - "openmc_cells = openmc_geometry.get_all_material_cells().values()\n", - "\n", - "# Create dictionary to store multi-group cross sections for all cells\n", - "xs_library = {}\n", - "\n", - "# Instantiate 8-group cross sections for each cell\n", - "for cell in openmc_cells:\n", - " xs_library[cell.id] = {}\n", - " xs_library[cell.id]['transport'] = mgxs.TransportXS(groups=fine_groups)\n", - " xs_library[cell.id]['fission'] = mgxs.FissionXS(groups=fine_groups)\n", - " xs_library[cell.id]['nu-fission'] = mgxs.FissionXS(groups=fine_groups, nu=True)\n", - " xs_library[cell.id]['nu-scatter'] = mgxs.ScatterMatrixXS(groups=fine_groups, nu=True)\n", - " xs_library[cell.id]['chi'] = mgxs.Chi(groups=fine_groups)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we showcase the use of OpenMC's [tally precision trigger](http://openmc.readthedocs.io/en/latest/io_formats/settings.html#trigger-element) feature in conjunction with the `openmc.mgxs` module. In particular, we will assign a tally trigger of 1E-2 on the standard deviation for each of the tallies used to compute multi-group cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a tally trigger for +/- 0.01 on each tally used to compute the multi-group cross sections\n", - "tally_trigger = openmc.Trigger('std_dev', 1e-2)\n", - "\n", - "# Add the tally trigger to each of the multi-group cross section tallies\n", - "for cell in openmc_cells:\n", - " for mgxs_type in xs_library[cell.id]:\n", - " xs_library[cell.id][mgxs_type].tally_trigger = tally_trigger" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we must loop over all cells to set the cross section domains to the various cells - fuel, clad and moderator - included in the geometry. In addition, we will set each cross section to tally cross sections on a per-nuclide basis through the use of the `MGXS` class' boolean `by_nuclide` instance attribute. " - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=53.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=21.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=3.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=4.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=41.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=15.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Instantiate an empty Tallies object\n", - "tallies_file = openmc.Tallies()\n", - "\n", - "# Iterate over all cells and cross section types\n", - "for cell in openmc_cells:\n", - " for rxn_type in xs_library[cell.id]:\n", - "\n", - " # Set the cross sections domain to the cell\n", - " xs_library[cell.id][rxn_type].domain = cell\n", - " \n", - " # Tally cross sections by nuclide\n", - " xs_library[cell.id][rxn_type].by_nuclide = True\n", - " \n", - " # Add OpenMC tallies to the tallies file for XML generation\n", - " for tally in xs_library[cell.id][rxn_type].tallies.values():\n", - " tallies_file.append(tally, merge=True)\n", - "\n", - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 07:08:16\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.20332\n", - " 2/1 1.22209\n", - " 3/1 1.24322\n", - " 4/1 1.21622\n", - " 5/1 1.25850\n", - " 6/1 1.22581\n", - " 7/1 1.21118\n", - " 8/1 1.23377\n", - " 9/1 1.24254\n", - " 10/1 1.21241\n", - " 11/1 1.21042\n", - " 12/1 1.23539 1.22290 +/- 0.01249\n", - " 13/1 1.22436 1.22339 +/- 0.00723\n", - " 14/1 1.22888 1.22476 +/- 0.00529\n", - " 15/1 1.22553 1.22491 +/- 0.00410\n", - " 16/1 1.24194 1.22775 +/- 0.00439\n", - " 17/1 1.24755 1.23058 +/- 0.00466\n", - " 18/1 1.21117 1.22815 +/- 0.00471\n", - " 19/1 1.22530 1.22784 +/- 0.00417\n", - " 20/1 1.20762 1.22582 +/- 0.00424\n", - " 21/1 1.20377 1.22381 +/- 0.00433\n", - " 22/1 1.24305 1.22541 +/- 0.00426\n", - " 23/1 1.22434 1.22533 +/- 0.00392\n", - " 24/1 1.22937 1.22562 +/- 0.00364\n", - " 25/1 1.22458 1.22555 +/- 0.00339\n", - " 26/1 1.18978 1.22332 +/- 0.00388\n", - " 27/1 1.20582 1.22229 +/- 0.00379\n", - " 28/1 1.22719 1.22256 +/- 0.00358\n", - " 29/1 1.21307 1.22206 +/- 0.00343\n", - " 30/1 1.20915 1.22141 +/- 0.00331\n", - " 31/1 1.22799 1.22173 +/- 0.00317\n", - " 32/1 1.21251 1.22131 +/- 0.00305\n", - " 33/1 1.20540 1.22062 +/- 0.00299\n", - " 34/1 1.20052 1.21978 +/- 0.00299\n", - " 35/1 1.24552 1.22081 +/- 0.00304\n", - " 36/1 1.21685 1.22066 +/- 0.00293\n", - " 37/1 1.22395 1.22078 +/- 0.00282\n", - " 38/1 1.22379 1.22089 +/- 0.00272\n", - " 39/1 1.20951 1.22049 +/- 0.00265\n", - " 40/1 1.25199 1.22154 +/- 0.00277\n", - " 41/1 1.23243 1.22190 +/- 0.00270\n", - " 42/1 1.20973 1.22152 +/- 0.00264\n", - " 43/1 1.24682 1.22228 +/- 0.00268\n", - " 44/1 1.20694 1.22183 +/- 0.00263\n", - " 45/1 1.22196 1.22183 +/- 0.00256\n", - " 46/1 1.20687 1.22142 +/- 0.00252\n", - " 47/1 1.22023 1.22139 +/- 0.00245\n", - " 48/1 1.22204 1.22140 +/- 0.00239\n", - " 49/1 1.22077 1.22139 +/- 0.00232\n", - " 50/1 1.23166 1.22164 +/- 0.00228\n", - " Triggers unsatisfied, max unc./thresh. is 1.17623 for flux in tally 53\n", - " The estimated number of batches is 66\n", - " Creating state point statepoint.050.h5...\n", - " 51/1 1.20071 1.22113 +/- 0.00228\n", - " Triggers unsatisfied, max unc./thresh. is 1.26577 for flux in tally 53\n", - " The estimated number of batches is 76\n", - " 52/1 1.21423 1.22097 +/- 0.00223\n", - " Triggers unsatisfied, max unc./thresh. is 1.24 for flux in tally 53\n", - " The estimated number of batches is 75\n", - " 53/1 1.25595 1.22178 +/- 0.00233\n", - " Triggers unsatisfied, max unc./thresh. is 1.2112 for flux in tally 53\n", - " The estimated number of batches is 74\n", - " 54/1 1.21806 1.22170 +/- 0.00227\n", - " Triggers unsatisfied, max unc./thresh. is 1.18484 for flux in tally 53\n", - " The estimated number of batches is 72\n", - " 55/1 1.22911 1.22186 +/- 0.00223\n", - " Triggers unsatisfied, max unc./thresh. is 1.1596 for flux in tally 53\n", - " The estimated number of batches is 71\n", - " 56/1 1.23054 1.22205 +/- 0.00219\n", - " Triggers unsatisfied, max unc./thresh. is 1.13453 for flux in tally 53\n", - " The estimated number of batches is 70\n", - " 57/1 1.19384 1.22145 +/- 0.00222\n", - " Triggers unsatisfied, max unc./thresh. is 1.11914 for flux in tally 53\n", - " The estimated number of batches is 69\n", - " 58/1 1.20625 1.22114 +/- 0.00220\n", - " Triggers unsatisfied, max unc./thresh. is 1.11471 for flux in tally 53\n", - " The estimated number of batches is 70\n", - " 59/1 1.21977 1.22111 +/- 0.00216\n", - " Triggers unsatisfied, max unc./thresh. is 1.10334 for flux in tally 53\n", - " The estimated number of batches is 70\n", - " 60/1 1.20813 1.22085 +/- 0.00213\n", - " Triggers unsatisfied, max unc./thresh. is 1.09813 for flux in tally 53\n", - " The estimated number of batches is 71\n", - " 61/1 1.22077 1.22085 +/- 0.00209\n", - " Triggers unsatisfied, max unc./thresh. is 1.10221 for flux in tally 53\n", - " The estimated number of batches is 72\n", - " 62/1 1.21956 1.22082 +/- 0.00205\n", - " Triggers unsatisfied, max unc./thresh. is 1.11395 for flux in tally 53\n", - " The estimated number of batches is 75\n", - " 63/1 1.22360 1.22087 +/- 0.00201\n", - " Triggers unsatisfied, max unc./thresh. is 1.09283 for flux in tally 53\n", - " The estimated number of batches is 74\n", - " 64/1 1.23955 1.22122 +/- 0.00200\n", - " Triggers unsatisfied, max unc./thresh. is 1.07416 for flux in tally 53\n", - " The estimated number of batches is 73\n", - " 65/1 1.21143 1.22104 +/- 0.00197\n", - " Triggers unsatisfied, max unc./thresh. is 1.06461 for flux in tally 53\n", - " The estimated number of batches is 73\n", - " 66/1 1.21791 1.22099 +/- 0.00194\n", - " Triggers unsatisfied, max unc./thresh. is 1.13207 for flux in tally 53\n", - " The estimated number of batches is 82\n", - " 67/1 1.24897 1.22148 +/- 0.00196\n", - " Triggers unsatisfied, max unc./thresh. is 1.11277 for flux in tally 53\n", - " The estimated number of batches is 81\n", - " 68/1 1.22221 1.22149 +/- 0.00193\n", - " Triggers unsatisfied, max unc./thresh. is 1.09514 for flux in tally 53\n", - " The estimated number of batches is 80\n", - " 69/1 1.25627 1.22208 +/- 0.00199\n", - " Triggers unsatisfied, max unc./thresh. is 1.07653 for flux in tally 53\n", - " The estimated number of batches is 79\n", - " 70/1 1.21493 1.22196 +/- 0.00196\n", - " Triggers unsatisfied, max unc./thresh. is 1.12831 for flux in tally 53\n", - " The estimated number of batches is 87\n", - " 71/1 1.23406 1.22216 +/- 0.00193\n", - " Triggers unsatisfied, max unc./thresh. is 1.11005 for flux in tally 53\n", - " The estimated number of batches is 86\n", - " 72/1 1.23842 1.22242 +/- 0.00192\n", - " Triggers unsatisfied, max unc./thresh. is 1.09352 for flux in tally 53\n", - " The estimated number of batches is 85\n", - " 73/1 1.24542 1.22279 +/- 0.00193\n", - " Triggers unsatisfied, max unc./thresh. is 1.08766 for flux in tally 53\n", - " The estimated number of batches is 85\n", - " 74/1 1.21314 1.22263 +/- 0.00190\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Triggers unsatisfied, max unc./thresh. is 1.07419 for flux in tally 53\n", - " The estimated number of batches is 84\n", - " 75/1 1.26484 1.22328 +/- 0.00198\n", - " Triggers unsatisfied, max unc./thresh. is 1.06788 for flux in tally 53\n", - " The estimated number of batches is 85\n", - " 76/1 1.22243 1.22327 +/- 0.00195\n", - " Triggers unsatisfied, max unc./thresh. is 1.05164 for flux in tally 53\n", - " The estimated number of batches is 83\n", - " 77/1 1.21865 1.22320 +/- 0.00192\n", - " Triggers unsatisfied, max unc./thresh. is 1.04022 for flux in tally 53\n", - " The estimated number of batches is 83\n", - " 78/1 1.23500 1.22338 +/- 0.00190\n", - " Triggers unsatisfied, max unc./thresh. is 1.0275 for flux in tally 53\n", - " The estimated number of batches is 82\n", - " 79/1 1.22125 1.22334 +/- 0.00187\n", - " Triggers unsatisfied, max unc./thresh. is 1.0283 for flux in tally 53\n", - " The estimated number of batches is 83\n", - " 80/1 1.23793 1.22355 +/- 0.00186\n", - " Triggers unsatisfied, max unc./thresh. is 1.01363 for flux in tally 53\n", - " The estimated number of batches is 82\n", - " 81/1 1.24238 1.22382 +/- 0.00185\n", - " Triggers unsatisfied, max unc./thresh. is 1.01172 for flux in tally 53\n", - " The estimated number of batches is 83\n", - " 82/1 1.23493 1.22397 +/- 0.00183\n", - " Triggers satisfied for batch 82\n", - " Creating state point statepoint.082.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 9.5644e-01 seconds\n", - " Reading cross sections = 9.0579e-01 seconds\n", - " Total time in simulation = 9.9887e+01 seconds\n", - " Time in transport only = 9.9333e+01 seconds\n", - " Time in inactive batches = 5.4841e+00 seconds\n", - " Time in active batches = 9.4403e+01 seconds\n", - " Time synchronizing fission bank = 7.3998e-02 seconds\n", - " Sampling source sites = 5.9021e-02 seconds\n", - " SEND/RECV source sites = 1.4787e-02 seconds\n", - " Time accumulating tallies = 1.2234e-03 seconds\n", - " Total time for finalization = 2.8416e-02 seconds\n", - " Total time elapsed = 1.0094e+02 seconds\n", - " Calculation Rate (inactive) = 18234.5 particles/second\n", - " Calculation Rate (active) = 7626.89 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.22348 +/- 0.00169\n", - " k-effective (Track-length) = 1.22397 +/- 0.00183\n", - " k-effective (Absorption) = 1.22467 +/- 0.00117\n", - " Combined k-effective = 1.22448 +/- 0.00108\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the last statepoint file\n", - "sp = openmc.StatePoint('statepoint.082.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by our multi-group cross sections. We simply have to load the tallies from the `StatePoint` into each object as follows and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Iterate over all cells and cross section types\n", - "for cell in openmc_cells:\n", - " for rxn_type in xs_library[cell.id]:\n", - " xs_library[cell.id][rxn_type].load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "That's it! Our multi-group cross sections are now ready for the big spotlight. This time we have cross sections in three distinct spatial zones - fuel, clad and moderator - on a per-nuclide basis." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Extracting and Storing MGXS Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's first inspect one of our cross sections by printing it to the screen as a microscopic cross section in units of barns." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi-Group XS\n", - "\tReaction Type =\tnu-fission\n", - "\tDomain Type =\tcell\n", - "\tDomain ID =\t1\n", - "\tNuclide =\tU235\n", - "\tCross Sections [barns]:\n", - " Group 1 [821000.0 - 20000000.0eV]:\t3.30e+00 +/- 2.14e-01%\n", - " Group 2 [5530.0 - 821000.0 eV]:\t3.96e+00 +/- 1.33e-01%\n", - " Group 3 [4.0 - 5530.0 eV]:\t5.50e+01 +/- 2.29e-01%\n", - " Group 4 [0.625 - 4.0 eV]:\t8.85e+01 +/- 3.10e-01%\n", - " Group 5 [0.28 - 0.625 eV]:\t2.90e+02 +/- 3.94e-01%\n", - " Group 6 [0.14 - 0.28 eV]:\t4.49e+02 +/- 4.12e-01%\n", - " Group 7 [0.058 - 0.14 eV]:\t6.87e+02 +/- 3.01e-01%\n", - " Group 8 [0.0 - 0.058 eV]:\t1.44e+03 +/- 2.79e-01%\n", - "\n", - "\tNuclide =\tU238\n", - "\tCross Sections [barns]:\n", - " Group 1 [821000.0 - 20000000.0eV]:\t1.06e+00 +/- 2.53e-01%\n", - " Group 2 [5530.0 - 821000.0 eV]:\t1.21e-03 +/- 2.60e-01%\n", - " Group 3 [4.0 - 5530.0 eV]:\t5.73e-04 +/- 2.93e+00%\n", - " Group 4 [0.625 - 4.0 eV]:\t6.54e-06 +/- 2.72e-01%\n", - " Group 5 [0.28 - 0.625 eV]:\t1.07e-05 +/- 3.83e-01%\n", - " Group 6 [0.14 - 0.28 eV]:\t1.55e-05 +/- 4.13e-01%\n", - " Group 7 [0.058 - 0.14 eV]:\t2.30e-05 +/- 3.01e-01%\n", - " Group 8 [0.0 - 0.058 eV]:\t4.24e-05 +/- 2.79e-01%\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "nufission = xs_library[fuel_cell.id]['nu-fission']\n", - "nufission.print_xs(xs_type='micro', nuclides=['U235', 'U238'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our multi-group cross sections are capable of summing across all nuclides to provide us with macroscopic cross sections as well." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi-Group XS\n", - "\tReaction Type =\tnu-fission\n", - "\tDomain Type =\tcell\n", - "\tDomain ID =\t1\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [821000.0 - 20000000.0eV]:\t2.52e-02 +/- 2.41e-01%\n", - " Group 2 [5530.0 - 821000.0 eV]:\t1.51e-03 +/- 1.31e-01%\n", - " Group 3 [4.0 - 5530.0 eV]:\t2.07e-02 +/- 2.29e-01%\n", - " Group 4 [0.625 - 4.0 eV]:\t3.32e-02 +/- 3.10e-01%\n", - " Group 5 [0.28 - 0.625 eV]:\t1.09e-01 +/- 3.94e-01%\n", - " Group 6 [0.14 - 0.28 eV]:\t1.69e-01 +/- 4.12e-01%\n", - " Group 7 [0.058 - 0.14 eV]:\t2.58e-01 +/- 3.01e-01%\n", - " Group 8 [0.0 - 0.058 eV]:\t5.40e-01 +/- 2.79e-01%\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "nufission = xs_library[fuel_cell.id]['nu-fission']\n", - "nufission.print_xs(xs_type='macro', nuclides='sum')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Although a printed report is nice, it is not scalable or flexible. Let's extract the microscopic cross section data for the moderator as a [Pandas](http://pandas.pydata.org/) `DataFrame` ." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellgroup ingroup outnuclidemeanstd. dev.
126311H10.2339910.003752
127311O161.5692880.006360
124312H11.5872790.003098
125312O160.2855990.001422
122313H10.0104820.000220
123313O160.0000000.000000
120314H10.0000090.000006
121314O160.0000000.000000
118315H10.0000050.000005
119315O160.0000000.000000
\n", - "
" - ], - "text/plain": [ - " cell group in group out nuclide mean std. dev.\n", - "126 3 1 1 H1 0.233991 0.003752\n", - "127 3 1 1 O16 1.569288 0.006360\n", - "124 3 1 2 H1 1.587279 0.003098\n", - "125 3 1 2 O16 0.285599 0.001422\n", - "122 3 1 3 H1 0.010482 0.000220\n", - "123 3 1 3 O16 0.000000 0.000000\n", - "120 3 1 4 H1 0.000009 0.000006\n", - "121 3 1 4 O16 0.000000 0.000000\n", - "118 3 1 5 H1 0.000005 0.000005\n", - "119 3 1 5 O16 0.000000 0.000000" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nuscatter = xs_library[moderator_cell.id]['nu-scatter']\n", - "df = nuscatter.get_pandas_dataframe(xs_type='micro')\n", - "df.head(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we illustate how one can easily take multi-group cross sections and condense them down to a coarser energy group structure. The `MGXS` class includes a `get_condensed_xs(...)` method which takes an `EnergyGroups` parameter with a coarse(r) group structure and returns a new `MGXS` condensed to the coarse groups. We illustrate this process below using the 2-group structure created earlier." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "# Extract the 8-group transport cross section for the fuel\n", - "fine_xs = xs_library[fuel_cell.id]['transport']\n", - "\n", - "# Condense to the 2-group structure\n", - "condensed_xs = fine_xs.get_condensed_xs(coarse_groups)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Group condensation is as simple as that! We now have a new coarse 2-group `TransportXS` in addition to our original 8-group `TransportXS`. Let's inspect the 2-group `TransportXS` by printing it to the screen and extracting a Pandas `DataFrame` as we have already learned how to do." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi-Group XS\n", - "\tReaction Type =\ttransport\n", - "\tDomain Type =\tcell\n", - "\tDomain ID =\t1\n", - "\tNuclide =\tU235\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t7.79e-03 +/- 2.12e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t1.82e-01 +/- 1.92e-01%\n", - "\n", - "\tNuclide =\tU238\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t2.17e-01 +/- 1.12e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t2.53e-01 +/- 1.89e-01%\n", - "\n", - "\tNuclide =\tO16\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t1.45e-01 +/- 1.12e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t1.74e-01 +/- 2.03e-01%\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "condensed_xs.print_xs()" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellgroup innuclidemeanstd. dev.
311U23520.7630620.044093
411U2389.5790860.010757
511O163.1572740.003531
012U235485.3490360.930937
112U23811.1991670.021167
212O163.7883830.007676
\n", - "
" - ], - "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "3 1 1 U235 20.763062 0.044093\n", - "4 1 1 U238 9.579086 0.010757\n", - "5 1 1 O16 3.157274 0.003531\n", - "0 1 2 U235 485.349036 0.930937\n", - "1 1 2 U238 11.199167 0.021167\n", - "2 1 2 O16 3.788383 0.007676" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = condensed_xs.get_pandas_dataframe(xs_type='micro')\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Verification with OpenMOC" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let's verify our cross sections using OpenMOC. First, we construct an equivalent OpenMOC geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "# Create an OpenMOC Geometry from the OpenMC Geometry\n", - "openmoc_geometry = get_openmoc_geometry(sp.summary.geometry)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we we can inject the multi-group cross sections into the equivalent fuel pin cell OpenMOC geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "# Get all OpenMOC cells in the gometry\n", - "openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()\n", - "\n", - "# Inject multi-group cross sections into OpenMOC Materials\n", - "for cell_id, cell in openmoc_cells.items():\n", - " \n", - " # Ignore the root cell\n", - " if cell.getName() == 'root cell':\n", - " continue\n", - " \n", - " # Get a reference to the Material filling this Cell\n", - " openmoc_material = cell.getFillMaterial()\n", - " \n", - " # Set the number of energy groups for the Material\n", - " openmoc_material.setNumEnergyGroups(fine_groups.num_groups)\n", - " \n", - " # Extract the appropriate cross section objects for this cell\n", - " transport = xs_library[cell_id]['transport']\n", - " nufission = xs_library[cell_id]['nu-fission']\n", - " nuscatter = xs_library[cell_id]['nu-scatter']\n", - " chi = xs_library[cell_id]['chi']\n", - " \n", - " # Inject NumPy arrays of cross section data into the Material\n", - " # NOTE: Sum across nuclides to get macro cross sections needed by OpenMOC\n", - " openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to run OpenMOC to verify our cross-sections from OpenMC." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Initializing a default angular quadrature...\n", - "[ NORMAL ] Initializing 2D tracks...\n", - "[ NORMAL ] Initializing 2D tracks reflections...\n", - "[ NORMAL ] Initializing 2D tracks array...\n", - "[ NORMAL ] Ray tracing for 2D track segmentation...\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 0.09 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 10.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 19.94 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 29.87 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 39.80 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 49.72 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 59.65 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 69.58 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 79.50 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 89.43 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 100.00 %\n", - "[ NORMAL ] Initializing FSR lookup vectors\n", - "[ NORMAL ] Total number of FSRs 3\n", - "[ RESULT ] Total Track Generation & Segmentation Time...........2.5566E-02 sec\n", - "[ NORMAL ] Initializing MOC eigenvalue solver...\n", - "[ NORMAL ] Initializing solver arrays...\n", - "[ NORMAL ] Centering segments around FSR centroid...\n", - "[ NORMAL ] Max boundary angular flux storage per domain = 0.42 MB\n", - "[ NORMAL ] Max scalar flux storage per domain = 0.00 MB\n", - "[ NORMAL ] Max source storage per domain = 0.00 MB\n", - "[ NORMAL ] Number of azimuthal angles = 128\n", - "[ NORMAL ] Azimuthal ray spacing = 0.100000\n", - "[ NORMAL ] Number of polar angles = 6\n", - "[ NORMAL ] Source type = Flat\n", - "[ NORMAL ] MOC transport undamped\n", - "[ NORMAL ] CMFD acceleration: OFF\n", - "[ NORMAL ] Using 1 threads\n", - "[ NORMAL ] Computing the eigenvalue...\n", - "[ NORMAL ] Iteration 0: k_eff = 0.423133 res = 5.671E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... -57686 D.R. = 0.00\n", - "[ NORMAL ] Iteration 1: k_eff = 0.475953 res = 2.442E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 5282 D.R. = 4.31\n", - "[ NORMAL ] Iteration 2: k_eff = 0.491468 res = 4.764E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1551 D.R. = 1.95\n", - "[ NORMAL ] Iteration 3: k_eff = 0.487446 res = 2.253E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -402 D.R. = 0.47\n", - "[ NORMAL ] Iteration 4: k_eff = 0.483930 res = 6.957E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... -351 D.R. = 0.31\n", - "[ NORMAL ] Iteration 5: k_eff = 0.477280 res = 3.902E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -665 D.R. = 5.61\n", - "[ NORMAL ] Iteration 6: k_eff = 0.468938 res = 3.161E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -834 D.R. = 0.81\n", - "[ NORMAL ] Iteration 7: k_eff = 0.460319 res = 2.480E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -861 D.R. = 0.78\n", - "[ NORMAL ] Iteration 8: k_eff = 0.450591 res = 9.377E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... -972 D.R. = 0.38\n", - "[ NORMAL ] Iteration 9: k_eff = 0.441377 res = 3.085E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -921 D.R. = 3.29\n", - "[ NORMAL ] Iteration 10: k_eff = 0.431990 res = 1.028E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -938 D.R. = 0.33\n", - "[ NORMAL ] Iteration 11: k_eff = 0.422932 res = 1.180E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -905 D.R. = 1.15\n", - "[ NORMAL ] Iteration 12: k_eff = 0.414487 res = 1.633E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -844 D.R. = 1.38\n", - "[ NORMAL ] Iteration 13: k_eff = 0.406708 res = 1.754E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -777 D.R. = 1.07\n", - "[ NORMAL ] Iteration 14: k_eff = 0.399378 res = 5.021E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -732 D.R. = 2.86\n", - "[ NORMAL ] Iteration 15: k_eff = 0.393067 res = 9.074E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... -631 D.R. = 0.18\n", - "[ NORMAL ] Iteration 16: k_eff = 0.387427 res = 4.840E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... -564 D.R. = 0.53\n", - "[ NORMAL ] Iteration 17: k_eff = 0.382668 res = 2.299E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -475 D.R. = 4.75\n", - "[ NORMAL ] Iteration 18: k_eff = 0.378741 res = 1.573E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -392 D.R. = 0.68\n", - "[ NORMAL ] Iteration 19: k_eff = 0.375642 res = 7.017E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -309 D.R. = 4.46\n", - "[ NORMAL ] Iteration 20: k_eff = 0.373489 res = 4.053E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -215 D.R. = 0.58\n", - "[ NORMAL ] Iteration 21: k_eff = 0.372357 res = 4.235E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -113 D.R. = 1.04\n", - "[ NORMAL ] Iteration 22: k_eff = 0.371974 res = 6.352E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -38 D.R. = 1.50\n", - "[ NORMAL ] Iteration 23: k_eff = 0.372581 res = 3.267E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 60 D.R. = 0.51\n", - "[ NORMAL ] Iteration 24: k_eff = 0.374056 res = 1.573E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 147 D.R. = 0.48\n", - "[ NORMAL ] Iteration 25: k_eff = 0.376384 res = 3.630E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 232 D.R. = 2.31\n", - "[ NORMAL ] Iteration 26: k_eff = 0.379563 res = 2.420E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 317 D.R. = 0.07\n", - "[ NORMAL ] Iteration 27: k_eff = 0.383583 res = 3.146E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 401 D.R. = 13.00\n", - "[ NORMAL ] Iteration 28: k_eff = 0.388380 res = 1.089E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 479 D.R. = 0.35\n", - "[ NORMAL ] Iteration 29: k_eff = 0.393938 res = 6.049E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 555 D.R. = 5.56\n", - "[ NORMAL ] Iteration 30: k_eff = 0.400234 res = 3.267E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 629 D.R. = 0.54\n", - "[ NORMAL ] Iteration 31: k_eff = 0.407235 res = 2.420E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 700 D.R. = 0.74\n", - "[ NORMAL ] Iteration 32: k_eff = 0.414884 res = 1.815E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 764 D.R. = 0.75\n", - "[ NORMAL ] Iteration 33: k_eff = 0.423172 res = 7.259E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 828 D.R. = 0.40\n", - "[ NORMAL ] Iteration 34: k_eff = 0.432051 res = 6.049E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 887 D.R. = 8.33\n", - "[ NORMAL ] Iteration 35: k_eff = 0.441471 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 942 D.R. = 0.96\n", - "[ NORMAL ] Iteration 36: k_eff = 0.451430 res = 2.662E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 995 D.R. = 0.46\n", - "[ NORMAL ] Iteration 37: k_eff = 0.461853 res = 8.227E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1042 D.R. = 3.09\n", - "[ NORMAL ] Iteration 38: k_eff = 0.472730 res = 5.928E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1087 D.R. = 0.72\n", - "[ NORMAL ] Iteration 39: k_eff = 0.484006 res = 2.299E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1127 D.R. = 0.39\n", - "[ NORMAL ] Iteration 40: k_eff = 0.495653 res = 2.299E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1164 D.R. = 1.00\n", - "[ NORMAL ] Iteration 41: k_eff = 0.507634 res = 7.017E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1198 D.R. = 3.05\n", - "[ NORMAL ] Iteration 42: k_eff = 0.519914 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1227 D.R. = 0.28\n", - "[ NORMAL ] Iteration 43: k_eff = 0.532458 res = 1.089E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1254 D.R. = 0.56\n", - "[ NORMAL ] Iteration 44: k_eff = 0.545234 res = 6.291E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1277 D.R. = 5.78\n", - "[ NORMAL ] Iteration 45: k_eff = 0.558210 res = 3.509E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1297 D.R. = 0.56\n", - "[ NORMAL ] Iteration 46: k_eff = 0.571353 res = 3.025E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1314 D.R. = 0.86\n", - "[ NORMAL ] Iteration 47: k_eff = 0.584635 res = 7.259E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1328 D.R. = 0.24\n", - "[ NORMAL ] Iteration 48: k_eff = 0.598027 res = 4.961E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1339 D.R. = 6.83\n", - "[ NORMAL ] Iteration 49: k_eff = 0.611500 res = 9.014E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1347 D.R. = 1.82\n", - "[ NORMAL ] Iteration 50: k_eff = 0.625029 res = 5.203E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1352 D.R. = 0.58\n", - "[ NORMAL ] Iteration 51: k_eff = 0.638590 res = 1.512E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1356 D.R. = 0.29\n", - "[ NORMAL ] Iteration 52: k_eff = 0.652158 res = 2.359E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1356 D.R. = 1.56\n", - "[ NORMAL ] Iteration 53: k_eff = 0.665710 res = 4.598E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1355 D.R. = 1.95\n", - "[ NORMAL ] Iteration 54: k_eff = 0.679228 res = 2.783E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1351 D.R. = 0.61\n", - "[ NORMAL ] Iteration 55: k_eff = 0.692689 res = 2.117E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1346 D.R. = 0.76\n", - "[ NORMAL ] Iteration 56: k_eff = 0.706075 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1338 D.R. = 0.91\n", - "[ NORMAL ] Iteration 57: k_eff = 0.719370 res = 5.505E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1329 D.R. = 2.84\n", - "[ NORMAL ] Iteration 58: k_eff = 0.732556 res = 2.238E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1318 D.R. = 0.41\n", - "[ NORMAL ] Iteration 59: k_eff = 0.745619 res = 7.864E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1306 D.R. = 0.35\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 60: k_eff = 0.758546 res = 4.477E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1292 D.R. = 5.69\n", - "[ NORMAL ] Iteration 61: k_eff = 0.771323 res = 4.658E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1277 D.R. = 1.04\n", - "[ NORMAL ] Iteration 62: k_eff = 0.783939 res = 9.679E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1261 D.R. = 0.21\n", - "[ NORMAL ] Iteration 63: k_eff = 0.796383 res = 4.235E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1244 D.R. = 0.44\n", - "[ NORMAL ] Iteration 64: k_eff = 0.808646 res = 9.074E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1226 D.R. = 2.14\n", - "[ NORMAL ] Iteration 65: k_eff = 0.820719 res = 6.412E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1207 D.R. = 7.07\n", - "[ NORMAL ] Iteration 66: k_eff = 0.832594 res = 2.420E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 1187 D.R. = 0.04\n", - "[ NORMAL ] Iteration 67: k_eff = 0.844264 res = 2.299E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1167 D.R. = 9.50\n", - "[ NORMAL ] Iteration 68: k_eff = 0.855724 res = 5.928E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1146 D.R. = 2.58\n", - "[ NORMAL ] Iteration 69: k_eff = 0.866968 res = 6.049E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1124 D.R. = 1.02\n", - "[ NORMAL ] Iteration 70: k_eff = 0.877992 res = 2.722E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1102 D.R. = 0.45\n", - "[ NORMAL ] Iteration 71: k_eff = 0.888792 res = 1.633E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1079 D.R. = 0.60\n", - "[ NORMAL ] Iteration 72: k_eff = 0.899364 res = 2.117E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1057 D.R. = 1.30\n", - "[ NORMAL ] Iteration 73: k_eff = 0.909708 res = 3.327E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1034 D.R. = 1.57\n", - "[ NORMAL ] Iteration 74: k_eff = 0.919819 res = 4.477E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1011 D.R. = 1.35\n", - "[ NORMAL ] Iteration 75: k_eff = 0.929699 res = 3.569E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 987 D.R. = 0.80\n", - "[ NORMAL ] Iteration 76: k_eff = 0.939346 res = 4.840E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 964 D.R. = 0.14\n", - "[ NORMAL ] Iteration 77: k_eff = 0.948758 res = 4.840E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 941 D.R. = 1.00\n", - "[ NORMAL ] Iteration 78: k_eff = 0.957938 res = 6.049E-10 delta-k (pcm) =\n", - "[ NORMAL ] ... 917 D.R. = 0.12\n", - "[ NORMAL ] Iteration 79: k_eff = 0.966885 res = 2.057E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 894 D.R. = 34.00\n", - "[ NORMAL ] Iteration 80: k_eff = 0.975601 res = 4.235E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 871 D.R. = 2.06\n", - "[ NORMAL ] Iteration 81: k_eff = 0.984087 res = 5.868E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 848 D.R. = 1.39\n", - "[ NORMAL ] Iteration 82: k_eff = 0.992344 res = 7.259E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 825 D.R. = 0.12\n", - "[ NORMAL ] Iteration 83: k_eff = 1.000375 res = 1.512E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 803 D.R. = 2.08\n", - "[ NORMAL ] Iteration 84: k_eff = 1.008182 res = 7.864E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 780 D.R. = 0.52\n", - "[ NORMAL ] Iteration 85: k_eff = 1.015768 res = 7.259E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 758 D.R. = 0.92\n", - "[ NORMAL ] Iteration 86: k_eff = 1.023136 res = 3.025E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 736 D.R. = 0.42\n", - "[ NORMAL ] Iteration 87: k_eff = 1.030288 res = 1.210E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 715 D.R. = 4.00\n", - "[ NORMAL ] Iteration 88: k_eff = 1.037228 res = 3.690E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 693 D.R. = 3.05\n", - "[ NORMAL ] Iteration 89: k_eff = 1.043960 res = 5.203E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 673 D.R. = 1.41\n", - "[ NORMAL ] Iteration 90: k_eff = 1.050486 res = 6.231E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 652 D.R. = 1.20\n", - "[ NORMAL ] Iteration 91: k_eff = 1.056812 res = 6.775E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 632 D.R. = 1.09\n", - "[ NORMAL ] Iteration 92: k_eff = 1.062939 res = 2.964E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 612 D.R. = 0.44\n", - "[ NORMAL ] Iteration 93: k_eff = 1.068872 res = 5.505E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 593 D.R. = 1.86\n", - "[ NORMAL ] Iteration 94: k_eff = 1.074616 res = 4.235E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 574 D.R. = 0.08\n", - "[ NORMAL ] Iteration 95: k_eff = 1.080173 res = 2.541E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 555 D.R. = 6.00\n", - "[ NORMAL ] Iteration 96: k_eff = 1.085550 res = 1.996E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 537 D.R. = 0.79\n", - "[ NORMAL ] Iteration 97: k_eff = 1.090748 res = 3.388E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 519 D.R. = 1.70\n", - "[ NORMAL ] Iteration 98: k_eff = 1.095774 res = 3.085E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 502 D.R. = 0.91\n", - "[ NORMAL ] Iteration 99: k_eff = 1.100629 res = 3.267E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 485 D.R. = 1.06\n", - "[ NORMAL ] Iteration 100: k_eff = 1.105320 res = 3.025E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 469 D.R. = 0.09\n", - "[ NORMAL ] Iteration 101: k_eff = 1.109851 res = 6.654E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 453 D.R. = 2.20\n", - "[ NORMAL ] Iteration 102: k_eff = 1.114224 res = 3.569E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 437 D.R. = 5.36\n", - "[ NORMAL ] Iteration 103: k_eff = 1.118444 res = 5.203E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 421 D.R. = 1.46\n", - "[ NORMAL ] Iteration 104: k_eff = 1.122516 res = 1.452E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 407 D.R. = 0.28\n", - "[ NORMAL ] Iteration 105: k_eff = 1.126445 res = 5.445E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 392 D.R. = 0.38\n", - "[ NORMAL ] Iteration 106: k_eff = 1.130232 res = 2.783E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 378 D.R. = 5.11\n", - "[ NORMAL ] Iteration 107: k_eff = 1.133884 res = 1.996E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 365 D.R. = 0.72\n", - "[ NORMAL ] Iteration 108: k_eff = 1.137403 res = 4.235E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 351 D.R. = 2.12\n", - "[ NORMAL ] Iteration 109: k_eff = 1.140793 res = 3.751E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 339 D.R. = 0.89\n", - "[ NORMAL ] Iteration 110: k_eff = 1.144059 res = 4.174E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 326 D.R. = 1.11\n", - "[ NORMAL ] Iteration 111: k_eff = 1.147203 res = 4.416E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 314 D.R. = 1.06\n", - "[ NORMAL ] Iteration 112: k_eff = 1.150231 res = 3.025E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 302 D.R. = 0.68\n", - "[ NORMAL ] Iteration 113: k_eff = 1.153146 res = 5.384E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 291 D.R. = 1.78\n", - "[ NORMAL ] Iteration 114: k_eff = 1.155950 res = 3.569E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 280 D.R. = 0.66\n", - "[ NORMAL ] Iteration 115: k_eff = 1.158649 res = 5.142E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 269 D.R. = 1.44\n", - "[ NORMAL ] Iteration 116: k_eff = 1.161244 res = 2.843E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 259 D.R. = 0.55\n", - "[ NORMAL ] Iteration 117: k_eff = 1.163739 res = 3.267E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 249 D.R. = 1.15\n", - "[ NORMAL ] Iteration 118: k_eff = 1.166139 res = 5.505E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 239 D.R. = 1.69\n", - "[ NORMAL ] Iteration 119: k_eff = 1.168445 res = 4.719E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 230 D.R. = 0.86\n", - "[ NORMAL ] Iteration 120: k_eff = 1.170662 res = 6.170E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 221 D.R. = 1.31\n", - "[ NORMAL ] Iteration 121: k_eff = 1.172791 res = 5.384E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 212 D.R. = 0.87\n", - "[ NORMAL ] Iteration 122: k_eff = 1.174837 res = 1.331E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 204 D.R. = 0.25\n", - "[ NORMAL ] Iteration 123: k_eff = 1.176801 res = 1.391E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 196 D.R. = 1.05\n", - "[ NORMAL ] Iteration 124: k_eff = 1.178688 res = 1.089E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 188 D.R. = 0.78\n", - "[ NORMAL ] Iteration 125: k_eff = 1.180500 res = 3.448E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 181 D.R. = 3.17\n", - "[ NORMAL ] Iteration 126: k_eff = 1.182238 res = 1.041E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 173 D.R. = 3.02\n", - "[ NORMAL ] Iteration 127: k_eff = 1.183907 res = 3.690E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 166 D.R. = 0.35\n", - "[ NORMAL ] Iteration 128: k_eff = 1.185508 res = 2.722E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 160 D.R. = 0.74\n", - "[ NORMAL ] Iteration 129: k_eff = 1.187044 res = 9.074E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 153 D.R. = 0.33\n", - "[ NORMAL ] Iteration 130: k_eff = 1.188518 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 147 D.R. = 3.20\n", - "[ NORMAL ] Iteration 131: k_eff = 1.189930 res = 2.783E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 141 D.R. = 0.96\n", - "[ NORMAL ] Iteration 132: k_eff = 1.191285 res = 2.541E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 135 D.R. = 0.91\n", - "[ NORMAL ] Iteration 133: k_eff = 1.192584 res = 4.537E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 129 D.R. = 1.79\n", - "[ NORMAL ] Iteration 134: k_eff = 1.193829 res = 5.505E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 124 D.R. = 1.21\n", - "[ NORMAL ] Iteration 135: k_eff = 1.195022 res = 6.412E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 119 D.R. = 1.16\n", - "[ NORMAL ] Iteration 136: k_eff = 1.196166 res = 6.049E-10 delta-k (pcm)\n", - "[ NORMAL ] ... = 114 D.R. = 0.01\n", - "[ NORMAL ] Iteration 137: k_eff = 1.197262 res = 4.416E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 109 D.R. = 73.00\n", - "[ NORMAL ] Iteration 138: k_eff = 1.198311 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 104 D.R. = 0.88\n", - "[ NORMAL ] Iteration 139: k_eff = 1.199316 res = 2.420E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 100 D.R. = 0.06\n", - "[ NORMAL ] Iteration 140: k_eff = 1.200279 res = 4.053E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 96 D.R. = 16.75\n", - "[ NORMAL ] Iteration 141: k_eff = 1.201201 res = 1.028E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 92 D.R. = 0.25\n", - "[ NORMAL ] Iteration 142: k_eff = 1.202083 res = 3.509E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 88 D.R. = 3.41\n", - "[ NORMAL ] Iteration 143: k_eff = 1.202927 res = 1.815E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 84 D.R. = 0.52\n", - "[ NORMAL ] Iteration 144: k_eff = 1.203736 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 80 D.R. = 1.07\n", - "[ NORMAL ] Iteration 145: k_eff = 1.204510 res = 6.836E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 77 D.R. = 3.53\n", - "[ NORMAL ] Iteration 146: k_eff = 1.205251 res = 5.324E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 74 D.R. = 0.78\n", - "[ NORMAL ] Iteration 147: k_eff = 1.205959 res = 2.299E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 70 D.R. = 0.43\n", - "[ NORMAL ] Iteration 148: k_eff = 1.206637 res = 1.815E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 67 D.R. = 0.79\n", - "[ NORMAL ] Iteration 149: k_eff = 1.207285 res = 8.469E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 64 D.R. = 0.47\n", - "[ NORMAL ] Iteration 150: k_eff = 1.207905 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 61 D.R. = 2.29\n", - "[ NORMAL ] Iteration 151: k_eff = 1.208498 res = 9.074E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 59 D.R. = 0.47\n", - "[ NORMAL ] Iteration 152: k_eff = 1.209065 res = 2.178E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 56 D.R. = 2.40\n", - "[ NORMAL ] Iteration 153: k_eff = 1.209607 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 54 D.R. = 3.11\n", - "[ NORMAL ] Iteration 154: k_eff = 1.210125 res = 9.074E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 51 D.R. = 1.34\n", - "[ NORMAL ] Iteration 155: k_eff = 1.210621 res = 5.445E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 49 D.R. = 0.06\n", - "[ NORMAL ] Iteration 156: k_eff = 1.211094 res = 6.049E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 47 D.R. = 1.11\n", - "[ NORMAL ] Iteration 157: k_eff = 1.211546 res = 6.049E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 45 D.R. = 1.00\n", - "[ NORMAL ] Iteration 158: k_eff = 1.211978 res = 4.658E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 43 D.R. = 7.70\n", - "[ NORMAL ] Iteration 159: k_eff = 1.212391 res = 1.815E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 41 D.R. = 0.04\n", - "[ NORMAL ] Iteration 160: k_eff = 1.212786 res = 1.210E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 39 D.R. = 6.67\n", - "[ NORMAL ] Iteration 161: k_eff = 1.213162 res = 6.049E-10 delta-k (pcm)\n", - "[ NORMAL ] ... = 37 D.R. = 0.05\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 162: k_eff = 1.213522 res = 1.996E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 35 D.R. = 33.00\n", - "[ NORMAL ] Iteration 163: k_eff = 1.213866 res = 4.658E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 34 D.R. = 2.33\n", - "[ NORMAL ] Iteration 164: k_eff = 1.214194 res = 1.996E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 32 D.R. = 0.43\n", - "[ NORMAL ] Iteration 165: k_eff = 1.214507 res = 1.210E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 31 D.R. = 0.06\n", - "[ NORMAL ] Iteration 166: k_eff = 1.214806 res = 1.875E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 29 D.R. = 15.50\n", - "[ NORMAL ] Iteration 167: k_eff = 1.215092 res = 4.961E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 28 D.R. = 2.65\n", - "[ NORMAL ] Iteration 168: k_eff = 1.215365 res = 6.049E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 27 D.R. = 1.22\n", - "[ NORMAL ] Iteration 169: k_eff = 1.215625 res = 2.964E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 26 D.R. = 0.49\n", - "[ NORMAL ] Iteration 170: k_eff = 1.215874 res = 5.505E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 24 D.R. = 1.86\n", - "[ NORMAL ] Iteration 171: k_eff = 1.216110 res = 2.117E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 23 D.R. = 0.38\n", - "[ NORMAL ] Iteration 172: k_eff = 1.216337 res = 4.174E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 22 D.R. = 1.97\n", - "[ NORMAL ] Iteration 173: k_eff = 1.216552 res = 3.509E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 21 D.R. = 0.84\n", - "[ NORMAL ] Iteration 174: k_eff = 1.216759 res = 2.722E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 20 D.R. = 0.78\n", - "[ NORMAL ] Iteration 175: k_eff = 1.216954 res = 2.601E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 19 D.R. = 0.96\n", - "[ NORMAL ] Iteration 176: k_eff = 1.217142 res = 4.295E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 18 D.R. = 1.65\n", - "[ NORMAL ] Iteration 177: k_eff = 1.217320 res = 4.598E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 17 D.R. = 1.07\n", - "[ NORMAL ] Iteration 178: k_eff = 1.217491 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 17 D.R. = 1.26\n", - "[ NORMAL ] Iteration 179: k_eff = 1.217654 res = 2.480E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 16 D.R. = 0.43\n", - "[ NORMAL ] Iteration 180: k_eff = 1.217809 res = 6.049E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 15 D.R. = 0.24\n", - "[ NORMAL ] Iteration 181: k_eff = 1.217956 res = 6.412E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 14 D.R. = 10.60\n", - "[ NORMAL ] Iteration 182: k_eff = 1.218098 res = 7.138E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 14 D.R. = 1.11\n", - "[ NORMAL ] Iteration 183: k_eff = 1.218232 res = 1.633E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 13 D.R. = 0.23\n", - "[ NORMAL ] Iteration 184: k_eff = 1.218360 res = 2.541E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 12 D.R. = 1.56\n", - "[ NORMAL ] Iteration 185: k_eff = 1.218482 res = 1.028E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 12 D.R. = 0.40\n", - "[ NORMAL ] Iteration 186: k_eff = 1.218599 res = 7.864E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 0.76\n", - "[ NORMAL ] Iteration 187: k_eff = 1.218709 res = 4.053E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 5.15\n", - "[ NORMAL ] Iteration 188: k_eff = 1.218815 res = 2.299E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 0.57\n", - "[ NORMAL ] Iteration 189: k_eff = 1.218916 res = 5.445E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 2.37\n", - "[ NORMAL ] Iteration 190: k_eff = 1.219011 res = 3.327E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = 0.61\n", - "[ NORMAL ] Iteration 191: k_eff = 1.219103 res = 4.840E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = 0.15\n", - "[ NORMAL ] Iteration 192: k_eff = 1.219190 res = 1.210E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 2.50\n", - "[ NORMAL ] Iteration 193: k_eff = 1.219273 res = 1.573E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 1.30\n", - "[ NORMAL ] Iteration 194: k_eff = 1.219352 res = 1.331E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 0.85\n", - "[ NORMAL ] Iteration 195: k_eff = 1.219428 res = 2.783E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 2.09\n", - "[ NORMAL ] Iteration 196: k_eff = 1.219499 res = 2.722E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 0.98\n", - "[ NORMAL ] Iteration 197: k_eff = 1.219567 res = 2.057E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.76\n", - "[ NORMAL ] Iteration 198: k_eff = 1.219633 res = 1.331E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.65\n", - "[ NORMAL ] Iteration 199: k_eff = 1.219695 res = 3.932E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 2.95\n", - "[ NORMAL ] Iteration 200: k_eff = 1.219753 res = 1.996E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.51\n", - "[ NORMAL ] Iteration 201: k_eff = 1.219810 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 2.42\n", - "[ NORMAL ] Iteration 202: k_eff = 1.219863 res = 1.270E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.26\n", - "[ NORMAL ] Iteration 203: k_eff = 1.219914 res = 2.662E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 2.10\n", - "[ NORMAL ] Iteration 204: k_eff = 1.219962 res = 5.445E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.20\n", - "[ NORMAL ] Iteration 205: k_eff = 1.220009 res = 3.327E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 6.11\n", - "[ NORMAL ] Iteration 206: k_eff = 1.220052 res = 4.658E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 1.40\n", - "[ NORMAL ] Iteration 207: k_eff = 1.220094 res = 3.025E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.65\n", - "[ NORMAL ] Iteration 208: k_eff = 1.220134 res = 2.117E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.70\n", - "[ NORMAL ] Iteration 209: k_eff = 1.220172 res = 1.875E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.89\n", - "[ NORMAL ] Iteration 210: k_eff = 1.220208 res = 1.028E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.55\n", - "[ NORMAL ] Iteration 211: k_eff = 1.220243 res = 5.263E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 5.12\n", - "[ NORMAL ] Iteration 212: k_eff = 1.220275 res = 2.480E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.47\n", - "[ NORMAL ] Iteration 213: k_eff = 1.220306 res = 4.598E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 1.85\n", - "[ NORMAL ] Iteration 214: k_eff = 1.220336 res = 3.630E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.08\n", - "[ NORMAL ] Iteration 215: k_eff = 1.220364 res = 1.391E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 3.83\n", - "[ NORMAL ] Iteration 216: k_eff = 1.220391 res = 6.049E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 4.35\n", - "[ NORMAL ] Iteration 217: k_eff = 1.220416 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.32\n", - "[ NORMAL ] Iteration 218: k_eff = 1.220441 res = 6.049E-10 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.03\n", - "[ NORMAL ] Iteration 219: k_eff = 1.220464 res = 1.270E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 21.00\n", - "[ NORMAL ] Iteration 220: k_eff = 1.220486 res = 1.452E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 1.14\n", - "[ NORMAL ] Iteration 221: k_eff = 1.220507 res = 2.299E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 1.58\n", - "[ NORMAL ] Iteration 222: k_eff = 1.220527 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.42\n", - "[ NORMAL ] Iteration 223: k_eff = 1.220545 res = 7.078E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 7.31\n", - "[ NORMAL ] Iteration 224: k_eff = 1.220563 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.14\n", - "[ NORMAL ] Iteration 225: k_eff = 1.220580 res = 3.146E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 3.25\n", - "[ NORMAL ] Iteration 226: k_eff = 1.220596 res = 1.633E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.52\n", - "[ NORMAL ] Iteration 227: k_eff = 1.220612 res = 3.569E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 2.19\n", - "[ NORMAL ] Iteration 228: k_eff = 1.220627 res = 2.722E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.76\n", - "[ NORMAL ] Iteration 229: k_eff = 1.220641 res = 1.875E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.69\n", - "[ NORMAL ] Iteration 230: k_eff = 1.220655 res = 3.448E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.84\n", - "[ NORMAL ] Iteration 231: k_eff = 1.220667 res = 8.046E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 2.33\n", - "[ NORMAL ] Iteration 232: k_eff = 1.220679 res = 3.751E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.47\n", - "[ NORMAL ] Iteration 233: k_eff = 1.220690 res = 5.686E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.52\n", - "[ NORMAL ] Iteration 234: k_eff = 1.220701 res = 1.270E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.22\n", - "[ NORMAL ] Iteration 235: k_eff = 1.220711 res = 6.715E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 0 D.R. = 5.29\n" - ] - } - ], - "source": [ - "# Generate tracks for OpenMOC\n", - "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, azim_spacing=0.1)\n", - "track_generator.generateTracks()\n", - "\n", - "# Run OpenMOC\n", - "solver = openmoc.CPUSolver(track_generator)\n", - "solver.computeEigenvalue()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We report the eigenvalues computed by OpenMC and OpenMOC here together to summarize our results." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "openmc keff = 1.224484\n", - "openmoc keff = 1.220711\n", - "bias [pcm]: -377.3\n" - ] - } - ], - "source": [ - "# Print report of keff and bias with OpenMC\n", - "openmoc_keff = solver.getKeff()\n", - "openmc_keff = sp.k_combined.n\n", - "bias = (openmoc_keff - openmc_keff) * 1e5\n", - "\n", - "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", - "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", - "print('bias [pcm]: {0:1.1f}'.format(bias))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As a sanity check, let's run a simulation with the coarse 2-group cross sections to ensure that they also produce a reasonable result." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "openmoc_geometry = get_openmoc_geometry(sp.summary.geometry)\n", - "openmoc_cells = openmoc_geometry.getRootUniverse().getAllCells()\n", - "\n", - "# Inject multi-group cross sections into OpenMOC Materials\n", - "for cell_id, cell in openmoc_cells.items():\n", - " \n", - " # Ignore the root cell\n", - " if cell.getName() == 'root cell':\n", - " continue\n", - " \n", - " openmoc_material = cell.getFillMaterial()\n", - " openmoc_material.setNumEnergyGroups(coarse_groups.num_groups)\n", - " \n", - " # Extract the appropriate cross section objects for this cell\n", - " transport = xs_library[cell_id]['transport']\n", - " nufission = xs_library[cell_id]['nu-fission']\n", - " nuscatter = xs_library[cell_id]['nu-scatter']\n", - " chi = xs_library[cell_id]['chi']\n", - " \n", - " # Perform group condensation\n", - " transport = transport.get_condensed_xs(coarse_groups)\n", - " nufission = nufission.get_condensed_xs(coarse_groups)\n", - " nuscatter = nuscatter.get_condensed_xs(coarse_groups)\n", - " chi = chi.get_condensed_xs(coarse_groups)\n", - " \n", - " # Inject NumPy arrays of cross section data into the Material\n", - " openmoc_material.setSigmaT(transport.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setNuSigmaF(nufission.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setSigmaS(nuscatter.get_xs(nuclides='sum').flatten())\n", - " openmoc_material.setChi(chi.get_xs(nuclides='sum').flatten())" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Initializing a default angular quadrature...\n", - "[ NORMAL ] Initializing 2D tracks...\n", - "[ NORMAL ] Initializing 2D tracks reflections...\n", - "[ NORMAL ] Initializing 2D tracks array...\n", - "[ NORMAL ] Ray tracing for 2D track segmentation...\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 0.09 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 10.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 19.94 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 29.87 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 39.80 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 49.72 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 59.65 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 69.58 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 79.50 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 89.43 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 100.00 %\n", - "[ NORMAL ] Initializing FSR lookup vectors\n", - "[ NORMAL ] Total number of FSRs 3\n", - "[ RESULT ] Total Track Generation & Segmentation Time...........3.9517E-02 sec\n", - "[ NORMAL ] Initializing MOC eigenvalue solver...\n", - "[ NORMAL ] Initializing solver arrays...\n", - "[ NORMAL ] Centering segments around FSR centroid...\n", - "[ NORMAL ] Max boundary angular flux storage per domain = 0.10 MB\n", - "[ NORMAL ] Max scalar flux storage per domain = 0.00 MB\n", - "[ NORMAL ] Max source storage per domain = 0.00 MB\n", - "[ NORMAL ] Number of azimuthal angles = 128\n", - "[ NORMAL ] Azimuthal ray spacing = 0.100000\n", - "[ NORMAL ] Number of polar angles = 6\n", - "[ NORMAL ] Source type = Flat\n", - "[ NORMAL ] MOC transport undamped\n", - "[ NORMAL ] CMFD acceleration: OFF\n", - "[ NORMAL ] Using 1 threads\n", - "[ NORMAL ] Computing the eigenvalue...\n", - "[ NORMAL ] Iteration 0: k_eff = 0.366880 res = 4.840E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -63312 D.R. = 0.00\n", - "[ NORMAL ] Iteration 1: k_eff = 0.391184 res = 9.679E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 2430 D.R. = 0.20\n", - "[ NORMAL ] Iteration 2: k_eff = 0.392990 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 180 D.R. = 6.00\n", - "[ NORMAL ] Iteration 3: k_eff = 0.381099 res = 9.195E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -1189 D.R. = 1.58\n", - "[ NORMAL ] Iteration 4: k_eff = 0.375018 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... -608 D.R. = 0.00\n", - "[ NORMAL ] Iteration 5: k_eff = 0.369593 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -542 D.R. = inf\n", - "[ NORMAL ] Iteration 6: k_eff = 0.365543 res = 1.065E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... -405 D.R. = 5.50\n", - "[ NORMAL ] Iteration 7: k_eff = 0.363054 res = 1.065E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... -248 D.R. = 1.00\n", - "[ NORMAL ] Iteration 8: k_eff = 0.361473 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -158 D.R. = 0.18\n", - "[ NORMAL ] Iteration 9: k_eff = 0.361280 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... -19 D.R. = 3.00\n", - "[ NORMAL ] Iteration 10: k_eff = 0.362003 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 72 D.R. = 0.33\n", - "[ NORMAL ] Iteration 11: k_eff = 0.363718 res = 4.840E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 171 D.R. = 2.50\n", - "[ NORMAL ] Iteration 12: k_eff = 0.366338 res = 1.258E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 262 D.R. = 2.60\n", - "[ NORMAL ] Iteration 13: k_eff = 0.369804 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 346 D.R. = 0.77\n", - "[ NORMAL ] Iteration 14: k_eff = 0.373989 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 418 D.R. = 0.40\n", - "[ NORMAL ] Iteration 15: k_eff = 0.378923 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 493 D.R. = 0.00\n", - "[ NORMAL ] Iteration 16: k_eff = 0.384479 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 555 D.R. = inf\n", - "[ NORMAL ] Iteration 17: k_eff = 0.390637 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 615 D.R. = 1.00\n", - "[ NORMAL ] Iteration 18: k_eff = 0.397338 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 670 D.R. = 0.00\n", - "[ NORMAL ] Iteration 19: k_eff = 0.404533 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 719 D.R. = inf\n", - "[ NORMAL ] Iteration 20: k_eff = 0.412184 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 765 D.R. = 1.67\n", - "[ NORMAL ] Iteration 21: k_eff = 0.420253 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 806 D.R. = 0.80\n", - "[ NORMAL ] Iteration 22: k_eff = 0.428686 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 843 D.R. = 0.75\n", - "[ NORMAL ] Iteration 23: k_eff = 0.437462 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 877 D.R. = 1.67\n", - "[ NORMAL ] Iteration 24: k_eff = 0.446538 res = 1.161E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 907 D.R. = 1.20\n", - "[ NORMAL ] Iteration 25: k_eff = 0.455883 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 934 D.R. = 0.17\n", - "[ NORMAL ] Iteration 26: k_eff = 0.465469 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 958 D.R. = 1.00\n", - "[ NORMAL ] Iteration 27: k_eff = 0.475265 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 979 D.R. = 2.00\n", - "[ NORMAL ] Iteration 28: k_eff = 0.485246 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 998 D.R. = 1.00\n", - "[ NORMAL ] Iteration 29: k_eff = 0.495385 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1013 D.R. = 0.50\n", - "[ NORMAL ] Iteration 30: k_eff = 0.505661 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1027 D.R. = 4.00\n", - "[ NORMAL ] Iteration 31: k_eff = 0.516051 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1038 D.R. = 1.25\n", - "[ NORMAL ] Iteration 32: k_eff = 0.526534 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1048 D.R. = 1.00\n", - "[ NORMAL ] Iteration 33: k_eff = 0.537092 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1055 D.R. = 1.00\n", - "[ NORMAL ] Iteration 34: k_eff = 0.547706 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1061 D.R. = 0.60\n", - "[ NORMAL ] Iteration 35: k_eff = 0.558361 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1065 D.R. = 0.33\n", - "[ NORMAL ] Iteration 36: k_eff = 0.569040 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1067 D.R. = 3.00\n", - "[ NORMAL ] Iteration 37: k_eff = 0.579730 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1068 D.R. = 1.67\n", - "[ NORMAL ] Iteration 38: k_eff = 0.590416 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 1068 D.R. = 0.00\n", - "[ NORMAL ] Iteration 39: k_eff = 0.601087 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1067 D.R. = inf\n", - "[ NORMAL ] Iteration 40: k_eff = 0.611731 res = 1.549E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 1064 D.R. = 1.60\n", - "[ NORMAL ] Iteration 41: k_eff = 0.622338 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1060 D.R. = 0.50\n", - "[ NORMAL ] Iteration 42: k_eff = 0.632897 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1055 D.R. = 1.00\n", - "[ NORMAL ] Iteration 43: k_eff = 0.643400 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1050 D.R. = 0.75\n", - "[ NORMAL ] Iteration 44: k_eff = 0.653837 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 1043 D.R. = 0.00\n", - "[ NORMAL ] Iteration 45: k_eff = 0.664203 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1036 D.R. = inf\n", - "[ NORMAL ] Iteration 46: k_eff = 0.674488 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1028 D.R. = 1.25\n", - "[ NORMAL ] Iteration 47: k_eff = 0.684688 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1020 D.R. = 1.00\n", - "[ NORMAL ] Iteration 48: k_eff = 0.694796 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1010 D.R. = 0.40\n", - "[ NORMAL ] Iteration 49: k_eff = 0.704807 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 1001 D.R. = 1.00\n", - "[ NORMAL ] Iteration 50: k_eff = 0.714715 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 990 D.R. = 0.50\n", - "[ NORMAL ] Iteration 51: k_eff = 0.724517 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 980 D.R. = 1.00\n", - "[ NORMAL ] Iteration 52: k_eff = 0.734209 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 969 D.R. = 1.00\n", - "[ NORMAL ] Iteration 53: k_eff = 0.743787 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 957 D.R. = 0.00\n", - "[ NORMAL ] Iteration 54: k_eff = 0.753247 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 946 D.R. = inf\n", - "[ NORMAL ] Iteration 55: k_eff = 0.762588 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 934 D.R. = 1.50\n", - "[ NORMAL ] Iteration 56: k_eff = 0.771806 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 921 D.R. = 0.33\n", - "[ NORMAL ] Iteration 57: k_eff = 0.780901 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 909 D.R. = 2.00\n", - "[ NORMAL ] Iteration 58: k_eff = 0.789868 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 896 D.R. = 0.50\n", - "[ NORMAL ] Iteration 59: k_eff = 0.798708 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 884 D.R. = 1.00\n", - "[ NORMAL ] Iteration 60: k_eff = 0.807419 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 871 D.R. = 4.00\n", - "[ NORMAL ] Iteration 61: k_eff = 0.816000 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 858 D.R. = 0.50\n", - "[ NORMAL ] Iteration 62: k_eff = 0.824450 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 844 D.R. = 1.00\n", - "[ NORMAL ] Iteration 63: k_eff = 0.832768 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 831 D.R. = 2.00\n", - "[ NORMAL ] Iteration 64: k_eff = 0.840954 res = 1.742E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 818 D.R. = 2.25\n", - "[ NORMAL ] Iteration 65: k_eff = 0.849008 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 805 D.R. = 0.44\n", - "[ NORMAL ] Iteration 66: k_eff = 0.856930 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 792 D.R. = 0.50\n", - "[ NORMAL ] Iteration 67: k_eff = 0.864720 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 778 D.R. = 1.00\n", - "[ NORMAL ] Iteration 68: k_eff = 0.872378 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 765 D.R. = 1.00\n", - "[ NORMAL ] Iteration 69: k_eff = 0.879905 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 752 D.R. = 0.50\n", - "[ NORMAL ] Iteration 70: k_eff = 0.887301 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 739 D.R. = 2.00\n", - "[ NORMAL ] Iteration 71: k_eff = 0.894566 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 726 D.R. = 1.50\n", - "[ NORMAL ] Iteration 72: k_eff = 0.901702 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 713 D.R. = 0.33\n", - "[ NORMAL ] Iteration 73: k_eff = 0.908710 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 700 D.R. = 2.00\n", - "[ NORMAL ] Iteration 74: k_eff = 0.915590 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 687 D.R. = 1.50\n", - "[ NORMAL ] Iteration 75: k_eff = 0.922342 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 675 D.R. = 0.00\n", - "[ NORMAL ] Iteration 76: k_eff = 0.928971 res = 1.161E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 662 D.R. = inf\n", - "[ NORMAL ] Iteration 77: k_eff = 0.935474 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 650 D.R. = 0.17\n", - "[ NORMAL ] Iteration 78: k_eff = 0.941853 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 637 D.R. = 1.00\n", - "[ NORMAL ] Iteration 79: k_eff = 0.948112 res = 9.679E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 625 D.R. = 5.00\n", - "[ NORMAL ] Iteration 80: k_eff = 0.954249 res = 1.065E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 613 D.R. = 1.10\n", - "[ NORMAL ] Iteration 81: k_eff = 0.960267 res = 9.679E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 601 D.R. = 0.09\n", - "[ NORMAL ] Iteration 82: k_eff = 0.966168 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 590 D.R. = 8.00\n", - "[ NORMAL ] Iteration 83: k_eff = 0.971953 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 578 D.R. = 0.75\n", - "[ NORMAL ] Iteration 84: k_eff = 0.977623 res = 1.936E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 566 D.R. = 0.33\n", - "[ NORMAL ] Iteration 85: k_eff = 0.983179 res = 2.904E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 555 D.R. = 1.50\n", - "[ NORMAL ] Iteration 86: k_eff = 0.988624 res = 0.000E+00 delta-k (pcm) =\n", - "[ NORMAL ] ... 544 D.R. = 0.00\n", - "[ NORMAL ] Iteration 87: k_eff = 0.993958 res = 6.775E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 533 D.R. = inf\n", - "[ NORMAL ] Iteration 88: k_eff = 0.999184 res = 9.679E-09 delta-k (pcm) =\n", - "[ NORMAL ] ... 522 D.R. = 0.14\n", - "[ NORMAL ] Iteration 89: k_eff = 1.004304 res = 4.840E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 511 D.R. = 5.00\n", - "[ NORMAL ] Iteration 90: k_eff = 1.009318 res = 3.872E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 501 D.R. = 0.80\n", - "[ NORMAL ] Iteration 91: k_eff = 1.014228 res = 4.840E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 491 D.R. = 1.25\n", - "[ NORMAL ] Iteration 92: k_eff = 1.019037 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 480 D.R. = 1.20\n", - "[ NORMAL ] Iteration 93: k_eff = 1.023744 res = 2.904E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 470 D.R. = 0.50\n", - "[ NORMAL ] Iteration 94: k_eff = 1.028353 res = 6.775E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 460 D.R. = 2.33\n", - "[ NORMAL ] Iteration 95: k_eff = 1.032865 res = 7.743E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 451 D.R. = 1.14\n", - "[ NORMAL ] Iteration 96: k_eff = 1.037281 res = 1.355E-07 delta-k (pcm) =\n", - "[ NORMAL ] ... 441 D.R. = 1.75\n", - "[ NORMAL ] Iteration 97: k_eff = 1.041604 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 432 D.R. = 0.43\n", - "[ NORMAL ] Iteration 98: k_eff = 1.045834 res = 4.840E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 422 D.R. = 0.83\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 99: k_eff = 1.049974 res = 5.807E-08 delta-k (pcm) =\n", - "[ NORMAL ] ... 413 D.R. = 1.20\n", - "[ NORMAL ] Iteration 100: k_eff = 1.054024 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 405 D.R. = 1.00\n", - "[ NORMAL ] Iteration 101: k_eff = 1.057987 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 396 D.R. = 0.83\n", - "[ NORMAL ] Iteration 102: k_eff = 1.061864 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 387 D.R. = 0.20\n", - "[ NORMAL ] Iteration 103: k_eff = 1.065657 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 379 D.R. = 3.00\n", - "[ NORMAL ] Iteration 104: k_eff = 1.069367 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 370 D.R. = 1.33\n", - "[ NORMAL ] Iteration 105: k_eff = 1.072996 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 362 D.R. = 1.00\n", - "[ NORMAL ] Iteration 106: k_eff = 1.076545 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 354 D.R. = 0.50\n", - "[ NORMAL ] Iteration 107: k_eff = 1.080016 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 347 D.R. = 3.50\n", - "[ NORMAL ] Iteration 108: k_eff = 1.083411 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 339 D.R. = 1.71\n", - "[ NORMAL ] Iteration 109: k_eff = 1.086731 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 331 D.R. = 0.50\n", - "[ NORMAL ] Iteration 110: k_eff = 1.089976 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 324 D.R. = 0.33\n", - "[ NORMAL ] Iteration 111: k_eff = 1.093150 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 317 D.R. = 4.00\n", - "[ NORMAL ] Iteration 112: k_eff = 1.096253 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 310 D.R. = 1.00\n", - "[ NORMAL ] Iteration 113: k_eff = 1.099286 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 303 D.R. = 0.50\n", - "[ NORMAL ] Iteration 114: k_eff = 1.102251 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 296 D.R. = 1.25\n", - "[ NORMAL ] Iteration 115: k_eff = 1.105150 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 289 D.R. = 0.20\n", - "[ NORMAL ] Iteration 116: k_eff = 1.107983 res = 1.452E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 283 D.R. = 15.00\n", - "[ NORMAL ] Iteration 117: k_eff = 1.110753 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 276 D.R. = 0.33\n", - "[ NORMAL ] Iteration 118: k_eff = 1.113459 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 270 D.R. = 1.80\n", - "[ NORMAL ] Iteration 119: k_eff = 1.116105 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 264 D.R. = 1.22\n", - "[ NORMAL ] Iteration 120: k_eff = 1.118690 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 258 D.R. = 0.36\n", - "[ NORMAL ] Iteration 121: k_eff = 1.121216 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 252 D.R. = 0.25\n", - "[ NORMAL ] Iteration 122: k_eff = 1.123685 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 246 D.R. = 1.00\n", - "[ NORMAL ] Iteration 123: k_eff = 1.126097 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 241 D.R. = 4.00\n", - "[ NORMAL ] Iteration 124: k_eff = 1.128454 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 235 D.R. = 0.00\n", - "[ NORMAL ] Iteration 125: k_eff = 1.130758 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 230 D.R. = inf\n", - "[ NORMAL ] Iteration 126: k_eff = 1.133008 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 224 D.R. = 5.50\n", - "[ NORMAL ] Iteration 127: k_eff = 1.135207 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 219 D.R. = 0.45\n", - "[ NORMAL ] Iteration 128: k_eff = 1.137354 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 214 D.R. = 0.40\n", - "[ NORMAL ] Iteration 129: k_eff = 1.139453 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 209 D.R. = 0.00\n", - "[ NORMAL ] Iteration 130: k_eff = 1.141503 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 204 D.R. = inf\n", - "[ NORMAL ] Iteration 131: k_eff = 1.143505 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 200 D.R. = 1.50\n", - "[ NORMAL ] Iteration 132: k_eff = 1.145461 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 195 D.R. = 2.00\n", - "[ NORMAL ] Iteration 133: k_eff = 1.147372 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 191 D.R. = 1.50\n", - "[ NORMAL ] Iteration 134: k_eff = 1.149238 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 186 D.R. = 1.22\n", - "[ NORMAL ] Iteration 135: k_eff = 1.151061 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 182 D.R. = 0.18\n", - "[ NORMAL ] Iteration 136: k_eff = 1.152842 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 178 D.R. = 1.00\n", - "[ NORMAL ] Iteration 137: k_eff = 1.154581 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 173 D.R. = 2.00\n", - "[ NORMAL ] Iteration 138: k_eff = 1.156279 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 169 D.R. = 2.50\n", - "[ NORMAL ] Iteration 139: k_eff = 1.157938 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 165 D.R. = 0.80\n", - "[ NORMAL ] Iteration 140: k_eff = 1.159557 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 161 D.R. = 1.50\n", - "[ NORMAL ] Iteration 141: k_eff = 1.161139 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 158 D.R. = 0.33\n", - "[ NORMAL ] Iteration 142: k_eff = 1.162684 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 154 D.R. = 1.00\n", - "[ NORMAL ] Iteration 143: k_eff = 1.164193 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 150 D.R. = 2.75\n", - "[ NORMAL ] Iteration 144: k_eff = 1.165666 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 147 D.R. = 0.09\n", - "[ NORMAL ] Iteration 145: k_eff = 1.167105 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 143 D.R. = 2.00\n", - "[ NORMAL ] Iteration 146: k_eff = 1.168509 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 140 D.R. = 4.00\n", - "[ NORMAL ] Iteration 147: k_eff = 1.169881 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 137 D.R. = 1.25\n", - "[ NORMAL ] Iteration 148: k_eff = 1.171220 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 133 D.R. = 0.10\n", - "[ NORMAL ] Iteration 149: k_eff = 1.172528 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 130 D.R. = 6.00\n", - "[ NORMAL ] Iteration 150: k_eff = 1.173804 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 127 D.R. = 1.67\n", - "[ NORMAL ] Iteration 151: k_eff = 1.175051 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 124 D.R. = 0.80\n", - "[ NORMAL ] Iteration 152: k_eff = 1.176268 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 121 D.R. = 1.00\n", - "[ NORMAL ] Iteration 153: k_eff = 1.177456 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 118 D.R. = 1.00\n", - "[ NORMAL ] Iteration 154: k_eff = 1.178616 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 115 D.R. = 0.63\n", - "[ NORMAL ] Iteration 155: k_eff = 1.179749 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 113 D.R. = 1.20\n", - "[ NORMAL ] Iteration 156: k_eff = 1.180855 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 110 D.R. = 0.83\n", - "[ NORMAL ] Iteration 157: k_eff = 1.181935 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 107 D.R. = 0.20\n", - "[ NORMAL ] Iteration 158: k_eff = 1.182988 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 105 D.R. = 3.00\n", - "[ NORMAL ] Iteration 159: k_eff = 1.184017 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 102 D.R. = 0.67\n", - "[ NORMAL ] Iteration 160: k_eff = 1.185021 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 100 D.R. = 1.50\n", - "[ NORMAL ] Iteration 161: k_eff = 1.186002 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 98 D.R. = 0.67\n", - "[ NORMAL ] Iteration 162: k_eff = 1.186959 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 95 D.R. = 2.50\n", - "[ NORMAL ] Iteration 163: k_eff = 1.187893 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 93 D.R. = 1.40\n", - "[ NORMAL ] Iteration 164: k_eff = 1.188805 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 91 D.R. = 1.29\n", - "[ NORMAL ] Iteration 165: k_eff = 1.189695 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 89 D.R. = 0.22\n", - "[ NORMAL ] Iteration 166: k_eff = 1.190564 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 86 D.R. = 2.00\n", - "[ NORMAL ] Iteration 167: k_eff = 1.191413 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 84 D.R. = 2.00\n", - "[ NORMAL ] Iteration 168: k_eff = 1.192241 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 82 D.R. = 0.00\n", - "[ NORMAL ] Iteration 169: k_eff = 1.193049 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 80 D.R. = inf\n", - "[ NORMAL ] Iteration 170: k_eff = 1.193838 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 78 D.R. = 4.50\n", - "[ NORMAL ] Iteration 171: k_eff = 1.194607 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 76 D.R. = 0.56\n", - "[ NORMAL ] Iteration 172: k_eff = 1.195359 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 75 D.R. = 1.20\n", - "[ NORMAL ] Iteration 173: k_eff = 1.196092 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 73 D.R. = 0.67\n", - "[ NORMAL ] Iteration 174: k_eff = 1.196808 res = 1.355E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 71 D.R. = 3.50\n", - "[ NORMAL ] Iteration 175: k_eff = 1.197507 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 69 D.R. = 0.86\n", - "[ NORMAL ] Iteration 176: k_eff = 1.198190 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 68 D.R. = 0.33\n", - "[ NORMAL ] Iteration 177: k_eff = 1.198855 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 66 D.R. = 0.75\n", - "[ NORMAL ] Iteration 178: k_eff = 1.199505 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 64 D.R. = 0.67\n", - "[ NORMAL ] Iteration 179: k_eff = 1.200139 res = 1.258E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 63 D.R. = 6.50\n", - "[ NORMAL ] Iteration 180: k_eff = 1.200757 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 61 D.R. = 0.62\n", - "[ NORMAL ] Iteration 181: k_eff = 1.201361 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 60 D.R. = 0.25\n", - "[ NORMAL ] Iteration 182: k_eff = 1.201951 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 58 D.R. = 1.50\n", - "[ NORMAL ] Iteration 183: k_eff = 1.202526 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 57 D.R. = 0.33\n", - "[ NORMAL ] Iteration 184: k_eff = 1.203088 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 56 D.R. = 5.00\n", - "[ NORMAL ] Iteration 185: k_eff = 1.203636 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 54 D.R. = 0.00\n", - "[ NORMAL ] Iteration 186: k_eff = 1.204171 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 53 D.R. = inf\n", - "[ NORMAL ] Iteration 187: k_eff = 1.204692 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 52 D.R. = 2.33\n", - "[ NORMAL ] Iteration 188: k_eff = 1.205202 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 50 D.R. = 0.57\n", - "[ NORMAL ] Iteration 189: k_eff = 1.205698 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 49 D.R. = 0.50\n", - "[ NORMAL ] Iteration 190: k_eff = 1.206183 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 48 D.R. = 0.50\n", - "[ NORMAL ] Iteration 191: k_eff = 1.206656 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 47 D.R. = 6.00\n", - "[ NORMAL ] Iteration 192: k_eff = 1.207118 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 46 D.R. = 0.00\n", - "[ NORMAL ] Iteration 193: k_eff = 1.207570 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 45 D.R. = inf\n", - "[ NORMAL ] Iteration 194: k_eff = 1.208010 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 44 D.R. = 0.33\n", - "[ NORMAL ] Iteration 195: k_eff = 1.208439 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 42 D.R. = 1.33\n", - "[ NORMAL ] Iteration 196: k_eff = 1.208858 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 41 D.R. = 0.50\n", - "[ NORMAL ] Iteration 197: k_eff = 1.209267 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 40 D.R. = 1.50\n", - "[ NORMAL ] Iteration 198: k_eff = 1.209665 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 39 D.R. = 1.33\n", - "[ NORMAL ] Iteration 199: k_eff = 1.210055 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 38 D.R. = 1.50\n", - "[ NORMAL ] Iteration 200: k_eff = 1.210435 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 37 D.R. = 0.17\n", - "[ NORMAL ] Iteration 201: k_eff = 1.210805 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 37 D.R. = 9.00\n", - "[ NORMAL ] Iteration 202: k_eff = 1.211167 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 36 D.R. = 0.11\n", - "[ NORMAL ] Iteration 203: k_eff = 1.211520 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 35 D.R. = 5.00\n", - "[ NORMAL ] Iteration 204: k_eff = 1.211864 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 34 D.R. = 0.60\n", - "[ NORMAL ] Iteration 205: k_eff = 1.212200 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 33 D.R. = 0.67\n", - "[ NORMAL ] Iteration 206: k_eff = 1.212528 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 32 D.R. = 2.50\n", - "[ NORMAL ] Iteration 207: k_eff = 1.212848 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 32 D.R. = 1.60\n", - "[ NORMAL ] Iteration 208: k_eff = 1.213160 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 31 D.R. = 0.25\n", - "[ NORMAL ] Iteration 209: k_eff = 1.213466 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 30 D.R. = 5.50\n", - "[ NORMAL ] Iteration 210: k_eff = 1.213763 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 29 D.R. = 0.55\n", - "[ NORMAL ] Iteration 211: k_eff = 1.214053 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 29 D.R. = 1.67\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 212: k_eff = 1.214337 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 28 D.R. = 0.30\n", - "[ NORMAL ] Iteration 213: k_eff = 1.214614 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 27 D.R. = 2.33\n", - "[ NORMAL ] Iteration 214: k_eff = 1.214883 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 26 D.R. = 1.29\n", - "[ NORMAL ] Iteration 215: k_eff = 1.215145 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 26 D.R. = 0.56\n", - "[ NORMAL ] Iteration 216: k_eff = 1.215402 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 25 D.R. = 0.40\n", - "[ NORMAL ] Iteration 217: k_eff = 1.215653 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 25 D.R. = 3.00\n", - "[ NORMAL ] Iteration 218: k_eff = 1.215897 res = 1.258E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 24 D.R. = 2.17\n", - "[ NORMAL ] Iteration 219: k_eff = 1.216136 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 23 D.R. = 0.77\n", - "[ NORMAL ] Iteration 220: k_eff = 1.216368 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 23 D.R. = 0.80\n", - "[ NORMAL ] Iteration 221: k_eff = 1.216595 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 22 D.R. = 0.25\n", - "[ NORMAL ] Iteration 222: k_eff = 1.216817 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 22 D.R. = 3.00\n", - "[ NORMAL ] Iteration 223: k_eff = 1.217033 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 21 D.R. = 0.33\n", - "[ NORMAL ] Iteration 224: k_eff = 1.217244 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 21 D.R. = 4.00\n", - "[ NORMAL ] Iteration 225: k_eff = 1.217450 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 20 D.R. = 0.75\n", - "[ NORMAL ] Iteration 226: k_eff = 1.217651 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 20 D.R. = 0.17\n", - "[ NORMAL ] Iteration 227: k_eff = 1.217847 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 19 D.R. = 4.00\n", - "[ NORMAL ] Iteration 228: k_eff = 1.218039 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 19 D.R. = 2.50\n", - "[ NORMAL ] Iteration 229: k_eff = 1.218225 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 18 D.R. = 0.20\n", - "[ NORMAL ] Iteration 230: k_eff = 1.218407 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 18 D.R. = 2.50\n", - "[ NORMAL ] Iteration 231: k_eff = 1.218585 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 17 D.R. = 1.00\n", - "[ NORMAL ] Iteration 232: k_eff = 1.218758 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 17 D.R. = 1.40\n", - "[ NORMAL ] Iteration 233: k_eff = 1.218927 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 16 D.R. = 0.71\n", - "[ NORMAL ] Iteration 234: k_eff = 1.219092 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 16 D.R. = 1.00\n", - "[ NORMAL ] Iteration 235: k_eff = 1.219253 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 16 D.R. = 1.40\n", - "[ NORMAL ] Iteration 236: k_eff = 1.219410 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 15 D.R. = 0.57\n", - "[ NORMAL ] Iteration 237: k_eff = 1.219563 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 15 D.R. = 0.50\n", - "[ NORMAL ] Iteration 238: k_eff = 1.219712 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 14 D.R. = 0.00\n", - "[ NORMAL ] Iteration 239: k_eff = 1.219858 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 14 D.R. = -nan\n", - "[ NORMAL ] Iteration 240: k_eff = 1.220000 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 14 D.R. = inf\n", - "[ NORMAL ] Iteration 241: k_eff = 1.220139 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 13 D.R. = 1.13\n", - "[ NORMAL ] Iteration 242: k_eff = 1.220274 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 13 D.R. = 1.11\n", - "[ NORMAL ] Iteration 243: k_eff = 1.220407 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 13 D.R. = 1.10\n", - "[ NORMAL ] Iteration 244: k_eff = 1.220536 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 12 D.R. = 0.64\n", - "[ NORMAL ] Iteration 245: k_eff = 1.220662 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 12 D.R. = 0.43\n", - "[ NORMAL ] Iteration 246: k_eff = 1.220784 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 12 D.R. = 0.67\n", - "[ NORMAL ] Iteration 247: k_eff = 1.220904 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 1.00\n", - "[ NORMAL ] Iteration 248: k_eff = 1.221021 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 3.50\n", - "[ NORMAL ] Iteration 249: k_eff = 1.221135 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 1.43\n", - "[ NORMAL ] Iteration 250: k_eff = 1.221246 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 11 D.R. = 0.80\n", - "[ NORMAL ] Iteration 251: k_eff = 1.221355 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 0.87\n", - "[ NORMAL ] Iteration 252: k_eff = 1.221461 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 0.43\n", - "[ NORMAL ] Iteration 253: k_eff = 1.221564 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 1.67\n", - "[ NORMAL ] Iteration 254: k_eff = 1.221665 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 10 D.R. = 0.40\n", - "[ NORMAL ] Iteration 255: k_eff = 1.221763 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = 0.00\n", - "[ NORMAL ] Iteration 256: k_eff = 1.221859 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = inf\n", - "[ NORMAL ] Iteration 257: k_eff = 1.221953 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = 1.00\n", - "[ NORMAL ] Iteration 258: k_eff = 1.222044 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 9 D.R. = 0.40\n", - "[ NORMAL ] Iteration 259: k_eff = 1.222133 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 1.50\n", - "[ NORMAL ] Iteration 260: k_eff = 1.222220 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 0.00\n", - "[ NORMAL ] Iteration 261: k_eff = 1.222305 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = inf\n", - "[ NORMAL ] Iteration 262: k_eff = 1.222387 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 1.17\n", - "[ NORMAL ] Iteration 263: k_eff = 1.222468 res = 1.839E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 8 D.R. = 2.71\n", - "[ NORMAL ] Iteration 264: k_eff = 1.222547 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 0.16\n", - "[ NORMAL ] Iteration 265: k_eff = 1.222624 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 1.00\n", - "[ NORMAL ] Iteration 266: k_eff = 1.222699 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 0.33\n", - "[ NORMAL ] Iteration 267: k_eff = 1.222772 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 6.00\n", - "[ NORMAL ] Iteration 268: k_eff = 1.222844 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 7 D.R. = 1.17\n", - "[ NORMAL ] Iteration 269: k_eff = 1.222913 res = 1.452E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 2.14\n", - "[ NORMAL ] Iteration 270: k_eff = 1.222981 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.40\n", - "[ NORMAL ] Iteration 271: k_eff = 1.223048 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.17\n", - "[ NORMAL ] Iteration 272: k_eff = 1.223113 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 3.00\n", - "[ NORMAL ] Iteration 273: k_eff = 1.223176 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 1.33\n", - "[ NORMAL ] Iteration 274: k_eff = 1.223238 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 1.00\n", - "[ NORMAL ] Iteration 275: k_eff = 1.223298 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 1.00\n", - "[ NORMAL ] Iteration 276: k_eff = 1.223357 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 1.00\n", - "[ NORMAL ] Iteration 277: k_eff = 1.223414 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.50\n", - "[ NORMAL ] Iteration 278: k_eff = 1.223470 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 1.50\n", - "[ NORMAL ] Iteration 279: k_eff = 1.223524 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 1.67\n", - "[ NORMAL ] Iteration 280: k_eff = 1.223577 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.20\n", - "[ NORMAL ] Iteration 281: k_eff = 1.223629 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 5.00\n", - "[ NORMAL ] Iteration 282: k_eff = 1.223680 res = 1.258E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 2.60\n", - "[ NORMAL ] Iteration 283: k_eff = 1.223729 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.77\n", - "[ NORMAL ] Iteration 284: k_eff = 1.223777 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.70\n", - "[ NORMAL ] Iteration 285: k_eff = 1.223824 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 1.00\n", - "[ NORMAL ] Iteration 286: k_eff = 1.223870 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 1.00\n", - "[ NORMAL ] Iteration 287: k_eff = 1.223915 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.29\n", - "[ NORMAL ] Iteration 288: k_eff = 1.223959 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.00\n", - "[ NORMAL ] Iteration 289: k_eff = 1.224001 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = inf\n", - "[ NORMAL ] Iteration 290: k_eff = 1.224043 res = 1.355E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 2.80\n", - "[ NORMAL ] Iteration 291: k_eff = 1.224083 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.57\n", - "[ NORMAL ] Iteration 292: k_eff = 1.224123 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.37\n", - "[ NORMAL ] Iteration 293: k_eff = 1.224161 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 1.33\n", - "[ NORMAL ] Iteration 294: k_eff = 1.224199 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 2.00\n", - "[ NORMAL ] Iteration 295: k_eff = 1.224235 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.50\n", - "[ NORMAL ] Iteration 296: k_eff = 1.224271 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 1.75\n", - "[ NORMAL ] Iteration 297: k_eff = 1.224306 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 1.71\n", - "[ NORMAL ] Iteration 298: k_eff = 1.224340 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.08\n", - "[ NORMAL ] Iteration 299: k_eff = 1.224373 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 2.00\n", - "[ NORMAL ] Iteration 300: k_eff = 1.224406 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 5.50\n", - "[ NORMAL ] Iteration 301: k_eff = 1.224438 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.82\n", - "[ NORMAL ] Iteration 302: k_eff = 1.224468 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.78\n", - "[ NORMAL ] Iteration 303: k_eff = 1.224498 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.71\n", - "[ NORMAL ] Iteration 304: k_eff = 1.224528 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.40\n", - "[ NORMAL ] Iteration 305: k_eff = 1.224557 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 3.00\n", - "[ NORMAL ] Iteration 306: k_eff = 1.224585 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.83\n", - "[ NORMAL ] Iteration 307: k_eff = 1.224612 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.20\n", - "[ NORMAL ] Iteration 308: k_eff = 1.224639 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 3.00\n", - "[ NORMAL ] Iteration 309: k_eff = 1.224665 res = 9.679E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 3.33\n", - "[ NORMAL ] Iteration 310: k_eff = 1.224691 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.80\n", - "[ NORMAL ] Iteration 311: k_eff = 1.224716 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.50\n", - "[ NORMAL ] Iteration 312: k_eff = 1.224740 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.75\n", - "[ NORMAL ] Iteration 313: k_eff = 1.224764 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 4.00\n", - "[ NORMAL ] Iteration 314: k_eff = 1.224786 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.17\n", - "[ NORMAL ] Iteration 315: k_eff = 1.224809 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 1.50\n", - "[ NORMAL ] Iteration 316: k_eff = 1.224831 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 3.67\n", - "[ NORMAL ] Iteration 317: k_eff = 1.224852 res = 1.161E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 1.09\n", - "[ NORMAL ] Iteration 318: k_eff = 1.224873 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.00\n", - "[ NORMAL ] Iteration 319: k_eff = 1.224893 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = inf\n", - "[ NORMAL ] Iteration 320: k_eff = 1.224913 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.63\n", - "[ NORMAL ] Iteration 321: k_eff = 1.224932 res = 6.775E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.40\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 322: k_eff = 1.224951 res = 8.711E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.29\n", - "[ NORMAL ] Iteration 323: k_eff = 1.224969 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.11\n", - "[ NORMAL ] Iteration 324: k_eff = 1.224987 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 8.00\n", - "[ NORMAL ] Iteration 325: k_eff = 1.225005 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.25\n", - "[ NORMAL ] Iteration 326: k_eff = 1.225022 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.50\n", - "[ NORMAL ] Iteration 327: k_eff = 1.225039 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 2.00\n", - "[ NORMAL ] Iteration 328: k_eff = 1.225055 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 3.00\n", - "[ NORMAL ] Iteration 329: k_eff = 1.225071 res = 1.065E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.83\n", - "[ NORMAL ] Iteration 330: k_eff = 1.225086 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.27\n", - "[ NORMAL ] Iteration 331: k_eff = 1.225102 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.00\n", - "[ NORMAL ] Iteration 332: k_eff = 1.225116 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.00\n", - "[ NORMAL ] Iteration 333: k_eff = 1.225131 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 2.00\n", - "[ NORMAL ] Iteration 334: k_eff = 1.225145 res = 4.840E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.83\n", - "[ NORMAL ] Iteration 335: k_eff = 1.225159 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.20\n", - "[ NORMAL ] Iteration 336: k_eff = 1.225172 res = 5.807E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 6.00\n", - "[ NORMAL ] Iteration 337: k_eff = 1.225185 res = 1.355E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 2.33\n", - "[ NORMAL ] Iteration 338: k_eff = 1.225198 res = 1.258E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.93\n", - "[ NORMAL ] Iteration 339: k_eff = 1.225210 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.00\n", - "[ NORMAL ] Iteration 340: k_eff = 1.225222 res = 9.679E-09 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = inf\n", - "[ NORMAL ] Iteration 341: k_eff = 1.225233 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 4.00\n", - "[ NORMAL ] Iteration 342: k_eff = 1.225245 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.50\n", - "[ NORMAL ] Iteration 343: k_eff = 1.225256 res = 0.000E+00 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.00\n", - "[ NORMAL ] Iteration 344: k_eff = 1.225267 res = 7.743E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = inf\n", - "[ NORMAL ] Iteration 345: k_eff = 1.225278 res = 2.904E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.38\n", - "[ NORMAL ] Iteration 346: k_eff = 1.225288 res = 3.872E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 1.33\n", - "[ NORMAL ] Iteration 347: k_eff = 1.225298 res = 1.936E-08 delta-k (pcm)\n", - "[ NORMAL ] ... = 0 D.R. = 0.50\n" - ] - } - ], - "source": [ - "# Generate tracks for OpenMOC\n", - "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=128, azim_spacing=0.1)\n", - "track_generator.generateTracks()\n", - "\n", - "# Run OpenMOC\n", - "solver = openmoc.CPUSolver(track_generator)\n", - "solver.computeEigenvalue()" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "openmc keff = 1.224484\n", - "openmoc keff = 1.225298\n", - "bias [pcm]: 81.4\n" - ] - } - ], - "source": [ - "# Print report of keff and bias with OpenMC\n", - "openmoc_keff = solver.getKeff()\n", - "openmc_keff = sp.k_combined.n\n", - "bias = (openmoc_keff - openmc_keff) * 1e5\n", - "\n", - "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", - "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", - "print('bias [pcm]: {0:1.1f}'.format(bias))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is a non-trivial bias in both the 2-group and 8-group cases. In the case of a pin cell, one can show that these biases do not converge to <100 pcm with more particle histories. For heterogeneous geometries, additional measures must be taken to address the following three sources of bias:\n", - "\n", - "* Appropriate transport-corrected cross sections\n", - "* Spatial discretization of OpenMOC's mesh\n", - "* Constant-in-angle multi-group cross sections" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "## Visualizing MGXS Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is often insightful to generate visual depictions of multi-group cross sections. There are many different types of plots which may be useful for multi-group cross section visualization, only a few of which will be shown here for enrichment and inspiration.\n", - "\n", - "One particularly useful visualization is a comparison of the continuous-energy and multi-group cross sections for a particular nuclide and reaction type. We illustrate one option for generating such plots with the use of the `openmc.plotter` module to plot continuous-energy cross sections from the openly available cross section library distributed by NNDC.\n", - "\n", - "The MGXS data can also be plotted using the openmc.plot_xs command, however we will do this manually here to show how the openmc.Mgxs.get_xs method can be used to obtain data." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1e-05, 20000000.0)" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Create a figure of the U-235 continuous-energy fission cross section \n", - "fig = openmc.plot_xs('U235', ['fission'])\n", - "\n", - "# Get the axis to use for plotting the MGXS\n", - "ax = fig.gca()\n", - "\n", - "# Extract energy group bounds and MGXS values to plot\n", - "fission = xs_library[fuel_cell.id]['fission']\n", - "energy_groups = fission.energy_groups\n", - "x = energy_groups.group_edges\n", - "y = fission.get_xs(nuclides=['U235'], order_groups='decreasing', xs_type='micro')\n", - "y = np.squeeze(y)\n", - "\n", - "# Fix low energy bound\n", - "x[0] = 1.e-5\n", - "\n", - "# Extend the mgxs values array for matplotlib's step plot\n", - "y = np.insert(y, 0, y[0])\n", - "\n", - "# Create a step plot for the MGXS\n", - "ax.plot(x, y, drawstyle='steps', color='r', linewidth=3)\n", - "\n", - "ax.set_title('U-235 Fission Cross Section')\n", - "ax.legend(['Continuous', 'Multi-Group'])\n", - "ax.set_xlim((x.min(), x.max()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another useful type of illustration is scattering matrix sparsity structures. First, we extract Pandas `DataFrames` for the H-1 and O-16 scattering matrices." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "# Construct a Pandas DataFrame for the microscopic nu-scattering matrix\n", - "nuscatter = xs_library[moderator_cell.id]['nu-scatter']\n", - "df = nuscatter.get_pandas_dataframe(xs_type='micro')\n", - "\n", - "# Slice DataFrame in two for each nuclide's mean values\n", - "h1 = df[df['nuclide'] == 'H1']['mean']\n", - "o16 = df[df['nuclide'] == 'O16']['mean']\n", - "\n", - "# Cast DataFrames as NumPy arrays\n", - "h1 = h1.values\n", - "o16 = o16.values\n", - "\n", - "# Reshape arrays to 2D matrix for plotting\n", - "h1.shape = (fine_groups.num_groups, fine_groups.num_groups)\n", - "o16.shape = (fine_groups.num_groups, fine_groups.num_groups)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Matplotlib's `imshow` routine can be used to plot the matrices to illustrate their sparsity structures." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Create plot of the H-1 scattering matrix\n", - "fig = plt.subplot(121)\n", - "fig.imshow(h1, interpolation='nearest', cmap='jet')\n", - "plt.title('H-1 Scattering Matrix')\n", - "plt.xlabel('Group Out')\n", - "plt.ylabel('Group In')\n", - "\n", - "# Create plot of the O-16 scattering matrix\n", - "fig2 = plt.subplot(122)\n", - "fig2.imshow(o16, interpolation='nearest', cmap='jet')\n", - "plt.title('O-16 Scattering Matrix')\n", - "plt.xlabel('Group Out')\n", - "plt.ylabel('Group In')\n", - "\n", - "# Show the plot on screen\n", - "plt.show()" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/mgxs-part-iii.ipynb b/examples/jupyter/mgxs-part-iii.ipynb deleted file mode 100644 index a4c440b3a..000000000 --- a/examples/jupyter/mgxs-part-iii.ipynb +++ /dev/null @@ -1,1667 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This IPython Notebook illustrates the use of the **`openmc.mgxs.Library`** class. The `Library` class is designed to automate the calculation of multi-group cross sections for use cases with one or more domains, cross section types, and/or nuclides. In particular, this Notebook illustrates the following features:\n", - "\n", - "* Calculation of multi-group cross sections for a **fuel assembly**\n", - "* Automated creation, manipulation and storage of `MGXS` with **`openmc.mgxs.Library`**\n", - "* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n", - "* Steady-state pin-by-pin **fission rates comparison** between OpenMC and [OpenMOC](https://mit-crpg.github.io/OpenMOC/)\n", - "\n", - "**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "import pickle\n", - "\n", - "from IPython.display import Image\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "import openmc\n", - "import openmc.mgxs\n", - "from openmc.openmoc_compatible import get_openmoc_geometry\n", - "import openmoc\n", - "import openmoc.process\n", - "from openmoc.materialize import load_openmc_mgxs_lib\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. We'll create three materials for the fuel, water, and cladding of the fuel pins." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6 enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "water.add_nuclide('B10', 8.0042e-6)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a `Materials` object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials object\n", - "materials_file = openmc.Materials([fuel, water, zircaloy])\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a square array of fuel pins and control rod guide tubes for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "min_x = openmc.XPlane(x0=-10.71, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+10.71, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-10.71, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=+10.71, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-10., boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=+10., boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "fuel_pin_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "fuel_pin_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "fuel_pin_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "fuel_pin_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Likewise, we can construct a control rod guide tube with the same surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a control rod guide tube\n", - "guide_tube_universe = openmc.Universe(name='Guide Tube')\n", - "\n", - "# Create guide tube Cell\n", - "guide_tube_cell = openmc.Cell(name='Guide Tube Water')\n", - "guide_tube_cell.fill = water\n", - "guide_tube_cell.region = -fuel_outer_radius\n", - "guide_tube_universe.add_cell(guide_tube_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='Guide Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "guide_tube_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='Guide Tube Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "guide_tube_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel assembly Lattice\n", - "assembly = openmc.RectLattice(name='1.6% Fuel Assembly')\n", - "assembly.pitch = (1.26, 1.26)\n", - "assembly.lower_left = [-1.26 * 17. / 2.0] * 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we create a NumPy array of fuel pin and guide tube universes for the lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Create array indices for guide tube locations in lattice\n", - "template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8,\n", - " 11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11])\n", - "template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8,\n", - " 8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14])\n", - "\n", - "# Initialize an empty 17x17 array of the lattice universes\n", - "universes = np.empty((17, 17), dtype=openmc.Universe)\n", - "\n", - "# Fill the array with the fuel pin and guide tube universes\n", - "universes[:,:] = fuel_pin_universe\n", - "universes[template_x, template_y] = guide_tube_universe\n", - "\n", - "# Store the array of universes in the lattice\n", - "assembly.universes = universes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the assembly and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell')\n", - "root_cell.fill = assembly\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "geometry = openmc.Geometry(root_universe)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 40 active batches each with 2500 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 50\n", - "inactive = 10\n", - "particles = 10000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': False}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-10.71, -10.71, -10, 10.71, 10.71, 10.]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us also create a plot to verify that our fuel assembly geometry was created successfully." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Instantiate a Plot\n", - "plot = openmc.Plot.from_geometry(geometry)\n", - "plot.pixels = (250, 250)\n", - "plot.color_by = 'material'\n", - "plot.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see from the plot, we have a nice array of fuel and guide tube pin cells with fuel, cladding, and water!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create an MGXS Library" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in `EnergyGroups` class." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a 2-group EnergyGroups object\n", - "groups = openmc.mgxs.EnergyGroups()\n", - "groups.group_edges = np.array([0., 0.625, 20.0e6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we will instantiate an `openmc.mgxs.Library` for the energy groups with the fuel assembly geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize a 2-group MGXS Library for OpenMOC\n", - "mgxs_lib = openmc.mgxs.Library(geometry)\n", - "mgxs_lib.energy_groups = groups" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we must specify to the `Library` which types of cross sections to compute. In particular, the following are the multi-group cross section `MGXS` subclasses that are mapped to string codes accepted by the `Library` class:\n", - "\n", - "* `TotalXS` (`\"total\"`)\n", - "* `TransportXS` (`\"transport\"` or `\"nu-transport` with `nu` set to `True`)\n", - "* `AbsorptionXS` (`\"absorption\"`)\n", - "* `CaptureXS` (`\"capture\"`)\n", - "* `FissionXS` (`\"fission\"` or `\"nu-fission\"` with `nu` set to `True`)\n", - "* `KappaFissionXS` (`\"kappa-fission\"`)\n", - "* `ScatterXS` (`\"scatter\"` or `\"nu-scatter\"` with `nu` set to `True`)\n", - "* `ScatterMatrixXS` (`\"scatter matrix\"` or `\"nu-scatter matrix\"` with `nu` set to `True`)\n", - "* `Chi` (`\"chi\"`)\n", - "* `ChiPrompt` (`\"chi prompt\"`)\n", - "* `InverseVelocity` (`\"inverse-velocity\"`)\n", - "* `PromptNuFissionXS` (`\"prompt-nu-fission\"`)\n", - "* `DelayedNuFissionXS` (`\"delayed-nu-fission\"`)\n", - "* `ChiDelayed` (`\"chi-delayed\"`)\n", - "* `Beta` (`\"beta\"`)\n", - "\n", - "In this case, let's create the multi-group cross sections needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we will define `\"nu-transport\"`, `\"nu-fission\"`, `'\"fission\"`, `\"nu-scatter matrix\"` and `\"chi\"` cross sections for our `Library`.\n", - "\n", - "**Note**: A variety of different approximate transport-corrected total multi-group cross sections (and corresponding scattering matrices) can be found in the literature. At the present time, the `openmc.mgxs` module only supports the `\"P0\"` transport correction. This correction can be turned on and off through the boolean `Library.correction` property which may take values of `\"P0\"` (default) or `None`." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Specify multi-group cross section types to compute\n", - "mgxs_lib.mgxs_types = ['nu-transport', 'nu-fission', 'fission', 'nu-scatter matrix', 'chi']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we must specify the type of domain over which we would like the `Library` to compute multi-group cross sections. The domain type corresponds to the type of tally filter to be used in the tallies created to compute multi-group cross sections. At the present time, the `Library` supports `\"material\"`, `\"cell\"`, `\"universe\"`, and `\"mesh\"` domain types. We will use a `\"cell\"` domain type here to compute cross sections in each of the cells in the fuel assembly geometry.\n", - "\n", - "**Note:** By default, the `Library` class will instantiate `MGXS` objects for each and every domain (material, cell or universe) in the geometry of interest. However, one may specify a subset of these domains to the `Library.domains` property. In our case, we wish to compute multi-group cross sections in each and every cell since they will be needed in our downstream OpenMOC calculation on the identical combinatorial geometry mesh." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# Specify a \"cell\" domain type for the cross section tally filters\n", - "mgxs_lib.domain_type = 'cell'\n", - "\n", - "# Specify the cell domains over which to compute multi-group cross sections\n", - "mgxs_lib.domains = geometry.get_all_material_cells().values()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can easily instruct the `Library` to compute multi-group cross sections on a nuclide-by-nuclide basis with the boolean `Library.by_nuclide` property. By default, `by_nuclide` is set to `False`, but we will set it to `True` here." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "# Compute cross sections on a nuclide-by-nuclide basis\n", - "mgxs_lib.by_nuclide = True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lastly, we use the `Library` to construct the tallies needed to compute all of the requested multi-group cross sections in each domain and nuclide." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "# Construct all tallies needed for the multi-group cross section library\n", - "mgxs_lib.build_library()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The tallies can now be export to a \"tallies.xml\" input file for OpenMC. \n", - "\n", - "**NOTE**: At this point the `Library` has constructed nearly 100 distinct `Tally` objects. The overhead to tally in OpenMC scales as $O(N)$ for $N$ tallies, which can become a bottleneck for large tally datasets. To compensate for this, the Python API's `Tally`, `Filter` and `Tallies` classes allow for the smart *merging* of tallies when possible. The `Library` class supports this runtime optimization with the use of the optional `merge` paramter (`False` by default) for the `Library.add_to_tallies_file(...)` method, as shown below." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a \"tallies.xml\" file for the MGXS Library\n", - "tallies_file = openmc.Tallies()\n", - "mgxs_lib.add_to_tallies_file(tallies_file, merge=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition, we instantiate a fission rate mesh tally to compare with OpenMOC." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a tally Mesh\n", - "mesh = openmc.RegularMesh(mesh_id=1)\n", - "mesh.dimension = [17, 17]\n", - "mesh.lower_left = [-10.71, -10.71]\n", - "mesh.upper_right = [+10.71, +10.71]\n", - "\n", - "# Instantiate tally Filter\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='mesh tally')\n", - "tally.filters = [mesh_filter]\n", - "tally.scores = ['fission', 'nu-fission']\n", - "\n", - "# Add tally to collection\n", - "tallies_file.append(tally)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=126.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=21.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=3.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=4.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=96.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=15.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=114.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Export all tallies to a \"tallies.xml\" file\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 07:12:55\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading B10 from /opt/data/hdf5/nndc_hdf5_v15/B10.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.03784\n", - " 2/1 1.02297\n", - " 3/1 1.02244\n", - " 4/1 1.02344\n", - " 5/1 1.02057\n", - " 6/1 1.04077\n", - " 7/1 1.00775\n", - " 8/1 1.03892\n", - " 9/1 1.01606\n", - " 10/1 1.02209\n", - " 11/1 1.03259\n", - " 12/1 1.03331 1.03295 +/- 0.00036\n", - " 13/1 1.02027 1.02872 +/- 0.00423\n", - " 14/1 1.03901 1.03130 +/- 0.00395\n", - " 15/1 1.02000 1.02904 +/- 0.00380\n", - " 16/1 1.04469 1.03164 +/- 0.00405\n", - " 17/1 1.01862 1.02978 +/- 0.00390\n", - " 18/1 1.03265 1.03014 +/- 0.00340\n", - " 19/1 1.00489 1.02734 +/- 0.00410\n", - " 20/1 1.04533 1.02914 +/- 0.00409\n", - " 21/1 1.01534 1.02788 +/- 0.00390\n", - " 22/1 1.02204 1.02739 +/- 0.00360\n", - " 23/1 1.02181 1.02696 +/- 0.00334\n", - " 24/1 0.99207 1.02447 +/- 0.00397\n", - " 25/1 1.03041 1.02487 +/- 0.00372\n", - " 26/1 1.03652 1.02560 +/- 0.00355\n", - " 27/1 1.03793 1.02632 +/- 0.00341\n", - " 28/1 1.02099 1.02603 +/- 0.00323\n", - " 29/1 1.01953 1.02568 +/- 0.00308\n", - " 30/1 1.01690 1.02525 +/- 0.00295\n", - " 31/1 1.01938 1.02497 +/- 0.00282\n", - " 32/1 1.01800 1.02465 +/- 0.00271\n", - " 33/1 1.01598 1.02427 +/- 0.00262\n", - " 34/1 1.01735 1.02398 +/- 0.00252\n", - " 35/1 1.01080 1.02346 +/- 0.00247\n", - " 36/1 1.01267 1.02304 +/- 0.00241\n", - " 37/1 1.01907 1.02289 +/- 0.00233\n", - " 38/1 1.02333 1.02291 +/- 0.00224\n", - " 39/1 1.01516 1.02264 +/- 0.00218\n", - " 40/1 1.02797 1.02282 +/- 0.00211\n", - " 41/1 1.03949 1.02336 +/- 0.00211\n", - " 42/1 1.01456 1.02308 +/- 0.00207\n", - " 43/1 1.02376 1.02310 +/- 0.00200\n", - " 44/1 1.01917 1.02299 +/- 0.00195\n", - " 45/1 1.01631 1.02280 +/- 0.00190\n", - " 46/1 1.02381 1.02282 +/- 0.00185\n", - " 47/1 1.04002 1.02329 +/- 0.00185\n", - " 48/1 1.01059 1.02296 +/- 0.00184\n", - " 49/1 1.02647 1.02305 +/- 0.00179\n", - " 50/1 1.02451 1.02308 +/- 0.00175\n", - " Creating state point statepoint.50.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 5.7635e-01 seconds\n", - " Reading cross sections = 5.4002e-01 seconds\n", - " Total time in simulation = 7.0174e+01 seconds\n", - " Time in transport only = 6.9687e+01 seconds\n", - " Time in inactive batches = 7.1832e+00 seconds\n", - " Time in active batches = 6.2991e+01 seconds\n", - " Time synchronizing fission bank = 3.9991e-02 seconds\n", - " Sampling source sites = 3.4633e-02 seconds\n", - " SEND/RECV source sites = 5.2616e-03 seconds\n", - " Time accumulating tallies = 4.9801e-04 seconds\n", - " Total time for finalization = 1.3501e-05 seconds\n", - " Total time elapsed = 7.0791e+01 seconds\n", - " Calculation Rate (inactive) = 13921.3 particles/second\n", - " Calculation Rate (active) = 6350.11 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.02434 +/- 0.00173\n", - " k-effective (Track-length) = 1.02308 +/- 0.00175\n", - " k-effective (Absorption) = 1.02494 +/- 0.00175\n", - " Combined k-effective = 1.02408 +/- 0.00144\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created statepoint and summary output files. We begin our analysis by instantiating a `StatePoint` object. " - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the last statepoint file\n", - "sp = openmc.StatePoint('statepoint.50.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint is now ready to be analyzed by the `Library`. We simply have to load the tallies from the statepoint into the `Library` and our `MGXS` objects will compute the cross sections for us under-the-hood." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize MGXS Library with OpenMC statepoint data\n", - "mgxs_lib.load_from_statepoint(sp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Voila! Our multi-group cross sections are now ready to rock 'n roll!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Extracting and Storing MGXS Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `Library` supports a rich API to automate a variety of tasks, including multi-group cross section data retrieval and storage. We will highlight a few of these features here. First, the `Library.get_mgxs(...)` method allows one to extract an `MGXS` object from the `Library` for a particular domain and cross section type. The following cell illustrates how one may extract the `NuFissionXS` object for the fuel cell.\n", - "\n", - "**Note:** The `MGXS.get_mgxs(...)` method will accept either the domain *or* the integer domain ID of interest." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "# Retrieve the NuFissionXS object for the fuel cell from the library\n", - "fuel_mgxs = mgxs_lib.get_mgxs(fuel_cell, 'nu-fission')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `NuFissionXS` object supports all of the methods described previously in the `openmc.mgxs` tutorials, such as [Pandas](http://pandas.pydata.org/) `DataFrames`:\n", - "Note that since so few histories were simulated, we should expect a few division-by-error errors as some tallies have not yet scored any results." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellgroup innuclidemeanstd. dev.
311U2358.089079e-031.461462e-05
411U2387.358661e-032.302063e-05
511O160.000000e+000.000000e+00
012U2353.617174e-019.467633e-04
112U2386.744743e-071.750450e-09
212O160.000000e+000.000000e+00
\n", - "
" - ], - "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "3 1 1 U235 8.089079e-03 1.461462e-05\n", - "4 1 1 U238 7.358661e-03 2.302063e-05\n", - "5 1 1 O16 0.000000e+00 0.000000e+00\n", - "0 1 2 U235 3.617174e-01 9.467633e-04\n", - "1 1 2 U238 6.744743e-07 1.750450e-09\n", - "2 1 2 O16 0.000000e+00 0.000000e+00" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = fuel_mgxs.get_pandas_dataframe()\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can use the `MGXS.print_xs(...)` method to view a string representation of the multi-group cross section data." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Multi-Group XS\n", - "\tReaction Type =\tnu-fission\n", - "\tDomain Type =\tcell\n", - "\tDomain ID =\t1\n", - "\tNuclide =\tU235\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t8.09e-03 +/- 1.81e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t3.62e-01 +/- 2.62e-01%\n", - "\n", - "\tNuclide =\tU238\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t7.36e-03 +/- 3.13e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t6.74e-07 +/- 2.60e-01%\n", - "\n", - "\tNuclide =\tO16\n", - "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t0.00e+00 +/- 0.00e+00%\n", - " Group 2 [0.0 - 0.625 eV]:\t0.00e+00 +/- 0.00e+00%\n", - "\n", - "\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/tallies.py:1269: RuntimeWarning: invalid value encountered in true_divide\n", - " data = self.std_dev[indices] / self.mean[indices]\n" - ] - } - ], - "source": [ - "fuel_mgxs.print_xs()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One can export the entire `Library` to HDF5 with the `Library.build_hdf5_store(...)` method as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "# Store the cross section data in an \"mgxs/mgxs.h5\" HDF5 binary file\n", - "mgxs_lib.build_hdf5_store(filename='mgxs.h5', directory='mgxs')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The HDF5 store will contain the numerical multi-group cross section data indexed by domain, nuclide and cross section type. Some data workflows may be optimized by storing and retrieving binary representations of the `MGXS` objects in the `Library`. This feature is supported through the `Library.dump_to_file(...)` and `Library.load_from_file(...)` routines which use Python's [`pickle`](https://docs.python.org/2/library/pickle.html) module. This is illustrated as follows." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "# Store a Library and its MGXS objects in a pickled binary file \"mgxs/mgxs.pkl\"\n", - "mgxs_lib.dump_to_file(filename='mgxs', directory='mgxs')" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a new MGXS Library from the pickled binary file \"mgxs/mgxs.pkl\"\n", - "mgxs_lib = openmc.mgxs.Library.load_from_file(filename='mgxs', directory='mgxs')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `Library` class may be used to leverage the energy condensation features supported by the `MGXS` class. In particular, one can use the `Library.get_condensed_library(...)` with a coarse group structure which is a subset of the original \"fine\" group structure as shown below." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a 1-group structure\n", - "coarse_groups = openmc.mgxs.EnergyGroups(group_edges=[0., 20.0e6])\n", - "\n", - "# Create a new MGXS Library on the coarse 1-group structure\n", - "coarse_mgxs_lib = mgxs_lib.get_condensed_library(coarse_groups)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellgroup innuclidemeanstd. dev.
011U2350.0745560.000144
111U2380.0059760.000019
211O160.0000000.000000
\n", - "
" - ], - "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "0 1 1 U235 0.074556 0.000144\n", - "1 1 1 U238 0.005976 0.000019\n", - "2 1 1 O16 0.000000 0.000000" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Retrieve the NuFissionXS object for the fuel cell from the 1-group library\n", - "coarse_fuel_mgxs = coarse_mgxs_lib.get_mgxs(fuel_cell, 'nu-fission')\n", - "\n", - "# Show the Pandas DataFrame for the 1-group MGXS\n", - "coarse_fuel_mgxs.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Verification with OpenMOC" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course it is always a good idea to verify that one's cross sections are accurate. We can easily do so here with the deterministic transport code [OpenMOC](https://mit-crpg.github.io/OpenMOC/). We first construct an equivalent OpenMOC geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "# Create an OpenMOC Geometry from the OpenMC Geometry\n", - "openmoc_geometry = get_openmoc_geometry(mgxs_lib.geometry)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we can inject the multi-group cross sections into the equivalent fuel assembly OpenMOC geometry. The `openmoc.materialize` module supports the loading of `Library` objects from OpenMC as illustrated below." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "# Load the library into the OpenMOC geometry\n", - "materials = load_openmc_mgxs_lib(mgxs_lib, openmoc_geometry)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to run OpenMOC to verify our cross-sections from OpenMC." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Initializing a default angular quadrature...\n", - "[ NORMAL ] Initializing 2D tracks...\n", - "[ NORMAL ] Initializing 2D tracks reflections...\n", - "[ NORMAL ] Initializing 2D tracks array...\n", - "[ NORMAL ] Ray tracing for 2D track segmentation...\n", - "[ WARNING ] The Geometry was set with non-infinite z-boundaries and supplied\n", - "[ WARNING ] ... to a 2D TrackGenerator. The min-z boundary was set to -10.00 \n", - "[ WARNING ] ... and the max-z boundary was set to 10.00. Z-boundaries are \n", - "[ WARNING ] ... assumed to be infinite in 2D TrackGenerators.\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 0.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 10.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 20.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 30.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 40.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 50.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 60.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 70.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 80.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 90.02 %\n", - "[ NORMAL ] Progress Segmenting 2D tracks: 100.00 %\n", - "[ NORMAL ] Initializing FSR lookup vectors\n", - "[ NORMAL ] Total number of FSRs 867\n", - "[ RESULT ] Total Track Generation & Segmentation Time...........4.2139E-01 sec\n", - "[ NORMAL ] Initializing MOC eigenvalue solver...\n", - "[ NORMAL ] Initializing solver arrays...\n", - "[ NORMAL ] Centering segments around FSR centroid...\n", - "[ NORMAL ] Max boundary angular flux storage per domain = 0.42 MB\n", - "[ NORMAL ] Max scalar flux storage per domain = 0.01 MB\n", - "[ NORMAL ] Max source storage per domain = 0.01 MB\n", - "[ NORMAL ] Number of azimuthal angles = 32\n", - "[ NORMAL ] Azimuthal ray spacing = 0.100000\n", - "[ NORMAL ] Number of polar angles = 6\n", - "[ NORMAL ] Source type = Flat\n", - "[ NORMAL ] MOC transport undamped\n", - "[ NORMAL ] CMFD acceleration: OFF\n", - "[ NORMAL ] Using 1 threads\n", - "[ NORMAL ] Computing the eigenvalue...\n", - "[ NORMAL ] Iteration 0: k_eff = 0.823216 res = 9.828E-02 delta-k (pcm) =\n", - "[ NORMAL ] ... -17678 D.R. = 0.10\n", - "[ NORMAL ] Iteration 1: k_eff = 0.779788 res = 4.642E-02 delta-k (pcm) =\n", - "[ NORMAL ] ... -4342 D.R. = 0.47\n", - "[ NORMAL ] Iteration 2: k_eff = 0.738779 res = 9.633E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -4100 D.R. = 0.21\n", - "[ NORMAL ] Iteration 3: k_eff = 0.710046 res = 8.556E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -2873 D.R. = 0.89\n", - "[ NORMAL ] Iteration 4: k_eff = 0.688781 res = 5.190E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -2126 D.R. = 0.61\n", - "[ NORMAL ] Iteration 5: k_eff = 0.674128 res = 3.585E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -1465 D.R. = 0.69\n", - "[ NORMAL ] Iteration 6: k_eff = 0.664928 res = 2.516E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -919 D.R. = 0.70\n", - "[ NORMAL ] Iteration 7: k_eff = 0.660304 res = 1.866E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -462 D.R. = 0.74\n", - "[ NORMAL ] Iteration 8: k_eff = 0.659481 res = 1.471E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... -82 D.R. = 0.79\n", - "[ NORMAL ] Iteration 9: k_eff = 0.661799 res = 1.248E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... 231 D.R. = 0.85\n", - "[ NORMAL ] Iteration 10: k_eff = 0.666690 res = 1.123E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... 489 D.R. = 0.90\n", - "[ NORMAL ] Iteration 11: k_eff = 0.673664 res = 1.049E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... 697 D.R. = 0.93\n", - "[ NORMAL ] Iteration 12: k_eff = 0.682301 res = 1.001E-03 delta-k (pcm) =\n", - "[ NORMAL ] ... 863 D.R. = 0.95\n", - "[ NORMAL ] Iteration 13: k_eff = 0.692239 res = 9.638E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 993 D.R. = 0.96\n", - "[ NORMAL ] Iteration 14: k_eff = 0.703171 res = 9.329E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1093 D.R. = 0.97\n", - "[ NORMAL ] Iteration 15: k_eff = 0.714835 res = 9.055E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1166 D.R. = 0.97\n", - "[ NORMAL ] Iteration 16: k_eff = 0.727008 res = 8.803E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1217 D.R. = 0.97\n", - "[ NORMAL ] Iteration 17: k_eff = 0.739503 res = 8.566E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1249 D.R. = 0.97\n", - "[ NORMAL ] Iteration 18: k_eff = 0.752162 res = 8.335E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1265 D.R. = 0.97\n", - "[ NORMAL ] Iteration 19: k_eff = 0.764855 res = 8.108E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1269 D.R. = 0.97\n", - "[ NORMAL ] Iteration 20: k_eff = 0.777472 res = 7.879E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1261 D.R. = 0.97\n", - "[ NORMAL ] Iteration 21: k_eff = 0.789924 res = 7.647E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1245 D.R. = 0.97\n", - "[ NORMAL ] Iteration 22: k_eff = 0.802140 res = 7.410E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1221 D.R. = 0.97\n", - "[ NORMAL ] Iteration 23: k_eff = 0.814061 res = 7.168E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1192 D.R. = 0.97\n", - "[ NORMAL ] Iteration 24: k_eff = 0.825643 res = 6.922E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1158 D.R. = 0.97\n", - "[ NORMAL ] Iteration 25: k_eff = 0.836850 res = 6.672E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1120 D.R. = 0.96\n", - "[ NORMAL ] Iteration 26: k_eff = 0.847658 res = 6.419E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1080 D.R. = 0.96\n", - "[ NORMAL ] Iteration 27: k_eff = 0.858047 res = 6.165E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 1038 D.R. = 0.96\n", - "[ NORMAL ] Iteration 28: k_eff = 0.868008 res = 5.911E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 996 D.R. = 0.96\n", - "[ NORMAL ] Iteration 29: k_eff = 0.877535 res = 5.658E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 952 D.R. = 0.96\n", - "[ NORMAL ] Iteration 30: k_eff = 0.886625 res = 5.409E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 909 D.R. = 0.96\n", - "[ NORMAL ] Iteration 31: k_eff = 0.895281 res = 5.163E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 865 D.R. = 0.95\n", - "[ NORMAL ] Iteration 32: k_eff = 0.903509 res = 4.921E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 822 D.R. = 0.95\n", - "[ NORMAL ] Iteration 33: k_eff = 0.911317 res = 4.685E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 780 D.R. = 0.95\n", - "[ NORMAL ] Iteration 34: k_eff = 0.918715 res = 4.456E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 739 D.R. = 0.95\n", - "[ NORMAL ] Iteration 35: k_eff = 0.925715 res = 4.232E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 699 D.R. = 0.95\n", - "[ NORMAL ] Iteration 36: k_eff = 0.932329 res = 4.016E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 661 D.R. = 0.95\n", - "[ NORMAL ] Iteration 37: k_eff = 0.938571 res = 3.807E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 624 D.R. = 0.95\n", - "[ NORMAL ] Iteration 38: k_eff = 0.944455 res = 3.606E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 588 D.R. = 0.95\n", - "[ NORMAL ] Iteration 39: k_eff = 0.949996 res = 3.413E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 554 D.R. = 0.95\n", - "[ NORMAL ] Iteration 40: k_eff = 0.955210 res = 3.227E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 521 D.R. = 0.95\n", - "[ NORMAL ] Iteration 41: k_eff = 0.960110 res = 3.049E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 490 D.R. = 0.94\n", - "[ NORMAL ] Iteration 42: k_eff = 0.964713 res = 2.880E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 460 D.R. = 0.94\n", - "[ NORMAL ] Iteration 43: k_eff = 0.969032 res = 2.717E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 431 D.R. = 0.94\n", - "[ NORMAL ] Iteration 44: k_eff = 0.973082 res = 2.562E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 405 D.R. = 0.94\n", - "[ NORMAL ] Iteration 45: k_eff = 0.976877 res = 2.414E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 379 D.R. = 0.94\n", - "[ NORMAL ] Iteration 46: k_eff = 0.980431 res = 2.274E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 355 D.R. = 0.94\n", - "[ NORMAL ] Iteration 47: k_eff = 0.983757 res = 2.140E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 332 D.R. = 0.94\n", - "[ NORMAL ] Iteration 48: k_eff = 0.986869 res = 2.014E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 311 D.R. = 0.94\n", - "[ NORMAL ] Iteration 49: k_eff = 0.989777 res = 1.894E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 290 D.R. = 0.94\n", - "[ NORMAL ] Iteration 50: k_eff = 0.992495 res = 1.780E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 271 D.R. = 0.94\n", - "[ NORMAL ] Iteration 51: k_eff = 0.995033 res = 1.672E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 253 D.R. = 0.94\n", - "[ NORMAL ] Iteration 52: k_eff = 0.997402 res = 1.569E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 236 D.R. = 0.94\n", - "[ NORMAL ] Iteration 53: k_eff = 0.999613 res = 1.473E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 221 D.R. = 0.94\n", - "[ NORMAL ] Iteration 54: k_eff = 1.001675 res = 1.382E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 206 D.R. = 0.94\n", - "[ NORMAL ] Iteration 55: k_eff = 1.003597 res = 1.296E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 192 D.R. = 0.94\n", - "[ NORMAL ] Iteration 56: k_eff = 1.005388 res = 1.215E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 179 D.R. = 0.94\n", - "[ NORMAL ] Iteration 57: k_eff = 1.007057 res = 1.138E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 166 D.R. = 0.94\n", - "[ NORMAL ] Iteration 58: k_eff = 1.008612 res = 1.066E-04 delta-k (pcm) =\n", - "[ NORMAL ] ... 155 D.R. = 0.94\n", - "[ NORMAL ] Iteration 59: k_eff = 1.010059 res = 9.980E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 144 D.R. = 0.94\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ NORMAL ] Iteration 60: k_eff = 1.011406 res = 9.342E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 134 D.R. = 0.94\n", - "[ NORMAL ] Iteration 61: k_eff = 1.012659 res = 8.740E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 125 D.R. = 0.94\n", - "[ NORMAL ] Iteration 62: k_eff = 1.013825 res = 8.175E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 116 D.R. = 0.94\n", - "[ NORMAL ] Iteration 63: k_eff = 1.014909 res = 7.642E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 108 D.R. = 0.93\n", - "[ NORMAL ] Iteration 64: k_eff = 1.015917 res = 7.142E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 100 D.R. = 0.93\n", - "[ NORMAL ] Iteration 65: k_eff = 1.016853 res = 6.675E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 93 D.R. = 0.93\n", - "[ NORMAL ] Iteration 66: k_eff = 1.017724 res = 6.235E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 87 D.R. = 0.93\n", - "[ NORMAL ] Iteration 67: k_eff = 1.018533 res = 5.822E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 80 D.R. = 0.93\n", - "[ NORMAL ] Iteration 68: k_eff = 1.019284 res = 5.436E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 75 D.R. = 0.93\n", - "[ NORMAL ] Iteration 69: k_eff = 1.019982 res = 5.074E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 69 D.R. = 0.93\n", - "[ NORMAL ] Iteration 70: k_eff = 1.020630 res = 4.734E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 64 D.R. = 0.93\n", - "[ NORMAL ] Iteration 71: k_eff = 1.021232 res = 4.417E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 60 D.R. = 0.93\n", - "[ NORMAL ] Iteration 72: k_eff = 1.021790 res = 4.119E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 55 D.R. = 0.93\n", - "[ NORMAL ] Iteration 73: k_eff = 1.022308 res = 3.841E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 51 D.R. = 0.93\n", - "[ NORMAL ] Iteration 74: k_eff = 1.022789 res = 3.579E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 48 D.R. = 0.93\n", - "[ NORMAL ] Iteration 75: k_eff = 1.023235 res = 3.336E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 44 D.R. = 0.93\n", - "[ NORMAL ] Iteration 76: k_eff = 1.023648 res = 3.107E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 41 D.R. = 0.93\n", - "[ NORMAL ] Iteration 77: k_eff = 1.024032 res = 2.897E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 38 D.R. = 0.93\n", - "[ NORMAL ] Iteration 78: k_eff = 1.024388 res = 2.696E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 35 D.R. = 0.93\n", - "[ NORMAL ] Iteration 79: k_eff = 1.024718 res = 2.510E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 32 D.R. = 0.93\n", - "[ NORMAL ] Iteration 80: k_eff = 1.025024 res = 2.338E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 30 D.R. = 0.93\n", - "[ NORMAL ] Iteration 81: k_eff = 1.025307 res = 2.175E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 28 D.R. = 0.93\n", - "[ NORMAL ] Iteration 82: k_eff = 1.025570 res = 2.025E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 26 D.R. = 0.93\n", - "[ NORMAL ] Iteration 83: k_eff = 1.025814 res = 1.886E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 24 D.R. = 0.93\n", - "[ NORMAL ] Iteration 84: k_eff = 1.026039 res = 1.752E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 22 D.R. = 0.93\n", - "[ NORMAL ] Iteration 85: k_eff = 1.026249 res = 1.628E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 20 D.R. = 0.93\n", - "[ NORMAL ] Iteration 86: k_eff = 1.026442 res = 1.517E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 19 D.R. = 0.93\n", - "[ NORMAL ] Iteration 87: k_eff = 1.026622 res = 1.408E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 17 D.R. = 0.93\n", - "[ NORMAL ] Iteration 88: k_eff = 1.026788 res = 1.308E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 16 D.R. = 0.93\n", - "[ NORMAL ] Iteration 89: k_eff = 1.026942 res = 1.218E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 15 D.R. = 0.93\n", - "[ NORMAL ] Iteration 90: k_eff = 1.027085 res = 1.132E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 14 D.R. = 0.93\n", - "[ NORMAL ] Iteration 91: k_eff = 1.027217 res = 1.049E-05 delta-k (pcm) =\n", - "[ NORMAL ] ... 13 D.R. = 0.93\n", - "[ NORMAL ] Iteration 92: k_eff = 1.027339 res = 9.760E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 12 D.R. = 0.93\n", - "[ NORMAL ] Iteration 93: k_eff = 1.027453 res = 9.076E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 11 D.R. = 0.93\n", - "[ NORMAL ] Iteration 94: k_eff = 1.027557 res = 8.434E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 10 D.R. = 0.93\n", - "[ NORMAL ] Iteration 95: k_eff = 1.027655 res = 7.827E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 9 D.R. = 0.93\n", - "[ NORMAL ] Iteration 96: k_eff = 1.027744 res = 7.266E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 8 D.R. = 0.93\n", - "[ NORMAL ] Iteration 97: k_eff = 1.027828 res = 6.737E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 8 D.R. = 0.93\n", - "[ NORMAL ] Iteration 98: k_eff = 1.027905 res = 6.255E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 7 D.R. = 0.93\n", - "[ NORMAL ] Iteration 99: k_eff = 1.027976 res = 5.803E-06 delta-k (pcm) =\n", - "[ NORMAL ] ... 7 D.R. = 0.93\n", - "[ NORMAL ] Iteration 100: k_eff = 1.028042 res = 5.383E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.93\n", - "[ NORMAL ] Iteration 101: k_eff = 1.028103 res = 5.017E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 6 D.R. = 0.93\n", - "[ NORMAL ] Iteration 102: k_eff = 1.028160 res = 4.618E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.92\n", - "[ NORMAL ] Iteration 103: k_eff = 1.028212 res = 4.306E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 5 D.R. = 0.93\n", - "[ NORMAL ] Iteration 104: k_eff = 1.028260 res = 3.999E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.93\n", - "[ NORMAL ] Iteration 105: k_eff = 1.028305 res = 3.706E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.93\n", - "[ NORMAL ] Iteration 106: k_eff = 1.028347 res = 3.429E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 4 D.R. = 0.93\n", - "[ NORMAL ] Iteration 107: k_eff = 1.028385 res = 3.213E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.94\n", - "[ NORMAL ] Iteration 108: k_eff = 1.028420 res = 2.943E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.92\n", - "[ NORMAL ] Iteration 109: k_eff = 1.028453 res = 2.740E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.93\n", - "[ NORMAL ] Iteration 110: k_eff = 1.028484 res = 2.531E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 3 D.R. = 0.92\n", - "[ NORMAL ] Iteration 111: k_eff = 1.028512 res = 2.369E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.94\n", - "[ NORMAL ] Iteration 112: k_eff = 1.028538 res = 2.186E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.92\n", - "[ NORMAL ] Iteration 113: k_eff = 1.028562 res = 2.026E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.93\n", - "[ NORMAL ] Iteration 114: k_eff = 1.028584 res = 1.858E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.92\n", - "[ NORMAL ] Iteration 115: k_eff = 1.028604 res = 1.760E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 2 D.R. = 0.95\n", - "[ NORMAL ] Iteration 116: k_eff = 1.028623 res = 1.612E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.92\n", - "[ NORMAL ] Iteration 117: k_eff = 1.028641 res = 1.496E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.93\n", - "[ NORMAL ] Iteration 118: k_eff = 1.028657 res = 1.382E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.92\n", - "[ NORMAL ] Iteration 119: k_eff = 1.028672 res = 1.293E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.94\n", - "[ NORMAL ] Iteration 120: k_eff = 1.028686 res = 1.191E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.92\n", - "[ NORMAL ] Iteration 121: k_eff = 1.028699 res = 1.112E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.93\n", - "[ NORMAL ] Iteration 122: k_eff = 1.028711 res = 1.005E-06 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.90\n", - "[ NORMAL ] Iteration 123: k_eff = 1.028722 res = 9.443E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.94\n", - "[ NORMAL ] Iteration 124: k_eff = 1.028732 res = 8.583E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 1 D.R. = 0.91\n", - "[ NORMAL ] Iteration 125: k_eff = 1.028742 res = 8.028E-07 delta-k (pcm)\n", - "[ NORMAL ] ... = 0 D.R. = 0.94\n" - ] - } - ], - "source": [ - "# Generate tracks for OpenMOC\n", - "track_generator = openmoc.TrackGenerator(openmoc_geometry, num_azim=32, azim_spacing=0.1)\n", - "track_generator.generateTracks()\n", - "\n", - "# Run OpenMOC\n", - "solver = openmoc.CPUSolver(track_generator)\n", - "solver.computeEigenvalue()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We report the eigenvalues computed by OpenMC and OpenMOC here together to summarize our results." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "openmc keff = 1.024078\n", - "openmoc keff = 1.028742\n", - "bias [pcm]: 466.4\n" - ] - } - ], - "source": [ - "# Print report of keff and bias with OpenMC\n", - "openmoc_keff = solver.getKeff()\n", - "openmc_keff = sp.k_combined.nominal_value\n", - "bias = (openmoc_keff - openmc_keff) * 1e5\n", - "\n", - "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", - "print('openmoc keff = {0:1.6f}'.format(openmoc_keff))\n", - "print('bias [pcm]: {0:1.1f}'.format(bias))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is a non-trivial bias between the eigenvalues computed by OpenMC and OpenMOC. One can show that these biases do not converge to <100 pcm with more particle histories. For heterogeneous geometries, additional measures must be taken to address the following three sources of bias:\n", - "\n", - "* Appropriate transport-corrected cross sections\n", - "* Spatial discretization of OpenMOC's mesh\n", - "* Constant-in-angle multi-group cross sections" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Flux and Pin Power Visualizations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will conclude this tutorial by illustrating how to visualize the fission rates computed by OpenMOC and OpenMC. First, we extract volume-integrated fission rates from OpenMC's mesh fission rate tally for each pin cell in the fuel assembly." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [], - "source": [ - "# Get the OpenMC fission rate mesh tally data\n", - "mesh_tally = sp.get_tally(name='mesh tally')\n", - "openmc_fission_rates = mesh_tally.get_values(scores=['nu-fission'])\n", - "\n", - "# Reshape array to 2D for plotting\n", - "openmc_fission_rates.shape = (17,17)\n", - "\n", - "# Normalize to the average pin power\n", - "openmc_fission_rates /= np.mean(openmc_fission_rates[openmc_fission_rates > 0.])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we extract OpenMOC's volume-averaged fission rates into a 2D 17x17 NumPy array." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [], - "source": [ - "# Create OpenMOC Mesh on which to tally fission rates\n", - "openmoc_mesh = openmoc.process.Mesh()\n", - "openmoc_mesh.dimension = np.array(mesh.dimension)\n", - "openmoc_mesh.lower_left = np.array(mesh.lower_left)\n", - "openmoc_mesh.upper_right = np.array(mesh.upper_right)\n", - "openmoc_mesh.width = openmoc_mesh.upper_right - openmoc_mesh.lower_left\n", - "openmoc_mesh.width /= openmoc_mesh.dimension\n", - "\n", - "# Tally OpenMOC fission rates on the Mesh\n", - "openmoc_fission_rates = openmoc_mesh.tally_fission_rates(solver)\n", - "openmoc_fission_rates = np.squeeze(openmoc_fission_rates)\n", - "openmoc_fission_rates = np.fliplr(openmoc_fission_rates)\n", - "\n", - "# Normalize to the average pin fission rate\n", - "openmoc_fission_rates /= np.mean(openmoc_fission_rates[openmoc_fission_rates > 0.])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can easily use Matplotlib to visualize the fission rates from OpenMC and OpenMOC side-by-side." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'OpenMOC Fission Rates')" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Ignore zero fission rates in guide tubes with Matplotlib color scheme\n", - "openmc_fission_rates[openmc_fission_rates == 0] = np.nan\n", - "openmoc_fission_rates[openmoc_fission_rates == 0] = np.nan\n", - "\n", - "# Plot OpenMC's fission rates in the left subplot\n", - "fig = plt.subplot(121)\n", - "plt.imshow(openmc_fission_rates, interpolation='none', cmap='jet')\n", - "plt.title('OpenMC Fission Rates')\n", - "\n", - "# Plot OpenMOC's fission rates in the right subplot\n", - "fig2 = plt.subplot(122)\n", - "plt.imshow(openmoc_fission_rates, interpolation='none', cmap='jet')\n", - "plt.title('OpenMOC Fission Rates')" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/nuclear-data-resonance-covariance.ipynb b/examples/jupyter/nuclear-data-resonance-covariance.ipynb deleted file mode 100644 index d8bca235d..000000000 --- a/examples/jupyter/nuclear-data-resonance-covariance.ipynb +++ /dev/null @@ -1,962 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this notebook we will explore features of the Python API that allow us to import and manipulate resonance covariance data. A full description of the ENDF-VI and ENDF-VII formats can be found in the [ENDF102 manual](https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import os\n", - "from pprint import pprint\n", - "import shutil\n", - "import subprocess\n", - "import urllib.request\n", - "\n", - "import h5py\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import openmc.data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ENDF: Resonance Covariance Data\n", - "\n", - "Let's download the ENDF/B-VII.1 evaluation for $^{157}$Gd and load it in:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Download ENDF file\n", - "url = 'https://t2.lanl.gov/nis/data/data/ENDFB-VII.1-neutron/Gd/157'\n", - "filename, headers = urllib.request.urlretrieve(url, 'gd157.endf')\n", - "\n", - "# Load into memory\n", - "gd157_endf = openmc.data.IncidentNeutron.from_endf(filename, covariance=True)\n", - "gd157_endf" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can access the parameters contained within File 32 in a similar manner to the File 2 parameters from before. " - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyJneutronWidthcaptureWidthfissionWidthAfissionWidthBL
00.03142.00.0004740.10720.00.00
12.82502.00.0003450.09700.00.00
216.24001.00.0004000.09100.00.00
316.77002.00.0128000.08050.00.00
420.56002.00.0113600.08800.00.00
\n", - "
" - ], - "text/plain": [ - " energy J neutronWidth captureWidth fissionWidthA fissionWidthB L\n", - "0 0.0314 2.0 0.000474 0.1072 0.0 0.0 0\n", - "1 2.8250 2.0 0.000345 0.0970 0.0 0.0 0\n", - "2 16.2400 1.0 0.000400 0.0910 0.0 0.0 0\n", - "3 16.7700 2.0 0.012800 0.0805 0.0 0.0 0\n", - "4 20.5600 2.0 0.011360 0.0880 0.0 0.0 0" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157_endf.resonance_covariance.ranges[0].parameters[:5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The newly created object will contain multiple resonance regions within `gd157_endf.resonance_covariance.ranges`. We can access the full covariance matrix from File 32 for a given range by:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "covariance = gd157_endf.resonance_covariance.ranges[0].covariance" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This covariance matrix currently only stores the upper triangular portion as covariance matrices are symmetric. Plotting the covariance matrix:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.imshow(covariance, cmap='seismic',vmin=-0.008, vmax=0.008)\n", - "plt.colorbar()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The correlation matrix can be constructed using the covariance matrix and also give some insight into the relations among the parameters." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "corr = np.zeros([len(covariance),len(covariance)])\n", - "for i in range(len(covariance)):\n", - " for j in range(len(covariance)):\n", - " corr[i, j]=covariance[i, j]/covariance[i, i]**(0.5)/covariance[j, j]**(0.5)\n", - "plt.imshow(corr, cmap='seismic',vmin=-1.0, vmax=1.0)\n", - "plt.colorbar()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sampling and Reconstruction" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The covariance module also has the ability to sample a new set of parameters using the covariance matrix. Currently the sampling uses numpy.multivariate_normal(). Because parameters are assumed to have a multivariate normal distribution this method doesn't not currently guarantee that sampled parameters will be positive." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/data/resonance_covariance.py:233: UserWarning: Sampling routine does not guarantee positive values for parameters. This can lead to undefined behavior in the reconstruction routine.\n", - " warnings.warn(warn_str)\n" - ] - }, - { - "data": { - "text/plain": [ - "openmc.data.resonance.ReichMoore" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rm_resonance = gd157_endf.resonances.ranges[0]\n", - "n_samples = 5\n", - "samples = gd157_endf.resonance_covariance.ranges[0].sample(n_samples)\n", - "type(samples[0])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The sampling routine requires the incorporation of the `openmc.data.ResonanceRange` for the same resonance range object. This allows each sample itself to be its own `openmc.data.ResonanceRange` with a new set of parameters. Looking at some of the sampled parameters below:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample 1\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyLJneutronWidthcaptureWidthfissionWidthAfissionWidthB
00.03067902.00.0004730.1085760.00.0
12.82384302.00.0003510.0864180.00.0
216.28114701.00.0004580.1068250.00.0
316.77176002.00.0135980.0728370.00.0
420.56154502.00.0111640.0866160.00.0
\n", - "
" - ], - "text/plain": [ - " energy L J neutronWidth captureWidth fissionWidthA fissionWidthB\n", - "0 0.030679 0 2.0 0.000473 0.108576 0.0 0.0\n", - "1 2.823843 0 2.0 0.000351 0.086418 0.0 0.0\n", - "2 16.281147 0 1.0 0.000458 0.106825 0.0 0.0\n", - "3 16.771760 0 2.0 0.013598 0.072837 0.0 0.0\n", - "4 20.561545 0 2.0 0.011164 0.086616 0.0 0.0" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "print('Sample 1')\n", - "samples[0].parameters[:5]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample 2\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyLJneutronWidthcaptureWidthfissionWidthAfissionWidthB
00.03285802.00.0004790.1052080.00.0
12.82385902.00.0003610.0937480.00.0
216.20306901.00.0002640.0152330.00.0
316.76505502.00.0136480.0761190.00.0
420.55767902.00.0111400.0975480.00.0
\n", - "
" - ], - "text/plain": [ - " energy L J neutronWidth captureWidth fissionWidthA fissionWidthB\n", - "0 0.032858 0 2.0 0.000479 0.105208 0.0 0.0\n", - "1 2.823859 0 2.0 0.000361 0.093748 0.0 0.0\n", - "2 16.203069 0 1.0 0.000264 0.015233 0.0 0.0\n", - "3 16.765055 0 2.0 0.013648 0.076119 0.0 0.0\n", - "4 20.557679 0 2.0 0.011140 0.097548 0.0 0.0" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "print('Sample 2')\n", - "samples[1].parameters[:5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can reconstruct the cross section from the sampled parameters using the reconstruct method of `openmc.data.ResonanceRange`. For more on reconstruction see the Nuclear Data example notebook. " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157_endf.resonances.ranges" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Cross section (b)')" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "energy_range = [rm_resonance.energy_min, rm_resonance.energy_max]\n", - "energies = np.logspace(np.log10(energy_range[0]),\n", - " np.log10(energy_range[1]), 10000)\n", - "for sample in samples:\n", - " xs = sample.reconstruct(energies)\n", - " elastic_xs = xs[2]\n", - " plt.loglog(energies, elastic_xs)\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Cross section (b)')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Subset Selection" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another capability of the covariance module is selecting a subset of the resonance parameters and the corresponding subset of the covariance matrix. We can do this by specifying the value we want to discriminate and the bounds within one energy region. Selecting only resonances with J=2:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyLJneutronWidthcaptureWidthfissionWidthAfissionWidthB
00.031402.00.0004740.10720.00.0
12.825002.00.0003450.09700.00.0
316.770002.00.0128000.08050.00.0
420.560002.00.0113600.08800.00.0
521.650002.00.0003760.11400.00.0
\n", - "
" - ], - "text/plain": [ - " energy L J neutronWidth captureWidth fissionWidthA fissionWidthB\n", - "0 0.0314 0 2.0 0.000474 0.1072 0.0 0.0\n", - "1 2.8250 0 2.0 0.000345 0.0970 0.0 0.0\n", - "3 16.7700 0 2.0 0.012800 0.0805 0.0 0.0\n", - "4 20.5600 0 2.0 0.011360 0.0880 0.0 0.0\n", - "5 21.6500 0 2.0 0.000376 0.1140 0.0 0.0" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "lower_bound = 2; # inclusive\n", - "upper_bound = 2; # inclusive\n", - "rm_res_cov_sub = gd157_endf.resonance_covariance.ranges[0].subset('J',[lower_bound,upper_bound])\n", - "rm_res_cov_sub.file2res.parameters[:5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The subset method will also store the corresponding subset of the covariance matrix" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(180, 180)" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rm_res_cov_sub.covariance\n", - "gd157_endf.resonance_covariance.ranges[0].covariance.shape\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Checking the size of the new covariance matrix to be sure it was sampled properly: " - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters\n", - "Original: 60\n", - "Subet: 36\n", - "Covariance Size\n", - "Original: (180, 180)\n", - "Subset: (108, 108)\n" - ] - } - ], - "source": [ - "old_n_parameters = gd157_endf.resonance_covariance.ranges[0].parameters.shape[0]\n", - "old_shape = gd157_endf.resonance_covariance.ranges[0].covariance.shape\n", - "new_n_parameters = rm_res_cov_sub.file2res.parameters.shape[0]\n", - "new_shape = rm_res_cov_sub.covariance.shape\n", - "print('Number of parameters\\nOriginal: '+str(old_n_parameters)+'\\nSubet: '+str(new_n_parameters)+'\\nCovariance Size\\nOriginal: '+str(old_shape)+'\\nSubset: '+str(new_shape))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And finally, we can sample from the subset as well" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyLJneutronWidthcaptureWidthfissionWidthAfissionWidthB
00.03048802.00.0004730.1089460.00.0
12.82594402.00.0003280.0983280.00.0
216.77388602.00.0129840.0767790.00.0
320.56573702.00.0116280.0889580.00.0
421.64646902.00.0003890.1278330.00.0
\n", - "
" - ], - "text/plain": [ - " energy L J neutronWidth captureWidth fissionWidthA fissionWidthB\n", - "0 0.030488 0 2.0 0.000473 0.108946 0.0 0.0\n", - "1 2.825944 0 2.0 0.000328 0.098328 0.0 0.0\n", - "2 16.773886 0 2.0 0.012984 0.076779 0.0 0.0\n", - "3 20.565737 0 2.0 0.011628 0.088958 0.0 0.0\n", - "4 21.646469 0 2.0 0.000389 0.127833 0.0 0.0" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "samples_sub = rm_res_cov_sub.sample(n_samples)\n", - "samples_sub[0].parameters[:5]" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/nuclear-data.ipynb b/examples/jupyter/nuclear-data.ipynb deleted file mode 100644 index e13b143e4..000000000 --- a/examples/jupyter/nuclear-data.ipynb +++ /dev/null @@ -1,1503 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this notebook, we will go through the salient features of the `openmc.data` package in the Python API. This package enables inspection, analysis, and conversion of nuclear data from ACE files. Most importantly, the package provides a mean to generate HDF5 nuclear data libraries that are used by the transport solver." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import os\n", - "from pprint import pprint\n", - "import shutil\n", - "import subprocess\n", - "import urllib.request\n", - "\n", - "import h5py\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import matplotlib.cm\n", - "from matplotlib.patches import Rectangle\n", - "\n", - "import openmc.data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Physical Data\n", - "\n", - "Some very helpful physical data is available as part of `openmc.data`: atomic masses, natural abundances, and atomic weights." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "53.939608306" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "openmc.data.atomic_mass('Fe54')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.00015574" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "openmc.data.NATURAL_ABUNDANCE['H2']" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "12.011115164864455" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "openmc.data.atomic_weight('C')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The IncidentNeutron class\n", - "\n", - "The most useful class within the `openmc.data` API is `IncidentNeutron`, which stores to continuous-energy incident neutron data. This class has factory methods `from_ace`, `from_endf`, and `from_hdf5` which take a data file on disk and parse it into a hierarchy of classes in memory. To demonstrate this feature, we will download an ACE file (which can be produced with [NJOY 2016](https://github.com/njoy/NJOY2016)) and then load it in using the `IncidentNeutron.from_ace` method. " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "url = 'https://anl.box.com/shared/static/kxm7s57z3xgfbeq29h54n7q6js8rd11c.ace'\n", - "filename, headers = urllib.request.urlretrieve(url, 'gd157.ace')" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Load ACE data into object\n", - "gd157 = openmc.data.IncidentNeutron.from_ace('gd157.ace')\n", - "gd157" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Cross sections" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From Python, it's easy to explore (and modify) the nuclear data. Let's start off by reading the total cross section. Reactions are indexed using their \"MT\" number -- a unique identifier for each reaction defined by the ENDF-6 format. The MT number for the total cross section is 1." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = gd157[1]\n", - "total" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Cross sections for each reaction can be stored at multiple temperatures. To see what temperatures are available, we can look at the reaction's `xs` attribute." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'294K': }" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total.xs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To find the cross section at a particular energy, 1 eV for example, simply get the cross section at the appropriate temperature and then call it as a function. Note that our nuclear data uses eV as the unit of energy." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "142.64747" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total.xs['294K'](1.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `xs` attribute can also be called on an array of energies." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([142.64747 , 38.6541761 , 175.40019642])" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total.xs['294K']([1.0, 2.0, 3.0])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A quick way to plot cross sections is to use the `energy` attribute of `IncidentNeutron`. This gives an array of all the energy values used in cross section interpolation for each temperature present." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'294K': array([1.0000e-05, 1.0325e-05, 1.0650e-05, ..., 1.9500e+07, 1.9900e+07,\n", - " 2.0000e+07])}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157.energy" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Cross section (b)')" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "energies = gd157.energy['294K']\n", - "total_xs = total.xs['294K'](energies)\n", - "plt.loglog(energies, total_xs)\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Cross section (b)')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reaction Data\n", - "\n", - "Most of the interesting data for an `IncidentNeutron` instance is contained within the `reactions` attribute, which is a dictionary mapping MT values to `Reaction` objects." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ]\n" - ] - } - ], - "source": [ - "pprint(list(gd157.reactions.values())[:10])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's suppose we want to look more closely at the (n,2n) reaction. This reaction has an energy threshold" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Threshold = 6400881.0 eV\n" - ] - } - ], - "source": [ - "n2n = gd157[16]\n", - "print('Threshold = {} eV'.format(n2n.xs['294K'].x[0]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The (n,2n) cross section, like all basic cross sections, is represented by the `Tabulated1D` class. The energy and cross section values in the table can be directly accessed with the `x` and `y` attributes. Using the `x` and `y` has the nice benefit of automatically acounting for reaction thresholds." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'294K': }" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n2n.xs" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(6400881.0, 20000000.0)" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "xs = n2n.xs['294K']\n", - "plt.plot(xs.x, xs.y)\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Cross section (b)')\n", - "plt.xlim((xs.x[0], xs.x[-1]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get information on the energy and angle distribution of the neutrons emitted in the reaction, we need to look at the `products` attribute." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n2n.products" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "neutron = n2n.products[0]\n", - "neutron.distribution" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that the neutrons emitted have a correlated angle-energy distribution. Let's look at the `energy_out` attribute to see what the outgoing energy distributions are." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dist = neutron.distribution[0]\n", - "dist.energy_out" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we see we have a tabulated outgoing energy distribution for each incoming energy. Note that the same probability distribution classes that we could use to create a source definition are also used within the `openmc.data` package. Let's plot every fifth distribution to get an idea of what they look like." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "for e_in, e_out_dist in zip(dist.energy[::5], dist.energy_out[::5]):\n", - " plt.semilogy(e_out_dist.x, e_out_dist.p, label='E={:.2f} MeV'.format(e_in/1e6))\n", - "plt.ylim(top=1e-6)\n", - "plt.legend()\n", - "plt.xlabel('Outgoing energy (eV)')\n", - "plt.ylabel('Probability/eV')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Unresolved resonance probability tables\n", - "\n", - "We can also look at unresolved resonance probability tables which are stored in a `ProbabilityTables` object. In the following example, we'll create a plot showing what the total cross section probability tables look like as a function of incoming energy." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Cross section(b)')" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAEQCAYAAACX5IJuAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzsnXeYVNX9/99netnZ2Q7sshRZWDoqKwiKGCxgwQqWoCaCEgtGk2iM35hfYotRjCRqLESNGitqxIYoVlRUmiIISBPYZZftdXZ26vn9MTuzt5y7c6cXzut59mHnzJ17zwyz530/9RBKKTgcDofDiRVNqifA4XA4nOyACwqHw+Fw4gIXFA6Hw+HEBS4oHA6Hw4kLXFA4HA6HExe4oHA4HA4nLnBB4XA4HE5c4ILC4XA4nLiQEYJCCLESQjYSQs5O9Vw4HA6HwyYlgkIIeZoQ0kAI2SYZn0MI+ZEQsocQ8gfBU7cCWJHcWXI4HA4nEkgqWq8QQk4C0AXgOUrp+N4xLYBdAE4DUANgA4BLAZQBKARgAtBEKX0n6RPmcDgcTlh0qbgopXQtIWSYZHgKgD2U0n0AQAh5GcC5AHIAWAGMBeAkhKyilPqTOF0Oh8PhqCAlgqJAGYBqweMaAFMppUsAgBDySwQsFKaYEEIWA1gMAFardfLo0aMTO1sOh8PJIjZt2tREKS2O5RzpJCj9Qil9JszzywEsB4Cqqiq6cePGZEyLw+FwsgJCyIFYz5FOWV6HAJQLHg/uHVMNIWQuIWR5e3t7XCfG4XA4nPCkk6BsADCSEDKcEGIAcAmAtyI5AaX0bUrpYrvdnpAJcjgcDkeZVKUNvwTgKwCVhJAaQsgiSqkXwBIA7wPYAWAFpfSHCM/LLRQOh8NJESlJG040PIYSOz09PTAajSCEpHoqHA4nCRBCNlFKq2I5Rzq5vGKGWyjxobOzE2azGXfccUeqp8LhcDKIrBIUHkOJD0FB/ve//53imXA4nEwiqwSFEx/0ej0AwO12p3gmHA4nk8gqQeEur/gQjKt5PJ4Uz4TD4WQSWSUo3OUVH/z+QDMCHpDncDiRkFWCwokPPp8v1VPgcDgZCBcUjoyghcLhcDiRkFWCwmMo8aE/C2XNmjU8WM/hcJhklaDwGEp8ULJQtm7ditNPPx2/+c1vkjwjDoeTCWSVoHDig5KF0tzcDADYtm0b83kOh3NkwwWFI0PJQtFqtQB40J7D4bDJKkHhMZT4oCQY2SYo8+fP56nRHE4cySpB4TGU+KBUh6LRaETPZzqvvfZaqqfA4WQVWSUonPgQzgLhd/UcDocFFxSODCULJBu3OuBwOPGDCwpHBrdQOBxONGSVoPCgfHxIZYyEUoqJEyfihRdeSNkcOBxOdGSVoPCgfHxIZRYXpRRbt27FZZddlrI5cDic6MgqQeHEByULJRmWi1Kc5rPPPsP69esTfn0OhxM9ulRPgJN+KFkoyWhrryRaJ598MgCeGMDhpDPcQuHISEcLhcPhpD9cUDgywlkoiYQLCoeTuXBB4chQEo6g0KTC5cXhcNIfLigcGeFcXokUFG6hcDiZS1YJCq9DiQ+pdHlxC4XDyVyySlB4HUp8COfySiTcQuFwMpesEpRU4nA4smZrXG6hcDicaOCCEieqqqowf/78VE8jLmRzDGXr1q0ghGDDhg3M571eL1wuV0LnwOFkK1xQ4oDL5cLOnTvx1ltvpXoqcSGb04bfeecdAMDrr7/OfP6kk06CyWRSda7PPvsM69atCz2eP38+FixYEPskOZwMhVfKx4GGhoZUTyGupDKGkkjRam5uxsGDBwGwhcvj8eCrr75SfT5p9X5ww65wjS1v+OWr6GjrCT3OzTPh4Weyw7rlHNlwQYkDDocj1VOIK6lsvZJIC2XYsGHo6uoCwBauU045JSHXvX7R62hv7xMQrVd8baG4cDiZDBeUONDd3R363e/3h7bKzVRS0XqluroaOTk5Cb1GUEwAtnB9/vnnCbmuUEw4nGwms1e+NEEoKD09mb94pCKGMmTIEFRUVCTMQqmpqUnIeVXB9yPjHCGkvaAQQsYQQh4nhLxGCLk21fNhIXR5OZ3OFM4kPqSq9UpLS0tCBKWhoQHl5eWisWTWu3h1Gnj1fT+yK2u44nCyg5S4vAghTwM4G0ADpXS8YHwOgH8C0AJ4klL6N0rpDgDXEEI0AJ4D8Fgq5twfQgslGwQlHdvXx0JLS4tsTCgolNKkbmvcY9WLHutdPlw2TxzIt9tN+NdTFyZtThxOPEiVhfIMgDnCAUKIFsC/AJwBYCyASwkhY3ufOwfAuwBWJXea6sg2Qcm29vXhxCLR78uv7//PjDU7HnfhZCIpsVAopWsJIcMkw1MA7KGU7gMAQsjLAM4FsJ1S+haAtwgh7wJ4MZlzVYPQ5SUUl0wl2yrlWYIitVASyf7RhaLHw35oEs8FDFHhXjBOBpJOWV5lAKoFj2sATCWEnAzgAgBG9GOhEEIWA1gMBAK8ySRbLRTpQhwUmkQuwKmwUJLdP8ynJdD6+q7pMWqTen0OJ1Gkk6AwoZR+CuBTFcctB7AcAKqqqpK6QmSboGRbDIWVxp1MC0VKzcgC0eOhO5tlxxicXlx+wfOycXueCY88PS9hc+NwYiGdsrwOARCm4gzuHVNNqtrXHylZXjyGkjyUZtzOiyA5aUw6CcoGACMJIcMJIQYAlwCIqDlWqtrXCy2UbI6hcJdXgPb29rh2R/Dq5PPzK02Zpxhz0phUpQ2/BOBkAEWEkBoAf6aUPkUIWQLgfQTShp+mlP4Q4XnnAphbUVER7yn3S7a5vFJpoai9xurVq1FZWYnhw4fHfM1IBSUvLw8FBQXhD1TJwXHFsrFyhhuMw0l3UpXldanC+CrEkBpMKX0bwNtVVVVXR3uOaHA4HDAajXC5XFkhKJnQbfiMM86ATqeDx+MRjTc2NqKwsFAUN0lElhertiUZmBwe/PxicaKj3W7CY8svSMl8OBwhaR+UzwS6u7tRWFiI2trarBCUTLBQgMDeJUIOHz6MQYMG4U9/+hPuvPPOfl/70EMPRXXNaDAb/XC6Eudd7mzq5gF8TlqQTjGUmElVUN7pdKKwsDD0e6ajFCtJ9y2A6+vrAQBvvvlm0q6phgtnN+Kyc+pDP2rwadmxEp9OE2jlIvjhAXxOupBVFkqqXF5OpxN5eXmh3zOdTLFQpATdXJGeI9lpw2ajD05X/7UntSPymeNHbW2UjTELI6E0yOEkjqwSlFThdDqRn58Pk8mUVYIiXWiVxgHg4osvxoIFC3DOOefEdO1YFnclQQl3zmSnDf98rjjgvvztQTGdz8sLIzlpQlYJSiqzvEpLS2E2m7NCUIKuLamLS2nhpZRixYoVWLFiRcx3+7G8Phh8F86zvb0d4b4P4a759ddf4/XXX8fSpUujnlt/GPQ+uD3qRMGrI9B51X1GWo9f1HSSN5zkJJqsEpRUurzMZnPWCEpwQZYKiFIMJZ4uo3hYC36/H2eccQZuueUWOByOsOcMN/9p06YBQMIE5eQT5G6sDz4ewDy2ZkKRbOyoTewtqKUeL95wkpNosioonyqyTVDCWShKrrB4EA8LpbW1FatXr8a8efNUtYlRuuaOHTtEn0GyYy1qYRVGApDvu8JjKpwEk1UWSqpcXtkqKFKhULJc0kVQggRjKWr3OWHNf/v27Rg3bhz+9Kc/ieaWzH1T1HJwkrwwEgCGfSu3fDicRJJVgpJKl5fFYsmaoHywvkNqoUQaW4mGeJxLGJyP1kI5dCjQRu6uu+7q97hEYTD44HbHN9hOCTD/8ldk43a7CU8+cm5cr8U5MskqQUkFlFL09PRklYUSFJRMtVBYwflIrxmuuj7RnDaziTn+3ifs2AoLWQBfQVx5bIUTL7igxEhPT+CPMSgobW1tKZ5R7AgLG4VunuACrWS5xIN4LNq1tbUAAvOK1kJxuVxxmdvhw4fh9/mh0SY/XHlwjDiAP+yHJmYYRef2ydq5ALylCydysioon4pK+aBFko0WCiC+yw8XW4kHqQh8s+Z/9tlny8YinVuwFcxvjr4CzYfiE88wG6IXb42fgrB+FI7nlgsnUrLKQklFDCXYaTibBUWr1YZ+F/4rPCZexFNQ1J4r3scFCbaCAYB7zvodmrsDNSFv7adw+qL7zK6cLRemJ1cXq6pjke4UGQ7io7yOhRMRWSUoqSAbLRShC8vn80Gv1wNQdnkdKYKyZcsWPPXUU1HNxScQkMtHDhQ9938b6qI6Z5ATjmfHWz6SxFuU2rkM2852hfE6Fk6kcEGJkWwUlFS6vFKxe6JaQTnzzDPR3Bz/fUpydARdKqvfE4HXwLZujE6vbIxbLJz+4IISI9kuKEJrJFEWSrz2d5cG4INJBeFQO/9YxaS9vRt2u0U2fusx8ur3OzfHHnMxGXzoUZF6rOQKU2w62Qu3WDhSuKDECEtQ0rUATi1KFkqiYijxEhS16b9qXpcIrrvqMbzw6u+Sci0AuGyOWJSefZVdAFk/lL1l9tCdzaJqe41UdPyU78PCEcGzvGIkuLe41WqF2WwGwE45zSSkMRTp7/G2UISvV7O4Kx0jHVcr7IkSFOm1D9Wot3AsCbjVMxljFH7JY74PC0dKVlkoqcjy6uzsBADYbLaQoDidTphMpmRNIe4It9VNRwslEkGJ9PrpwpKx7O/Pq/uid6meexZb0F59Te5yA+SuMKolIlHR+tPvc+OklqwSlFSgJCj5+eyMmkxg9erVod/VxFBiLWxMlKAA6lxeqUgEyARqRhaIHg/dKRYkvrEXRwoXlBhREpRsIRlZXkIhUHOuTHF5JQKTlqAngloSNRiNfrhU7Hnv0xCRVeLXZ5XHnBMHwgoKIWQwgEsAzABQCsAJYBuAdwG8Ryk9om/vurq6AAA5OTlZLyiJcnllawwlEZw/XB5Av++7djjkGb6qOe+cFub4K6+KXWHS4H3pT5nfZogTX/oVFELIfwCUAXgHwH0AGgCYAIwCMAfAHwkhf6CUrk30RNOVzs5OmM1m6HS6rBCU4OJaXl6O6upqZjwl1WnDkbi8Ir1+JnLTBPaf8Yt7PMzxROMnwCWXviQbt9tNeOLx81MwI06yCGeh/J1Suo0xvg3A/wghBgBD4j+tzKGzsxM2mw0AskJQggKSk5Mjegwkx+XFWtzVBtujtVCyNYZi0gI9MYS3DEY/3P24whS3I+ZdjY9Y+hUUoZj0isdoBGJxP1JK3ZRSN4A9iZ2ielKxwZZQUCyWQNFasL9XJhIUEKvVCgBwu92h5xJloYRzeUUrKEB61aG0bm7C/0z/xpW+25NyvYtH5IgeP7GjK6LXnzS7VfT4q7dyRQKzb0IJ83UVW9hbEgNyy0Xn9YvykXn1fWajKihPCDkLwOMA9iKQwzGcEPIrSul7iZxcpKQqbTgoKLm5uaGxTEWNoCTbQpGeP9PThp31XTAPyAl/YJyxaAm6YwjozzyvQ/T4jffZe7OEq7CXHSyAWzGZjdosr78D+BmldA8AEEJGoDcon6iJZQpdXV0h91BQUDo6Ovp7SVojdXklw0JJlMsLSC8LJcjbox4WPZ679zoYiqwJv+7iUYXM8Yd2sptLRovbzF5WWL3BONmFWkHpDIpJL/sAZO5teBzp7OxEcXGgpUU2CEpQQFgWSlBIHA4Hpk+fjjvvvBN//etfsXTp0piuycokU3oeSP86lN27d2PJkiW44447VB2/dba8g/G4b66M65wSQcTbFFOqGF8RImxACXA3WCYRLssruF3bRkLIKgArEDBS5wPYkOC5ZQQtLS2orKwEgJDrK5MFRY3LCwC++uorXHrppWhqakJjY2yNDBNpoUR6/Xjwu9/9Dh988AFmzJgR9Tncjd0wFMsbSSYCi1aD7ij2Z1HapvjbfQZoGcF6DUVAVASocY9xN1jmEM5CmSv4vR7AzN7fGxFIHz7iaWlpQUFBoKJYq9XCarVmraBIXV06nU52TDREEkPpr4OwGjFS+7p4EEuD0HVV8qaLAHBq9Q1Rn1OJq0YPZI7/eXN0+7TUVhQwx0dtOiwbk7rHuFssswmX5ZX+djeDpqb4+oSV8Hq9aGtrQ2Fhn2/abrdntKD05/ISdiEG+gQl1maYkVgokQpKpNdPd9yNDhiKEx9vAQCrjsARx31a1OwYybRYeCuXjCGcy+t2AP+ilLYqPD8LgIVS+k4iJhct1dXVOHDgAIYOHZrQ67S1BSqFgxYKEIijZLKg9GehCGtSAIS2Bo7WQvH5fKCUhk0blsZY4m2hxDuG8vbbbwMA1q1bF9fzAsDX056RjR33zcXQ5Jnjfq3fj80TPX5wRyucMdS1HGLsGDlov7gzuI/RzkXr8cviKgCPraQj4VxeWwG8QwjpAbAZfa6ukQCOBvAhgL8mdIZRsmjRIqxZsyah+5IEN1wSWijZLChSCyX42UqFRi3HH388Nm7ciMOH+1wh8bZQUunyWrVqlfg6sgbw8aH7168wx/Of/1Vcr7NwtPhvadlW9vsxGnxwqQzWS/uDsVBsk89jK2lHOJfXmwDeJISMBHACgEEAOgA8D2AxpTQtS8IHDx6Mjz76CE888QSuueaahF2npSXQAymbLRShWEiFI7gQR2uhbNy4UXQeIHyWV3/WRLoJSrZj1YHZQ+zMmewkjQ/fyYPHLbZA6oeJ+4OV72L3FVOCZ4SlF6rShimluwHsTvBcmBBCzgNwFoBcAE9RSj8I95ri4mKMGjUKN998M2bPno3hw4cnZG5BQZFaKMI77kyjvzoUqaAEg/SxBuUjqZSP1OWlhmwVFFeDA8aSxMVbbhjHPveDWx3M8arT5M0k170nro3xagl0kjhLJIWS3GpJLWor5UcBuBnAMOFrKKWzorkoIeRpAGcDaKCUjheMzwHwTwBaAE9SSv9GKV0JYCUhJB/AAwDCCgoAPPXUUxg/fjwWLlyIjz76CBpN/FttB4P/2WShBN1awTYy/QlK8NhoXV5BIsnyStcYSqyimgg+HPuM6PHZ26+BKYECEw3S1vnVlfLiy+Hb2Uk2Ok929mDLZNQWNr6KQOuVJwHEtptSgGcAPALgueAAIUQL4F8ATgNQA2ADIeQtSun23kNu731eFUOGDMGyZctw1VVX4dFHH8WSJUviMG0xdXWBtMpBgwaFxux2O1pbmTkMGUF/giKNoQQfJzptWK2FwhKGZLi8du3aFapFSmdWT3qCOX5ewx+SPJM+zjpb7OJa8Sa7PxgLluUiDJlev+h1tLf3cDdYElF72+6llD5GKV1PKd0U/In2or3t7qXO0ikA9lBK9/U2nXwZwLkkwH0I7L2yOZLrLFy4EHPmzMGtt96KXbt2RTtdRQ4dOoS8vLzQ4gsARUVF6OzsTMs7VjUErQ0lC8VgMIQeJ8vlpdZCiZZYz7dly5Y4zSQ1OA9H1jQykWj18psCr5bt8KJaAr/kx6fpOzbo/uJusOSh1kJ5mxByHYA3AISKDiilkUXQ+qcMQLXgcQ2AqQBuAHAqADshpIJS+jjrxYSQxQAWAwHrpHcMTz75JCZOnIgFCxZg3bp10Ov1cZtwbW0tSktLRWNFRYFNiZqammTPZQLhXF5WqzU0liyXVywxFB6UD8/LZf9gjl/pujmq81m1gIPhx1BT1zLiaLm7eBfYPchGbJMH/z16DeZfHsh6M6qYKye+qBWUX/T+e4tgjAI4Kr7TkUMpfQjAQyqOWw5gOQBUVVWFvrVlZWVYvnw55s2bh7/85S+455574jY3lqAE+3pluqAYjUZotVpR0aLX64XFYgm59BLh8lKT5ZVuMZQHHnggptenK92HHbAMjDzmctMoG3OcGuXnenBrdNX4igh8XkGXWAIrBzgS1GZ5JSZNSswhAOWCx4N7x1SjtB/KhRdeiEWLFuHee+/F7NmzcdJJJ8U8WSDg8po1S5yXILRQMpGgSAR3oBRuFubxeJCfny87NplZXulYh7J+/XpVx2WaHfTK0MdEj8/Y/3OYBianv5gamBt8CRpQUi1R/MyXLHwN7W1yV5g9z4RHnp4X55keOajN8tIDuBZAcCX+FMATlNJ47jG6AcBIQshwBITkEgA/j+QE/e2H8o9//AOfffYZLrvsMnz//ffIy8tjnEE9fr8fdXV1ooA8kPmCEnRf6XQ6WCwW0WZhQZdXkHjFUBKZ5RXp9ROJRgOYzRr4/RQaga/f66HQ6dP/Nvq9YS+KHl9w6KqYG1iq2aPFYPDD7ZaHe/cfIw/gH7WpAVLpFrrBgpgc7KWLJTIc9ah1eT0GQA/g0d7Hl/eOXRXNRQkhLwE4GUARIaQGwJ8ppU8RQpYAeB+BtOGnKaU/RHhexR0bc3Jy8OKLL2L69Om45ppr8NJLL8VURV9TUwOv1yurccl0QQlaHXq9XiYoQZdXkOBCH2sMJZF1KOkYQ3F2i11su3fIF7GSQTr445FPmUA2z2Q3sPzZ9+qLia8dJW7Hcn1TFzok9yezTm1mvva9T9gbfAXx6wk0HnUt8znxQa2gHEcpnSR4/DEhJOrUFkrppQrjqwCsYj2n8rz97th43HHH4Y477sAf//hHnH766Vi4cGG0l8KePYHtYaTiFSxyjLWle6oQurxYFkpwzxchyS5sVCJdenkpEYlsVYw1MMf37vBAK8l68vsD1k828MBJ8vf9ty3sGxZWixdhYWTLKYHvqv3jTvAOk8lBraD4CCEjKKV7AYAQchTiU48SV9TsKX/rrbfik08+wfXXX4/Jkydj0qRJisf2h5Kg6HQ65OfnZ6yFInR5Wa1WmaCUlMjdDPEUFDVBeSXLMlpLI2mCEgdDqK5G/llXjI9/Y8hM4MyT5H9jK53Fod/tCHxWejfjO0V692eRQDWEN6KMAbX3NbcA+IQQ8ikh5DMAHwP4XeKmFR2U0rcppYvtdrviMVqtFi+88AIKCgowb948tLe3Kx7bH7t27YLRaERZWZnsueLiYtTX10d13lSjZKH4/X74/f6EC4p0zxUg8S4vacFm4kiua02r9nYxzbFo4/+5deWb0VEg/1GC17KoQ22W10e9DSKD5cA/Ukpj2wQjhZSUlGDFihWYOXMmFi5ciNdeey3ieMp3332H8ePHh1q4CykrK8OhQxElqKUN0hhK0HUXHLfb7bjttttw7733hl4TzxgKS1BisVDUCEqyilCrqQN7fR0YSK3QJMGvP2aieIHcuTU5i6Kz3gHzAHmKsLPBAXMUrV+uHkPBEuMndsjvh4WtXHRaP7w+jap9WDjxIdx+KLMopR8LtgIOUkEIAaX0fwmcW8SocXkFOeGEE3Dffffh5ptvxv33349bb71V9XUopdi8eTPmzWOnF5aXl+OTTz5Rfb50QslCCdajGI1GnHzyySJBiWeWlxoLRakvW7SCEqsgRsLtPethgx7jaAHGowDjUID8LNv89OXh/1Z9bLTFk0qccXpfAL+797/18x/lGZ32Jnaj9P4aUQpdYdwFxiachTITAffWXMZzFEBaCUq4oLyU3/72t9i4cSNuu+02VFZW4rzzzlN1nQMHDqC1tRXHHnss8/nBgwejtrYWPp+PacGkM0HhMBgMIkHp6Qnc3ZrNZlm3gUS7vBKdNpxMQbneOA6bXU3YhhZ8jYBbtNyXg3GkAONJAUYhDwaS3O+MRouUZZS5mxwwFPVZLf52JzR2dTEhixboVjFvndEPr0t8E6JktUi3JA4i3ZqYu8DYhNsP5c+9v95JKf1J+FxvvUhGQwjB008/jZ9++gkLFizAF198gWOOOSbs67744gsAwJQpU5jPl5eXw+fzob6+PuOq5Z1OJ3Q6ncxCCQqKyWSSCUqiXF6UUvRawqExr9cb2npYSiZYKCfqBmGyewD8lKIaXfgBLfgBLfiQVmM1PQgdNKhEHs78aQBOKCzGaFtuwt1jw0ewLaQDP/XAm+CP5ruznhU9LimX/3/lrriE+dpfjZVX5C/b2ikbG326vJ3L+q/YKcdDt7CTaaSWi18D/Pzivrocu92Ex5ZLHTlHHmrDdq8DkN6OvwZgcnynk3zMZjNWrlyJKVOmYO7cufjyyy/Dbh38wQcfoKioCEcffTTz+cGDBwMIbEWciYJiNgfuEIWCEqyYZwlKPC0U4eLu9Xqh1+tlzxuN7C5NmSAoQTSEYChsGAobztYMg4v68CPa8ANtwQ+0GUt378DS3TtQaDBgekExTigM/CSTo6tyRI83f9MFYUKcRkvh96VXOq5FR9DdWz2vpneYFGb1Pfqvuge4xRIkXAxlNIBxCDRmFMpvLpB+jt9IYihCBg4ciHfeeQczZ87EKaecgrVr1yoKgcvlwrvvvos5c+Yo+vLLywMdZGpqajB16tSI5pJqWIJCKU2oy0tolQgzrjweD/R6vUgUPB5PRru8lDASLSaiEBNJIYCRGHGCButaGvFlc+Dn7cOBJI8yWDG2N/ZSiTwYk+geKy0XC/lRY9hisn9PfK/rb3NCk6fODXbd2L5CSb0mMN8/fFOHLkkin9ngg5OxTXH1mCLmeUdtkmyaJ2jxAgDER3m6McJbKJUIbISVB3EcpROAqjhFMok0hiJk4sSJeO+993Daaadh1qxZWL16NYYNGyY7buXKlWhpacEvfvEL+Ul6CQrKgQMHIp1GyhEKitVqhd/vh9Pp7NflFU9BES7ubrcbFotF0YKRkkkWSjgGmEw4v7Qc55eWw08pfuzqwLrmJryzqw6f4hDWoBo6EFRQO3bsGYATi4oxzp5491gqcF67kjlueVVdRf7/HSNf5t4sZhce/3PlIOa4T0+g9fR9lzR+QE0a+JFmuajdU34apfSrJM0pZRx//PF47733MHfuXEybNg0rV64UWRherxd33303RowYgVNPPVXxPPn5+cjPz0/IHiyJRigowX5n7e3t/bq8Yl2QhVaJ1EIBxKLgdrvjXoeSjoIiREMIxtjsGGOzo3L3QLipD7vRHoq/LN35I5biRxQYDJhWWIjpRUWYVlSIgdQWU3uhIxGTwYcehuVSN71A9HjwJ02iwkil7LAj7eNXG0O5hhCyg1LaBgC92/H+nVIafe+SNOXEE0/El19+iTPPPBPTp0/HTTfdhF//+tfIycnBjTfeiG3btuF///tfv1sKE0JQWVmZ8YIS7Czc1taWUJcXS0SEv0stlCNNUKQYiBb+9PGyAAAgAElEQVTjet1eADD2Zxqsa2nCF02N+LKxCe8GdxI1mnF8flHvT/LiL3oD4GF8JTQaIJ5NCXrqHTAx6l3UYNQALsZczp/VwDz+zS/ErjCnTdwixuzwKNorwuB9kGwN4qsVlIlBMQEASmkrISR8OlSSiTaGImXs2LHYsmULbrnlFjz44IN48MEHg+fHnXfeifPPPz/sOSorK7FmzZqY5pEKWBZKa2uryOUlzbJKpqBEaqGoIdWCQoi8LUsww00Npm4LZpmGYNbgIaBlFAd6HFjf3oiNjiZ83HQYbxwO7FtXprVigr4AE/UFGKfPR66G3S8sVo47MYc5fnCv/HP2eil0ur736fcF0pjV8MZgeb3LJQ3XQVcQXmTmDGFvtPfvnezvgl7nh8cruIk0ABB87SMtnsxWV5haQdEQQvIppa0AQAgpiOC1SSOWGIoUu92O5cuX49Zbb8WqVavQ3d2N008/XVVaMRAQlGeffRadnZ2w2dgbDqUjLEFpa2sLubxSYaFIn890C0UqILl58hVUb2RXh4erGSGEYJg5B8PMObjcPAx+Cuzs6sA3rY348GA9Pu2pxeqegMAM0eZgnD4fUw1FONpcgHxd8vc4/Gm3uOGGTi8PvheXqS+SqV/0n9DvA574FcwDc+BpdkJfGFu/s+nHtIoe7yoT5yTVbJY3TQWAoTvZnZIBueWSDVaLWlH4O4CvCCGv9j6eDyB+Wx+mMSNGjMANN9wQ8esqKwNdanbt2oXJkzMnu9rpdKKgIOBKEbq8ggWPiY6hsARFGrSPt6C43W7U1cV550AFdDqC4gHSz0/9ne3gIeoX/YAoAZNMNkwqsmF89SB49X78RDuwk7Zhh78VH/fU4r3agMAMNeRgkrkAR1sCP/lgWxrJp7/6dWVeLg1sbTx4qPwzm/rjL5mvMWsBZxyLPJWaULJwNDjwi/P+G3qcm2fCw8/Mj99kkoDaXl7PEUI2AghuT3gBpXR74qaV+YwfPx4A8P3332eUoHR2diInJ7CQCC2U4KJvs9niLihKWV4sCyVRLq8rr7wyqtdmGjqiwUiSh5HIw1ztMHipHz0DXdjibMZ3zhZ82FmLt9oPAgCGHrKiyl6EqtxCVOUWQrpcuHoojKbER531Jra1lgh+Wcl2l937bbfoca4Bon1bTEY/elzyuKozh30DYOl0ySRS+riDsdnXDb98VTaeTsITiduqAICDUvofQkgxIWS4tHqe00dFRQVyc3OxcePGjFqs2tvbEezWLIyhBBfr3NxcWQwlGF8BIvP9B1GyUIKutERbKB6PR/QejiR0RIMJtnxMsOXjMgBe6seeng5862jG965WvN90CK/XB9LfS3UWTDAVYIIpH+OM+ah+T8v8v54+K10sG2X8rU5o8tW7waw6wCGoZXlstlh4nq1kV9ivXGaGhhFbYf2FyOwwRt4PS2RYY6lC7RbAfwZQhUBdyn8Q2L3xeQAnJG5qkROvoHw80Gg0mDx5MjZu3JjqqUSEUFCMRiPMZjNaW1uh0WhE8ROdThcSAuGC7/f7I+5fFi5tOBYLJZ26DWcCOqLBaHMeRpvzcKVZAx+l2OPswKbOJmz1NOPrlnq831UDAMiFARXUjgoEfobCBj1J3k5fOh0g3XlArdXUee0K5njhCnb4dcn46OJLdcPZW2lUbKnvrWXpQ6mPWCah9h2cD+AYAJsBgFJaSwhJu0hzPIPy8WDy5Ml4+OGH4Xa7YTAkJqMmnrhcLrjdbgj3kykpKUF9fT2sVqtot0a9Xs/cRySahphSwQiSrBhKsBsAR46WEFRa7Ki02FEw4Cj4KcXurk5sbm3Fqm2N2IN2bEagSFAHDYZTG2buLsaxeQU4xp6PfEPfQqzVU/g8YRb7CMIlYybK3VPr1jhCv+v0gNcD+HxUtsulEu6mbhiKLOEPVInB4IObUdfSXiSfu71J7FbzE+CiBS+LxtJ9KzW1guKmlFJCCAUAQkh0yd9HGMcddxxcLhe2bNmC4447LtXTCUtwszGhoJSVlaG2thYDBgyQCUow80sIq1twOIRuLqHrKR5ZXmoQ7krJ6R8NIai05aLSlovSHwK1Le3UhT1ox260Yw/a8Uz1Xjx5MNB/ZajRikk5BZiUU4DZE20YYbOK3GQfvyGuTdHr4xeTmTIj4Hr7+lOH7LnRx7Atjk0nPM8+1zeXgtj7hMbV1A2jQHhMhKKHyud+ygy2K2zTyxZQt/h4Weoxw53I1Ns0Kp5UKygrCCFPAMgjhFwNYCEA9ZseHKGcfPLJAIAPP/wwowRFKBylpaXYtm0bTCaTTFBYRCMoQsEQilQws0x4zkS4vBwO+YLDUY+dGDEZJZiMwG6eI482YbujDd87WrClqxWftR3GW83VuOsAUGDUo6ooD5OL8nBsUR6sJXZYNezvUhCfNwG7T2oR0Sbm/tufEz3+4i2x1fHzbT9nvu7/dbInbj9ZfvF93xWKHg/Z2SzTCr+O4VL0U1x+wfOw55nwyNPsPZqShdosrwcIIacB6EAgjvL/KKWZV7WXZEpKSjBp0iSsWbMGt912W6qnExaWhVJaWooPPvgAubm5KCzs+8JbrVY0N8tz7KPZn10oKEILJWg5CJ93uVyK1zhSBSXduv6aNFocayvEsbbA98VPKQ70dKHa1oj1jW3Y2NiKDw4F3GQEwBB9DkYb7RhjysN0WxEqLDboBLGY+gP9C040FI1jf167tsTX9WnSUvSo/L/R6vzwCYonqQbQRtAtOR2KJdUG5a0APqaUriGEVAKoJIToKaWZ1bMiBZx22ml46KGH0N3dDYslfr7ZRKAkKB0dHdi9ezfOOeec0PigQYNw8OBB2TmiCXALXyN0PwUXeqGF4nA4EiIo6fZ/43ZRGIzqFqIh49m7D9buNsJg6DuHUusTpcw8+bjY4aK2lYqGEAw323BShQkLKgKNU1tdbnzX3I7V37VjR087vupuwPtdh/CPpoAgjbHaMTYnD2Otdowy2zHUlAOtZI6EUFCJm4kVqI8ErS5gEUVKT6MTpmJ5hOOsoeyd0h9vMaJd8qcydHyX6PFerbzz8YgtDbKKfL8+eYkQ4VBrSK4FMKO3h9dqABsBXAxgQaImli3Mnj0bDzzwAD744APVO0Kmio6OwEZEQkEZNWoUgEDq8KBBfZ1YBw4cyDwHK64SDqGgdHV1wWQyoaenJyQoQgslUkFRQ3d3d6g7QCrw+yk0GvHCuO5D9t3m4KEG2bFKfP2J+P9iWAV7x4nAxyv/7Exm8UJltIo/95KBkSWaeFwU+l6RzDca8LPSYhQfCLjJKKWo83ajxtCJbd1t2N7VhtfrD+CF3rYAZo0Woyy5GGPNwxirHWMseZhUZoU01j5xcl/Kst9HodESEA1AVRrOIxQsl3AtYd6bzt68tmLjOfDnyr9bj8+S38Bculocy2MF9OuHyrPGiqs7oPVTUJWJB4lEraAQSmk3IWQRgMcopfcTQr5L5MSyhZkzZ6K4uBgvvfRS2gtKS0sLgL4KeQCYNGlS6HdhO3+ldjLRCEowVgIEBCU/Px91dXVMC6Wrq0sxThOLhRKsuUk0peUGuFziOTUcVm/ot7emaK/eSCAUYASoN38OSIXLlkvg9wVaxpTqrRisycHxOYOAHMBHKQ66u1Ct7cTO7nbscLRhZeNBvFzfKzI7tBhjy8X4XDvG2+0Yn2tHCc0NuctamwIqklcgX+a8PYAugh2dWmvFB/v9blXCPvjut9hPPH6TbEhaLHn6LLlL+cuVNnh6xELfVJY+CbeqBYUQMg0Bi2RR71jabZaeTnUoQfR6PebPn4///Oc/ad/Xq6Eh0Gm1pKQkNCYUkWOP7du0M9gJQEo8LJSSkhLU1dXJYiharRZdXV1xdXnpdLp+rR5O5OTmsRfa2hr52PAx4sXxpx19/19aQjDcaMNYsx2zbYFdUH2U4qCrCzud7Tioace2jna8dqgazx3cDyDgLgtYMnYM09pQYcqFnZplG5Ht+4y9fOUP8EJNKU1Tg9gvZrNrVVuOAOCsd8As6ZS87BTxnB77gcIhib8cf658i+MvX7OBegjC5DYkBbWCciOA2wC8QSn9gRByFIBPEjet6Ei3OpQgl112GR599FG8+OKL+NWvfpXq6SjS0NAAm80mcv9oNBo899xzWL9+PaqqqkLj1113HTweD1566SVs397XhSceFsqQIUNgNptlFordbo97DCU3N5cLSgahJQTDTTYMN9lQNGgwCAmIzE+OLmzraMe3De3Y4WjH243V6O51lxEAg7QWDNfZMExnwzC9DQZXIQYazLLYkYfRPiV4kv4aQHS2sy1Hr1sHHcMz+PKQx2Rj5xxcCPPAPpH57VB5y5mlB7SybY3tk2MIGsUZtVleaxGIowQf7wPw60RNKts4/vjjceyxx+Khhx7C4sWL03bTo4aGBpF1EuTyyy/H5ZdfLhqz2Wy4/fbbsXr1atF4rBaKy+WCwWCAxWKRxVDsdnvEFkq4NGa73Y6WlpaMrpb3uAN7kCQa6ofo7j2aNjvhYLXy7+9YICAyFTk2VOTYcKplCIBAZlkT6cbOrg5srG3FPlcn9ro78aWjPvCibwGbVo9RllwcZbFhhDnwM8FsRaHBIHtf0rep1wNqWtjt+17pP0YuAm8NeVr0+LK9l0AnaQ/z+0ny2OXC2ja0uwB78ptFy8j8Wv8MgBCCm266CVdccQXefPPNtI2lNDQ0oLg4so2YpH29YrVQAMBgMMBqtSpaKEoiwRoPZ3mUlJTgp59+QlMTuwAtE9i1gb2SEOIULc4+L4VWp14ApMkC0rt3t9uHWJs2SrPZWK383T2RX0NDCMrNVpSbrRjv6vtOO3we/OTuQq22C7u7O7Db2YFVTTVwBFO7dgD5ej0qcmwYmWNDRU4OKnJsqLRbUag3hYSm6gRxv7L1n3chkhIsU64GPR39fzerl8jjL0e9+1vZ2CNnpM8NKheUJHHppZfinnvuwR//+EfMnTs34vYkyaChoUEUM1FDUFByc3PR0dERs4UCyAVFaKE0NDQoikQ0ghIUUGFNzZQpU7B+/Xr1byABaLVgLlCRWAUWq/g7Vr2fncI6cgw7w621WXwXXThI3XeWlc4LAGaz3J303TrxbX7FmAgi5cy6cfmYML3ZqtVjvDkfJ+T3peRSStHo6cE+ZxcOuLqw19mJfd2deLu2Fp2+vvnlGXUYk5+DynwrBnnyUGHNxVGWHJQYTagYzf4MpRuIBbnoUfne9f+94lDYbDRPkwN6aduWLieQYwYcToDdOixpcEFJEjqdDvfccw/mzZuHp556CosXL071lGQcPnwYU6dOjeg1wSSDoqIidHR0RNXGhGWh5Ofno7U1sKlRUHAGDBiAnTt3ikRCuMCqEZSjjz4a333Xl6AYdPEFCyrPOecc3HfffRgzZkzE70MtUkuBJR5KC9TBn1xIViv3aCksZ7sPD+yJ702UySZffbva+iLTQffcoHL5dX0esbgNhRVD7VZ4PX0uX0opmjwu7O3uRGt+M3a2OLCz1YE39zWg1XUodJxZo0Wp3oIhRisGG6woN1pDv9fv9DFvACa7c6ExiOdlsYgf+/0BMRTy7elPyM414QzBl+eeS2XPJxO1hY33A7gbgBOBOpSJAH5DKWU3vuEwueCCCzBz5kz8/ve/x1lnnYWysrJUTymE0+lEQ0MDhg4dGtHrghbN6NGjsW/fvpAIRALLQikqKsKBA4G26UHBKS8vR1NTk6yZpNEYcPkoNasUMm3aNOzbty9UcyN18Wm1WhQVyQvK4kVnhw+11eL3Wzku3Vv+JQ5pcSSrJiep8xHVchAM0JkxwGxGaaU1VIdCKcXmTVrsd3dhv7MLB5wO7GjqwC5HB9Z21MMnEHwLdBhAzRgAS++PGQNhQeNGIM8iTsvSGwLxsCAuh0b2WVDqlQuUTgN4/YAh9faB2hmcTin9PSHkfAD7AVyAQJCeC0oEEELw5JNPYuLEiVi4cCFWrVqVNq6v4OIdqctr+PDhodcRQqKKRUgtFKPRCKvVik2bNgHosx5KS0vh8/lE7qmenp6QoKixUDQajagPmbRAU6PRiFrMRIqwrb8UY4Jauyu5VWJ9vdS9pjYoz7qzBtiV9SUDxYtqZ7vc6rDmKGVeyetdhO+FaCion4QKHMWw2xordSZurTOKAvNNu9zIgRXjYcV4ABcVBOboo37U+5w45O1Gra8bNR4H6nzd2Odtxzf++pDU3PkvoMRswAi7BUNzzRhmM6NkWA6GWCwYYrWgxGRE3T75Z+H1UPj9YgvVOG0I+/NJAWoFJXjcWQBepZS2p2umUrpTUVGBZcuW4ZprrsFf/vIX3HXXXameEgBg//79ABCxhbJgwQJs3LgRN954I1asWBGVoEgtFKPRiKKiIjQ1NYFSCpfLBaPRiAEDBgAA6uvrQ8c6nc5QZb8aQdFqtSJBKS0tlT0fy3f73HPPxeuvv8587tr8sVGftz+k+7IHybFpRK40pQyqn3azq/IDi33fCzwu8c2Pq4e9k2JPJzuzqahEvty0t0af8po/WP7//eXqvvPNujDw/7hzvfh9AEBhMXvpq6thu+tGjteJPjvpZ2nJCX42WtigRwUCjVSdTh+8vWEYN/XhsM+JQ14HjKO6sK+zG3vbu/H5oRa84nCJZmjUaDBQb0apwYJSgwVlBisGGcwYW2pFudmCHF3fd9jX7YPWooXP6WftyZVU1ArKO4SQnQi4vK4lhBQDSEonst6alz8CsFNKU9tKM04sXrwY33zzDe6++26MGjVKlpKbCqK1UAoLC/Hcc4FOrEVFRWhsbIz42kHB8Pv98Hg8sNlsKCoqgsvlgsPhgMvlgslkCrmnamtrQ68VNpNkCYp0TKvVijLTioqKYDAYQqIW642SsD2NFDftnQuBaH2jfgqSADfPqLFiV9reXew/WWnwPe2QfF5BWO1QhPEorxvQGcBsvcK2WpQtFKkVx8pGYzF+CgRZbDoANgA2tNXrQXIJ0Ov1dvt92LK/A9VOJw57u1HncaLe50StuxvfO1rh8Pf+HwX+TJGn16PcbMVgswXD/mDC7NIBOCa/AEPOVzWthKG2DuUPvXGUdkqpjxDiAHButBclhDwN4GwADZTS8YLxOQD+iUAV/pOU0r/11rwsIoS8Fu310g1CCB599FHs378fV155JaxWKy644IKUzmnPnj0wGAz9LojhKC0tRXV1dcSv6+7uhslkglarRUtLC3JyckJup6amppBba/DgQLX07t27Q68VZpWptVCEY0ajEYMGDQoJqobhqxkyZAizESaLkSNHKj7nIX7odARWSfaV2wNIV8yCQvafJju+kJwgvdIiLEf9LlnSBAVbrnyhzslln8vRJD926Ii+O/d93wf+nwuL5cc11LJFtL6WXVyi04lTs6WxHouVgPoZ7WbWekIWipBhFTrJ3i9azJ1jAvxGAIE2QDU7jNAbAt/Hdo8b1c5ufLK5FU3oQYPficYuJzZ3tuKD+h6sO9yK548+iTn3ZKI2KD8fwOpeMbkdwLEIBOkPR3ndZwA8AiC0yQAhRAvgXwBOA1ADYAMh5C1K6XbmGTIck8mEN998E6effjrmz5+PJ554AldddVXK5rN161aMHTs2ppjOqFGj8PLLL0dc8NbV1QWLxRJazG02W8gVVVNTE7JQgvGaH374IfTaaARl7ty5eOKJQLaMwWBAWVmZTFBOPvlkfPrppwAi66CsFH8Zqs/BKTmlzOdiRSnFWLqwK7m8lLoGG4xicQ32xup7Hfv/2GJnF2S0N8h7g+zfJ3bXjZ5ghl7WPVe9QAm/e1odhc9L4HFT6A3qXh/c5VGK9LOTxnpGjmcvpSWD2TVCX34oT68fdZ4NWkPfe//uuTa4RUalHlMNJaLAPQA8bt6KNpcbdTUesBsiJQ+1Lq8/UUpfJYScCOBUAEsBPAYgshzTXiilawkhwyTDUwDs6bVIQAh5GQErKCsFBQgsnGvWrMG8efNw9dVXY+/evbjrrrtkxYLJYOvWrTjllFNiOkdlZSXa2tpQX1+v2I2YhcPhgNlsDu3QmJOTExKP/fv3o6enByaTCWazGWVlZdizZ0/otcGW+wA7y0sqKH6/H8uWLcOrr76KlpaWQFNCQRwlKCgvvPACVq5ciWXLluGWW25R3TLHZDLhmmuuweOPPy4af6p8hqrX98FeRFnum9ET2K33cwrEB0rrUoKwrAJAXWv6SPB6/NBJxEIqhju3yhfan81lZ8Gxgv8ed19cZ1RV4Pvw/svyNzJSod7lOEnBYui8kjBVa4sXfsG8KShIBEF+1k1A+/dO0Y3YKefrZe+vp0src/M99m7gX2mwPhWoXbmCb/0sAMsppe8SQu6O81zKAAj9JTUAphJCCgHcA+AYQshtlNJ7WS8mhCwGsBgIuCgyhZycHLz99tu4/vrr8be//Q1fffUVXnzxRVmwOJE0NDSgtrYWEyZMiOk8xx9/PABg7dq1uOiii/o9VtpBeODAgejsDDS+Ky4uDsVyfvrpJ1F7+VGjRuHQob4agGBDS+k5lca8Xi/MZjNWrlyJ3/3udxg9erTosw7+QZeWluK6667DddddBwCorq7G3XfLv/IWiwUWiyWUjGAymfDII49g0aJFol06Ozv65iHd54SVxWTJBViuLCVXmBqUXFZq9zWRipnS3iPSbLAg276Ti8VRo8RisXuH+sLYrmZWN8S+CQZjLCwRVrai2ULu8fhFltOwCoNoUzO9wY/eHdJFHNrJ7gFWNsQoFxrqE1tBLVroJFsitzdqZPN2u/3o8nuxtaEVE+vqUFxcnJKbUkC9oBzq3QL4NAD3EUKMQHISCiilzQCuUXHccgDLAaCqqir1Uh0Ber0ey5cvx4knnohrr70W48aNw9KlS7Fw4UKmTz/efPHFFwCAE044IabzVFVVITc3F++//35YQZF2GDabzSgvL8eBAwdQVlYGk8mEQYMGYd++fWhvbw9lck2ZMgWffNLXlzScoEh3YwxaQTNmzAhVwwvrgQwGdobSXXfdhdtuuw1Wq7hK+fHHH8ezzz6Ljz76CABCsaCqqipRtb8Q6QKn0VD4Zf539sLGWgi9HipbeAB5IPmwQnxg2s/YFk7TYfEqPGCw+BqFA9iWg8/LzjpjoaZ3l6uHwmhSt/gL3XRtdQF3U36+/H0H3EbyC+uN7PEtn4oLdmdfJHZluRzsv9Mep595PlZ2W8UxWqEeYs82ucrb8+WuxmFDdNiy34FbnF/jltJSaDQaDBo0COXl5Rg8eDBKS0tRXFyMoqKi0L/Bn8LCwriKj9ozXQRgDoAHKKVthJBBAG6J2ywCHAJQLng8uHdMNenYvj4SrrjiCkydOhWLFy/G1Vdfjf/+979YtmyZqG18Ili7di1MJpOom3A06HQ6nH/++VixYgWWLVsm2oNeilBQenp6YLFYcPvtt8NisYSq9SdMmIAtW7aAUhqyOoNWEBCIh9TV1YUeswQlWMAYxMPo6Ce0UMaOVU7tZe3qaLVa8eSTT4ZcdDk5fS6TUaNG4dtvvwUgLpgrGSC+sy6tkM+7p1ML1kLEWghra9h39aWDDcxzSFGuJxEHnqVZVcr1L2wxNBgBt0RrSsok7ev3yF+3bg07Oy3gCpO+P+H5AvNgFUsqzV0p3qLRQuziklhhSqKu01N4PQzXJUNIbSP00Aqu7f/MBY3k/6W12St7L38/pRKXVA5El8cHz7zrUFdXh+rqalRXV2Pr1q14//33Q9Y/i/z8/LgV86rN8uomhOwFMJsQMhvA55TSD+Iygz42ABhJCBmOgJBcAuDnkZwgXdvXR0JlZSU++eQT/Oc//8Hvf/97TJ48GfPnz8ddd92FysrKuF+PUoo33ngDp5xyiuLdeSQsWbIEzz77LO6//36miyiINNBtNpsxffp0TJ8+PTQ2efJkLF26FMXFxSF33KxZswAE3GL5+fnYuXOn4jkBcYwFCC8oN9xwQ39vT4bJZMKwYcPw9NNPY+HChaIsr+uvvx5XXXUV/lkktvykfnVW+qui752xRa3eKPfxA+o79wZKGlh30T7JcWIhbDzMTlaYOZodlJ9xptxF1SnZQ4olOqwxgC2EQrdeoG08jWgDs5oDbEujVBJcp34isjJZ1gQATJ3NHv/2U/nS27JV/Lm1tajrNllkNeCMYcWATgP7tdcyj3G73WhubkZjYyOamprQ1NQk+12YPRktarO8bgRwNYDgPpfPE0KWU0ofjuaihJCXAJwMoIgQUgPgz5TSpwghSwC8j0Da8NOU0h/6OQ3rvBltoQTRaDRYtGgR5s2bh7///e948MEH8frrr+Pcc8/FTTfdhBkzZsStbfi6detw8ODBfhf/SKiqqsLll1+O+++/H3PnzlXsDSZd/AsKCpjn8nq9qKurC/Xcys3NxYYNG2C323HbbbeJ+nL19PSECiKDtLa2QqPR4NFHH8U111zDDNwLXV7hstyqqqqwceNG1NXV4d5778Vpp50GALjyyitx+eWXi9wHCxcuxKxZs7D9BPEfeXOTeA75xfJMoOZ6diffinHyP1lrvmwIAHBot/jY5sbY6k3UtkWhlB03YI5Lqt1nnS9/f0oNE91OQPoZNdb3vceCAawYS3To84zwtAlUzWYEOvseGwrNcDfLLUWf1QitQ66G2gIDfC0SQbYZgM6+MWOxGa5G8TmNRWa4msRj2nFFMLjd8JiU+9cHSwL6Kwt45ZVXFJ9Ti1qX1yIAUymlDgAghNwH4CsAUQkKpZTZwYxSugrAqmjO2fv6jLdQhNjtdtx5551YsmQJli1bhuXLl+ONN97A0UcfjauuugoXX3xxzKbq0qVLkZ+fH9eW+suWLcOXX36Jc889F59//jmzNkMqKKx026A1AgBHHXVU6Pega27atGl4/fXXceDAAQwdOhROp1O2N3xzczPMZnO/1ld5eZ+nNZxQf/jhh+ju7sbAgQPxz3/+U/Sc1BdNCMHw4cPxo14Dn0fQ0FJSyMNsciIAABe6SURBVMiyRpQsFFZmk1KMQe7WUWg3otDWXmoNSVNlFdOQFTTZ0yN/wpwT31QyfaEJnuaAi4zkmkA7emAsNsHVKHabscYAwFBkhrtJLgwzPxSX3XXYxFlip+gHMOezu2MPc3w0Q+s0kl0lzzHIMyWlxwDA1w19bt8TmVdLHqq3AEZfphd6f+e9V5JESUkJ7r33XvzpT3/CCy+8gEceeQRLlizBTTfdhDlz5uCiiy7CnDlzIt7L5J133sGbb76JO+64I65bExcWFuKdd97BSSedhBNOOAHvvvuuKOMJgKwrMUtQ8vLycNlll+Gll14SiUuQs88+GzfffDNWrlyJG2+8ET09PTCbzXj//ffxxRdf4K677kJNTQ2MRmNIUKR9wwB2bEQJu90eShBQy/CR4tXj26/F772pTu7aqFVoAWLPt8rG1r/H7vBstrAsErkCHK5mt1AZMUYswvt3ic/H2qs9QAyWUI4J6JIs9DYT0MmIo0ju6AFg2uYFod81vbuUn0Xln6WOsG8wdBqFu/y2/jtAdLh9yDXIF/tuL4FFJ/9su9xAjqH/sR6fHyat+O6hy+NHjiT12ukhMOspnIxYTbIh4bZIBQBCyG8B/ALAG71D5wF4hlL6jwTOLWIELq+r4+EPTGe+//57vPDCC3jhhRdw6NAhEEIwZcoUzJkzB9OnT8eUKVOQl5en+Pp3330Xl1xyCY466iisX78+1GAxnuzatQunn3466urqsGzZMlx77bUhC+CLL77AjBl9tRnPPPMMfvGLX8jO4fF4cPjwYZEVEYRSiqlTp6KjowPbt2/HhRdeiH379mHLli2oq6sLxUYGDRqETZs2obS0FB999BFTnILzUvP3ECl75l8KX2vfor99L+Bq7HscCJ6LURKUCccyBOULdsDVbFGXIThkgh3eVvld+aCh4gXyUJMOnpa+hT233Axfq1ygJ52tARxykWtpt4N2iI/X5BsAwZj9pV/KXkcUEkq7ve2yMbOu78YoKCjeCASl22NArlG+MLuaGmET6OdhsxEWgVV381fs741eyx53Mqw1KacOlQvz9y3yue0/3GctvXJu9B03CCGbKKUxZeaoDco/SAj5FH0W1ZWU0m9juXAiyDaXV39MnDgREydOxL333ovNmzdj1apVePfdd3HnnXeGgpWjR4/G6NGjMWzYMJSUlECj0aC2thaffvoptmzZggkTJuC9995LiJgAgSynTZs24YorrsD111+PVatW4dFHH8WQIUPQ0tIiOnb8eHaNr16vZ4oJ0LcT5oIFC7By5Uo4HI6QtVFSUgKtVgufzxdqr9KfWJx00klYu3at4vOxUPHiFaLHlTqxu+SrGY/C0yRegI1FFria5Iuy1m6Gr128+BuKTXCrcN8YikxwN8mPm/4Fu2hz78//DX9b3/HT1i8SPd/jUxAyPdsNm+eVb23gp+oCz2rp8lDk9GZbBX93eCiskgws4XFCfv0RO+U5P18sQGVWqVXHtg48bgK9Qd1Nis8FaAV/it1OAotZRZaeGyAGAGmwi3VYC6W3JcoPlNLRyZlS7FRVVdGNGzemehopob29HRs2bMDXX3+N9evXY+/evdi/f3/IxWSxWDBp0iRcdtllWLRoUcLERIjf78fDDz+M//u//4NGo8Ff//pXOBwO3HbbbXjuuefw/fff4/77748q0cDr9WLSpElwu90wGAwYMWIE3norsHXq4MGDcejQIYwaNQo//vhjv+epra1FbW1tzKnTTDzviR9LBMXHcBEF766lsKqxW9zs7HqLTuyaU1q8LURu9QBAu0+cgmXSit2iSoJiUxAUhwpB6fFpRHf+AODwEObi3+hsh1USi7hzc99nG+xiYmXcNjcrlMq0trL/HvLzxS8ok3xke5o00DGEY/vH8mQTADhqarvs+IOrxSeljASIo89oh17iof3hmb644TuPRd8dMikWSm//rh8JIUMopeo65KWIbMnyigW73Y5TTz0Vp556amiMUgqn0wlKKSwWS9wyxNSi0Whw44034txzz8WvfvUr/PrXvwYQ2JQr1k7LOp0OS5cuxVlnnQVAXJw5ZswYHDp0SFQbokRpaWnCuhN0eSlyBIukw+ODVZ8e++AAbL98LHR6fLAx3p8aS+HR7XJxbVQonteQSLYLVofPA2hVJIe5egiMpj5B2LmOLRwavx9gCMOuTfLUvByELwjd8xLjPWsC6XOpbl0PqA/K5wP4gRCyHkCo9JdSek5CZhUlR5LLKxIIIREFnhPFsGHDsHr1anzwwQdYs2YNfvnLX8blvGeccQbmzZuH1157DSee2JfncvTRR+PDDz/st8AyGSzd3iZ6bJUEaa8ZUygTmC6PDzmMRbnb64NFJx53egEz4y/Z4fHDKhCKbi+V3f0DwH1bm2VjAHDNWLFlIBUelkAAwP/byD6fiaGhnZJOy8Vx3LzS7SYwGCjcPQQGkzq3U+23bGvNNtMNneAca9+UJGYozNviYNfAdOTLhYH4/KDayGXB2JM+2w+obg6Z0FlwjhgIIZg9ezZmz54d13O++OKLuOmmmzBt2rTQ+IwZM/DAAw8kpX1NLPx7p3wBbnOxrciBFvnC6PAq+O/98rYvkfDQNnGcwE/FLq6AtiS+y5HHQ6DXs7oGyOMTHheB3hgY+/qbQCqvpU1+5z96VptIIMLx0yqJlSuJ6Wu8fvh1sX3PChrEMbOWgVb4oxCYVNKvoBBCKgAMoJR+Jhk/EUAd+1Wpg7u8jlz0er2sF9mZZ56J22+/PWxfsUTjdmtgMMS5dW+WIBUFl5vAKBGJLZtKmK/1M27MTUKLoJ9MeJlABGEbKGEp29fGHG8rMjOtDjUCVFIjj1F12RkuLz8FNJnh8voHgNsY4+29z82N+4xigLu8OEJ0Ol1abLH88YfiGpszZzfBbOxfYNwuAoMxOT1Og66hcHNQOk6KkkXBek/bPhd/NiQvtbUUai0Nte4pqdURpPiQ/PPxagm7xUAYzN2Z4/IaQCndKh2klG5l7GfC4XBU8Pan4qrq808+DJPE/bL2I/ZGXRee1QSzJJW0x0VgUiE+LheBkXHcZ+vZBbGkQ7KXjCS4PGNmEzM2sXED26IgTrmIahLoMguKg8bnl7mOlAShdL+8tgUAmgeJLZri2q74TbQXg1v6eUMmMNHGWZJFOEFRroxTDENxOJxIWPUuQzwU1oy3/ifPDurJYaclzTm5EUaB+Kx5ny1SiDJnYf1qheWBnfAUNdHGJ8p3BWqd9C55urTOw7YQvQrZbixREqHUwCwG9G75HPNcjH5hMcZu4kk4QdlICLmaUvpv4SAh5CoAmxI3rejgMRROOqLz+eFNwV3l2rfUZSKlO4N2seMT1aPkypWoO/iSanE8wyVJqzP2sGt8PMb0SQ9PBuEE5SYAbxBCFqBPQKoQyHGIvoImQfAYCicdKdstLujbN4ntEjoSiUd2lJBBB/r2v/FFU1uTAEtD9aURZYPE3jnbWQH7JNOvoFBK6wFMJ4T8DECwN8a7lNKPEz4zDidL0Xp88KWgsDHSu3fip6Jq7Xgv/oA8ZlE3MQ9+g7prqP4cIxAJnZfdKFNGb2ZV1NdmjWsJnn+lbwuoX5z33/DnB6D1UTy78jJVxyYatb28PgHwSdgDORxOWIZuF9ed1A2zyxZqpcWfNa52oS+uZdelNI6ywc+4m5dmKBmd4iK95gGR1UmEjUMAGLy5RTYmdS8FGbGtSTbmZXwOqkUiAsxOcWaVNGEhiN7tx3//J1/s1YhFbp4JHW3s3SrTldTsZM/hcEIMYmQWKfneNX75wqhVCDA3lKuLtg/Yyc5s8hj7Xx5YdRIAcNBWyBQopQyqhKHWikhTHn5mvmzsl+f/V7YHTYo8dEy4oHA4CYYgGfXkctRYBIlgyDZ265WoYhoxkE71GfGC1cs3ATsuRE1WCQrP8uKkI9K0VXeSMn+kFoTTqrxrZdaQqqC6wnXteakPlCeTrBIUnuXF4WQYagQgAteVMH2X1f49asLMU0OBZ99IfGCcFVfJTSPRyipB4XCOSNTelccaU0hE8Z6n/2p8ALB2sTv2+rXRz4UQtqtIaVxDkRa+JVZcJZ3ggsLhJBvpwh7jQq3zsbOYpIuz1cHe0s8p3aVKAWnltp8gvSLC/fD8awvCH9QPalN4j3S4oHA4SUZNyqlihXUaZS4pCRkrdTfbSSe3UyrhgsLhJBi73YT29vjUE1gY7p+Ys6cURCrdGxGmmmdXxrbbaDbCBYXDSTD/eupC0WM17hNplXpUqHSl5XSwXWFSYu5LFW/rKoVtUjhsskpQeNowJ1uwMXYZBJQrsllIYx7JrgORwhKuWESK1Y3Xz4hNpUOPKynpnq0VLVklKDxtmMPhBCEU+O/rsQXjE0W6Z2tFC3eQcjic+MJoD6OaNEjN5URPVlkoHE5GEmssIM1iCdIstkhg7SuSThtIcfqHCwqHk2JYVdaR1D1ovRT//Z/ctXP5Bc/HPDcOJxK49HM4nNQRbxeX4HxHWh+tdIBbKBxOkpFm+CQtuyfOrjWlNiWRoHf7RfUcsVakJ6unFocNFxQOJ8mkKsMnVteY0mZRUnibkiMX7vLicDicMEityGyoGUkE3ELhcDicMGRr3Ui8SXsLhRBiJYQ8Swj5NyEkPauUOJxkwQhaKAWfpeM8SM1JNCmxUAghTwM4G0ADpXS8YHwOgH8C0AJ4klL6NwAXAHiNUvo2IeQVAC+kYs4cTjoQSdD5kafnqTrOnmdCe1t8mlcmhDSrs+EokyqX1zMAHgHwXHCAEKIF8C8ApwGoAbCBEPIWgMEAtvYeJq964nA4MaEkPOlSx6L1UTy7Ui6iPPiffqTE5UUpXQugRTI8BcAeSuk+SqkbwMsAzkVAXAb3HpP2LjoOh8M5UkmnBboMQLXgcU3v2P8AXEgIeQzA20ovJoQsJoRsJIRsbGxsTOxMORwOhyMj7bO8KKUOAFeqOG45gOUAUFVVxTvMcTgxIo2t8KA+JxzpJCiHAJQLHg/uHVMN3w+Fw4kfaoP6HE6QdHJ5bQAwkhAynBBiAHAJgLciOQGl9G1K6WK73Z6QCXI4HA5HmZQICiHkJQBfAagkhNQQQhZRSr0AlgB4H8AOACsopT9EeN65hJDl7e3t8Z80h8PhcPolJS4vSumlCuOrAKyK4bx8x0YOh8NJEenk8ooZbqFwsgWlXlG8h1QfrM+Cfz6pJZ2C8jHDLRROtsB7R4WHf0bpR1ZZKBwOh8NJHVklKNzlxeFwOKkjqwSFpw1zOJkFj3lkF1kVQ+FwOOmNcLtfTvaRVRYKh8PhcFJHVgkKj6FwOBxO6sgqQeExFA4n9fAamiMXHkPhcDhxhdeHHLlklYXC4XA4nNSRVYLCYygcDoeTOrJKUHgMhcPhcFJHVgkKh8PhcFIHFxQOh8PhxAUuKBwOh8OJC1klKDwoz+FwOKkjqwSFB+U5HA4ndWSVoHA4HA4ndXBB4XA4HE5c4ILC4XA4nLjABYXD4XA4cYELCofD4XDiAhcUDofD4cSFrBIUXofC4XA4qSOrBIXXoXA4/7+9+4+Ro6zjOP7+UKQlNQEjBhU0talSxT9KNVBzRqpC1UiooQ0iCCkSCBr4R0yEaEIMMdUYYyRVCQpFEA9oRTwRQio/gsES+gPF4gliJbYSUgqNCaRiqF//mOecZbvb3bl75uZ27/NKNt15nmdmvvvN9L43M3vPmDVnqAqKmZk1xwXFzMyycEExM7MsXFDMzCwLFxQzM8vCBcXMzLJwQTEzsyxmfEGRtFDSDZI2Nh2LmZl1V2tBkXSjpD2SdrS1f1LSU5KekXTlobYRETsj4qI64zQzs6k7vObt3wSsA26eaJA0B/gBcDqwG9giaQyYA6xtW/8LEbGn5hjNzCyDWgtKRDwsaUFb88nAMxGxE0DSbcDKiFgLnFFnPGZmVp+6z1A6OQ7Y1bK8Gzil22BJbwa+CZwk6apUeDqNuwS4JC2+2n6ZbYqOAqrMONlrfLf+fturLB8D7O0RbxXORe8YJzveuejSf7Mu6LVelc/e3tdkLvoZW+dx0fr+hF7B9hQRtb6ABcCOluXVwE9als8H1mXe59bM27s+5/hu/f22V1l2LpwL5+Kgz97e11gu+hk7XbnIkYcmvuX1T+AdLcvHp7aZ7NeZx3fr77e96nJOzsXkt+1c9D++zlzUmYeq2+9n7MDkQqky1SbdQ7k7It6flg8HngY+TlFItgDnRsSTGfe5NSI+mGt7g8y5KDkXJeei5FwUcuSh7q8NjwKbgRMk7ZZ0UUS8BlwG3AeMA3fkLCbJ9Zm3N8ici5JzUXIuSs5FYcp5qP0MxczMZocZ/5fyZmY2GFxQzMwsCxcUMzPLYugLiqT5kn4q6ceSzms6niZ5os2SpM+kY+J2SSuajqdJkt4r6TpJGyV9sel4mpZ+ZmyVNKtn7pC0XNLv0rGxvJ91BrKgVJx08ixgY0RcDJw57cHWrEouYsgn2qyYi7vSMXEp8Nkm4q1TxVyMR8SlwNnASBPx1mkSk9R+FbhjeqOcHhVzEcDLwDyKGU16y/kXotP1Aj4CLOX1f4E/B/gbsBA4Avgj8D7gKmBJGvPzpmNvMhct/RubjnsG5eK7wNKmY286FxS/bN1L8TdhjcffVC4oJq09B1gDnNF07A3n4rDUfyxwaz/bH8gzlIh4GHiprfn/k05GxH+A24CVFJX1+DRmID/voVTMxVCrkgsVvg3cGxHbpzvWulU9LiJiLCI+BQzdZeGKuVgOLAPOBS6WNFQ/M6rkIiL+m/r3AXP72X4Tk0PWpdukk9cC6yR9mvqnXJgpOuai34k2h0y34+Jy4DTgKEmLIuK6JoKbZt2Oi+UUl4bnAvc0EFcTOuYiIi4DkLQG2NvyQ3WYdTsuzgI+ARxN8RiSnoapoHQUEa8AFzYdx0wQES9S3DOY9SLiWopfNma9iHgIeKjhMGaUiLip6RiaFhF3AndWWWeYTucGcdLJujgXJeei5FyUnItStlwMU0HZArxb0rskHUFxY22s4Zia4lyUnIuSc1FyLkrZcjGQBaXBSSdnHOei5FyUnIuSc1GqOxeeHNLMzLIYyDMUMzObeVxQzMwsCxcUMzPLwgXFzMyycEExM7MsXFDMzCwLFxSb1SQdkPSHlteVvdeaHun5JAsP0X+1pLVtbUskjaf3v5X0prrjNJvggmKz3f6IWNLy+tZUNyhpynPkSToRmBMROw8xbJSDn+VyTmoHuAX40lRjMeuXC4pZB5KelfQNSdsl/UnS4tQ+Pz2k6DFJj0tamdrXSBqT9ABwv6TDJP1Q0l8kbZJ0j6TVkj4m6a6W/Zwu6ZcdQjgP+FXLuBWSNqd4Nkh6Y0Q8DeyTdErLemdTFpQx4HN5M2PWnQuKzXZHtl3yav2Nf29ELAV+BHwltX0NeCAiTgY+CnxH0vzUtxRYHRGnUkwHv4DiQUXnAx9KYx4EFkt6S1q+ELixQ1wjwDYASccAXwdOS/FsBb6cxo1SnJUgaRnwUkT8FSAi9gFz02MLzGo39NPXm/WwPyKWdOmbmLp7G0WBAFgBnClposDMA96Z3m+KiImHF30Y2JCep/G8pAcBIiIk3QJ8XtJ6ikJzQYd9vw14Ib1fRlGYHpEExVP1Nqe+24HfS7qC11/umrAHeDvwYpfPaJaNC4pZd6+mfw9Q/l8RsCoinmodmC47vdLndtdTPOzt3xRF57UOY/ZTFKuJfW6KiIMuX0XELkl/B04FVlGeCU2Yl7ZlVjtf8jKr5j7gcqVTBUkndRn3CLAq3Us5luLRsgBExHPAcxSXsdZ3WX8cWJTePwqMSFqU9jlf0ntaxo4C3wN2RsTuicYU41uBZ6t8QLPJckGx2a79Hkqvb3ldA7wBeELSk2m5k19QPEr1z8DPgO3Av1r6bwV2RcR4l/V/QypCEfECsAYYlfQExeWuxS1jNwAncvDlrg8Aj3Y5AzLLztPXm9UkfRPr5XRT/DFgJCKeT33rgMcj4oYu6x5JcQN/JCIOTHL/3wfGIuL+yX0Cs2p8D8WsPndLOpriJvo1LcVkG8X9liu6rRgR+yVdDRwH/GOS+9/hYmLTyWcoZmaWhe+hmJlZFi4oZmaWhQuKmZll4YJiZmZZuKCYmVkWLihmZpbF/wDNo3Ic5jzz+gAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig = plt.figure()\n", - "ax = fig.add_subplot(111)\n", - "cm = matplotlib.cm.Spectral_r\n", - "\n", - "# Determine size of probability tables\n", - "urr = gd157.urr['294K']\n", - "n_energy = urr.table.shape[0]\n", - "n_band = urr.table.shape[2]\n", - "\n", - "for i in range(n_energy):\n", - " # Get bounds on energy\n", - " if i > 0:\n", - " e_left = urr.energy[i] - 0.5*(urr.energy[i] - urr.energy[i-1])\n", - " else:\n", - " e_left = urr.energy[i] - 0.5*(urr.energy[i+1] - urr.energy[i])\n", - "\n", - " if i < n_energy - 1:\n", - " e_right = urr.energy[i] + 0.5*(urr.energy[i+1] - urr.energy[i])\n", - " else:\n", - " e_right = urr.energy[i] + 0.5*(urr.energy[i] - urr.energy[i-1])\n", - " \n", - " for j in range(n_band):\n", - " # Determine maximum probability for a single band\n", - " max_prob = np.diff(urr.table[i,0,:]).max()\n", - " \n", - " # Determine bottom of band\n", - " if j > 0:\n", - " xs_bottom = urr.table[i,1,j] - 0.5*(urr.table[i,1,j] - urr.table[i,1,j-1])\n", - " value = (urr.table[i,0,j] - urr.table[i,0,j-1])/max_prob\n", - " else:\n", - " xs_bottom = urr.table[i,1,j] - 0.5*(urr.table[i,1,j+1] - urr.table[i,1,j])\n", - " value = urr.table[i,0,j]/max_prob\n", - "\n", - " # Determine top of band\n", - " if j < n_band - 1:\n", - " xs_top = urr.table[i,1,j] + 0.5*(urr.table[i,1,j+1] - urr.table[i,1,j])\n", - " else:\n", - " xs_top = urr.table[i,1,j] + 0.5*(urr.table[i,1,j] - urr.table[i,1,j-1])\n", - " \n", - " # Draw rectangle with appropriate color\n", - " ax.add_patch(Rectangle((e_left, xs_bottom), e_right - e_left, xs_top - xs_bottom,\n", - " color=cm(value)))\n", - "\n", - "# Overlay total cross section\n", - "ax.plot(gd157.energy['294K'], total.xs['294K'](gd157.energy['294K']), 'k')\n", - "\n", - "# Make plot pretty and labeled\n", - "ax.set_xlim(1.0, 1.0e5)\n", - "ax.set_ylim(1e-1, 1e4)\n", - "ax.set_xscale('log')\n", - "ax.set_yscale('log')\n", - "ax.set_xlabel('Energy (eV)')\n", - "ax.set_ylabel('Cross section(b)')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting HDF5 data\n", - "\n", - "If you have an instance `IncidentNeutron` that was created from ACE or HDF5 data, you can easily write it to disk using the `export_to_hdf5()` method. This can be used to convert ACE to HDF5 or to take an existing data set and actually modify cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "gd157.export_to_hdf5('gd157.h5', 'w')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With few exceptions, the HDF5 file encodes the same data as the ACE file." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157_reconstructed = openmc.data.IncidentNeutron.from_hdf5('gd157.h5')\n", - "np.all(gd157[16].xs['294K'].y == gd157_reconstructed[16].xs['294K'].y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And one of the best parts of using HDF5 is that it is a widely used format with lots of third-party support. You can use `h5py`, for example, to inspect the data." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "reaction_002, (n,elastic)\n", - "reaction_016, (n,2n)\n", - "reaction_017, (n,3n)\n", - "reaction_022, (n,na)\n", - "reaction_024, (n,2na)\n", - "reaction_028, (n,np)\n", - "reaction_041, (n,2np)\n", - "reaction_051, (n,n1)\n", - "reaction_052, (n,n2)\n", - "reaction_053, (n,n3)\n" - ] - } - ], - "source": [ - "h5file = h5py.File('gd157.h5', 'r')\n", - "main_group = h5file['Gd157/reactions']\n", - "for name, obj in sorted(list(main_group.items()))[:10]:\n", - " if 'reaction_' in name:\n", - " print('{}, {}'.format(name, obj.attrs['label'].decode()))" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[,\n", - " ,\n", - " ]\n" - ] - } - ], - "source": [ - "n2n_group = main_group['reaction_016']\n", - "pprint(list(n2n_group.values()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So we see that the hierarchy of data within the HDF5 mirrors the hierarchy of Python objects that we manipulated before." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0.000000e+00, 3.026796e-13, 1.291101e-02, 6.511110e-02,\n", - " 3.926270e-01, 5.752268e-01, 6.969600e-01, 7.399378e-01,\n", - " 9.635450e-01, 1.142130e+00, 1.308020e+00, 1.463500e+00,\n", - " 1.557600e+00, 1.640550e+00, 1.688960e+00, 1.711400e+00,\n", - " 1.739450e+00, 1.782070e+00, 1.816650e+00, 1.845280e+00,\n", - " 1.865409e+00, 1.867240e+00, 1.881558e+00, 1.881560e+00,\n", - " 1.881800e+00, 1.894470e+00, 1.869570e+00, 1.821200e+00,\n", - " 1.716000e+00, 1.600540e+00, 1.431620e+00, 1.283460e+00,\n", - " 1.101660e+00, 1.065300e+00, 9.307300e-01, 8.029800e-01,\n", - " 7.777400e-01])" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n2n_group['294K/xs'][()]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Working with ENDF files\n", - "\n", - "In addition to being able to load ACE and HDF5 data, we can also load ENDF data directly into an `IncidentNeutron` instance using the `from_endf()` factory method. Let's download the ENDF/B-VII.1 evaluation for $^{157}$Gd and load it in:" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Download ENDF file\n", - "url = 'https://t2.lanl.gov/nis/data/data/ENDFB-VII.1-neutron/Gd/157'\n", - "filename, headers = urllib.request.urlretrieve(url, 'gd157.endf')\n", - "\n", - "# Load into memory\n", - "gd157_endf = openmc.data.IncidentNeutron.from_endf(filename)\n", - "gd157_endf" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Just as before, we can get a reaction by indexing the object directly:" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "elastic = gd157_endf[2]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, if we look at the cross section now, we see that it isn't represented as tabulated data anymore." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'0K': }" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "elastic.xs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If had [Cython](http://cython.org/) installed when you built/installed OpenMC, you should be able to evaluate resonant cross sections from ENDF data directly, i.e., OpenMC will reconstruct resonances behind the scenes for you." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "998.7871174521487" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "elastic.xs['0K'](0.0253)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When data is loaded from an ENDF file, there is also a special `resonances` attribute that contains resolved and unresolved resonance region data (from MF=2 in an ENDF file)." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ]" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157_endf.resonances.ranges" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that $^{157}$Gd has a resolved resonance region represented in the Reich-Moore format as well as an unresolved resonance region. We can look at the min/max energy of each region by doing the following:" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[(1e-05, 306.6), (306.6, 54881.1)]" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[(r.energy_min, r.energy_max) for r in gd157_endf.resonances.ranges]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With knowledge of the energy bounds, let's create an array of energies over the entire resolved resonance range and plot the elastic scattering cross section." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Cross section (b)')" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Create log-spaced array of energies\n", - "resolved = gd157_endf.resonances.resolved\n", - "energies = np.logspace(np.log10(resolved.energy_min),\n", - " np.log10(resolved.energy_max), 1000)\n", - "\n", - "# Evaluate elastic scattering xs at energies\n", - "xs = elastic.xs['0K'](energies)\n", - "\n", - "# Plot cross section vs energies\n", - "plt.loglog(energies, xs)\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Cross section (b)')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Resonance ranges also have a useful `parameters` attribute that shows the energies and widths for resonances." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energyLJneutronWidthcaptureWidthfissionWidthAfissionWidthB
00.031402.00.0004740.10720.00.0
12.825002.00.0003450.09700.00.0
216.240001.00.0004000.09100.00.0
316.770002.00.0128000.08050.00.0
420.560002.00.0113600.08800.00.0
521.650002.00.0003760.11400.00.0
623.330001.00.0008130.12100.00.0
725.400002.00.0018400.08500.00.0
840.170001.00.0013070.11000.00.0
944.220002.00.0089600.09600.00.0
\n", - "
" - ], - "text/plain": [ - " energy L J neutronWidth captureWidth fissionWidthA fissionWidthB\n", - "0 0.0314 0 2.0 0.000474 0.1072 0.0 0.0\n", - "1 2.8250 0 2.0 0.000345 0.0970 0.0 0.0\n", - "2 16.2400 0 1.0 0.000400 0.0910 0.0 0.0\n", - "3 16.7700 0 2.0 0.012800 0.0805 0.0 0.0\n", - "4 20.5600 0 2.0 0.011360 0.0880 0.0 0.0\n", - "5 21.6500 0 2.0 0.000376 0.1140 0.0 0.0\n", - "6 23.3300 0 1.0 0.000813 0.1210 0.0 0.0\n", - "7 25.4000 0 2.0 0.001840 0.0850 0.0 0.0\n", - "8 40.1700 0 1.0 0.001307 0.1100 0.0 0.0\n", - "9 44.2200 0 2.0 0.008960 0.0960 0.0 0.0" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "resolved.parameters.head(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Heavy-nuclide resonance scattering\n", - "\n", - "OpenMC has two methods for accounting for resonance upscattering in heavy nuclides, DBRC and RVS. These methods rely on 0 K elastic scattering data being present. If you have an existing ACE/HDF5 dataset and you need to add 0 K elastic scattering data to it, this can be done using the `IncidentNeutron.add_elastic_0K_from_endf()` method. Let's do this with our original `gd157` object that we instantiated from an ACE file." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "gd157.add_elastic_0K_from_endf('gd157.endf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's check to make sure that we have both the room temperature elastic scattering cross section as well as a 0K cross section." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'294K': ,\n", - " '0K': }" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gd157[2].xs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generating data from NJOY\n", - "\n", - "To run OpenMC in continuous-energy mode, you generally need to have ACE files already available that can be converted to OpenMC's native HDF5 format. If you don't already have suitable ACE files or need to generate new data, both the `IncidentNeutron` and `ThermalScattering` classes include `from_njoy()` methods that will run [NJOY](https://www.njoy21.io/) to generate ACE files and then read those files to create OpenMC class instances. The `from_njoy()` methods take as input the name of an ENDF file on disk. By default, it is assumed that you have an executable named `njoy` available on your path. This can be configured with the optional `njoy_exec` argument. Additionally, if you want to show the progress of NJOY as it is running, you can pass `stdout=True`.\n", - "\n", - "Let's use `IncidentNeutron.from_njoy()` to run NJOY to create data for $^2$H using an ENDF file. We'll specify that we want data specifically at 300, 400, and 500 K." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - " njoy 2016.49 25Jan19 07/19/19 06:12:49\n", - " *****************************************************************************\n", - "\n", - " reconr... 0.0s\n", - "\n", - " broadr... 0.1s\n", - " 300.0 deg 0.1s\n", - " 400.0 deg 0.2s\n", - " 500.0 deg 0.3s\n", - "\n", - " heatr... 0.3s\n", - "\n", - " gaspr... 0.6s\n", - "\n", - " purr... 0.7s\n", - "\n", - " mat = 128 0.7s\n", - "\n", - " ---message from purr---mat 128 has no resonance parameters\n", - " copy as is to nout\n", - "\n", - " acer... 0.7s\n", - "\n", - " acer... 1.0s\n", - "\n", - " acer... 1.1s\n", - " 1.2s\n", - " *****************************************************************************\n" - ] - } - ], - "source": [ - "# Download ENDF file\n", - "url = 'https://t2.lanl.gov/nis/data/data/ENDFB-VII.1-neutron/H/2'\n", - "filename, headers = urllib.request.urlretrieve(url, 'h2.endf')\n", - "\n", - "# Run NJOY to create deuterium data\n", - "h2 = openmc.data.IncidentNeutron.from_njoy('h2.endf', temperatures=[300., 400., 500.], stdout=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can use our `h2` object just as we did before." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'300K': ,\n", - " '400K': ,\n", - " '500K': ,\n", - " '0K': }" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "h2[2].xs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that 0 K elastic scattering data is automatically added when using `from_njoy()` so that resonance elastic scattering treatments can be used." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Windowed multipole\n", - "\n", - "OpenMC can also be used with an experimental format called windowed multipole. Windowed multipole allows for analytic on-the-fly Doppler broadening of the resolved resonance range. Windowed multipole data can be downloaded with the `openmc-get-multipole-data` script. This data can be used in the transport solver, but it can also be used directly in the Python API." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [], - "source": [ - "url = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/092238.h5'\n", - "filename, headers = urllib.request.urlretrieve(url, '092238.h5')" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [], - "source": [ - "u238_multipole = openmc.data.WindowedMultipole.from_hdf5('092238.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `WindowedMultipole` object can be called with energy and temperature values. Calling the object gives a tuple of 3 cross sections: elastic scattering, radiative capture, and fission." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array(9.13284265), array(0.50530278), array(2.9316765e-06))" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "u238_multipole(1.0, 294)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "An array can be passed for the energy argument." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD8CAYAAAB5Pm/hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzt3Xl8XHW9+P/Xe/bse7okTfeFrrQNZfeiIBQVUBalghsKihe338/rxav3qle/bvdevcLVCyiIC18QFZAqiKCsUqCllC6UtmnpktA2SdPss8/n+8fMpNOQmUwyZzLJ5P18PPpI5uTMzJvJyZv3eX8+53PEGINSSqn8Zct1AEoppbJLE71SSuU5TfRKKZXnNNErpVSe00SvlFJ5ThO9UkrlOU30SimV5zTRK6VUnstKoheRIhHZJCLvycbrK6WUSp8jnZ1E5C7gPUCrMWZpwva1wI8AO/AzY8x3Yz/6Z+D+dIOorq42s2bNSnd3pZRSwMsvv9xujKkZbr+0Ej1wN/A/wC/jG0TEDvwYeCfQDGwUkYeBOuA1wJNusLNmzWLTpk3p7q6UUgoQkQPp7JdWojfGPCMiswZtXgM0GWP2xd7wPuAyoBgoAhYDXhF5xBgTSTNupZRSFku3oh9KHXAo4XEzcLox5iYAEfko0J4syYvIDcANAA0NDRmEoZRSKpWszboxxtxtjPljip/fYYxpNMY01tQM22JSSik1Spkk+hZgRsLj+ti2tInIJSJyR1dXVwZhKKWUSiWTRL8RmC8is0XEBVwNPDySFzDGrDfG3FBWVpZBGEoppVJJK9GLyL3ABmChiDSLyMeNMSHgJuAxYCdwvzFmR/ZCVUopNRrpzrpZl2T7I8Ajo31zEbkEuGTevHmjfQmllFLDyOkSCBOldfPn7Ydpau3JdRhK5SVvIEw4orc0zaacJvqJMBi7t62XT/16M199aHuuQ1Eq73T7gqz65uP8+3rt+maTVvTDeLPTC8C25vH7PyOlJqqXDxzHGwzziw1pXeCpRklXrxxGlzcIgJ5ZKmW9pqO9A9/7guEcRpLftHUzjHiiDxvN9EpZ7c0u78D3LZ3eFHuqTGjrZhid/dFELzmOQ6l81NrjH/j+aLcvh5HkN23dDKPPH8p1CErlrbYePyXu6Czv7tjZs7KeJvph+ILRNdn8oQgRbdQrZanjfQFmVRcBJ9qkynraox+GN2GAyBfSwSKlrNTjCzGjsgA40SZV1tMe/TD8CYneG9BEr5SVenxBppYWYLeJVvRZpK2bYSRW8V6d/qWUZcIRQ18gTInHQXmBUxN9FmmiH0ZiFa/zfJWyTq8vOtGhxOOgrMBJpyb6rNEe/TDig7EA/dq6Ucoy3b5oYi/1OCkrdOqsmyzSHv0wEls3gZDe+lYpq/QMqui1dZM92roZhi8YocQTnecbCGuiV8oqPbGKvsTjpMTjHEj8ynqa6IcRDEcojl3QoRW9UtaJJ/bSAgdFLjv9AU302aKJfhjBcISiWKIPhvWCKaWs0uM/UdEXuOz0+3UMLFs00Q8jGIpQ5LIDWtErZaX4rJtit4Mil4P+YBijiwdmhc66GUYgHKHQFa/oNdErZZX4dSmFLjsFLjvhiMGvxVRW6KybYQRCJ1o3WtErZR1vIPr35HHaB86a9erz7NDWzTCCYUOxO9a60YpeKct4g2FcDht2mwycNffrRYlZoYl+GImDsVrRK2UdXzBMgTNaRBXGiql+XRY8KzTRpxCJGEIRkzDrRhO9UlbxBsIUxlo28a969Xl2aKJPIRiJJvYiHYxVynL9CRV9gTP6N9anc+mzQhN9CvF58wWu6MekrRulrOMNhPHEEn2RWwdjs0kTfQrxxO6y23A5bAT0gimlLOMLhikY1Lrp00SfFTqPPoV4q8bpsOGy27SiV8pC3sTB2Fh71Kutm6zQefQpDK7otUevlHUSWzcDFb0ug5AV2rpJIZ7YXQ4bTrtoRa+UhRJbN/Gvel/m7NBEn0J8MNZpt+G0a0WvlJW8wTCFsYreZbdhE/Bpjz4rNNGnMNCjj7Vu/JrolbJMf+BERS8iFDjtel/mLNFEn0J8gSWnXXDZbQS1daOUZbzBEz16iK55o4k+OzTRpzDQox+YXqmJXikrhCOGQCgyMOsGYok+oH9j2aCJPoXE6ZXao1fKOr5Y5R6/GDH6vX1gu7KWJvoUTqro7TaCIb1gSikrxFs0iRW99uizx/JELyKniMhtIvI7EbnR6tcfS4FQwqwbHYxVyjLxpQ48gxO9zrrJirQSvYjcJSKtIrJ90Pa1IrJLRJpE5GYAY8xOY8yngPcDZ1sf8tg5MY9eB2OVspJv4O5SjoFtHpdW9NmSbkV/N7A2cYOI2IEfAxcDi4F1IrI49rNLgT8Bj1gWaQ6cPL1SdDBWKYvElyM+qUfvtGmPPkvSSvTGmGeAjkGb1wBNxph9xpgAcB9wWWz/h40xFwPXWBnsWAuETiR6HYxVyjrxyn1w60YTfXY4ht8lqTrgUMLjZuB0ETkPuBxwk6KiF5EbgBsAGhoaMggje06q6LV1o5RlhhyM1dZN1mSS6IdkjHkKeCqN/e4A7gBobGwcl9NZ4ssSuxzRwVht3ShlDd8Qg7EeHYzNmkxm3bQAMxIe18e2pW2iLFMcn16pi5opZQ3vwGDsyYneF9S/sWzIJNFvBOaLyGwRcQFXAw+P5AXG+zLFwcQlEBy2gUXOlFKZSTaPPhCOENIzZ8ulO73yXmADsFBEmkXk48aYEHAT8BiwE7jfGLNjJG8+ESp6EbDbJLpMsR6ASlkiXrl7XCcnegCfnjlbLq0evTFmXZLtj5DBFEpjzHpgfWNj4/WjfY1s8ocjOO02RASn3UY4YghHDHab5Do0pSY03xAVfTzpewNhit2WDx9OaroEQgrBkMFlj35ELkf0q06xVCpz3kA4dqacOI8+VtHrzBvL6T1jUwiGIzjt0eo9nvC1faNU5hLvFxsXf6xTLK2n94xNIRiODFTy8cpD59IrlbnBa9HDiatkdYql9bR1k0Ig1qOHxNaNzrxRKlO+QPik5Q/gxJx6bd1YT1s3KQTDJ3r08YSvc+mVypy2bsaWtm5SCITCAwk+3qvXHr1SmfMNkei1os8ebd2kEAwbnI5ognfrrBulLOMNhnFrRT9mtHWTQjChR6+tG6Ws4w1G3tq6GZhHr39jVtPWTQr+YASPI3rwDcy60YpeqYz5AslbN1rRW09bNyn4Q2HczpNn3WiPXqnMeYPhgQo+Ti+Yyh5N9Cn4gpGB3ry2bpSyzlDz6J12wW4TnUefBZroU/CHwrhjrRuXXefRK2WVoWbdiEj0BuFa0VtOB2NT8IdOVPS61o1S1vEFw3icb00/Hk30WaGDsSn4Q5GB08uBefTaulEqI8FwhGDYvKWih+gyCNqjt562blLwB8Nv7dFrRa9URgaWKHYNkej1BuFZoYk+BV8oMjDrRi+YUsoa8dbM4MHY+DYdjLWeJvokQuEI4YgZGIzVWTdKWcMXuyBqqNaN9uizQwdjk/DHEnq8kj+xDocmeqUy4Qulbt149W/McjoYm0Q80ccTfHyGgFYbSmUm3poZcjDWacenrRvLaesmCX+s6ohX9PE5vjpQpFRm+gPJe/QFLm3dZIMm+iTiLRp3wlzfAped/kAoVyEplRd6/dG/oRLPW28Arj367NBEn8SJiv5E1VHgtOvKekplqNcfBKDY/dZEr62b7NBEn4Q/ePJgLET79Nq6USozvb5oRV80RKIvdNnpC4QwRpcasZIm+iQGD8aC9g+VskKvP/o3NFTrpsTjIGJO9PGVNTTRJzF4MBbirRs9AJXKRK8/iMMmJ/1txZV4nAD0+HQszEo6jz6JgcHYhB69DhQplbleX4hijwMRecvPimNVfo8vONZh5TWdR59EvBefOOum0KXTK5XKVI8/NORALJxo5/T4taK3krZukuiLHWiJB2SB0669Q6Uy1OtLnuhLByp6TfRW0kSfRHyub+LMAB2MVSpzvSkr+niPXls3VtJEn0TvEBW9R+f4KpWxPn9ooBc/WIlW9FmhiT6JXl+IQpcdu+3EgJHe5kypzPWkaN3Et2tFby1N9EkMdXpZ4LQTihhdk16pDBzvD1BR6BryZ0UuByJa0VtNE30SQ80MKIw97tWDUKlRCUcMnd4gFYXOIX9uswklbocmeotpok9iqD6izghQKjNd3iDGQEXR0BU9RH/W0RcYw6jynyb6JIaaAlZaEK1CurV/qNSoHO+PJvDKFIm+UhO95bKS6EXkvSLyUxH5jYhcmI33yLahevSlHk30SmXieCyBJ+vRA1QWujimid5SaSd6EblLRFpFZPug7WtFZJeINInIzQDGmIeMMdcDnwI+YG3IY2OomQHxqV/dXm3dKDUaHekk+iIXHX3+sQppUhhJRX83sDZxg4jYgR8DFwOLgXUisjhhl6/Gfj7h9PpDb1lGtaxAL+ZQKhPx1k1F0dCDsQCVxdHWjS5VbJ20E70x5hmgY9DmNUCTMWafMSYA3AdcJlHfAx41xmy2LtyxEYkYenxBygfNDDjRutGKXqnRiLdkUvXoq4pcBMNG17uxUKY9+jrgUMLj5ti2zwAXAFeKyKeGeqKI3CAim0RkU1tbW4ZhWKvbFyRioHzQ6WXxQOtGK3qlRuNol48St4NC19AXTAFUFrkB6OjVPr1Vkn/aGTDG3ALcMsw+dwB3ADQ2No6rc7Tj/dFEPniur90mFOscX6VG7Ui3j6llnpT71JREE31rj59Z1UVjEVbey7SibwFmJDyuj21Ly3hdj36gjzjEgFGpx0GXVvRKjcqRbv+wiX5a7OdHun1jEdKkkGmi3wjMF5HZIuICrgYeTvfJ43U9+s5Yoh/cowcoK3TR5dVTSqVG42iXjymlqRN9/H8ER7q8YxHSpDCS6ZX3AhuAhSLSLCIfN8aEgJuAx4CdwP3GmB0jeM3xWdH3xVs3b63oq4tdtGvvUKkRC0cMbb1+pg6T6EvcDopcdg53aUVvlbR79MaYdUm2PwI8Mpo3N8asB9Y3NjZeP5rnZ0uq1k1VkYsDx/rHOiSlJrz2Xj/hiGHKMK0bEWFqmYcjmugto0sgDKGzP4hNhr5LfWWRm2O9ejGHUiMVT9zThqnoAaaVFWhFbyG9OfgQjvX5qSxyYbO99ebFVcUu+gJhvXesUiMUT9zDDcbG99GK3jp6c/AhtPX4qSkZ+mCsLo62c3QtDqVGpqUzOrg6LY1EP63MQ2uPj5De+8ES2roZQmuPn9rYXN7B4hdzaPtGqZE51NFPsduR8qrYuOnlBUQMHO3RvzMraOtmCK3dyRN9lVb0So3KgWN9NFQWIvLWluhgMysLo89p78t2WJOCtm4GiUQM7b3+gavzBqseqOg10Ss1Egc6+plZVZjWvjNjV8Tu1xlultDWzSDH+wOEIiZ56yZe0WvrRqm0RSKG5g4vDZXpJfpppR5cDhv7j2lFbwVt3QzSGusJJhuMLXLZcTts2rpRagSOdPsIhCM0pFnR22zCzMpC9mvrxhLauhkknuhrS4eu6EWE2lI3R3UdDqXSFr/IMN2KHmBWdZFW9BbR1s0gbfFEn6R1AzCtVC/mUGokmtp6AZhbU5z2c2ZVFXLgWD+RyLha3HZC0kQ/SLxSTzYYC3oxh1IjtedoD8VuR1pz6ONmVRfhD0V0FUsLaKIfpKXTS0WhM+WNEabFEr3e6kyp9Ow52su82uK0plbGzaqKzbzRPn3GdDB2kJbjXuoqClLuM7XMQyAcGbjRsVIqtT2tPSyYkn7bBk60efa09mYjpElFB2MHaen0Ul+eesAofvqpfXqlhtfRF6C9N8CCKSUjet6UUjdlBU5eP9KTpcgmD23dJDDGpFnRR3+ufXqlhrf7aDRRz6sdWUUvIiyaWsKuI93ZCGtS0USfoKMvgDcYpq48daI/UdHrHXCUGk689TLSih6IJfoenXmTIU30CeKr69UPU9FXF7tx2W00d2qiV2o4r73ZTYlnZDNu4hZOLaUvEB7421Sjo4OxCVqORw+m4Vo3dptQX1HAQV2HQ6lhbW/pYnl92Yhm3MQtmhY9C9A+fWZ0MDZBfAGlGWlcvTezqlAXXFJqGP5QmNePdLO0bnR/4/F2z87D2qfPhLZuEuxr66WmxE2pxznsvjOrijh4rE/n0iuVwu4jvQTDhuV15aN6frHbwZzqIrY2j4+z/olKE32Cfe19zIktjzqchspC+gJhXdxMqRS2tnQCsLx+9Gftp84oZ8uhTi2qMqCJPsEb7X3MSXMtjlnVsRsj6KJLSiW1vaWLsgLnsBMcUlkxo5z2Xj9v6nTmUdNEH9PZH6CjL8DcmnQr+uh+B7RPr1RSmw90jnogNu7UGdG2z5aDnVaFNelooo/Z2xatzGen2bqZUVmAiCZ6pZLp7A+w62gPa2ZVZvQ6p0wrxeWwseXQcYsim3w00cfsiy2jmm7rxu2wM72sQFs3SiWxaX80MZ82O7NE73LYWDK9lC2HtKIfLZ1HH7OvvQ+nXZgxgl7i7OqigTMBpdTJNu7vwGmXgdZLJk6dUc62li6C4YgFkU0+Oo8+ZveRHmZXF+Gwp/+RLJhSwp5WvTxbqaG8tL+D5fXleJz2jF9r9cwKfMEI21pyXxRORNq6idl5uJvF00pH9JwFU4rxBSMcOq59eqUSeQNhtjV3cVqG/fm4M+ZUAbBh7zFLXm+y0URPdNDozS4fp4w00U+NXrW3+6iul61Uos0HjxOKGNbMrrDk9aqL3SycUsIL+zTRj4YmeuC12OXVi6ePLNHPjy27Gl+GVSkV9czuNpx24fTZVZa95plzq9i4vwN/KGzZa04WmuiJrq4HjLiiL/E4qSsv0ESv1CBP727jtFmVFLmT35JzpM6cW4UvGOHVQ9qnHylN9EQr+toSN9XFyW8InsyCKcXs0pX1lBpwpMvH60d6+IcFNZa+7hmzqxCB5/e2W/q6k4EmeqIV/Uir+biFU0vZ29arp5NKxTyzuw2Af1hobaIvK3SyvL6cp2Ovr9I36RN9rz/E7qM9o57ru6yujGDYaFWvVMxTu1uZUhodPLXa+Ytq2XKok/Zev+Wvnc8mfaLf2txJxMDKhtEl+viqfDq/VynwBcM8vauNty+szWh9m2TesagWY+CpXVrVj4TliV5E5ojInSLyO6tfOxteiS2UtHLG6KaB1VcUUF7oZJuul60Uz+1ppy8QZu3SqVl5/SXTS5lS6uZvrx/Nyuvnq7QSvYjcJSKtIrJ90Pa1IrJLRJpE5GYAY8w+Y8zHsxFsNrxy8Dhza4ooKxz+ZiNDERGW1ZXpjRGUAh7dfoQSj4Oz5lZn5fVFhHcsquWZ3e0EQrocQrrSrejvBtYmbhARO/Bj4GJgMbBORBZbGl2WGWN45WAnKxsyu6hjWV0Zu4/24AvqgKyavILhCE/sPMo7T5mCy5G9rvAFp0yh1x/i7006+yZdaf02jDHPAB2DNq8BmmIVfAC4D7jM4viyam9bH8f6AqyemVmiXzGjnFDEsONNrerV5PX83mN0eYNZa9vEnTO/mlKPg/Vb38zq++STTP63WwccSnjcDNSJSJWI3AasFJEvJ3uyiNwgIptEZFNbW24GVuLzcc+am9nVe42x/1G89Iaul60mrwc2N1PqcfA2i+fPD+Z22LloyVT+suOonkWnyfLzK2PMMWPMp4wxc40x30mx3x3GmEZjTGNNTXYPjGSebzpGXXkBDZWFGb1OVbGbuTVFbNw/+KRHqcmhxxfksR1HuGTFdEtWqxzOe1ZMp9cf0jn1acok0bcAMxIe18e2pS2X69FHIoYN+45x1twqS6aBrZldyab9HbpksZqUHt12BF8wwhWr68fk/c6aW0VFoZM/bj08Ju830WWS6DcC80Vktoi4gKuBh0fyArlcj/61w910eYOcNc+aRZcaZ1bS7QuxS9e9UZPQ7zY3M6e6iJUW3GQkHU67jYuXTeOJ147S4wuOyXtOZOlOr7wX2AAsFJFmEfm4MSYE3AQ8BuwE7jfG7BjJm+eyoj/Rn7dmGtia2O3StH2jJpv97X289EYHl6+qy8pFUslctboebzDM+le1qh9OurNu1hljphljnMaYemPMnbHtjxhjFsT68f9npG+ey4r+ydfbWDClmCmlHkter76igGllHl7cp4leTS6/fuEADptwVeOM4Xe20Kkzylk4pYTfbDo0/M6T3KS8Z2xXf5CX9ndwwSlTLHtNEeGsudU819ROWPv0apLwBsLcv+kQFy2dalnRlC4R4f2nzeDVQ53sjN1TQg1tUt4z9qndrYQjhvMtTPQQXa2vyxtka7PerV5NDn/Y0kK3L8RHzpyVk/d/38o6XHYbv9moVX0qk3JRs7/ubKW62GXJ3ekTnTuvGhF4Zrdesafyky8Y5g9bWujsDxCOGO54dh+nTCvltFnW3DJwpCqLXKxdOpXfv9xMrz+UkxgmgknXugmGIzy5q5W3L6zFbrN24KiiyMXyujKe2aNze1V++v6fd/G5+7Zw/S838dArLexr6+Mz75g3poOwg113zmx6/CF+q736pCZd6+a5Pe30+EJcuCQ7l2m/bUENrxw8Tle/TvlS+cUYwx+2RC+V2bj/OP//b19laV0pa7P0t5SuU2eUs3pmBXf9/Q0dH0ti0rVuHn71zdhl2tlZXe+8hbVETHQcYLzbc7SHlw/oLCGVnv3H+jnWF+A7ly/js+fPZ83sSm5dtwqbxWfGo/Hxc2ZzqMPL46/p8sVDse7OvROANxDmL7HLtN2O7FymvXJGObUlbh7bcYTLTq3LyntY5Z0/fAaA/d99d44jURPB5gPRtZxWNpSzburobr2ZLRcunkJ9RQF3Prcv64uqTUSTqkf/19eP0hcIc+mK6Vl7D5tNuHDJFJ58vW1cL7jUHzgxcKXreqt0vNrcSZHLzvxa628RmCmH3cYnzpnNxv3H2bD3WK7DGXcmVY/+wc0t1Ja4OX2ONcseJHPRkql4g+GBmySPR+09gYHv3+z05jASNVFsbe5iSV2Z5ZMYrHL1mgZqS9z89xO7cx3KuDNpevRvdnp5clcrVzXWZ/1APWNOFaUeB3/efiSr75OJ1h7fwPddXh04VqkFwxF2Hu5med3YX8WeLo/TzqfPm8uLb3RoVT/IpEn09286hAGuPq0h6+/ltNu4eOk0/rzjCH3jdG5vZ8KsIE30ajh7jvbiD0VYVj9+Ez2cqOp/+MRujNEZOHGTokcfjhh+s/EQ586vYUaGa8+n66rGevoDYf60bXwuuJR4cUm3rv6nhhG/2nvpOK7oIVrV/+Pb5/HSGx08tWv8tk7H2qTo0T+1q5XDXT4+uGbsFl1aPbOCOdVF/G5T85i950j0JCR6rejVcJ7Z00ZtiZvZVUW5DmVY69Y0MLu6iG/96TWCYZ1oAJOkdfOzZ99gaqnH8rVtUhGJrub30v4OmlrH3xr1vb4Tib7HNz7bS2p88AXDPLO7nfNPqR0Xc+aH43LY+PLFi9jb1sd9Lx3MdTjjQt4n+m3NXWzYd4zrzpmF0z62/7nvb6zHZbfxqw0HxvR909HrDxK/an08TwNVufeHLS30+kNcsjx705Kt9s7FUzhjTiU/fGKPnrEyCRL9Hc/uo8TtYN2a7A/CDlZV7Obdy6fx+80t425QttcXosTtwO2w4Q1ooldD8wXD3PLXJpZML+XMudmdlmwlEeGr717M8f4AP3xcp1vmdaI/1NHPI9sO88HTGyjxOHMSwzWnN9DrD427QVlvMEyhy0GBy45XK3qVxE+ebKKl08tX3704pwuXjcbSujKuPX0mv9iwny2HJvfS4Xk96+aWv+7BbhM+dvbsrLx+OlbPrGBOTRH3j7P1sr3BCAUuOwVOu1b0akjbW7r4yVN7ee+p0ydUNZ/on9YupLbEzZcf2DapB2bzdtbNvrZefr+5mQ+dMZOpZWN755tEIsL7G2ew6cBxmlp7cxbHYN5AGI/TToHLTr9W9GoQfyjM/3f/FiqLXHzj0qW5DmfUSj1OvnHpUnYe7ubO597IdTg5k7etmx8+sQe3w86N583NdShcvqoOu024fxytl+0Lhilw2ihw2vFpRa8G+cHju9l9tJfvXbGcssLctD2tsnbpVC5cPIUfPr6bPUfH3wy4sZCXiX5bcxd/3PomHzt7FtXF7lyHQ22Jh7VLpnLvSwfpGScXJ/mCsYreqT16dbInX2/l9qf3sW5NA29fVJvrcCzxf963jGK3g8/dt2VSLuKXd4neGMPXHt5OVZGLT42Daj7uU/8wlx5fiF+/MD7m9XqDYQpirRtN9CqupdPLF+7fwinTSvnaJYtzHY5lakrcfPeK5bx2uJsfTMJZOHmX6B/a0sLmg518ae0iSnM002Yoy+rLOHd+NXc+98a4mLfuDYbx6GCsShAIRfjM/91MKGz4yTWr8Dizc8+GXHnn4imsW9PA7c/s5fmmyXVf57xK9L3+EN955HVW1Jdx5ar6XIfzFjeeN5f2Xv+4uLelL6AVvTrBGMNXHtzG5oOdfO+K5cyuHv9LHYzGv77nFObWFPOZe1/hcNfkWZ47rxL9dx/dSVuvn69fumRcXqp95pwqTptVwS1/a8p5Fe0LRfDEBmNzHYvKvZ8+u4/fvtzMZ8+fz7uXT8t1OFlT6HJw27Wr8QXDfPqezZOmX5838+if39vOr184yHVnz2ZlQ4UF0VlPRPjS2kW09fj5+fO5nerljVX0Hh2MnfQef+0o33n0dd69bBqfP39+rsPJunm1xfzHVSt45WAn3/zja7kOZ0zkxTz6/kCIm3+/jVlVhXzxwoUWRZcdp82q5PxFtdz21F66+nMzA8cYMzAYW+jSin4ye/lAB5+99xWW1ZXxn1etGJdnwtnwrmXTuP7c2fzqhQP8+oXxtxaV1fKidfONh1/j0PF+vnfFcgpc438A6YsXLaTHH+LHTzXl5P39sdPV+GBsKGIm9VWDk9XOw9187OcbmVLq5s6PnDYh/nas9M9rF/GORbX82x+28+Su1lyHk1UTPtE/9EoLv9l0iE+fNzfr94K1yinTSrlyVT13PfdGTpYwjs/68TjsA3/c/VrVTyr72/v40J0vUehy8OtPnE5NSe6vNxlrDruNW9et5JRppdx0z2Zee7M71yFlzYRO9G+2ERL3AAAUnUlEQVS09/GVB7fROLOCL1ywINfhjMg/X7yIApedrz28Y8xveRbvyRe47ANT6Pzap580DnX0c83PXiQcifDrT6yhvmJs7ro2HhW5Hdz10dMoLXDy0Z+/xP72vlyHlBUTOtE/+EoLToeNW9atxDHGa81nqrrYzRcvXMjfm47xyLaxvYl4vCdfELsyFtAB2UnijfY+3n/7Bnr9IX553enMqy3JdUg5N6XUwy+vW0MwHOGan71I8/H+XIdkuYmVHQf5wgXz+dNnz2V6eUGuQxmVa05vYPG0Ur6xfseYDszGk7rHaRto3Wiiz39NrT28//YN+EMR7r3+jHF/o++xNH9KCb/6+Ol0+4Jc+7MXae325TokS03oRC8i1E3QJA/RHuH3r1zOsb4A31i/Y8zed6CidzlOVPSj6NF39AV4cd8xS2NT2bHlUCcfuP0FAH5zwxksnl6a44jGn6V1ZfziujW09fhZ99MXONKVP8l+Qif6fLC0rox/fPs8Hnilhb/sGJsWTnzgtTChRz+aiv6//rKLD9zxAq8cPG5pfMpaj792lKvv2ECR28H9nzyT+VO0XZPMqoYKfv6xNRzt9nPV7c9z8Fh+tHE00Y8DN719HqdMK+VfHtzOsV5/1t+vP7FHH2vdjGb9nQ17o9X8a4fzd7bCRPerDfv55K82sXBKCQ98+qy8XdrASmtmV/J/rz+dHl+IK297nt15sLSx5YleRIpE5Bci8lMRucbq189HLoeNH7x/Bd2+IF+4/1UikezOwvEGo/evLXSdGIz1BUc+jz4cmy2UL1VPPgmGI3z94R386x928I5Ftdx7wxnjYsnuiWJ5fTn3f/JMAK66bcNAUTNRpZXoReQuEWkVke2Dtq8VkV0i0iQiN8c2Xw78zhhzPXCpxfHmrfiysM/sbuMnWb6QKl7RF7kz69F3e6MDyG1jcBai0tfa4+Oan77I3c/v5+PnzOa2a1dT6HLkOqwJZ8GUEn5/41nUlLj58F0vjqsbB41UuhX93cDaxA0iYgd+DFwMLAbWichioB6IfyI6lWMEPrimgctOnc4PHt/N83uzt4zqicFYOx5n9BAYaY/eGEO3L3pmEE/4Kvc2HzzOJbc+x9aWTn509an863sWT7ipx+PJjMpCfn/jWZwxp4ov/W4r33309ayfcWdDWkeAMeYZoGPQ5jVAkzFmnzEmANwHXAY0E032KV9fRG4QkU0isqmtrW3kkechEeHb71vG7Ooi/vGezRw4lp2LNwYGY512PKPs0ff6Q4RjB3yXJvqci0QMtz+9lw/cvgGXw8YDN57NZafW5TqsvFBW4OSuj57GNac3cNvTe/no3RvHZCzNSpn8r76OE5U7RBN8HfAAcIWI/C+wPtmTjTF3GGMajTGNNTU1GYSRX4rcDu78yGkY4Lq7N2YlifYHwrjsNhx226hbN4lxdeZocTYV1drt48N3vcR3Hn2d8xdNYf1N5+j0SYs57Ta+9d6lfPt9y3hh3zHefctzbNo/uPYdvyw/pzPG9BljPmaMudEYc0+qfa1cpjifzKou4rZrV3Owo59P3/Oy5WtmewOhgdk2TrsNh01G3LqJJ/qyAqdW9Dn02I4jrP3Rs2w60MF3Ll/G/167ivJCV67DyksiwgdPb+DBT5+F22njA3e8wC1/3UMgFMEYw2M7jvCzZ/fRHwjlOtS3yGSEpgWYkfC4PrYtbcaY9cD6xsbG6zOIIy+dMaeKb79vGf/0u618/jevcMvV1i3z0B8IU5iwUuFobhAeT+4NlYV5Mf1somnr8fP19Tv409bDLJ5Wyi3rVjKvtjjXYU0KS6aXsf4z5/CVB7fzg8d38/CrbzK11MNzsdsTbm3u4pZ1K3Mc5ckySfQbgfkiMptogr8a+KAlUSkArmqcQZc3yLf+tJMC5zb+48rllqwX3h8Mn7QkrcdlH3GPvjsh0W9r6cIXDOfdPUbHI2MMD21p4RvrX6PfH+aLFy7gk/8wF6cOuI6pUo+TW9et5LIV0/nhE7vZ19bLzRcvot8f4pa/NbFuTQNnzh0/q+mmlehF5F7gPKBaRJqBrxlj7hSRm4DHADtwlzFmRNfxi8glwCXz5s0bWdSTyCfOnUOvP8R/P7EHj9PGNy9bmnGy9w5V0Y+yRz+jMrryYbc3qIk+y5pae/jG+td4dk87KxvK+f4Vy/Uq1xy7YPEULlg8ZeCxLxjm/k3NfP+x13ngxrMQGR83ckkr0Rtj1iXZ/gjwyGjfXFs36fnc+fPxBsPc/vQ+vIEw379yeUZtnP5AiELniV99octOr3/0rZv449pSz6hjUsn1+IL86Ik93P38fgpcdr5+yWI+dOYs7JPkblATicdp5/MXzOfmB7bx25ebeX/jjOGfNAZyehWFVvTpERFuXruIYpeD/3p8Nz3+ELeuWznqCtobCJ80YFfqcdLjG9mAapc3iN0mTC/3DDxW1gqFIzywuYXvP7aLY31+PtA4gy9etFCvcB3nrlxdz0NbWvjyA9vo7A9w3dmzc34tQ17cM3YyEBE+c/58vnHpEh5/7SjX/uxF2kc5l/d4f5CKQufA4xKPgx7fyGYKdHmDlHoclBVEX2ekz1fJRSKGR7Yd5qL/foYv/X4rMyoLeOjTZ/PdK5Zrkp8AHHYbP/1wI+9YVMu3H3mdd93yLE/tah3zGwwl0hGcCeYjZ83i1nUr2dbSxWX/83d2jmJBseN9ASqKEir6Aic9/pFW9CHKCpyUxhJ99wjPCNRbGWN4alcrl/74OT59z2ZEhNuuXcUDN57FihnluQ5PjUCJx8kdH1rN7R9ajS8Y4aM/38gV//s8z+5py0nC19bNBHTJiunMrCrk+l9u4vKfPM8337uUK1fXD/9EwB8K0+MPUZnQuinxOOj2jryiLytwUuqJJXpt3YyaMYandrfxkyeb2Lj/OPUVBfzXVSt478o67cNPYCLCRUum8vaFtfz25UP8+G9NfOjOlzhtVgU3njeX8xbUWjKLLh05TfQ6GDt6y+vLWX/TOXz2vlf44m9f5fmmdr753qUUuVP/So/1BgCoLD6R6MsLnHT7goQjJu3E0uUNUlrgpMQTfb9ubd2MWCgc4Y9bD3Pb03t5/UgP08o8/PtlS7j6tAZcDj3Zzhcuh41rTp/JlavruX/jIX7y1F6uu3sTc2uK+MS5c3jfyrqsz1jTJe0msNpSD/d84gxu/dsefvTXPWw6cJxvv28Z58yvTvqcgx3RJYXjs2UAakrcGAPHev1pz5zp9gaZUVGAx2nH7bBpRT8Cvf4Qv3+5mZ8+u4/m417m1Rbzn1et4NIV0zXB5zG3w86HzpzF1Wsa+NPWw/z02X18+YFt+INhPnr27Ky+tyb6Cc5uEz5/wQLOnFPFzQ9s49o7X+TK1fX8y7tOobLorZfC723rBWBW1YkbUNSURJN7a0/6iT7euoFoj1979MPbdaSHX79wgAdfaaHXH2JVQzlfu2QJ5y8au1N4lXtOu433rqzjslOn88K+DpbWZX9dIu3R54nT51Tx6OfO5da/7eH2p/fx5+1HuOFtc7junNkUJ7Rznm86Rk2Jm/qKE/fanVYWTe4tnV6W1g0/A8oYc3KiH0WPf7IIhCL8eccRfv3CAV56owOXw8Z7lk3jmjNmsqqhfNxcUKPGnoiM2dWz2qPPIx6nnX+6aBHvW1nHfzy2ix88vpvbn97LpadO59z5NXR7gzy24wjXnjHzpAQzN7ZGSlNrLxctGf594ksUa0U/NGMMmw8e58FXWvjj1sN09gdpqCzkX961iCtXzxjyTEupbNLWTR6aV1vC7R9qZGtzJ7/cEG0V3PtSdEXpJdNL+fwF80/av9jtYHZ1ERvTXHY1PqAbn9Nd4nHS1R+w8L9gYtrb1ssfXmnhoS1vcrCjH4/TxoWLp3L5qjreNr9G2zMqZzTR57Hl9eX851XlfOu9S9lztBeDYen0siETzjsW1fKrDQfo8QUp8TiHeLUT4hdqVcVm7lQVudgX6/1PJsYYdh3t4S87jvLYjiPseLMbm8DZ86r53PnzuWjp1JPaZkrlivboJwGP086y+tS990tXTOfO597gZ8++wRfeuSDlvvFEH6/oa0vctPb4Mcbkfc85HIm2Zf6y4wh/ee0oB471IwKrGir46rtP4dIV03XNHzXuaI9eAbBiRjmXrJjO/zzZxCnTSlm7dGrSfeNTNGdURKdo1pS4CYQidHtDlBWmPhuYiA4c6+PZPe08t6ed5/e20+0L4bLbOGteFZ9821wuWFxLbYkmdzV+6XmlGvDdy5dxsKOfG+95mQ+fMZPPnj+fqiHWVtnb2kdlkWsgqdeVR2fwHDreT1nhxF+3qKXTy6b9Hbyw7xjPNbVzqMMLwPQyD2uXTuXc+TWct7Bm2BaXUuOFJno1oMjt4L7rz+A7j+7kVy8c4N6Nh1i7ZCqXrJjO6XMqKfU4CYUj/H1vOysT1l6J39lo99GetKZnjieBUITXj3Tz8oHjbDpwnM0HjnO4ywdAidvBGXOruP7cOZw9r5o51UV535pS+UkTvTpJgcvOv1+2lA+fOYtfbdjPg6+08PCrb2ITqK8oJBSO8GaXj6+865SB58yuLqLU4+DZPe1cviq9NXdyoas/SFNbDzsP97DjzS62t3Sz60gPgXD0nrzTyzw0zqpkdUM5jbMqWTS1JOfLyyplBcnl0plxjY2NZtOmTbkOQw3BHwqz+UAnG/Yd4432PgDOW1DDFYMWUfv6wzv4xYb9fCu2wJrbkZu7TQVCEQ53eTnU4eWN9l72tPbS1Br92tZzYlnn8kInS6eXsWR6KUvrylg9s4Lp5QUpXlmp8UdEXjbGNA67Xy4TfcKsm+v37NmTszhU5nr9Ia77+UZe2t9BocvOqoYK5k8pZlZVETMqC6gqclNZ5KKiyEWRy552C8QYgz8Uoc8fotcfotsbor3XT1uvP/q1x097b4AjXV6aj3s50u0j8ZAudjuYV1vMvNpi5se+LphSQn1FgbZh1IQ3IRJ9nFb0+SESMTzX1M4TO4/y8oHjvNHeR/8Q96J12AS3w4Y7tiCa22FDRAhHDOGIIWKiX+MJPhRJfowWuexUl7iZUuKhvrKAGRWF1FcUUF9RyKzqQqaWejShq7yVbqLXHr2yjM0mvG1BDW9bUANEq/G2Xj+HOrwc7wvQ0R/geF+ALm8QfyiCPxTGH4zgD0UwgF2ir2EXwW4TXA4bxW4HRW7HwNcSj4OaEjc1xW6qi90UuPSG5EoNRxO9yhoRobbEo3PMlcoxnVKglFJ5ThO9UkrlOU30SimV5zTRK6VUnstpoheRS0Tkjq6urlyGoZRSeS2nid4Ys94Yc0NZ2cRaH0UppSYSbd0opVSe00SvlFJ5blwsgSAibcCBUT69Gmi3MByraFwjo3GNzHiNC8ZvbPkY10xjTM1wO42LRJ8JEdmUzloPY03jGhmNa2TGa1wwfmObzHFp60YppfKcJnqllMpz+ZDo78h1AEloXCOjcY3MeI0Lxm9skzauCd+jV0oplVo+VPRKKaVSmDCJXkT2i8g2EdkiIm+5HZVE3SIiTSKyVURWjUFMC2PxxP91i8jnB+1znoh0Jezzb1mK5S4RaRWR7QnbKkXkcRHZE/takeS5H4nts0dEPjIGcf2HiLwe+z09KCLlSZ6b8neehbi+LiItCb+rdyV57loR2RU71m4eg7h+kxDTfhHZkuS52fy8ZojIkyLymojsEJHPxbbn9BhLEVdOj7EUceXmGDPGTIh/wH6gOsXP3wU8CghwBvDiGMdnB44QndeauP084I9j8P5vA1YB2xO2fR+4Ofb9zcD3hnheJbAv9rUi9n1FluO6EHDEvv/eUHGl8zvPQlxfB76Yxu95LzAHcAGvAouzGdegn/8X8G85+LymAati35cAu4HFuT7GUsSV02MsRVw5OcYmTEWfhsuAX5qoF4ByEZk2hu9/PrDXGDPaC78yYox5BugYtPky4Bex738BvHeIp14EPG6M6TDGHAceB9ZmMy5jzF+MMaHYwxeAeqveL5O40rQGaDLG7DPGBID7iH7OWY9LRAR4P3CvVe+XLmPMYWPM5tj3PcBOoI4cH2PJ4sr1MZbi80qH5cfYREr0BviLiLwsIjcM8fM64FDC42bS/2CtcDXJ/wDPFJFXReRREVkyhjFNMcYcjn1/BJgyxD65/tyuI3omNpThfufZcFPsdP+uJG2IXH5e5wJHjTF7kvx8TD4vEZkFrAReZBwdY4PiSpTTY2yIuMb8GJtIif4cY8wq4GLgH0XkbbkOKE5EXMClwG+H+PFmou2cFcCtwENjGVuciZ4TjqspViLyFSAE3JNkl7H+nf8vMBc4FThMtE0ynqwjdTWf9c9LRIqB3wOfN8Z0J/4sl8dYsrhyfYwNEVdOjrEJk+iNMS2xr63Ag0RPbxK1ADMSHtfHto2Fi4HNxpijg39gjOk2xvTGvn8EcIpI9RjFdTTevop9bR1in5x8biLyUeA9wDWxBPEWafzOLWWMOWqMCRtjIsBPk7xfrj4vB3A58Jtk+2T78xIRJ9GkdY8x5oHY5pwfY0niyvkxNlRcuTrGJkSiF5EiESmJf090oGX7oN0eBj4sUWcAXQmnlNmWtNISkamx3ioisoboZ35sjOJ6GIjPcPgI8Ich9nkMuFBEKmKnkRfGtmWNiKwFvgRcaozpT7JPOr9zq+NKHNN5X5L32wjMF5HZsTO5q4l+ztl2AfC6MaZ5qB9m+/OKHcN3AjuNMT9I+FFOj7FkceX6GEsRV26OMatHm7Pxj+jo86uxfzuAr8S2fwr4VOx7AX5MdLR6G9A4RrEVEU3cZQnbEuO6KRbzq0QHhc7KUhz3Ej0VDBLt6X0cqAL+CuwBngAqY/s2Aj9LeO51QFPs38fGIK4moj3ILbF/t8X2nQ48kup3nuW4fhU7drYS/cOaNjiu2ON3EZ1FsXcs4optvzt+TCXsO5af1zlE2zJbE35v78r1MZYirpweYyniyskxplfGKqVUnpsQrRullFKjp4leKaXynCZ6pZTKc5rolVIqz2miV0qpPKeJXiml8pwmeqWUynOa6JVSKs/9P5C1CbudEwAzAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "E = np.linspace(5, 25, 1000)\n", - "plt.semilogy(E, u238_multipole(E, 293.606)[1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The real advantage to multipole is that it can be used to generate cross sections at any temperature. For example, this plot shows the Doppler broadening of the 6.67 eV resonance between 0 K and 900 K." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "E = np.linspace(6.1, 7.1, 1000)\n", - "plt.semilogy(E, u238_multipole(E, 0)[1])\n", - "plt.semilogy(E, u238_multipole(E, 900)[1])" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/pandas-dataframes.ipynb b/examples/jupyter/pandas-dataframes.ipynb deleted file mode 100644 index 7cc2d92e9..000000000 --- a/examples/jupyter/pandas-dataframes.ipynb +++ /dev/null @@ -1,2516 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook demonstrates how systematic analysis of tally scores is possible using Pandas dataframes. A dataframe can be automatically generated using the `Tally.get_pandas_dataframe(...)` method. Furthermore, by linking the tally data in a statepoint file with geometry and material information from a summary file, the dataframe can be shown with user-supplied labels." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import glob\n", - "\n", - "from IPython.display import Image\n", - "import matplotlib.pyplot as plt\n", - "import scipy.stats\n", - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "import openmc\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. We will create three materials for the fuel, water, and cladding of the fuel pin." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6 enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "water.add_nuclide('B10', 8.0042e-6)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a materials file object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials collection\n", - "materials_file = openmc.Materials([fuel, water, zircaloy])\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. This problem will be a square array of fuel pins for which we can use OpenMC's lattice/universe feature. The basic universe will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces for fuel and clad, as well as the outer bounding surfaces of the problem." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "# Use both reflective and vacuum boundaries to make life interesting\n", - "min_x = openmc.XPlane(x0=-10.71, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+10.71, boundary_type='vacuum')\n", - "min_y = openmc.YPlane(y0=-10.71, boundary_type='vacuum')\n", - "max_y = openmc.YPlane(y0=+10.71, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-10.71, boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=+10.71, boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now construct a fuel pin cell from cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel', fill=fuel,\n", - " region=-fuel_outer_radius)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad', fill=zircaloy)\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator', fill=water,\n", - " region=+clad_outer_radius)\n", - "\n", - "# Create a Universe to encapsulate a fuel pin\n", - "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin', cells=[\n", - " fuel_cell, clad_cell, moderator_cell\n", - "])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the pin cell universe, we can construct a 17x17 rectangular lattice with a 1.26 cm pitch." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create fuel assembly Lattice\n", - "assembly = openmc.RectLattice(name='1.6% Fuel - 0BA')\n", - "assembly.pitch = (1.26, 1.26)\n", - "assembly.lower_left = [-1.26 * 17. / 2.0] * 2\n", - "assembly.universes = [[pin_cell_universe] * 17] * 17" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell', fill=assembly)\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(name='root universe')\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and export to \"geometry.xml\"\n", - "geometry = openmc.Geometry(root_universe)\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 5 inactive batches and 15 minimum active batches each with 2500 particles. We also tell OpenMC to turn tally triggers on, which means it will keep running until some criterion on the uncertainty of tallies is reached." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "min_batches = 20\n", - "max_batches = 200\n", - "inactive = 5\n", - "particles = 2500\n", - "\n", - "# Instantiate a Settings object\n", - "settings = openmc.Settings()\n", - "settings.batches = min_batches\n", - "settings.inactive = inactive\n", - "settings.particles = particles\n", - "settings.output = {'tallies': False}\n", - "settings.trigger_active = True\n", - "settings.trigger_max_batches = max_batches\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-10.71, -10.71, -10, 10.71, 10.71, 10.]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEVyEhLpgJFNv8T///98iBL0AAAAAWJLR0QDEQxM8gAAAAd0SU1FB+MHEhEuBAW6hPoAAAOeSURBVGje7ZtLkqowFIZPrAsDRz247YAluIosgYEO2h20q3AJDFyAA6wSVnkDCAnkBAK/lH0bTpVVX1mCmsfJRx5E7w6hXn/U64PFWKNkkaIriXNMQWajpNDAO9HJQqJzRmGeUpRLHkVeYOJAEnkut+qT5zxpI/EYtZE26qJI3Uy9x2NY4sOBFDafvNWYD2NSo/H9t6FbJRY+qv///E0GbnowNZGqgkxpX1xf4XkYLzWq+rureyRVpfGYUuBEok/VxI6SxJHFQ4MBi2sEsSoIKktqAlJREUVNhZmscTeMzWVN+4l084h082h6atHApG4/DTrar9AtVdiN1my/Rv9huxLXafJ5+u/G/lIOH1b/3fb9aWdRUKv/GiU9BlUi1vVfYlwm7V5s6j8u2p9UnfHZpsbjGnVOO07CcvxsMm2m06uB93rQbGHajJ++Sb+LW91/s6FBp4sh038njX8hcn3WP/7zP7o9/hf/P9ROEfb7R2ZiVI2fRZletfQkXiieSLSrRCq4u7Dwr28XriGkNt02/rWRLKylN8xaeHKjNJH6pJdHT/+Vbun9f/z3zHbamf13PyS9nP/uLOnlsczKGeO/h0m4RimycrT/fsZt//WQXg55/zWa0oWR3tV/u/7L5S/Wf6389Rr/9ZBeHrXIHliMtfSyuMZOldZX5bS7eBQKheSSXt6fLBWmjrR5Se/qvz7+6y4023/9pJfB0nTpW0uvNyar/5YhZJOpOmj7b2AjRanW29TDf3MD1T08pdelwqv/9viDS3pn89+0i6b/Zl2s/Nfwt9H+++6+8xOi678WPkuKR2IqbVB6o37/3Tv89zLWf33aL9p/5vHf/vzxSv8lxH9v1E7abWSk99pFznRH4eKj8Jevp5McWKxMl8HSX4alt0+Fnf7r4W9bdvwc478v8NeX++/I34+WH1p/cPtZeqD5C82fYP5Gxw90/Pot/jvVX1B/gv1t6YE+P4DPL+jz0+/x32nPz+jzOzp/AM9fCInNnyw90Pk7cP4Qnb9E509f56/T5o/R+Wt0/hydv4fXD5Ye6PoVuH6Grt/N47/+65ezzB+NWL9F14/R9Wt0/Rxev196oPtHwP0r8/iv//6d1X+x/WPw/jUhsf1zSw90/+YZ2z+K7l9d/RfbP43u34b3jy890PMLJ+z8xGv8d/r5kdV/sfNL6Pkp+PzW0gM9PwieX0TPT87rv5P2D/4M//U8v4ueH4bPL6Pnp98b/wAXomzv5H3x5AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wNy0xOFQyMjo0NjowNC0wNTowMEOkh1cAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDctMThUMjI6NDY6MDQtMDU6MDAy+T/rAAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Instantiate a Plot\n", - "plot = openmc.Plot(plot_id=1)\n", - "plot.filename = 'materials-xy'\n", - "plot.origin = [0, 0, 0]\n", - "plot.width = [21.5, 21.5]\n", - "plot.pixels = [250, 250]\n", - "plot.color_by = 'material'\n", - "\n", - "# Show plot\n", - "openmc.plot_inline(plot)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see from the plot, we have a nice array of pin cells with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a variety of tallies." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate an empty Tallies object\n", - "tallies = openmc.Tallies()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate a fission rate mesh Tally" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a tally Mesh\n", - "mesh = openmc.RegularMesh(mesh_id=1)\n", - "mesh.dimension = [17, 17]\n", - "mesh.lower_left = [-10.71, -10.71]\n", - "mesh.width = [1.26, 1.26]\n", - "\n", - "# Instantiate tally Filter\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Instantiate energy Filter\n", - "energy_filter = openmc.EnergyFilter([0, 0.625, 20.0e6])\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='mesh tally')\n", - "tally.filters = [mesh_filter, energy_filter]\n", - "tally.scores = ['fission', 'nu-fission']\n", - "\n", - "# Add mesh and Tally to Tallies\n", - "tallies.append(tally)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate a cell Tally with nuclides" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate tally Filter\n", - "cell_filter = openmc.CellFilter(fuel_cell)\n", - "\n", - "# Instantiate the tally\n", - "tally = openmc.Tally(name='cell tally')\n", - "tally.filters = [cell_filter]\n", - "tally.scores = ['scatter']\n", - "tally.nuclides = ['U235', 'U238']\n", - "\n", - "# Add mesh and tally to Tallies\n", - "tallies.append(tally)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a \"distribcell\" Tally. The distribcell filter allows us to tally multiple repeated instances of the same cell throughout the geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate tally Filter\n", - "distribcell_filter = openmc.DistribcellFilter(moderator_cell)\n", - "\n", - "# Instantiate tally Trigger for kicks\n", - "trigger = openmc.Trigger(trigger_type='std_dev', threshold=5e-5)\n", - "trigger.scores = ['absorption']\n", - "\n", - "# Instantiate the Tally\n", - "tally = openmc.Tally(name='distribcell tally')\n", - "tally.filters = [distribcell_filter]\n", - "tally.scores = ['absorption', 'scatter']\n", - "tally.triggers = [trigger]\n", - "\n", - "# Add mesh and tally to Tallies\n", - "tallies.append(tally)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Export to \"tallies.xml\"\n", - "tallies.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-18 22:46:04\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading B10 from /opt/data/hdf5/nndc_hdf5_v15/B10.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 0.55921\n", - " 2/1 0.63816\n", - " 3/1 0.68834\n", - " 4/1 0.71192\n", - " 5/1 0.67935\n", - " 6/1 0.68254\n", - " 7/1 0.65804 0.67029 +/- 0.01225\n", - " 8/1 0.66225 0.66761 +/- 0.00756\n", - " 9/1 0.66336 0.66655 +/- 0.00545\n", - " 10/1 0.70686 0.67461 +/- 0.00910\n", - " 11/1 0.71753 0.68176 +/- 0.01031\n", - " 12/1 0.66967 0.68004 +/- 0.00889\n", - " 13/1 0.67800 0.67978 +/- 0.00770\n", - " 14/1 0.65634 0.67718 +/- 0.00727\n", - " 15/1 0.66891 0.67635 +/- 0.00656\n", - " 16/1 0.66281 0.67512 +/- 0.00606\n", - " 17/1 0.68160 0.67566 +/- 0.00556\n", - " 18/1 0.63835 0.67279 +/- 0.00586\n", - " 19/1 0.66200 0.67202 +/- 0.00548\n", - " 20/1 0.67156 0.67199 +/- 0.00510\n", - " Triggers unsatisfied, max unc./thresh. is 68.3537 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 70089 --- greater than max batches\n", - " Creating state point statepoint.020.h5...\n", - " 21/1 0.67469 0.67216 +/- 0.00478\n", - " Triggers unsatisfied, max unc./thresh. is 63.9814 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 65503 --- greater than max batches\n", - " 22/1 0.69218 0.67334 +/- 0.00464\n", - " Triggers unsatisfied, max unc./thresh. is 64.4829 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 70692 --- greater than max batches\n", - " 23/1 0.72838 0.67639 +/- 0.00534\n", - " Triggers unsatisfied, max unc./thresh. is 65.1347 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 76371 --- greater than max batches\n", - " 24/1 0.68472 0.67683 +/- 0.00507\n", - " Triggers unsatisfied, max unc./thresh. is 61.6163 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 72140 --- greater than max batches\n", - " 25/1 0.66664 0.67632 +/- 0.00483\n", - " Triggers unsatisfied, max unc./thresh. is 59.0208 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 69675 --- greater than max batches\n", - " 26/1 0.65315 0.67522 +/- 0.00473\n", - " Triggers unsatisfied, max unc./thresh. is 56.5216 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 67094 --- greater than max batches\n", - " 27/1 0.63865 0.67356 +/- 0.00480\n", - " Triggers unsatisfied, max unc./thresh. is 53.8991 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 63918 --- greater than max batches\n", - " 28/1 0.68053 0.67386 +/- 0.00460\n", - " Triggers unsatisfied, max unc./thresh. is 51.504 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61017 --- greater than max batches\n", - " 29/1 0.71585 0.67561 +/- 0.00474\n", - " Triggers unsatisfied, max unc./thresh. is 49.3115 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58364 --- greater than max batches\n", - " 30/1 0.67268 0.67549 +/- 0.00455\n", - " Triggers unsatisfied, max unc./thresh. is 47.3457 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56046 --- greater than max batches\n", - " 31/1 0.67027 0.67529 +/- 0.00437\n", - " Triggers unsatisfied, max unc./thresh. is 48.2456 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60524 --- greater than max batches\n", - " 32/1 0.67324 0.67522 +/- 0.00421\n", - " Triggers unsatisfied, max unc./thresh. is 47.1077 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59922 --- greater than max batches\n", - " 33/1 0.66398 0.67481 +/- 0.00408\n", - " Triggers unsatisfied, max unc./thresh. is 45.4352 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57807 --- greater than max batches\n", - " 34/1 0.66373 0.67443 +/- 0.00395\n", - " Triggers unsatisfied, max unc./thresh. is 44.8243 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58273 --- greater than max batches\n", - " 35/1 0.68412 0.67476 +/- 0.00383\n", - " Triggers unsatisfied, max unc./thresh. is 43.7412 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57404 --- greater than max batches\n", - " 36/1 0.66026 0.67429 +/- 0.00374\n", - " Triggers unsatisfied, max unc./thresh. is 43.0549 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57471 --- greater than max batches\n", - " 37/1 0.67283 0.67424 +/- 0.00362\n", - " Triggers unsatisfied, max unc./thresh. is 42.9634 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59073 --- greater than max batches\n", - " 38/1 0.69507 0.67487 +/- 0.00356\n", - " Triggers unsatisfied, max unc./thresh. is 41.6527 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57259 --- greater than max batches\n", - " 39/1 0.68681 0.67522 +/- 0.00347\n", - " Triggers unsatisfied, max unc./thresh. is 40.4174 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55547 --- greater than max batches\n", - " 40/1 0.65886 0.67476 +/- 0.00340\n", - " Triggers unsatisfied, max unc./thresh. is 39.424 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54404 --- greater than max batches\n", - " 41/1 0.63736 0.67372 +/- 0.00347\n", - " Triggers unsatisfied, max unc./thresh. is 40.094 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57877 --- greater than max batches\n", - " 42/1 0.71800 0.67491 +/- 0.00358\n", - " Triggers unsatisfied, max unc./thresh. is 39.0603 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56457 --- greater than max batches\n", - " 43/1 0.67193 0.67484 +/- 0.00348\n", - " Triggers unsatisfied, max unc./thresh. is 38.8448 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57344 --- greater than max batches\n", - " 44/1 0.66680 0.67463 +/- 0.00340\n", - " Triggers unsatisfied, max unc./thresh. is 38.227 for absorption in tally 3\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " WARNING: The estimated number of batches is 56996 --- greater than max batches\n", - " 45/1 0.65956 0.67425 +/- 0.00334\n", - " Triggers unsatisfied, max unc./thresh. is 37.2591 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55535 --- greater than max batches\n", - " 46/1 0.64705 0.67359 +/- 0.00332\n", - " Triggers unsatisfied, max unc./thresh. is 37.802 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58594 --- greater than max batches\n", - " 47/1 0.67729 0.67368 +/- 0.00324\n", - " Triggers unsatisfied, max unc./thresh. is 36.9727 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57419 --- greater than max batches\n", - " 48/1 0.68259 0.67389 +/- 0.00317\n", - " Triggers unsatisfied, max unc./thresh. is 36.3752 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56901 --- greater than max batches\n", - " 49/1 0.64395 0.67320 +/- 0.00317\n", - " Triggers unsatisfied, max unc./thresh. is 35.7676 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56296 --- greater than max batches\n", - " 50/1 0.68839 0.67354 +/- 0.00312\n", - " Triggers unsatisfied, max unc./thresh. is 34.977 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55058 --- greater than max batches\n", - " 51/1 0.71108 0.67436 +/- 0.00316\n", - " Triggers unsatisfied, max unc./thresh. is 34.453 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54608 --- greater than max batches\n", - " 52/1 0.66286 0.67411 +/- 0.00310\n", - " Triggers unsatisfied, max unc./thresh. is 33.9781 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54268 --- greater than max batches\n", - " 53/1 0.62666 0.67313 +/- 0.00319\n", - " Triggers unsatisfied, max unc./thresh. is 33.4946 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 53856 --- greater than max batches\n", - " 54/1 0.67124 0.67309 +/- 0.00313\n", - " Triggers unsatisfied, max unc./thresh. is 32.8639 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 52927 --- greater than max batches\n", - " 55/1 0.67741 0.67317 +/- 0.00306\n", - " Triggers unsatisfied, max unc./thresh. is 32.2922 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 52145 --- greater than max batches\n", - " 56/1 0.67182 0.67315 +/- 0.00300\n", - " Triggers unsatisfied, max unc./thresh. is 31.9136 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 51948 --- greater than max batches\n", - " 57/1 0.68764 0.67343 +/- 0.00296\n", - " Triggers unsatisfied, max unc./thresh. is 31.3059 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50969 --- greater than max batches\n", - " 58/1 0.72310 0.67436 +/- 0.00305\n", - " Triggers unsatisfied, max unc./thresh. is 30.8841 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50558 --- greater than max batches\n", - " 59/1 0.67689 0.67441 +/- 0.00299\n", - " Triggers unsatisfied, max unc./thresh. is 30.5895 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50534 --- greater than max batches\n", - " 60/1 0.65890 0.67413 +/- 0.00295\n", - " Triggers unsatisfied, max unc./thresh. is 30.0567 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 49693 --- greater than max batches\n", - " 61/1 0.69128 0.67443 +/- 0.00291\n", - " Triggers unsatisfied, max unc./thresh. is 29.8144 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 49784 --- greater than max batches\n", - " 62/1 0.65469 0.67409 +/- 0.00288\n", - " Triggers unsatisfied, max unc./thresh. is 29.3138 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 48986 --- greater than max batches\n", - " 63/1 0.71839 0.67485 +/- 0.00293\n", - " Triggers unsatisfied, max unc./thresh. is 28.9465 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 48604 --- greater than max batches\n", - " 64/1 0.69556 0.67520 +/- 0.00291\n", - " Triggers unsatisfied, max unc./thresh. is 29.1602 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50174 --- greater than max batches\n", - " 65/1 0.70067 0.67563 +/- 0.00289\n", - " Triggers unsatisfied, max unc./thresh. is 28.9248 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50204 --- greater than max batches\n", - " 66/1 0.67994 0.67570 +/- 0.00284\n", - " Triggers unsatisfied, max unc./thresh. is 28.7841 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50545 --- greater than max batches\n", - " 67/1 0.74539 0.67682 +/- 0.00301\n", - " Triggers unsatisfied, max unc./thresh. is 28.4946 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50346 --- greater than max batches\n", - " 68/1 0.67753 0.67683 +/- 0.00296\n", - " Triggers unsatisfied, max unc./thresh. is 28.1166 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 49810 --- greater than max batches\n", - " 69/1 0.69595 0.67713 +/- 0.00293\n", - " Triggers unsatisfied, max unc./thresh. is 28.0441 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50340 --- greater than max batches\n", - " 70/1 0.70621 0.67758 +/- 0.00292\n", - " Triggers unsatisfied, max unc./thresh. is 27.708 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 49908 --- greater than max batches\n", - " 71/1 0.71027 0.67807 +/- 0.00292\n", - " Triggers unsatisfied, max unc./thresh. is 27.2979 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 49187 --- greater than max batches\n", - " 72/1 0.63710 0.67746 +/- 0.00294\n", - " Triggers unsatisfied, max unc./thresh. is 27.3359 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 50071 --- greater than max batches\n", - " 73/1 0.70979 0.67794 +/- 0.00294\n", - " Triggers unsatisfied, max unc./thresh. is 29.5308 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59306 --- greater than max batches\n", - " 74/1 0.65957 0.67767 +/- 0.00291\n", - " Triggers unsatisfied, max unc./thresh. is 29.2344 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58976 --- greater than max batches\n", - " 75/1 0.66611 0.67751 +/- 0.00287\n", - " Triggers unsatisfied, max unc./thresh. is 28.8289 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58183 --- greater than max batches\n", - " 76/1 0.66033 0.67726 +/- 0.00284\n", - " Triggers unsatisfied, max unc./thresh. is 28.4986 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57670 --- greater than max batches\n", - " 77/1 0.68535 0.67738 +/- 0.00280\n", - " Triggers unsatisfied, max unc./thresh. is 28.2548 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57486 --- greater than max batches\n", - " 78/1 0.71920 0.67795 +/- 0.00282\n", - " Triggers unsatisfied, max unc./thresh. is 28.2853 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58410 --- greater than max batches\n", - " 79/1 0.67645 0.67793 +/- 0.00278\n", - " Triggers unsatisfied, max unc./thresh. is 27.9534 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57829 --- greater than max batches\n", - " 80/1 0.68300 0.67800 +/- 0.00275\n", - " Triggers unsatisfied, max unc./thresh. is 27.5813 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57060 --- greater than max batches\n", - " 81/1 0.69810 0.67826 +/- 0.00272\n", - " Triggers unsatisfied, max unc./thresh. is 27.2164 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56301 --- greater than max batches\n", - " 82/1 0.68213 0.67831 +/- 0.00269\n", - " Triggers unsatisfied, max unc./thresh. is 26.8628 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55570 --- greater than max batches\n", - " 83/1 0.68745 0.67843 +/- 0.00265\n", - " Triggers unsatisfied, max unc./thresh. is 26.5172 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54852 --- greater than max batches\n", - " 84/1 0.65239 0.67810 +/- 0.00264\n", - " Triggers unsatisfied, max unc./thresh. is 26.2016 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54241 --- greater than max batches\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 85/1 0.64990 0.67775 +/- 0.00263\n", - " Triggers unsatisfied, max unc./thresh. is 25.9705 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 53963 --- greater than max batches\n", - " 86/1 0.68586 0.67785 +/- 0.00260\n", - " Triggers unsatisfied, max unc./thresh. is 25.7908 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 53884 --- greater than max batches\n", - " 87/1 0.63453 0.67732 +/- 0.00262\n", - " Triggers unsatisfied, max unc./thresh. is 25.5271 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 53439 --- greater than max batches\n", - " 88/1 0.65402 0.67704 +/- 0.00261\n", - " Triggers unsatisfied, max unc./thresh. is 25.321 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 53221 --- greater than max batches\n", - " 89/1 0.69063 0.67720 +/- 0.00258\n", - " Triggers unsatisfied, max unc./thresh. is 25.8769 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56253 --- greater than max batches\n", - " 90/1 0.65729 0.67697 +/- 0.00256\n", - " Triggers unsatisfied, max unc./thresh. is 25.7648 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56431 --- greater than max batches\n", - " 91/1 0.72355 0.67751 +/- 0.00259\n", - " Triggers unsatisfied, max unc./thresh. is 25.5034 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55942 --- greater than max batches\n", - " 92/1 0.63010 0.67696 +/- 0.00262\n", - " Triggers unsatisfied, max unc./thresh. is 25.2708 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55565 --- greater than max batches\n", - " 93/1 0.68610 0.67707 +/- 0.00259\n", - " Triggers unsatisfied, max unc./thresh. is 24.9941 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54980 --- greater than max batches\n", - " 94/1 0.67618 0.67706 +/- 0.00256\n", - " Triggers unsatisfied, max unc./thresh. is 24.7139 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 54365 --- greater than max batches\n", - " 95/1 0.68946 0.67719 +/- 0.00253\n", - " Triggers unsatisfied, max unc./thresh. is 25.4371 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58240 --- greater than max batches\n", - " 96/1 0.70557 0.67751 +/- 0.00252\n", - " Triggers unsatisfied, max unc./thresh. is 25.5082 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59216 --- greater than max batches\n", - " 97/1 0.64689 0.67717 +/- 0.00252\n", - " Triggers unsatisfied, max unc./thresh. is 25.2374 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58603 --- greater than max batches\n", - " 98/1 0.70194 0.67744 +/- 0.00251\n", - " Triggers unsatisfied, max unc./thresh. is 25.393 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59972 --- greater than max batches\n", - " 99/1 0.68278 0.67750 +/- 0.00248\n", - " Triggers unsatisfied, max unc./thresh. is 25.5651 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61441 --- greater than max batches\n", - " 100/1 0.67066 0.67742 +/- 0.00246\n", - " Triggers unsatisfied, max unc./thresh. is 25.3552 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61079 --- greater than max batches\n", - " 101/1 0.64907 0.67713 +/- 0.00245\n", - " Triggers unsatisfied, max unc./thresh. is 25.3463 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61679 --- greater than max batches\n", - " 102/1 0.69810 0.67735 +/- 0.00243\n", - " Triggers unsatisfied, max unc./thresh. is 25.1877 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61544 --- greater than max batches\n", - " 103/1 0.70659 0.67764 +/- 0.00242\n", - " Triggers unsatisfied, max unc./thresh. is 24.9371 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60948 --- greater than max batches\n", - " 104/1 0.64152 0.67728 +/- 0.00243\n", - " Triggers unsatisfied, max unc./thresh. is 24.6848 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60330 --- greater than max batches\n", - " 105/1 0.68117 0.67732 +/- 0.00240\n", - " Triggers unsatisfied, max unc./thresh. is 24.4368 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59721 --- greater than max batches\n", - " 106/1 0.71963 0.67774 +/- 0.00242\n", - " Triggers unsatisfied, max unc./thresh. is 24.2091 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59200 --- greater than max batches\n", - " 107/1 0.69488 0.67790 +/- 0.00240\n", - " Triggers unsatisfied, max unc./thresh. is 23.9711 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58616 --- greater than max batches\n", - " 108/1 0.65697 0.67770 +/- 0.00238\n", - " Triggers unsatisfied, max unc./thresh. is 23.8071 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58384 --- greater than max batches\n", - " 109/1 0.70032 0.67792 +/- 0.00237\n", - " Triggers unsatisfied, max unc./thresh. is 23.5788 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57825 --- greater than max batches\n", - " 110/1 0.66571 0.67780 +/- 0.00235\n", - " Triggers unsatisfied, max unc./thresh. is 23.5035 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58009 --- greater than max batches\n", - " 111/1 0.69676 0.67798 +/- 0.00234\n", - " Triggers unsatisfied, max unc./thresh. is 23.3157 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57629 --- greater than max batches\n", - " 112/1 0.68219 0.67802 +/- 0.00231\n", - " Triggers unsatisfied, max unc./thresh. is 23.1525 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57361 --- greater than max batches\n", - " 113/1 0.69025 0.67813 +/- 0.00230\n", - " Triggers unsatisfied, max unc./thresh. is 23.0036 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57156 --- greater than max batches\n", - " 114/1 0.69241 0.67826 +/- 0.00228\n", - " Triggers unsatisfied, max unc./thresh. is 22.792 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56628 --- greater than max batches\n", - " 115/1 0.68646 0.67834 +/- 0.00226\n", - " Triggers unsatisfied, max unc./thresh. is 22.6864 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56620 --- greater than max batches\n", - " 116/1 0.69601 0.67850 +/- 0.00224\n", - " Triggers unsatisfied, max unc./thresh. is 22.5007 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 56203 --- greater than max batches\n", - " 117/1 0.68761 0.67858 +/- 0.00222\n", - " Triggers unsatisfied, max unc./thresh. is 22.3093 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 55749 --- greater than max batches\n", - " 118/1 0.71356 0.67889 +/- 0.00223\n", - " Triggers unsatisfied, max unc./thresh. is 22.6651 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58054 --- greater than max batches\n", - " 119/1 0.69850 0.67906 +/- 0.00221\n", - " Triggers unsatisfied, max unc./thresh. is 22.4712 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57570 --- greater than max batches\n", - " 120/1 0.70957 0.67933 +/- 0.00221\n", - " Triggers unsatisfied, max unc./thresh. is 22.3266 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57331 --- greater than max batches\n", - " 121/1 0.69643 0.67947 +/- 0.00220\n", - " Triggers unsatisfied, max unc./thresh. is 22.6029 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59269 --- greater than max batches\n", - " 122/1 0.67717 0.67945 +/- 0.00218\n", - " Triggers unsatisfied, max unc./thresh. is 22.4667 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59062 --- greater than max batches\n", - " 123/1 0.68419 0.67949 +/- 0.00216\n", - " Triggers unsatisfied, max unc./thresh. is 22.3764 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59089 --- greater than max batches\n", - " 124/1 0.69221 0.67960 +/- 0.00214\n", - " Triggers unsatisfied, max unc./thresh. is 22.3341 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59364 --- greater than max batches\n", - " 125/1 0.73940 0.68010 +/- 0.00218\n", - " Triggers unsatisfied, max unc./thresh. is 22.1478 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58868 --- greater than max batches\n", - " 126/1 0.66908 0.68001 +/- 0.00217\n", - " Triggers unsatisfied, max unc./thresh. is 22.0085 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58615 --- greater than max batches\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 127/1 0.66041 0.67985 +/- 0.00216\n", - " Triggers unsatisfied, max unc./thresh. is 21.8274 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58131 --- greater than max batches\n", - " 128/1 0.69395 0.67996 +/- 0.00214\n", - " Triggers unsatisfied, max unc./thresh. is 21.6537 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57678 --- greater than max batches\n", - " 129/1 0.68665 0.68002 +/- 0.00212\n", - " Triggers unsatisfied, max unc./thresh. is 21.7739 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58794 --- greater than max batches\n", - " 130/1 0.64849 0.67976 +/- 0.00212\n", - " Triggers unsatisfied, max unc./thresh. is 21.7492 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59134 --- greater than max batches\n", - " 131/1 0.69734 0.67990 +/- 0.00211\n", - " Triggers unsatisfied, max unc./thresh. is 21.59 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58738 --- greater than max batches\n", - " 132/1 0.69482 0.68002 +/- 0.00210\n", - " Triggers unsatisfied, max unc./thresh. is 21.4249 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58302 --- greater than max batches\n", - " 133/1 0.68884 0.68009 +/- 0.00208\n", - " Triggers unsatisfied, max unc./thresh. is 21.2587 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57853 --- greater than max batches\n", - " 134/1 0.63042 0.67971 +/- 0.00210\n", - " Triggers unsatisfied, max unc./thresh. is 21.1851 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57902 --- greater than max batches\n", - " 135/1 0.69209 0.67980 +/- 0.00209\n", - " Triggers unsatisfied, max unc./thresh. is 21.0525 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57623 --- greater than max batches\n", - " 136/1 0.69873 0.67995 +/- 0.00208\n", - " Triggers unsatisfied, max unc./thresh. is 20.9996 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57774 --- greater than max batches\n", - " 137/1 0.70270 0.68012 +/- 0.00207\n", - " Triggers unsatisfied, max unc./thresh. is 20.8455 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 57364 --- greater than max batches\n", - " 138/1 0.67295 0.68006 +/- 0.00205\n", - " Triggers unsatisfied, max unc./thresh. is 21.3716 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60752 --- greater than max batches\n", - " 139/1 0.63853 0.67975 +/- 0.00206\n", - " Triggers unsatisfied, max unc./thresh. is 21.2124 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60301 --- greater than max batches\n", - " 140/1 0.66645 0.67966 +/- 0.00205\n", - " Triggers unsatisfied, max unc./thresh. is 21.1279 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60268 --- greater than max batches\n", - " 141/1 0.70730 0.67986 +/- 0.00204\n", - " Triggers unsatisfied, max unc./thresh. is 20.9845 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59893 --- greater than max batches\n", - " 142/1 0.68838 0.67992 +/- 0.00203\n", - " Triggers unsatisfied, max unc./thresh. is 20.8774 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59719 --- greater than max batches\n", - " 143/1 0.64900 0.67970 +/- 0.00203\n", - " Triggers unsatisfied, max unc./thresh. is 21.3772 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 63069 --- greater than max batches\n", - " 144/1 0.64490 0.67945 +/- 0.00203\n", - " Triggers unsatisfied, max unc./thresh. is 21.2531 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62791 --- greater than max batches\n", - " 145/1 0.69221 0.67954 +/- 0.00201\n", - " Triggers unsatisfied, max unc./thresh. is 21.2049 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62956 --- greater than max batches\n", - " 146/1 0.69481 0.67965 +/- 0.00200\n", - " Triggers unsatisfied, max unc./thresh. is 21.0645 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62569 --- greater than max batches\n", - " 147/1 0.70394 0.67982 +/- 0.00200\n", - " Triggers unsatisfied, max unc./thresh. is 20.9156 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62125 --- greater than max batches\n", - " 148/1 0.69482 0.67992 +/- 0.00198\n", - " Triggers unsatisfied, max unc./thresh. is 20.7699 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61694 --- greater than max batches\n", - " 149/1 0.63886 0.67964 +/- 0.00199\n", - " Triggers unsatisfied, max unc./thresh. is 20.6366 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61331 --- greater than max batches\n", - " 150/1 0.69377 0.67973 +/- 0.00198\n", - " Triggers unsatisfied, max unc./thresh. is 20.5819 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61430 --- greater than max batches\n", - " 151/1 0.71045 0.67994 +/- 0.00198\n", - " Triggers unsatisfied, max unc./thresh. is 20.5417 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61612 --- greater than max batches\n", - " 152/1 0.66093 0.67982 +/- 0.00197\n", - " Triggers unsatisfied, max unc./thresh. is 20.4124 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61256 --- greater than max batches\n", - " 153/1 0.68564 0.67985 +/- 0.00196\n", - " Triggers unsatisfied, max unc./thresh. is 20.3025 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61010 --- greater than max batches\n", - " 154/1 0.66961 0.67979 +/- 0.00194\n", - " Triggers unsatisfied, max unc./thresh. is 20.2239 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60948 --- greater than max batches\n", - " 155/1 0.67099 0.67973 +/- 0.00193\n", - " Triggers unsatisfied, max unc./thresh. is 20.0962 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60584 --- greater than max batches\n", - " 156/1 0.72742 0.68004 +/- 0.00194\n", - " Triggers unsatisfied, max unc./thresh. is 19.9753 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60256 --- greater than max batches\n", - " 157/1 0.66458 0.67994 +/- 0.00193\n", - " Triggers unsatisfied, max unc./thresh. is 19.8852 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60109 --- greater than max batches\n", - " 158/1 0.69052 0.68001 +/- 0.00192\n", - " Triggers unsatisfied, max unc./thresh. is 19.7963 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59965 --- greater than max batches\n", - " 159/1 0.70643 0.68018 +/- 0.00192\n", - " Triggers unsatisfied, max unc./thresh. is 19.6991 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59766 --- greater than max batches\n", - " 160/1 0.68576 0.68022 +/- 0.00191\n", - " Triggers unsatisfied, max unc./thresh. is 19.6197 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59670 --- greater than max batches\n", - " 161/1 0.69854 0.68034 +/- 0.00190\n", - " Triggers unsatisfied, max unc./thresh. is 19.8287 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61341 --- greater than max batches\n", - " 162/1 0.65983 0.68020 +/- 0.00189\n", - " Triggers unsatisfied, max unc./thresh. is 20.0243 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62958 --- greater than max batches\n", - " 163/1 0.66316 0.68010 +/- 0.00188\n", - " Triggers unsatisfied, max unc./thresh. is 19.8975 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62560 --- greater than max batches\n", - " 164/1 0.66179 0.67998 +/- 0.00187\n", - " Triggers unsatisfied, max unc./thresh. is 19.895 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62940 --- greater than max batches\n", - " 165/1 0.70881 0.68016 +/- 0.00187\n", - " Triggers unsatisfied, max unc./thresh. is 19.8013 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62740 --- greater than max batches\n", - " 166/1 0.70729 0.68033 +/- 0.00187\n", - " Triggers unsatisfied, max unc./thresh. is 19.6876 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62410 --- greater than max batches\n", - " 167/1 0.71073 0.68052 +/- 0.00186\n", - " Triggers unsatisfied, max unc./thresh. is 19.5695 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 62046 --- greater than max batches\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 168/1 0.69610 0.68061 +/- 0.00185\n", - " Triggers unsatisfied, max unc./thresh. is 19.4797 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61857 --- greater than max batches\n", - " 169/1 0.67141 0.68056 +/- 0.00184\n", - " Triggers unsatisfied, max unc./thresh. is 19.438 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61970 --- greater than max batches\n", - " 170/1 0.67727 0.68054 +/- 0.00183\n", - " Triggers unsatisfied, max unc./thresh. is 19.3208 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61599 --- greater than max batches\n", - " 171/1 0.64150 0.68030 +/- 0.00184\n", - " Triggers unsatisfied, max unc./thresh. is 19.2066 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61242 --- greater than max batches\n", - " 172/1 0.68758 0.68035 +/- 0.00183\n", - " Triggers unsatisfied, max unc./thresh. is 19.114 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61018 --- greater than max batches\n", - " 173/1 0.67126 0.68029 +/- 0.00182\n", - " Triggers unsatisfied, max unc./thresh. is 19.1545 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61644 --- greater than max batches\n", - " 174/1 0.65933 0.68017 +/- 0.00181\n", - " Triggers unsatisfied, max unc./thresh. is 19.0415 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 61281 --- greater than max batches\n", - " 175/1 0.70572 0.68032 +/- 0.00181\n", - " Triggers unsatisfied, max unc./thresh. is 18.9347 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60954 --- greater than max batches\n", - " 176/1 0.66175 0.68021 +/- 0.00180\n", - " Triggers unsatisfied, max unc./thresh. is 18.8337 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60660 --- greater than max batches\n", - " 177/1 0.68714 0.68025 +/- 0.00179\n", - " Triggers unsatisfied, max unc./thresh. is 18.7329 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60364 --- greater than max batches\n", - " 178/1 0.70181 0.68037 +/- 0.00178\n", - " Triggers unsatisfied, max unc./thresh. is 18.6297 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 60048 --- greater than max batches\n", - " 179/1 0.66700 0.68030 +/- 0.00177\n", - " Triggers unsatisfied, max unc./thresh. is 18.5239 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59711 --- greater than max batches\n", - " 180/1 0.68980 0.68035 +/- 0.00176\n", - " Triggers unsatisfied, max unc./thresh. is 18.4186 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59374 --- greater than max batches\n", - " 181/1 0.69586 0.68044 +/- 0.00176\n", - " Triggers unsatisfied, max unc./thresh. is 18.3816 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59473 --- greater than max batches\n", - " 182/1 0.68689 0.68048 +/- 0.00175\n", - " Triggers unsatisfied, max unc./thresh. is 18.2781 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59139 --- greater than max batches\n", - " 183/1 0.69257 0.68054 +/- 0.00174\n", - " Triggers unsatisfied, max unc./thresh. is 18.1773 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58819 --- greater than max batches\n", - " 184/1 0.69926 0.68065 +/- 0.00173\n", - " Triggers unsatisfied, max unc./thresh. is 18.2191 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59422 --- greater than max batches\n", - " 185/1 0.67801 0.68063 +/- 0.00172\n", - " Triggers unsatisfied, max unc./thresh. is 18.1184 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59096 --- greater than max batches\n", - " 186/1 0.67049 0.68058 +/- 0.00171\n", - " Triggers unsatisfied, max unc./thresh. is 18.0484 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58965 --- greater than max batches\n", - " 187/1 0.68164 0.68058 +/- 0.00170\n", - " Triggers unsatisfied, max unc./thresh. is 17.9808 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58848 --- greater than max batches\n", - " 188/1 0.66856 0.68052 +/- 0.00170\n", - " Triggers unsatisfied, max unc./thresh. is 17.9146 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58736 --- greater than max batches\n", - " 189/1 0.71850 0.68073 +/- 0.00170\n", - " Triggers unsatisfied, max unc./thresh. is 17.8551 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58665 --- greater than max batches\n", - " 190/1 0.67095 0.68067 +/- 0.00169\n", - " Triggers unsatisfied, max unc./thresh. is 17.8953 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59250 --- greater than max batches\n", - " 191/1 0.70857 0.68082 +/- 0.00169\n", - " Triggers unsatisfied, max unc./thresh. is 17.8197 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59068 --- greater than max batches\n", - " 192/1 0.65322 0.68067 +/- 0.00169\n", - " Triggers unsatisfied, max unc./thresh. is 17.8199 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59387 --- greater than max batches\n", - " 193/1 0.67888 0.68066 +/- 0.00168\n", - " Triggers unsatisfied, max unc./thresh. is 17.8072 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59620 --- greater than max batches\n", - " 194/1 0.72890 0.68092 +/- 0.00169\n", - " Triggers unsatisfied, max unc./thresh. is 17.7152 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59319 --- greater than max batches\n", - " 195/1 0.64688 0.68074 +/- 0.00169\n", - " Triggers unsatisfied, max unc./thresh. is 17.6252 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59029 --- greater than max batches\n", - " 196/1 0.68906 0.68078 +/- 0.00168\n", - " Triggers unsatisfied, max unc./thresh. is 17.5465 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58810 --- greater than max batches\n", - " 197/1 0.69381 0.68085 +/- 0.00167\n", - " Triggers unsatisfied, max unc./thresh. is 17.4939 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58764 --- greater than max batches\n", - " 198/1 0.70057 0.68095 +/- 0.00167\n", - " Triggers unsatisfied, max unc./thresh. is 17.4414 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58717 --- greater than max batches\n", - " 199/1 0.67868 0.68094 +/- 0.00166\n", - " Triggers unsatisfied, max unc./thresh. is 17.4394 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 59008 --- greater than max batches\n", - " 200/1 0.69190 0.68100 +/- 0.00165\n", - " Triggers unsatisfied, max unc./thresh. is 17.3511 for absorption in tally 3\n", - " WARNING: The estimated number of batches is 58712 --- greater than max batches\n", - " Creating state point statepoint.200.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 9.3777e-01 seconds\n", - " Reading cross sections = 8.7757e-01 seconds\n", - " Total time in simulation = 4.0652e+01 seconds\n", - " Time in transport only = 3.9022e+01 seconds\n", - " Time in inactive batches = 9.1120e-01 seconds\n", - " Time in active batches = 3.9741e+01 seconds\n", - " Time synchronizing fission bank = 4.0496e-02 seconds\n", - " Sampling source sites = 3.3700e-02 seconds\n", - " SEND/RECV source sites = 6.4404e-03 seconds\n", - " Time accumulating tallies = 2.0272e-03 seconds\n", - " Total time for finalization = 4.0896e-03 seconds\n", - " Total time elapsed = 4.1621e+01 seconds\n", - " Calculation Rate (inactive) = 13718.1 particles/second\n", - " Calculation Rate (active) = 12267.1 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 0.68122 +/- 0.00150\n", - " k-effective (Track-length) = 0.68100 +/- 0.00165\n", - " k-effective (Absorption) = 0.68224 +/- 0.00159\n", - " Combined k-effective = 0.68162 +/- 0.00134\n", - " Leakage Fraction = 0.34047 +/- 0.00082\n", - "\n" - ] - } - ], - "source": [ - "# Remove old HDF5 (summary, statepoint) files\n", - "!rm statepoint.*\n", - "\n", - "# Run OpenMC!\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# We do not know how many batches were needed to satisfy the \n", - "# tally trigger(s), so find the statepoint file(s)\n", - "statepoints = glob.glob('statepoint.*.h5')\n", - "\n", - "# Load the last statepoint file\n", - "sp = openmc.StatePoint(statepoints[-1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Analyze the mesh fission rate tally**" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tally\n", - "\tID =\t1\n", - "\tName =\tmesh tally\n", - "\tFilters =\tMeshFilter, EnergyFilter\n", - "\tNuclides =\ttotal \n", - "\tScores =\t['fission', 'nu-fission']\n", - "\tEstimator =\ttracklength\n", - "\n" - ] - } - ], - "source": [ - "# Find the mesh tally with the StatePoint API\n", - "tally = sp.get_tally(name='mesh tally')\n", - "\n", - "# Print a little info about the mesh tally to the screen\n", - "print(tally)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the new Tally data retrieval API with pure NumPy" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[0.16617932]]\n", - "\n", - " [[0.06455926]]\n", - "\n", - " [[0.32266365]]\n", - "\n", - " [[0.13355528]]]\n" - ] - } - ], - "source": [ - "# Get the relative error for the thermal fission reaction \n", - "# rates in the four corner pins \n", - "data = tally.get_values(scores=['fission'],\n", - " filters=[openmc.MeshFilter, openmc.EnergyFilter], \\\n", - " filter_bins=[((1,1),(1,17), (17,1), (17,17)), \\\n", - " ((0., 0.625),)], value='rel_err')\n", - "print(data)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
mesh 1energy low [eV]energy high [eV]scoremeanstd. dev.
xyz
01110.00e+006.25e-01fission1.76e-042.92e-05
11110.00e+006.25e-01nu-fission4.28e-047.12e-05
21116.25e-012.00e+07fission6.67e-056.94e-06
31116.25e-012.00e+07nu-fission1.75e-041.71e-05
42110.00e+006.25e-01fission2.04e-043.80e-05
52110.00e+006.25e-01nu-fission4.96e-049.27e-05
62116.25e-012.00e+07fission5.76e-056.97e-06
72116.25e-012.00e+07nu-fission1.52e-041.91e-05
83110.00e+006.25e-01fission1.80e-043.15e-05
93110.00e+006.25e-01nu-fission4.38e-047.68e-05
103116.25e-012.00e+07fission7.19e-059.68e-06
113116.25e-012.00e+07nu-fission1.89e-042.49e-05
124110.00e+006.25e-01fission1.91e-043.67e-05
134110.00e+006.25e-01nu-fission4.66e-048.93e-05
144116.25e-012.00e+07fission6.78e-059.81e-06
154116.25e-012.00e+07nu-fission1.76e-042.44e-05
165110.00e+006.25e-01fission1.56e-042.32e-05
175110.00e+006.25e-01nu-fission3.81e-045.65e-05
185116.25e-012.00e+07fission6.28e-058.06e-06
195116.25e-012.00e+07nu-fission1.62e-042.05e-05
\n", - "
" - ], - "text/plain": [ - " mesh 1 energy low [eV] energy high [eV] score mean \\\n", - " x y z \n", - "0 1 1 1 0.00e+00 6.25e-01 fission 1.76e-04 \n", - "1 1 1 1 0.00e+00 6.25e-01 nu-fission 4.28e-04 \n", - "2 1 1 1 6.25e-01 2.00e+07 fission 6.67e-05 \n", - "3 1 1 1 6.25e-01 2.00e+07 nu-fission 1.75e-04 \n", - "4 2 1 1 0.00e+00 6.25e-01 fission 2.04e-04 \n", - "5 2 1 1 0.00e+00 6.25e-01 nu-fission 4.96e-04 \n", - "6 2 1 1 6.25e-01 2.00e+07 fission 5.76e-05 \n", - "7 2 1 1 6.25e-01 2.00e+07 nu-fission 1.52e-04 \n", - "8 3 1 1 0.00e+00 6.25e-01 fission 1.80e-04 \n", - "9 3 1 1 0.00e+00 6.25e-01 nu-fission 4.38e-04 \n", - "10 3 1 1 6.25e-01 2.00e+07 fission 7.19e-05 \n", - "11 3 1 1 6.25e-01 2.00e+07 nu-fission 1.89e-04 \n", - "12 4 1 1 0.00e+00 6.25e-01 fission 1.91e-04 \n", - "13 4 1 1 0.00e+00 6.25e-01 nu-fission 4.66e-04 \n", - "14 4 1 1 6.25e-01 2.00e+07 fission 6.78e-05 \n", - "15 4 1 1 6.25e-01 2.00e+07 nu-fission 1.76e-04 \n", - "16 5 1 1 0.00e+00 6.25e-01 fission 1.56e-04 \n", - "17 5 1 1 0.00e+00 6.25e-01 nu-fission 3.81e-04 \n", - "18 5 1 1 6.25e-01 2.00e+07 fission 6.28e-05 \n", - "19 5 1 1 6.25e-01 2.00e+07 nu-fission 1.62e-04 \n", - "\n", - " std. dev. \n", - " \n", - "0 2.92e-05 \n", - "1 7.12e-05 \n", - "2 6.94e-06 \n", - "3 1.71e-05 \n", - "4 3.80e-05 \n", - "5 9.27e-05 \n", - "6 6.97e-06 \n", - "7 1.91e-05 \n", - "8 3.15e-05 \n", - "9 7.68e-05 \n", - "10 9.68e-06 \n", - "11 2.49e-05 \n", - "12 3.67e-05 \n", - "13 8.93e-05 \n", - "14 9.81e-06 \n", - "15 2.44e-05 \n", - "16 2.32e-05 \n", - "17 5.65e-05 \n", - "18 8.06e-06 \n", - "19 2.05e-05 " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get a pandas dataframe for the mesh tally data\n", - "df = tally.get_pandas_dataframe(nuclides=False)\n", - "\n", - "# Set the Pandas float display settings\n", - "pd.options.display.float_format = '{:.2e}'.format\n", - "\n", - "# Print the first twenty rows in the dataframe\n", - "df.head(20)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Create a boxplot to view the distribution of\n", - "# fission and nu-fission rates in the pins\n", - "bp = df.boxplot(column='mean', by='score')" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Extract thermal nu-fission rates from pandas\n", - "fiss = df[df['score'] == 'nu-fission']\n", - "fiss = fiss[fiss['energy low [eV]'] == 0.0]\n", - "\n", - "# Extract mean and reshape as 2D NumPy arrays\n", - "mean = fiss['mean'].values.reshape((17,17))\n", - "\n", - "plt.imshow(mean, interpolation='nearest')\n", - "plt.title('fission rate')\n", - "plt.xlabel('x')\n", - "plt.ylabel('y')\n", - "plt.colorbar()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Analyze the cell+nuclides scatter-y2 rate tally**" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tally\n", - "\tID =\t2\n", - "\tName =\tcell tally\n", - "\tFilters =\tCellFilter\n", - "\tNuclides =\tU235 U238 \n", - "\tScores =\t['scatter']\n", - "\tEstimator =\ttracklength\n", - "\n" - ] - } - ], - "source": [ - "# Find the cell Tally with the StatePoint API\n", - "tally = sp.get_tally(name='cell tally')\n", - "\n", - "# Print a little info about the cell tally to the screen\n", - "print(tally)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellnuclidescoremeanstd. dev.
01U235scatter3.80e-021.33e-04
11U238scatter2.33e+008.12e-03
\n", - "
" - ], - "text/plain": [ - " cell nuclide score mean std. dev.\n", - "0 1 U235 scatter 3.80e-02 1.33e-04\n", - "1 1 U238 scatter 2.33e+00 8.12e-03" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get a pandas dataframe for the cell tally data\n", - "df = tally.get_pandas_dataframe()\n", - "\n", - "# Print the first twenty rows in the dataframe\n", - "df.head(20)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the new Tally data retrieval API with pure NumPy" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[0.00811746]\n", - " [0.00013266]]]\n" - ] - } - ], - "source": [ - "# Get the standard deviations the total scattering rate\n", - "data = tally.get_values(scores=['scatter'], \n", - " nuclides=['U238', 'U235'], value='std_dev')\n", - "print(data)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Analyze the distribcell tally**" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tally\n", - "\tID =\t3\n", - "\tName =\tdistribcell tally\n", - "\tFilters =\tDistribcellFilter\n", - "\tNuclides =\ttotal \n", - "\tScores =\t['absorption', 'scatter']\n", - "\tEstimator =\ttracklength\n", - "\n" - ] - } - ], - "source": [ - "# Find the distribcell Tally with the StatePoint API\n", - "tally = sp.get_tally(name='distribcell tally')\n", - "\n", - "# Print a little info about the distribcell tally to the screen\n", - "print(tally)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the new Tally data retrieval API with pure NumPy" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[0.04347272]]\n", - "\n", - " [[0.04671736]]\n", - "\n", - " [[0.04878286]]\n", - "\n", - " [[0.03059582]]\n", - "\n", - " [[0.04548096]]\n", - "\n", - " [[0.04288085]]\n", - "\n", - " [[0.02557663]]\n", - "\n", - " [[0.0419826 ]]\n", - "\n", - " [[0.05878954]]\n", - "\n", - " [[0.04217666]]]\n" - ] - } - ], - "source": [ - "# Get the relative error for the scattering reaction rates in\n", - "# the first 10 distribcell instances \n", - "data = tally.get_values(scores=['scatter'], filters=[openmc.DistribcellFilter],\n", - " filter_bins=[tuple(range(10))], value='rel_err')\n", - "print(data)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print the distribcell tally dataframe" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
level 1level 2level 3distribcellscoremeanstd. dev.
univcelllatunivcell
idididxyidid
55834271613279absorption6.26e-044.62e-05
55934271613279scatter8.73e-022.14e-03
56034281613280absorption6.15e-043.12e-05
56134281613280scatter8.06e-021.85e-03
56234291613281absorption6.36e-044.24e-05
56334291613281scatter7.59e-021.93e-03
564342101613282absorption5.30e-042.75e-05
565342101613282scatter6.82e-021.02e-03
566342111613283absorption4.67e-042.84e-05
567342111613283scatter6.42e-021.81e-03
568342121613284absorption4.52e-042.13e-05
569342121613284scatter5.64e-021.20e-03
570342131613285absorption3.85e-041.99e-05
571342131613285scatter4.86e-021.58e-03
572342141613286absorption2.84e-042.16e-05
573342141613286scatter3.91e-021.66e-03
574342151613287absorption2.17e-042.15e-05
575342151613287scatter3.02e-021.71e-03
576342161613288absorption1.50e-041.42e-05
577342161613288scatter1.89e-029.31e-04
\n", - "
" - ], - "text/plain": [ - " level 1 level 2 level 3 distribcell score \\\n", - " univ cell lat univ cell \n", - " id id id x y id id \n", - "558 3 4 2 7 16 1 3 279 absorption \n", - "559 3 4 2 7 16 1 3 279 scatter \n", - "560 3 4 2 8 16 1 3 280 absorption \n", - "561 3 4 2 8 16 1 3 280 scatter \n", - "562 3 4 2 9 16 1 3 281 absorption \n", - "563 3 4 2 9 16 1 3 281 scatter \n", - "564 3 4 2 10 16 1 3 282 absorption \n", - "565 3 4 2 10 16 1 3 282 scatter \n", - "566 3 4 2 11 16 1 3 283 absorption \n", - "567 3 4 2 11 16 1 3 283 scatter \n", - "568 3 4 2 12 16 1 3 284 absorption \n", - "569 3 4 2 12 16 1 3 284 scatter \n", - "570 3 4 2 13 16 1 3 285 absorption \n", - "571 3 4 2 13 16 1 3 285 scatter \n", - "572 3 4 2 14 16 1 3 286 absorption \n", - "573 3 4 2 14 16 1 3 286 scatter \n", - "574 3 4 2 15 16 1 3 287 absorption \n", - "575 3 4 2 15 16 1 3 287 scatter \n", - "576 3 4 2 16 16 1 3 288 absorption \n", - "577 3 4 2 16 16 1 3 288 scatter \n", - "\n", - " mean std. dev. \n", - " \n", - " \n", - "558 6.26e-04 4.62e-05 \n", - "559 8.73e-02 2.14e-03 \n", - "560 6.15e-04 3.12e-05 \n", - "561 8.06e-02 1.85e-03 \n", - "562 6.36e-04 4.24e-05 \n", - "563 7.59e-02 1.93e-03 \n", - "564 5.30e-04 2.75e-05 \n", - "565 6.82e-02 1.02e-03 \n", - "566 4.67e-04 2.84e-05 \n", - "567 6.42e-02 1.81e-03 \n", - "568 4.52e-04 2.13e-05 \n", - "569 5.64e-02 1.20e-03 \n", - "570 3.85e-04 1.99e-05 \n", - "571 4.86e-02 1.58e-03 \n", - "572 2.84e-04 2.16e-05 \n", - "573 3.91e-02 1.66e-03 \n", - "574 2.17e-04 2.15e-05 \n", - "575 3.02e-02 1.71e-03 \n", - "576 1.50e-04 1.42e-05 \n", - "577 1.89e-02 9.31e-04 " - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get a pandas dataframe for the distribcell tally data\n", - "df = tally.get_pandas_dataframe(nuclides=False)\n", - "\n", - "# Print the last twenty rows in the dataframe\n", - "df.tail(20)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
meanstd. dev.
count2.89e+022.89e+02
mean4.15e-042.29e-05
std2.33e-049.14e-06
min1.84e-053.31e-06
25%2.08e-041.58e-05
50%4.10e-042.24e-05
75%6.25e-042.93e-05
max8.87e-045.06e-05
\n", - "
" - ], - "text/plain": [ - " mean std. dev.\n", - " \n", - " \n", - "count 2.89e+02 2.89e+02\n", - "mean 4.15e-04 2.29e-05\n", - "std 2.33e-04 9.14e-06\n", - "min 1.84e-05 3.31e-06\n", - "25% 2.08e-04 1.58e-05\n", - "50% 4.10e-04 2.24e-05\n", - "75% 6.25e-04 2.93e-05\n", - "max 8.87e-04 5.06e-05" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Show summary statistics for absorption distribcell tally data\n", - "absorption = df[df['score'] == 'absorption']\n", - "absorption[['mean', 'std. dev.']].dropna().describe()\n", - "\n", - "# Note that the maximum standard deviation does indeed\n", - "# meet the 5e-5 threshold set by the tally trigger" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform a statistical test comparing the tally sample distributions for two categories of fuel pins." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mann-Whitney Test p-value: 0.3531165056829588\n" - ] - } - ], - "source": [ - "# Extract tally data from pins in the pins divided along y=-x diagonal \n", - "multi_index = ('level 2', 'lat',)\n", - "lower = df[df[multi_index + ('x',)] + df[multi_index + ('y',)] < 16]\n", - "upper = df[df[multi_index + ('x',)] + df[multi_index + ('y',)] > 16]\n", - "lower = lower[lower['score'] == 'absorption']\n", - "upper = upper[upper['score'] == 'absorption']\n", - "\n", - "# Perform non-parametric Mann-Whitney U Test to see if the \n", - "# absorption rates (may) come from same sampling distribution\n", - "u, p = scipy.stats.mannwhitneyu(lower['mean'], upper['mean'])\n", - "print('Mann-Whitney Test p-value: {0}'.format(p))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the symmetry implied by the y=-x diagonal ensures that the two sampling distributions are identical. Indeed, as illustrated by the test above, for any reasonable significance level (*e.g.*, $\\alpha$=0.05) one would **not reject** the null hypothesis that the two sampling distributions are identical.\n", - "\n", - "Next, perform the same test but with two groupings of pins which are not symmetrically identical to one another." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mann-Whitney Test p-value: 2.835784441937541e-42\n" - ] - } - ], - "source": [ - "# Extract tally data from pins in the pins divided along y=x diagonal\n", - "multi_index = ('level 2', 'lat',)\n", - "lower = df[df[multi_index + ('x',)] > df[multi_index + ('y',)]]\n", - "upper = df[df[multi_index + ('x',)] < df[multi_index + ('y',)]]\n", - "lower = lower[lower['score'] == 'absorption']\n", - "upper = upper[upper['score'] == 'absorption']\n", - "\n", - "# Perform non-parametric Mann-Whitney U Test to see if the \n", - "# absorption rates (may) come from same sampling distribution\n", - "u, p = scipy.stats.mannwhitneyu(lower['mean'], upper['mean'])\n", - "print('Mann-Whitney Test p-value: {0}'.format(p))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the asymmetry implied by the y=x diagonal ensures that the two sampling distributions are *not* identical. Indeed, as illustrated by the test above, for any reasonable significance level (*e.g.*, $\\alpha$=0.05) one would **reject** the null hypothesis that the two sampling distributions are identical." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/.pyenv/versions/3.7.0/lib/python3.7/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning: \n", - "A value is trying to be set on a copy of a slice from a DataFrame.\n", - "Try using .loc[row_indexer,col_indexer] = value instead\n", - "\n", - "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", - " after removing the cwd from sys.path.\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Extract the scatter tally data from pandas\n", - "scatter = df[df['score'] == 'scatter']\n", - "\n", - "scatter['rel. err.'] = scatter['std. dev.'] / scatter['mean']\n", - "\n", - "# Show a scatter plot of the mean vs. the std. dev.\n", - "scatter.plot(kind='scatter', x='mean', y='rel. err.', title='Scattering Rates')" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEWCAYAAABrDZDcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzt3Xl8VOXZ//HPNZOEHdnixiKIyq4IQRAFBRRxQ1ux7qJtpXYR26fVWvVnrW19rPqo1dZSq6gt7qJC3UBUBBVQQBEEXFCUiCKCAiJbZq7fH+eAMQQyJJk5Sc73/XrNKzNnvc7JzFxz3+c+923ujoiIxFci6gBERCRaSgQiIjGnRCAiEnNKBCIiMadEICISc0oEIiIxp0QgkgEzu9zM7ow6DpFsUCKQyJjZ4Wb2qpmtMbPVZvaKmfWp4jbPM7OXy0y7x8z+VJXtuvu17v7jqmxjR8zMzWy9mX1tZp+Y2U1mlsxw3SPNrDgbcUl8KBFIJMysKfAkcBvQAmgN/AHYFGVc5TGzvBzs5iB3bwwcAZwG/DAH+xQBlAgkOgcAuPsD7p5y9w3uPtnd39q6gJldYGaLzGydmS00s17h9MvMbEmp6d8Lp3cBxgCHhr+uvzKzUcBZwKXhtP+Gy+5tZuPNbKWZfWhmo0vt92oze9TMxpnZWuC8cNq4cH778Ff8SDP72My+MLMrSq3fwMzuNbMvw/gvzfRXu7u/D7wC9Cy1vfNLnYcPzOwn4fRGwDPA3uGxfR0eV6LUOVplZg+bWYtwnfrhca0Kz8/rZrbHLv/3pE5RIpCovAukwi/MY82seemZZnYqcDVwLtAUGA6sCmcvAQYAuxGUIsaZ2V7uvgi4EJjh7o3dvZm73wHcB1wfTjvRzBLAf4F5BCWRIcAvzeyYUiGcBDwKNAvXL8/hQKdw/avCRATwe6A9sC9wNHB2pifFzDqHx/Z+qcmfAyeE5+F84GYz6+Xu64FjgeXhsTV29+XARcDJBKWLvYEvgb+H2xoZnre2QMvwfG3IND6pm5QIJBLuvpbgi9SBfwErzWxiqV+nPyb48n7dA++7+0fhuo+4+3J3T7v7Q8B7wCG7sPs+QKG7X+Pum939gzCG00stM8Pdnwj3saMvyj+EJZl5BEnloHD6D4Br3f1Ldy8Gbs0gprlmth5YBEwFbt86w92fcvcl4Xl4CZhMkCx25ELgCncvdvdNBAl1RFjFtYUgAewXlsTmhP8LiTElAomMuy9y9/PcvQ3QneDX6y3h7LYEv/y3Y2bnmtmbYdXGV+G6rXZh1/sQVKd8VWoblwOlq0iWZbCdz0o9/wZoHD7fu8z6mWyrV7j+aUBfoNHWGWGJaWZ4Qf0r4Dh2frz7AI+XOrZFQIrg+P4DTAIeNLPlZna9meVnEJ/UYUoEUiO4+2LgHoIvdQi+PDuWXc7M9iH49f4LoKW7NwMWALZ1U+VtvszrZcCHYdXR1kcTdz9uJ+vsik+BNqVet81kpfAX/8PADOAqADOrB4wHbgT2CI/3aXZ+vMuAY8scX313/8Tdt7j7H9y9K9CfoMrp3Eoco9QhSgQSCTPrbGa/NrM24eu2wBnAzHCRO4HfmFlvC+wXJoFGBF9+K8P1zufb5AGwAmhjZgVlpu1b6vVrwDoz+214YTdpZt2r2nS1lIeB35lZczNrTZC0dsV1wAVmtidQANQjON4SMzsWGFpq2RVASzPbrdS0McCfw/OFmRWa2Unh80Fm1sOC5qlrCaqK0rt+iFKXKBFIVNYRVIHMCuvGZxL8sv81BNcBgD8D94fLPgG0cPeFwP8R/GpeAfQgaGWz1QvA28BnZvZFOO0uoGtYVfKEu6cIfgn3BD4EviBIPKW/TKviGqA43PYUgovOGTeLdff5wDTgEndfB4wmSC5fAmcCE0stuxh4APggPL69gb+Gy0w2s3UE57ZvuMqeYTxrCaqMXiKoLpIYMw1MI5JdZvZT4HR3PyLqWETKoxKBSDUzs73M7LCwPX8nglLO41HHJbIjubhjUiRuCoB/Ah2Ar4AHKdUcVKSmUdWQiEjMqWpIRCTmakXVUKtWrbx9+/ZRhyEiUqvMmTPnC3cvrGi5WpEI2rdvz+zZs6MOQ0SkVjGzjzJZTlVDIiIxp0QgIhJzSgQiIjFXK64RiEjtt2XLFoqLi9m4cWPUodQ59evXp02bNuTnV64jWSUCEcmJ4uJimjRpQvv27TGzileQjLg7q1atori4mA4dOlRqG6oaEpGc2LhxIy1btlQSqGZmRsuWLatU0lIiEJGcURLIjqqeVyUCEZGYUyIQkdho3LjxtudPP/00BxxwAB999BFXX301rVu3pmfPnuy///58//vfZ+HChduWPfLII+nUqRM9e/akZ8+ejBgxIorws0YXi6VK2l/21C6vs/S643dpWztaXqSynn/+eUaPHs2kSZPYZ599APjVr37Fb37zGwAeeughBg8ezPz58yksDHpouO+++ygqKoos5mxSiUBEYmXatGlccMEFPPnkk3TsuN2w2ACcdtppDB06lPvvvz/H0UVDJQIRyb1nLoPP5lfvNvfsAcdet9NFNm3axMknn8zUqVPp3LnzTpft1asXixcv3vb6rLPOokGDBgAcffTR3HDDDVWPuYZQIhCR2MjPz6d///7cdddd/PWvf93psmXHaqnLVUNKBCKSexX8cs+WRCLBww8/zJAhQ7j22mu5/PLLd7jsG2+8UWe/+MvSNQIRiZWGDRvy1FNPcd9993HXXXeVu8z48eOZPHkyZ5xxRo6ji4ZKBCISOy1atODZZ59l4MCB21oF3XzzzYwbN47169fTvXt3XnjhhW3z4LvXCFq1asWUKVMiiT0blAhEJDa+/vrrbc/btm3Lhx9+CMDw4cO5+uqrd7je1KlTsxxZtFQ1JCISc1lLBGY21sw+N7MFZaZfZGaLzextM7s+W/sXEZHMZLNEcA8wrPQEMxsEnAQc5O7dgBuzuH8REclA1hKBu08DVpeZ/FPgOnffFC7zebb2LyIimcn1NYIDgAFmNsvMXjKzPjta0MxGmdlsM5u9cuXKHIYoIhIvuU4EeUALoB9wCfCw7aAjbXe/w92L3L2odBMuERGpXrluPloMPObBvduvmVkaaAXoJ79IzFSm59qdyaSX2saNG3+nCek999zD7Nmz+dvf/saYMWNo2LAh5557brnrTp06lYKCAvr3719tMdcUuU4ETwCDgBfN7ACgAPgixzGIiGznwgsv3On8qVOn0rhx42pJBCUlJeTl1ZzbuLLZfPQBYAbQycyKzexHwFhg37BJ6YPASC/bs5OISASuvvpqbrwxaMh466230rVrVw488EBOP/10li5dypgxY7j55pvp2bMn06dPZ+nSpQwePJgDDzyQIUOG8PHHHwOwZMkS+vXrR48ePbjyyiu3DYYzdepUBgwYwPDhw+natSsAJ598Mr1796Zbt27ccccd22Jp3Lgxl1xyCd26deOoo47itdde48gjj2Tfffdl4sSJ1X7sWUtJ7r6jTjrOztY+RUR2ZsOGDfTs2XPb69WrVzN8+PDtlrvuuuv48MMPqVevHl999RXNmjXjwgsvpHHjxtsGrznxxBMZOXIkI0eOZOzYsYwePZonnniCiy++mIsvvpgzzjiDMWPGfGe7c+fOZcGCBXTo0AGAsWPH0qJFCzZs2ECfPn045ZRTaNmyJevXr2fw4MHccMMNfO973+PKK6/kueeeY+HChYwcObLcmKtCdxaLSGw0aNCAN998c9vjmmuuKXe5Aw88kLPOOotx48btsApnxowZnHnmmQCcc845vPzyy9umn3rqqQDb5m91yCGHbEsCEJQ8DjroIPr168eyZct47733ACgoKGDYsOA2rB49enDEEUeQn59Pjx49WLp0aeVPwA4oEYiIlPHUU0/x85//nLlz59KnTx9KSkqqZbuNGjXa9nzq1KlMmTKFGTNmMG/ePA4++GA2btwIBOMmbG1QmUgkqFev3rbn1RVLaUoEIiKlpNNpli1bxqBBg/jLX/7CmjVr+Prrr2nSpAnr1q3btlz//v158MEHgWDQmgEDBgDQr18/xo8fD7BtfnnWrFlD8+bNadiwIYsXL2bmzJlZPKqdqzmXrUUkVjJp7hmFVCrF2WefzZo1a3B3Ro8eTbNmzTjxxBMZMWIEEyZM4LbbbuO2227j/PPP54YbbqCwsJC7774bgFtuuYWzzz6bP//5zwwbNozddtut3P0MGzaMMWPG0KVLFzp16kS/fv1yeZjfYbWh0U5RUZHPnj076jCkHJVpC76jL4AdbaumfmHIrlm0aBFdunSJOoys++abb2jQoAFmxoMPPsgDDzzAhAkTsr7f8s6vmc1x9wqHWVOJQESkGs2ZM4df/OIXuDvNmjVj7NixUYdUISUCqXN2tWShkohUpwEDBjBv3ryow9glulgsIjlTG6qia6OqnlclAhHJifr167Nq1Solg2rm7qxatYr69etXehuqGhKRnGjTpg3FxcWoW/nqV79+fdq0aVPp9ZUIRCQn8vPzv3NXrdQcqhoSEYk5JQIRkZhTIhARiTklAhGRmMvmwDRjzezzcBCasvN+bWZuZq2ytX8REclMNksE9wDDyk40s7bAUODjLO5bREQylLVE4O7TgNXlzLoZuBTQXSUiIjVATu8jMLOTgE/cfd7WQRd2suwoYBRAu3btchCdSO6pXySpCXJ2sdjMGgKXA1dlsry73+HuRe5eVFhYmN3gRERiLJethjoCHYB5ZrYUaAPMNbM9cxiDiIiUkbOqIXefD+y+9XWYDIrc/YtcxSAiItvLZvPRB4AZQCczKzazH2VrXyIiUnlZKxG4+xkVzG+frX2LiEjmdGexiEjMKRGIiMScEoGISMwpEYiIxJwSgYhIzCkRiIjEnMYsltjYUT891bWdXe0fSKSmUIlARCTmlAhERGJOiUBEJOaUCEREYk6JQEQk5pQIRERiTolARCTmlAhERGIumwPTjDWzz81sQalpN5jZYjN7y8weN7Nm2dq/iIhkJpslgnuAYWWmPQd0d/cDgXeB32Vx/yIikoGsJQJ3nwasLjNtsruXhC9nEgxgLyIiEYryGsEPgWci3L+IiBBRp3NmdgVQAty3k2VGAaMA2rVrl6PIpCba1U7epPJ0ruMp5yUCMzsPOAE4y919R8u5+x3uXuTuRYWFhTmLT0QkbnJaIjCzYcClwBHu/k0u9y0iIuXLZvPRB4AZQCczKzazHwF/A5oAz5nZm2Y2Jlv7FxGRzGStRODuZ5Qz+a5s7U9ERCpHdxaLiMScEoGISMwpEYiIxJwSgYhIzCkRiIjEXCR3FotsZ9PX9E8soLMto6WtoT5b2EABq7wpS33P8LEHrt8uItVOiUCi9dl8eOVWWDSR+ws2AlDiCTZSQAM2kbRvbz5f6w15M92RN70jr6c7w+ZBUNAwqshF6gwlAonG5m9g8hUw+26o1xQOPodzX2nB/HQHvqQJYIDTkrXsYyvomFhOT1tCz8T7/Cwxkby8J9j85xt4w/fn1VQ3Xkl3Y57vxxa9pUV2mT41kntffQwPngmfLYB+P4UjfgsNmjFtetkOz4xV7MYq3425qQN4hCMBaMBG+iTeoX9iIf0TC7g47zF+ZeP5xusxI92VF9M9eTHVk09QH1UimVAikJzai1Vwz/GwYQ2c9Qjsf/Qub2MD9ZmWPohp6YMAaMrX9Ess4rDEAo5MzGNI/huQD++k24RJ4WBm+wGkSFb34YjUCUoEkjNNWc+4gmthw3o4dwK07lUt211LYyan+zA53Qdw9rVPGZR4g0GJN/lh8hkuzHuSld6UJ1OH8t/Uocz1/QmqnkQElAgkZ5wb88fQzj6HM5+stiSwPeMD35sPUntzV+p4GvMNAxLzOTE5gzOTL3B+3iSWpQt5KHUkD6UGsRINmy2iRCA5cX7yWYYm5/CHLefw+33652y/X9OQZ9J9eSbdlyZ8w9DEbL6XnM5v8h/h4rzHmJQuYlzqaGamu6BSgsSVEoFkXWtWcknew0xJHczdqWH8PqI41tGQ8emBjE8PpEPJp5yVnMKI5DROSM5iQbo9/ygZzjPpQ0jrXgWJGb3jJcuca/LvwYGrtpxPTfnV/aHvxZ9KzqHvpr/z2y0X0IBN/L3gVl4o+DVnJp+nHpujDlEkZ5QIJKsGJOYzJPkGN5eMYDmtog5nO5so4KHUII7efAM/2fxLvqIR1+bfxcv1LobpN8HGNVGHKJJ1GSUCM3vMzI43s4wTh5mNNbPPzWxBqWktzOw5M3sv/Nu8MkFLbeFckvcQxd6Kf6eGRh3MTqVJMCl9CCdv/iNnbL6CRel28Pwf4Obu8NxVsO6zqEMUyZpMv9hvB84E3jOz68ysUwbr3AMMKzPtMuB5d98feD58LXXUsMTrHJj4kJu3jGAz+VGHkyFjRrob5275HfxkGux3FLx6G9zSAyaOhlVLog5QpNpllAjcfYq7nwX0ApYCU8zsVTM738zK/YS7+zRgdZnJJwH3hs/vBU6uVNRSCzi/yHuCJem9eDx9eNTBVM5eB8Gpd8NFc+Dgs2Heg3Bbb/6efwv9EgsBr3ATIrVBxq2GzKwlcDZwDvAGcB9wODASwnv/K7aHu38aPv8M2GMn+xsFjAJo165dpmFKlrS/rGz3Dzt3aGIh3RNL+e2WC2p/K5wW+8IJN8MRl8GsMRw+fQzHJ1/jg/SePJAazGOpAaxit10+R7lQXTHtaDtLrzu+WpaXaGV6jeBxYDrQEDjR3Ye7+0PufhHQuDI7dndnJz+p3P0Ody9y96LCQvUZU9uMSgZ38z6ROizqUKpPkz3gqN9zyKbb+dXmn/IFu3FF/v3Mqvdz/pN/LWckn6cFa6OOUmSXZVoi+Je7P116gpnVc/dN7l60C/tbYWZ7ufunZrYX8PkurCu1xL62nEHJedy0ZQSbKIg6nGq3iQIeTw/g8c0D2M+KOSn5KickZvC/+Xfxx7y7mZnuwuR0EZNTRXxGy6jDFalQpmX2P5UzbUYl9jeRoCqJ8O+ESmxDargfJKdS4gkeSA2OOpSse9/b8H8lP2DQ5ps4btO1/DN1AnvZaq7Jv5eZ9S9iQsGV/Cz5BPtZMbqmIDXVTksEZrYn0BpoYGYH8+3dQE0Jqol2tu4DBNcOWplZMfB74DrgYTP7EfAR8IMqRS81Tj4lnJKcxvPpXjHrx8dY6O1ZWNKeGzidjvYJQxNzOCb5OpfmP8ylPMwH6T2DzvFSvXnD99Noa1JjVFQ1dAxwHtAGuKnU9HXA5Ttb0d3P2MGsIZkGJ7XP4MRcCm0tD6QGRR1KpJZ4a/6Ras0/UsPZg9UcnZzD0MRsfpR8mgvz/svn3oznUr2ZnC5iRrprLWpeK3XRThOBu98L3Gtmp7j7+BzFJLXY6ckX+dRbbBsrQGAFLRiXOppxqaNpynqOTLzJMcnXOTn5MmflPc8ab8j41EDuSw1hibeOOlyJoYqqhs5293FAezP7n7Lz3f2mclaTmCrkKwYm3uL21Em1v8lolqylERPThzExfRj12Ez/xNt8Pzmds5PP8cO8Z5mR6sq41FGQGgpJlRIkNyqqGmoU/q1UE1GJl2OTs0iaMyGVu26ma7NNFPBi+mBeTB9MK9ZwavIlzkw+z98LboWbH4be5wWPpntFHarUcRVVDf0z/PuH3IQjtdmJyRksSrflfW8TdSi1zhfsxj9Sw/ln6gSOSMzj7j3fhJeug+k3QpfhcMgoaNcv6jCljsr0hrLrzaypmeWb2fNmttLMzs52cFJ77MUq+iTe5cnUoVGHUqulSfBi+mA4+1G4aC70vRCWPA93D4Mxh3N68gUasDHqMKWOybQid6i7rwVOIOhraD/gkmwFJbXP8cmZADyZ1q/WatOyIxzzZ/ifxXDirYBxXf6dzKr3C67M+w+d7WN0b4JUh0zvLN663PHAI+6+xqxmDDAiNcMJyZm8le7AR75n1KFUmxrTd1BBQ+g9EnqdyymX38zIvMmMTE7mx3nP8H56b55M9+Oo3xWrSk4qLdNE8KSZLQY2AD81s0JQ+VQCu/MlPRNLuH6L7g/MKjPmeCfmbOlEC9ZybPI1TkjMZHTycX6Z9xhL0nsxKd2HSaki5nlHaspocFLzZZQI3P0yM7seWOPuKTNbT9CltAhDknMBmJLuHXEk8bGaptyXOor7UkdRyJcMS77OMYnXGZV8kp/lTWS5t2ByqohJ6T68lu5MimTUIUsNtiuD13cmuJ+g9Dr/ruZ4pBY6KjGXj9K7866qJiKxkub8JzWU/6SGshtfMyQxl2HJ1zk9+SLn5U3mS2/M8+lePJvqw/R0jzrZEaBUTUaJwMz+A3QE3gRS4WRHiSD2GrCRwxMLgpugVBURuTU05rH0QB5LD6QBGxmYeItjkrM5OjGbEclprPMG3Jc6ijtLjuMLdos6XKkhMi0RFAFdwzEERLYZkJhPPdvClHSvqEORMjZQn0npQ5iUPoQ8SuiXWMRpyRe5IPkk5yWf5Z+pE7m9ZLhKCJJx89EFQN1pDiLV5qjEXNZ4Q15PZzKMtUSlhDxeTvfgoi2jGbL5Riani7g47zGeK7iEXvZu1OFJxDJNBK2AhWY2ycwmbn1kMzCp+Yw0g5NvMDXdk5JdutwkUVrqezF6y0WcvvlKHOPhgmv4aXIiuichvjL99F6dzSCkdupqH9HK1jI1pZ5Ga6OZ6a6csPla/jf/Tn6b/yDtbAVXlvxQLYxiKNPmoy+Z2T7A/u4+xcwaQuXfLWb2K+DHBD9B5gPnu7vuS6hlBibmA/ByukfEkUhlraMhv9hyER/4nozOe4KWtpafbblYJbyYybSvoQuAR4F/hpNaA09UZodm1hoYDRS5e3eChHJ6ZbYl0RqQeIuF6X1iNhJZXWTcVPIDrtoykqHJOdyYPwYjHXVQkkOZXiP4OXAYsBbA3d8Ddq/CfvMIhr/MIxjycnkVtiURaMBGihLvME2lgTrj36lj+MuW0zk5+SpX5N0XdTiSQ5mW/za5++at/QuFX+CVurLk7p+Y2Y3AxwRdVkx298lllzOzUcAogHbt2lVmV5JFfROLKLAU0yuRCGpMHz6ynX+khrO7fcmP855hQboDT6QPjzokyYFMSwQvmdnlBL/ijwYeAf5bmR2aWXOC7ik6AHsDjcrr0trd73D3IncvKiwsrMyuJIsGJuazwQuYrWajdc6fS85iZroL1+X/i662NOpwJAcyTQSXASsJLuz+BHgauLKS+zwK+NDdV7r7FuAxQENa1TIDE28xK91FNyPVQSXk8fPNo1lDI27Ov516bI46JMmyjBKBu6cJLg7/zN1HuPu/qnCX8cdAPzNraEFd0xBgUSW3JRHYmy/YL7G8UtVCUjusYjcu3fITOiWK+VXeo1GHI1m200RggavN7AvgHeCdcHSyqyq7Q3efRdACaS5BCSMB3FHZ7UnuHZ4Mmo1OSx8YcSSSTS+lD2JcyRBGJZ/iYHsv6nAkiyoqEfyKoLVQH3dv4e4tgL7AYeG9AJXi7r93987u3t3dz3H3TZXdluTegMR8PvPmvOetow5FsuzakrNYQXP+mH83CTUprbMqSgTnAGe4+4dbJ7j7B8DZwLnZDExqKqdfYiGvpruh3kbrvm+oz5+2nE33xFLOTD4fdTiSJRUlgnx3/6LsRHdfCeRnJySpyTracgptLTPTXaIORXLkqXRfXk5145K8h2jGuqjDkSyoKBHsrLmAmhLE0KGJhUDQT43EhXFNybk0YQMX5lWq1bjUcBUlgoPMbG05j3WAmozEUL/EIpZ7Cz72qtxYLrXNu96Wx9OHc15yEnuwOupwpJrtNBG4e9Ldm5bzaOLuqhqKHadvYmFYGtD1gbi5uWQECdKMzns86lCkmmV6Q5nItusDM1QtFEvFXsh9qaM4Lfki7WxF1OFINVIikIx9e31AF4rj6vaS4aRIMir5ZNShSDVSp+OSsX6JRXziLVmm6wNZV1M75ltJcx5NDeTU5DT+WnJKjY1Tdo1KBJKhrdcHuqDrA/F2R+p48ijhh3nPRB2KVBMlAsnIfvZJeP+Arg/E3Ue+J0+n+3JWcgpN+CbqcKQaKBFIRvolgn4BdX1AAMaUDKepbeC05ItRhyLVQIlAMtIvsVDXB2Sbt709r6U7cU7yOQ1rWQcoEUjF3OmXWKTrA/Id/y4Zyj6JzzkyMS/qUKSKlAikYivfoZWuD0gZk9J9WOHNGJncbqRZqWWUCKRiS6cDuj4g37WFPO4vGcKRyXm0t0+jDkeqQIlAKrb0ZV0fkHLdnxrMFk9yTnJK1KFIFUSSCMysmZk9amaLzWyRmR0aRRySAXdY+rKuD0i5VtKcSek+nJKcprGNa7GoSgR/BZ51987AQWjM4ppr5TvwzRe6PiA79GBqEM1sPUcn5kQdilRSzhOBme0GDATuAnD3ze7+Va7jkAyF1wdm6fqA7MCr6W4Ueyt+kJwadShSSVH0NdQBWAncbWYHAXOAi919femFzGwUMAqgXbt2OQ8yrsr2HfO3/EfpldD4A7JjaRKMTw3kouTjtGYln1AYdUiyi6KoGsoDegH/cPeDgfXAZWUXcvc73L3I3YsKC/XGiobTN7EoLA3o+oDs2COpI0iYc0pyetShSCVEkQiKgWJ3nxW+fpQgMUgNE4w/sEbVQlKhYi/k5VQ3Tk2+pDuNa6GcJwJ3/wxYZmadwklDgIW5jkMq1jexGND1AcnMw6kjaZtYSf/E21GHIrsoqlZDFwH3mdlbQE/g2ojikJ3om1jECm/Gh75n1KFILTAp3Ye13pDvq3qo1olkYBp3fxMoimLfkildH5Bds4kCnk4dwgnJmVzBJjZSL+qQJEO6s1jKtY+tYE/7UtVCsksmpA+jsW3UPQW1jBKBlEvjD0hlzEx3Ybm34OTkK1GHIrtAiUDK1TexiJXelCW+d9ShSC3iJJiY6s/AxFs0Z23U4UiGlAikHLo+IJU3IXUY+Zbi+OSsiheWGkGJQLbTxlbS2lbp+oBUyiJvx+J0W76XfDnqUCRDSgSyna3XB5QIpHKMCanD6J14j7a2IupgJANKBLKdvraI1d6Y97x11KFILTUxFfQsf1Li1YgjkUwoEch2+iUW8Vq6C663h1TSJxQyK905rB7yqMORCuiTLt+xN1/QNrEGu/QFAAAOiElEQVRSzUalyp5IHUbHxKd0s4+iDkUqoEQg39FX1wekmjyTOoTNnmS47imo8ZQI5DsOTSzkS2/MYm8bdShSy31FE15KH8Tw5Az1SFrDKRHIt9w5LLmAGemuuj4g1WJiqj972WoOsXeiDkV2Qp92+dbqD2htq3g13S3qSKSOmJLuxXqvx0mqHqrRlAjkWx9MBeCVdPdo45A6YwP1mZwu4rjkLPIpiToc2QElAvnWhy+x3Fto/AGpVhNS/Wlm6zkiMS/qUGQHIksEZpY0szfM7MmoYpBS0mn4cDqvpLqj/oWkOr2c7sFqb6zqoRosyhLBxcCiCPcvpa2YDxtWq1pIql0JeTyV6sdRibmwaV3U4Ug5IkkEZtYGOB64M4r9SznC6wO6UCzZMCHVnwa2GRY/HXUoUo6oSgS3AJfCjhsXm9koM5ttZrNXrlyZu8ji6oOXoFUnPqd51JFIHTTHD6DYW8H8R6IORcqR80RgZicAn7v7Tseyc/c73L3I3YsKCwtzFF1MlWyGj2fAvkdEHYnUUVsHrGHJC7D+i6jDkTKiKBEcBgw3s6XAg8BgMxsXQRyyVfFrsOUb6KBEINkzIdUfPAVvPx51KFJGzhOBu//O3du4e3vgdOAFdz8713FIKe89B4k86DAw6kikDnvH28HuXWH+o1GHImXoPgKB96dAu0OhftOoI5G6rscIWDYTvlSPpDVJpInA3ae6+wlRxhB7az6BFQtgv6OijkTioPspwd8F46ONQ75DJYK4e39K8Hf/odHGIfHQvD207avqoRpGiSDu3n8OmraG3TX+gORIj1Ph87dhxdtRRyIhJYI4S22BJVODaiFTtxKSI11PBkuqVFCDKBHE2cczYfM62P/oqCOROGlcCB0HBYkgrQFragIlgjh7/zlI5Ov+Acm9HqfCmo+De1gkckoEcfbOM7CPmo1KBDofD3n11eVEDaFEEFcr34Ev3oUuw6OOROKoXhPodGxwl3FqS9TRxJ4SQVwt+m/wt/Px0cYh8dXjB/DNqm0930p0lAjiavGT0Lo3NN076kgkrvY7Cuo3g7ceijqS2FMiiKOvlsHyN6DLiVFHInGWVxB0ObFwInyzOupoYk2JII4WPxX87axEIBHrfR6kNsFbD0cdSawpEcTRov9CYWdotV/UkUjc7dkD9u4Fc+4B96ijiS0lgrhZuxw+egW6fS/qSEQCvc+DlYtgme4piIoSQdzMfxTw4IYekZqg+ylQ0Bjm3ht1JLGlRBA38x8OWgu17Bh1JCKBeo2Di8YLHoMNX0UdTSxFMWZxWzN70cwWmtnbZnZxrmOIrc8Xw2fzVRqQmqf3eVCyQU1JIxJFiaAE+LW7dwX6AT83s64RxBE/8x8GS0C370cdich37X0wtC6CWWPUEV0Eohiz+FN3nxs+XwcsAlrnOo7YSZXAm/dDxyHQZI+ooxHZ3qE/g9UfwLvPRh1J7ER6jcDM2gMHA7PKmTfKzGab2eyVK1fmOrS6571JsO5TKDo/6khEytflJGjaBmbeHnUksRNZIjCzxsB44JfuvrbsfHe/w92L3L2osLAw9wHWNbPvhiZ7wf7HRB2JSPmSedB3FCydDp++FXU0sRJJIjCzfIIkcJ+7PxZFDLHy1cfB2MQHnxN82ERqql4jIb8RvHpr1JHEShSthgy4C1jk7jflev+xNHtsMBRlr3OjjkRk5xo0gz4/ggXj4Yv3oo4mNqIoERwGnAMMNrM3w8dxEcQRD5vWwetjgw7mmrWNOhqRivUfHQxaM+2GqCOJjZzXE7j7y4BGSs+Vuf+GTWugv27XkFqicSEU/TC4aHzEb3XzYw7ozuK6LLUFZtwO+xwObXpHHY1I5vqPhmQBvPSXqCOJBSWCuuyth2BtMRw2OupIRHZNkz2g74XBe/iTuVFHU+cpEdRVJZtg6nVBF7/7D406GpFdN+B/oGErmHSFuqjOMiWCumr2WFizDIZcFbQYEqlt6u8Ggy6Hj1+FhROijqZOUyKoi75ZDS9dDx0GQsdBUUcjUnm9RsIe3eHZy2DjmqijqbOUCOqi5/8QfGiGXRd1JCJVk8yD4bfB1yvguauijqbOUiKoa5a9BnPuhX4/hT26RR2NSNW17gWH/jwYznLJC1FHUycpEdQlm76Gx0bBbm2C9tcidcWRl0OrTsH7e91nUUdT5ygR1CXP/ha+XArf+yfUbxp1NCLVp6Ah/OBe2LweHv1R0K26VBslgrri9TvhjXFBk7v2h0UdjUj1270LHH8TfPQyPPlLNSmtRuqKsi54fwo8fWnQxfSgK6KORiR7ep4Bq96H6TcG3aoP1vu9OigR1HYfvAQPngW7d4VT7oREMuqIRLJr8JXw9Wcw7XpIl+hemWqgRFCbLRgPj/806JTr3Am6LiDxYAYn3gqJPHj5Jlj/ORz3f5BfP+rIai0lgtpoy0Z48U/w6m3Qth+cfj80ahl1VCK5k0jCCbdAo92DksGn82DEPdBqv6gjq5V0sbi2+XAa/GtQkAR6nw8jJyoJSDyZBdcIzngI1hTDPw6FF/4UtCySXaJEUBukU/DOs/Dvk+HeE4O7hs98BE68BfLqRR2dSLQ6DYOfzYSuJweD2dzcHab+BdYujzqyWiOSqiEzGwb8FUgCd7q7+kIoa8NX8PGMoEXQO8/A2k+CYvDRf4RDLoD8BlFHKFJzNNkTTvlX8NmY/n8w9VqY+r/Q/nA4YFjwd88eakyxAzlPBGaWBP4OHA0UA6+b2UR3X5jrWDKyta2yO+Cl2i6X97yiZT3oHnrz10Hxdevjm1XBr5d1nwYDzX+2ANZ8HKya3yjoPO6Ya6HTcZBXkIODFqml2h4CZz4Eq5bAWw/D24/B5LCJaX5DaLU/FHaGZu2g8R7QeHdo2DKYV9Ao+JvfMChpJ5JgCbBk+LzutkyKokRwCPC+u38AYGYPAicB1Z8Inv1d0D8J7PzLeUfzc62gSdA9RNs+UHQ+tO4N7fqp+kdkV7XsCIN+FzzWLoelr8DyN2Dl4uD5ukfA07u+XQuTQyJJRiPuZpQ8Kljm9HHQcXAm0VVaFImgNbCs1OtioG/ZhcxsFDAqfPm1mb2zi/tpBXxRqQgjsxb4BJiVqx3WwnOUczpHFcv4HFk8R56s2nvoyiFV2fc+mSxUY5uPuvsdwB2VXd/MZrt7UTWGVOfoHFVM56hiOkc7VxvOTxSthj4B2pZ63SacJiIiEYgiEbwO7G9mHcysADgdmBhBHCIiQgRVQ+5eYma/ACYRNB8d6+5vZ2FXla5WihGdo4rpHFVM52jnavz5MVdXriIisaY7i0VEYk6JQEQk5mp1IjCzFmb2nJm9F/5tvoPlRobLvGdmI0tNn2pm75jZm+Fj99xFn11mNiw8tvfN7LJy5tczs4fC+bPMrH2peb8Lp79jZsfkMu5cqez5MbP2Zrah1HtmTK5jz5UMztFAM5trZiVmNqLMvHI/c3VNFc9RqtT7KNoGM+5eax/A9cBl4fPLgL+Us0wL4IPwb/PwefNw3lSgKOrjyMJ5SQJLgH2BAmAe0LXMMj8DxoTPTwceCp93DZevB3QIt5OM+phq0PlpDyyI+hhqyDlqDxwI/BsYUWr6Dj9zdelRlXMUzvs66mPY+qjVJQKCrinuDZ/fC5xczjLHAM+5+2p3/xJ4DhiWo/iisq0bD3ffDGztxqO00ufuUWCImVk4/UF33+TuHwLvh9urS6pyfuKiwnPk7kvd/S2gbF8NcfnMVeUc1Si1PRHs4e6fhs8/A/YoZ5nyurRoXer13WHR7P/VoQ96Rcf8nWXcvQRYA7TMcN3arirnB6CDmb1hZi+Z2YBsBxuRqrwP4vAegqofZ30zm21mM82svB+xOVNju5jYysymAHuWM+s7o1a7u5vZrraFPcvdPzGzJsB44ByCIpzIjnwKtHP3VWbWG3jCzLq5+9qoA5NaZ5/w+2df4AUzm+/uS6IIpMaXCNz9KHfvXs5jArDCzPYCCP9+Xs4mdtilhbtv/bsOuJ+6UwWSSTce25YxszxgN2BVhuvWdpU+P2GV2SoAd59DUEd8QNYjzr2qvA/i8B6CKh5nqe+fDwiuVx5cncHtihqfCCowEdjaImEkMKGcZSYBQ82sediqaCgwyczyzKwVgJnlAycAC3IQcy5k0o1H6XM3AnjBgytYE4HTw1YzHYD9gddyFHeuVPr8mFlhOKYG4S+5/QkuhtY1VekKptzPXJbijFKlz1F4buqFz1sBh5GNrvgzFfXV6qo8COpsnwfeA6YALcLpRQQjn21d7ocEFz3fB84PpzUC5gBvAW8TjpgW9TFV47k5DniX4BfrFeG0a4Dh4fP6wCPhOXkN2LfUuleE670DHBv1sdSk8wOcEr5f3gTmAidGfSwRnqM+BPXi6wlKk2+XWne7z1xdfFT2HAH9gfkELY3mAz+K8jjUxYSISMzV9qohERGpIiUCEZGYUyIQEYk5JQIRkZhTIhARiTklApFSzMzNbFyp13lmttLMnowyLpFsUiIQ+a71QHczaxC+Ppq6eVesyDZKBCLbexo4Pnx+BvDA1hlm1sjMxprZa2HHcyeF09ub2fSw7/m5ZtY/nH5kOO7Fo2a22Mzuq0OdG0odoUQgsr0HCbrZqE/Ql/ysUvOuIOhu4hBgEHCDmTUi6OfqaHfvBZwG3FpqnYOBXxKM9bAvQXcCIjVGje99VCTX3P2tcESyMwhKB6UNBYab2W/C1/WBdsBy4G9m1hNI8d2O6F5z92IAM3uTYLCSl7MVv8iuUiIQKd9E4EbgSL4dhwDAgFPc/Z3SC5vZ1cAK4CCCkvbGUrM3lXqeQp87qWFUNSRSvrHAH9x9fpnpk4CLttbzm9nWroN3Az519zTBuBbJnEUqUkVKBCLlcPdid7+1nFl/BPKBt8zs7fA1wO3ASDObB3QmaH0kUiuo91ERkZhTiUBEJOaUCEREYk6JQEQk5pQIRERiTolARCTmlAhERGJOiUBEJOb+P473f3S9Fk+fAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Plot a histogram and kernel density estimate for the scattering rates\n", - "scatter['mean'].plot(kind='hist', bins=25)\n", - "scatter['mean'].plot(kind='kde')\n", - "plt.title('Scattering Rates')\n", - "plt.xlabel('Mean')\n", - "plt.legend(['KDE', 'Histogram'])" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/pincell.ipynb b/examples/jupyter/pincell.ipynb deleted file mode 100644 index e50a4a322..000000000 --- a/examples/jupyter/pincell.ipynb +++ /dev/null @@ -1,1564 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook is intended to demonstrate the basic features of the Python API for constructing input files and running OpenMC. In it, we will show how to create a basic reflective pin-cell model that is equivalent to modeling an infinite array of fuel pins. If you have never used OpenMC, this can serve as a good starting point to learn the Python API. We highly recommend having a copy of the [Python API reference documentation](https://docs.openmc.org/en/stable/pythonapi/index.html) open in another browser tab that you can refer to." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Defining Materials\n", - "\n", - "Materials in OpenMC are defined as a set of nuclides with specified atom/weight fractions. To begin, we will create a material by making an instance of the `Material` class. In OpenMC, many objects, including materials, are identified by a \"unique ID\" that is simply just a positive integer. These IDs are used when exporting XML files that the solver reads in. They also appear in the output and can be used for identification. Since an integer ID is not very useful by itself, you can also give a material a `name` as well." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Material\n", - "\tID =\t1\n", - "\tName =\tuo2\n", - "\tTemperature =\tNone\n", - "\tDensity =\tNone [sum]\n", - "\tS(a,b) Tables \n", - "\tNuclides \n", - "\n" - ] - } - ], - "source": [ - "uo2 = openmc.Material(1, \"uo2\")\n", - "print(uo2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On the XML side, you have no choice but to supply an ID. However, in the Python API, if you don't give an ID, one will be automatically generated for you:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Material\n", - "\tID =\t2\n", - "\tName =\t\n", - "\tTemperature =\tNone\n", - "\tDensity =\tNone [sum]\n", - "\tS(a,b) Tables \n", - "\tNuclides \n", - "\n" - ] - } - ], - "source": [ - "mat = openmc.Material()\n", - "print(mat)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that an ID of 2 was automatically assigned. Let's now move on to adding nuclides to our `uo2` material. The `Material` object has a method `add_nuclide()` whose first argument is the name of the nuclide and second argument is the atom or weight fraction." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on method add_nuclide in module openmc.material:\n", - "\n", - "add_nuclide(nuclide, percent, percent_type='ao') method of openmc.material.Material instance\n", - " Add a nuclide to the material\n", - " \n", - " Parameters\n", - " ----------\n", - " nuclide : str\n", - " Nuclide to add, e.g., 'Mo95'\n", - " percent : float\n", - " Atom or weight percent\n", - " percent_type : {'ao', 'wo'}\n", - " 'ao' for atom percent and 'wo' for weight percent\n", - "\n" - ] - } - ], - "source": [ - "help(uo2.add_nuclide)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that by default it assumes we want an atom fraction." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Add nuclides to uo2\n", - "uo2.add_nuclide('U235', 0.03)\n", - "uo2.add_nuclide('U238', 0.97)\n", - "uo2.add_nuclide('O16', 2.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to assign a total density to the material. We'll use the `set_density` for this." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "uo2.set_density('g/cm3', 10.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You may sometimes be given a material specification where all the nuclide densities are in units of atom/b-cm. In this case, you just want the density to be the sum of the constituents. In that case, you can simply run `mat.set_density('sum')`.\n", - "\n", - "With UO2 finished, let's now create materials for the clad and coolant. Note the use of `add_element()` for zirconium." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=2.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "zirconium = openmc.Material(2, \"zirconium\")\n", - "zirconium.add_element('Zr', 1.0)\n", - "zirconium.set_density('g/cm3', 6.6)\n", - "\n", - "water = openmc.Material(3, \"h2o\")\n", - "water.add_nuclide('H1', 2.0)\n", - "water.add_nuclide('O16', 1.0)\n", - "water.set_density('g/cm3', 1.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "An astute observer might now point out that this water material we just created will only use free-atom cross sections. We need to tell it to use an $S(\\alpha,\\beta)$ table so that the bound atom cross section is used at thermal energies. To do this, there's an `add_s_alpha_beta()` method. Note the use of the GND-style name \"c_H_in_H2O\"." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "water.add_s_alpha_beta('c_H_in_H2O')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When we go to run the transport solver in OpenMC, it is going to look for a `materials.xml` file. Thus far, we have only created objects in memory. To actually create a `materials.xml` file, we need to instantiate a `Materials` collection and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "mats = openmc.Materials([uo2, zirconium, water])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that `Materials` is actually a subclass of Python's built-in `list`, so we can use methods like `append()`, `insert()`, `pop()`, etc." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "mats = openmc.Materials()\n", - "mats.append(uo2)\n", - "mats += [zirconium, water]\n", - "isinstance(mats, list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we can create the XML file with the `export_to_xml()` method. In a Jupyter notebook, we can run a shell command by putting `!` before it, so in this case we are going to display the `materials.xml` file that we created." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "mats.export_to_xml()\n", - "!cat materials.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Element Expansion\n", - "\n", - "Did you notice something really cool that happened to our Zr element? OpenMC automatically turned it into a list of nuclides when it exported it! The way this feature works is as follows:\n", - "\n", - "- First, it checks whether `Materials.cross_sections` has been set, indicating the path to a `cross_sections.xml` file.\n", - "- If `Materials.cross_sections` isn't set, it looks for the `OPENMC_CROSS_SECTIONS` environment variable.\n", - "- If either of these are found, it scans the file to see what nuclides are actually available and will expand elements accordingly.\n", - "\n", - "Let's see what happens if we change O16 in water to elemental O." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "water.remove_nuclide('O16')\n", - "water.add_element('O', 1.0)\n", - "\n", - "mats.export_to_xml()\n", - "!cat materials.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that now O16 and O17 were automatically added. O18 is missing because our cross sections file (which is based on ENDF/B-VII.1) doesn't have O18. If OpenMC didn't know about the cross sections file, it would have assumed that all isotopes exist." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### The `cross_sections.xml` file\n", - "\n", - "The `cross_sections.xml` tells OpenMC where it can find nuclide cross sections and $S(\\alpha,\\beta)$ tables. It serves the same purpose as MCNP's `xsdir` file and Serpent's `xsdata` file. As we mentioned, this can be set either by the `OPENMC_CROSS_SECTIONS` environment variable or the `Materials.cross_sections` attribute.\n", - "\n", - "Let's have a look at what's inside this file:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " ...\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ] - } - ], - "source": [ - "!cat $OPENMC_CROSS_SECTIONS | head -n 10\n", - "print(' ...')\n", - "!cat $OPENMC_CROSS_SECTIONS | tail -n 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Enrichment\n", - "\n", - "Note that the `add_element()` method has a special argument `enrichment` that can be used for Uranium. For example, if we know that we want to create 3% enriched UO2, the following would work:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "uo2_three = openmc.Material()\n", - "uo2_three.add_element('U', 1.0, enrichment=3.0)\n", - "uo2_three.add_element('O', 2.0)\n", - "uo2_three.set_density('g/cc', 10.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Defining Geometry\n", - "\n", - "At this point, we have three materials defined, exported to XML, and ready to be used in our model. To finish our model, we need to define the geometric arrangement of materials. OpenMC represents physical volumes using constructive solid geometry (CSG), also known as combinatorial geometry. The object that allows us to assign a material to a region of space is called a `Cell` (same concept in MCNP, for those familiar). In order to define a region that we can assign to a cell, we must first define surfaces which bound the region. A *surface* is a locus of zeros of a function of Cartesian coordinates $x$, $y$, and $z$, e.g.\n", - "\n", - "- A plane perpendicular to the x axis: $x - x_0 = 0$\n", - "- A cylinder parallel to the z axis: $(x - x_0)^2 + (y - y_0)^2 - R^2 = 0$\n", - "- A sphere: $(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0$\n", - "\n", - "Between those three classes of surfaces (planes, cylinders, spheres), one can construct a wide variety of models. It is also possible to define cones and general second-order surfaces (tori are not currently supported).\n", - "\n", - "Note that defining a surface is not sufficient to specify a volume -- in order to define an actual volume, one must reference the half-space of a surface. A surface *half-space* is the region whose points satisfy a positive or negative inequality of the surface equation. For example, for a sphere of radius one centered at the origin, the surface equation is $f(x,y,z) = x^2 + y^2 + z^2 - 1 = 0$. Thus, we say that the negative half-space of the sphere, is defined as the collection of points satisfying $f(x,y,z) < 0$, which one can reason is the inside of the sphere. Conversely, the positive half-space of the sphere would correspond to all points outside of the sphere.\n", - "\n", - "Let's go ahead and create a sphere and confirm that what we've told you is true." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "sph = openmc.Sphere(r=1.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that by default the sphere is centered at the origin so we didn't have to supply `x0`, `y0`, or `z0` arguments. Strictly speaking, we could have omitted `R` as well since it defaults to one. To get the negative or positive half-space, we simply need to apply the `-` or `+` unary operators, respectively.\n", - "\n", - "(NOTE: Those unary operators are defined by special methods: `__pos__` and `__neg__` in this case)." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "inside_sphere = -sph\n", - "outside_sphere = +sph" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's see if `inside_sphere` actually contains points inside the sphere:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True False\n", - "False True\n" - ] - } - ], - "source": [ - "print((0,0,0) in inside_sphere, (0,0,2) in inside_sphere)\n", - "print((0,0,0) in outside_sphere, (0,0,2) in outside_sphere)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Everything works as expected! Now that we understand how to create half-spaces, we can create more complex volumes by combining half-spaces using Boolean operators: `&` (intersection), `|` (union), and `~` (complement). For example, let's say we want to define a region that is the top part of the sphere (all points inside the sphere that have $z > 0$." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "z_plane = openmc.ZPlane(z0=0)\n", - "northern_hemisphere = -sph & +z_plane" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For many regions, OpenMC can automatically determine a bounding box. To get the bounding box, we use the `bounding_box` property of a region, which returns a tuple of the lower-left and upper-right Cartesian coordinates for the bounding box:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array([-1., -1., 0.]), array([1., 1., 1.]))" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "northern_hemisphere.bounding_box" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we see how to create volumes, we can use them to create a cell." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "cell = openmc.Cell()\n", - "cell.region = northern_hemisphere\n", - "\n", - "# or...\n", - "cell = openmc.Cell(region=northern_hemisphere)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, the cell is not filled by any material (void). In order to assign a material, we set the `fill` property of a `Cell`." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "cell.fill = water" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Universes and in-line plotting" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A collection of cells is known as a universe (again, this will be familiar to MCNP/Serpent users) and can be used as a repeatable unit when creating a model. Although we don't need it yet, the benefit of creating a universe is that we can visualize our geometry while we're creating it." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "universe = openmc.Universe()\n", - "universe.add_cell(cell)\n", - "\n", - "# this also works\n", - "universe = openmc.Universe(cells=[cell])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `Universe` object has a `plot` method that will display our the universe as current constructed:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "universe.plot(width=(2.0, 2.0))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, the plot will appear in the $x$-$y$ plane. We can change that with the `basis` argument." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "universe.plot(width=(2.0, 2.0), basis='xz')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we have particular fondness for, say, fuchsia, we can tell the `plot()` method to make our cell that color." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "universe.plot(width=(2.0, 2.0), basis='xz',\n", - " colors={cell: 'fuchsia'})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Pin cell geometry\n", - "\n", - "We now have enough knowledge to create our pin-cell. We need three surfaces to define the fuel and clad:\n", - "\n", - "1. The outer surface of the fuel -- a cylinder parallel to the z axis\n", - "2. The inner surface of the clad -- same as above\n", - "3. The outer surface of the clad -- same as above\n", - "\n", - "These three surfaces will all be instances of `openmc.ZCylinder`, each with a different radius according to the specification." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "fuel_or = openmc.ZCylinder(r=0.39)\n", - "clad_ir = openmc.ZCylinder(r=0.40)\n", - "clad_or = openmc.ZCylinder(r=0.46)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces created, we can now take advantage of the built-in operators on surfaces to create regions for the fuel, the gap, and the clad:" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "fuel_region = -fuel_or\n", - "gap_region = +fuel_or & -clad_ir\n", - "clad_region = +clad_ir & -clad_or" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can create corresponding cells that assign materials to these regions. As with materials, cells have unique IDs that are assigned either manually or automatically. Note that the gap cell doesn't have any material assigned (it is void by default)." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Cell instance already exists with id=1.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Cell instance already exists with id=2.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "fuel = openmc.Cell(1, 'fuel')\n", - "fuel.fill = uo2\n", - "fuel.region = fuel_region\n", - "\n", - "gap = openmc.Cell(2, 'air gap')\n", - "gap.region = gap_region\n", - "\n", - "clad = openmc.Cell(3, 'clad')\n", - "clad.fill = zirconium\n", - "clad.region = clad_region" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we need to handle the coolant outside of our fuel pin. To do this, we create x- and y-planes that bound the geometry." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "pitch = 1.26\n", - "left = openmc.XPlane(x0=-pitch/2, boundary_type='reflective')\n", - "right = openmc.XPlane(x0=pitch/2, boundary_type='reflective')\n", - "bottom = openmc.YPlane(y0=-pitch/2, boundary_type='reflective')\n", - "top = openmc.YPlane(y0=pitch/2, boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The water region is going to be everything outside of the clad outer radius and within the box formed as the intersection of four half-spaces." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "water_region = +left & -right & +bottom & -top & +clad_or\n", - "\n", - "moderator = openmc.Cell(4, 'moderator')\n", - "moderator.fill = water\n", - "moderator.region = water_region" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC also includes a factory function that generates a rectangular prism that could have made our lives easier." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "openmc.region.Intersection" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "box = openmc.rectangular_prism(width=pitch, height=pitch,\n", - " boundary_type='reflective')\n", - "type(box)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pay attention here -- the object that was returned is NOT a surface. It is actually the intersection of four surface half-spaces, just like we created manually before. Thus, we don't need to apply the unary operator (`-box`). Instead, we can directly combine it with `+clad_or`." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "water_region = box & +clad_or" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final step is to assign the cells we created to a universe and tell OpenMC that this universe is the \"root\" universe in our geometry. The `Geometry` is the final object that is actually exported to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "root = openmc.Universe(cells=(fuel, gap, clad, moderator))\n", - "\n", - "geom = openmc.Geometry()\n", - "geom.root_universe = root\n", - "\n", - "# or...\n", - "geom = openmc.Geometry(root)\n", - "geom.export_to_xml()\n", - "!cat geometry.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Starting source and settings\n", - "\n", - "The Python API has a module ``openmc.stats`` with various univariate and multivariate probability distributions. We can use these distributions to create a starting source using the ``openmc.Source`` object." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "point = openmc.stats.Point((0, 0, 0))\n", - "src = openmc.Source(space=point)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's create a `Settings` object and give it the source we created along with specifying how many batches and particles we want to run." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.source = src\n", - "settings.batches = 100\n", - "settings.inactive = 10\n", - "settings.particles = 1000" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " eigenvalue\r\n", - " 1000\r\n", - " 100\r\n", - " 10\r\n", - " \r\n", - " \r\n", - " 0 0 0\r\n", - " \r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "settings.export_to_xml()\n", - "!cat settings.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## User-defined tallies\n", - "\n", - "We actually have all the *required* files needed to run a simulation. Before we do that though, let's give a quick example of how to create tallies. We will show how one would tally the total, fission, absorption, and (n,$\\gamma$) reaction rates for $^{235}$U in the cell containing fuel. Recall that filters allow us to specify *where* in phase-space we want events to be tallied and scores tell us *what* we want to tally:\n", - "\n", - "$$X = \\underbrace{\\int d\\mathbf{r} \\int d\\mathbf{\\Omega} \\int dE}_{\\text{filters}} \\; \\underbrace{f(\\mathbf{r},\\mathbf{\\Omega},E)}_{\\text{scores}} \\psi (\\mathbf{r},\\mathbf{\\Omega},E)$$\n", - "\n", - "In this case, the *where* is \"the fuel cell\". So, we will create a cell filter specifying the fuel cell." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "cell_filter = openmc.CellFilter(fuel)\n", - "\n", - "t = openmc.Tally(1)\n", - "t.filters = [cell_filter]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The *what* is the total, fission, absorption, and (n,$\\gamma$) reaction rates in $^{235}$U. By default, if we only specify what reactions, it will gives us tallies over all nuclides. We can use the `nuclides` attribute to name specific nuclides we're interested in." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [], - "source": [ - "t.nuclides = ['U235']\n", - "t.scores = ['total', 'fission', 'absorption', '(n,gamma)']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similar to the other files, we need to create a `Tallies` collection and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - " 1\r\n", - " \r\n", - " \r\n", - " 1\r\n", - " U235\r\n", - " total fission absorption (n,gamma)\r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "tallies = openmc.Tallies([t])\n", - "tallies.export_to_xml()\n", - "!cat tallies.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Running OpenMC\n", - "\n", - "Running OpenMC from Python can be done using the `openmc.run()` function. This function allows you to set the number of MPI processes and OpenMP threads, if need be." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 06:20:10\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Reading Zr91 from /opt/data/hdf5/nndc_hdf5_v15/Zr91.h5\n", - " Reading Zr92 from /opt/data/hdf5/nndc_hdf5_v15/Zr92.h5\n", - " Reading Zr94 from /opt/data/hdf5/nndc_hdf5_v15/Zr94.h5\n", - " Reading Zr96 from /opt/data/hdf5/nndc_hdf5_v15/Zr96.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading O17 from /opt/data/hdf5/nndc_hdf5_v15/O17.h5\n", - " Reading c_H_in_H2O from /opt/data/hdf5/nndc_hdf5_v15/c_H_in_H2O.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.32572\n", - " 2/1 1.46138\n", - " 3/1 1.46068\n", - " 4/1 1.39592\n", - " 5/1 1.37519\n", - " 6/1 1.38777\n", - " 7/1 1.50242\n", - " 8/1 1.42042\n", - " 9/1 1.47458\n", - " 10/1 1.49148\n", - " 11/1 1.39339\n", - " 12/1 1.40637 1.39988 +/- 0.00649\n", - " 13/1 1.42972 1.40983 +/- 0.01063\n", - " 14/1 1.46319 1.42317 +/- 0.01531\n", - " 15/1 1.41538 1.42161 +/- 0.01196\n", - " 16/1 1.38163 1.41494 +/- 0.01182\n", - " 17/1 1.41257 1.41461 +/- 0.01000\n", - " 18/1 1.43455 1.41710 +/- 0.00901\n", - " 19/1 1.33136 1.40757 +/- 0.01241\n", - " 20/1 1.41560 1.40837 +/- 0.01113\n", - " 21/1 1.38911 1.40662 +/- 0.01021\n", - " 22/1 1.28621 1.39659 +/- 0.01370\n", - " 23/1 1.45693 1.40123 +/- 0.01343\n", - " 24/1 1.46839 1.40603 +/- 0.01333\n", - " 25/1 1.46738 1.41012 +/- 0.01306\n", - " 26/1 1.43977 1.41197 +/- 0.01236\n", - " 27/1 1.44066 1.41366 +/- 0.01173\n", - " 28/1 1.39358 1.41254 +/- 0.01112\n", - " 29/1 1.39142 1.41143 +/- 0.01057\n", - " 30/1 1.38525 1.41012 +/- 0.01012\n", - " 31/1 1.38025 1.40870 +/- 0.00973\n", - " 32/1 1.45348 1.41074 +/- 0.00949\n", - " 33/1 1.35893 1.40848 +/- 0.00935\n", - " 34/1 1.32332 1.40493 +/- 0.00963\n", - " 35/1 1.46285 1.40725 +/- 0.00952\n", - " 36/1 1.33760 1.40457 +/- 0.00953\n", - " 37/1 1.41117 1.40482 +/- 0.00917\n", - " 38/1 1.45574 1.40664 +/- 0.00903\n", - " 39/1 1.43472 1.40760 +/- 0.00876\n", - " 40/1 1.30110 1.40405 +/- 0.00918\n", - " 41/1 1.41765 1.40449 +/- 0.00889\n", - " 42/1 1.45300 1.40601 +/- 0.00874\n", - " 43/1 1.40491 1.40597 +/- 0.00847\n", - " 44/1 1.42053 1.40640 +/- 0.00823\n", - " 45/1 1.38805 1.40588 +/- 0.00801\n", - " 46/1 1.34293 1.40413 +/- 0.00798\n", - " 47/1 1.35441 1.40279 +/- 0.00787\n", - " 48/1 1.29370 1.39991 +/- 0.00818\n", - " 49/1 1.48467 1.40209 +/- 0.00826\n", - " 50/1 1.41759 1.40248 +/- 0.00806\n", - " 51/1 1.37151 1.40172 +/- 0.00790\n", - " 52/1 1.42403 1.40225 +/- 0.00773\n", - " 53/1 1.38826 1.40193 +/- 0.00755\n", - " 54/1 1.48944 1.40392 +/- 0.00764\n", - " 55/1 1.41452 1.40415 +/- 0.00747\n", - " 56/1 1.47337 1.40566 +/- 0.00746\n", - " 57/1 1.35700 1.40462 +/- 0.00738\n", - " 58/1 1.40305 1.40459 +/- 0.00722\n", - " 59/1 1.41608 1.40482 +/- 0.00708\n", - " 60/1 1.47254 1.40618 +/- 0.00706\n", - " 61/1 1.36847 1.40544 +/- 0.00696\n", - " 62/1 1.34103 1.40420 +/- 0.00694\n", - " 63/1 1.39510 1.40403 +/- 0.00681\n", - " 64/1 1.40228 1.40399 +/- 0.00668\n", - " 65/1 1.29401 1.40200 +/- 0.00686\n", - " 66/1 1.42693 1.40244 +/- 0.00675\n", - " 67/1 1.36447 1.40177 +/- 0.00666\n", - " 68/1 1.37498 1.40131 +/- 0.00656\n", - " 69/1 1.36958 1.40077 +/- 0.00647\n", - " 70/1 1.38585 1.40053 +/- 0.00637\n", - " 71/1 1.42133 1.40087 +/- 0.00627\n", - " 72/1 1.44900 1.40164 +/- 0.00622\n", - " 73/1 1.37696 1.40125 +/- 0.00613\n", - " 74/1 1.48851 1.40261 +/- 0.00619\n", - " 75/1 1.38933 1.40241 +/- 0.00610\n", - " 76/1 1.41780 1.40264 +/- 0.00601\n", - " 77/1 1.41054 1.40276 +/- 0.00592\n", - " 78/1 1.38194 1.40246 +/- 0.00584\n", - " 79/1 1.38446 1.40219 +/- 0.00576\n", - " 80/1 1.37504 1.40181 +/- 0.00569\n", - " 81/1 1.40550 1.40186 +/- 0.00561\n", - " 82/1 1.49785 1.40319 +/- 0.00569\n", - " 83/1 1.35613 1.40255 +/- 0.00565\n", - " 84/1 1.41786 1.40275 +/- 0.00557\n", - " 85/1 1.38444 1.40251 +/- 0.00550\n", - " 86/1 1.40459 1.40254 +/- 0.00543\n", - " 87/1 1.39923 1.40249 +/- 0.00536\n", - " 88/1 1.44540 1.40304 +/- 0.00532\n", - " 89/1 1.45962 1.40376 +/- 0.00530\n", - " 90/1 1.37057 1.40335 +/- 0.00525\n", - " 91/1 1.38115 1.40307 +/- 0.00519\n", - " 92/1 1.35758 1.40252 +/- 0.00516\n", - " 93/1 1.34508 1.40182 +/- 0.00514\n", - " 94/1 1.31471 1.40079 +/- 0.00519\n", - " 95/1 1.41434 1.40095 +/- 0.00513\n", - " 96/1 1.33895 1.40023 +/- 0.00512\n", - " 97/1 1.44716 1.40077 +/- 0.00509\n", - " 98/1 1.38455 1.40058 +/- 0.00503\n", - " 99/1 1.52127 1.40194 +/- 0.00516\n", - " 100/1 1.35488 1.40141 +/- 0.00513\n", - " Creating state point statepoint.100.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 7.5853e-01 seconds\n", - " Reading cross sections = 7.3383e-01 seconds\n", - " Total time in simulation = 6.5719e+00 seconds\n", - " Time in transport only = 5.9772e+00 seconds\n", - " Time in inactive batches = 4.8850e-01 seconds\n", - " Time in active batches = 6.0834e+00 seconds\n", - " Time synchronizing fission bank = 5.9939e-03 seconds\n", - " Sampling source sites = 5.1295e-03 seconds\n", - " SEND/RECV source sites = 7.3640e-04 seconds\n", - " Time accumulating tallies = 9.9301e-05 seconds\n", - " Total time for finalization = 1.1585e-04 seconds\n", - " Total time elapsed = 7.3346e+00 seconds\n", - " Calculation Rate (inactive) = 20471.0 particles/second\n", - " Calculation Rate (active) = 14794.4 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.39737 +/- 0.00470\n", - " k-effective (Track-length) = 1.40141 +/- 0.00513\n", - " k-effective (Absorption) = 1.39596 +/- 0.00308\n", - " Combined k-effective = 1.39719 +/- 0.00286\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Great! OpenMC already told us our k-effective. It also spit out a file called `tallies.out` that shows our tallies. This is a very basic method to look at tally data; for more sophisticated methods, see other example notebooks." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " ============================> TALLY 1 <============================\r\n", - "\r\n", - " Cell 1\r\n", - " U235\r\n", - " Total Reaction Rate 0.731003 +/- 0.00253759\r\n", - " Fission Rate 0.547587 +/- 0.00210114\r\n", - " Absorption Rate 0.657406 +/- 0.0024539\r\n", - " (n,gamma) 0.109821 +/- 0.000368054\r\n" - ] - } - ], - "source": [ - "!cat tallies.out" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Geometry plotting\n", - "\n", - "We saw before that we could call the `Universe.plot()` method to show a universe while we were creating our geometry. There is also a built-in plotter in the Fortran codebase that is much faster than the Python plotter and has more options. The interface looks somewhat similar to the `Universe.plot()` method. Instead though, we create `Plot` instances, assign them to a `Plots` collection, export it to XML, and then run OpenMC in geometry plotting mode. As an example, let's specify that we want the plot to be colored by material (rather than by cell) and we assign yellow to fuel and blue to water." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [], - "source": [ - "p = openmc.Plot()\n", - "p.filename = 'pinplot'\n", - "p.width = (pitch, pitch)\n", - "p.pixels = (200, 200)\n", - "p.color_by = 'material'\n", - "p.colors = {uo2: 'yellow', water: 'blue'}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our plot created, we need to add it to a `Plots` collection which can be exported to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - " 0.0 0.0 0.0\r\n", - " 1.26 1.26\r\n", - " 200 200\r\n", - " \r\n", - " \r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "plots = openmc.Plots([p])\n", - "plots.export_to_xml()\n", - "!cat plots.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can run OpenMC in plotting mode by calling the `plot_geometry()` function. Under the hood this is calling `openmc --plot`." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 06:20:18\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading tallies XML file...\n", - " Reading plot XML file...\n", - "\n", - " =======================> PLOTTING SUMMARY <========================\n", - "\n", - "Plot ID: 1\n", - "Plot file: pinplot.ppm\n", - "Universe depth: -1\n", - "Plot Type: Slice\n", - "Origin: 0 0 0\n", - "Width: 1.26 1.26\n", - "Coloring: Materials\n", - "Basis: XY\n", - "Pixels: 200 200 \n", - "\n", - " Processing plot 1: pinplot.ppm...\n" - ] - } - ], - "source": [ - "openmc.plot_geometry()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC writes out a peculiar image with a `.ppm` extension. If you have ImageMagick installed, this can be converted into a more normal `.png` file." - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "!convert pinplot.ppm pinplot.png" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can use functionality from IPython to display the image inline in our notebook:" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAgMAAADQNkYNAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEUAAP9yEhL//////wAZPRNOAAAAAWJLR0QCZgt8ZAAAAAd0SU1FB+MHEwEUEnBdK8cAAAI7SURBVGje7ZmxkcIwEEUhcAnuhxIIEIGvAwioxiU4QASU4GougA4gsM6SfNxh766sfx7N3Ix+zJv9X7KxtLtaZWVlZWWl1Fr12sQQpXLaRRMRTKFe2kbk+Na8POpNkbbmWlMqtkwxRsJllIotMxQ56F7neWX8LmrdGtNpPWc//Z4cLsbpfp6xN85XNRA904Sd2V/stXlJ16EFcL4O7Q/SnUPOrK/9xfzSvQ44K0dFhjLCmq0nRYYyvDPrq2rfka4RnVlfoyJ9GdGZ9XUdI89aWGYbpTITNUKYgvLlnXFhSsqXd7bjEcKXc8YhvYEjhdzY/Db9lUKebP4+/b6lkK7m8nNRhDAlE8WFoREuig/DpKej+DAbGmGiuDAUUsgItWR8ejZ/yaZ3+SmET+/zL4JIC8Ys2VpI7/JPkSKEbCnkyiNPCilDyI5A+AVzSzZFVAhRBCKssVvlBRB5W8iNwZCThDymiLyT5F5iSCsh3RSRN5/cfgwxoiikkpFmgqgwopZAPmTkcxnkKCO3BZDQs088/RhykpFHRjLyP5AE70uadz/Z/1iK/2TgYwF9klJ8K4GPeJrTBXDsSXMeS3O2RA69wNEaOMAD1wTgMgJceYCLVZobH3IVBS68wLUauLwDLQKgEYG0O4CmCtC6ARpEQBsKaXYBLTWgcQe0B4EmJNLqBBqqQNsWaA4jLWig0Q2005GmPTAaAAYQyJgDGKYgIxtgMISMn4AhFzJKAwZ2yFgQGT4iI86srKysrD/rC4LWcCSWwIp+AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTA3LTE5VDA2OjIwOjE4LTA1OjAwIrpoEwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wNy0xOVQwNjoyMDoxOC0wNTowMFPn0K8AAAAASUVORK5CYII=\n", - "text/plain": [ - "" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import Image\n", - "Image(\"pinplot.png\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "That was a little bit cumbersome. Thankfully, OpenMC provides us with a method on the `Plot` class that does all that \"boilerplate\" work." - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAgMAAADQNkYNAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEUAAP9yEhL//////wAZPRNOAAAAAWJLR0QCZgt8ZAAAAAd0SU1FB+MHEwEUEnBdK8cAAAI7SURBVGje7ZmxkcIwEEUhcAnuhxIIEIGvAwioxiU4QASU4GougA4gsM6SfNxh766sfx7N3Ix+zJv9X7KxtLtaZWVlZWWl1Fr12sQQpXLaRRMRTKFe2kbk+Na8POpNkbbmWlMqtkwxRsJllIotMxQ56F7neWX8LmrdGtNpPWc//Z4cLsbpfp6xN85XNRA904Sd2V/stXlJ16EFcL4O7Q/SnUPOrK/9xfzSvQ44K0dFhjLCmq0nRYYyvDPrq2rfka4RnVlfoyJ9GdGZ9XUdI89aWGYbpTITNUKYgvLlnXFhSsqXd7bjEcKXc8YhvYEjhdzY/Db9lUKebP4+/b6lkK7m8nNRhDAlE8WFoREuig/DpKej+DAbGmGiuDAUUsgItWR8ejZ/yaZ3+SmET+/zL4JIC8Ys2VpI7/JPkSKEbCnkyiNPCilDyI5A+AVzSzZFVAhRBCKssVvlBRB5W8iNwZCThDymiLyT5F5iSCsh3RSRN5/cfgwxoiikkpFmgqgwopZAPmTkcxnkKCO3BZDQs088/RhykpFHRjLyP5AE70uadz/Z/1iK/2TgYwF9klJ8K4GPeJrTBXDsSXMeS3O2RA69wNEaOMAD1wTgMgJceYCLVZobH3IVBS68wLUauLwDLQKgEYG0O4CmCtC6ARpEQBsKaXYBLTWgcQe0B4EmJNLqBBqqQNsWaA4jLWig0Q2005GmPTAaAAYQyJgDGKYgIxtgMISMn4AhFzJKAwZ2yFgQGT4iI86srKysrD/rC4LWcCSWwIp+AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTA3LTE5VDA2OjIwOjE4LTA1OjAwIrpoEwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wNy0xOVQwNjoyMDoxOC0wNTowMFPn0K8AAAAASUVORK5CYII=\n", - "text/plain": [ - "" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p.to_ipython_image()" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/pincell_depletion.ipynb b/examples/jupyter/pincell_depletion.ipynb deleted file mode 100644 index 94ec479f6..000000000 --- a/examples/jupyter/pincell_depletion.ipynb +++ /dev/null @@ -1,996 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook is intended to introduce the reader to the depletion interface contained in OpenMC. It is recommended that you are moderately familiar with building models using the OpenMC Python API. The earlier examples are excellent starting points, as this notebook will not focus heavily on model building.\n", - "\n", - "If you have a real power reactor, the fuel composition is constantly changing as fission events produce energy, remove some fissile isotopes, and produce fission products. Other reactions, like $(n, \\alpha)$ and $(n, \\gamma)$ will alter the composition as well. Furthermore, some nuclides undergo spontaneous decay with widely ranging frequencies. Depletion is the process of modeling this behavior.\n", - "\n", - "In this notebook, we will model a simple fuel pin in an infinite lattice using the Python API. We will then build and examine some of the necessary components for performing depletion analysis. Then, we will use the depletion interface in OpenMC to simulate the fuel pin producing power over several months. Lastly, we will wrap up with some helpful tips to improve the fidelity of depletion simulations." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import math\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Build the Geometry\n", - "\n", - "Much of this section is borrowed from the \"Modeling a Pin-Cell\" example. If you find yourself not understanding some aspects of this section, feel free to refer to that example, as some details may be glossed over for brevity.\n", - "\n", - "First, we will create our fuel, cladding, and water materials to represent a typical PWR." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "fuel = openmc.Material(name=\"uo2\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "fuel.add_element(\"U\", 1, percent_type=\"ao\", enrichment=4.25)\n", - "fuel.add_element(\"O\", 2)\n", - "fuel.set_density(\"g/cc\", 10.4)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "clad = openmc.Material(name=\"clad\")" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "clad.add_element(\"Zr\", 1)\n", - "clad.set_density(\"g/cc\", 6)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "water = openmc.Material(name=\"water\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "water.add_element(\"O\", 1)\n", - "water.add_element(\"H\", 2)\n", - "water.set_density(\"g/cc\", 1.0)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "water.add_s_alpha_beta(\"c_H_in_H2O\")" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "materials = openmc.Materials([fuel, clad, water])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here, we are going to use the `openmc.model.pin` function to build our pin cell. The `pin` function anticipates concentric cylinders and materials to fill the inner regions. One additional material is needed than the number of cylinders to cover the domain outside the final ring. \n", - "\n", - "To do this, we define two radii for the outer radius of our fuel pin, and the outer radius of the cladding." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "radii = [0.42, 0.45]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using these radii, we define concentric `ZCylinder` objects. So long as the cylinders are concentric and increasing in radius, any orientation can be used. We also take advantage of the fact that the `openmc.Materials` object is a subclass of the `list` object to assign materials to the regions defined by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "pin_surfaces = [openmc.ZCylinder(r=r) for r in radii]" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "pin_univ = openmc.model.pin(pin_surfaces, materials)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first material, in our case `fuel`, is placed inside the first cylinder in the inner-most region. The second material, `clad`, fills the space between our cylinders, while `water` is placed outside the last ring. The `pin` function returns an `openmc.Universe` object, and has some additional features we will mention later." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pin_univ.plot()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "bound_box = openmc.rectangular_prism(0.62, 0.62, boundary_type=\"reflective\")" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "root_cell = openmc.Cell(fill=pin_univ, region=bound_box)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "root_univ = openmc.Universe(cells=[root_cell])" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "geometry = openmc.Geometry(root_univ)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lastly we construct our settings. For the sake of time, a relatively low number of particles will be used." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "settings.particles = 100\n", - "settings.inactive = 10\n", - "settings.batches = 50" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The depletion interface relies on `OpenMC` to perform the transport simulation and obtain reaction rates and other important information. We then have to create the `xml` input files that `openmc` expects, specifically `geometry.xml`, `settings.xml`, and `materials.xml`." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "settings.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we write the material file, we must add one bit of information: the volume of our fuel. In order to translate the reaction rates obtained by `openmc` to meaningful units for depletion, we have to normalize them to a correct power. This requires us to know, or be able to calculate, how much fuel is in our problem. Correctly setting the volumes is a critical step, and can lead to incorrect answers, as the fuel is over- or under-depleted due to poor normalization.\n", - "\n", - "For our problem, we can assign the \"volume\" to be the cross-sectional area of our fuel. This is identical to modeling our fuel pin inside a box with height of 1 cm." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "fuel.volume = math.pi * radii[0] ** 2" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], - "source": [ - "materials.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Setting up for depletion\n", - "\n", - "The OpenMC depletion interface can be accessed from the `openmc.deplete` module, and has a variety of classes that will help us." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "import openmc.deplete" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to run the depletion calculation we need the following information:\n", - "\n", - "1. Nuclide decay, fission yield, and reaction data\n", - "2. Operational power or power density\n", - "3. Desired depletion schedule\n", - "4. Desired time integration scheme\n", - "\n", - "The first item is necessary to determine the paths by which nuclides transmute over the depletion simulation. This includes spontaneous decay, fission product yield distributions, and nuclides produced through neutron-reactions. For example,\n", - "* Te129 decays to I129 with a half life of ~70 minutes\n", - "* A fission event for U-235 produces fission products like Xe135 according to a distribution\n", - "* For thermal problems, Am241 will produce metastable Am242 about 8% of the time during an $(n,\\gamma)$ reaction. The other 92% of capture reactions will produce ground state Am242\n", - "\n", - "These data are often distributed with other nuclear data, like incident neutron cross sections with ENDF/B-VII.\n", - "OpenMC uses the [`openmc.deplete.Chain`](https://docs.openmc.org/en/latest/pythonapi/generated/openmc.deplete.Chain.html#openmc.deplete.Chain) to collect represent the various decay and transmutation pathways in a single object.\n", - "While a complete `Chain` can be created using nuclear data files, users may prefer to download pre-generated XML-representations instead.\n", - "Such files can be found at https://openmc.org/depletion-chains/ and include full and compressed chains, with capture branching ratios derived using PWR- or SFR-spectra.\n", - "\n", - "For this problem, we will be using a much smaller depletion chain that contains very few nuclides. In a realistic problem, over 1000 isotopes may be included in the depletion chain." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "chain = openmc.deplete.Chain.from_xml(\"./chain_simple.xml\")" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "OrderedDict([('I135', 0),\n", - " ('Xe135', 1),\n", - " ('Xe136', 2),\n", - " ('Cs135', 3),\n", - " ('Gd157', 4),\n", - " ('Gd156', 5),\n", - " ('U234', 6),\n", - " ('U235', 7),\n", - " ('U238', 8)])" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "chain.nuclide_dict" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The primary entry point for depletion is the `openmc.deplete.Operator`. It relies on the `openmc.deplete.Chain` and helper classes to run `openmc`, retrieve and normalize reaction rates, and other perform other tasks. For a thorough description, please see the full API documentation." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will create our Operator using the geometry and settings from above, and our simple chain file. The materials are read in automatically using the `materials.xml` file." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "operator = openmc.deplete.Operator(geometry, settings, \"./chain_simple.xml\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will then simulate our fuel pin operating at linear power of 174 W/cm, or 174 W given a unit height for our problem." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "power = 174" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this problem, we will take depletion step sizes of 30 days, and instruct OpenMC to re-run a transport simulation every 30 days until we have modeled the problem over a six month cycle. The depletion interface expects the time to be given in seconds, so we will have to convert. Note that these values are not cumulative." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "time_steps = [30 * 24 * 60 * 60] * 6" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And lastly, we will use the basic predictor, or forward Euler, time integration scheme. Other, more advanced methods are provided to the user through `openmc.deplete`" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [], - "source": [ - "integrator = openmc.deplete.PredictorIntegrator(operator, time_steps, power)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To perform the simulation, we use the `integrate` method, and let `openmc` take care of the rest." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "integrator.integrate()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Processing the outputs\n", - "\n", - "The depletion simulation produces a few output files. First, the statepoint files from each individual transport simulation are written to `openmc_simulation_n.h5`, where `` indicates the current depletion step. Any tallies that we defined in `tallies.xml` will be included in these files across our simulations. We have 7 such files, one for each our of 6 depletion steps and the initial state." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "c5g7.h5\t\t\t openmc_simulation_n2.h5 openmc_simulation_n6.h5\r\n", - "depletion_results.h5\t openmc_simulation_n3.h5 statepoint.50.h5\r\n", - "openmc_simulation_n0.h5 openmc_simulation_n4.h5 summary.h5\r\n", - "openmc_simulation_n1.h5 openmc_simulation_n5.h5\r\n" - ] - } - ], - "source": [ - "!ls *.h5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `depletion_results.h5` file contains information that is aggregated over all time steps through depletion. This includes the multiplication factor, as well as concentrations. We can process this file using the `openmc.deplete.ResultsList` object" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "results = openmc.deplete.ResultsList.from_hdf5(\"./depletion_results.h5\")" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "time, k = results.get_eigenvalue()" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "time /= (24 * 60 * 60) # convert back to days from seconds" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0.76882937, 0.00982155],\n", - " [0.75724033, 0.00827689],\n", - " [0.75532242, 0.01031746],\n", - " [0.74796855, 0.00919769],\n", - " [0.74066561, 0.01157708],\n", - " [0.73184492, 0.00971504],\n", - " [0.7207293 , 0.00703074]])" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "k" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first column of `k` is the value of `k-combined` at each point in our simulation, while the second column contains the associated uncertainty. We can plot this using `matplotlib`" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [], - "source": [ - "from matplotlib import pyplot" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pyplot.errorbar(time, k[:, 0], yerr=k[:, 1])\n", - "pyplot.xlabel(\"Time [d]\")\n", - "pyplot.ylabel(\"$k_{eff}\\pm \\sigma$\");" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Due to the low number of particles selected, we have not only a very high uncertainty, but likely a horrendously poor fission source. This pin cell should have $k>1$, but we can still see the decline over time due to fuel consumption." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can then examine concentrations of atoms in each of our materials. This requires knowing the material ID, which can be obtained from the `materials.xml` file." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [], - "source": [ - "_time, u5 = results.get_atoms(\"1\", \"U235\")\n", - "_time, xe135 = results.get_atoms(\"1\", \"Xe135\")" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pyplot.plot(time, u5, label=\"U235\")\n", - "pyplot.xlabel(\"Time [d]\")\n", - "pyplot.ylabel(\"Number of atoms - U235\");" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pyplot.plot(time, xe135, label=\"Xe135\")\n", - "pyplot.xlabel(\"Time [d]\")\n", - "pyplot.ylabel(\"Number of atoms - Xe135\");" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also examine reaction rates over time using the `ResultsList`" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "_time, u5_fission = results.get_reaction_rate(\"1\", \"U235\", \"fission\")" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pyplot.plot(time, u5_fission)\n", - "pyplot.xlabel(\"Time [d]\")\n", - "pyplot.ylabel(\"Fission reactions / s\");" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Helpful tips\n", - "\n", - "Depletion is a tricky task to get correct. Use too short of time steps and you may never get your results due to running many transport simulations. Use long of time steps and you may get incorrect answers. Consider the xenon plot from above. Xenon-135 is a fission product with a thermal absorption cross section on the order of millions of barns, but has a half life of ~9 hours. Taking smaller time steps at the beginning of your simulation to build up some equilibrium in your fission products is highly recommended.\n", - "\n", - "When possible, differentiate materials that reappear in multiple places. If we had built an entire core with the single `fuel` material, every pin would be depleted using the same averaged spectrum and reaction rates which is incorrect. The `Operator` can differentiate these materials using the `diff_burnable_mats` argument, but note that the volumes will be copied from the original material.\n", - "\n", - "Using higher-order integrators, like the `CECMIntegrator`, `EPCRK4Integrator` with a fourth order Runge-Kutta, or the `LEQIIntegrator`, can improve the accuracy of a simulation, or at least allow you to take longer depletion steps between transport simulations with similar accuracy.\n", - "\n", - "Fuel pins with integrated burnable absorbers, like gadolinia, experience strong flux gradients until the absorbers are mostly burned away. This means that the spectrum and magnitude of the flux at the edge of the fuel pin can be vastly different than that in the interior. The helper `pin` function can be used to subdivide regions into equal volume segments, as follows." - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "div_surfs_1 = [openmc.ZCylinder(r=1)]\n", - "div_1 = openmc.model.pin(div_surfs_1, [fuel, water], subdivisions={0: 10})" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "div_1.plot(width=(2.0, 2.0))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The innermost region has been divided into 10 equal volume regions. We can pass additional arguments to divide multiple regions, except for the region outside the last cylinder." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Register depletion chain\n", - "\n", - "The depletion chain we created can be registered into the OpenMC `cross_sections.xml` file, so we don't have to always pass the `chain_file` argument to the `Operator`. To do this, we create a `DataLibrary` using `openmc.data`. Without any arguments, the `from_xml` method will look for the file located at `OPENMC_CROSS_SECTIONS`. For this example, we will just create a bare library." - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [], - "source": [ - "data_lib = openmc.data.DataLibrary()" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [], - "source": [ - "data_lib.register_file(\"./chain_simple.xml\")" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [], - "source": [ - "data_lib.export_to_xml()" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r\n", - "\r\n", - " \r\n", - "\r\n" - ] - } - ], - "source": [ - "!cat cross_sections.xml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This allows us to make an `Operator` simply with the geometry and settings arguments, provided we exported our library to `OPENMC_CROSS_SECTIONS`. For a problem where we built and registered a `Chain` using all the available nuclear data, we might see something like the following." - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [], - "source": [ - "new_op = openmc.deplete.Operator(geometry, settings)" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3820" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(new_op.chain.nuclide_dict)" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'He3', 'He4', 'He5']" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[nuc.name for nuc in new_op.chain.nuclides[:10]]" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Ds268',\n", - " 'Ds269',\n", - " 'Ds270',\n", - " 'Ds270_m1',\n", - " 'Ds271',\n", - " 'Ds271_m1',\n", - " 'Ds272',\n", - " 'Ds273',\n", - " 'Ds279_m1',\n", - " 'Rg272']" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[nuc.name for nuc in new_op.chain.nuclides[-10:]]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Choice of depletion step size\n", - "\n", - "A general rule of thumb is to use depletion step sizes around 2 MWd/kgHM, where kgHM is really the initial heavy metal mass in kg. If your problem includes integral burnable absorbers, these typically require shorter time steps at or below 1 MWd/kgHM. These are typically valid for the predictor scheme, as the point of recent schemes is to extend this step size. A good convergence study, where the step size is decreased until some convergence metric is satisfied, is a beneficial exercise.\n", - "\n", - "We can use the `Operator` to determine our maximum step size using this recommendation. The `heavy_metal` attribute returns the mass of initial heavy metal in g, which, using our power, can be used to compute this step size. $$\\frac{2\\,MWd}{kgHM} = \\frac{P\\times\\Delta}{hm_{op}}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "5.080339195584719" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "operator.heavy_metal" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [], - "source": [ - "max_step = 2 * operator.heavy_metal / power * 1E3" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"Maximum\" depletion step: 58.4 [d]\n" - ] - } - ], - "source": [ - "print(\"\\\"Maximum\\\" depletion step: {:5.3} [d]\".format(max_step))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Alternatively, if we were provided the power density of our problem, we can provide this directly with `openmc.deplete.PredictorIntegrator(operator, time_steps, power_density=pdens)`. The values of `power` and `power_density` do not have to be scalars. For problems with variable power, we can provide an iterable with the same number of elements as `time_steps`." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/post-processing.ipynb b/examples/jupyter/post-processing.ipynb deleted file mode 100644 index 22ccb2b5b..000000000 --- a/examples/jupyter/post-processing.ipynb +++ /dev/null @@ -1,985 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook demonstrates some basic post-processing tasks that can be performed with the Python API, such as plotting a 2D mesh tally and plotting neutron source sites from an eigenvalue calculation. The problem we will use is a simple reflected pin-cell." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "from IPython.display import Image\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. We'll create three materials for the fuel, water, and cladding of the fuel pin." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6 enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "water.add_nuclide('B10', 8.0042e-6)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a materials file object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials collection\n", - "materials_file = openmc.Materials([fuel, water, zircaloy])\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six reflective planes." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-0.63, boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=+0.63, boundary_type='reflective')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "pin_cell_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "pin_cell_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "pin_cell_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell')\n", - "root_cell.fill = pin_cell_universe\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "geometry = openmc.Geometry(root_universe)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 10 inactive batches and 90 active batches each with 5000 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 100\n", - "inactive = 10\n", - "particles = 5000\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEXpgJFyEhJNv8T///9xF1FxAAAAAWJLR0QDEQxM8gAAAAd0SU1FB+MHEwEWFzIBvcoAAAKlSURBVGje7ZrBscIwDETxwSWkn5TAgXCgBPqhBA6kyj/fDhCIJa2zZAwz0pmHpZWdSazd7Tw8PDw8PDw8vinCMBzW03HIsRLvhnv0HL7qD+IwjzXKzaNaxeEt9kz21RWEBV5XQbfka3pQWL4qgdLyNQkUcbwFT/FP4zjWt+D+++OY4laZQJgtnqNOwe5l9XkGmIIL/PEHUAGTeuc5P15wBbu34ucSIAXkX77h4xUtIBSXnxIAOhCLy98TANNfLj8lYBYQCuLPWmAWEBe9f90DUPdKy08JWB0U1HsoaAgQxPSnAgwBopz+VABQvoDnAnqTP0r8zealzfPcQqqAQSs/C6AKGLX0pwKs8uX0cwGaAHr6uYC9wSt46qDCB4RXBDTkMwWMhnxZQF3+s8pf1AZY5VsCWuVnAUQ+YPxB43X5koAiH035soCa/AaeBOw34m359AaQPCK/1oAAyJ8aIPBI+7QGRkD+3IBt+A6QPzeg34SH2pcauN+Kt9uXGljkse0jb6BP8AD+vwGKPLZ95A0UofbnDbAFj20/eQN+gD8h/LgRD25/8QCA2088AD/Oo8dPOoDo8ZMOoPPNeej4pwdAgUcfX9IDzHnnf5lnz88XnH/nSf4M8cIL7I+/P3yCP0G88P7W+v2z9ft36+8P9vuJ/X5r/f3Jfj83//5vff/R+v6Hvb9i78/Y+7vW94/N71/Z+2P2/pq9P2fv7+n5ATu/YOcn7PyGnR+x8yt6ftYN3PzOENCcH7LzS3Z+Ss9vO62DV5uPmgAXSz5+fs7O72n/QBQLwPwLrH+C9W/Q/hHWv8L6Z2j/ThZgvX+I9S/R/inWv8X6x2j/Guufo/17rH+Q9S/S/knWv0n7R2n/Kuufpf27tH+Y9i/vWP+0h4eHh4eHh8cW8QcxLJDBvLKoigAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wNy0xOVQwNjoyMjoyMy0wNTowMKrH6zcAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDctMTlUMDY6MjI6MjMtMDU6MDDbmlOLAAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "plot = openmc.Plot.from_geometry(geometry)\n", - "plot.pixels = (250, 250)\n", - "plot.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see from the plot, we have a nice pin cell with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a 2D mesh tally." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate an empty Tallies object\n", - "tallies_file = openmc.Tallies()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# Create mesh which will be used for tally\n", - "mesh = openmc.RegularMesh()\n", - "mesh.dimension = [100, 100]\n", - "mesh.lower_left = [-0.63, -0.63]\n", - "mesh.upper_right = [0.63, 0.63]\n", - "\n", - "# Create mesh filter for tally\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Create mesh tally to score flux and fission rate\n", - "tally = openmc.Tally(name='flux')\n", - "tally.filters = [mesh_filter]\n", - "tally.scores = ['flux', 'fission']\n", - "tallies_file.append(tally)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-19 06:22:24\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading B10 from /opt/data/hdf5/nndc_hdf5_v15/B10.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 1.04359\n", - " 2/1 1.04323\n", - " 3/1 1.04711\n", - " 4/1 1.03892\n", - " 5/1 1.02459\n", - " 6/1 1.03936\n", - " 7/1 1.03529\n", - " 8/1 1.01590\n", - " 9/1 1.03060\n", - " 10/1 1.02892\n", - " 11/1 1.03987\n", - " 12/1 1.04395 1.04191 +/- 0.00204\n", - " 13/1 1.04971 1.04451 +/- 0.00285\n", - " 14/1 1.03880 1.04308 +/- 0.00247\n", - " 15/1 1.03091 1.04065 +/- 0.00310\n", - " 16/1 1.03618 1.03990 +/- 0.00264\n", - " 17/1 1.04109 1.04007 +/- 0.00223\n", - " 18/1 1.02978 1.03879 +/- 0.00232\n", - " 19/1 1.06363 1.04155 +/- 0.00344\n", - " 20/1 1.06549 1.04394 +/- 0.00390\n", - " 21/1 1.03469 1.04310 +/- 0.00362\n", - " 22/1 1.01925 1.04111 +/- 0.00386\n", - " 23/1 1.03268 1.04046 +/- 0.00361\n", - " 24/1 1.03906 1.04036 +/- 0.00334\n", - " 25/1 1.02632 1.03943 +/- 0.00325\n", - " 26/1 1.03906 1.03940 +/- 0.00304\n", - " 27/1 1.05058 1.04006 +/- 0.00293\n", - " 28/1 1.03248 1.03964 +/- 0.00279\n", - " 29/1 1.04076 1.03970 +/- 0.00264\n", - " 30/1 1.00994 1.03821 +/- 0.00292\n", - " 31/1 1.04785 1.03867 +/- 0.00281\n", - " 32/1 1.03080 1.03831 +/- 0.00270\n", - " 33/1 1.01862 1.03746 +/- 0.00272\n", - " 34/1 1.05370 1.03813 +/- 0.00269\n", - " 35/1 1.02226 1.03750 +/- 0.00266\n", - " 36/1 1.02862 1.03716 +/- 0.00258\n", - " 37/1 1.04790 1.03755 +/- 0.00251\n", - " 38/1 1.03762 1.03756 +/- 0.00242\n", - " 39/1 1.02255 1.03704 +/- 0.00239\n", - " 40/1 1.06094 1.03784 +/- 0.00245\n", - " 41/1 1.03842 1.03786 +/- 0.00237\n", - " 42/1 1.00628 1.03687 +/- 0.00249\n", - " 43/1 1.04916 1.03724 +/- 0.00245\n", - " 44/1 1.06237 1.03798 +/- 0.00248\n", - " 45/1 1.08153 1.03922 +/- 0.00271\n", - " 46/1 1.05649 1.03970 +/- 0.00268\n", - " 47/1 1.06265 1.04032 +/- 0.00268\n", - " 48/1 1.05728 1.04077 +/- 0.00265\n", - " 49/1 1.07343 1.04161 +/- 0.00271\n", - " 50/1 1.04640 1.04173 +/- 0.00265\n", - " 51/1 1.05143 1.04196 +/- 0.00259\n", - " 52/1 1.03639 1.04183 +/- 0.00253\n", - " 53/1 1.04846 1.04199 +/- 0.00248\n", - " 54/1 1.02435 1.04158 +/- 0.00245\n", - " 55/1 1.04806 1.04173 +/- 0.00240\n", - " 56/1 1.04798 1.04186 +/- 0.00235\n", - " 57/1 1.06621 1.04238 +/- 0.00236\n", - " 58/1 1.05734 1.04269 +/- 0.00233\n", - " 59/1 1.04581 1.04276 +/- 0.00228\n", - " 60/1 1.02682 1.04244 +/- 0.00226\n", - " 61/1 1.05971 1.04278 +/- 0.00224\n", - " 62/1 1.02357 1.04241 +/- 0.00223\n", - " 63/1 1.02645 1.04211 +/- 0.00221\n", - " 64/1 1.00711 1.04146 +/- 0.00226\n", - " 65/1 1.06171 1.04183 +/- 0.00225\n", - " 66/1 1.03444 1.04170 +/- 0.00221\n", - " 67/1 1.05875 1.04199 +/- 0.00219\n", - " 68/1 1.04640 1.04207 +/- 0.00216\n", - " 69/1 1.04376 1.04210 +/- 0.00212\n", - " 70/1 1.07078 1.04258 +/- 0.00214\n", - " 71/1 1.03916 1.04252 +/- 0.00210\n", - " 72/1 1.01843 1.04213 +/- 0.00211\n", - " 73/1 1.03666 1.04205 +/- 0.00207\n", - " 74/1 1.04625 1.04211 +/- 0.00204\n", - " 75/1 1.05277 1.04228 +/- 0.00202\n", - " 76/1 1.04944 1.04238 +/- 0.00199\n", - " 77/1 1.01898 1.04203 +/- 0.00199\n", - " 78/1 1.03283 1.04190 +/- 0.00197\n", - " 79/1 1.02304 1.04163 +/- 0.00196\n", - " 80/1 1.01539 1.04125 +/- 0.00196\n", - " 81/1 1.03988 1.04123 +/- 0.00194\n", - " 82/1 1.02138 1.04096 +/- 0.00193\n", - " 83/1 1.02473 1.04073 +/- 0.00192\n", - " 84/1 1.03810 1.04070 +/- 0.00189\n", - " 85/1 1.07438 1.04115 +/- 0.00192\n", - " 86/1 1.03048 1.04101 +/- 0.00190\n", - " 87/1 1.06778 1.04135 +/- 0.00191\n", - " 88/1 1.07341 1.04177 +/- 0.00192\n", - " 89/1 1.06729 1.04209 +/- 0.00193\n", - " 90/1 1.05069 1.04220 +/- 0.00191\n", - " 91/1 1.07675 1.04262 +/- 0.00193\n", - " 92/1 1.06470 1.04289 +/- 0.00193\n", - " 93/1 1.02609 1.04269 +/- 0.00191\n", - " 94/1 1.04761 1.04275 +/- 0.00189\n", - " 95/1 1.08802 1.04328 +/- 0.00194\n", - " 96/1 1.04162 1.04326 +/- 0.00192\n", - " 97/1 1.04573 1.04329 +/- 0.00190\n", - " 98/1 1.03232 1.04317 +/- 0.00188\n", - " 99/1 1.03473 1.04307 +/- 0.00186\n", - " 100/1 1.04505 1.04309 +/- 0.00184\n", - " Creating state point statepoint.100.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 6.4445e-01 seconds\n", - " Reading cross sections = 6.1129e-01 seconds\n", - " Total time in simulation = 2.0000e+02 seconds\n", - " Time in transport only = 1.9970e+02 seconds\n", - " Time in inactive batches = 2.9966e+00 seconds\n", - " Time in active batches = 1.9701e+02 seconds\n", - " Time synchronizing fission bank = 4.0040e-02 seconds\n", - " Sampling source sites = 3.1522e-02 seconds\n", - " SEND/RECV source sites = 8.3459e-03 seconds\n", - " Time accumulating tallies = 9.3582e-03 seconds\n", - " Total time for finalization = 4.6582e-02 seconds\n", - " Total time elapsed = 2.0072e+02 seconds\n", - " Calculation Rate (inactive) = 16685.4 particles/second\n", - " Calculation Rate (active) = 2284.19 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.04342 +/- 0.00159\n", - " k-effective (Track-length) = 1.04309 +/- 0.00184\n", - " k-effective (Absorption) = 1.04107 +/- 0.00140\n", - " Combined k-effective = 1.04195 +/- 0.00117\n", - " Leakage Fraction = 0.00000 +/- 0.00000\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC!\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created a statepoint file with all the tally data in it. We begin our analysis here loading the statepoint file and 'reading' the results. By default, data from the statepoint file is only read into memory when it is requested. This helps keep the memory use to a minimum even when a statepoint file may be huge." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Load the statepoint file\n", - "sp = openmc.StatePoint('statepoint.100.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we need to get the tally, which can be done with the ``StatePoint.get_tally(...)`` method." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tally\n", - "\tID =\t1\n", - "\tName =\tflux\n", - "\tFilters =\tMeshFilter\n", - "\tNuclides =\ttotal \n", - "\tScores =\t['flux', 'fission']\n", - "\tEstimator =\ttracklength\n", - "\n" - ] - } - ], - "source": [ - "tally = sp.get_tally(scores=['flux'])\n", - "print(tally)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statepoint file actually stores the sum and sum-of-squares for each tally bin from which the mean and variance can be calculated as described [here](http://openmc.readthedocs.io/en/latest/methods/tallies.html#variance). The sum and sum-of-squares can be accessed using the ``sum`` and ``sum_sq`` properties:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[[0.40767451, 0. ]],\n", - "\n", - " [[0.40933814, 0. ]],\n", - "\n", - " [[0.4119165 , 0. ]],\n", - "\n", - " ...,\n", - "\n", - " [[0.40854327, 0. ]],\n", - "\n", - " [[0.40970805, 0. ]],\n", - "\n", - " [[0.40948065, 0. ]]])" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tally.sum" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, the mean and standard deviation of the mean are usually what you are more interested in. The Tally class also has properties ``mean`` and ``std_dev`` which automatically calculate these statistics on-the-fly." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(10000, 1, 2)\n" - ] - }, - { - "data": { - "text/plain": [ - "(array([[[0.00452972, 0. ]],\n", - " \n", - " [[0.0045482 , 0. ]],\n", - " \n", - " [[0.00457685, 0. ]],\n", - " \n", - " ...,\n", - " \n", - " [[0.00453937, 0. ]],\n", - " \n", - " [[0.00455231, 0. ]],\n", - " \n", - " [[0.00454978, 0. ]]]),\n", - " array([[[2.03553236e-05, 0.00000000e+00]],\n", - " \n", - " [[1.83847389e-05, 0.00000000e+00]],\n", - " \n", - " [[1.68647098e-05, 0.00000000e+00]],\n", - " \n", - " ...,\n", - " \n", - " [[1.71606078e-05, 0.00000000e+00]],\n", - " \n", - " [[1.87645811e-05, 0.00000000e+00]],\n", - " \n", - " [[1.94447454e-05, 0.00000000e+00]]]))" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "print(tally.mean.shape)\n", - "(tally.mean, tally.std_dev)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The tally data has three dimensions: one for filter combinations, one for nuclides, and one for scores. We see that there are 10000 filter combinations (corresponding to the 100 x 100 mesh bins), a single nuclide (since none was specified), and two scores. If we only want to look at a single score, we can use the ``get_slice(...)`` method as follows." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tally\n", - "\tID =\t2\n", - "\tName =\tflux\n", - "\tFilters =\tMeshFilter\n", - "\tNuclides =\ttotal \n", - "\tScores =\t['flux']\n", - "\tEstimator =\ttracklength\n", - "\n" - ] - } - ], - "source": [ - "flux = tally.get_slice(scores=['flux'])\n", - "fission = tally.get_slice(scores=['fission'])\n", - "print(flux)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get the bins into a form that we can plot, we can simply change the shape of the array since it is a numpy array." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "flux.std_dev.shape = (100, 100)\n", - "flux.mean.shape = (100, 100)\n", - "fission.std_dev.shape = (100, 100)\n", - "fission.mean.shape = (100, 100)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig = plt.subplot(121)\n", - "fig.imshow(flux.mean)\n", - "fig2 = plt.subplot(122)\n", - "fig2.imshow(fission.mean)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's say we want to look at the distribution of relative errors of our tally bins for flux. First we create a new variable called ``relative_error`` and set it to the ratio of the standard deviation and the mean, being careful not to divide by zero in case some bins were never scored to." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Determine relative error\n", - "relative_error = np.zeros_like(flux.std_dev)\n", - "nonzero = flux.mean > 0\n", - "relative_error[nonzero] = flux.std_dev[nonzero] / flux.mean[nonzero]\n", - "\n", - "# distribution of relative errors\n", - "ret = plt.hist(relative_error[nonzero], bins=50)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Source Sites" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Source sites can be accessed from the ``source`` property. As shown below, the source sites are represented as a numpy array with a structured datatype." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([((-0.28690552, -0.23731283, 0.51447853), ( 0.02705364, -0.14292142, 0.98936422), 1780128.70101981, 1., 0, 0),\n", - " ((-0.28690552, -0.23731283, 0.51447853), (-0.16786951, 0.86432444, -0.47409186), 1553436.10501094, 1., 0, 0),\n", - " (( 0.17162994, 0.134092 , 0.42932363), ( 0.25199134, -0.11168216, 0.96126347), 829530.02360943, 1., 0, 0),\n", - " ...,\n", - " ((-0.24444068, -0.01351615, -0.41772172), ( 0.10437178, -0.86754673, 0.486281 ), 807617.55637656, 1., 0, 0),\n", - " ((-0.2146841 , 0.14307096, 0.07419328), ( 0.89645066, -0.35557279, -0.26446968), 6036005.44157462, 1., 0, 0),\n", - " ((-0.2146841 , 0.14307096, 0.07419328), (-0.95287644, -0.25857878, 0.15863005), 4923751.04163063, 1., 0, 0)],\n", - " dtype=[('r', [('x', '" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Create log-spaced energy bins from 1 keV to 10 MeV\n", - "energy_bins = np.logspace(3,7)\n", - "\n", - "# Calculate pdf for source energies\n", - "probability, bin_edges = np.histogram(sp.source['E'], energy_bins, density=True)\n", - "\n", - "# Make sure integrating the PDF gives us unity\n", - "print(sum(probability*np.diff(energy_bins)))\n", - "\n", - "# Plot source energy PDF\n", - "plt.semilogx(energy_bins[:-1], probability*np.diff(energy_bins), linestyle='steps')\n", - "plt.xlabel('Energy (eV)')\n", - "plt.ylabel('Probability/eV')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's also look at the spatial distribution of the sites. To make the plot a little more interesting, we can also include the direction of the particle emitted from the source and color each source by the logarithm of its energy." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(-0.5, 0.5)" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.quiver(sp.source['r']['x'], sp.source['r']['y'],\n", - " sp.source['u']['x'], sp.source['u']['y'],\n", - " np.log(sp.source['E']), cmap='jet', scale=20.0)\n", - "plt.colorbar()\n", - "plt.xlim((-0.5,0.5))\n", - "plt.ylim((-0.5,0.5))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/search.ipynb b/examples/jupyter/search.ipynb deleted file mode 100644 index bfdc20695..000000000 --- a/examples/jupyter/search.ipynb +++ /dev/null @@ -1,352 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This Notebook illustrates the usage of the OpenMC Python API's generic eigenvalue search capability. In this Notebook, we will do a critical boron concentration search of a typical PWR pin cell.\n", - "\n", - "To use the search functionality, we must create a function which creates our model according to the input parameter we wish to search for (in this case, the boron concentration). \n", - "\n", - "This notebook will first create that function, and then, run the search." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize third-party libraries and the OpenMC Python API\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "import openmc\n", - "import openmc.model\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Create Parametrized Model\n", - "\n", - "To perform the search we will use the `openmc.search_for_keff` function. This function requires a different function be defined which creates an parametrized model to analyze. This model is required to be stored in an `openmc.model.Model` object. The first parameter of this function will be modified during the search process for our critical eigenvalue.\n", - "\n", - "Our model will be a pin-cell from the [Multi-Group Mode Part II](http://docs.openmc.org/en/latest/examples/mg-mode-part-ii.html) assembly, except this time the entire model building process will be contained within a function, and the Boron concentration will be parametrized." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# Create the model. `ppm_Boron` will be the parametric variable.\n", - "\n", - "def build_model(ppm_Boron):\n", - " # Create the pin materials\n", - " fuel = openmc.Material(name='1.6% Fuel')\n", - " fuel.set_density('g/cm3', 10.31341)\n", - " fuel.add_element('U', 1., enrichment=1.6)\n", - " fuel.add_element('O', 2.)\n", - "\n", - " zircaloy = openmc.Material(name='Zircaloy')\n", - " zircaloy.set_density('g/cm3', 6.55)\n", - " zircaloy.add_element('Zr', 1.)\n", - "\n", - " water = openmc.Material(name='Borated Water')\n", - " water.set_density('g/cm3', 0.741)\n", - " water.add_element('H', 2.)\n", - " water.add_element('O', 1.)\n", - "\n", - " # Include the amount of boron in the water based on the ppm,\n", - " # neglecting the other constituents of boric acid\n", - " water.add_element('B', ppm_Boron * 1e-6)\n", - " \n", - " # Instantiate a Materials object\n", - " materials = openmc.Materials([fuel, zircaloy, water])\n", - " \n", - " # Create cylinders for the fuel and clad\n", - " fuel_outer_radius = openmc.ZCylinder(r=0.39218)\n", - " clad_outer_radius = openmc.ZCylinder(r=0.45720)\n", - "\n", - " # Create boundary planes to surround the geometry\n", - " min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", - " max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", - " min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", - " max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", - "\n", - " # Create fuel Cell\n", - " fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - " fuel_cell.fill = fuel\n", - " fuel_cell.region = -fuel_outer_radius\n", - "\n", - " # Create a clad Cell\n", - " clad_cell = openmc.Cell(name='1.6% Clad')\n", - " clad_cell.fill = zircaloy\n", - " clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "\n", - " # Create a moderator Cell\n", - " moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - " moderator_cell.fill = water\n", - " moderator_cell.region = +clad_outer_radius & (+min_x & -max_x & +min_y & -max_y)\n", - "\n", - " # Create root Universe\n", - " root_universe = openmc.Universe(name='root universe', universe_id=0)\n", - " root_universe.add_cells([fuel_cell, clad_cell, moderator_cell])\n", - "\n", - " # Create Geometry and set root universe\n", - " geometry = openmc.Geometry(root_universe)\n", - " \n", - " # Finish with the settings file\n", - " settings = openmc.Settings()\n", - " settings.batches = 300\n", - " settings.inactive = 20\n", - " settings.particles = 1000\n", - " settings.run_mode = 'eigenvalue'\n", - "\n", - " # Create an initial uniform spatial source distribution over fissionable zones\n", - " bounds = [-0.63, -0.63, -10, 0.63, 0.63, 10.]\n", - " uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - " settings.source = openmc.source.Source(space=uniform_dist)\n", - "\n", - " # We dont need a tallies file so dont waste the disk input/output time\n", - " settings.output = {'tallies': False}\n", - " \n", - " model = openmc.model.Model(geometry, materials, settings)\n", - " \n", - " return model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Search for the Critical Boron Concentration\n", - "\n", - "To perform the search we imply call the `openmc.search_for_keff` function and pass in the relvant arguments. For our purposes we will be passing in the model building function (`build_model` defined above), a bracketed range for the expected critical Boron concentration (1,000 to 2,500 ppm), the tolerance, and the method we wish to use. \n", - "\n", - "Instead of the bracketed range we could have used a single initial guess, but have elected not to in this example. Finally, due to the high noise inherent in using as few histories as are used in this example, our tolerance on the final keff value will be rather large (1.e-2) and a bisection method will be used for the search." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 1; Guess of 1.00e+03 produced a keff of 1.08853 +/- 0.00158\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 2; Guess of 2.50e+03 produced a keff of 0.95372 +/- 0.00148\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 3; Guess of 1.75e+03 produced a keff of 1.01328 +/- 0.00169\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 4; Guess of 2.12e+03 produced a keff of 0.98150 +/- 0.00158\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 5; Guess of 1.94e+03 produced a keff of 0.99886 +/- 0.00146\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 6; Guess of 1.84e+03 produced a keff of 1.00759 +/- 0.00162\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 7; Guess of 1.89e+03 produced a keff of 1.00063 +/- 0.00166\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 8; Guess of 1.91e+03 produced a keff of 0.99970 +/- 0.00150\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", - " warn(msg, IDWarning)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Iteration: 9; Guess of 1.90e+03 produced a keff of 0.99935 +/- 0.00164\n", - "Critical Boron Concentration: 1902 ppm\n" - ] - } - ], - "source": [ - "# Perform the search\n", - "crit_ppm, guesses, keffs = openmc.search_for_keff(build_model, bracket=[1000., 2500.],\n", - " tol=1e-2, bracketed_method='bisect',\n", - " print_iterations=True)\n", - "\n", - "print('Critical Boron Concentration: {:4.0f} ppm'.format(crit_ppm))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, the `openmc.search_for_keff` function also provided us with `List`s of the guesses and corresponding keff values generated during the search process with OpenMC. Let's use that information to make a quick plot of the value of keff versus the boron concentration." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(8, 4.5))\n", - "plt.title('Eigenvalue versus Boron Concentration')\n", - "# Create a scatter plot using the mean value of keff\n", - "plt.scatter(guesses, [keffs[i].nominal_value for i in range(len(keffs))])\n", - "plt.xlabel('Boron Concentration [ppm]')\n", - "plt.ylabel('Eigenvalue')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "We see a nearly linear reactivity coefficient for the boron concentration, exactly as one would expect for a pure 1/v absorber at small concentrations." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/jupyter/tally-arithmetic.ipynb b/examples/jupyter/tally-arithmetic.ipynb deleted file mode 100644 index 40eb2b05f..000000000 --- a/examples/jupyter/tally-arithmetic.ipynb +++ /dev/null @@ -1,1753 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook shows the how tallies can be combined (added, subtracted, multiplied, etc.) using the Python API in order to create derived tallies. Since no covariance information is obtained, it is assumed that tallies are completely independent of one another when propagating uncertainties. The target problem is a simple pin cell." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import glob\n", - "\n", - "from IPython.display import Image\n", - "import numpy as np\n", - "import openmc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate Input Files" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we need to define materials that will be used in the problem. We'll create three materials for the fuel, water, and cladding of the fuel pin." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# 1.6 enriched fuel\n", - "fuel = openmc.Material(name='1.6% Fuel')\n", - "fuel.set_density('g/cm3', 10.31341)\n", - "fuel.add_nuclide('U235', 3.7503e-4)\n", - "fuel.add_nuclide('U238', 2.2625e-2)\n", - "fuel.add_nuclide('O16', 4.6007e-2)\n", - "\n", - "# borated water\n", - "water = openmc.Material(name='Borated Water')\n", - "water.set_density('g/cm3', 0.740582)\n", - "water.add_nuclide('H1', 4.9457e-2)\n", - "water.add_nuclide('O16', 2.4732e-2)\n", - "water.add_nuclide('B10', 8.0042e-6)\n", - "\n", - "# zircaloy\n", - "zircaloy = openmc.Material(name='Zircaloy')\n", - "zircaloy.set_density('g/cm3', 6.55)\n", - "zircaloy.add_nuclide('Zr90', 7.2758e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With our three materials, we can now create a materials file object that can be exported to an actual XML file." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate a Materials collection\n", - "materials_file = openmc.Materials([fuel, water, zircaloy])\n", - "\n", - "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's move on to the geometry. Our problem will have three regions for the fuel, the clad, and the surrounding coolant. The first step is to create the bounding surfaces -- in this case two cylinders and six planes." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Create cylinders for the fuel and clad\n", - "fuel_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.39218)\n", - "clad_outer_radius = openmc.ZCylinder(x0=0.0, y0=0.0, r=0.45720)\n", - "\n", - "# Create boundary planes to surround the geometry\n", - "# Use both reflective and vacuum boundaries to make life interesting\n", - "min_x = openmc.XPlane(x0=-0.63, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=+0.63, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-0.63, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=+0.63, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-100., boundary_type='vacuum')\n", - "max_z = openmc.ZPlane(z0=+100., boundary_type='vacuum')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the surfaces defined, we can now create cells that are defined by intersections of half-spaces created by the surfaces." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a Universe to encapsulate a fuel pin\n", - "pin_cell_universe = openmc.Universe(name='1.6% Fuel Pin')\n", - "\n", - "# Create fuel Cell\n", - "fuel_cell = openmc.Cell(name='1.6% Fuel')\n", - "fuel_cell.fill = fuel\n", - "fuel_cell.region = -fuel_outer_radius\n", - "pin_cell_universe.add_cell(fuel_cell)\n", - "\n", - "# Create a clad Cell\n", - "clad_cell = openmc.Cell(name='1.6% Clad')\n", - "clad_cell.fill = zircaloy\n", - "clad_cell.region = +fuel_outer_radius & -clad_outer_radius\n", - "pin_cell_universe.add_cell(clad_cell)\n", - "\n", - "# Create a moderator Cell\n", - "moderator_cell = openmc.Cell(name='1.6% Moderator')\n", - "moderator_cell.fill = water\n", - "moderator_cell.region = +clad_outer_radius\n", - "pin_cell_universe.add_cell(moderator_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC requires that there is a \"root\" universe. Let us create a root cell that is filled by the pin cell universe and then assign it to the root universe." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Create root Cell\n", - "root_cell = openmc.Cell(name='root cell')\n", - "root_cell.fill = pin_cell_universe\n", - "\n", - "# Add boundary planes\n", - "root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z\n", - "\n", - "# Create root Universe\n", - "root_universe = openmc.Universe(universe_id=0, name='root universe')\n", - "root_universe.add_cell(root_cell)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now must create a geometry that is assigned a root universe, put the geometry into a geometry file, and export it to XML." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Geometry and set root Universe\n", - "geometry = openmc.Geometry(root_universe)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# Export to \"geometry.xml\"\n", - "geometry.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the geometry and materials finished, we now just need to define simulation parameters. In this case, we will use 5 inactive batches and 15 active batches each with 2500 particles." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# OpenMC simulation parameters\n", - "batches = 20\n", - "inactive = 5\n", - "particles = 2500\n", - "\n", - "# Instantiate a Settings object\n", - "settings_file = openmc.Settings()\n", - "settings_file.batches = batches\n", - "settings_file.inactive = inactive\n", - "settings_file.particles = particles\n", - "settings_file.output = {'tallies': True}\n", - "\n", - "# Create an initial uniform spatial source distribution over fissionable zones\n", - "bounds = [-0.63, -0.63, -100., 0.63, 0.63, 100.]\n", - "uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n", - "settings_file.source = openmc.Source(space=uniform_dist)\n", - "\n", - "# Export to \"settings.xml\"\n", - "settings_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us also create a plot file that we can use to verify that our pin cell geometry was created successfully." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEVyEhLpgJFNv8T///98iBL0AAAAAWJLR0QDEQxM8gAAAAd0SU1FB+MHEhEzAhO1TdMAAAKlSURBVGje7ZrBscIwDETxwSWkn5TAgXCgBPqhBA6kyj/fDhCIJa2zZAwz0pmHpZWdSazd7Tw8PDw8PDw8vinCMBzW03HIsRLvhnv0HL7qD+IwjzXKzaNaxeEt9kz21RWEBV5XQbfka3pQWL4qgdLyNQkUcbwFT/FP4zjWt+D+++OY4laZQJgtnqNOwe5l9XkGmIIL/PEHUAGTeuc5P15wBbu34ucSIAXkX77h4xUtIBSXnxIAOhCLy98TANNfLj8lYBYQCuLPWmAWEBe9f90DUPdKy08JWB0U1HsoaAgQxPSnAgwBopz+VABQvoDnAnqTP0r8zealzfPcQqqAQSs/C6AKGLX0pwKs8uX0cwGaAHr6uYC9wSt46qDCB4RXBDTkMwWMhnxZQF3+s8pf1AZY5VsCWuVnAUQ+YPxB43X5koAiH035soCa/AaeBOw34m359AaQPCK/1oAAyJ8aIPBI+7QGRkD+3IBt+A6QPzeg34SH2pcauN+Kt9uXGljkse0jb6BP8AD+vwGKPLZ95A0UofbnDbAFj20/eQN+gD8h/LgRD25/8QCA2088AD/Oo8dPOoDo8ZMOoPPNeej4pwdAgUcfX9IDzHnnf5lnz88XnH/nSf4M8cIL7I+/P3yCP0G88P7W+v2z9ft36+8P9vuJ/X5r/f3Jfj83//5vff/R+v6Hvb9i78/Y+7vW94/N71/Z+2P2/pq9P2fv7+n5ATu/YOcn7PyGnR+x8yt6ftYN3PzOENCcH7LzS3Z+Ss9vO62DV5uPmgAXSz5+fs7O72n/QBQLwPwLrH+C9W/Q/hHWv8L6Z2j/ThZgvX+I9S/R/inWv8X6x2j/Guufo/17rH+Q9S/S/knWv0n7R2n/Kuufpf27tH+Y9i/vWP+0h4eHh4eHh8cW8QcxLJDBvLKoigAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wNy0xOFQyMjo1MTowMi0wNTowMAMmdtQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDctMThUMjI6NTE6MDItMDU6MDBye85oAAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Instantiate a Plot\n", - "plot = openmc.Plot(plot_id=1)\n", - "plot.filename = 'materials-xy'\n", - "plot.origin = [0, 0, 0]\n", - "plot.width = [1.26, 1.26]\n", - "plot.pixels = [250, 250]\n", - "plot.color_by = 'material'\n", - "\n", - "# Show plot\n", - "openmc.plot_inline(plot)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see from the plot, we have a nice pin cell with fuel, cladding, and water! Before we run our simulation, we need to tell the code what we want to tally. The following code shows how to create a variety of tallies." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate an empty Tallies object\n", - "tallies_file = openmc.Tallies()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# Create Tallies to compute microscopic multi-group cross-sections\n", - "\n", - "# Instantiate energy filter for multi-group cross-section Tallies\n", - "energy_filter = openmc.EnergyFilter([0., 0.625, 20.0e6])\n", - "\n", - "# Instantiate flux Tally in moderator and fuel\n", - "tally = openmc.Tally(name='flux')\n", - "tally.filters = [openmc.CellFilter([fuel_cell, moderator_cell])]\n", - "tally.filters.append(energy_filter)\n", - "tally.scores = ['flux']\n", - "tallies_file.append(tally)\n", - "\n", - "# Instantiate reaction rate Tally in fuel\n", - "tally = openmc.Tally(name='fuel rxn rates')\n", - "tally.filters = [openmc.CellFilter(fuel_cell)]\n", - "tally.filters.append(energy_filter)\n", - "tally.scores = ['nu-fission', 'scatter']\n", - "tally.nuclides = ['U238', 'U235']\n", - "tallies_file.append(tally)\n", - "\n", - "# Instantiate reaction rate Tally in moderator\n", - "tally = openmc.Tally(name='moderator rxn rates')\n", - "tally.filters = [openmc.CellFilter(moderator_cell)]\n", - "tally.filters.append(energy_filter)\n", - "tally.scores = ['absorption', 'total']\n", - "tally.nuclides = ['O16', 'H1']\n", - "tallies_file.append(tally)\n", - "\n", - "# Instantiate a tally mesh\n", - "mesh = openmc.RegularMesh(mesh_id=1)\n", - "mesh.dimension = [1, 1, 1]\n", - "mesh.lower_left = [-0.63, -0.63, -100.]\n", - "mesh.width = [1.26, 1.26, 200.]\n", - "meshsurface_filter = openmc.MeshSurfaceFilter(mesh)\n", - "\n", - "# Instantiate thermal, fast, and total leakage tallies\n", - "leak = openmc.Tally(name='leakage')\n", - "leak.filters = [meshsurface_filter]\n", - "leak.scores = ['current']\n", - "tallies_file.append(leak)\n", - "\n", - "thermal_leak = openmc.Tally(name='thermal leakage')\n", - "thermal_leak.filters = [meshsurface_filter, openmc.EnergyFilter([0., 0.625])]\n", - "thermal_leak.scores = ['current']\n", - "tallies_file.append(thermal_leak)\n", - "\n", - "fast_leak = openmc.Tally(name='fast leakage')\n", - "fast_leak.filters = [meshsurface_filter, openmc.EnergyFilter([0.625, 20.0e6])]\n", - "fast_leak.scores = ['current']\n", - "tallies_file.append(fast_leak)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# K-Eigenvalue (infinity) tallies\n", - "fiss_rate = openmc.Tally(name='fiss. rate')\n", - "abs_rate = openmc.Tally(name='abs. rate')\n", - "fiss_rate.scores = ['nu-fission']\n", - "abs_rate.scores = ['absorption']\n", - "tallies_file += (fiss_rate, abs_rate)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Resonance Escape Probability tallies\n", - "therm_abs_rate = openmc.Tally(name='therm. abs. rate')\n", - "therm_abs_rate.scores = ['absorption']\n", - "therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625])]\n", - "tallies_file.append(therm_abs_rate)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Thermal Flux Utilization tallies\n", - "fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate')\n", - "fuel_therm_abs_rate.scores = ['absorption']\n", - "fuel_therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625]),\n", - " openmc.CellFilter([fuel_cell])]\n", - "tallies_file.append(fuel_therm_abs_rate)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# Fast Fission Factor tallies\n", - "therm_fiss_rate = openmc.Tally(name='therm. fiss. rate')\n", - "therm_fiss_rate.scores = ['nu-fission']\n", - "therm_fiss_rate.filters = [openmc.EnergyFilter([0., 0.625])]\n", - "tallies_file.append(therm_fiss_rate)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiate energy filter to illustrate Tally slicing\n", - "fine_energy_filter = openmc.EnergyFilter(np.logspace(np.log10(1e-2), np.log10(20.0e6), 10))\n", - "\n", - "# Instantiate flux Tally in moderator and fuel\n", - "tally = openmc.Tally(name='need-to-slice')\n", - "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", - "tallies_file.append(tally)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=6.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=3.\n", - " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", - " warn(msg, IDWarning)\n" - ] - } - ], - "source": [ - "# Export to \"tallies.xml\"\n", - "tallies_file.export_to_xml()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we a have a complete set of inputs, so we can go ahead and run our simulation." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " %%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n", - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n", - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%%%%%%\n", - " ##################### %%%%%%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%%\n", - " ####################### %%%%%%%%%%%%%%%%%\n", - " ###################### %%%%%%%%%%%%%%%%%\n", - " #################### %%%%%%%%%%%%%%%%%\n", - " ################# %%%%%%%%%%%%%%%%%\n", - " ############### %%%%%%%%%%%%%%%%\n", - " ############ %%%%%%%%%%%%%%%\n", - " ######## %%%%%%%%%%%%%%\n", - " %%%%%%%%%%%\n", - "\n", - " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2019 MIT and OpenMC contributors\n", - " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.11.0-dev\n", - " Git SHA1 | 61c911cffdae2406f9f4bc667a9a6954748bb70c\n", - " Date/Time | 2019-07-18 22:51:02\n", - " OpenMP Threads | 4\n", - "\n", - " Reading settings XML file...\n", - " Reading cross sections XML file...\n", - " Reading materials XML file...\n", - " Reading geometry XML file...\n", - " Reading U235 from /opt/data/hdf5/nndc_hdf5_v15/U235.h5\n", - " Reading U238 from /opt/data/hdf5/nndc_hdf5_v15/U238.h5\n", - " Reading O16 from /opt/data/hdf5/nndc_hdf5_v15/O16.h5\n", - " Reading H1 from /opt/data/hdf5/nndc_hdf5_v15/H1.h5\n", - " Reading B10 from /opt/data/hdf5/nndc_hdf5_v15/B10.h5\n", - " Reading Zr90 from /opt/data/hdf5/nndc_hdf5_v15/Zr90.h5\n", - " Maximum neutron transport energy: 20000000.000000 eV for U235\n", - " Reading tallies XML file...\n", - " Writing summary.h5 file...\n", - " Initializing source particles...\n", - "\n", - " ====================> K EIGENVALUE SIMULATION <====================\n", - "\n", - " Bat./Gen. k Average k\n", - " ========= ======== ====================\n", - " 1/1 0.96168\n", - " 2/1 0.96651\n", - " 3/1 1.00678\n", - " 4/1 0.98773\n", - " 5/1 1.01883\n", - " 6/1 1.02959\n", - " 7/1 0.99859 1.01409 +/- 0.01550\n", - " 8/1 1.03441 1.02086 +/- 0.01123\n", - " 9/1 1.06097 1.03089 +/- 0.01279\n", - " 10/1 1.06132 1.03698 +/- 0.01163\n", - " 11/1 1.04687 1.03863 +/- 0.00964\n", - " 12/1 1.02982 1.03737 +/- 0.00824\n", - " 13/1 1.03520 1.03710 +/- 0.00714\n", - " 14/1 0.99508 1.03243 +/- 0.00784\n", - " 15/1 1.03987 1.03317 +/- 0.00705\n", - " 16/1 1.02743 1.03265 +/- 0.00640\n", - " 17/1 1.02975 1.03241 +/- 0.00585\n", - " 18/1 0.99671 1.02966 +/- 0.00604\n", - " 19/1 1.02040 1.02900 +/- 0.00563\n", - " 20/1 1.02024 1.02842 +/- 0.00527\n", - " Creating state point statepoint.20.h5...\n", - "\n", - " =======================> TIMING STATISTICS <=======================\n", - "\n", - " Total time for initialization = 3.4427e-01 seconds\n", - " Reading cross sections = 3.1628e-01 seconds\n", - " Total time in simulation = 3.7319e+00 seconds\n", - " Time in transport only = 3.6302e+00 seconds\n", - " Time in inactive batches = 4.9601e-01 seconds\n", - " Time in active batches = 3.2359e+00 seconds\n", - " Time synchronizing fission bank = 2.8100e-03 seconds\n", - " Sampling source sites = 2.4682e-03 seconds\n", - " SEND/RECV source sites = 3.2484e-04 seconds\n", - " Time accumulating tallies = 4.4538e-05 seconds\n", - " Total time for finalization = 9.3656e-04 seconds\n", - " Total time elapsed = 4.0859e+00 seconds\n", - " Calculation Rate (inactive) = 25201.2 particles/second\n", - " Calculation Rate (active) = 11588.7 particles/second\n", - "\n", - " ============================> RESULTS <============================\n", - "\n", - " k-effective (Collision) = 1.02889 +/- 0.00492\n", - " k-effective (Track-length) = 1.02842 +/- 0.00527\n", - " k-effective (Absorption) = 1.02637 +/- 0.00349\n", - " Combined k-effective = 1.02700 +/- 0.00291\n", - " Leakage Fraction = 0.01717 +/- 0.00107\n", - "\n" - ] - } - ], - "source": [ - "# Run OpenMC!\n", - "openmc.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tally Data Processing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our simulation ran successfully and created a statepoint file with all the tally data in it. We begin our analysis here loading the statepoint file and 'reading' the results. By default, the tally results are not read into memory because they might be large, even large enough to exceed the available memory on a computer." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Load the statepoint file\n", - "sp = openmc.StatePoint('statepoint.20.h5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have a tally of the total fission rate and the total absorption rate, so we can calculate k-eff as:\n", - "$$k_{eff} = \\frac{\\langle \\nu \\Sigma_f \\phi \\rangle}{\\langle \\Sigma_a \\phi \\rangle + \\langle L \\rangle}$$\n", - "In this notation, $\\langle \\cdot \\rangle^a_b$ represents an OpenMC that is integrated over region $a$ and energy range $b$. If $a$ or $b$ is not reported, it means the value represents an integral over all space or all energy, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nuclidescoremeanstd. dev.
0total(nu-fission / (absorption + current))1.0230020.006647
\n", - "
" - ], - "text/plain": [ - " nuclide score mean std. dev.\n", - "0 total (nu-fission / (absorption + current)) 1.02e+00 6.65e-03" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get the fission and absorption rate tallies\n", - "fiss_rate = sp.get_tally(name='fiss. rate')\n", - "abs_rate = sp.get_tally(name='abs. rate')\n", - "\n", - "# Get the leakage tally\n", - "leak = sp.get_tally(name='leakage')\n", - "leak = leak.summation(filter_type=openmc.MeshSurfaceFilter, remove_filter=True)\n", - "\n", - "# Compute k-infinity using tally arithmetic\n", - "keff = fiss_rate / (abs_rate + leak)\n", - "keff.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that even though the neutron production rate, absorption rate, and current are separate tallies, we still get a first-order estimate of the uncertainty on the quotient of them automatically!\n", - "\n", - "Often in textbooks you'll see k-eff represented using the six-factor formula $$k_{eff} = p \\epsilon f \\eta P_{FNL} P_{TNL}.$$ Let's analyze each of these factors, starting with the resonance escape probability which is defined as $$p=\\frac{\\langle\\Sigma_a\\phi\\rangle_T + \\langle L \\rangle_T}{\\langle\\Sigma_a\\phi\\rangle + \\langle L \\rangle_T}$$ where the subscript $T$ means thermal energies." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]nuclidescoremeanstd. dev.
00.00.625total((absorption + current) / (absorption + current))0.6943680.004606
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] nuclide \\\n", - "0 0.00e+00 6.25e-01 total \n", - "\n", - " score mean std. dev. \n", - "0 ((absorption + current) / (absorption + current)) 6.94e-01 4.61e-03 " - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Compute resonance escape probability using tally arithmetic\n", - "therm_abs_rate = sp.get_tally(name='therm. abs. rate')\n", - "thermal_leak = sp.get_tally(name='thermal leakage')\n", - "thermal_leak = thermal_leak.summation(filter_type=openmc.MeshSurfaceFilter, remove_filter=True)\n", - "res_esc = (therm_abs_rate + thermal_leak) / (abs_rate + thermal_leak)\n", - "res_esc.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The fast fission factor can be calculated as\n", - "$$\\epsilon=\\frac{\\langle\\nu\\Sigma_f\\phi\\rangle}{\\langle\\nu\\Sigma_f\\phi\\rangle_T}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]nuclidescoremeanstd. dev.
00.00.625total(nu-fission / nu-fission)1.2030990.009615
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] nuclide score \\\n", - "0 0.00e+00 6.25e-01 total (nu-fission / nu-fission) \n", - "\n", - " mean std. dev. \n", - "0 1.20e+00 9.61e-03 " - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Compute fast fission factor factor using tally arithmetic\n", - "therm_fiss_rate = sp.get_tally(name='therm. fiss. rate')\n", - "fast_fiss = fiss_rate / therm_fiss_rate\n", - "fast_fiss.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The thermal flux utilization is calculated as\n", - "$$f=\\frac{\\langle\\Sigma_a\\phi\\rangle^F_T}{\\langle\\Sigma_a\\phi\\rangle_T}$$\n", - "where the superscript $F$ denotes fuel." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]cellnuclidescoremeanstd. dev.
00.00.6251total(absorption / absorption)0.7494230.006089
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] cell nuclide score \\\n", - "0 0.00e+00 6.25e-01 1 total (absorption / absorption) \n", - "\n", - " mean std. dev. \n", - "0 7.49e-01 6.09e-03 " - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Compute thermal flux utilization factor using tally arithmetic\n", - "fuel_therm_abs_rate = sp.get_tally(name='fuel therm. abs. rate')\n", - "therm_util = fuel_therm_abs_rate / therm_abs_rate\n", - "therm_util.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next factor is the number of fission neutrons produced per absorption in fuel, calculated as $$\\eta = \\frac{\\langle \\nu\\Sigma_f\\phi \\rangle_T}{\\langle \\Sigma_a \\phi \\rangle^F_T}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]cellnuclidescoremeanstd. dev.
00.00.6251total(nu-fission / absorption)1.6637270.014403
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] cell nuclide score \\\n", - "0 0.00e+00 6.25e-01 1 total (nu-fission / absorption) \n", - "\n", - " mean std. dev. \n", - "0 1.66e+00 1.44e-02 " - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Compute neutrons produced per absorption (eta) using tally arithmetic\n", - "eta = therm_fiss_rate / fuel_therm_abs_rate\n", - "eta.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are two leakage factors to account for fast and thermal leakage. The fast non-leakage probability is computed as $$P_{FNL} = \\frac{\\langle \\Sigma_a\\phi \\rangle + \\langle L \\rangle_T}{\\langle \\Sigma_a \\phi \\rangle + \\langle L \\rangle}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]nuclidescoremeanstd. dev.
00.00.625total((absorption + current) / (absorption + current))0.9846680.005509
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] nuclide \\\n", - "0 0.00e+00 6.25e-01 total \n", - "\n", - " score mean std. dev. \n", - "0 ((absorption + current) / (absorption + current)) 9.85e-01 5.51e-03 " - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p_fnl = (abs_rate + thermal_leak) / (abs_rate + leak)\n", - "p_fnl.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final factor is the thermal non-leakage probability and is computed as $$P_{TNL} = \\frac{\\langle \\Sigma_a\\phi \\rangle_T}{\\langle \\Sigma_a \\phi \\rangle_T + \\langle L \\rangle_T}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]nuclidescoremeanstd. dev.
00.00.625total(absorption / (absorption + current))0.9974390.007548
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] nuclide \\\n", - "0 0.00e+00 6.25e-01 total \n", - "\n", - " score mean std. dev. \n", - "0 (absorption / (absorption + current)) 9.97e-01 7.55e-03 " - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p_tnl = therm_abs_rate / (therm_abs_rate + thermal_leak)\n", - "p_tnl.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can calculate $k_{eff}$ using the product of the factors form the four-factor formula." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
energy low [eV]energy high [eV]cellnuclidescoremeanstd. dev.
00.00.6251total(((((((absorption + current) / (absorption + c...1.0230020.018791
\n", - "
" - ], - "text/plain": [ - " energy low [eV] energy high [eV] cell nuclide \\\n", - "0 0.00e+00 6.25e-01 1 total \n", - "\n", - " score mean std. dev. \n", - "0 (((((((absorption + current) / (absorption + c... 1.02e+00 1.88e-02 " - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "keff = res_esc * fast_fiss * therm_util * eta * p_fnl * p_tnl\n", - "keff.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that the value we've obtained here has exactly the same mean as before. However, because of the way it was calculated, the standard deviation appears to be larger.\n", - "\n", - "Let's move on to a more complicated example now. Before we set up tallies to get reaction rates in the fuel and moderator in two energy groups for two different nuclides. We can use tally arithmetic to divide each of these reaction rates by the flux to get microscopic multi-group cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Compute microscopic multi-group cross-sections\n", - "flux = sp.get_tally(name='flux')\n", - "flux = flux.get_slice(filters=[openmc.CellFilter], filter_bins=[(fuel_cell.id,)])\n", - "fuel_rxn_rates = sp.get_tally(name='fuel rxn rates')\n", - "mod_rxn_rates = sp.get_tally(name='moderator rxn rates')" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01(U238 / total)(nu-fission / flux)6.659486e-075.627975e-09
110.0006.250000e-01(U238 / total)(scatter / flux)2.099901e-011.748379e-03
210.0006.250000e-01(U235 / total)(nu-fission / flux)3.566329e-013.030782e-03
310.0006.250000e-01(U235 / total)(scatter / flux)5.555466e-034.635318e-05
410.6252.000000e+07(U238 / total)(nu-fission / flux)7.251304e-035.161998e-05
510.6252.000000e+07(U238 / total)(scatter / flux)2.272661e-019.576939e-04
610.6252.000000e+07(U235 / total)(nu-fission / flux)7.920169e-035.751231e-05
710.6252.000000e+07(U235 / total)(scatter / flux)3.358280e-031.341281e-05
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide \\\n", - "0 1 0.00e+00 6.25e-01 (U238 / total) \n", - "1 1 0.00e+00 6.25e-01 (U238 / total) \n", - "2 1 0.00e+00 6.25e-01 (U235 / total) \n", - "3 1 0.00e+00 6.25e-01 (U235 / total) \n", - "4 1 6.25e-01 2.00e+07 (U238 / total) \n", - "5 1 6.25e-01 2.00e+07 (U238 / total) \n", - "6 1 6.25e-01 2.00e+07 (U235 / total) \n", - "7 1 6.25e-01 2.00e+07 (U235 / total) \n", - "\n", - " score mean std. dev. \n", - "0 (nu-fission / flux) 6.66e-07 5.63e-09 \n", - "1 (scatter / flux) 2.10e-01 1.75e-03 \n", - "2 (nu-fission / flux) 3.57e-01 3.03e-03 \n", - "3 (scatter / flux) 5.56e-03 4.64e-05 \n", - "4 (nu-fission / flux) 7.25e-03 5.16e-05 \n", - "5 (scatter / flux) 2.27e-01 9.58e-04 \n", - "6 (nu-fission / flux) 7.92e-03 5.75e-05 \n", - "7 (scatter / flux) 3.36e-03 1.34e-05 " - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fuel_xs = fuel_rxn_rates / flux\n", - "fuel_xs.get_pandas_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We see that when the two tallies with multiple bins were divided, the derived tally contains the outer product of the combinations. If the filters/scores are the same, no outer product is needed. The `get_values(...)` method allows us to obtain a subset of tally scores. In the following example, we obtain just the neutron production microscopic cross sections." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[6.65948580e-07]\n", - " [3.56632881e-01]]\n", - "\n", - " [[7.25130446e-03]\n", - " [7.92016892e-03]]]\n" - ] - } - ], - "source": [ - "# Show how to use Tally.get_values(...) with a CrossScore\n", - "nu_fiss_xs = fuel_xs.get_values(scores=['(nu-fission / flux)'])\n", - "print(nu_fiss_xs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The same idea can be used not only for scores but also for filters and nuclides." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[0.00555547]]\n", - "\n", - " [[0.00335828]]]\n" - ] - } - ], - "source": [ - "# Show how to use Tally.get_values(...) with a CrossScore and CrossNuclide\n", - "u235_scatter_xs = fuel_xs.get_values(nuclides=['(U235 / total)'], \n", - " scores=['(scatter / flux)'])\n", - "print(u235_scatter_xs)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[0.22726611]\n", - " [0.00335828]]]\n" - ] - } - ], - "source": [ - "# Show how to use Tally.get_values(...) with a CrossFilter and CrossScore\n", - "fast_scatter_xs = fuel_xs.get_values(filters=[openmc.EnergyFilter], \n", - " filter_bins=[((0.625, 20.0e6),)], \n", - " scores=['(scatter / flux)'])\n", - "print(fast_scatter_xs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A more advanced method is to use `get_slice(...)` to create a new derived tally that is a subset of an existing tally. This has the benefit that we can use `get_pandas_dataframe()` to see the tallies in a more human-readable format." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
010.0006.250000e-01U238nu-fission0.0000029.679304e-09
110.0006.250000e-01U235nu-fission0.8548055.239673e-03
210.6252.000000e+07U238nu-fission0.0829785.346135e-04
310.6252.000000e+07U235nu-fission0.0906325.981942e-04
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide score mean \\\n", - "0 1 0.00e+00 6.25e-01 U238 nu-fission 1.60e-06 \n", - "1 1 0.00e+00 6.25e-01 U235 nu-fission 8.55e-01 \n", - "2 1 6.25e-01 2.00e+07 U238 nu-fission 8.30e-02 \n", - "3 1 6.25e-01 2.00e+07 U235 nu-fission 9.06e-02 \n", - "\n", - " std. dev. \n", - "0 9.68e-09 \n", - "1 5.24e-03 \n", - "2 5.35e-04 \n", - "3 5.98e-04 " - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# \"Slice\" the nu-fission data into a new derived Tally\n", - "nu_fission_rates = fuel_rxn_rates.get_slice(scores=['nu-fission'])\n", - "nu_fission_rates.get_pandas_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cellenergy low [eV]energy high [eV]nuclidescoremeanstd. dev.
031.000000e-021.080060e-01H1scatter4.5411880.025230
131.080060e-011.166529e+00H1scatter2.0013320.006754
231.166529e+001.259921e+01H1scatter1.6392920.011374
331.259921e+011.360790e+02H1scatter1.8216330.009590
431.360790e+021.469734e+03H1scatter2.0323950.009953
531.469734e+031.587401e+04H1scatter2.1207450.011090
631.587401e+041.714488e+05H1scatter2.1817090.013602
731.714488e+051.851749e+06H1scatter2.0136440.009219
831.851749e+062.000000e+07H1scatter0.3726400.002903
\n", - "
" - ], - "text/plain": [ - " cell energy low [eV] energy high [eV] nuclide score mean \\\n", - "0 3 1.00e-02 1.08e-01 H1 scatter 4.54e+00 \n", - "1 3 1.08e-01 1.17e+00 H1 scatter 2.00e+00 \n", - "2 3 1.17e+00 1.26e+01 H1 scatter 1.64e+00 \n", - "3 3 1.26e+01 1.36e+02 H1 scatter 1.82e+00 \n", - "4 3 1.36e+02 1.47e+03 H1 scatter 2.03e+00 \n", - "5 3 1.47e+03 1.59e+04 H1 scatter 2.12e+00 \n", - "6 3 1.59e+04 1.71e+05 H1 scatter 2.18e+00 \n", - "7 3 1.71e+05 1.85e+06 H1 scatter 2.01e+00 \n", - "8 3 1.85e+06 2.00e+07 H1 scatter 3.73e-01 \n", - "\n", - " std. dev. \n", - "0 2.52e-02 \n", - "1 6.75e-03 \n", - "2 1.14e-02 \n", - "3 9.59e-03 \n", - "4 9.95e-03 \n", - "5 1.11e-02 \n", - "6 1.36e-02 \n", - "7 9.22e-03 \n", - "8 2.90e-03 " - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# \"Slice\" the H-1 scatter data in the moderator Cell into a new derived Tally\n", - "need_to_slice = sp.get_tally(name='need-to-slice')\n", - "slice_test = need_to_slice.get_slice(scores=['scatter'], nuclides=['H1'],\n", - " filters=[openmc.CellFilter], filter_bins=[(moderator_cell.id,)])\n", - "slice_test.get_pandas_dataframe()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/jupyter/triso.ipynb b/examples/jupyter/triso.ipynb deleted file mode 100644 index 1934433e9..000000000 --- a/examples/jupyter/triso.ipynb +++ /dev/null @@ -1,365 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "OpenMC includes a few convenience functions for generationing TRISO particle locations and placing them in a lattice. To be clear, this capability is not a stochastic geometry capability like that included in MCNP. It's also important to note that OpenMC does not use delta tracking, which would normally speed up calculations in geometries with tons of surfaces and cells. However, the computational burden can be eased by placing TRISO particles in a lattice." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "from math import pi\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import openmc\n", - "import openmc.model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's first start by creating materials that will be used in our TRISO particles and the background material." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "fuel = openmc.Material(name='Fuel')\n", - "fuel.set_density('g/cm3', 10.5)\n", - "fuel.add_nuclide('U235', 4.6716e-02)\n", - "fuel.add_nuclide('U238', 2.8697e-01)\n", - "fuel.add_nuclide('O16', 5.0000e-01)\n", - "fuel.add_element('C', 1.6667e-01)\n", - "\n", - "buff = openmc.Material(name='Buffer')\n", - "buff.set_density('g/cm3', 1.0)\n", - "buff.add_element('C', 1.0)\n", - "buff.add_s_alpha_beta('c_Graphite')\n", - "\n", - "PyC1 = openmc.Material(name='PyC1')\n", - "PyC1.set_density('g/cm3', 1.9)\n", - "PyC1.add_element('C', 1.0)\n", - "PyC1.add_s_alpha_beta('c_Graphite')\n", - "\n", - "PyC2 = openmc.Material(name='PyC2')\n", - "PyC2.set_density('g/cm3', 1.87)\n", - "PyC2.add_element('C', 1.0)\n", - "PyC2.add_s_alpha_beta('c_Graphite')\n", - "\n", - "SiC = openmc.Material(name='SiC')\n", - "SiC.set_density('g/cm3', 3.2)\n", - "SiC.add_element('C', 0.5)\n", - "SiC.add_element('Si', 0.5)\n", - "\n", - "graphite = openmc.Material()\n", - "graphite.set_density('g/cm3', 1.1995)\n", - "graphite.add_element('C', 1.0)\n", - "graphite.add_s_alpha_beta('c_Graphite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To actually create individual TRISO particles, we first need to create a universe that will be used within each particle. The reason we use the same universe for each TRISO particle is to reduce the total number of cells/surfaces needed which can substantially improve performance over using unique cells/surfaces in each." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Create TRISO universe\n", - "spheres = [openmc.Sphere(r=1e-4*r)\n", - " for r in [215., 315., 350., 385.]]\n", - "cells = [openmc.Cell(fill=fuel, region=-spheres[0]),\n", - " openmc.Cell(fill=buff, region=+spheres[0] & -spheres[1]),\n", - " openmc.Cell(fill=PyC1, region=+spheres[1] & -spheres[2]),\n", - " openmc.Cell(fill=SiC, region=+spheres[2] & -spheres[3]),\n", - " openmc.Cell(fill=PyC2, region=+spheres[3])]\n", - "triso_univ = openmc.Universe(cells=cells)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need a region to pack the TRISO particles in. We will use a 1 cm x 1 cm x 1 cm box centered at the origin." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "min_x = openmc.XPlane(x0=-0.5, boundary_type='reflective')\n", - "max_x = openmc.XPlane(x0=0.5, boundary_type='reflective')\n", - "min_y = openmc.YPlane(y0=-0.5, boundary_type='reflective')\n", - "max_y = openmc.YPlane(y0=0.5, boundary_type='reflective')\n", - "min_z = openmc.ZPlane(z0=-0.5, boundary_type='reflective')\n", - "max_z = openmc.ZPlane(z0=0.5, boundary_type='reflective')\n", - "region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to randomly select locations for the TRISO particles. In this example, we will select locations at random within the box with a packing fraction of 30%. Note that `pack_spheres` can handle up to the theoretical maximum of 60% (it will just be slow)." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "outer_radius = 425.*1e-4\n", - "centers = openmc.model.pack_spheres(radius=outer_radius, region=region, pf=0.3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have the locations of the TRISO particles determined and a universe that can be used for each particle, we can create the TRISO particles." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "trisos = [openmc.model.TRISO(outer_radius, triso_univ, c) for c in centers]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each TRISO object actually **is** a Cell, in fact; we can look at the properties of the TRISO just as we would a cell:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cell\n", - "\tID =\t6\n", - "\tName =\t\n", - "\tFill =\t1\n", - "\tRegion =\t-11\n", - "\tRotation =\tNone\n", - "\tTranslation =\t[-0.33455672 0.31790187 0.24135378]\n", - "\n" - ] - } - ], - "source": [ - "print(trisos[0])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's confirm that all our TRISO particles are within the box." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[-0.45718713 -0.45730405 -0.45725048]\n", - "[0.45705454 0.45743843 0.45741142]\n" - ] - } - ], - "source": [ - "centers = np.vstack([t.center for t in trisos])\n", - "print(centers.min(axis=0))\n", - "print(centers.max(axis=0))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also look at what the actual packing fraction turned out to be:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.2996893513959326" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(trisos)*4/3*pi*outer_radius**3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have our TRISO particles created, we need to place them in a lattice to provide optimal tracking performance in OpenMC. We can use the box we created above to place the lattice in. Actually creating a lattice containing TRISO particles can be done with the `model.create_triso_lattice()` function. This function requires that we give it a list of TRISO particles, the lower-left coordinates of the lattice, the pitch of each lattice cell, the overall shape of the lattice (number of cells in each direction), and a background material." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "box = openmc.Cell(region=region)\n", - "lower_left, upper_right = box.region.bounding_box\n", - "shape = (3, 3, 3)\n", - "pitch = (upper_right - lower_left)/shape\n", - "lattice = openmc.model.create_triso_lattice(\n", - " trisos, lower_left, pitch, shape, graphite)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can set the fill of our box cell to be the lattice:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "box.fill = lattice" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, let's take a look at our geometry by putting the box in a universe and plotting it. We're going to use the Fortran-side plotter since it's much faster." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "univ = openmc.Universe(cells=[box])\n", - "\n", - "geom = openmc.Geometry(univ)\n", - "geom.export_to_xml()\n", - "\n", - "mats = list(geom.get_all_materials().values())\n", - "openmc.Materials(mats).export_to_xml()\n", - "\n", - "settings = openmc.Settings()\n", - "settings.run_mode = 'plot'\n", - "settings.export_to_xml()\n", - "\n", - "p = openmc.Plot.from_geometry(geom)\n", - "p.to_ipython_image()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we plot the universe by material rather than by cell, we can see that the entire background is just graphite." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p.color_by = 'material'\n", - "p.colors = {graphite: 'gray'}\n", - "p.to_ipython_image()" - ] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/examples/python/basic/build-xml.py b/examples/python/basic/build-xml.py deleted file mode 100644 index 5caed2810..000000000 --- a/examples/python/basic/build-xml.py +++ /dev/null @@ -1,121 +0,0 @@ -import openmc - - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 15 -inactive = 5 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -moderator = openmc.Material(material_id=41, name='moderator') -moderator.set_density('g/cc', 1.0) -moderator.add_element('H', 2.) -moderator.add_element('O', 1.) -moderator.add_s_alpha_beta('c_H_in_H2O') - -fuel = openmc.Material(material_id=40, name='fuel') -fuel.set_density('g/cc', 4.5) -fuel.add_nuclide('U235', 1.) - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([moderator, fuel]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate ZCylinder surfaces -surf1 = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=7, name='surf 1') -surf2 = openmc.ZCylinder(surface_id=2, x0=0, y0=0, r=9, name='surf 2') -surf3 = openmc.ZCylinder(surface_id=3, x0=0, y0=0, r=11, name='surf 3') -surf3.boundary_type = 'vacuum' - -# Instantiate Cells -cell1 = openmc.Cell(cell_id=1, name='cell 1') -cell2 = openmc.Cell(cell_id=100, name='cell 2') -cell3 = openmc.Cell(cell_id=101, name='cell 3') -cell4 = openmc.Cell(cell_id=2, name='cell 4') - -# Use surface half-spaces to define regions -cell1.region = -surf2 -cell2.region = -surf1 -cell3.region = +surf1 -cell4.region = +surf2 & -surf3 - -# Register Materials with Cells -cell2.fill = fuel -cell3.fill = moderator -cell4.fill = moderator - -# Instantiate Universes -universe1 = openmc.Universe(universe_id=37) -root = openmc.Universe(universe_id=0, name='root universe') -cell1.fill = universe1 - -# Register Cells with Universes -universe1.add_cells([cell2, cell3]) -root.add_cells([cell1, cell4]) - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-4., -4., -4., 4., 4., 4.] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC tallies.xml file -############################################################################### - -# Instantiate some tally Filters -cell_filter = openmc.CellFilter(cell2) -energy_filter = openmc.EnergyFilter([0., 20.e6]) -energyout_filter = openmc.EnergyoutFilter([0., 20.e6]) - -# Instantiate the first Tally -first_tally = openmc.Tally(tally_id=1, name='first tally') -first_tally.filters = [cell_filter] -scores = ['total', 'scatter', 'nu-scatter', - 'absorption', 'fission', 'nu-fission'] -first_tally.scores = scores - -# Instantiate the second Tally -second_tally = openmc.Tally(tally_id=2, name='second tally') -second_tally.filters = [cell_filter, energy_filter] -second_tally.scores = scores - -# Instantiate the third Tally -third_tally = openmc.Tally(tally_id=3, name='third tally') -third_tally.filters = [cell_filter, energy_filter, energyout_filter] -third_tally.scores = ['scatter', 'nu-scatter', 'nu-fission'] - -# Instantiate a Tallies collection and export to XML -tallies_file = openmc.Tallies((first_tally, second_tally, third_tally)) -tallies_file.export_to_xml() diff --git a/examples/python/boxes/build-xml.py b/examples/python/boxes/build-xml.py deleted file mode 100644 index d04f0f67a..000000000 --- a/examples/python/boxes/build-xml.py +++ /dev/null @@ -1,125 +0,0 @@ -import numpy as np -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 15 -inactive = 5 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml File -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -fuel1 = openmc.Material(material_id=1, name='fuel') -fuel1.set_density('g/cc', 4.5) -fuel1.add_nuclide('U235', 1.) - -fuel2 = openmc.Material(material_id=2, name='depleted fuel') -fuel2.set_density('g/cc', 4.5) -fuel2.add_nuclide('U238', 1.) - -moderator = openmc.Material(material_id=3, name='moderator') -moderator.set_density('g/cc', 1.0) -moderator.add_element('H', 2.) -moderator.add_element('O', 1.) -moderator.add_s_alpha_beta('c_H_in_H2O') - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([fuel1, fuel2, moderator]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate planar surfaces -x1 = openmc.XPlane(surface_id=1, x0=-10) -x2 = openmc.XPlane(surface_id=2, x0=-7) -x3 = openmc.XPlane(surface_id=3, x0=-4) -x4 = openmc.XPlane(surface_id=4, x0=4) -x5 = openmc.XPlane(surface_id=5, x0=7) -x6 = openmc.XPlane(surface_id=6, x0=10) -y1 = openmc.YPlane(surface_id=11, y0=-10) -y2 = openmc.YPlane(surface_id=12, y0=-7) -y3 = openmc.YPlane(surface_id=13, y0=-4) -y4 = openmc.YPlane(surface_id=14, y0=4) -y5 = openmc.YPlane(surface_id=15, y0=7) -y6 = openmc.YPlane(surface_id=16, y0=10) -z1 = openmc.ZPlane(surface_id=21, z0=-10) -z2 = openmc.ZPlane(surface_id=22, z0=-7) -z3 = openmc.ZPlane(surface_id=23, z0=-4) -z4 = openmc.ZPlane(surface_id=24, z0=4) -z5 = openmc.ZPlane(surface_id=25, z0=7) -z6 = openmc.ZPlane(surface_id=26, z0=10) - -# Set vacuum boundary conditions on outside -for surface in [x1, x6, y1, y6, z1, z6]: - surface.boundary_type = 'vacuum' - -# Instantiate Cells -inner_box = openmc.Cell(cell_id=1, name='inner box') -middle_box = openmc.Cell(cell_id=2, name='middle box') -outer_box = openmc.Cell(cell_id=3, name='outer box') - -# Use each set of six planes to create solid cube regions. We can then use these -# to create cubic shells. -inner_cube = +x3 & -x4 & +y3 & -y4 & +z3 & -z4 -middle_cube = +x2 & -x5 & +y2 & -y5 & +z2 & -z5 -outer_cube = +x1 & -x6 & +y1 & -y6 & +z1 & -z6 -outside_inner_cube = -x3 | +x4 | -y3 | +y4 | -z3 | +z4 - -# Use surface half-spaces to define regions -inner_box.region = inner_cube -middle_box.region = middle_cube & outside_inner_cube -outer_box.region = outer_cube & ~middle_cube - -# Register Materials with Cells -inner_box.fill = fuel1 -middle_box.fill = fuel2 -outer_box.fill = moderator - -# Instantiate root universe -root = openmc.Universe(universe_id=0, name='root universe') -root.add_cells([inner_box, middle_box, outer_box]) - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml File -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -uniform_dist = openmc.stats.Box(*outer_cube.bounding_box, only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.export_to_xml() - -############################################################################### -# Exporting to OpenMC plots.xml File -############################################################################### - -plot = openmc.Plot(plot_id=1) -plot.origin = [0, 0, 0] -plot.width = [20, 20] -plot.pixels = [200, 200] -plot.color_by = 'cell' - -# Instantiate a Plots collection and export to XML -plot_file = openmc.Plots([plot]) -plot_file.export_to_xml() diff --git a/examples/python/lattice/hexagonal/build-xml.py b/examples/python/lattice/hexagonal/build-xml.py deleted file mode 100644 index c0aa815b4..000000000 --- a/examples/python/lattice/hexagonal/build-xml.py +++ /dev/null @@ -1,161 +0,0 @@ -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 20 -inactive = 10 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml File -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -fuel = openmc.Material(material_id=1, name='fuel') -fuel.set_density('g/cc', 4.5) -fuel.add_nuclide('U235', 1.) - -moderator = openmc.Material(material_id=2, name='moderator') -moderator.set_density('g/cc', 1.0) -moderator.add_element('H', 2.) -moderator.add_element('O', 1.) -moderator.add_s_alpha_beta('c_H_in_H2O') - -iron = openmc.Material(material_id=3, name='iron') -iron.set_density('g/cc', 7.9) -iron.add_element('Fe', 1.) - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([moderator, fuel, iron]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate Surfaces -left = openmc.XPlane(surface_id=1, x0=-3, name='left') -right = openmc.XPlane(surface_id=2, x0=3, name='right') -bottom = openmc.YPlane(surface_id=3, y0=-4, name='bottom') -top = openmc.YPlane(surface_id=4, y0=4, name='top') -fuel_surf = openmc.ZCylinder(surface_id=5, x0=0, y0=0, r=0.4) - -left.boundary_type = 'vacuum' -right.boundary_type = 'vacuum' -top.boundary_type = 'vacuum' -bottom.boundary_type = 'vacuum' - -# Instantiate Cells -cell1 = openmc.Cell(cell_id=1, name='Cell 1') -cell2 = openmc.Cell(cell_id=101, name='cell 2') -cell3 = openmc.Cell(cell_id=102, name='cell 3') -cell4 = openmc.Cell(cell_id=500, name='cell 4') -cell5 = openmc.Cell(cell_id=600, name='cell 5') -cell6 = openmc.Cell(cell_id=601, name='cell 6') - -# Use surface half-spaces to define regions -cell1.region = +left & -right & +bottom & -top -cell2.region = -fuel_surf -cell3.region = +fuel_surf -cell5.region = -fuel_surf -cell6.region = +fuel_surf - -# Register Materials with Cells -cell2.fill = fuel -cell3.fill = moderator -cell4.fill = moderator -cell5.fill = iron -cell6.fill = moderator - -# Instantiate Universe -univ1 = openmc.Universe(universe_id=1) -univ2 = openmc.Universe(universe_id=3) -univ3 = openmc.Universe(universe_id=4) -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -univ1.add_cells([cell2, cell3]) -univ2.add_cells([cell4]) -univ3.add_cells([cell5, cell6]) -root.add_cell(cell1) - -# Instantiate a Lattice -lattice = openmc.HexLattice(lattice_id=5) -lattice.center = [0., 0., 0.] -lattice.pitch = [1., 2.] -lattice.universes = \ - [ [ [univ2] + [univ3]*11, [univ2] + [univ3]*5, [univ3] ], - [ [univ2] + [univ1]*11, [univ2] + [univ1]*5, [univ1] ], - [ [univ2] + [univ3]*11, [univ2] + [univ3]*5, [univ3] ] ] -lattice.outer = univ2 - -# Fill Cell with the Lattice -cell1.fill = lattice - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-1, -1, -1, 1, 1, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.keff_trigger = {'type' : 'std_dev', 'threshold' : 5E-4} -settings_file.trigger_active = True -settings_file.trigger_max_batches = 100 -settings_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC plots.xml file -############################################################################### - -plot_xy = openmc.Plot(plot_id=1) -plot_xy.filename = 'plot_xy' -plot_xy.origin = [0, 0, 0] -plot_xy.width = [6, 6] -plot_xy.pixels = [400, 400] -plot_xy.color_by = 'material' - -plot_yz = openmc.Plot(plot_id=2) -plot_yz.filename = 'plot_yz' -plot_yz.basis = 'yz' -plot_yz.origin = [0, 0, 0] -plot_yz.width = [8, 8] -plot_yz.pixels = [400, 400] -plot_yz.color_by = 'material' - -# Instantiate a Plots collection, add plots, and export to XML -plot_file = openmc.Plots((plot_xy, plot_yz)) -plot_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC tallies.xml File -############################################################################### - -# Instantiate a distribcell Tally -tally = openmc.Tally(tally_id=1) -tally.filters = [openmc.DistribcellFilter(cell2)] -tally.scores = ['total'] - -# Instantiate a Tallies collection and export to XML -tallies_file = openmc.Tallies([tally]) -tallies_file.export_to_xml() diff --git a/examples/python/lattice/nested/build-xml.py b/examples/python/lattice/nested/build-xml.py deleted file mode 100644 index 06641f5ac..000000000 --- a/examples/python/lattice/nested/build-xml.py +++ /dev/null @@ -1,169 +0,0 @@ -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 20 -inactive = 10 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -fuel = openmc.Material(material_id=1, name='fuel') -fuel.set_density('g/cc', 4.5) -fuel.add_nuclide('U235', 1.) - -moderator = openmc.Material(material_id=2, name='moderator') -moderator.set_density('g/cc', 1.0) -moderator.add_element('H', 2.) -moderator.add_element('O', 1.) -moderator.add_s_alpha_beta('c_H_in_H2O') - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials((moderator, fuel)) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate Surfaces -left = openmc.XPlane(surface_id=1, x0=-2, name='left') -right = openmc.XPlane(surface_id=2, x0=2, name='right') -bottom = openmc.YPlane(surface_id=3, y0=-2, name='bottom') -top = openmc.YPlane(surface_id=4, y0=2, name='top') -fuel1 = openmc.ZCylinder(surface_id=5, x0=0, y0=0, r=0.4) -fuel2 = openmc.ZCylinder(surface_id=6, x0=0, y0=0, r=0.3) -fuel3 = openmc.ZCylinder(surface_id=7, x0=0, y0=0, r=0.2) - -left.boundary_type = 'vacuum' -right.boundary_type = 'vacuum' -top.boundary_type = 'vacuum' -bottom.boundary_type = 'vacuum' - -# Instantiate Cells -cell1 = openmc.Cell(cell_id=1, name='Cell 1') -cell2 = openmc.Cell(cell_id=2, name='Cell 2') -cell3 = openmc.Cell(cell_id=101, name='cell 3') -cell4 = openmc.Cell(cell_id=102, name='cell 4') -cell5 = openmc.Cell(cell_id=201, name='cell 5') -cell6 = openmc.Cell(cell_id=202, name='cell 6') -cell7 = openmc.Cell(cell_id=301, name='cell 7') -cell8 = openmc.Cell(cell_id=302, name='cell 8') - -# Use surface half-space to define regions -cell1.region = +left & -right & +bottom & -top -cell2.region = +left & -right & +bottom & -top -cell3.region = -fuel1 -cell4.region = +fuel1 -cell5.region = -fuel2 -cell6.region = +fuel2 -cell7.region = -fuel3 -cell8.region = +fuel3 - -# Register Materials with Cells -cell3.fill = fuel -cell4.fill = moderator -cell5.fill = fuel -cell6.fill = moderator -cell7.fill = fuel -cell8.fill = moderator - -# Instantiate Universe -univ1 = openmc.Universe(universe_id=1) -univ2 = openmc.Universe(universe_id=2) -univ3 = openmc.Universe(universe_id=3) -univ4 = openmc.Universe(universe_id=5) -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -univ1.add_cells([cell3, cell4]) -univ2.add_cells([cell5, cell6]) -univ3.add_cells([cell7, cell8]) -root.add_cell(cell1) -univ4.add_cell(cell2) - -# Instantiate nested Lattices -lattice1 = openmc.RectLattice(lattice_id=4, name='4x4 assembly') -lattice1.lower_left = [-1., -1.] -lattice1.pitch = [1., 1.] -lattice1.universes = [[univ1, univ2], - [univ2, univ3]] - -lattice2 = openmc.RectLattice(lattice_id=6, name='4x4 core') -lattice2.lower_left = [-2., -2.] -lattice2.pitch = [2., 2.] -lattice2.universes = [[univ4, univ4], - [univ4, univ4]] - -# Fill Cell with the Lattice -cell1.fill = lattice2 -cell2.fill = lattice1 - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-1, -1, -1, 1, 1, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC plots.xml file -############################################################################### - -plot = openmc.Plot(plot_id=1) -plot.origin = [0, 0, 0] -plot.width = [4, 4] -plot.pixels = [400, 400] -plot.color_by = 'material' - -# Instantiate a Plots object and export to XML -plot_file = openmc.Plots([plot]) -plot_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC tallies.xml file -############################################################################### - -# Instantiate a tally mesh -mesh = openmc.RegularMesh(mesh_id=1) -mesh.dimension = [4, 4] -mesh.lower_left = [-2, -2] -mesh.width = [1, 1] - -# Instantiate tally Filter -mesh_filter = openmc.MeshFilter(mesh) - -# Instantiate the Tally -tally = openmc.Tally(tally_id=1) -tally.filters = [mesh_filter] -tally.scores = ['total'] - -# Instantiate a Tallies collection, register Tally/RegularMesh, and export to -# XML -tallies_file = openmc.Tallies([tally]) -tallies_file.export_to_xml() diff --git a/examples/python/lattice/simple/build-xml.py b/examples/python/lattice/simple/build-xml.py deleted file mode 100644 index 17544b87f..000000000 --- a/examples/python/lattice/simple/build-xml.py +++ /dev/null @@ -1,166 +0,0 @@ -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 20 -inactive = 10 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -fuel = openmc.Material(material_id=1, name='fuel') -fuel.set_density('g/cc', 4.5) -fuel.add_nuclide('U235', 1.) - -moderator = openmc.Material(material_id=2, name='moderator') -moderator.set_density('g/cc', 1.0) -moderator.add_element('H', 2.) -moderator.add_element('O', 1.) -moderator.add_s_alpha_beta('c_H_in_H2O') - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([moderator, fuel]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate Surfaces -left = openmc.XPlane(surface_id=1, x0=-2, name='left') -right = openmc.XPlane(surface_id=2, x0=2, name='right') -bottom = openmc.YPlane(surface_id=3, y0=-2, name='bottom') -top = openmc.YPlane(surface_id=4, y0=2, name='top') -fuel1 = openmc.ZCylinder(surface_id=5, x0=0, y0=0, r=0.4) -fuel2 = openmc.ZCylinder(surface_id=6, x0=0, y0=0, r=0.3) -fuel3 = openmc.ZCylinder(surface_id=7, x0=0, y0=0, r=0.2) - -left.boundary_type = 'vacuum' -right.boundary_type = 'vacuum' -top.boundary_type = 'vacuum' -bottom.boundary_type = 'vacuum' - -# Instantiate Cells -cell1 = openmc.Cell(cell_id=1, name='Cell 1') -cell2 = openmc.Cell(cell_id=101, name='cell 2') -cell3 = openmc.Cell(cell_id=102, name='cell 3') -cell4 = openmc.Cell(cell_id=201, name='cell 4') -cell5 = openmc.Cell(cell_id=202, name='cell 5') -cell6 = openmc.Cell(cell_id=301, name='cell 6') -cell7 = openmc.Cell(cell_id=302, name='cell 7') - -# Use surface half-spaces to define regions -cell1.region = +left & -right & +bottom & -top -cell2.region = -fuel1 -cell3.region = +fuel1 -cell4.region = -fuel2 -cell5.region = +fuel2 -cell6.region = -fuel3 -cell7.region = +fuel3 - -# Register Materials with Cells -cell2.fill = fuel -cell3.fill = moderator -cell4.fill = fuel -cell5.fill = moderator -cell6.fill = fuel -cell7.fill = moderator - -# Instantiate Universe -univ1 = openmc.Universe(universe_id=1) -univ2 = openmc.Universe(universe_id=2) -univ3 = openmc.Universe(universe_id=3) -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -univ1.add_cells([cell2, cell3]) -univ2.add_cells([cell4, cell5]) -univ3.add_cells([cell6, cell7]) -root.add_cell(cell1) - -# Instantiate a Lattice -lattice = openmc.RectLattice(lattice_id=5) -lattice.lower_left = [-2., -2.] -lattice.pitch = [1., 1.] -lattice.universes = [[univ1, univ2, univ1, univ2], - [univ2, univ3, univ2, univ3], - [univ1, univ2, univ1, univ2], - [univ2, univ3, univ2, univ3]] - -# Fill Cell with the Lattice -cell1.fill = lattice - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-1, -1, -1, 1, 1, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.trigger_active = True -settings_file.trigger_max_batches = 100 -settings_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC plots.xml file -############################################################################### - -plot = openmc.Plot(plot_id=1) -plot.origin = [0, 0, 0] -plot.width = [4, 4] -plot.pixels = [400, 400] -plot.color_by = 'material' - -# Instantiate a Plots collection and export to XML -plot_file = openmc.Plots([plot]) -plot_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC tallies.xml file -############################################################################### - -# Instantiate a tally mesh -mesh = openmc.RegularMesh(mesh_id=1) -mesh.dimension = [4, 4] -mesh.lower_left = [-2, -2] -mesh.width = [1, 1] - -# Instantiate tally Filter -mesh_filter = openmc.MeshFilter(mesh) - -# Instantiate tally Trigger -trigger = openmc.Trigger(trigger_type='rel_err', threshold=1E-2) -trigger.scores = ['all'] - -# Instantiate the Tally -tally = openmc.Tally(tally_id=1) -tally.filters = [mesh_filter] -tally.scores = ['total'] -tally.triggers = [trigger] - -# Instantiate a Tallies collection and export to XML -tallies_file = openmc.Tallies([tally]) -tallies_file.export_to_xml() diff --git a/examples/python/pincell/build-xml.py b/examples/python/pincell/build-xml.py deleted file mode 100644 index 072cc911f..000000000 --- a/examples/python/pincell/build-xml.py +++ /dev/null @@ -1,138 +0,0 @@ -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 100 -inactive = 10 -particles = 1000 - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - - -# Instantiate some Materials and register the appropriate Nuclides -uo2 = openmc.Material(material_id=1, name='UO2 fuel at 2.4% wt enrichment') -uo2.set_density('g/cm3', 10.29769) -uo2.add_element('U', 1., enrichment=2.4) -uo2.add_element('O', 2.) - -helium = openmc.Material(material_id=2, name='Helium for gap') -helium.set_density('g/cm3', 0.001598) -helium.add_element('He', 2.4044e-4) - -zircaloy = openmc.Material(material_id=3, name='Zircaloy 4') -zircaloy.set_density('g/cm3', 6.55) -zircaloy.add_element('Sn', 0.014 , 'wo') -zircaloy.add_element('Fe', 0.00165, 'wo') -zircaloy.add_element('Cr', 0.001 , 'wo') -zircaloy.add_element('Zr', 0.98335, 'wo') - -borated_water = openmc.Material(material_id=4, name='Borated water') -borated_water.set_density('g/cm3', 0.740582) -borated_water.add_element('B', 4.0e-5) -borated_water.add_element('H', 5.0e-2) -borated_water.add_element('O', 2.4e-2) -borated_water.add_s_alpha_beta('c_H_in_H2O') - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([uo2, helium, zircaloy, borated_water]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate ZCylinder surfaces -fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=0.39218, name='Fuel OR') -clad_ir = openmc.ZCylinder(surface_id=2, x0=0, y0=0, r=0.40005, name='Clad IR') -clad_or = openmc.ZCylinder(surface_id=3, x0=0, y0=0, r=0.45720, name='Clad OR') -left = openmc.XPlane(surface_id=4, x0=-0.62992, name='left') -right = openmc.XPlane(surface_id=5, x0=0.62992, name='right') -bottom = openmc.YPlane(surface_id=6, y0=-0.62992, name='bottom') -top = openmc.YPlane(surface_id=7, y0=0.62992, name='top') - -left.boundary_type = 'reflective' -right.boundary_type = 'reflective' -top.boundary_type = 'reflective' -bottom.boundary_type = 'reflective' - -# Instantiate Cells -fuel = openmc.Cell(cell_id=1, name='cell 1') -gap = openmc.Cell(cell_id=2, name='cell 2') -clad = openmc.Cell(cell_id=3, name='cell 3') -water = openmc.Cell(cell_id=4, name='cell 4') - -# Use surface half-spaces to define regions -fuel.region = -fuel_or -gap.region = +fuel_or & -clad_ir -clad.region = +clad_ir & -clad_or -water.region = +clad_or & +left & -right & +bottom & -top - -# Register Materials with Cells -fuel.fill = uo2 -gap.fill = helium -clad.fill = zircaloy -water.fill = borated_water - -# Instantiate Universe -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -root.add_cells([fuel, gap, clad, water]) - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -entropy_mesh = openmc.RegularMesh() -entropy_mesh.lower_left = [-0.39218, -0.39218, -1.e50] -entropy_mesh.upper_right = [0.39218, 0.39218, 1.e50] -entropy_mesh.dimension = [10, 10, 1] -settings_file.entropy_mesh = entropy_mesh -settings_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC tallies.xml file -############################################################################### - -# Instantiate a tally mesh -mesh = openmc.RegularMesh() -mesh.dimension = [100, 100, 1] -mesh.lower_left = [-0.62992, -0.62992, -1.e50] -mesh.upper_right = [0.62992, 0.62992, 1.e50] - -# Instantiate some tally Filters -energy_filter = openmc.EnergyFilter([0., 4., 20.e6]) -mesh_filter = openmc.MeshFilter(mesh) - -# Instantiate the Tally -tally = openmc.Tally(tally_id=1, name='tally 1') -tally.filters = [energy_filter, mesh_filter] -tally.scores = ['flux', 'fission', 'nu-fission'] - -# Instantiate a Tallies collection and export to XML -tallies_file = openmc.Tallies([tally]) -tallies_file.export_to_xml() diff --git a/examples/python/pincell_depletion/chain_simple.xml b/examples/python/pincell_depletion/chain_simple.xml deleted file mode 100644 index c2e50a370..000000000 --- a/examples/python/pincell_depletion/chain_simple.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 4.356330e-05 - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 4.9097e-6 - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 3.7100E-07 - - - - diff --git a/examples/python/pincell_depletion/restart_depletion.py b/examples/python/pincell_depletion/restart_depletion.py deleted file mode 100644 index 013a2469e..000000000 --- a/examples/python/pincell_depletion/restart_depletion.py +++ /dev/null @@ -1,104 +0,0 @@ -import openmc -import openmc.deplete -import numpy as np -import matplotlib.pyplot as plt - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 100 -inactive = 10 -particles = 1000 - -# Depletion simulation parameters -time_step = 1*24*60*60 # s -final_time = 5*24*60*60 # s -time_steps = np.full(final_time // time_step, time_step) - -chain_file = './chain_simple.xml' -power = 174 # W/cm, for 2D simulations only (use W for 3D) - -############################################################################### -# Load previous simulation results -############################################################################### - -# Load geometry from statepoint -statepoint = 'statepoint.100.h5' -with openmc.StatePoint(statepoint) as sp: - geometry = sp.summary.geometry - -# Load previous depletion results -previous_results = openmc.deplete.ResultsList("depletion_results.h5") - -############################################################################### -# Transport calculation settings -############################################################################### - -# Instantiate a Settings object, set all runtime parameters -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -entropy_mesh = openmc.RegularMesh() -entropy_mesh.lower_left = [-0.39218, -0.39218, -1.e50] -entropy_mesh.upper_right = [0.39218, 0.39218, 1.e50] -entropy_mesh.dimension = [10, 10, 1] -settings_file.entropy_mesh = entropy_mesh - -############################################################################### -# Initialize and run depletion calculation -############################################################################### - -op = openmc.deplete.Operator(geometry, settings_file, chain_file, - previous_results) - -# Perform simulation using the predictor algorithm -integrator = openmc.deplete.PredictorIntegrator(op, time_steps, power) -integrator.integrate() - -############################################################################### -# Read depletion calculation results -############################################################################### - -# Open results file -results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") - -# Obtain K_eff as a function of time -time, keff = results.get_eigenvalue() - -# Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms('1', 'U235') - -# Obtain Xe135 absorption as a function of time -time, Xe_gam = results.get_reaction_rate('1', 'Xe135', '(n,gamma)') - -############################################################################### -# Generate plots -############################################################################### - -plt.figure() -plt.plot(time/(24*60*60), keff, label="K-effective") -plt.xlabel("Time (days)") -plt.ylabel("Keff") -plt.show() - -plt.figure() -plt.plot(time/(24*60*60), n_U235, label="U 235") -plt.xlabel("Time (days)") -plt.ylabel("n U5 (-)") -plt.show() - -plt.figure() -plt.plot(time/(24*60*60), Xe_gam, label="Xe135 absorption") -plt.xlabel("Time (days)") -plt.ylabel("RR (-)") -plt.show() -plt.close('all') diff --git a/examples/python/pincell_depletion/run_depletion.py b/examples/python/pincell_depletion/run_depletion.py deleted file mode 100644 index 9933edd48..000000000 --- a/examples/python/pincell_depletion/run_depletion.py +++ /dev/null @@ -1,175 +0,0 @@ -import openmc -import openmc.deplete -import numpy as np -import matplotlib.pyplot as plt - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 100 -inactive = 10 -particles = 1000 - -# Depletion simulation parameters -time_step = 1*24*60*60 # s -final_time = 5*24*60*60 # s -time_steps = np.full(final_time // time_step, time_step) -chain_file = './chain_simple.xml' -power = 174 # W/cm, for 2D simulations only (use W for 3D) - -############################################################################### -# Define materials -############################################################################### - -# Instantiate some Materials and register the appropriate Nuclides -uo2 = openmc.Material(material_id=1, name='UO2 fuel at 2.4% wt enrichment') -uo2.set_density('g/cm3', 10.29769) -uo2.add_element('U', 1., enrichment=2.4) -uo2.add_element('O', 2.) -uo2.depletable = True - -helium = openmc.Material(material_id=2, name='Helium for gap') -helium.set_density('g/cm3', 0.001598) -helium.add_element('He', 2.4044e-4) - -zircaloy = openmc.Material(material_id=3, name='Zircaloy 4') -zircaloy.set_density('g/cm3', 6.55) -zircaloy.add_element('Sn', 0.014 , 'wo') -zircaloy.add_element('Fe', 0.00165, 'wo') -zircaloy.add_element('Cr', 0.001 , 'wo') -zircaloy.add_element('Zr', 0.98335, 'wo') - -borated_water = openmc.Material(material_id=4, name='Borated water') -borated_water.set_density('g/cm3', 0.740582) -borated_water.add_element('B', 4.0e-5) -borated_water.add_element('H', 5.0e-2) -borated_water.add_element('O', 2.4e-2) -borated_water.add_s_alpha_beta('c_H_in_H2O') - -############################################################################### -# Create geometry -############################################################################### - -# Instantiate ZCylinder surfaces -fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=0.39218, name='Fuel OR') -clad_ir = openmc.ZCylinder(surface_id=2, x0=0, y0=0, r=0.40005, name='Clad IR') -clad_or = openmc.ZCylinder(surface_id=3, x0=0, y0=0, r=0.45720, name='Clad OR') -left = openmc.XPlane(surface_id=4, x0=-0.62992, name='left') -right = openmc.XPlane(surface_id=5, x0=0.62992, name='right') -bottom = openmc.YPlane(surface_id=6, y0=-0.62992, name='bottom') -top = openmc.YPlane(surface_id=7, y0=0.62992, name='top') - -left.boundary_type = 'reflective' -right.boundary_type = 'reflective' -top.boundary_type = 'reflective' -bottom.boundary_type = 'reflective' - -# Instantiate Cells -fuel = openmc.Cell(cell_id=1, name='cell 1') -gap = openmc.Cell(cell_id=2, name='cell 2') -clad = openmc.Cell(cell_id=3, name='cell 3') -water = openmc.Cell(cell_id=4, name='cell 4') - -# Use surface half-spaces to define regions -fuel.region = -fuel_or -gap.region = +fuel_or & -clad_ir -clad.region = +clad_ir & -clad_or -water.region = +clad_or & +left & -right & +bottom & -top - -# Register Materials with Cells -fuel.fill = uo2 -gap.fill = helium -clad.fill = zircaloy -water.fill = borated_water - -# Instantiate Universe -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -root.add_cells([fuel, gap, clad, water]) - -# Instantiate a Geometry, register the root Universe -geometry = openmc.Geometry(root) - -############################################################################### -# Set volumes of depletable materials -############################################################################### - -# Compute cell areas -area = {} -area[fuel] = np.pi * fuel_or.coefficients['r'] ** 2 - -# Set materials volume for depletion. Set to an area for 2D simulations -uo2.volume = area[fuel] - -############################################################################### -# Transport calculation settings -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -entropy_mesh = openmc.RegularMesh() -entropy_mesh.lower_left = [-0.39218, -0.39218, -1.e50] -entropy_mesh.upper_right = [0.39218, 0.39218, 1.e50] -entropy_mesh.dimension = [10, 10, 1] -settings_file.entropy_mesh = entropy_mesh - -############################################################################### -# Initialize and run depletion calculation -############################################################################### - -op = openmc.deplete.Operator(geometry, settings_file, chain_file) - -# Perform simulation using the predictor algorithm -integrator = openmc.deplete.PredictorIntegrator(op, time_steps, power) -integrator.integrate() - -############################################################################### -# Read depletion calculation results -############################################################################### - -# Open results file -results = openmc.deplete.ResultsList.from_hdf5("depletion_results.h5") - -# Obtain K_eff as a function of time -time, keff = results.get_eigenvalue() - -# Obtain U235 concentration as a function of time -time, n_U235 = results.get_atoms('1', 'U235') - -# Obtain Xe135 absorption as a function of time -time, Xe_gam = results.get_reaction_rate('1', 'Xe135', '(n,gamma)') - -############################################################################### -# Generate plots -############################################################################### - -plt.figure() -plt.plot(time/(24*60*60), keff, label="K-effective") -plt.xlabel("Time (days)") -plt.ylabel("Keff") -plt.show() - -plt.figure() -plt.plot(time/(24*60*60), n_U235, label="U 235") -plt.xlabel("Time (days)") -plt.ylabel("n U5 (-)") -plt.show() - -plt.figure() -plt.plot(time/(24*60*60), Xe_gam, label="Xe135 absorption") -plt.xlabel("Time (days)") -plt.ylabel("RR (-)") -plt.show() -plt.close('all') diff --git a/examples/python/pincell_multigroup/build-xml.py b/examples/python/pincell_multigroup/build-xml.py deleted file mode 100644 index bb9fc7860..000000000 --- a/examples/python/pincell_multigroup/build-xml.py +++ /dev/null @@ -1,175 +0,0 @@ -import numpy as np - -import openmc -import openmc.mgxs - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 100 -inactive = 10 -particles = 1000 - -############################################################################### -# Exporting to OpenMC mgxs.h5 file -############################################################################### - -# Instantiate the energy group data -groups = openmc.mgxs.EnergyGroups(group_edges=[ - 1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6]) - -# Instantiate the 7-group (C5G7) cross section data -uo2_xsdata = openmc.XSdata('UO2', groups) -uo2_xsdata.order = 0 -uo2_xsdata.set_total( - [0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678, - 0.5644058]) -uo2_xsdata.set_absorption([8.0248E-03, 3.7174E-03, 2.6769E-02, 9.6236E-02, - 3.0020E-02, 1.1126E-01, 2.8278E-01]) -scatter_matrix = np.array( - [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000], - [0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000], - [0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000], - [0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000], - [0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000], - [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090], - [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]) -scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) -uo2_xsdata.set_scatter_matrix(scatter_matrix) -uo2_xsdata.set_fission([7.21206E-03, 8.19301E-04, 6.45320E-03, - 1.85648E-02, 1.78084E-02, 8.30348E-02, - 2.16004E-01]) -uo2_xsdata.set_nu_fission([2.005998E-02, 2.027303E-03, 1.570599E-02, - 4.518301E-02, 4.334208E-02, 2.020901E-01, - 5.257105E-01]) -uo2_xsdata.set_chi([5.8791E-01, 4.1176E-01, 3.3906E-04, 1.1761E-07, 0.0000E+00, - 0.0000E+00, 0.0000E+00]) - -h2o_xsdata = openmc.XSdata('LWTR', groups) -h2o_xsdata.order = 0 -h2o_xsdata.set_total([0.15920605, 0.412969593, 0.59030986, 0.58435, - 0.718, 1.2544497, 2.650379]) -h2o_xsdata.set_absorption([6.0105E-04, 1.5793E-05, 3.3716E-04, - 1.9406E-03, 5.7416E-03, 1.5001E-02, - 3.7239E-02]) -scatter_matrix = np.array( - [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000], - [0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010], - [0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034], - [0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390], - [0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290], - [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200], - [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]) -scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) -h2o_xsdata.set_scatter_matrix(scatter_matrix) - -mg_cross_sections_file = openmc.MGXSLibrary(groups) -mg_cross_sections_file.add_xsdatas([uo2_xsdata, h2o_xsdata]) -mg_cross_sections_file.export_to_hdf5() - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - -# Instantiate some Macroscopic Data -uo2_data = openmc.Macroscopic('UO2') -h2o_data = openmc.Macroscopic('LWTR') - -# Instantiate some Materials and register the appropriate Macroscopic objects -uo2 = openmc.Material(material_id=1, name='UO2 fuel') -uo2.set_density('macro', 1.0) -uo2.add_macroscopic(uo2_data) - -water = openmc.Material(material_id=2, name='Water') -water.set_density('macro', 1.0) -water.add_macroscopic(h2o_data) - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([uo2, water]) -materials_file.cross_sections = "./mgxs.h5" -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate ZCylinder surfaces -fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=0.54, name='Fuel OR') -left = openmc.XPlane(surface_id=4, x0=-0.63, name='left') -right = openmc.XPlane(surface_id=5, x0=0.63, name='right') -bottom = openmc.YPlane(surface_id=6, y0=-0.63, name='bottom') -top = openmc.YPlane(surface_id=7, y0=0.63, name='top') - -left.boundary_type = 'reflective' -right.boundary_type = 'reflective' -top.boundary_type = 'reflective' -bottom.boundary_type = 'reflective' - -# Instantiate Cells -fuel = openmc.Cell(cell_id=1, name='cell 1') -moderator = openmc.Cell(cell_id=2, name='cell 2') - -# Use surface half-spaces to define regions -fuel.region = -fuel_or -moderator.region = +fuel_or & +left & -right & +bottom & -top - -# Register Materials with Cells -fuel.fill = uo2 -moderator.fill = water - -# Instantiate Universe -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cells with Universe -root.add_cells([fuel, moderator]) - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.energy_mode = "multi-group" -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -bounds = [-0.63, -0.63, -1, 0.63, 0.63, 1] -uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.export_to_xml() - -############################################################################### -# Exporting to OpenMC tallies.xml file -############################################################################### - -# Instantiate a tally mesh -mesh = openmc.RegularMesh(mesh_id=1) -mesh.dimension = [100, 100, 1] -mesh.lower_left = [-0.63, -0.63, -1.e50] -mesh.upper_right = [0.63, 0.63, 1.e50] - -# Instantiate some tally Filters -energy_filter = openmc.EnergyFilter([1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, - 1.0e6, 20.0e6]) -mesh_filter = openmc.MeshFilter(mesh) - -# Instantiate the Tally -tally = openmc.Tally(tally_id=1, name='tally 1') -tally.filters = [energy_filter, mesh_filter] -tally.scores = ['flux', 'fission', 'nu-fission'] - -# Instantiate a Tallies collection, register all Tallies, and export to XML -tallies_file = openmc.Tallies([tally]) -tallies_file.export_to_xml() diff --git a/examples/python/reflective/build-xml.py b/examples/python/reflective/build-xml.py deleted file mode 100644 index 09fa02626..000000000 --- a/examples/python/reflective/build-xml.py +++ /dev/null @@ -1,82 +0,0 @@ -import numpy as np -import openmc - -############################################################################### -# Simulation Input File Parameters -############################################################################### - -# OpenMC simulation parameters -batches = 500 -inactive = 10 -particles = 10000 - - -############################################################################### -# Exporting to OpenMC materials.xml file -############################################################################### - -# Instantiate a Material and register the Nuclide -fuel = openmc.Material(material_id=1, name='fuel') -fuel.set_density('g/cc', 4.5) -fuel.add_nuclide('U235', 1.) - -# Instantiate a Materials collection and export to XML -materials_file = openmc.Materials([fuel]) -materials_file.export_to_xml() - - -############################################################################### -# Exporting to OpenMC geometry.xml file -############################################################################### - -# Instantiate Surfaces -surf1 = openmc.XPlane(surface_id=1, x0=-1, name='surf 1') -surf2 = openmc.XPlane(surface_id=2, x0=+1, name='surf 2') -surf3 = openmc.YPlane(surface_id=3, y0=-1, name='surf 3') -surf4 = openmc.YPlane(surface_id=4, y0=+1, name='surf 4') -surf5 = openmc.ZPlane(surface_id=5, z0=-1, name='surf 5') -surf6 = openmc.ZPlane(surface_id=6, z0=+1, name='surf 6') - -surf1.boundary_type = 'vacuum' -surf2.boundary_type = 'vacuum' -surf3.boundary_type = 'reflective' -surf4.boundary_type = 'reflective' -surf5.boundary_type = 'reflective' -surf6.boundary_type = 'reflective' - -# Instantiate Cell -cell = openmc.Cell(cell_id=1, name='cell 1') - -# Use surface half-spaces to define region -cell.region = +surf1 & -surf2 & +surf3 & -surf4 & +surf5 & -surf6 - -# Register Material with Cell -cell.fill = fuel - -# Instantiate Universes -root = openmc.Universe(universe_id=0, name='root universe') - -# Register Cell with Universe -root.add_cell(cell) - -# Instantiate a Geometry, register the root Universe, and export to XML -geometry = openmc.Geometry(root) -geometry.export_to_xml() - - -############################################################################### -# Exporting to OpenMC settings.xml file -############################################################################### - -# Instantiate a Settings object, set all runtime parameters, and export to XML -settings_file = openmc.Settings() -settings_file.batches = batches -settings_file.inactive = inactive -settings_file.particles = particles - -# Create an initial uniform spatial source distribution over fissionable zones -uniform_dist = openmc.stats.Box(*cell.region.bounding_box, - only_fissionable=True) -settings_file.source = openmc.source.Source(space=uniform_dist) - -settings_file.export_to_xml() diff --git a/examples/xml/basic/geometry.xml b/examples/xml/basic/geometry.xml deleted file mode 100644 index b30884f8c..000000000 --- a/examples/xml/basic/geometry.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/examples/xml/basic/materials.xml b/examples/xml/basic/materials.xml deleted file mode 100644 index 606c676df..000000000 --- a/examples/xml/basic/materials.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/examples/xml/basic/settings.xml b/examples/xml/basic/settings.xml deleted file mode 100644 index 6e622b6ce..000000000 --- a/examples/xml/basic/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - eigenvalue - 15 - 5 - 10000 - - - - - -4 -4 -4 4 4 4 - - - - diff --git a/examples/xml/basic/tallies.xml b/examples/xml/basic/tallies.xml deleted file mode 100644 index a125e9ca2..000000000 --- a/examples/xml/basic/tallies.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - 100 - - - - 0 20.0e6 - - - - 0 20.0e6 - - - - 1 - total scatter nu-scatter absorption fission nu-fission - - - - 1 2 - total scatter nu-scatter absorption fission nu-fission - - - - 1 2 3 - scatter nu-scatter nu-fission - - - diff --git a/examples/xml/boxes/geometry.xml b/examples/xml/boxes/geometry.xml deleted file mode 100644 index abe4924e6..000000000 --- a/examples/xml/boxes/geometry.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/xml/boxes/materials.xml b/examples/xml/boxes/materials.xml deleted file mode 100644 index 1d0ab4a1c..000000000 --- a/examples/xml/boxes/materials.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/xml/boxes/plots.xml b/examples/xml/boxes/plots.xml deleted file mode 100644 index 0a75f574e..000000000 --- a/examples/xml/boxes/plots.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - cell - 0. 0. 0. - 20. 20. - 200 200 - - diff --git a/examples/xml/boxes/settings.xml b/examples/xml/boxes/settings.xml deleted file mode 100644 index 9007a12c5..000000000 --- a/examples/xml/boxes/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - eigenvalue - 15 - 5 - 10000 - - - - - - - diff --git a/examples/xml/lattice/nested/geometry.xml b/examples/xml/lattice/nested/geometry.xml deleted file mode 100644 index 324f71cb3..000000000 --- a/examples/xml/lattice/nested/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - 2 2 - -1.0 -1.0 - 1.0 1.0 - - 1 2 - 2 3 - - - - - - 2 2 - -2.0 -2.0 - 2.0 2.0 - - 5 5 - 5 5 - - - - - - - - - - - - diff --git a/examples/xml/lattice/nested/materials.xml b/examples/xml/lattice/nested/materials.xml deleted file mode 100644 index 222272195..000000000 --- a/examples/xml/lattice/nested/materials.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/examples/xml/lattice/nested/plots.xml b/examples/xml/lattice/nested/plots.xml deleted file mode 100644 index 0f92e0621..000000000 --- a/examples/xml/lattice/nested/plots.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 0. 0. 0. - 4.0 4.0 - 400 400 - - - diff --git a/examples/xml/lattice/nested/settings.xml b/examples/xml/lattice/nested/settings.xml deleted file mode 100644 index 879173d1b..000000000 --- a/examples/xml/lattice/nested/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 10000 - - - - - -1 -1 -1 1 1 1 - - - - diff --git a/examples/xml/lattice/nested/tallies.xml b/examples/xml/lattice/nested/tallies.xml deleted file mode 100644 index d342174a9..000000000 --- a/examples/xml/lattice/nested/tallies.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - regular - 4 4 - -2.0 -2.0 - 1.0 1.0 - - - - 1 - - - - 1 - total - - - diff --git a/examples/xml/lattice/simple/geometry.xml b/examples/xml/lattice/simple/geometry.xml deleted file mode 100644 index bda7246c7..000000000 --- a/examples/xml/lattice/simple/geometry.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - 4 4 - -2.0 -2.0 - 1.0 1.0 - - 1 2 1 2 - 2 3 2 3 - 1 2 1 2 - 2 3 2 3 - - - - - - - - - - - - diff --git a/examples/xml/lattice/simple/materials.xml b/examples/xml/lattice/simple/materials.xml deleted file mode 100644 index 222272195..000000000 --- a/examples/xml/lattice/simple/materials.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/examples/xml/lattice/simple/plots.xml b/examples/xml/lattice/simple/plots.xml deleted file mode 100644 index 0f92e0621..000000000 --- a/examples/xml/lattice/simple/plots.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 0. 0. 0. - 4.0 4.0 - 400 400 - - - diff --git a/examples/xml/lattice/simple/settings.xml b/examples/xml/lattice/simple/settings.xml deleted file mode 100644 index 879173d1b..000000000 --- a/examples/xml/lattice/simple/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 10000 - - - - - -1 -1 -1 1 1 1 - - - - diff --git a/examples/xml/lattice/simple/tallies.xml b/examples/xml/lattice/simple/tallies.xml deleted file mode 100644 index d342174a9..000000000 --- a/examples/xml/lattice/simple/tallies.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - regular - 4 4 - -2.0 -2.0 - 1.0 1.0 - - - - 1 - - - - 1 - total - - - diff --git a/examples/xml/pincell/geometry.xml b/examples/xml/pincell/geometry.xml deleted file mode 100644 index f67f9e74c..000000000 --- a/examples/xml/pincell/geometry.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/xml/pincell/materials.xml b/examples/xml/pincell/materials.xml deleted file mode 100644 index 9f9afa384..000000000 --- a/examples/xml/pincell/materials.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/xml/pincell/settings.xml b/examples/xml/pincell/settings.xml deleted file mode 100644 index 5845898c8..000000000 --- a/examples/xml/pincell/settings.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - eigenvalue - 100 - 10 - 1000 - - - - - - -0.62992 -0.62992 -1. - 0.62992 0.62992 1. - - - - - - - -0.39218 -0.39218 -1.e50 - 0.39218 0.39218 1.e50 - 10 10 1 - - 1 - - diff --git a/examples/xml/pincell/tallies.xml b/examples/xml/pincell/tallies.xml deleted file mode 100644 index 7e1e0dafe..000000000 --- a/examples/xml/pincell/tallies.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - 100 100 1 - -0.62992 -0.62992 -1.e50 - 0.62992 0.62992 1.e50 - - - - 2 - - - - 0. 4. 20.0e6 - - - - 1 2 - flux fission nu-fission - - - diff --git a/examples/xml/pincell_multigroup/geometry.xml b/examples/xml/pincell_multigroup/geometry.xml deleted file mode 100644 index a1df07a9e..000000000 --- a/examples/xml/pincell_multigroup/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/examples/xml/pincell_multigroup/materials.xml b/examples/xml/pincell_multigroup/materials.xml deleted file mode 100644 index f0225b100..000000000 --- a/examples/xml/pincell_multigroup/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - ./mgxs.h5 - - - - - - - - - diff --git a/examples/xml/pincell_multigroup/mgxs.h5 b/examples/xml/pincell_multigroup/mgxs.h5 deleted file mode 100644 index dbcda859d..000000000 Binary files a/examples/xml/pincell_multigroup/mgxs.h5 and /dev/null differ diff --git a/examples/xml/pincell_multigroup/plots.xml b/examples/xml/pincell_multigroup/plots.xml deleted file mode 100644 index 92ab1c2ca..000000000 --- a/examples/xml/pincell_multigroup/plots.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - 1 - mat - material - 0 0 0 - 1.26 1.26 - slice - 1000 1000 - - - - - - - - 2 - cell - cell - 0 0 0 - 1.26 1.26 - slice - 1000 1000 - - - diff --git a/examples/xml/pincell_multigroup/settings.xml b/examples/xml/pincell_multigroup/settings.xml deleted file mode 100644 index 6966d02b7..000000000 --- a/examples/xml/pincell_multigroup/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - eigenvalue - 1000 - 100 - 10 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - multi-group - diff --git a/examples/xml/pincell_multigroup/tallies.xml b/examples/xml/pincell_multigroup/tallies.xml deleted file mode 100644 index d84e129f2..000000000 --- a/examples/xml/pincell_multigroup/tallies.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - 100 100 1 - -0.63 -0.63 -1e+50 - 0.63 0.63 1e+50 - - - 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 - - - 1 - - - 1 2 - flux fission nu-fission - - diff --git a/examples/xml/reflective/geometry.xml b/examples/xml/reflective/geometry.xml deleted file mode 100644 index 51cdf1ecb..000000000 --- a/examples/xml/reflective/geometry.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - 0 - 1 - 1 -2 3 -4 5 -6 - - - - - - - - - - - diff --git a/examples/xml/reflective/materials.xml b/examples/xml/reflective/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/examples/xml/reflective/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/examples/xml/reflective/settings.xml b/examples/xml/reflective/settings.xml deleted file mode 100644 index 0ae6e5623..000000000 --- a/examples/xml/reflective/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - eigenvalue - 500 - 10 - 10000 - - - - - -1 -1 -1 1 1 1 - - - - diff --git a/include/openmc/angle_energy.h b/include/openmc/angle_energy.h deleted file mode 100644 index 9c04ff8c7..000000000 --- a/include/openmc/angle_energy.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef OPENMC_ANGLE_ENERGY_H -#define OPENMC_ANGLE_ENERGY_H - -namespace openmc { - -//============================================================================== -//! Abstract type that defines a correlated or uncorrelated angle-energy -//! distribution that is a function of incoming energy. Each derived type must -//! implement a sample() method that returns an outgoing energy and -//! scattering cosine given an incoming energy. -//============================================================================== - -class AngleEnergy { -public: - virtual void sample(double E_in, double& E_out, double& mu) const = 0; - virtual ~AngleEnergy() = default; -}; - -} - -#endif // OPENMC_ANGLE_ENERGY_H diff --git a/include/openmc/bank.h b/include/openmc/bank.h deleted file mode 100644 index 93e2be669..000000000 --- a/include/openmc/bank.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef OPENMC_BANK_H -#define OPENMC_BANK_H - -#include -#include - -#include "openmc/particle.h" -#include "openmc/position.h" - -// Without an explicit instantiation of vector, the Intel compiler -// will complain about the threadprivate directive on filter_matches. Note that -// this has to happen *outside* of the openmc namespace -extern template class std::vector; - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -extern std::vector source_bank; -extern std::vector fission_bank; -extern std::vector secondary_bank; -#ifdef _OPENMP -extern std::vector master_fission_bank; -#endif - -#pragma omp threadprivate(fission_bank, secondary_bank) - -} // namespace simulation - -//============================================================================== -// Non-member functions -//============================================================================== - -void free_memory_bank(); - -} // namespace openmc - -#endif // OPENMC_BANK_H diff --git a/include/openmc/bremsstrahlung.h b/include/openmc/bremsstrahlung.h deleted file mode 100644 index bd9d012c1..000000000 --- a/include/openmc/bremsstrahlung.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef OPENMC_BREMSSTRAHLUNG_H -#define OPENMC_BREMSSTRAHLUNG_H - -#include "openmc/particle.h" - -#include "xtensor/xtensor.hpp" - -namespace openmc { - -//============================================================================== -// Bremsstrahlung classes -//============================================================================== - -class BremsstrahlungData { -public: - // Data - xt::xtensor pdf; //!< Bremsstrahlung energy PDF - xt::xtensor cdf; //!< Bremsstrahlung energy CDF - xt::xtensor yield; //!< Photon yield -}; - -class Bremsstrahlung { -public: - // Data - BremsstrahlungData electron; - BremsstrahlungData positron; -}; - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -extern xt::xtensor ttb_e_grid; //! energy T of incident electron in [eV] -extern xt::xtensor ttb_k_grid; //! reduced energy W/T of emitted photon - -} // namespace data - -//============================================================================== -// Global variables -//============================================================================== - -void thick_target_bremsstrahlung(Particle& p, double* E_lost); - -} // namespace openmc - -#endif // OPENMC_BREMSSTRAHLUNG_H diff --git a/include/openmc/capi.h b/include/openmc/capi.h deleted file mode 100644 index 82f01d60b..000000000 --- a/include/openmc/capi.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef OPENMC_CAPI_H -#define OPENMC_CAPI_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - int openmc_calculate_volumes(); - int openmc_cell_filter_get_bins(int32_t index, const int32_t** cells, int32_t* n); - 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_get_temperature(int32_t index, const int32_t* instance, double* T); - int openmc_cell_get_name(int32_t index, const char** name); - int openmc_cell_set_name(int32_t index, const char* name); - 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, const double** energies, size_t* n); - int openmc_energy_filter_set_bins(int32_t index, size_t n, const double* energies); - int openmc_energyfunc_filter_get_energy(int32_t index, size_t* n, const double** energy); - int openmc_energyfunc_filter_get_y(int32_t index, size_t* n, const double** y); - int openmc_energyfunc_filter_set_data(int32_t index, size_t n, - const double* energies, const double* y); - 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_meshes(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_get_type(int32_t index, char* type); - int openmc_filter_set_id(int32_t index, int32_t id); - int openmc_finalize(); - int openmc_find_cell(const double* xyz, int32_t* index, int32_t* instance); - int openmc_cell_bounding_box(const int32_t index, double* llc, double* urc); - int openmc_global_bounding_box(double* llc, double* urc); - int openmc_fission_bank(void** ptr, int64_t* n); - 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_mesh_index(int32_t id, int32_t* index); - int openmc_get_nuclide_index(const char name[], int* index); - int64_t openmc_get_seed(); - int openmc_get_tally_index(int32_t id, int32_t* index); - void openmc_get_tally_next_id(int32_t* id); - int openmc_global_tallies(double** ptr); - int openmc_hard_reset(); - int openmc_init(int argc, char* argv[], const void* intracomm); - bool openmc_is_statepoint_batch(); - int openmc_legendre_filter_get_order(int32_t index, int* order); - int openmc_legendre_filter_set_order(int32_t index, int order); - int openmc_load_nuclide(const char* name); - int openmc_material_add_nuclide(int32_t index, const char name[], double density); - int openmc_material_get_densities(int32_t index, const int** nuclides, const double** densities, int* n); - int openmc_material_get_id(int32_t index, int32_t* id); - int openmc_material_get_fissionable(int32_t index, bool* fissionable); - int openmc_material_get_density(int32_t index, double* density); - int openmc_material_get_volume(int32_t index, double* volume); - int openmc_material_set_density(int32_t index, double density, const char* units); - 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_get_name(int32_t index, const char** name); - int openmc_material_set_name(int32_t index, const char* name); - int openmc_material_set_volume(int32_t index, double volume); - int openmc_material_filter_get_bins(int32_t index, const int32_t** bins, size_t* n); - int openmc_material_filter_set_bins(int32_t index, size_t n, const int32_t* bins); - int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh); - int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh); - int openmc_mesh_get_id(int32_t index, int32_t* id); - int openmc_mesh_get_dimension(int32_t index, int** id, int* n); - int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n); - int openmc_mesh_set_id(int32_t index, int32_t id); - int openmc_mesh_set_dimension(int32_t index, int n, const int* dims); - int openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width); - int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh); - int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh); - int openmc_new_filter(const char* type, int32_t* index); - int openmc_next_batch(int* status); - int openmc_nuclide_name(int index, const char** name); - int openmc_plot_geometry(); - int openmc_id_map(const void* slice, int32_t* data_out); - int openmc_property_map(const void* slice, double* data_out); - int openmc_reset(); - int openmc_run(); - void openmc_set_seed(int64_t new_seed); - int openmc_simulation_finalize(); - int openmc_simulation_init(); - int openmc_source_bank(void** ptr, int64_t* n); - int openmc_spatial_legendre_filter_get_order(int32_t index, int* order); - int openmc_spatial_legendre_filter_get_params(int32_t index, int* axis, double* min, double* max); - int openmc_spatial_legendre_filter_set_order(int32_t index, int order); - int openmc_spatial_legendre_filter_set_params(int32_t index, const int* axis, - const double* min, const double* max); - int openmc_sphharm_filter_get_order(int32_t index, int* order); - int openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]); - int openmc_sphharm_filter_set_order(int32_t index, int order); - int openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]); - int openmc_statepoint_write(const char* filename, bool* write_source); - int openmc_tally_allocate(int32_t index, const char* type); - int openmc_tally_get_active(int32_t index, bool* active); - int openmc_tally_get_estimator(int32_t index, int* estimator); - int openmc_tally_get_id(int32_t index, int32_t* id); - int openmc_tally_get_filters(int32_t index, const int32_t** indices, size_t* 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_get_type(int32_t index, int32_t* type); - int openmc_tally_get_writable(int32_t index, bool* writable); - int openmc_tally_reset(int32_t index); - int openmc_tally_results(int32_t index, double** ptr, size_t shape_[3]); - int openmc_tally_set_active(int32_t index, bool active); - int openmc_tally_set_estimator(int32_t index, const char* estimator); - int openmc_tally_set_filters(int32_t index, size_t 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 char** scores); - int openmc_tally_set_type(int32_t index, const char* type); - int openmc_tally_set_writable(int32_t index, bool writable); - int openmc_zernike_filter_get_order(int32_t index, int* order); - int openmc_zernike_filter_get_params(int32_t index, double* x, double* y, double* r); - int openmc_zernike_filter_set_order(int32_t index, int order); - int openmc_zernike_filter_set_params(int32_t index, const double* x, - const double* y, const double* r); - - //! Sets the fixed variables that are used for CMFD linear solver - //! \param[in] CSR format index pointer array of loss matrix - //! \param[in] length of indptr - //! \param[in] CSR format index array of loss matrix - //! \param[in] number of non-zero elements in CMFD loss matrix - //! \param[in] dimension n of nxn CMFD loss matrix - //! \param[in] spectral radius of CMFD matrices and tolerances - //! \param[in] indices storing spatial and energy dimensions of CMFD problem - //! \param[in] coremap for problem, storing accelerated regions - extern "C" void openmc_initialize_linsolver(const int* indptr, int len_indptr, - const int* indices, int n_elements, - int dim, double spectral, - const int* cmfd_indices, - const int* map); - - //! Runs a Gauss Seidel linear solver to solve CMFD matrix equations - //! linear solver - //! \param[in] CSR format data array of coefficient matrix - //! \param[in] right hand side vector - //! \param[out] unknown vector - //! \param[in] tolerance on final error - //! \return number of inner iterations required to reach convergence - extern "C" int openmc_run_linsolver(const double* A_data, const double* b, - double* x, double tol); - - // Error codes - extern int OPENMC_E_UNASSIGNED; - extern int OPENMC_E_ALLOCATE; - extern int OPENMC_E_OUT_OF_BOUNDS; - extern int OPENMC_E_INVALID_SIZE; - extern int OPENMC_E_INVALID_ARGUMENT; - extern int OPENMC_E_INVALID_TYPE; - extern int OPENMC_E_INVALID_ID; - extern int OPENMC_E_GEOMETRY; - extern int OPENMC_E_DATA; - extern int OPENMC_E_PHYSICS; - extern int OPENMC_E_WARNING; - - // Global variables - extern char openmc_err_msg[256]; - -#ifdef __cplusplus -} -#endif - -#endif // OPENMC_CAPI_H diff --git a/include/openmc/cell.h b/include/openmc/cell.h deleted file mode 100644 index 7206938c4..000000000 --- a/include/openmc/cell.h +++ /dev/null @@ -1,300 +0,0 @@ -#ifndef OPENMC_CELL_H -#define OPENMC_CELL_H - -#include -#include -#include // for unique_ptr -#include -#include -#include - -#include "hdf5.h" -#include "pugixml.hpp" -#include "dagmc.h" - -#include "openmc/constants.h" -#include "openmc/neighbor_list.h" -#include "openmc/position.h" -#include "openmc/surface.h" - -namespace openmc { - -//============================================================================== -// Constants -//============================================================================== - -// TODO: Convert to enum -constexpr int FILL_MATERIAL {1}; -constexpr int FILL_UNIVERSE {2}; -constexpr int FILL_LATTICE {3}; - -// TODO: Convert to enum -constexpr int32_t OP_LEFT_PAREN {std::numeric_limits::max()}; -constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits::max() - 1}; -constexpr int32_t OP_COMPLEMENT {std::numeric_limits::max() - 2}; -constexpr int32_t OP_INTERSECTION {std::numeric_limits::max() - 3}; -constexpr int32_t OP_UNION {std::numeric_limits::max() - 4}; - -//============================================================================== -// Global variables -//============================================================================== - -class Cell; -class Universe; -class UniversePartitioner; - -namespace model { - extern std::vector> cells; - extern std::unordered_map cell_map; - - extern std::vector> universes; - extern std::unordered_map universe_map; -} // namespace model - -//============================================================================== -//! A geometry primitive that fills all space and contains cells. -//============================================================================== - -class Universe -{ -public: - int32_t id_; //!< Unique ID - std::vector cells_; //!< Cells within this universe - - //! \brief Write universe information to an HDF5 group. - //! \param group_id An HDF5 group id. - void to_hdf5(hid_t group_id) const; - - BoundingBox bounding_box() const; - - std::unique_ptr partitioner_; -}; - -//============================================================================== -//! A geometry primitive that links surfaces, universes, and materials -//============================================================================== - -class Cell { -public: - //---------------------------------------------------------------------------- - // Constructors, destructors, factory functions - - explicit Cell(pugi::xml_node cell_node); - Cell() {}; - virtual ~Cell() = default; - - //---------------------------------------------------------------------------- - // Methods - - //! \brief Determine if a cell contains the particle at a given location. - //! - //! The bounds of the cell are detemined by a logical expression involving - //! surface half-spaces. At initialization, the expression was converted - //! to RPN notation. - //! - //! The function is split into two cases, one for simple cells (those - //! involving only the intersection of half-spaces) and one for complex cells. - //! Simple cells can be evaluated with short circuit evaluation, i.e., as soon - //! as we know that one half-space is not satisfied, we can exit. This - //! provides a performance benefit for the common case. In - //! contains_complex, we evaluate the RPN expression using a stack, similar to - //! how a RPN calculator would work. - //! \param r The 3D Cartesian coordinate to check. - //! \param u A direction used to "break ties" the coordinates are very - //! close to a surface. - //! \param on_surface The signed index of a surface that the coordinate is - //! known to be on. This index takes precedence over surface sense - //! calculations. - virtual bool - contains(Position r, Direction u, int32_t on_surface) const = 0; - - //! Find the oncoming boundary of this cell. - virtual std::pair - distance(Position r, Direction u, int32_t on_surface) const = 0; - - //! Write all information needed to reconstruct the cell to an HDF5 group. - //! \param group_id An HDF5 group id. - virtual void to_hdf5(hid_t group_id) const = 0; - - //! Get the BoundingBox for this cell. - virtual BoundingBox bounding_box() const = 0; - - //---------------------------------------------------------------------------- - // Accessors - - //! Get the temperature of a cell instance - //! \param[in] instance Instance index. If -1 is given, the temperature for - //! the first instance is returned. - //! \return Temperature in [K] - double temperature(int32_t instance = -1) const; - - //! Set the temperature of a cell instance - //! \param[in] T Temperature in [K] - //! \param[in] instance Instance index. If -1 is given, the temperature for - //! all instances is set. - void set_temperature(double T, int32_t instance = -1); - - //! Get the name of a cell - //! \return Cell name - const std::string& name() const { return name_; }; - - //! Set the temperature of a cell instance - //! \param[in] name Cell name - void set_name(const std::string& name) { name_ = name; }; - - //---------------------------------------------------------------------------- - // Data members - - int32_t id_; //!< Unique ID - std::string name_; //!< User-defined name - int type_; //!< Material, universe, or lattice - int32_t universe_; //!< Universe # this cell is in - int32_t fill_; //!< Universe # filling this cell - int32_t n_instances_{0}; //!< Number of instances of this cell - - //! \brief Index corresponding to this cell in distribcell arrays - int distribcell_index_{C_NONE}; - - //! \brief Material(s) within this cell. - //! - //! May be multiple materials for distribcell. - std::vector material_; - - //! \brief Temperature(s) within this cell. - //! - //! The stored values are actually sqrt(k_Boltzmann * T) for each temperature - //! T. The units are sqrt(eV). - std::vector sqrtkT_; - - //! Definition of spatial region as Boolean expression of half-spaces - std::vector region_; - //! Reverse Polish notation for region expression - std::vector rpn_; - bool simple_; //!< Does the region contain only intersections? - - //! \brief Neighboring cells in the same universe. - NeighborList neighbors_; - - Position translation_ {0, 0, 0}; //!< Translation vector for filled universe - - //! \brief Rotational tranfsormation of the filled universe. - // - //! The vector is empty if there is no rotation. Otherwise, the first three - //! values are the rotation angles respectively about the x-, y-, and z-, axes - //! in degrees. The next 9 values give the rotation matrix in row-major - //! order. - std::vector rotation_; - - std::vector offset_; //!< Distribcell offset table -}; - -//============================================================================== - -class CSGCell : public Cell -{ -public: - CSGCell(); - - explicit CSGCell(pugi::xml_node cell_node); - - bool - contains(Position r, Direction u, int32_t on_surface) const; - - std::pair - distance(Position r, Direction u, int32_t on_surface) const; - - void to_hdf5(hid_t group_id) const; - - BoundingBox bounding_box() const; - -protected: - bool contains_simple(Position r, Direction u, int32_t on_surface) const; - bool contains_complex(Position r, Direction u, int32_t on_surface) const; - BoundingBox bounding_box_simple() const; - static BoundingBox bounding_box_complex(std::vector rpn); - - //! Applies DeMorgan's laws to a section of the RPN - //! \param start Starting point for token modification - //! \param stop Stopping point for token modification - static void apply_demorgan(std::vector::iterator start, - std::vector::iterator stop); - - //! Removes complement operators from the RPN - //! \param rpn The rpn to remove complement operators from. - static void remove_complement_ops(std::vector& rpn); - - //! Returns the beginning position of a parenthesis block (immediately before - //! two surface tokens) in the RPN given a starting position at the end of - //! that block (immediately after two surface tokens) - //! \param start Starting position of the search - //! \param rpn The rpn being searched - static std::vector::iterator - find_left_parenthesis(std::vector::iterator start, - const std::vector& rpn); - -}; - -//============================================================================== - -#ifdef DAGMC -class DAGCell : public Cell -{ -public: - DAGCell(); - - bool contains(Position r, Direction u, int32_t on_surface) const; - - std::pair - distance(Position r, Direction u, int32_t on_surface) const; - - BoundingBox bounding_box() const; - - void to_hdf5(hid_t group_id) const; - - moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of cell -}; -#endif - -//============================================================================== -//! Speeds up geometry searches by grouping cells in a search tree. -// -//! Currently this object only works with universes that are divided up by a -//! bunch of z-planes. It could be generalized to other planes, cylinders, -//! and spheres. -//============================================================================== - -class UniversePartitioner -{ -public: - explicit UniversePartitioner(const Universe& univ); - - //! Return the list of cells that could contain the given coordinates. - const std::vector& get_cells(Position r, Direction u) const; - -private: - //! A sorted vector of indices to surfaces that partition the universe - std::vector surfs_; - - //! Vectors listing the indices of the cells that lie within each partition - // - //! There are n+1 partitions with n surfaces. `partitions_.front()` gives the - //! cells that lie on the negative side of `surfs_.front()`. - //! `partitions_.back()` gives the cells that lie on the positive side of - //! `surfs_.back()`. Otherwise, `partitions_[i]` gives cells sandwiched - //! between `surfs_[i-1]` and `surfs_[i]`. - std::vector> partitions_; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_cells(pugi::xml_node node); - -#ifdef DAGMC -int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed); -#endif - -} // namespace openmc -#endif // OPENMC_CELL_H diff --git a/include/openmc/cmfd_solver.h b/include/openmc/cmfd_solver.h deleted file mode 100644 index 731fe7ffb..000000000 --- a/include/openmc/cmfd_solver.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef OPENMC_CMFD_SOLVER_H -#define OPENMC_CMFD_SOLVER_H - -namespace openmc { - -void free_memory_cmfd(); - -} // namespace openmc - -#endif // OPENMC_CMFD_SOLVER_H diff --git a/include/openmc/constants.h b/include/openmc/constants.h deleted file mode 100644 index 046a7abef..000000000 --- a/include/openmc/constants.h +++ /dev/null @@ -1,431 +0,0 @@ -//! \file constants.h -//! A collection of constants - -#ifndef OPENMC_CONSTANTS_H -#define OPENMC_CONSTANTS_H - -#include -#include -#include -#include - -namespace openmc { - -using double_2dvec = std::vector>; -using double_3dvec = std::vector>>; -using double_4dvec = std::vector>>>; - -// ============================================================================ -// VERSIONING NUMBERS - -// OpenMC major, minor, and release numbers -constexpr int VERSION_MAJOR {0}; -constexpr int VERSION_MINOR {11}; -constexpr int VERSION_RELEASE {0}; -constexpr bool VERSION_DEV {false}; -constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; - -// HDF5 data format -constexpr int HDF5_VERSION[] {3, 0}; - -// Version numbers for binary files -constexpr std::array VERSION_STATEPOINT {17, 0}; -constexpr std::array VERSION_PARTICLE_RESTART {2, 0}; -constexpr std::array VERSION_TRACK {2, 0}; -constexpr std::array VERSION_SUMMARY {6, 0}; -constexpr std::array VERSION_VOLUME {1, 0}; -constexpr std::array VERSION_VOXEL {2, 0}; -constexpr std::array VERSION_MGXS_LIBRARY {1, 0}; - -// ============================================================================ -// ADJUSTABLE PARAMETERS - -// NOTE: This is the only section of the constants module that should ever be -// adjusted. Modifying constants in other sections may cause the code to fail. - -// Monoatomic ideal-gas scattering treatment threshold -constexpr double FREE_GAS_THRESHOLD {400.0}; - -// Significance level for confidence intervals -constexpr double CONFIDENCE_LEVEL {0.95}; - -// Used for surface current tallies -constexpr double TINY_BIT {1e-8}; - -// User for precision in geometry -constexpr double FP_PRECISION {1e-14}; -constexpr double FP_REL_PRECISION {1e-5}; -constexpr double FP_COINCIDENT {1e-12}; - -// Maximum number of collisions/crossings -constexpr int MAX_EVENTS {1000000}; -constexpr int MAX_SAMPLE {100000}; - -// Maximum number of words in a single line, length of line, and length of -// single word -constexpr int MAX_LINE_LEN {250}; -constexpr int MAX_WORD_LEN {150}; - -// Maximum number of external source spatial resamples to encounter before an -// error is thrown. -constexpr int EXTSRC_REJECT_THRESHOLD {10000}; -constexpr double EXTSRC_REJECT_FRACTION {0.05}; - -// ============================================================================ -// MATH AND PHYSICAL CONSTANTS - -// Values here are from the Committee on Data for Science and Technology -// (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009). - -// TODO: cmath::M_PI has 3 more digits precision than the Fortran constant we -// use so for now we will reuse the Fortran constant until we are OK with -// modifying test results -constexpr double PI {3.1415926535898}; -const double SQRT_PI {std::sqrt(PI)}; -constexpr double INFTY {std::numeric_limits::max()}; - -// Physical constants -constexpr double MASS_NEUTRON {1.00866491588}; // mass of a neutron in amu -constexpr double MASS_NEUTRON_EV {939.5654133e6}; // mass of a neutron in eV/c^2 -constexpr double MASS_PROTON {1.007276466879}; // mass of a proton in amu -constexpr double MASS_ELECTRON_EV {0.5109989461e6}; // electron mass energy equivalent in eV/c^2 -constexpr double FINE_STRUCTURE {137.035999139}; // inverse fine structure constant -constexpr double PLANCK_C {1.2398419739062977e4}; // Planck's constant times c in eV-Angstroms -constexpr double AMU {1.660539040e-27}; // 1 amu in kg -constexpr double C_LIGHT {2.99792458e8}; // speed of light in m/s -constexpr double N_AVOGADRO {0.6022140857}; // Avogadro's number in 10^24/mol -constexpr double K_BOLTZMANN {8.6173303e-5}; // Boltzmann constant in eV/K - -// Electron subshell labels -constexpr std::array SUBSHELLS = { - "K", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5", - "N1", "N2", "N3", "N4", "N5", "N6", "N7", "O1", "O2", - "O3", "O4", "O5", "O6", "O7", "O8", "O9", "P1", "P2", - "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10", "P11", - "Q1", "Q2", "Q3" -}; - -// Void material and nuclide -// TODO: refactor and remove -constexpr int MATERIAL_VOID {-1}; -constexpr int NUCLIDE_NONE {-1}; - -// ============================================================================ -// CROSS SECTION RELATED CONSTANTS - -// Angular distribution type -// TODO: Convert to enum -constexpr int ANGLE_ISOTROPIC {1}; -constexpr int ANGLE_32_EQUI {2}; -constexpr int ANGLE_TABULAR {3}; -constexpr int ANGLE_LEGENDRE {4}; -constexpr int ANGLE_HISTOGRAM {5}; - -// Temperature treatment method -// TODO: Convert to enum? -constexpr int TEMPERATURE_NEAREST {1}; -constexpr int TEMPERATURE_INTERPOLATION {2}; - -// Reaction types -// TODO: Convert to enum -constexpr int REACTION_NONE {0}; -constexpr int TOTAL_XS {1}; -constexpr int ELASTIC {2}; -constexpr int N_NONELASTIC {3}; -constexpr int N_LEVEL {4}; -constexpr int MISC {5}; -constexpr int N_2ND {11}; -constexpr int N_2N {16}; -constexpr int N_3N {17}; -constexpr int N_FISSION {18}; -constexpr int N_F {19}; -constexpr int N_NF {20}; -constexpr int N_2NF {21}; -constexpr int N_NA {22}; -constexpr int N_N3A {23}; -constexpr int N_2NA {24}; -constexpr int N_3NA {25}; -constexpr int N_NP {28}; -constexpr int N_N2A {29}; -constexpr int N_2N2A {30}; -constexpr int N_ND {32}; -constexpr int N_NT {33}; -constexpr int N_N3HE {34}; -constexpr int N_ND2A {35}; -constexpr int N_NT2A {36}; -constexpr int N_4N {37}; -constexpr int N_3NF {38}; -constexpr int N_2NP {41}; -constexpr int N_3NP {42}; -constexpr int N_N2P {44}; -constexpr int N_NPA {45}; -constexpr int N_N1 {51}; -constexpr int N_N40 {90}; -constexpr int N_NC {91}; -constexpr int N_DISAPPEAR {101}; -constexpr int N_GAMMA {102}; -constexpr int N_P {103}; -constexpr int N_D {104}; -constexpr int N_T {105}; -constexpr int N_3HE {106}; -constexpr int N_A {107}; -constexpr int N_2A {108}; -constexpr int N_3A {109}; -constexpr int N_2P {111}; -constexpr int N_PA {112}; -constexpr int N_T2A {113}; -constexpr int N_D2A {114}; -constexpr int N_PD {115}; -constexpr int N_PT {116}; -constexpr int N_DA {117}; -constexpr int N_5N {152}; -constexpr int N_6N {153}; -constexpr int N_2NT {154}; -constexpr int N_TA {155}; -constexpr int N_4NP {156}; -constexpr int N_3ND {157}; -constexpr int N_NDA {158}; -constexpr int N_2NPA {159}; -constexpr int N_7N {160}; -constexpr int N_8N {161}; -constexpr int N_5NP {162}; -constexpr int N_6NP {163}; -constexpr int N_7NP {164}; -constexpr int N_4NA {165}; -constexpr int N_5NA {166}; -constexpr int N_6NA {167}; -constexpr int N_7NA {168}; -constexpr int N_4ND {169}; -constexpr int N_5ND {170}; -constexpr int N_6ND {171}; -constexpr int N_3NT {172}; -constexpr int N_4NT {173}; -constexpr int N_5NT {174}; -constexpr int N_6NT {175}; -constexpr int N_2N3HE {176}; -constexpr int N_3N3HE {177}; -constexpr int N_4N3HE {178}; -constexpr int N_3N2P {179}; -constexpr int N_3N3A {180}; -constexpr int N_3NPA {181}; -constexpr int N_DT {182}; -constexpr int N_NPD {183}; -constexpr int N_NPT {184}; -constexpr int N_NDT {185}; -constexpr int N_NP3HE {186}; -constexpr int N_ND3HE {187}; -constexpr int N_NT3HE {188}; -constexpr int N_NTA {189}; -constexpr int N_2N2P {190}; -constexpr int N_P3HE {191}; -constexpr int N_D3HE {192}; -constexpr int N_3HEA {193}; -constexpr int N_4N2P {194}; -constexpr int N_4N2A {195}; -constexpr int N_4NPA {196}; -constexpr int N_3P {197}; -constexpr int N_N3P {198}; -constexpr int N_3N2PA {199}; -constexpr int N_5N2P {200}; -constexpr int N_XP {203}; -constexpr int N_XD {204}; -constexpr int N_XT {205}; -constexpr int N_X3HE {206}; -constexpr int N_XA {207}; -constexpr int HEATING {301}; -constexpr int DAMAGE_ENERGY {444}; -constexpr int COHERENT {502}; -constexpr int INCOHERENT {504}; -constexpr int PAIR_PROD_ELEC {515}; -constexpr int PAIR_PROD {516}; -constexpr int PAIR_PROD_NUC {517}; -constexpr int PHOTOELECTRIC {522}; -constexpr int N_P0 {600}; -constexpr int N_PC {649}; -constexpr int N_D0 {650}; -constexpr int N_DC {699}; -constexpr int N_T0 {700}; -constexpr int N_TC {749}; -constexpr int N_3HE0 {750}; -constexpr int N_3HEC {799}; -constexpr int N_A0 {800}; -constexpr int N_AC {849}; -constexpr int N_2N0 {875}; -constexpr int N_2NC {891}; -constexpr int HEATING_LOCAL {901}; - -constexpr std::array DEPLETION_RX {N_GAMMA, N_P, N_A, N_2N, N_3N, N_4N}; - -// Fission neutron emission (nu) type -constexpr int NU_NONE {0}; // No nu values (non-fissionable) -constexpr int NU_POLYNOMIAL {1}; // Nu values given by polynomial -constexpr int NU_TABULAR {2}; // Nu values given by tabular distribution - -// Library types -constexpr int LIBRARY_NEUTRON {1}; -constexpr int LIBRARY_THERMAL {2}; -constexpr int LIBRARY_PHOTON {3}; -constexpr int LIBRARY_MULTIGROUP {4}; - -// Probability table parameters -constexpr int URR_CUM_PROB {0}; -constexpr int URR_TOTAL {1}; -constexpr int URR_ELASTIC {2}; -constexpr int URR_FISSION {3}; -constexpr int URR_N_GAMMA {4}; -constexpr int URR_HEATING {5}; - -// Maximum number of partial fission reactions -constexpr int PARTIAL_FISSION_MAX {4}; - -// Resonance elastic scattering methods -// TODO: Convert to enum -enum class ResScatMethod { - rvs, // Relative velocity sampling - dbrc, // Doppler broadening rejection correction - cxs // Constant cross section -}; - -// Electron treatments -// TODO: Convert to enum -constexpr int ELECTRON_LED {1}; // Local Energy Deposition -constexpr int ELECTRON_TTB {2}; // Thick Target Bremsstrahlung - -// ============================================================================ -// MULTIGROUP RELATED - -// MGXS Table Types -// TODO: Convert to enum -constexpr int MGXS_ISOTROPIC {1}; // Isotroically weighted data -constexpr int MGXS_ANGLE {2}; // Data by angular bins - -// Flag to denote this was a macroscopic data object -constexpr double MACROSCOPIC_AWR {-2.}; - -// Number of mu bins to use when converting Legendres to tabular type -constexpr int DEFAULT_NMU {33}; - -// Mgxs::get_xs enumerated types -// TODO: Convert to enum -constexpr int MG_GET_XS_TOTAL {0}; -constexpr int MG_GET_XS_ABSORPTION {1}; -constexpr int MG_GET_XS_INVERSE_VELOCITY {2}; -constexpr int MG_GET_XS_DECAY_RATE {3}; -constexpr int MG_GET_XS_SCATTER {4}; -constexpr int MG_GET_XS_SCATTER_MULT {5}; -constexpr int MG_GET_XS_SCATTER_FMU_MULT {6}; -constexpr int MG_GET_XS_SCATTER_FMU {7}; -constexpr int MG_GET_XS_FISSION {8}; -constexpr int MG_GET_XS_KAPPA_FISSION {9}; -constexpr int MG_GET_XS_PROMPT_NU_FISSION {10}; -constexpr int MG_GET_XS_DELAYED_NU_FISSION {11}; -constexpr int MG_GET_XS_NU_FISSION {12}; -constexpr int MG_GET_XS_CHI_PROMPT {13}; -constexpr int MG_GET_XS_CHI_DELAYED {14}; - -// ============================================================================ -// TALLY-RELATED CONSTANTS - -// Tally result entries -constexpr int RESULT_VALUE {0}; -constexpr int RESULT_SUM {1}; -constexpr int RESULT_SUM_SQ {2}; - -// Tally type -// TODO: Convert to enum -constexpr int TALLY_VOLUME {1}; -constexpr int TALLY_MESH_SURFACE {2}; -constexpr int TALLY_SURFACE {3}; - -// Tally estimator types -// TODO: Convert to enum -constexpr int ESTIMATOR_ANALOG {1}; -constexpr int ESTIMATOR_TRACKLENGTH {2}; -constexpr int ESTIMATOR_COLLISION {3}; - -// Event types for tallies -// TODO: Convert to enum -constexpr int EVENT_SURFACE {-2}; -constexpr int EVENT_LATTICE {-1}; -constexpr int EVENT_KILL {0}; -constexpr int EVENT_SCATTER {1}; -constexpr int EVENT_ABSORB {2}; - -// Tally score type -- if you change these, make sure you also update the -// _SCORES dictionary in openmc/capi/tally.py -// TODO: Convert to enum -constexpr int SCORE_FLUX {-1}; // flux -constexpr int SCORE_TOTAL {-2}; // total reaction rate -constexpr int SCORE_SCATTER {-3}; // scattering rate -constexpr int SCORE_NU_SCATTER {-4}; // scattering production rate -constexpr int SCORE_ABSORPTION {-5}; // absorption rate -constexpr int SCORE_FISSION {-6}; // fission rate -constexpr int SCORE_NU_FISSION {-7}; // neutron production rate -constexpr int SCORE_KAPPA_FISSION {-8}; // fission energy production rate -constexpr int SCORE_CURRENT {-9}; // current -constexpr int SCORE_EVENTS {-10}; // number of events -constexpr int SCORE_DELAYED_NU_FISSION {-11}; // delayed neutron production rate -constexpr int SCORE_PROMPT_NU_FISSION {-12}; // prompt neutron production rate -constexpr int SCORE_INVERSE_VELOCITY {-13}; // flux-weighted inverse velocity -constexpr int SCORE_FISS_Q_PROMPT {-14}; // prompt fission Q-value -constexpr int SCORE_FISS_Q_RECOV {-15}; // recoverable fission Q-value -constexpr int SCORE_DECAY_RATE {-16}; // delayed neutron precursor decay rate - -// Tally map bin finding -constexpr int NO_BIN_FOUND {-1}; - -// Tally filter and map types -// TODO: Refactor to remove or convert to enum -constexpr int FILTER_UNIVERSE {1}; -constexpr int FILTER_MATERIAL {2}; -constexpr int FILTER_CELL {3}; - -// Mesh types -constexpr int MESH_REGULAR {1}; - -// Tally surface current directions -constexpr int OUT_LEFT {1}; // x min -constexpr int IN_LEFT {2}; // x min -constexpr int OUT_RIGHT {3}; // x max -constexpr int IN_RIGHT {4}; // x max -constexpr int OUT_BACK {5}; // y min -constexpr int IN_BACK {6}; // y min -constexpr int OUT_FRONT {7}; // y max -constexpr int IN_FRONT {8}; // y max -constexpr int OUT_BOTTOM {9}; // z min -constexpr int IN_BOTTOM {10}; // z min -constexpr int OUT_TOP {11}; // z max -constexpr int IN_TOP {12}; // z max - -// Global tally parameters -constexpr int N_GLOBAL_TALLIES {4}; -constexpr int K_COLLISION {0}; -constexpr int K_ABSORPTION {1}; -constexpr int K_TRACKLENGTH {2}; -constexpr int LEAKAGE {3}; - -// Miscellaneous -constexpr int C_NONE {-1}; -constexpr int F90_NONE {0}; //TODO: replace usage of this with C_NONE - -// Interpolation rules -enum class Interpolation { - histogram = 1, lin_lin = 2, lin_log = 3, log_lin = 4, log_log = 5 -}; - -// Run modes -constexpr int RUN_MODE_FIXEDSOURCE {1}; -constexpr int RUN_MODE_EIGENVALUE {2}; -constexpr int RUN_MODE_PLOTTING {3}; -constexpr int RUN_MODE_PARTICLE {4}; -constexpr int RUN_MODE_VOLUME {5}; - -// ============================================================================ -// CMFD CONSTANTS - -// For non-accelerated regions on coarse mesh overlay -constexpr int CMFD_NOACCEL {-1}; - -} // namespace openmc - -#endif // OPENMC_CONSTANTS_H diff --git a/include/openmc/container_util.h b/include/openmc/container_util.h deleted file mode 100644 index 1e65a18df..000000000 --- a/include/openmc/container_util.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef OPENMC_CONTAINER_UTIL_H -#define OPENMC_CONTAINER_UTIL_H - -#include // for find -#include // for begin, end - -namespace openmc { - -template -inline bool contains(const C& v, const T& x) -{ - return std::end(v) != std::find(std::begin(v), std::end(v), x); -} - -} - -#endif // OPENMC_CONTAINER_UTIL_H diff --git a/include/openmc/cross_sections.h b/include/openmc/cross_sections.h deleted file mode 100644 index 3700bc217..000000000 --- a/include/openmc/cross_sections.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef OPENMC_CROSS_SECTIONS_H -#define OPENMC_CROSS_SECTIONS_H - -#include "pugixml.hpp" - -#include -#include -#include - -namespace openmc { - -//============================================================================== -// Library class -//============================================================================== - -class Library { -public: - // Types, enums - enum class Type { - neutron = 1, photon = 3, thermal = 2, multigroup = 4, wmp = 5 - }; - - // Constructors - Library() { }; - Library(pugi::xml_node node, const std::string& directory); - - // Comparison operator (for using in map) - bool operator<(const Library& other) { - return path_ < other.path_; - } - - // Data members - Type type_; //!< Type of data library - std::vector materials_; //!< Materials contained in library - std::string path_; //!< File path to library -}; - -using LibraryKey = std::pair; - -//============================================================================== -// Global variable declarations -//============================================================================== - -namespace data { - -//!< Data libraries -extern std::vector libraries; - -//! Maps (type, name) to index in libraries -extern std::map library_map; - -} // namespace data - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Read cross sections file (either XML or multigroup H5) and populate data -//! libraries -void read_cross_sections_xml(); - - -//! Load nuclide and thermal scattering data from HDF5 files -// -//! \param[in] nuc_temps Temperatures for each nuclide in [K] -//! \param[in] thermal_temps Temperatures for each thermal scattering table in [K] -void read_ce_cross_sections(const std::vector>& nuc_temps, - const std::vector>& thermal_temps); - -//! Read cross_sections.xml and populate data libraries -void read_ce_cross_sections_xml(); - -void library_clear(); - -} // namespace openmc - -#endif // OPENMC_CROSS_SECTIONS_H diff --git a/include/openmc/dagmc.h b/include/openmc/dagmc.h deleted file mode 100644 index d3012e3a0..000000000 --- a/include/openmc/dagmc.h +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef OPENMC_DAGMC_H -#define OPENMC_DAGMC_H - -namespace openmc { -extern "C" const bool dagmc_enabled; -} - -#ifdef DAGMC - -#include "DagMC.hpp" -#include "openmc/xml_interface.h" -#include "openmc/position.h" - -namespace openmc { - -namespace simulation { - -extern moab::DagMC::RayHistory history; //!< facet history for DagMC particles -extern Direction last_dir; //!< last direction passed to DagMC's ray_fire -#pragma omp threadprivate(history, last_dir) - -} - -namespace model { - extern moab::DagMC* DAG; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void load_dagmc_geometry(); -void free_memory_dagmc(); -void read_geometry_dagmc(); -bool read_uwuw_materials(pugi::xml_document& doc); -bool get_uwuw_materials_xml(std::string& s); - -} // namespace openmc - -#endif // DAGMC - -#endif // OPENMC_DAGMC_H diff --git a/include/openmc/distribution.h b/include/openmc/distribution.h deleted file mode 100644 index fecddc346..000000000 --- a/include/openmc/distribution.h +++ /dev/null @@ -1,197 +0,0 @@ -//! \file distribution.h -//! Univariate probability distributions - -#ifndef OPENMC_DISTRIBUTION_H -#define OPENMC_DISTRIBUTION_H - -#include // for size_t -#include // for unique_ptr -#include // for vector - -#include "pugixml.hpp" - -#include "openmc/constants.h" - -namespace openmc { - -//============================================================================== -//! Abstract class representing a univariate probability distribution -//============================================================================== - -class Distribution { -public: - virtual ~Distribution() = default; - virtual double sample() const = 0; -}; - -//============================================================================== -//! A discrete distribution (probability mass function) -//============================================================================== - -class Discrete : public Distribution { -public: - explicit Discrete(pugi::xml_node node); - Discrete(const double* x, const double* p, int n); - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; - - // Properties - const std::vector& x() const { return x_; } - const std::vector& p() const { return p_; } -private: - std::vector x_; //!< Possible outcomes - std::vector p_; //!< Probability of each outcome - - //! Normalize distribution so that probabilities sum to unity - void normalize(); -}; - -//============================================================================== -//! Uniform distribution over the interval [a,b] -//============================================================================== - -class Uniform : public Distribution { -public: - explicit Uniform(pugi::xml_node node); - Uniform(double a, double b) : a_{a}, b_{b} {}; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - double a_; //!< Lower bound of distribution - double b_; //!< Upper bound of distribution -}; - -//============================================================================== -//! Maxwellian distribution of form c*E*exp(-E/theta) -//============================================================================== - -class Maxwell : public Distribution { -public: - explicit Maxwell(pugi::xml_node node); - Maxwell(double theta) : theta_{theta} { }; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - double theta_; //!< Factor in exponential [eV] -}; - -//============================================================================== -//! Watt fission spectrum with form c*exp(-E/a)*sinh(sqrt(b*E)) -//============================================================================== - -class Watt : public Distribution { -public: - explicit Watt(pugi::xml_node node); - Watt(double a, double b) : a_{a}, b_{b} { }; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - double a_; //!< Factor in exponential [eV] - double b_; //!< Factor in square root [1/eV] -}; - -//============================================================================== -//! Normal distributions with form 1/2*std_dev*sqrt(pi) exp (-(e-E0)/2*std_dev)^2 -//============================================================================== - -class Normal : public Distribution { -public: - explicit Normal(pugi::xml_node node); - Normal(double mean_value, double std_dev) : mean_value_{mean_value}, std_dev_{std_dev} { }; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - double mean_value_; //!< middle of distribution [eV] - double std_dev_; //!< standard deviation [eV] -}; - -//============================================================================== -//! Muir (fusion) spectrum derived from Normal with extra params e0 is mean -//! std dev is sqrt(4*e0*kt/m) -//============================================================================== - -class Muir : public Distribution { -public: - explicit Muir(pugi::xml_node node); - Muir(double e0, double m_rat, double kt) : e0_{e0}, m_rat_{m_rat}, kt_{kt} { }; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - // example DT fusion m_rat = 5 (D = 2 + T = 3) - // ion temp = 20000 eV - // mean neutron energy 14.08e6 eV - double e0_; //!< mean neutron energy [eV] - double m_rat_; //!< ratio of reactant masses relative to atomic mass unit - double kt_; //!< ion temperature [eV] -}; - -//============================================================================== -//! Histogram or linear-linear interpolated tabular distribution -//============================================================================== - -class Tabular : public Distribution { -public: - explicit Tabular(pugi::xml_node node); - Tabular(const double* x, const double* p, int n, Interpolation interp, - const double* c=nullptr); - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; - - // x property - std::vector& x() { return x_; } - const std::vector& x() const { return x_; } -private: - std::vector x_; //!< tabulated independent variable - std::vector p_; //!< tabulated probability density - std::vector c_; //!< cumulative distribution at tabulated values - Interpolation interp_; //!< interpolation rule - - //! Initialize tabulated probability density function - //! \param x Array of values for independent variable - //! \param p Array of tabulated probabilities - //! \param n Number of tabulated values - void init(const double* x, const double* p, std::size_t n, - const double* c=nullptr); -}; - -//============================================================================== -//! Equiprobable distribution -//============================================================================== - -class Equiprobable : public Distribution { -public: - explicit Equiprobable(pugi::xml_node node); - Equiprobable(const double* x, int n) : x_{x, x+n} { }; - - //! Sample a value from the distribution - //! \return Sampled value - double sample() const; -private: - std::vector x_; //! Possible outcomes -}; - - -using UPtrDist = std::unique_ptr; - -//! Return univariate probability distribution specified in XML file -//! \param[in] node XML node representing distribution -//! \return Unique pointer to distribution -UPtrDist distribution_from_xml(pugi::xml_node node); - -} // namespace openmc - -#endif // OPENMC_DISTRIBUTION_H diff --git a/include/openmc/distribution_angle.h b/include/openmc/distribution_angle.h deleted file mode 100644 index 4344eb60d..000000000 --- a/include/openmc/distribution_angle.h +++ /dev/null @@ -1,40 +0,0 @@ -//! \file distribution_angle.h -//! Angle distribution dependent on incident particle energy - -#ifndef OPENMC_DISTRIBUTION_ANGLE_H -#define OPENMC_DISTRIBUTION_ANGLE_H - -#include // for vector - -#include "hdf5.h" - -#include "openmc/distribution.h" - -namespace openmc { - -//============================================================================== -//! Angle distribution that depends on incident particle energy -//============================================================================== - -class AngleDistribution { -public: - AngleDistribution() = default; - explicit AngleDistribution(hid_t group); - - //! Sample an angle given an incident particle energy - //! \param[in] E Particle energy in [eV] - //! \return Cosine of the angle in the range [-1,1] - double sample(double E) const; - - //! Determine whether angle distribution is empty - //! \return Whether distribution is empty - bool empty() const { return energy_.empty(); } - -private: - std::vector energy_; - std::vector distribution_; -}; - -} // namespace openmc - -#endif // OPENMC_DISTRIBUTION_ANGLE_H diff --git a/include/openmc/distribution_energy.h b/include/openmc/distribution_energy.h deleted file mode 100644 index f13bd5de4..000000000 --- a/include/openmc/distribution_energy.h +++ /dev/null @@ -1,152 +0,0 @@ -//! \file distribution_energy.h -//! Energy distributions that depend on incident particle energy - -#ifndef OPENMC_DISTRIBUTION_ENERGY_H -#define OPENMC_DISTRIBUTION_ENERGY_H - -#include - -#include "xtensor/xtensor.hpp" -#include "hdf5.h" - -#include "openmc/constants.h" -#include "openmc/endf.h" - -namespace openmc { - -//=============================================================================== -//! Abstract class defining an energy distribution that is a function of the -//! incident energy of a projectile. Each derived type must implement a sample() -//! function that returns a sampled outgoing energy given an incoming energy -//=============================================================================== - -class EnergyDistribution { -public: - virtual double sample(double E) const = 0; - virtual ~EnergyDistribution() = default; -}; - -//=============================================================================== -//! Discrete photon energy distribution -//=============================================================================== - -class DiscretePhoton : public EnergyDistribution { -public: - explicit DiscretePhoton(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - int primary_flag_; //!< Indicator of whether the photon is a primary or - //!< non-primary photon. - double energy_; //!< Photon energy or binding energy - double A_; //!< Atomic weight ratio of the target nuclide -}; - -//=============================================================================== -//! Level inelastic scattering distribution -//=============================================================================== - -class LevelInelastic : public EnergyDistribution { -public: - explicit LevelInelastic(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - double threshold_; //!< Energy threshold in lab, (A + 1)/A * |Q| - double mass_ratio_; //!< (A/(A+1))^2 -}; - -//=============================================================================== -//! An energy distribution represented as a tabular distribution with histogram -//! or linear-linear interpolation. This corresponds to ACE law 4, which NJOY -//! produces for a number of ENDF energy distributions. -//=============================================================================== - -class ContinuousTabular : public EnergyDistribution { -public: - explicit ContinuousTabular(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - //! Outgoing energy for a single incoming energy - struct CTTable { - Interpolation interpolation; //!< Interpolation law - int n_discrete; //!< Number of of discrete energies - xt::xtensor e_out; //!< Outgoing energies in [eV] - xt::xtensor p; //!< Probability density - xt::xtensor c; //!< Cumulative distribution - }; - - int n_region_; //!< Number of inteprolation regions - std::vector breakpoints_; //!< Breakpoints between regions - std::vector interpolation_; //!< Interpolation laws - std::vector energy_; //!< Incident energy in [eV] - std::vector distribution_; //!< Distributions for each incident energy -}; - -//=============================================================================== -//! Evaporation spectrum corresponding to ACE law 9 and ENDF File 5, LF=9. -//=============================================================================== - -class Evaporation : public EnergyDistribution { -public: - explicit Evaporation(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - Tabulated1D theta_; //!< Incoming energy dependent parameter - double u_; //!< Restriction energy -}; - -//=============================================================================== -//! Energy distribution of neutrons emitted from a Maxwell fission spectrum. -//! This corresponds to ACE law 7 and ENDF File 5, LF=7. -//=============================================================================== - -class MaxwellEnergy : public EnergyDistribution { -public: - explicit MaxwellEnergy(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - Tabulated1D theta_; //!< Incoming energy dependent parameter - double u_; //!< Restriction energy -}; - -//=============================================================================== -//! Energy distribution of neutrons emitted from a Watt fission spectrum. This -//! corresponds to ACE law 11 and ENDF File 5, LF=11. -//=============================================================================== - -class WattEnergy : public EnergyDistribution { -public: - explicit WattEnergy(hid_t group); - - //! Sample energy distribution - //! \param[in] E Incident particle energy in [eV] - //! \return Sampled energy in [eV] - double sample(double E) const; -private: - Tabulated1D a_; //!< Energy-dependent 'a' parameter - Tabulated1D b_; //!< Energy-dependent 'b' parameter - double u_; //!< Restriction energy -}; - -} // namespace openmc - -#endif // OPENMC_DISTRIBUTION_ENERGY_H diff --git a/include/openmc/distribution_multi.h b/include/openmc/distribution_multi.h deleted file mode 100644 index 487f52831..000000000 --- a/include/openmc/distribution_multi.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef DISTRIBUTION_MULTI_H -#define DISTRIBUTION_MULTI_H - -#include - -#include "pugixml.hpp" - -#include "openmc/distribution.h" -#include "openmc/position.h" - -namespace openmc { - -//============================================================================== -//! Probability density function for points on the unit sphere. Extensions of -//! this type are used to sample angular distributions for starting sources -//============================================================================== - -class UnitSphereDistribution { -public: - UnitSphereDistribution() { }; - explicit UnitSphereDistribution(Direction u) : u_ref_{u} { }; - explicit UnitSphereDistribution(pugi::xml_node node); - virtual ~UnitSphereDistribution() = default; - - //! Sample a direction from the distribution - //! \return Direction sampled - virtual Direction sample() const = 0; - - Direction u_ref_ {0.0, 0.0, 1.0}; //!< reference direction -}; - -//============================================================================== -//! Explicit distribution of polar and azimuthal angles -//============================================================================== - -class PolarAzimuthal : public UnitSphereDistribution { -public: - PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi); - explicit PolarAzimuthal(pugi::xml_node node); - - //! Sample a direction from the distribution - //! \return Direction sampled - Direction sample() const; -private: - UPtrDist mu_; //!< Distribution of polar angle - UPtrDist phi_; //!< Distribution of azimuthal angle -}; - -//============================================================================== -//! Uniform distribution on the unit sphere -//============================================================================== - -class Isotropic : public UnitSphereDistribution { -public: - Isotropic() { }; - - //! Sample a direction from the distribution - //! \return Sampled direction - Direction sample() const; -}; - -//============================================================================== -//! Monodirectional distribution -//============================================================================== - -class Monodirectional : public UnitSphereDistribution { -public: - Monodirectional(Direction u) : UnitSphereDistribution{u} { }; - explicit Monodirectional(pugi::xml_node node) : UnitSphereDistribution{node} { }; - - //! Sample a direction from the distribution - //! \return Sampled direction - Direction sample() const; -}; - -using UPtrAngle = std::unique_ptr; - -} // namespace openmc - -#endif // DISTRIBUTION_MULTI_H diff --git a/include/openmc/distribution_spatial.h b/include/openmc/distribution_spatial.h deleted file mode 100644 index 248f03588..000000000 --- a/include/openmc/distribution_spatial.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef OPENMC_DISTRIBUTION_SPATIAL_H -#define OPENMC_DISTRIBUTION_SPATIAL_H - -#include "pugixml.hpp" - -#include "openmc/distribution.h" -#include "openmc/position.h" - -namespace openmc { - -//============================================================================== -//! Probability density function for points in Euclidean space -//============================================================================== - -class SpatialDistribution { -public: - virtual ~SpatialDistribution() = default; - - //! Sample a position from the distribution - virtual Position sample() const = 0; -}; - -//============================================================================== -//! Distribution of points specified by independent distributions in x,y,z -//============================================================================== - -class CartesianIndependent : public SpatialDistribution { -public: - explicit CartesianIndependent(pugi::xml_node node); - - //! Sample a position from the distribution - //! \return Sampled position - Position sample() const; -private: - UPtrDist x_; //!< Distribution of x coordinates - UPtrDist y_; //!< Distribution of y coordinates - UPtrDist z_; //!< Distribution of z coordinates -}; - -//============================================================================== -//! Uniform distribution of points over a box -//============================================================================== - -class SpatialBox : public SpatialDistribution { -public: - explicit SpatialBox(pugi::xml_node node, bool fission=false); - - //! Sample a position from the distribution - //! \return Sampled position - Position sample() const; - - // Properties - bool only_fissionable() const { return only_fissionable_; } -private: - Position lower_left_; //!< Lower-left coordinates of box - Position upper_right_; //!< Upper-right coordinates of box - bool only_fissionable_ {false}; //!< Only accept sites in fissionable region? -}; - -//============================================================================== -//! Distribution at a single point -//============================================================================== - -class SpatialPoint : public SpatialDistribution { -public: - SpatialPoint() : r_{} { }; - SpatialPoint(Position r) : r_{r} { }; - explicit SpatialPoint(pugi::xml_node node); - - //! Sample a position from the distribution - //! \return Sampled position - Position sample() const; -private: - Position r_; //!< Single position at which sites are generated -}; - -using UPtrSpace = std::unique_ptr; - -} // namespace openmc - -#endif // OPENMC_DISTRIBUTION_SPATIAL_H diff --git a/include/openmc/eigenvalue.h b/include/openmc/eigenvalue.h deleted file mode 100644 index d29f404b9..000000000 --- a/include/openmc/eigenvalue.h +++ /dev/null @@ -1,92 +0,0 @@ -//! \file eigenvalue.h -//! \brief Data/functions related to k-eigenvalue calculations - -#ifndef OPENMC_EIGENVALUE_H -#define OPENMC_EIGENVALUE_H - -#include -#include // for int64_t -#include - -#include "xtensor/xtensor.hpp" -#include - -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -extern double keff_generation; //!< Single-generation k on each processor -extern std::array k_sum; //!< Used to reduce sum and sum_sq -extern std::vector entropy; //!< Shannon entropy at each generation -extern xt::xtensor source_frac; //!< Source fraction for UFS - -} // namespace simulation - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Collect/normalize the tracklength keff from each process -void calculate_generation_keff(); - -//! Calculate mean/standard deviation of keff during active generations -//! -//! This function sets the global variables keff and keff_std which represent -//! the mean and standard deviation of the mean of k-effective over active -//! generations. It also broadcasts the value from the master process. -void calculate_average_keff(); - -#ifdef _OPENMP -//! Join threadprivate fission banks into a single fission bank -//! -//! Note that this operation is necessarily sequential to preserve the order of -//! the bank when using varying numbers of threads. -void join_bank_from_threads(); -#endif - -//! Calculates a minimum variance estimate of k-effective -//! -//! The minimum variance estimate is based on a linear combination of the -//! collision, absorption, and tracklength estimates. The theory behind this can -//! be found in M. Halperin, "Almost linearly-optimum combination of unbiased -//! estimates," J. Am. Stat. Assoc., 56, 36-43 (1961), -//! doi:10.1080/01621459.1961.10482088. The implementation here follows that -//! described in T. Urbatsch et al., "Estimation and interpretation of keff -//! confidence intervals in MCNP," Nucl. Technol., 111, 169-182 (1995). -//! -//! \param[out] k_combined Estimate of k-effective and its standard deviation -//! \return Error status -extern "C" int openmc_get_keff(double* k_combined); - -//! Sample/redistribute source sites from accumulated fission sites -void synchronize_bank(); - -//! Calculates the Shannon entropy of the fission source distribution to assess -//! source convergence -void shannon_entropy(); - -//! Determines the source fraction in each UFS mesh cell and reweights the -//! source bank so that the sum of the weights is equal to n_particles. The -//! 'source_frac' variable is used later to bias the production of fission sites -void ufs_count_sites(); - -//! Get UFS weight corresponding to particle's location -extern "C" double ufs_get_weight(const Particle* p); - -//! Write data related to k-eigenvalue to statepoint -//! \param[in] group HDF5 group -void write_eigenvalue_hdf5(hid_t group); - -//! Read data related to k-eigenvalue from statepoint -//! \param[in] group HDF5 group -void read_eigenvalue_hdf5(hid_t group); - -} // namespace openmc - -#endif // OPENMC_EIGENVALUE_H diff --git a/include/openmc/endf.h b/include/openmc/endf.h deleted file mode 100644 index 27958db5c..000000000 --- a/include/openmc/endf.h +++ /dev/null @@ -1,133 +0,0 @@ -//! \file endf.h -//! Classes and functions related to the ENDF-6 format - -#ifndef OPENMC_ENDF_H -#define OPENMC_ENDF_H - -#include -#include - -#include "hdf5.h" - -#include "openmc/constants.h" - -namespace openmc { - -//! Convert integer representing interpolation law to enum -//! \param[in] i Intereger (e.g. 1=histogram, 2=lin-lin) -//! \return Corresponding enum value -Interpolation int2interp(int i); - -//! Determine whether MT number corresponds to a fission reaction -//! \param[in] MT ENDF MT value -//! \return Whether corresponding reaction is a fission reaction -bool is_fission(int MT); - -//! Determine if a given MT number is that of a disappearance reaction, i.e., a -//! reaction with no neutron in the exit channel -//! \param[in] MT ENDF MT value -//! \return Whether corresponding reaction is a disappearance reaction -bool is_disappearance(int MT); - -//! Determine if a given MT number is that of an inelastic scattering reaction -//! \param[in] MT ENDF MT value -//! \return Whether corresponding reaction is an inelastic scattering reaction -bool is_inelastic_scatter(int MT); - -//============================================================================== -//! Abstract one-dimensional function -//============================================================================== - -class Function1D { -public: - virtual double operator()(double x) const = 0; - virtual ~Function1D() = default; -}; - -//============================================================================== -//! One-dimensional function expressed as a polynomial -//============================================================================== - -class Polynomial : public Function1D { -public: - //! Construct polynomial from HDF5 data - //! \param[in] dset Dataset containing coefficients - explicit Polynomial(hid_t dset); - - //! Evaluate the polynomials - //! \param[in] x independent variable - //! \return Polynomial evaluated at x - double operator()(double x) const override; -private: - std::vector coef_; //!< Polynomial coefficients -}; - -//============================================================================== -//! One-dimensional interpolable function -//============================================================================== - -class Tabulated1D : public Function1D { -public: - Tabulated1D() = default; - - //! Construct function from HDF5 data - //! \param[in] dset Dataset containing tabulated data - explicit Tabulated1D(hid_t dset); - - //! Evaluate the tabulated function - //! \param[in] x independent variable - //! \return Function evaluated at x - double operator()(double x) const override; - - // Accessors - const std::vector& x() const { return x_; } - const std::vector& y() const { return y_; } -private: - std::size_t n_regions_ {0}; //!< number of interpolation regions - std::vector nbt_; //!< values separating interpolation regions - std::vector int_; //!< interpolation schemes - std::size_t n_pairs_; //!< number of (x,y) pairs - std::vector x_; //!< values of abscissa - std::vector y_; //!< values of ordinate -}; - -//============================================================================== -//! Coherent elastic scattering data from a crystalline material -//============================================================================== - -class CoherentElasticXS : public Function1D { -public: - explicit CoherentElasticXS(hid_t dset); - - double operator()(double E) const override; - - const std::vector& bragg_edges() const { return bragg_edges_; } - const std::vector& factors() const { return factors_; } -private: - std::vector bragg_edges_; //!< Bragg edges in [eV] - std::vector factors_; //!< Partial sums of structure factors [eV-b] -}; - -//============================================================================== -//! Incoherent elastic scattering cross section -//============================================================================== - -class IncoherentElasticXS : public Function1D { -public: - explicit IncoherentElasticXS(hid_t dset); - - double operator()(double E) const override; -private: - double bound_xs_; //!< Characteristic bound xs in [b] - double debye_waller_; //!< Debye-Waller integral divided by atomic mass in [eV^-1] -}; - -//! Read 1D function from HDF5 dataset -//! \param[in] group HDF5 group containing dataset -//! \param[in] name Name of dataset -//! \return Unique pointer to 1D function -std::unique_ptr read_function(hid_t group, const char* name); - -} // namespace openmc - -#endif // OPENMC_ENDF_H diff --git a/include/openmc/error.h b/include/openmc/error.h deleted file mode 100644 index 32ed36c8b..000000000 --- a/include/openmc/error.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef OPENMC_ERROR_H -#define OPENMC_ERROR_H - -#include -#include -#include - -#include "openmc/capi.h" - -#ifdef __GNUC__ -#define UNREACHABLE() __builtin_unreachable() -#else -#define UNREACHABLE() (void)0 -#endif - -namespace openmc { - -inline void -set_errmsg(const char* message) -{ - std::strcpy(openmc_err_msg, message); -} - -inline void -set_errmsg(const std::string& message) -{ - std::strcpy(openmc_err_msg, message.c_str()); -} - -inline void -set_errmsg(const std::stringstream& message) -{ - std::strcpy(openmc_err_msg, message.str().c_str()); -} - -[[noreturn]] void fatal_error(const std::string& message, int err=-1); - -[[noreturn]] inline -void fatal_error(const std::stringstream& message) -{ - fatal_error(message.str()); -} - -[[noreturn]] inline -void fatal_error(const char* message) -{ - fatal_error(std::string{message, std::strlen(message)}); -} - -void warning(const std::string& message); - -inline -void warning(const std::stringstream& message) -{ - warning(message.str()); -} - -void write_message(const std::string& message, int level=0); - -inline -void write_message(const std::stringstream& message, int level) -{ - write_message(message.str(), level); -} - -#ifdef OPENMC_MPI -extern "C" void abort_mpi(int code); -#endif - -} // namespace openmc -#endif // OPENMC_ERROR_H diff --git a/include/openmc/file_utils.h b/include/openmc/file_utils.h deleted file mode 100644 index f9c23468d..000000000 --- a/include/openmc/file_utils.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef OPENMC_FILE_UTILS_H -#define OPENMC_FILE_UTILS_H - -#include // for ifstream -#include - -namespace openmc { - -//! Determine if a file exists -//! \param[in] filename Path to file -//! \return Whether file exists -inline bool file_exists(const std::string& filename) -{ - std::ifstream s {filename}; - return s.good(); -} - -} // namespace openmc - -#endif // OPENMC_FILE_UTILS_H diff --git a/include/openmc/finalize.h b/include/openmc/finalize.h deleted file mode 100644 index f99201abe..000000000 --- a/include/openmc/finalize.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef OPENMC_FINALIZE_H -#define OPENMC_FINALIZE_H - -namespace openmc { - -} // namespace openmc - -#endif // OPENMC_FINALIZE_H diff --git a/include/openmc/geometry.h b/include/openmc/geometry.h deleted file mode 100644 index e386348c4..000000000 --- a/include/openmc/geometry.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef OPENMC_GEOMETRY_H -#define OPENMC_GEOMETRY_H - -#include -#include -#include -#include - -#include "openmc/particle.h" - - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - -extern int root_universe; //!< Index of root universe -extern int n_coord_levels; //!< Number of CSG coordinate levels - -extern std::vector overlap_check_count; - -} // namespace model - -//============================================================================== -// Information about nearest boundary crossing -//============================================================================== - -struct BoundaryInfo { - double distance {INFINITY}; //!< distance to nearest boundary - int surface_index {0}; //!< if boundary is surface, index in surfaces vector - int coord_level; //!< coordinate level after crossing boundary - std::array lattice_translation {}; //!< which way lattice indices will change -}; - -//============================================================================== -//! Check two distances by coincidence tolerance -//============================================================================== - -inline bool coincident(double d1, double d2) { - return std::abs(d1 - d2) < FP_COINCIDENT; -} - -//============================================================================== -//! Check for overlapping cells at a particle's position. -//============================================================================== - -bool check_cell_overlap(Particle* p, bool error=true); - -//============================================================================== -//! Locate a particle in the geometry tree and set its geometry data fields. -//! -//! \param p A particle to be located. This function will populate the -//! geometry-dependent data fields of the particle. -//! \param use_neighbor_lists If true, neighbor lists will be used to accelerate -//! the geometry search, but this only works if the cell attribute of the -//! particle's lowest coordinate level is valid and meaningful. -//! \return True if the particle's location could be found and ascribed to a -//! valid geometry coordinate stack. -//============================================================================== - -bool find_cell(Particle* p, bool use_neighbor_lists); - -//============================================================================== -//! Move a particle into a new lattice tile. -//============================================================================== - -void cross_lattice(Particle* p, const BoundaryInfo& boundary); - -//============================================================================== -//! Find the next boundary a particle will intersect. -//============================================================================== - -BoundaryInfo distance_to_boundary(Particle* p); - -} // namespace openmc - -#endif // OPENMC_GEOMETRY_H diff --git a/include/openmc/geometry_aux.h b/include/openmc/geometry_aux.h deleted file mode 100644 index ffcdcf885..000000000 --- a/include/openmc/geometry_aux.h +++ /dev/null @@ -1,118 +0,0 @@ -//! \file geometry_aux.h -//! Auxilary functions for geometry initialization and general data handling. - -#ifndef OPENMC_GEOMETRY_AUX_H -#define OPENMC_GEOMETRY_AUX_H - -#include -#include -#include - -namespace openmc { - -void read_geometry_xml(); - -//============================================================================== -//! Replace Universe, Lattice, and Material IDs with indices. -//============================================================================== - -void adjust_indices(); - -//============================================================================== -//! Assign defaults to cells with undefined temperatures. -//============================================================================== - -void assign_temperatures(); - -//============================================================================== -//! \brief Obtain a list of temperatures that each nuclide/thermal scattering -//! table appears at in the model. Later, this list is used to determine the -//! actual temperatures to read (which may be different if interpolation is -//! used) -//! -//! \param[out] nuc_temps Vector of temperatures for each nuclide -//! \param[out] thermal_temps Vector of tempratures for each thermal scattering -//! table -//============================================================================== - -void get_temperatures(std::vector>& nuc_temps, - std::vector>& thermal_temps); - -//============================================================================== -//! \brief Perform final setup for geometry -//! -//! \param[out] nuc_temps Vector of temperatures for each nuclide -//! \param[out] thermal_temps Vector of tempratures for each thermal scattering -//! table -//============================================================================== - -void finalize_geometry(std::vector>& nuc_temps, - std::vector>& thermal_temps); - -//============================================================================== -//! Figure out which Universe is the root universe. -//! -//! This function looks for a universe that is not listed in a Cell::fill or in -//! a Lattice. -//! \return The index of the root universe. -//============================================================================== - -int32_t find_root_universe(); - -//============================================================================== -//! Populate all data structures needed for distribcells. -//============================================================================== - -void prepare_distribcell(); - -//============================================================================== -//! Recursively search through the geometry and count cell instances. -//! -//! This function will update the Cell::n_instances value for each cell in the -//! geometry. -//! \param univ_indx The index of the universe to begin searching from (probably -//! the root universe). -//============================================================================== - -void count_cell_instances(int32_t univ_indx); - -//============================================================================== -//! Recursively search through universes and count universe instances. -//! \param search_univ The index of the universe to begin searching from. -//! \param target_univ_id The ID of the universe to be counted. -//! \return The number of instances of target_univ_id in the geometry tree under -//! search_univ. -//============================================================================== - -int count_universe_instances(int32_t search_univ, int32_t target_univ_id); - -//============================================================================== -//! Build a character array representing the path to a distribcell instance. -//! \param target_cell The index of the Cell in the global Cell array. -//! \param map The index of the distribcell mapping corresponding to the target -//! cell. -//! \param target_offset An instance number for a distributed cell. -//! \return The unique traversal through the geometry tree that leads to the -//! desired instance of the target cell. -//============================================================================== - -std::string -distribcell_path(int32_t target_cell, int32_t map, int32_t target_offset); - -//============================================================================== -//! Determine the maximum number of nested coordinate levels in the geometry. -//! \param univ The index of the universe to begin seraching from (probably the -//! root universe). -//! \return The number of coordinate levels. -//============================================================================== - -int maximum_levels(int32_t univ); - -//============================================================================== -//! Deallocates global vectors and maps for cells, universes, and lattices. -//============================================================================== - -void free_memory_geometry(); - -} // namespace openmc -#endif // OPENMC_GEOMETRY_AUX_H diff --git a/include/openmc/hdf5_interface.h b/include/openmc/hdf5_interface.h deleted file mode 100644 index d0474c834..000000000 --- a/include/openmc/hdf5_interface.h +++ /dev/null @@ -1,508 +0,0 @@ -#ifndef OPENMC_HDF5_INTERFACE_H -#define OPENMC_HDF5_INTERFACE_H - -#include // for min -#include -#include -#include -#include // for strlen -#include -#include -#include -#include - -#include "hdf5.h" -#include "hdf5_hl.h" -#include "xtensor/xadapt.hpp" -#include "xtensor/xarray.hpp" - -#include "openmc/position.h" -#include "openmc/error.h" - -namespace openmc { - -//============================================================================== -// Low-level internal functions -//============================================================================== - -void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, - void* buffer); -void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer); -void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, - void* buffer, bool indep); -void write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer, bool indep); -bool using_mpio_device(hid_t obj_id); - -//============================================================================== -// Normal functions that are used to read/write files -//============================================================================== - -hid_t create_group(hid_t parent_id, const std::string& name); - -inline hid_t create_group(hid_t parent_id, const std::stringstream& name) -{return create_group(parent_id, name.str());} - - -hid_t file_open(const std::string& filename, char mode, bool parallel=false); - -void write_string(hid_t group_id, const char* name, const std::string& buffer, - bool indep); - -std::vector attribute_shape(hid_t obj_id, const char* name); -std::vector dataset_names(hid_t group_id); -void ensure_exists(hid_t obj_id, const char* name, bool attribute=false); -std::vector group_names(hid_t group_id); -std::vector object_shape(hid_t obj_id); -std::string object_name(hid_t obj_id); - -//============================================================================== -// Fortran compatibility functions -//============================================================================== - -extern "C" { - bool attribute_exists(hid_t obj_id, const char* name); - size_t attribute_typesize(hid_t obj_id, const char* name); - hid_t create_group(hid_t parent_id, const char* name); - void close_dataset(hid_t dataset_id); - void close_group(hid_t group_id); - int dataset_ndims(hid_t dset); - size_t dataset_typesize(hid_t obj_id, const char* name); - hid_t file_open(const char* filename, char mode, bool parallel); - void file_close(hid_t file_id); - void get_name(hid_t obj_id, char* name); - int get_num_datasets(hid_t group_id); - int get_num_groups(hid_t group_id); - void get_datasets(hid_t group_id, char* name[]); - void get_groups(hid_t group_id, char* name[]); - void get_shape(hid_t obj_id, hsize_t* dims); - void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims); - bool object_exists(hid_t object_id, const char* name); - hid_t open_dataset(hid_t group_id, const char* name); - hid_t open_group(hid_t group_id, const char* name); - void read_attr_double(hid_t obj_id, const char* name, double* buffer); - void read_attr_int(hid_t obj_id, const char* name, int* buffer); - void read_attr_string(hid_t obj_id, const char* name, size_t slen, - char* buffer); - void read_complex(hid_t obj_id, const char* name, - std::complex* buffer, bool indep); - void read_double(hid_t obj_id, const char* name, double* buffer, - bool indep); - void read_int(hid_t obj_id, const char* name, int* buffer, - bool indep); - void read_llong(hid_t obj_id, const char* name, long long* buffer, - bool indep); - void read_string(hid_t obj_id, const char* name, size_t slen, - char* buffer, bool indep); - - - void read_tally_results(hid_t group_id, hsize_t n_filter, - hsize_t n_score, double* results); - void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, - const char* name, const double* buffer); - void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims, - const char* name, const int* buffer); - void write_attr_string(hid_t obj_id, const char* name, const char* buffer); - void write_double(hid_t group_id, int ndim, const hsize_t* dims, - const char* name, const double* buffer, bool indep); - void write_int(hid_t group_id, int ndim, const hsize_t* dims, - const char* name, const int* buffer, bool indep); - void write_llong(hid_t group_id, int ndim, const hsize_t* dims, - const char* name, const long long* buffer, bool indep); - void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, - const char* name, char const* buffer, bool indep); - void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, - const double* results); -} // extern "C" - -//============================================================================== -// Template struct used to map types to HDF5 datatype IDs, which are stored -// using the type hid_t. By having a single static data member, the template can -// be specialized for each type we know of. The specializations appear in the -// .cpp file since they are definitions. -//============================================================================== - -template -struct H5TypeMap { static const hid_t type_id; }; - -//============================================================================== -// Templates/overloads for read_attribute -//============================================================================== - -// Scalar version -template -void read_attribute(hid_t obj_id, const char* name, T& buffer) -{ - read_attr(obj_id, name, H5TypeMap::type_id, &buffer); -} - -// array version -template inline void -read_attribute(hid_t obj_id, const char* name, std::array& buffer) -{ - read_attr(obj_id, name, H5TypeMap::type_id, buffer.data()); -} - -// vector version -template -void read_attribute(hid_t obj_id, const char* name, std::vector& vec) -{ - // Get shape of attribute array - auto shape = attribute_shape(obj_id, name); - - // Allocate new array to read data into - std::size_t size = 1; - for (const auto x : shape) - size *= x; - vec.resize(size); - - // Read data from attribute - read_attr(obj_id, name, H5TypeMap::type_id, vec.data()); -} - -// Generic array version -template -void read_attribute(hid_t obj_id, const char* name, xt::xarray& arr) -{ - // Get shape of attribute array - auto shape = attribute_shape(obj_id, name); - - // Allocate new array to read data into - std::size_t size = 1; - for (const auto x : shape) - size *= x; - std::vector buffer(size); - - // Read data from attribute - read_attr(obj_id, name, H5TypeMap::type_id, buffer.data()); - - // Adapt array into xarray - arr = xt::adapt(buffer, shape); -} - -// overload for std::string -inline void -read_attribute(hid_t obj_id, const char* name, std::string& str) -{ - // Create buffer to read data into - auto n = attribute_typesize(obj_id, name); - char* buffer = new char[n]; - - // Read attribute and set string - read_attr_string(obj_id, name, n, buffer); - str = std::string{buffer, n}; - delete[] buffer; -} - -// overload for std::vector -inline void -read_attribute(hid_t obj_id, const char* name, std::vector& vec) -{ - auto dims = attribute_shape(obj_id, name); - auto m = dims[0]; - - // Allocate a C char array to get strings - auto n = attribute_typesize(obj_id, name); - char* buffer = new char[m*n]; - - // Read char data in attribute - read_attr_string(obj_id, name, n, buffer); - - for (int i = 0; i < m; ++i) { - // Determine proper length of string -- strlen doesn't work because - // buffer[i] might not have any null characters - std::size_t k = 0; - for (; k < n; ++k) if (buffer[i*n + k] == '\0') break; - - // Create string based on (char*, size_t) constructor - vec.emplace_back(&buffer[i*n], k); - } - delete[] buffer; -} - -//============================================================================== -// Templates/overloads for read_dataset and related methods -//============================================================================== - -// Template for scalars. We need to be careful that the compiler does not use -// this version of read_dataset for vectors, arrays, or other non-scalar types. -// enable_if_t allows us to conditionally remove the function from overload -// resolution when the type T doesn't meet a certain criterion. -template inline -std::enable_if_t>::value> -read_dataset(hid_t obj_id, const char* name, T& buffer, bool indep=false) -{ - read_dataset(obj_id, name, H5TypeMap::type_id, &buffer, indep); -} - -// overload for std::string -inline void -read_dataset(hid_t obj_id, const char* name, std::string& str, bool indep=false) -{ - // Create buffer to read data into - auto n = dataset_typesize(obj_id, name); - char* buffer = new char[n]; - - // Read attribute and set string - read_string(obj_id, name, n, buffer, indep); - str = std::string{buffer, n}; -} - -// array version -template inline void -read_dataset(hid_t dset, const char* name, std::array& buffer, bool indep=false) -{ - read_dataset(dset, name, H5TypeMap::type_id, buffer.data(), indep); -} - -// vector version -template -void read_dataset(hid_t dset, std::vector& vec, bool indep=false) -{ - // Get shape of dataset - std::vector shape = object_shape(dset); - - // Resize vector to appropriate size - vec.resize(shape[0]); - - // Read data into vector - read_dataset(dset, nullptr, H5TypeMap::type_id, vec.data(), indep); -} - -template -void read_dataset(hid_t obj_id, const char* name, std::vector& vec, bool indep=false) -{ - hid_t dset = open_dataset(obj_id, name); - read_dataset(dset, vec, indep); - close_dataset(dset); -} - -template -void read_dataset(hid_t dset, xt::xarray& arr, bool indep=false) -{ - // Get shape of dataset - std::vector shape = object_shape(dset); - - // Allocate space in the array to read data into - std::size_t size = 1; - for (const auto x : shape) - size *= x; - arr.resize(shape); - - // Read data from attribute - read_dataset(dset, nullptr, H5TypeMap::type_id, arr.data(), indep); -} - -template<> -void read_dataset(hid_t dset, xt::xarray>& arr, bool indep); - -template -void read_dataset(hid_t obj_id, const char* name, xt::xarray& arr, bool indep=false) -{ - // Open dataset and read array - hid_t dset = open_dataset(obj_id, name); - read_dataset(dset, arr, indep); - close_dataset(dset); -} - - -template -void read_dataset(hid_t obj_id, const char* name, xt::xtensor& arr, bool indep=false) -{ - // Open dataset and read array - hid_t dset = open_dataset(obj_id, name); - - // Get shape of dataset - std::vector hsize_t_shape = object_shape(dset); - close_dataset(dset); - - // cast from hsize_t to size_t - std::vector shape(hsize_t_shape.size()); - for (int i = 0; i < shape.size(); i++) { - shape[i] = static_cast(hsize_t_shape[i]); - } - - // Allocate new xarray to read data into - xt::xarray xarr(shape); - - // Read data from the dataset - read_dataset(obj_id, name, xarr); - - // Copy into xtensor - arr = xarr; -} - -// overload for Position -inline void -read_dataset(hid_t obj_id, const char* name, Position& r, bool indep=false) -{ - std::array x; - read_dataset(obj_id, name, x, indep); - r.x = x[0]; - r.y = x[1]; - r.z = x[2]; -} - -template -void read_dataset_as_shape(hid_t obj_id, const char* name, - xt::xtensor& arr, bool indep=false) -{ - hid_t dset = open_dataset(obj_id, name); - - // Allocate new array to read data into - std::size_t size = 1; - for (const auto x : arr.shape()) - size *= x; - std::vector buffer(size); - - // Read data from attribute - read_dataset(dset, nullptr, H5TypeMap::type_id, buffer.data(), indep); - - // Adapt into xarray - arr = xt::adapt(buffer, arr.shape()); - - close_dataset(dset); -} - - -template -void read_nd_vector(hid_t obj_id, const char* name, xt::xtensor& result, - bool must_have=false) -{ - if (object_exists(obj_id, name)) { - read_dataset_as_shape(obj_id, name, result, true); - } else if (must_have) { - fatal_error(std::string("Must provide " + std::string(name) + "!")); - } -} - -//============================================================================== -// Templates/overloads for write_attribute -//============================================================================== - -template inline void -write_attribute(hid_t obj_id, const char* name, T buffer) -{ - write_attr(obj_id, 0, nullptr, name, H5TypeMap::type_id, &buffer); -} - -inline void -write_attribute(hid_t obj_id, const char* name, const char* buffer) -{ - write_attr_string(obj_id, name, buffer); -} - -inline void -write_attribute(hid_t obj_id, const char* name, const std::string& buffer) -{ - write_attr_string(obj_id, name, buffer.c_str()); -} - -template inline void -write_attribute(hid_t obj_id, const char* name, const std::array& buffer) -{ - hsize_t dims[] {N}; - write_attr(obj_id, 1, dims, name, H5TypeMap::type_id, buffer.data()); -} - -template inline void -write_attribute(hid_t obj_id, const char* name, const std::vector& buffer) -{ - hsize_t dims[] {buffer.size()}; - write_attr(obj_id, 1, dims, name, H5TypeMap::type_id, buffer.data()); -} - -inline void -write_attribute(hid_t obj_id, const char* name, Position r) -{ - std::array buffer {r.x, r.y, r.z}; - write_attribute(obj_id, name, buffer); -} - - - -//============================================================================== -// Templates/overloads for write_dataset -//============================================================================== - -// Template for scalars (ensured by SFINAE) -template inline -std::enable_if_t>::value> -write_dataset(hid_t obj_id, const char* name, T buffer) -{ - write_dataset(obj_id, 0, nullptr, name, H5TypeMap::type_id, &buffer, false); -} - -inline void -write_dataset(hid_t obj_id, const char* name, const char* buffer) -{ - write_string(obj_id, name, buffer, false); -} - -template inline void -write_dataset(hid_t obj_id, const char* name, const std::array& buffer) -{ - hsize_t dims[] {N}; - write_dataset(obj_id, 1, dims, name, H5TypeMap::type_id, buffer.data(), false); -} - -inline void -write_dataset(hid_t obj_id, const char* name, const std::vector& buffer) -{ - auto n {buffer.size()}; - hsize_t dims[] {n}; - - // Determine length of longest string, including \0 - size_t m = 1; - for (const auto& s : buffer) { - m = std::max(m, s.size() + 1); - } - - // Copy data into contiguous buffer - char* temp = new char[n*m]; - std::fill(temp, temp + n*m, '\0'); - for (int i = 0; i < n; ++i) { - std::copy(buffer[i].begin(), buffer[i].end(), temp + i*m); - } - - // Write 2D data - write_string(obj_id, 1, dims, m, name, temp, false); - - // Free temp array - delete[] temp; -} - -template inline void -write_dataset(hid_t obj_id, const char* name, const std::vector& buffer) -{ - hsize_t dims[] {buffer.size()}; - write_dataset(obj_id, 1, dims, name, H5TypeMap::type_id, buffer.data(), false); -} - -// Template for xarray, xtensor, etc. -template inline void -write_dataset(hid_t obj_id, const char* name, const xt::xcontainer& arr) -{ - using T = typename D::value_type; - auto s = arr.shape(); - std::vector dims {s.cbegin(), s.cend()}; - write_dataset(obj_id, dims.size(), dims.data(), name, H5TypeMap::type_id, - arr.data(), false); -} - -inline void -write_dataset(hid_t obj_id, const char* name, Position r) -{ - std::array buffer {r.x, r.y, r.z}; - write_dataset(obj_id, name, buffer); -} - -inline void -write_dataset(hid_t obj_id, const char* name, std::string buffer) -{ - write_string(obj_id, name, buffer.c_str(), false); -} - -} // namespace openmc -#endif // OPENMC_HDF5_INTERFACE_H diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h deleted file mode 100644 index eba616474..000000000 --- a/include/openmc/initialize.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef OPENMC_INITIALIZE_H -#define OPENMC_INITIALIZE_H - -#ifdef OPENMC_MPI -#include "mpi.h" -#endif - -namespace openmc { - -int parse_command_line(int argc, char* argv[]); -#ifdef OPENMC_MPI -void initialize_mpi(MPI_Comm intracomm); -#endif -void read_input_xml(); - -} - -#endif // OPENMC_INITIALIZE_H diff --git a/include/openmc/lattice.h b/include/openmc/lattice.h deleted file mode 100644 index cd73b9640..000000000 --- a/include/openmc/lattice.h +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef OPENMC_LATTICE_H -#define OPENMC_LATTICE_H - -#include -#include -#include // for unique_ptr -#include -#include -#include - -#include "hdf5.h" -#include "pugixml.hpp" - -#include "openmc/constants.h" -#include "openmc/position.h" - - -namespace openmc { - -//============================================================================== -// Module constants -//============================================================================== - -constexpr int32_t NO_OUTER_UNIVERSE{-1}; - -enum class LatticeType { - rect, hex -}; - - -//============================================================================== -// Global variables -//============================================================================== - -class Lattice; - -namespace model { - extern std::vector> lattices; - extern std::unordered_map lattice_map; -} // namespace model - -//============================================================================== -//! \class Lattice -//! \brief Abstract type for ordered array of universes. -//============================================================================== - -class LatticeIter; -class ReverseLatticeIter; - -class Lattice -{ -public: - int32_t id_; //!< Universe ID number - std::string name_; //!< User-defined name - LatticeType type_; - std::vector universes_; //!< Universes filling each lattice tile - int32_t outer_ {NO_OUTER_UNIVERSE}; //!< Universe tiled outside the lattice - std::vector offsets_; //!< Distribcell offset table - - explicit Lattice(pugi::xml_node lat_node); - - virtual ~Lattice() {} - - virtual int32_t& operator[](std::array i_xyz) = 0; - - virtual LatticeIter begin(); - LatticeIter end(); - - virtual ReverseLatticeIter rbegin(); - ReverseLatticeIter rend(); - - //! Convert internal universe values from IDs to indices using universe_map. - void adjust_indices(); - - //! Allocate offset table for distribcell. - void allocate_offset_table(int n_maps) - {offsets_.resize(n_maps * universes_.size(), C_NONE);} - - //! Populate the distribcell offset tables. - int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map); - - //! \brief Check lattice indices. - //! \param i_xyz[3] The indices for a lattice tile. - //! \return true if the given indices fit within the lattice bounds. False - //! otherwise. - virtual bool are_valid_indices(const int i_xyz[3]) const = 0; - - bool - are_valid_indices(std::array i_xyz) const - { - int i_xyz_[3] {i_xyz[0], i_xyz[1], i_xyz[2]}; - return are_valid_indices(i_xyz_); - } - - //! \brief Find the next lattice surface crossing - //! \param r A 3D Cartesian coordinate. - //! \param u A 3D Cartesian direction. - //! \param i_xyz The indices for a lattice tile. - //! \return The distance to the next crossing and an array indicating how the - //! lattice indices would change after crossing that boundary. - virtual std::pair> - distance(Position r, Direction u, const std::array& i_xyz) const - = 0; - - //! \brief Find the lattice tile indices for a given point. - //! \param r A 3D Cartesian coordinate. - //! \return An array containing the indices of a lattice tile. - virtual std::array get_indices(Position r, Direction u) const = 0; - - //! \brief Get coordinates local to a lattice tile. - //! \param r A 3D Cartesian coordinate. - //! \param i_xyz The indices for a lattice tile. - //! \return Local 3D Cartesian coordinates. - virtual Position - get_local_position(Position r, const std::array i_xyz) const = 0; - - //! \brief Check flattened lattice index. - //! \param indx The index for a lattice tile. - //! \return true if the given index fit within the lattice bounds. False - //! otherwise. - virtual bool is_valid_index(int indx) const - {return (indx >= 0) && (indx < universes_.size());} - - //! \brief Get the distribcell offset for a lattice tile. - //! \param The map index for the target cell. - //! \param i_xyz[3] The indices for a lattice tile. - //! \return Distribcell offset i.e. the largest instance number for the target - //! cell found in the geometry tree under this lattice tile. - virtual int32_t& offset(int map, const int i_xyz[3]) = 0; - - //! \brief Convert an array index to a useful human-readable string. - //! \param indx The index for a lattice tile. - //! \return A string representing the lattice tile. - virtual std::string index_to_string(int indx) const = 0; - - //! \brief Write lattice information to an HDF5 group. - //! \param group_id An HDF5 group id. - void to_hdf5(hid_t group_id) const; - -protected: - bool is_3d_; //!< Has divisions along the z-axis? - - virtual void to_hdf5_inner(hid_t group_id) const = 0; -}; - -//============================================================================== -//! An iterator over lattice universes. -//============================================================================== - -class LatticeIter -{ -public: - int indx_; //!< An index to a Lattice universes or offsets array. - - LatticeIter(Lattice &lat, int indx) - : indx_(indx), lat_(lat) - {} - - bool operator==(const LatticeIter &rhs) {return (indx_ == rhs.indx_);} - - bool operator!=(const LatticeIter &rhs) {return !(*this == rhs);} - - int32_t& operator*() {return lat_.universes_[indx_];} - - LatticeIter& operator++() - { - while (indx_ < lat_.universes_.size()) { - ++indx_; - if (lat_.is_valid_index(indx_)) return *this; - } - indx_ = lat_.universes_.size(); - return *this; - } - -protected: - Lattice& lat_; -}; - -//============================================================================== -//! A reverse iterator over lattice universes. -//============================================================================== - -class ReverseLatticeIter : public LatticeIter -{ -public: - ReverseLatticeIter(Lattice &lat, int indx) - : LatticeIter {lat, indx} - {} - - ReverseLatticeIter& operator++() - { - while (indx_ > -1) { - --indx_; - if (lat_.is_valid_index(indx_)) return *this; - } - indx_ = -1; - return *this; - } -}; - -//============================================================================== - -class RectLattice : public Lattice -{ -public: - explicit RectLattice(pugi::xml_node lat_node); - - int32_t& operator[](std::array i_xyz); - - bool are_valid_indices(const int i_xyz[3]) const; - - std::pair> - distance(Position r, Direction u, const std::array& i_xyz) const; - - std::array get_indices(Position r, Direction u) const; - - Position - get_local_position(Position r, const std::array i_xyz) const; - - int32_t& offset(int map, const int i_xyz[3]); - - std::string index_to_string(int indx) const; - - void to_hdf5_inner(hid_t group_id) const; - -private: - std::array n_cells_; //!< Number of cells along each axis - Position lower_left_; //!< Global lower-left corner of the lattice - Position pitch_; //!< Lattice tile width along each axis - - // Convenience aliases - int &nx {n_cells_[0]}; - int &ny {n_cells_[1]}; - int &nz {n_cells_[2]}; -}; - -//============================================================================== - -class HexLattice : public Lattice -{ -public: - explicit HexLattice(pugi::xml_node lat_node); - - int32_t& operator[](std::array i_xyz); - - LatticeIter begin(); - - ReverseLatticeIter rbegin(); - - bool are_valid_indices(const int i_xyz[3]) const; - - std::pair> - distance(Position r, Direction u, const std::array& i_xyz) const; - - std::array get_indices(Position r, Direction u) const; - - Position - get_local_position(Position r, const std::array i_xyz) const; - - bool is_valid_index(int indx) const; - - int32_t& offset(int map, const int i_xyz[3]); - - std::string index_to_string(int indx) const; - - void to_hdf5_inner(hid_t group_id) const; - -private: - enum class Orientation { - y, //!< Flat side of lattice parallel to y-axis - x //!< Flat side of lattice parallel to x-axis - }; - - //! Fill universes_ vector for 'y' orientation - void fill_lattice_y(const std::vector& univ_words); - - //! Fill universes_ vector for 'x' orientation - void fill_lattice_x(const std::vector& univ_words); - - int n_rings_; //!< Number of radial tile positions - int n_axial_; //!< Number of axial tile positions - Orientation orientation_; //!< Orientation of lattice - Position center_; //!< Global center of lattice - std::array pitch_; //!< Lattice tile width and height -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_lattices(pugi::xml_node node); - -} // namespace openmc -#endif // OPENMC_LATTICE_H diff --git a/include/openmc/material.h b/include/openmc/material.h deleted file mode 100644 index 70c6b3852..000000000 --- a/include/openmc/material.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef OPENMC_MATERIAL_H -#define OPENMC_MATERIAL_H - -#include // for unique_ptr -#include -#include -#include - -#include -#include -#include "pugixml.hpp" -#include "xtensor/xtensor.hpp" - -#include "openmc/bremsstrahlung.h" -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -class Material; - -namespace model { - -extern std::vector> materials; -extern std::unordered_map material_map; - -} // namespace model - -//============================================================================== -//! A substance with constituent nuclides and thermal scattering data -//============================================================================== - -class Material -{ -public: - //---------------------------------------------------------------------------- - // Types - struct ThermalTable { - int index_table; //!< Index of table in data::thermal_scatt - int index_nuclide; //!< Index in nuclide_ - double fraction; //!< How often to use table - }; - - //---------------------------------------------------------------------------- - // Constructors, destructors, factory functions - Material() {}; - explicit Material(pugi::xml_node material_node); - ~Material(); - - //---------------------------------------------------------------------------- - // Methods - - void calculate_xs(Particle& p) const; - - //! Assign thermal scattering tables to specific nuclides within the material - //! so the code knows when to apply bound thermal scattering data - void init_thermal(); - - //! Set up mapping between global nuclides vector and indices in nuclide_ - void init_nuclide_index(); - - //! Finalize the material, assigning tables, normalize density, etc. - void finalize(); - - //! Write material data to HDF5 - void to_hdf5(hid_t group) const; - - //! Add nuclide to the material - // - //! \param[in] nuclide Name of the nuclide - //! \param[in] density Density of the nuclide in [atom/b-cm] - void add_nuclide(const std::string& nuclide, double density); - - //! Set atom densities for the material - // - //! \param[in] name Name of each nuclide - //! \param[in] density Density of each nuclide in [atom/b-cm] - void set_densities(const std::vector& name, - const std::vector& density); - - //---------------------------------------------------------------------------- - // Accessors - - //! Get density in [atom/b-cm] - //! \return Density in [atom/b-cm] - double density() const { return density_; } - - //! Get density in [g/cm^3] - //! \return Density in [g/cm^3] - double density_gpcc() const { return density_gpcc_; } - - //! Get name - //! \return Material name - const std::string& name() const { return name_; } - - //! Set name - void set_name(const std::string& name) { name_ = name; } - - //! Set total density of the material - // - //! \param[in] density Density value - //! \param[in] units Units of density - void set_density(double density, gsl::cstring_span units); - - //! Get nuclides in material - //! \return Indices into the global nuclides vector - gsl::span nuclides() const { return {nuclide_.data(), nuclide_.size()}; } - - //! Get densities of each nuclide in material - //! \return Densities in [atom/b-cm] - gsl::span densities() const { return {atom_density_.data(), atom_density_.size()}; } - - //! Get ID of material - //! \return ID of material - int32_t id() const { return id_; } - - //! Assign a unique ID to the material - //! \param[in] Unique ID to assign. A value of -1 indicates that an ID - //! should be automatically assigned. - void set_id(int32_t id); - - //! Get whether material is fissionable - //! \return Whether material is fissionable - bool fissionable() const { return fissionable_; } - - //! Get volume of material - //! \return Volume in [cm^3] - double volume() const; - - //---------------------------------------------------------------------------- - // Data - int32_t id_ {-1}; //!< Unique ID - std::string name_; //!< Name of material - std::vector nuclide_; //!< Indices in nuclides vector - std::vector element_; //!< Indices in elements vector - xt::xtensor atom_density_; //!< Nuclide atom density in [atom/b-cm] - double density_; //!< Total atom density in [atom/b-cm] - double density_gpcc_; //!< Total atom density in [g/cm^3] - double volume_ {-1.0}; //!< Volume in [cm^3] - bool fissionable_ {false}; //!< Does this material contain fissionable nuclides - bool depletable_ {false}; //!< Is the material depletable? - std::vector p0_; //!< Indicate which nuclides are to be treated with iso-in-lab scattering - - // To improve performance of tallying, we store an array (direct address - // table) that indicates for each nuclide in data::nuclides the index of the - // corresponding nuclide in the nuclide_ vector. If it is not present in the - // material, the entry is set to -1. - std::vector mat_nuclide_index_; - - // Thermal scattering tables - std::vector thermal_tables_; - - //! \brief Default temperature for cells containing this material. - //! - //! A negative value indicates no default temperature was specified. - double temperature_ {-1}; - - std::unique_ptr ttb_; - -private: - //---------------------------------------------------------------------------- - // Private methods - - //! Calculate the collision stopping power - void collision_stopping_power(double* s_col, bool positron); - - //! Initialize bremsstrahlung data - void init_bremsstrahlung(); - - //! Normalize density - void normalize_density(); - - void calculate_neutron_xs(Particle& p) const; - void calculate_photon_xs(Particle& p) const; - - //---------------------------------------------------------------------------- - // Private data members - gsl::index index_; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Calculate Sternheimer adjustment factor -double sternheimer_adjustment(const std::vector& f, const - std::vector& e_b_sq, double e_p_sq, double n_conduction, double - log_I, double tol, int max_iter); - -//! Calculate density effect correction -double density_effect(const std::vector& f, const std::vector& - e_b_sq, double e_p_sq, double n_conduction, double rho, double E, double tol, - int max_iter); - -//! Read material data from materials.xml -void read_materials_xml(); - -void free_memory_material(); - -} // namespace openmc -#endif // OPENMC_MATERIAL_H diff --git a/include/openmc/math_functions.h b/include/openmc/math_functions.h deleted file mode 100644 index 39b703ab5..000000000 --- a/include/openmc/math_functions.h +++ /dev/null @@ -1,277 +0,0 @@ -//! \file math_functions.h -//! A collection of elementary math functions. - -#ifndef OPENMC_MATH_FUNCTIONS_H -#define OPENMC_MATH_FUNCTIONS_H - -#include -#include -#include - -#include "openmc/constants.h" -#include "openmc/position.h" -#include "openmc/random_lcg.h" - - -namespace openmc { - -//============================================================================== -//! Calculate the percentile of the standard normal distribution with a -//! specified probability level. -//! -//! \param p The probability level -//! \return The requested percentile -//============================================================================== - -extern "C" double normal_percentile(double p); - -//============================================================================== -//! Calculate the percentile of the Student's t distribution with a specified -//! probability level and number of degrees of freedom. -//! -//! \param p The probability level -//! \param df The degrees of freedom -//! \return The requested percentile -//============================================================================== - -extern "C" double t_percentile(double p, int df); - -//============================================================================== -//! Calculate the n-th order Legendre polynomials at the value of x. -//! -//! \param n The maximum order requested -//! \param x The value to evaluate at; x is expected to be within [-1,1] -//! \param pnx The requested Legendre polynomials of order 0 to n (inclusive) -//! evaluated at x. -//============================================================================== - -extern "C" void calc_pn_c(int n, double x, double pnx[]); - -//============================================================================== -//! Find the value of f(x) given a set of Legendre coefficients and the value -//! of x. -//! -//! \param n The maximum order of the expansion -//! \param data The polynomial expansion coefficient data; without the (2l+1)/2 -//! factor. -//! \param x The value to evaluate at; x is expected to be within [-1,1] -//! \return The requested Legendre polynomials of order 0 to n (inclusive) -//! evaluated at x -//============================================================================== - -extern "C" double evaluate_legendre(int n, const double data[], double x); - -//============================================================================== -//! Calculate the n-th order real spherical harmonics for a given angle (in -//! terms of (u,v,w)) for all 0<=n and -m<=n<=n. -//! -//! \param n The maximum order requested -//! \param uvw[3] The direction the harmonics are requested at -//! \param rn The requested harmonics of order 0 to n (inclusive) -//! evaluated at uvw. -//============================================================================== - -extern "C" void calc_rn_c(int n, const double uvw[3], double rn[]); - -void calc_rn(int n, Direction u, double rn[]); - -//============================================================================== -//! Calculate the n-th order modified Zernike polynomial moment for a given -//! angle (rho, theta) location on the unit disk. -//! -//! This procedure uses the modified Kintner's method for calculating Zernike -//! polynomials as outlined in Chong, C. W., Raveendran, P., & Mukundan, -//! R. (2003). A comparative analysis of algorithms for fast computation of -//! Zernike moments. Pattern Recognition, 36(3), 731-742. -//! The normalization of the polynomials is such that the integral of Z_pq^2 -//! over the unit disk is exactly pi. -//! -//! \param n The maximum order requested -//! \param rho The radial parameter to specify location on the unit disk -//! \param phi The angle parameter to specify location on the unit disk -//! \param zn The requested moments of order 0 to n (inclusive) -//! evaluated at rho and phi. -//============================================================================== - -extern "C" void calc_zn(int n, double rho, double phi, double zn[]); - -//============================================================================== -//! Calculate only the even radial components of n-th order modified Zernike -//! polynomial moment with azimuthal dependency m = 0 for a given angle -//! (rho, theta) location on the unit disk. -//! -//! Since m = 0, n could only be even orders. Z_q0 = R_q0 -//! -//! This procedure uses the modified Kintner's method for calculating Zernike -//! polynomials as outlined in Chong, C. W., Raveendran, P., & Mukundan, -//! R. (2003). A comparative analysis of algorithms for fast computation of -//! Zernike moments. Pattern Recognition, 36(3), 731-742. -//! The normalization of the polynomials is such that the integral of Z_pq^2 -//! over the unit disk is exactly pi. -//! -//! \param n The maximum order requested -//! \param rho The radial parameter to specify location on the unit disk -//! \param phi The angle parameter to specify location on the unit disk -//! \param zn_rad The requested moments of order 0 to n (inclusive) -//! evaluated at rho and phi when m = 0. -//============================================================================== - -extern "C" void calc_zn_rad(int n, double rho, double zn_rad[]); - -//============================================================================== -//! Rotate the direction cosines through a polar angle whose cosine is mu and -//! through an azimuthal angle sampled uniformly. -//! -//! This is done with direct sampling rather than rejection sampling as is done -//! in MCNP and Serpent. -//! -//! \param uvw[3] The initial, and final, direction vector -//! \param mu The cosine of angle in lab or CM -//! \param phi The azimuthal angle; will randomly chosen angle if a nullptr -//! is passed -//============================================================================== - -extern "C" void rotate_angle_c(double uvw[3], double mu, const double* phi); - -Direction rotate_angle(Direction u, double mu, const double* phi); - -//============================================================================== -//! Samples an energy from the Maxwell fission distribution based on a direct -//! sampling scheme. -//! -//! The probability distribution function for a Maxwellian is given as -//! p(x) = 2/(T*sqrt(pi))*sqrt(x/T)*exp(-x/T). This PDF can be sampled using -//! rule C64 in the Monte Carlo Sampler LA-9721-MS. -//! -//! \param T The tabulated function of the incoming energy -//! \return The sampled outgoing energy -//============================================================================== - -extern "C" double maxwell_spectrum(double T); - -//============================================================================== -//! Samples an energy from a Watt energy-dependent fission distribution. -//! -//! Although fitted parameters exist for many nuclides, generally the -//! continuous tabular distributions (LAW 4) should be used in lieu of the Watt -//! spectrum. This direct sampling scheme is an unpublished scheme based on the -//! original Watt spectrum derivation (See F. Brown's MC lectures). -//! -//! \param a Watt parameter a -//! \param b Watt parameter b -//! \return The sampled outgoing energy -//============================================================================== - -extern "C" double watt_spectrum(double a, double b); - -//============================================================================== -//! Samples an energy from the Gaussian energy-dependent fission distribution. -//! -//! Samples from a Normal distribution with a given mean and standard deviation -//! The PDF is defined as s(x) = (1/2*sigma*sqrt(2) * e-((mu-x)/2*sigma)^2 -//! Its sampled according to -//! http://www-pdg.lbl.gov/2009/reviews/rpp2009-rev-monte-carlo-techniques.pdf -//! section 33.4.4 -//! -//! @param mean mean of the Gaussian distribution -//! @param std_dev standard deviation of the Gaussian distribution -//! @result The sampled outgoing energy -//============================================================================== - -extern "C" double normal_variate(double mean, double std_dev); - -//============================================================================== -//! Samples an energy from the Muir (Gaussian) energy-dependent distribution. -//! -//! This is another form of the Gaussian distribution but with more easily -//! modifiable parameters -//! https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS -//! -//! @param e0 peak neutron energy [eV] -//! @param m_rat ratio of the fusion reactants to AMU -//! @param kt the ion temperature of the reactants [eV] -//! @result The sampled outgoing energy -//============================================================================== - -extern "C" double muir_spectrum(double e0, double m_rat, double kt); - -//============================================================================== -//! Doppler broadens the windowed multipole curvefit. -//! -//! The curvefit is a polynomial of the form a/E + b/sqrt(E) + c + d sqrt(E)... -//! -//! \param E The energy to evaluate the broadening at -//! \param dopp sqrt(atomic weight ratio / kT) with kT given in eV -//! \param n The number of components to the polynomial -//! \param factors The output leading coefficient -//============================================================================== - -extern "C" void broaden_wmp_polynomials(double E, double dopp, int n, double factors[]); - -//============================================================================== -//! Constructs a natural cubic spline. -//! -//! Given a tabulated function y_i = f(x_i), this computes the second -//! derivative of the interpolating function at each x_i, which can then be -//! used in any subsequent calls to spline_interpolate or spline_integrate for -//! the same set of x and y values. -//! -//! \param n Number of points -//! \param x Values of the independent variable, which must be strictly -//! increasing. -//! \param y Values of the dependent variable. -//! \param[out] z The second derivative of the interpolating function at each -//! value of x. -//============================================================================== - -void spline(int n, const double x[], const double y[], double z[]); - -//============================================================================== -//! Determine the cubic spline interpolated y-value for a given x-value. -//! -//! \param n Number of points -//! \param x Values of the independent variable, which must be strictly -//! increasing. -//! \param y Values of the dependent variable. -//! \param z The second derivative of the interpolating function at each -//! value of x. -//! \param xint Point at which to evaluate the cubic spline polynomial -//! \return Interpolated value -//============================================================================== - -double spline_interpolate(int n, const double x[], const double y[], - const double z[], double xint); - -//============================================================================== -//! Evaluate the definite integral of the interpolating cubic spline between -//! the given endpoints. -//! -//! \param n Number of points -//! \param x Values of the independent variable, which must be strictly -//! increasing. -//! \param y Values of the dependent variable. -//! \param z The second derivative of the interpolating function at each -//! value of x. -//! \param xa Lower limit of integration -//! \param xb Upper limit of integration -//! \return Integral -//============================================================================== - -double spline_integrate(int n, const double x[], const double y[], - const double z[], double xa, double xb); - -//! Evaluate the Faddeeva function -//! -//! \param z Complex argument -//! \return Faddeeva function evaluated at z -std::complex faddeeva(std::complex z); - -//! Evaluate derivative of the Faddeeva function -//! -//! \param z Complex argument -//! \param order Order of the derivative -//! \return Derivative of Faddeeva function evaluated at z -std::complex w_derivative(std::complex z, int order); - -} // namespace openmc -#endif // OPENMC_MATH_FUNCTIONS_H diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h deleted file mode 100644 index 34782b5e3..000000000 --- a/include/openmc/mesh.h +++ /dev/null @@ -1,246 +0,0 @@ -//! \file mesh.h -//! \brief Mesh types used for tallies, Shannon entropy, CMFD, etc. - -#ifndef OPENMC_MESH_H -#define OPENMC_MESH_H - -#include // for unique_ptr -#include -#include - -#include "hdf5.h" -#include "pugixml.hpp" -#include "xtensor/xtensor.hpp" - -#include "openmc/particle.h" -#include "openmc/position.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -class Mesh; - -namespace model { - -extern std::vector> meshes; -extern std::unordered_map mesh_map; - -} // namespace model - -class Mesh -{ -public: - // Constructors and destructor - Mesh() = default; - Mesh(pugi::xml_node node); - virtual ~Mesh() = default; - - // Methods - - //! Determine which bins were crossed by a particle - // - //! \param[in] p Particle to check - //! \param[out] bins Bins that were crossed - //! \param[out] lengths Fraction of tracklength in each bin - virtual void bins_crossed(const Particle* p, std::vector& bins, - std::vector& lengths) const = 0; - - //! Determine which surface bins were crossed by a particle - // - //! \param[in] p Particle to check - //! \param[out] bins Surface bins that were crossed - virtual void - surface_bins_crossed(const Particle* p, std::vector& bins) const = 0; - - //! Get bin at a given position in space - // - //! \param[in] r Position to get bin for - //! \return Mesh bin - virtual int get_bin(Position r) const = 0; - - //! Get bin given mesh indices - // - //! \param[in] Array of mesh indices - //! \return Mesh bin - virtual int get_bin_from_indices(const int* ijk) const = 0; - - //! Get mesh indices given a position - // - //! \param[in] r Position to get indices for - //! \param[out] ijk Array of mesh indices - //! \param[out] in_mesh Whether position is in mesh - virtual void get_indices(Position r, int* ijk, bool* in_mesh) const = 0; - - //! Get mesh indices corresponding to a mesh bin - // - //! \param[in] bin Mesh bin - //! \param[out] ijk Mesh indices - virtual void get_indices_from_bin(int bin, int* ijk) const = 0; - - //! Get the number of mesh cells. - virtual int n_bins() const = 0; - - //! Get the number of mesh cell surfaces. - virtual int n_surface_bins() const = 0; - - //! Find the mesh lines that intersect an axis-aligned slice plot - // - //! \param[in] plot_ll The lower-left coordinates of the slice plot. - //! \param[in] plot_ur The upper-right coordinates of the slice plot. - //! \return A pair of vectors indicating where the mesh lines lie along each - //! of the plot's axes. For example an xy-slice plot will get back a vector - //! of x-coordinates and another of y-coordinates. These vectors may be - //! empty for low-dimensional meshes. - virtual std::pair, std::vector> - plot(Position plot_ll, Position plot_ur) const = 0; - - //! Write mesh data to an HDF5 group - // - //! \param[in] group HDF5 group - virtual void to_hdf5(hid_t group) const = 0; - - // Data members - - int id_ {-1}; //!< User-specified ID - int n_dimension_; //!< Number of dimensions - xt::xtensor lower_left_; //!< Lower-left coordinates of mesh - xt::xtensor upper_right_; //!< Upper-right coordinates of mesh -}; - -//============================================================================== -//! Tessellation of n-dimensional Euclidean space by congruent squares or cubes -//============================================================================== - -class RegularMesh : public Mesh -{ -public: - // Constructors - RegularMesh() = default; - RegularMesh(pugi::xml_node node); - - // Overriden methods - - void bins_crossed(const Particle* p, std::vector& bins, - std::vector& lengths) const override; - - void surface_bins_crossed(const Particle* p, std::vector& bins) - const override; - - int get_bin(Position r) const override; - - int get_bin_from_indices(const int* ijk) const override; - - void get_indices(Position r, int* ijk, bool* in_mesh) const override; - - void get_indices_from_bin(int bin, int* ijk) const override; - - int n_bins() const override; - - int n_surface_bins() const override; - - std::pair, std::vector> - plot(Position plot_ll, Position plot_ur) const override; - - void to_hdf5(hid_t group) const override; - - // New methods - - //! Check where a line segment intersects the mesh and if it intersects at all - // - //! \param[in,out] r0 In: starting position, out: intersection point - //! \param[in] r1 Ending position - //! \param[out] ijk Indices of the mesh bin containing the intersection point - //! \return Whether the line segment connecting r0 and r1 intersects mesh - bool intersects(Position& r0, Position r1, int* ijk) const; - - //! Count number of bank sites in each mesh bin / energy bin - // - //! \param[in] bank Array of bank sites - //! \param[out] Whether any bank sites are outside the mesh - //! \return Array indicating number of sites in each mesh/energy bin - xt::xtensor count_sites(const std::vector& bank, - bool* outside) const; - - // Data members - - double volume_frac_; //!< Volume fraction of each mesh element - xt::xtensor shape_; //!< Number of mesh elements in each dimension - xt::xtensor width_; //!< Width of each mesh element - -private: - bool intersects_1d(Position& r0, Position r1, int* ijk) const; - bool intersects_2d(Position& r0, Position r1, int* ijk) const; - bool intersects_3d(Position& r0, Position r1, int* ijk) const; -}; - -class RectilinearMesh : public Mesh -{ -public: - // Constructors - RectilinearMesh(pugi::xml_node node); - - // Overriden methods - - void bins_crossed(const Particle* p, std::vector& bins, - std::vector& lengths) const override; - - void surface_bins_crossed(const Particle* p, std::vector& bins) - const override; - - int get_bin(Position r) const override; - - int get_bin_from_indices(const int* ijk) const override; - - void get_indices(Position r, int* ijk, bool* in_mesh) const override; - - void get_indices_from_bin(int bin, int* ijk) const override; - - int n_bins() const override; - - int n_surface_bins() const override; - - std::pair, std::vector> - plot(Position plot_ll, Position plot_ur) const override; - - void to_hdf5(hid_t group) const override; - - // New methods - - //! Check where a line segment intersects the mesh and if it intersects at all - // - //! \param[in,out] r0 In: starting position, out: intersection point - //! \param[in] r1 Ending position - //! \param[out] ijk Indices of the mesh bin containing the intersection point - //! \return Whether the line segment connecting r0 and r1 intersects mesh - bool intersects(Position& r0, Position r1, int* ijk) const; - - // Data members - - xt::xtensor shape_; //!< Number of mesh elements in each dimension - -private: - std::vector> grid_; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Read meshes from either settings/tallies -// -//! \param[in] root XML node -void read_meshes(pugi::xml_node root); - -//! Write mesh data to an HDF5 group -// -//! \param[in] group HDF5 group -void meshes_to_hdf5(hid_t group); - -void free_memory_mesh(); - -} // namespace openmc - -#endif // OPENMC_MESH_H diff --git a/include/openmc/message_passing.h b/include/openmc/message_passing.h deleted file mode 100644 index c730674ab..000000000 --- a/include/openmc/message_passing.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef OPENMC_MESSAGE_PASSING_H -#define OPENMC_MESSAGE_PASSING_H - -#ifdef OPENMC_MPI -#include -#endif - -namespace openmc { -namespace mpi { - - extern int rank; - extern int n_procs; - extern bool master; - -#ifdef OPENMC_MPI - extern MPI_Datatype bank; - extern MPI_Comm intracomm; -#endif - -} // namespace mpi -} // namespace openmc - -#endif // OPENMC_MESSAGE_PASSING_H diff --git a/include/openmc/mgxs.h b/include/openmc/mgxs.h deleted file mode 100644 index 1b4062da9..000000000 --- a/include/openmc/mgxs.h +++ /dev/null @@ -1,183 +0,0 @@ -//! \file mgxs.h -//! A collection of classes for Multi-Group Cross Section data - -#ifndef OPENMC_MGXS_H -#define OPENMC_MGXS_H - -#include -#include - -#include "xtensor/xtensor.hpp" - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/xsdata.h" - - -namespace openmc { - -//============================================================================== -// Cache contains the cached data for an MGXS object -//============================================================================== - -struct CacheData { - double sqrtkT; // last temperature corresponding to t - int t; // temperature index - int a; // angle index - // last angle that corresponds to a - double u; - double v; - double w; -}; - -//============================================================================== -// MGXS contains the mgxs data for a nuclide/material -//============================================================================== - -class Mgxs { - private: - - xt::xtensor kTs; // temperature in eV (k * T) - int scatter_format; // flag for if this is legendre, histogram, or tabular - int num_delayed_groups; // number of delayed neutron groups - int num_groups; // number of energy groups - std::vector xs; // Cross section data - // MGXS Incoming Flux Angular grid information - bool is_isotropic; // used to skip search for angle indices if isotropic - int n_pol; - int n_azi; - std::vector polar; - std::vector azimuthal; - - //! \brief Initializes the Mgxs object metadata - //! - //! @param in_name Name of the object. - //! @param in_awr atomic-weight ratio. - //! @param in_kTs temperatures (in units of eV) that data is available. - //! @param in_fissionable Is this item fissionable or not. - //! @param in_scatter_format Denotes whether Legendre, Tabular, or - //! Histogram scattering is used. - //! @param in_is_isotropic Is this an isotropic or angular with respect to - //! the incoming particle. - //! @param in_polar Polar angle grid. - //! @param in_azimuthal Azimuthal angle grid. - void - init(const std::string& in_name, double in_awr, const std::vector& in_kTs, - bool in_fissionable, int in_scatter_format, bool in_is_isotropic, - const std::vector& in_polar, const std::vector& in_azimuthal); - - //! \brief Initializes the Mgxs object metadata from the HDF5 file - //! - //! @param xs_id HDF5 group id for the cross section data. - //! @param temperature Temperatures to read. - //! @param temps_to_read Resultant list of temperatures in the library - //! to read which correspond to the requested temperatures. - //! @param order_dim Resultant dimensionality of the scattering order. - void - metadata_from_hdf5(hid_t xs_id, const std::vector& temperature, - std::vector& temps_to_read, int& order_dim); - - //! \brief Performs the actual act of combining the microscopic data for a - //! single temperature. - //! - //! @param micros Microscopic objects to combine. - //! @param scalars Scalars to multiply the microscopic data by. - //! @param micro_ts The temperature index of the microscopic objects that - //! corresponds to the temperature of interest. - //! @param this_t The temperature index of the macroscopic object. - void - combine(const std::vector& micros, const std::vector& scalars, - const std::vector& micro_ts, int this_t); - - //! \brief Checks to see if this and that are able to be combined - //! - //! This comparison is used when building macroscopic cross sections - //! from microscopic cross sections. - //! @param that The other Mgxs to compare to this one. - //! @return True if they can be combined, False otherwise. - bool equiv(const Mgxs& that); - - public: - - std::string name; // name of dataset, e.g., UO2 - double awr; // atomic weight ratio - bool fissionable; // Is this fissionable - std::vector cache; // index and data cache - - Mgxs() = default; - - //! \brief Constructor that loads the Mgxs object from the HDF5 file - //! - //! @param xs_id HDF5 group id for the cross section data. - //! @param temperature Temperatures to read. - Mgxs(hid_t xs_id, const std::vector& temperature); - - //! \brief Constructor that initializes and populates all data to build a - //! macroscopic cross section from microscopic cross section. - //! - //! @param in_name Name of the object. - //! @param mat_kTs temperatures (in units of eV) that data is needed. - //! @param micros Microscopic objects to combine. - //! @param atom_densities Atom densities of those microscopic quantities. - Mgxs(const std::string& in_name, const std::vector& mat_kTs, - const std::vector& micros, const std::vector& atom_densities); - - //! \brief Provides a cross section value given certain parameters - //! - //! @param xstype Type of cross section requested, according to the - //! enumerated constants. - //! @param gin Incoming energy group. - //! @param gout Outgoing energy group; use nullptr if irrelevant, or if a - //! sum is requested. - //! @param mu Cosine of the change-in-angle, for scattering quantities; - //! use nullptr if irrelevant. - //! @param dg delayed group index; use nullptr if irrelevant. - //! @return Requested cross section value. - double - get_xs(int xstype, int gin, const int* gout, const double* mu, - const int* dg); - - //! \brief Samples the fission neutron energy and if prompt or delayed. - //! - //! @param gin Incoming energy group. - //! @param dg Sampled delayed group index. - //! @param gout Sampled outgoing energy group. - void - sample_fission_energy(int gin, int& dg, int& gout); - - //! \brief Samples the outgoing energy and angle from a scatter event. - //! - //! @param gin Incoming energy group. - //! @param gout Sampled outgoing energy group. - //! @param mu Sampled cosine of the change-in-angle. - //! @param wgt Weight of the particle to be adjusted. - void - sample_scatter(int gin, int& gout, double& mu, double& wgt); - - //! \brief Calculates cross section quantities needed for tracking. - //! - //! @param gin Incoming energy group. - //! @param sqrtkT Temperature of the material. - //! @param u Incoming particle direction. - //! @param total_xs Resultant total cross section. - //! @param abs_xs Resultant absorption cross section. - //! @param nu_fiss_xs Resultant nu-fission cross section. - void - calculate_xs(int gin, double sqrtkT, Direction u, - double& total_xs, double& abs_xs, double& nu_fiss_xs); - - //! \brief Sets the temperature index in cache given a temperature - //! - //! @param sqrtkT Temperature of the material. - void - set_temperature_index(double sqrtkT); - - //! \brief Sets the angle index in cache given a direction - //! - //! @param u Incoming particle direction. - void - set_angle_index(Direction u); -}; - -} // namespace openmc -#endif // OPENMC_MGXS_H diff --git a/include/openmc/mgxs_interface.h b/include/openmc/mgxs_interface.h deleted file mode 100644 index bf72d675b..000000000 --- a/include/openmc/mgxs_interface.h +++ /dev/null @@ -1,81 +0,0 @@ -//! \file mgxs_interface.h -//! A collection of C interfaces to the C++ Mgxs class - -#ifndef OPENMC_MGXS_INTERFACE_H -#define OPENMC_MGXS_INTERFACE_H - -#include "hdf5_interface.h" -#include "mgxs.h" - -#include - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -extern std::vector nuclides_MG; -extern std::vector macro_xs; -extern int num_energy_groups; -extern int num_delayed_groups; -extern std::vector energy_bins; -extern std::vector energy_bin_avg; -extern std::vector rev_energy_bins; - -} // namespace data - -//============================================================================== -// Mgxs data loading interface methods -//============================================================================== - -void read_mgxs(); - -void -add_mgxs(hid_t file_id, const std::string& name, - const std::vector& temperature); - -void create_macro_xs(); - -std::vector> get_mat_kTs(); - -void read_mg_cross_sections_header(); - -//============================================================================== -// Mgxs tracking/transport/tallying interface methods -//============================================================================== - -extern "C" void -calculate_xs_c(int i_mat, int gin, double sqrtkT, Direction u, - double& total_xs, double& abs_xs, double& nu_fiss_xs); - -double -get_nuclide_xs(int index, int xstype, int gin, const int* gout, - const double* mu, const int* dg); - -inline double -get_nuclide_xs(int index, int xstype, int gin) -{return get_nuclide_xs(index, xstype, gin, nullptr, nullptr, nullptr);} - -double -get_macro_xs(int index, int xstype, int gin, const int* gout, - const double* mu, const int* dg); - -inline double -get_macro_xs(int index, int xstype, int gin) -{return get_macro_xs(index, xstype, gin, nullptr, nullptr, nullptr);} - -//============================================================================== -// General Mgxs methods -//============================================================================== - -extern "C" void -get_name_c(int index, int name_len, char* name); - -extern "C" double -get_awr_c(int index); - -} // namespace openmc -#endif // OPENMC_MGXS_INTERFACE_H diff --git a/include/openmc/neighbor_list.h b/include/openmc/neighbor_list.h deleted file mode 100644 index f6142101d..000000000 --- a/include/openmc/neighbor_list.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef OPENMC_NEIGHBOR_LIST_H -#define OPENMC_NEIGHBOR_LIST_H - -#include -#include -#include -#include - -#include "openmc/openmp_interface.h" - -namespace openmc { - -//============================================================================== -//! A threadsafe, dynamic container for listing neighboring cells. -// -//! This container is a reduced interface for a linked list with an added OpenMP -//! lock for write operations. It allows for threadsafe dynamic growth; any -//! number of threads can safely read data without locks or reference counting. -//============================================================================== - -class NeighborList -{ -public: - using value_type = int32_t; - using const_iterator = std::forward_list::const_iterator; - - // Attempt to add an element. - // - // If the relevant OpenMP lock is currently owned by another thread, this - // function will return without actually modifying the data. It has been - // found that returning the transport calculation and possibly re-adding the - // element later is slightly faster than waiting on the lock to be released. - void push_back(int new_elem) - { - // Try to acquire the lock. - std::unique_lock lock(mutex_, std::try_to_lock); - if (lock) { - // It is possible another thread already added this element to the list - // while this thread was searching for a cell so make sure the given - // element isn't a duplicate before adding it. - if (std::find(list_.cbegin(), list_.cend(), new_elem) == list_.cend()) { - // Find the end of the list and add the the new element there. - if (!list_.empty()) { - auto it1 = list_.cbegin(); - auto it2 = ++list_.cbegin(); - while (it2 != list_.cend()) it1 = it2++; - list_.insert_after(it1, new_elem); - } else { - list_.push_front(new_elem); - } - } - } - } - - const_iterator cbegin() const - {return list_.cbegin();} - - const_iterator cend() const - {return list_.cend();} - - -private: - std::forward_list list_; - OpenMPMutex mutex_; -}; - -} // namespace openmc -#endif // OPENMC_NEIGHBOR_LIST_H diff --git a/include/openmc/nuclide.h b/include/openmc/nuclide.h deleted file mode 100644 index a1571ea58..000000000 --- a/include/openmc/nuclide.h +++ /dev/null @@ -1,148 +0,0 @@ -//! \file nuclide.h -//! \brief Nuclide type and other associated types/data - -#ifndef OPENMC_NUCLIDE_H -#define OPENMC_NUCLIDE_H - -#include -#include // for unique_ptr -#include -#include - -#include - -#include "openmc/constants.h" -#include "openmc/endf.h" -#include "openmc/particle.h" -#include "openmc/reaction.h" -#include "openmc/reaction_product.h" -#include "openmc/urr.h" -#include "openmc/wmp.h" - -namespace openmc { - -//============================================================================== -// Data for a nuclide -//============================================================================== - -class Nuclide { -public: - // Types, aliases - using EmissionMode = ReactionProduct::EmissionMode; - struct EnergyGrid { - std::vector grid_index; - std::vector energy; - }; - - // Constructors - Nuclide(hid_t group, const std::vector& temperature, int i_nuclide); - - //! Initialize logarithmic grid for energy searches - void init_grid(); - - void calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle& p); - - void calculate_sab_xs(int i_sab, double sab_frac, Particle& p); - - // Methods - double nu(double E, EmissionMode mode, int group=0) const; - void calculate_elastic_xs(Particle& p) const; - - //! Determines the microscopic 0K elastic cross section at a trial relative - //! energy used in resonance scattering - double elastic_xs_0K(double E) const; - - //! \brief Determines cross sections in the unresolved resonance range - //! from probability tables. - void calculate_urr_xs(int i_temp, Particle& p) const; - - // Data members - std::string name_; //!< Name of nuclide, e.g. "U235" - int Z_; //!< Atomic number - int A_; //!< Mass number - int metastable_; //!< Metastable state - double awr_; //!< Atomic weight ratio - int i_nuclide_; //!< Index in the nuclides array - - // Temperature dependent cross section data - std::vector kTs_; //!< temperatures in eV (k*T) - std::vector grid_; //!< Energy grid at each temperature - std::vector> xs_; //!< Cross sections at each temperature - - // Multipole data - std::unique_ptr multipole_; - - // Fission data - bool fissionable_ {false}; //!< Whether nuclide is fissionable - bool has_partial_fission_ {false}; //!< has partial fission reactions? - std::vector fission_rx_; //!< Fission reactions - int n_precursor_ {0}; //!< Number of delayed neutron precursors - std::unique_ptr total_nu_; //!< Total neutron yield - std::unique_ptr fission_q_prompt_; //!< Prompt fission energy release - std::unique_ptr fission_q_recov_; //!< Recoverable fission energy release - - // Resonance scattering information - bool resonant_ {false}; - std::vector energy_0K_; - std::vector elastic_0K_; - std::vector xs_cdf_; - - // Unresolved resonance range information - bool urr_present_ {false}; - int urr_inelastic_ {C_NONE}; - std::vector urr_data_; - - std::vector> reactions_; //!< Reactions - std::array reaction_index_; //!< Index of each reaction - std::vector index_inelastic_scatter_; - -private: - void create_derived(); - - static int XS_TOTAL; - static int XS_ABSORPTION; - static int XS_FISSION; - static int XS_NU_FISSION; - static int XS_PHOTON_PROD; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Checks for the right version of nuclear data within HDF5 files -void check_data_version(hid_t file_id); - -bool multipole_in_range(const Nuclide* nuc, double E); - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -// Minimum/maximum transport energy for each particle type. Order corresponds to -// that of the ParticleType enum -extern std::array energy_min; -extern std::array energy_max; - -//! Minimum temperature in [K] that nuclide data is available at -extern double temperature_min; - -//! Maximum temperature in [K] that nuclide data is available at -extern double temperature_max; - -extern std::vector> nuclides; -extern std::unordered_map nuclide_map; - -} // namespace data - -//============================================================================== -// Non-member functions -//============================================================================== - -void nuclides_clear(); - -} // namespace openmc - -#endif // OPENMC_NUCLIDE_H diff --git a/include/openmc/openmp_interface.h b/include/openmc/openmp_interface.h deleted file mode 100644 index 076b19dc0..000000000 --- a/include/openmc/openmp_interface.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef OPENMC_OPENMP_INTERFACE_H -#define OPENMC_OPENMP_INTERFACE_H - -#ifdef _OPENMP -#include -#endif - -namespace openmc { - -//============================================================================== -//! An object used to prevent concurrent access to a piece of data. -// -//! This type meets the C++ "Lockable" requirements. -//============================================================================== - -class OpenMPMutex -{ -public: - OpenMPMutex() - { - #ifdef _OPEMP - omp_init_lock(&mutex_); - #endif - } - - ~OpenMPMutex() - { - #ifdef _OPEMP - omp_destroy_lock(&mutex_); - #endif - } - - // Mutexes cannot be copied. We need to explicitly delete the copy - // constructor and copy assignment operator to ensure the compiler doesn't - // "help" us by implicitly trying to copy the underlying mutexes. - OpenMPMutex(const OpenMPMutex&) = delete; - OpenMPMutex& operator= (const OpenMPMutex&) = delete; - - //! Lock the mutex. - // - //! This function blocks execution until the lock succeeds. - void lock() - { - #ifdef _OPEMP - omp_set_lock(&mutex_); - #endif - } - - //! Try to lock the mutex and indicate success. - // - //! This function does not block. It returns immediately and gives false if - //! the lock is unavailable. - bool try_lock() noexcept - { - #ifdef _OPEMP - return omp_test_lock(&mutex_); - #else - return true; - #endif - } - - //! Unlock the mutex. - void unlock() noexcept - { - #ifdef _OPEMP - omp_unset_lock(&mutex_); - #endif - } - -private: - #ifdef _OPEMP - omp_lock_t mutex_; - #endif -}; - -} // namespace openmc -#endif // OPENMC_OPENMP_INTERFACE_H diff --git a/include/openmc/output.h b/include/openmc/output.h deleted file mode 100644 index 117f75148..000000000 --- a/include/openmc/output.h +++ /dev/null @@ -1,62 +0,0 @@ -//! \file output.h -//! Functions for ASCII output. - -#ifndef OPENMC_OUTPUT_H -#define OPENMC_OUTPUT_H - -#include - -#include "openmc/particle.h" - -namespace openmc { - -//! \brief Display the main title banner as well as information about the -//! program developers, version, and date/time which the problem was run. -void title(); - -//! Display a header block. -// -//! \param msg The main text of the header -//! \param level The lowest verbosity level at which this header is printed -void header(const char* msg, int level); - -//! Retrieve a time stamp. -// -//! \return current time stamp (format: "yyyy-mm-dd hh:mm:ss") -std::string time_stamp(); - -//! Display the attributes of a particle. -extern "C" void print_particle(Particle* p); - -//! Display plot information. -void print_plot(); - -//! Display information regarding cell overlap checking. -void print_overlap_check(); - -//! Display information about command line usage of OpenMC -void print_usage(); - -//! Display current version and copright/license information -void print_version(); - -//! Display header listing what physical values will displayed -void print_columns(); - -//! Display information about a generation of neutrons -void print_generation(); - -//! \brief Display last batch's tallied value of the neutron multiplication -//! factor as well as the average value if we're in active batches -void print_batch_keff(); - -//! Display time elapsed for various stages of a run -void print_runtime(); - -//! Display results for global tallies including k-effective estimators -void print_results(); - -void write_tallies(); - -} // namespace openmc -#endif // OPENMC_OUTPUT_H diff --git a/include/openmc/particle.h b/include/openmc/particle.h deleted file mode 100644 index a2b7ce557..000000000 --- a/include/openmc/particle.h +++ /dev/null @@ -1,292 +0,0 @@ -#ifndef OPENMC_PARTICLE_H -#define OPENMC_PARTICLE_H - -//! \file particle.h -//! \brief Particle type - -#include -#include -#include // for unique_ptr -#include -#include -#include - -#include "openmc/constants.h" -#include "openmc/position.h" - -namespace openmc { - -//============================================================================== -// Constants -//============================================================================== - -// Since cross section libraries come with different numbers of delayed groups -// (e.g. ENDF/B-VII.1 has 6 and JEFF 3.1.1 has 8 delayed groups) and we don't -// yet know what cross section library is being used when the tallies.xml file -// is read in, we want to have an upper bound on the size of the array we -// use to store the bins for delayed group tallies. -constexpr int MAX_DELAYED_GROUPS {8}; - -// Maximum number of lost particles -constexpr int MAX_LOST_PARTICLES {10}; - -// Maximum number of lost particles, relative to the total number of particles -constexpr double REL_MAX_LOST_PARTICLES {1.0e-6}; - -constexpr double CACHE_INVALID {-1.0}; - -//============================================================================== -// Class declarations -//============================================================================== - -class LocalCoord { -public: - void rotate(const std::vector& rotation); - - //! clear data from a single coordinate level - void reset(); - - Position r; //!< particle position - Direction u; //!< particle direction - int cell {-1}; - int universe {-1}; - int lattice {-1}; - int lattice_x {-1}; - int lattice_y {-1}; - int lattice_z {-1}; - bool rotated {false}; //!< Is the level rotated? -}; - -//============================================================================== -//! Cached microscopic cross sections for a particular nuclide at the current -//! energy -//============================================================================== - -struct NuclideMicroXS { - // Microscopic cross sections in barns - double total; //!< total cross section - double absorption; //!< absorption (disappearance) - double fission; //!< fission - double nu_fission; //!< neutron production from fission - - double elastic; //!< If sab_frac is not 1 or 0, then this value is - //!< averaged over bound and non-bound nuclei - double thermal; //!< Bound thermal elastic & inelastic scattering - double thermal_elastic; //!< Bound thermal elastic scattering - double photon_prod; //!< microscopic photon production xs - - // Cross sections for depletion reactions (note that these are not stored in - // macroscopic cache) - double reaction[DEPLETION_RX.size()]; - - // Indicies and factors needed to compute cross sections from the data tables - int index_grid; //!< Index on nuclide energy grid - int index_temp; //!< Temperature index for nuclide - double interp_factor; //!< Interpolation factor on nuc. energy grid - int index_sab {-1}; //!< Index in sab_tables - int index_temp_sab; //!< Temperature index for sab_tables - double sab_frac; //!< Fraction of atoms affected by S(a,b) - bool use_ptable; //!< In URR range with probability tables? - - // Energy and temperature last used to evaluate these cross sections. If - // these values have changed, then the cross sections must be re-evaluated. - double last_E {0.0}; //!< Last evaluated energy - double last_sqrtkT {0.0}; //!< Last temperature in sqrt(Boltzmann constant - //!< * temperature (eV)) -}; - -//============================================================================== -//! Cached microscopic photon cross sections for a particular element at the -//! current energy -//============================================================================== - -struct ElementMicroXS { - int index_grid; //!< index on element energy grid - double last_E {0.0}; //!< last evaluated energy in [eV] - double interp_factor; //!< interpolation factor on energy grid - double total; //!< microscopic total photon xs - double coherent; //!< microscopic coherent xs - double incoherent; //!< microscopic incoherent xs - double photoelectric; //!< microscopic photoelectric xs - double pair_production; //!< microscopic pair production xs -}; - -//============================================================================== -// MACROXS contains cached macroscopic cross sections for the material a -// particle is traveling through -//============================================================================== - -struct MacroXS { - double total; //!< macroscopic total xs - double absorption; //!< macroscopic absorption xs - double fission; //!< macroscopic fission xs - double nu_fission; //!< macroscopic production xs - double photon_prod; //!< macroscopic photon production xs - - // Photon cross sections - double coherent; //!< macroscopic coherent xs - double incoherent; //!< macroscopic incoherent xs - double photoelectric; //!< macroscopic photoelectric xs - double pair_production; //!< macroscopic pair production xs -}; - -//============================================================================ -//! State of a particle being transported through geometry -//============================================================================ - -class Particle { -public: - //========================================================================== - // Aliases and type definitions - - //! Particle types - enum class Type { - neutron, photon, electron, positron - }; - - //! Saved ("banked") state of a particle - struct Bank { - Position r; - Direction u; - double E; - double wgt; - int delayed_group; - Type particle; - }; - - //========================================================================== - // Constructors - - Particle(); - - //========================================================================== - // Methods and accessors - - // Accessors for position in global coordinates - Position& r() { return coord_[0].r; } - const Position& r() const { return coord_[0].r; } - - // Accessors for position in local coordinates - Position& r_local() { return coord_[n_coord_ - 1].r; } - const Position& r_local() const { return coord_[n_coord_ - 1].r; } - - // Accessors for direction in global coordinates - Direction& u() { return coord_[0].u; } - const Direction& u() const { return coord_[0].u; } - - // Accessors for direction in local coordinates - Direction& u_local() { return coord_[n_coord_ - 1].u; } - const Direction& u_local() const { return coord_[n_coord_ - 1].u; } - - //! resets all coordinate levels for the particle - void clear(); - - //! create a secondary particle - // - //! stores the current phase space attributes of the particle in the - //! secondary bank and increments the number of sites in the secondary bank. - //! \param u Direction of the secondary particle - //! \param E Energy of the secondary particle in [eV] - //! \param type Particle type - void create_secondary(Direction u, double E, Type type); - - //! initialize from a source site - // - //! initializes a particle from data stored in a source site. The source - //! site may have been produced from an external source, from fission, or - //! simply as a secondary particle. - //! \param src Source site data - void from_source(const Bank* src); - - //! Transport a particle from birth to death - void transport(); - - //! Cross a surface and handle boundary conditions - void cross_surface(); - - //! mark a particle as lost and create a particle restart file - //! \param message A warning message to display - void mark_as_lost(const char* message); - - void mark_as_lost(const std::string& message) - {mark_as_lost(message.c_str());} - - void mark_as_lost(const std::stringstream& message) - {mark_as_lost(message.str());} - - //! create a particle restart HDF5 file - void write_restart() const; - - //========================================================================== - // Data members - - // Cross section caches - std::vector neutron_xs_; //!< Microscopic neutron cross sections - std::vector photon_xs_; //!< Microscopic photon cross sections - MacroXS macro_xs_; //!< Macroscopic cross sections - - int64_t id_; //!< Unique ID - Type type_ {Type::neutron}; //!< Particle type (n, p, e, etc.) - - int n_coord_ {1}; //!< number of current coordinate levels - int cell_instance_; //!< offset for distributed properties - std::vector coord_; //!< coordinates for all levels - - // Particle coordinates before crossing a surface - int n_coord_last_ {1}; //!< number of current coordinates - std::vector cell_last_; //!< coordinates for all levels - - // Energy data - double E_; //!< post-collision energy in eV - double E_last_; //!< pre-collision energy in eV - int g_ {0}; //!< post-collision energy group (MG only) - int g_last_; //!< pre-collision energy group (MG only) - - // Other physical data - double wgt_ {1.0}; //!< particle weight - double mu_; //!< angle of scatter - bool alive_ {true}; //!< is particle alive? - - // Other physical data - Position r_last_current_; //!< coordinates of the last collision or - //!< reflective/periodic surface crossing for - //!< current tallies - Position r_last_; //!< previous coordinates - Direction u_last_; //!< previous direction coordinates - double wgt_last_ {1.0}; //!< pre-collision particle weight - double wgt_absorb_ {0.0}; //!< weight absorbed for survival biasing - - // What event took place - bool fission_ {false}; //!< did particle cause implicit fission - int event_; //!< scatter, absorption - int event_nuclide_; //!< index in nuclides array - int event_mt_; //!< reaction MT - int delayed_group_ {0}; //!< delayed group - - // Post-collision physical data - int n_bank_ {0}; //!< number of fission sites banked - int n_bank_second_ {0}; //!< number of secondary particles banked - double wgt_bank_ {0.0}; //!< weight of fission sites banked - int n_delayed_bank_[MAX_DELAYED_GROUPS]; //!< number of delayed fission - //!< sites banked - - // Indices for various arrays - int surface_ {0}; //!< index for surface particle is on - int cell_born_ {-1}; //!< index for cell particle was born in - int material_ {-1}; //!< index for current material - int material_last_ {-1}; //!< index for last material - - // Temperature of current cell - double sqrtkT_ {-1.0}; //!< sqrt(k_Boltzmann * temperature) in eV - double sqrtkT_last_ {0.0}; //!< last temperature - - // Statistical data - int n_collision_ {0}; //!< number of collisions - - // Track output - bool write_track_ {false}; -}; - -} // namespace openmc - -#endif // OPENMC_PARTICLE_H diff --git a/include/openmc/particle_restart.h b/include/openmc/particle_restart.h deleted file mode 100644 index 24ea237a4..000000000 --- a/include/openmc/particle_restart.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef OPENMC_PARTICLE_RESTART_H -#define OPENMC_PARTICLE_RESTART_H - -namespace openmc { - -void run_particle_restart(); - -} // namespace openmc - -#endif // OPENMC_PARTICLE_RESTART_H diff --git a/include/openmc/photon.h b/include/openmc/photon.h deleted file mode 100644 index 0fbdbc0c9..000000000 --- a/include/openmc/photon.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef OPENMC_PHOTON_H -#define OPENMC_PHOTON_H - -#include "openmc/endf.h" -#include "openmc/particle.h" - -#include -#include "xtensor/xtensor.hpp" - -#include -#include -#include // for pair -#include - -namespace openmc { - -//============================================================================== -//! Photon interaction data for a single element -//============================================================================== - -class ElectronSubshell { -public: - // Constructors - ElectronSubshell() { }; - - int index_subshell; //!< index in SUBSHELLS - int threshold; - double n_electrons; - double binding_energy; - xt::xtensor cross_section; - - // Transition data - int n_transitions; - xt::xtensor transition_subshells; - xt::xtensor transition_energy; - xt::xtensor transition_probability; -}; - -class PhotonInteraction { -public: - // Constructors - PhotonInteraction(hid_t group, int i_element); - - // Methods - void calculate_xs(Particle& p) const; - - void compton_scatter(double alpha, bool doppler, double* alpha_out, - double* mu, int* i_shell) const; - - double rayleigh_scatter(double alpha) const; - - void pair_production(double alpha, double* E_electron, double* E_positron, - double* mu_electron, double* mu_positron) const; - - void atomic_relaxation(const ElectronSubshell& shell, Particle& p) const; - - // Data members - std::string name_; //!< Name of element, e.g. "Zr" - int Z_; //!< Atomic number - int i_element_; //!< Index in global elements vector - - // Microscopic cross sections - xt::xtensor energy_; - xt::xtensor coherent_; - xt::xtensor incoherent_; - xt::xtensor photoelectric_total_; - xt::xtensor pair_production_total_; - xt::xtensor pair_production_electron_; - xt::xtensor pair_production_nuclear_; - xt::xtensor heating_; - - // Form factors - Tabulated1D incoherent_form_factor_; - Tabulated1D coherent_int_form_factor_; - Tabulated1D coherent_anomalous_real_; - Tabulated1D coherent_anomalous_imag_; - - // Photoionization and atomic relaxation data - std::unordered_map shell_map_; //!< Given a shell designator, e.g. 3, this - //!< dictionary gives an index in shells_ - std::vector shells_; - - // Compton profile data - xt::xtensor profile_pdf_; - xt::xtensor profile_cdf_; - xt::xtensor binding_energy_; - xt::xtensor electron_pdf_; - - // Stopping power data - double I_; // mean excitation energy - xt::xtensor n_electrons_; - xt::xtensor ionization_energy_; - xt::xtensor stopping_power_radiative_; - - // Bremsstrahlung scaled DCS - xt::xtensor dcs_; - -private: - void compton_doppler(double alpha, double mu, double* E_out, int* i_shell) const; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -std::pair klein_nishina(double alpha); - -void free_memory_photon(); - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -extern xt::xtensor compton_profile_pz; //! Compton profile momentum grid - -//! Photon interaction data for each element -extern std::vector elements; -extern std::unordered_map element_map; - -} // namespace data - -} // namespace openmc - -#endif // OPENMC_PHOTON_H diff --git a/include/openmc/physics.h b/include/openmc/physics.h deleted file mode 100644 index 107380eb8..000000000 --- a/include/openmc/physics.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef OPENMC_PHYSICS_H -#define OPENMC_PHYSICS_H - -#include "openmc/bank.h" -#include "openmc/nuclide.h" -#include "openmc/particle.h" -#include "openmc/position.h" -#include "openmc/reaction.h" - -#include - -namespace openmc { - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Sample a nuclide and reaction and then calls the appropriate routine -void collision(Particle* p); - -//! Samples an incident neutron reaction -void sample_neutron_reaction(Particle* p); - -//! Samples an element based on the macroscopic cross sections for each nuclide -//! within a material and then samples a reaction for that element and calls the -//! appropriate routine to process the physics. -void sample_photon_reaction(Particle* p); - -//! Terminates the particle and either deposits all energy locally -//! (electron_treatment = ELECTRON_LED) or creates secondary bremsstrahlung -//! photons from electron deflections with charged particles (electron_treatment -//! = ELECTRON_TTB). -void sample_electron_reaction(Particle* p); - -//! Terminates the particle and either deposits all energy locally -//! (electron_treatment = ELECTRON_LED) or creates secondary bremsstrahlung -//! photons from electron deflections with charged particles (electron_treatment -//! = ELECTRON_TTB). Two annihilation photons of energy MASS_ELECTRON_EV (0.511 -//! MeV) are created and travel in opposite directions. -void sample_positron_reaction(Particle* p); - -//! Sample a nuclide based on their total cross sections and densities within -//! the current material -//! -//! \param[in] p Particle -//! \return Index in the data::nuclides vector -int sample_nuclide(const Particle* p); - -//! Determine the average total, prompt, and delayed neutrons produced from -//! fission and creates appropriate bank sites. -void create_fission_sites(Particle* p, int i_nuclide, const Reaction* rx, - std::vector& bank); - -int sample_element(Particle* p); - -Reaction* sample_fission(int i_nuclide, const Particle* p); - -void sample_photon_product(int i_nuclide, const Particle* p, int* i_rx, int* i_product); - -void absorption(Particle* p, int i_nuclide); - -void scatter(Particle*, int i_nuclide); - -//! Treats the elastic scattering of a neutron with a target. -void elastic_scatter(int i_nuclide, const Reaction& rx, double kT, - Particle* p); - -void sab_scatter(int i_nuclide, int i_sab, Particle* p); - -//! samples the target velocity. The constant cross section free gas model is -//! the default method. Methods for correctly accounting for the energy -//! dependence of cross sections in treating resonance elastic scattering such -//! as the DBRC and a new, accelerated scheme are also implemented here. -Direction sample_target_velocity(const Nuclide* nuc, double E, Direction u, - Direction v_neut, double xs_eff, double kT); - -//! samples a target velocity based on the free gas scattering formulation, used -//! by most Monte Carlo codes, in which cross section is assumed to be constant -//! in energy. Excellent documentation for this method can be found in -//! FRA-TM-123. -Direction sample_cxs_target_velocity(double awr, double E, Direction u, double kT); - -void sample_fission_neutron(int i_nuclide, const Reaction* rx, double E_in, Particle::Bank* site); - -//! handles all reactions with a single secondary neutron (other than fission), -//! i.e. level scattering, (n,np), (n,na), etc. -void inelastic_scatter(const Nuclide* nuc, const Reaction* rx, Particle* p); - -void sample_secondary_photons(Particle* p, int i_nuclide); - -} // namespace openmc - -#endif // OPENMC_PHYSICS_H diff --git a/include/openmc/physics_common.h b/include/openmc/physics_common.h deleted file mode 100644 index 33fb8ed61..000000000 --- a/include/openmc/physics_common.h +++ /dev/null @@ -1,16 +0,0 @@ -//! \file physics_common.h -//! A collection of physics methods common to MG, CE, photon, etc. - -#ifndef OPENMC_PHYSICS_COMMON_H -#define OPENMC_PHYSICS_COMMON_H - -#include "openmc/particle.h" - -namespace openmc { - -//! \brief Performs the russian roulette operation for a particle -extern "C" void -russian_roulette(Particle* p); - -} // namespace openmc -#endif // OPENMC_PHYSICS_COMMON_H diff --git a/include/openmc/physics_mg.h b/include/openmc/physics_mg.h deleted file mode 100644 index f246cb6ec..000000000 --- a/include/openmc/physics_mg.h +++ /dev/null @@ -1,46 +0,0 @@ -//! \file physics_mg.h -//! Methods needed to perform the collision physics for multi-group mode - -#ifndef OPENMC_PHYSICS_MG_H -#define OPENMC_PHYSICS_MG_H - -#include "openmc/capi.h" -#include "openmc/particle.h" -#include "openmc/nuclide.h" - -#include - -namespace openmc { - -//! \brief samples particle behavior after a collision event. -//! \param p Particle to operate on -void -collision_mg(Particle* p); - -//! \brief samples a reaction type. -//! -//! Note that there is special logic when suvival biasing is turned on since -//! fission and disappearance are treated implicitly. -//! \param p Particle to operate on -void -sample_reaction(Particle* p); - -//! \brief Samples the scattering event -//! \param p Particle to operate on -void -scatter(Particle* p); - -//! \brief Determines the average total, prompt and delayed neutrons produced -//! from fission and creates the appropriate bank sites. -//! \param p Particle to operate on -//! \param bank The particle bank to populate -void -create_fission_sites(Particle* p, std::vector& bank); - -//! \brief Handles an absorption event -//! \param p Particle to operate on -void -absorption(Particle* p); - -} // namespace openmc -#endif // OPENMC_PHYSICS_MG_H diff --git a/include/openmc/plot.h b/include/openmc/plot.h deleted file mode 100644 index da83f42aa..000000000 --- a/include/openmc/plot.h +++ /dev/null @@ -1,292 +0,0 @@ -#ifndef OPENMC_PLOT_H -#define OPENMC_PLOT_H - -#include -#include - -#include "pugixml.hpp" -#include "xtensor/xarray.hpp" - -#include "hdf5.h" -#include "openmc/position.h" -#include "openmc/constants.h" -#include "openmc/cell.h" -#include "openmc/geometry.h" -#include "openmc/particle.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//=============================================================================== -// Global variables -//=============================================================================== - -class Plot; - -namespace model { - -extern std::vector plots; //!< Plot instance container -extern std::unordered_map plot_map; //!< map of plot ids to index - -} // namespace model - -//=============================================================================== -// RGBColor holds color information for plotted objects -//=============================================================================== - -struct RGBColor { - //Constructors - RGBColor() : red(0), green(0), blue(0) { }; - RGBColor(const int v[3]) : red(v[0]), green(v[1]), blue(v[2]) { }; - RGBColor(int r, int g, int b) : red(r), green(g), blue(b) { }; - - RGBColor(const std::vector &v) { - if (v.size() != 3) { - throw std::out_of_range("Incorrect vector size for RGBColor."); - } - red = v[0]; - green = v[1]; - blue = v[2]; - } - - bool operator ==(const RGBColor& other) { - return red == other.red && green == other.green && blue == other.blue; - } - - // Members - uint8_t red, green, blue; -}; - -// some default colors -const RGBColor WHITE {255, 255, 255}; -const RGBColor RED {255, 0, 0}; - - -typedef xt::xtensor ImageData; - -struct IdData { - // Constructor - IdData(size_t h_res, size_t v_res); - - // Methods - void set_value(size_t y, size_t x, const Particle& p, int level); - void set_overlap(size_t y, size_t x); - - // Members - xt::xtensor data_; //!< 2D array of cell & material ids -}; - -struct PropertyData { - // Constructor - PropertyData(size_t h_res, size_t v_res); - - // Methods - void set_value(size_t y, size_t x, const Particle& p, int level); - void set_overlap(size_t y, size_t x); - - // Members - xt::xtensor data_; //!< 2D array of temperature & density data -}; - -enum class PlotType { - slice = 1, - voxel = 2 -}; - -enum class PlotBasis { - xy = 1, - xz = 2, - yz = 3 -}; - -enum class PlotColorBy { - cells = 0, - mats = 1 -}; - -//=============================================================================== -// Plot class -//=============================================================================== -class PlotBase { -public: - template T get_map() const; - - // Members -public: - Position origin_; //!< Plot origin in geometry - Position width_; //!< Plot width in geometry - PlotBasis basis_; //!< Plot basis (XY/XZ/YZ) - std::array pixels_; //!< Plot size in pixels - bool color_overlaps_; //!< Show overlapping cells? - int level_; //!< Plot universe level -}; - -template -T PlotBase::get_map() const { - - size_t width = pixels_[0]; - size_t height = pixels_[1]; - - // get pixel size - double in_pixel = (width_[0])/static_cast(width); - double out_pixel = (width_[1])/static_cast(height); - - // size data array - T data(width, height); - - // setup basis indices and initial position centered on pixel - int in_i, out_i; - Position xyz = origin_; - switch(basis_) { - case PlotBasis::xy : - in_i = 0; - out_i = 1; - break; - case PlotBasis::xz : - in_i = 0; - out_i = 2; - break; - case PlotBasis::yz : - in_i = 1; - out_i = 2; - break; -#ifdef __GNUC__ - default: - __builtin_unreachable(); -#endif - } - - // set initial position - xyz[in_i] = origin_[in_i] - width_[0] / 2. + in_pixel / 2.; - xyz[out_i] = origin_[out_i] + width_[1] / 2. - out_pixel / 2.; - - // arbitrary direction - Direction dir = {0.7071, 0.7071, 0.0}; - - #pragma omp parallel - { - Particle p; - p.r() = xyz; - p.u() = dir; - p.coord_[0].universe = model::root_universe; - int level = level_; - int j{}; - - #pragma omp for - for (int y = 0; y < height; y++) { - p.r()[out_i] = xyz[out_i] - out_pixel * y; - for (int x = 0; x < width; x++) { - p.r()[in_i] = xyz[in_i] + in_pixel * x; - p.n_coord_ = 1; - // local variables - bool found_cell = find_cell(&p, 0); - j = p.n_coord_ - 1; - if (level >=0) {j = level + 1;} - if (found_cell) { - data.set_value(y, x, p, j); - } - if (color_overlaps_ && check_cell_overlap(&p, false)) { - data.set_overlap(y, x); - } - } // inner for - } // outer for - } // omp parallel - - return data; -} - -class Plot : public PlotBase { - -public: - // Constructor - Plot(pugi::xml_node plot); - - // Methods -private: - void set_id(pugi::xml_node plot_node); - void set_type(pugi::xml_node plot_node); - void set_output_path(pugi::xml_node plot_node); - void set_bg_color(pugi::xml_node plot_node); - void set_basis(pugi::xml_node plot_node); - void set_origin(pugi::xml_node plot_node); - void set_width(pugi::xml_node plot_node); - void set_universe(pugi::xml_node plot_node); - void set_default_colors(pugi::xml_node plot_node); - void set_user_colors(pugi::xml_node plot_node); - void set_meshlines(pugi::xml_node plot_node); - void set_mask(pugi::xml_node plot_node); - void set_overlap_color(pugi::xml_node plot_node); - -// Members -public: - int id_; //!< Plot ID - PlotType type_; //!< Plot type (Slice/Voxel) - PlotColorBy color_by_; //!< Plot coloring (cell/material) - int meshlines_width_; //!< Width of lines added to the plot - int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot - RGBColor meshlines_color_; //!< Color of meshlines on the plot - RGBColor not_found_ {WHITE}; //!< Plot background color - RGBColor overlap_color_ {RED}; //!< Plot overlap color - std::vector colors_; //!< Plot colors - std::string path_plot_; //!< Plot output filename -}; - -//=============================================================================== -// Non-member functions -//=============================================================================== - -//! Add mesh lines to image data of a plot object -//! \param[in] plot object -//! \param[out] image data associated with the plot object -void draw_mesh_lines(Plot pl, ImageData& data); - -//! Write a ppm image to file using a plot object's image data -//! \param[in] plot object -//! \param[out] image data associated with the plot object -void output_ppm(Plot pl, const ImageData& data); - -//! Initialize a voxel file -//! \param[in] id of an open hdf5 file -//! \param[in] dimensions of the voxel file (dx, dy, dz) -//! \param[out] dataspace pointer to voxel data -//! \param[out] dataset pointer to voxesl data -//! \param[out] pointer to memory space of voxel data -void voxel_init(hid_t file_id, const hsize_t* dims, hid_t* dspace, - hid_t* dset, hid_t* memspace); - -//! Write a section of the voxel data to hdf5 -//! \param[in] voxel slice -//! \param[out] dataspace pointer to voxel data -//! \param[out] dataset pointer to voxesl data -//! \param[out] pointer to data to write -void voxel_write_slice(int x, hid_t dspace, hid_t dset, - hid_t memspace, void* buf); - -//! Close voxel file entities -//! \param[in] data space to close -//! \param[in] dataset to close -//! \param[in] memory space to close -void voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace); - -//=============================================================================== -// External functions -//=============================================================================== - -//! Read plot specifications from a plots.xml file -void read_plots_xml(); - -//! Create a ppm image for a plot object -//! \param[in] plot object -void create_ppm(Plot pl); - -//! Create an hdf5 voxel file for a plot object -//! \param[in] plot object -void create_voxel(Plot pl); - -//! Create a randomly generated RGB color -//! \return RGBColor with random value -RGBColor random_color(); - - -} // namespace openmc -#endif // OPENMC_PLOT_H diff --git a/include/openmc/position.h b/include/openmc/position.h deleted file mode 100644 index 2be72b27c..000000000 --- a/include/openmc/position.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef OPENMC_POSITION_H -#define OPENMC_POSITION_H - -#include -#include // for sqrt -#include -#include // for out_of_range -#include - -namespace openmc { - -//============================================================================== -//! Type representing a position in Cartesian coordinates -//============================================================================== - -struct Position { - // Constructors - Position() = default; - Position(double x_, double y_, double z_) : x{x_}, y{y_}, z{z_} { }; - Position(const double xyz[]) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { }; - Position(const std::vector& xyz) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { }; - Position(const std::array& xyz) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { }; - - // Unary operators - Position& operator+=(Position); - Position& operator+=(double); - Position& operator-=(Position); - Position& operator-=(double); - Position& operator*=(Position); - Position& operator*=(double); - Position& operator/=(Position); - Position& operator/=(double); - Position operator-() const; - - const double& operator[](int i) const { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - default: - throw std::out_of_range{"Index in Position must be between 0 and 2."}; - } - } - double& operator[](int i) { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - default: - throw std::out_of_range{"Index in Position must be between 0 and 2."}; - } - } - - // Other member functions - - //! Dot product of two vectors - //! \param[in] other Vector to take dot product with - //! \result Resulting dot product - inline double dot(Position other) const { - return x*other.x + y*other.y + z*other.z; - } - inline double norm() const { - return std::sqrt(x*x + y*y + z*z); - } - - //! Rotate the position based on a rotation matrix - Position rotate(const std::vector& rotation) const; - - // Data members - double x = 0.; - double y = 0.; - double z = 0.; -}; - -// Binary operators -inline Position operator+(Position a, Position b) { return a += b; } -inline Position operator+(Position a, double b) { return a += b; } -inline Position operator+(double a, Position b) { return b += a; } - -inline Position operator-(Position a, Position b) { return a -= b; } -inline Position operator-(Position a, double b) { return a -= b; } -inline Position operator-(double a, Position b) { return b -= a; } - -inline Position operator*(Position a, Position b) { return a *= b; } -inline Position operator*(Position a, double b) { return a *= b; } -inline Position operator*(double a, Position b) { return b *= a; } - -inline Position operator/(Position a, Position b) { return a /= b; } -inline Position operator/(Position a, double b) { return a /= b; } -inline Position operator/(double a, Position b) { return b /= a; } - -inline bool operator==(Position a, Position b) -{return a.x == b.x && a.y == b.y && a.z == b.z;} - -inline bool operator!=(Position a, Position b) -{return a.x != b.x || a.y != b.y || a.z != b.z;} - -std::ostream& operator<<(std::ostream& os, Position a); - -//============================================================================== -//! Type representing a vector direction in Cartesian coordinates -//============================================================================== - -using Direction = Position; - -} // namespace openmc - -#endif // OPENMC_POSITION_H diff --git a/include/openmc/progress_bar.h b/include/openmc/progress_bar.h deleted file mode 100644 index 18a3eea47..000000000 --- a/include/openmc/progress_bar.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef OPENMC_PROGRESSBAR_H -#define OPENMC_PROGRESSBAR_H - -#include - -class ProgressBar { - -public: - // Constructor - ProgressBar(); - - void set_value(double val); - -private: - std::string bar; - char bar_old[72] = "???% | |"; - -}; - - -#endif // OPENMC_PROGRESSBAR_H - diff --git a/include/openmc/random_lcg.h b/include/openmc/random_lcg.h deleted file mode 100644 index 8fce80392..000000000 --- a/include/openmc/random_lcg.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef OPENMC_RANDOM_LCG_H -#define OPENMC_RANDOM_LCG_H - -#include - - -namespace openmc { - -//============================================================================== -// Module constants. -//============================================================================== - -extern "C" const int N_STREAMS; -extern "C" const int STREAM_TRACKING; -extern "C" const int STREAM_TALLIES; -extern "C" const int STREAM_SOURCE; -extern "C" const int STREAM_URR_PTABLE; -extern "C" const int STREAM_VOLUME; -extern "C" const int STREAM_PHOTON; -constexpr int64_t DEFAULT_SEED = 1; - -//============================================================================== -//! Generate a pseudo-random number using a linear congruential generator. -//! @return A random number between 0 and 1 -//============================================================================== - -extern "C" double prn(); - -//============================================================================== -//! Generate a random number which is 'n' times ahead from the current seed. -//! -//! The result of this function will be the same as the result from calling -//! `prn()` 'n' times. -//! @param n The number of RNG seeds to skip ahead by -//! @return A random number between 0 and 1 -//============================================================================== - -extern "C" double future_prn(int64_t n); - -//============================================================================== -//! Set the RNG seed to a unique value based on the ID of the particle. -//! @param id The particle ID -//============================================================================== - -extern "C" void set_particle_seed(int64_t id); - -//============================================================================== -//! Advance the random number seed 'n' times from the current seed. -//! @param n The number of RNG seeds to skip ahead by -//============================================================================== - -extern "C" void advance_prn_seed(int64_t n); - -//============================================================================== -//! Advance a random number seed 'n' times. -//! -//! This is usually used to skip a fixed number of random numbers (the stride) -//! so that a given particle always has the same starting seed regardless of -//! how many processors are used. -//! @param n The number of RNG seeds to skip ahead by -//! @param seed The starting to seed to advance from -//============================================================================== - -uint64_t future_seed(uint64_t n, uint64_t seed); - -//============================================================================== -//! Switch the RNG to a different stream of random numbers. -//! -//! If random numbers are needed in routines not used directly for tracking -//! (e.g. physics), this allows the numbers to be generated without affecting -//! reproducibility of the physics. -//! @param n The RNG stream to switch to. Use the constants such as -//! `STREAM_TRACKING` and `STREAM_TALLIES` for this argument. -//============================================================================== - -extern "C" void prn_set_stream(int n); - -//============================================================================== -// API FUNCTIONS -//============================================================================== - -//============================================================================== -//! Get OpenMC's master seed. -//============================================================================== - -extern "C" int64_t openmc_get_seed(); - -//============================================================================== -//! Set OpenMC's master seed. -//! @param new_seed The master seed. All other seeds will be derived from this -//! one. -//============================================================================== - -extern "C" void openmc_set_seed(int64_t new_seed); - -} // namespace openmc -#endif // OPENMC_RANDOM_LCG_H diff --git a/include/openmc/reaction.h b/include/openmc/reaction.h deleted file mode 100644 index dd6de245f..000000000 --- a/include/openmc/reaction.h +++ /dev/null @@ -1,51 +0,0 @@ -//! \file reaction.h -//! Data for an incident neutron reaction - -#ifndef OPENMC_REACTION_H -#define OPENMC_REACTION_H - -#include -#include - -#include "hdf5.h" - -#include "openmc/reaction_product.h" - -namespace openmc { - -//============================================================================== -//! Data for a single reaction including cross sections (possibly at multiple -//! temperatures) and reaction products (with secondary angle-energy -//! distributions) -//============================================================================== - -class Reaction { -public: - //! Construct reaction from HDF5 data - //! \param[in] group HDF5 group containing reaction data - //! \param[in] temperatures Desired temperatures for cross sections - explicit Reaction(hid_t group, const std::vector& temperatures); - - //! Cross section at a single temperature - struct TemperatureXS { - int threshold; - std::vector value; - }; - - int mt_; //!< ENDF MT value - double q_value_; //!< Reaction Q value in [eV] - bool scatter_in_cm_; //!< scattering system in center-of-mass? - bool redundant_; //!< redundant reaction? - std::vector xs_; //!< Cross section at each temperature - std::vector products_; //!< Reaction products -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -std::string reaction_name(int mt); - -} // namespace openmc - -#endif // OPENMC_REACTION_H diff --git a/include/openmc/reaction_product.h b/include/openmc/reaction_product.h deleted file mode 100644 index 9377b5b6a..000000000 --- a/include/openmc/reaction_product.h +++ /dev/null @@ -1,57 +0,0 @@ -//! \file reaction_product.h -//! Data for a reaction product - -#ifndef OPENMC_REACTION_PRODUCT_H -#define OPENMC_REACTION_PRODUCT_H - -#include // for unique_ptr -#include // for vector - -#include "hdf5.h" - -#include "openmc/angle_energy.h" -#include "openmc/endf.h" -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -//! Data for a reaction product including its yield and angle-energy -//! distributions, each of which has a given probability of occurring for a -//! given incoming energy. In general, most products only have one angle-energy -//! distribution, but for some cases (e.g., (n,2n) in certain nuclides) multiple -//! distinct distributions exist. -//============================================================================== - -class ReactionProduct { -public: - //! Emission mode for product - enum class EmissionMode { - prompt, // Prompt emission of secondary particle - delayed, // Yield represents total emission (prompt + delayed) - total // Delayed emission of secondary particle - }; - - using Secondary = std::unique_ptr; - - //! Construct reaction product from HDF5 data - //! \param[in] group HDF5 group containing data - explicit ReactionProduct(hid_t group); - - //! Sample an outgoing angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const; - - Particle::Type particle_; //!< Particle type - EmissionMode emission_mode_; //!< Emission mode - double decay_rate_; //!< Decay rate (for delayed neutron precursors) in [1/s] - std::unique_ptr yield_; //!< Yield as a function of energy - std::vector applicability_; //!< Applicability of distribution - std::vector distribution_; //!< Secondary angle-energy distribution -}; - -} // namespace opemc - -#endif // OPENMC_REACTION_PRODUCT_H diff --git a/include/openmc/scattdata.h b/include/openmc/scattdata.h deleted file mode 100644 index 1a3a252a5..000000000 --- a/include/openmc/scattdata.h +++ /dev/null @@ -1,265 +0,0 @@ -//! \file scattdata.h -//! A collection of multi-group scattering data classes - -#ifndef OPENMC_SCATTDATA_H -#define OPENMC_SCATTDATA_H - -#include - -#include "xtensor/xtensor.hpp" - -#include "openmc/constants.h" - -namespace openmc { - -// forward declarations so we can name our friend functions -class ScattDataLegendre; -class ScattDataTabular; - -//============================================================================== -// SCATTDATA contains all the data needed to describe the scattering energy and -// angular distribution data -//============================================================================== - -class ScattData { - public: - virtual ~ScattData() = default; - protected: - //! \brief Initializes the attributes of the base class. - void - base_init(int order, const xt::xtensor& in_gmin, - const xt::xtensor& in_gmax, const double_2dvec& in_energy, - const double_2dvec& in_mult); - - //! \brief Combines microscopic ScattDatas into a macroscopic one. - void - base_combine(size_t max_order, const std::vector& those_scatts, - const std::vector& scalars, xt::xtensor& in_gmin, - xt::xtensor& in_gmax, double_2dvec& sparse_mult, - double_3dvec& sparse_scatter); - - public: - - double_2dvec energy; // Normalized p0 matrix for sampling Eout - double_2dvec mult; // nu-scatter multiplication (nu-scatt/scatt) - double_3dvec dist; // Angular distribution - xt::xtensor gmin; // minimum outgoing group - xt::xtensor gmax; // maximum outgoing group - xt::xtensor scattxs; // Isotropic Sigma_{s,g_{in}} - - //! \brief Calculates the value of normalized f(mu). - //! - //! The value of f(mu) is normalized as in the integral of f(mu)dmu across - //! [-1,1] is 1. - //! - //! @param gin Incoming energy group of interest. - //! @param gout Outgoing energy group of interest. - //! @param mu Cosine of the change-in-angle of interest. - //! @return The value of f(mu). - virtual double - calc_f(int gin, int gout, double mu) = 0; - - //! \brief Samples the outgoing energy and angle from the ScattData info. - //! - //! @param gin Incoming energy group. - //! @param gout Sampled outgoing energy group. - //! @param mu Sampled cosine of the change-in-angle. - //! @param wgt Weight of the particle to be adjusted. - virtual void - sample(int gin, int& gout, double& mu, double& wgt) = 0; - - //! \brief Initializes the ScattData object from a given scatter and - //! multiplicity matrix. - //! - //! @param in_gmin List of minimum outgoing groups for every incoming group - //! @param in_gmax List of maximum outgoing groups for every incoming group - //! @param in_mult Input sparse multiplicity matrix - //! @param coeffs Input sparse scattering matrix - virtual void - init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, - const double_2dvec& in_mult, const double_3dvec& coeffs) = 0; - - //! \brief Combines the microscopic data. - //! - //! @param those_scatts Microscopic objects to combine. - //! @param scalars Scalars to multiply the microscopic data by. - virtual void - combine(const std::vector& those_scatts, - const std::vector& scalars) = 0; - - //! \brief Getter for the dimensionality of the scattering order. - //! - //! If Legendre this is the "n" in "Pn"; for Tabular, this is the number - //! of points, and for Histogram this is the number of bins. - //! - //! @return The order. - virtual size_t - get_order() = 0; - - //! \brief Builds a dense scattering matrix from the constituent parts - //! - //! @param max_order If Legendre this is the maximum value of "n" in "Pn" - //! requested; ignored otherwise. - //! @return The dense scattering matrix. - virtual xt::xtensor - get_matrix(size_t max_order) = 0; - - //! \brief Samples the outgoing energy from the ScattData info. - //! - //! @param gin Incoming energy group. - //! @param gout Sampled outgoing energy group. - //! @param i_gout Sampled outgoing energy group index. - void - sample_energy(int gin, int& gout, int& i_gout); - - //! \brief Provides a cross section value given certain parameters - //! - //! @param xstype Type of cross section requested, according to the - //! enumerated constants. - //! @param gin Incoming energy group. - //! @param gout Outgoing energy group; use nullptr if irrelevant, or if a - //! sum is requested. - //! @param mu Cosine of the change-in-angle, for scattering quantities; - //! use nullptr if irrelevant. - //! @return Requested cross section value. - double - get_xs(int xstype, int gin, const int* gout, const double* mu); -}; - -//============================================================================== -// ScattDataLegendre represents the angular distributions as Legendre kernels -//============================================================================== - -class ScattDataLegendre: public ScattData { - - protected: - - // Maximal value for rejection sampling from a rectangle - double_2dvec max_val; - - // Friend convert_legendre_to_tabular so it has access to protected - // parameters - friend void - convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab); - - public: - - void - init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, - const double_2dvec& in_mult, const double_3dvec& coeffs); - - void - combine(const std::vector& those_scatts, - const std::vector& scalars); - - //! \brief Find the maximal value of the angular distribution to use as a - // bounding box with rejection sampling. - void - update_max_val(); - - double - calc_f(int gin, int gout, double mu); - - void - sample(int gin, int& gout, double& mu, double& wgt); - - size_t - get_order() {return dist[0][0].size() - 1;}; - - xt::xtensor - get_matrix(size_t max_order); -}; - -//============================================================================== -// ScattDataHistogram represents the angular distributions as a histogram, as it -// would be if it came from a "mu" tally in OpenMC -//============================================================================== - -class ScattDataHistogram: public ScattData { - - protected: - - xt::xtensor mu; // Angle distribution mu bin boundaries - double dmu; // Quick storage of the mu spacing - double_3dvec fmu; // The angular distribution histogram - - public: - - void - init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, - const double_2dvec& in_mult, const double_3dvec& coeffs); - - void - combine(const std::vector& those_scatts, - const std::vector& scalars); - - double - calc_f(int gin, int gout, double mu); - - void - sample(int gin, int& gout, double& mu, double& wgt); - - size_t - get_order() {return dist[0][0].size();}; - - xt::xtensor - get_matrix(size_t max_order); -}; - -//============================================================================== -// ScattDataTabular represents the angular distributions as a table of mu and -// f(mu) -//============================================================================== - -class ScattDataTabular: public ScattData { - - protected: - - xt::xtensor mu; // Angle distribution mu grid points - double dmu; // Quick storage of the mu spacing - double_3dvec fmu; // The angular distribution function - - // Friend convert_legendre_to_tabular so it has access to protected - // parameters - friend void - convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab); - - public: - - void - init(const xt::xtensor& in_gmin, const xt::xtensor& in_gmax, - const double_2dvec& in_mult, const double_3dvec& coeffs); - - void - combine(const std::vector& those_scatts, - const std::vector& scalars); - - double - calc_f(int gin, int gout, double mu); - - void - sample(int gin, int& gout, double& mu, double& wgt); - - size_t - get_order() {return dist[0][0].size();}; - - xt::xtensor - get_matrix(size_t max_order); -}; - -//============================================================================== -// Function to convert Legendre functions to tabular -//============================================================================== - -//! \brief Converts a ScattDatalegendre to a ScattDataHistogram -//! -//! @param leg The initial ScattDataLegendre object. -//! @param leg The resultant ScattDataTabular object. -//! @param n_mu The number of mu points to use when building the -//! ScattDataTabular object. -void -convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab, - int n_mu); - -} // namespace openmc -#endif // OPENMC_SCATTDATA_H diff --git a/include/openmc/search.h b/include/openmc/search.h deleted file mode 100644 index 446e2916a..000000000 --- a/include/openmc/search.h +++ /dev/null @@ -1,32 +0,0 @@ -//! \file search.h -//! Search algorithms - -#ifndef OPENMC_SEARCH_H -#define OPENMC_SEARCH_H - -#include // for lower_bound, upper_bound - -namespace openmc { - -//! Perform binary search - -template -typename std::iterator_traits::difference_type -lower_bound_index(It first, It last, const T& value) -{ - if (*first == value) return 0; - It index = std::lower_bound(first, last, value) - 1; - return (index == last) ? -1 : index - first; -} - -template -typename std::iterator_traits::difference_type -upper_bound_index(It first, It last, const T& value) -{ - It index = std::upper_bound(first, last, value) - 1; - return (index == last) ? -1 : index - first; -} - -} // namespace openmc - -#endif // OPENMC_SEARCH_H diff --git a/include/openmc/secondary_correlated.h b/include/openmc/secondary_correlated.h deleted file mode 100644 index 603d8c414..000000000 --- a/include/openmc/secondary_correlated.h +++ /dev/null @@ -1,61 +0,0 @@ -//! \file secondary_correlated.h -//! Correlated angle-energy distribution - -#ifndef OPENMC_SECONDARY_CORRELATED_H -#define OPENMC_SECONDARY_CORRELATED_H - -#include - -#include "hdf5.h" -#include "xtensor/xtensor.hpp" - -#include "openmc/angle_energy.h" -#include "openmc/endf.h" -#include "openmc/distribution.h" - -namespace openmc { - -//============================================================================== -//! Correlated angle-energy distribution corresponding to ACE law 61 and ENDF -//! File 6, LAW=1, LANG!=2. -//============================================================================== - -class CorrelatedAngleEnergy : public AngleEnergy { -public: - //! Outgoing energy/angle at a single incoming energy - struct CorrTable { - int n_discrete; //!< Number of discrete lines - Interpolation interpolation; //!< Interpolation law - xt::xtensor e_out; //!< Outgoing energies [eV] - xt::xtensor p; //!< Probability density - xt::xtensor c; //!< Cumulative distribution - std::vector angle; //!< Angle distribution - }; - - explicit CorrelatedAngleEnergy(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; - - // energy property - std::vector& energy() { return energy_; } - const std::vector& energy() const { return energy_; } - - // distribution property - std::vector& distribution() { return distribution_; } - const std::vector& distribution() const { return distribution_; } -private: - int n_region_; //!< Number of interpolation regions - std::vector breakpoints_; //!< Breakpoints between regions - std::vector interpolation_; //!< Interpolation laws - std::vector energy_; //!< Energies [eV] at which distributions - //!< are tabulated - std::vector distribution_; //!< Distribution at each energy -}; - -} // namespace openmc - -#endif // OPENMC_SECONDARY_CORRELATED_H diff --git a/include/openmc/secondary_kalbach.h b/include/openmc/secondary_kalbach.h deleted file mode 100644 index 0217c7e77..000000000 --- a/include/openmc/secondary_kalbach.h +++ /dev/null @@ -1,55 +0,0 @@ -//! \file secondary_kalbach.h -//! Kalbach-Mann angle-energy distribution - -#ifndef OPENMC_SECONDARY_KALBACH_H -#define OPENMC_SECONDARY_KALBACH_H - -#include - -#include "hdf5.h" -#include "xtensor/xtensor.hpp" - -#include "openmc/angle_energy.h" -#include "openmc/constants.h" -#include "openmc/endf.h" - -namespace openmc { - -//============================================================================== -//! Correlated angle-energy distribution with the angular distribution -//! represented using Kalbach-Mann systematics. This corresponds to ACE law 44 -//! and ENDF File 6, LAW=1, LANG=2. -//============================================================================== - -class KalbachMann : public AngleEnergy { -public: - explicit KalbachMann(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - //! Outgoing energy/angle at a single incoming energy - struct KMTable { - int n_discrete; //!< Number of discrete lines - Interpolation interpolation; //!< Interpolation law - xt::xtensor e_out; //!< Outgoing energies [eV] - xt::xtensor p; //!< Probability density - xt::xtensor c; //!< Cumulative distribution - xt::xtensor r; //!< Pre-compound fraction - xt::xtensor a; //!< Parameterized function - }; - - int n_region_; //!< Number of interpolation regions - std::vector breakpoints_; //!< Breakpoints between regions - std::vector interpolation_; //!< Interpolation laws - std::vector energy_; //!< Energies [eV] at which distributions - //!< are tabulated - std::vector distribution_; //!< Distribution at each energy -}; - -} // namespace openmc - -#endif // OPENMC_SECONDARY_KALBACH_H diff --git a/include/openmc/secondary_nbody.h b/include/openmc/secondary_nbody.h deleted file mode 100644 index eb90bd8a0..000000000 --- a/include/openmc/secondary_nbody.h +++ /dev/null @@ -1,37 +0,0 @@ -//! \file secondary_nbody.h -//! N-body phase space distribution - -#ifndef OPENMC_SECONDARY_NBODY_H -#define OPENMC_SECONDARY_NBODY_H - -#include "hdf5.h" - -#include "openmc/angle_energy.h" - -namespace openmc { - -//============================================================================== -//! Angle-energy distribution for particles emitted from neutron and -//! charged-particle reactions. This corresponds to ACE law 66 and ENDF File 6, -//! LAW=6. -//============================================================================== - -class NBodyPhaseSpace : public AngleEnergy { -public: - explicit NBodyPhaseSpace(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - int n_bodies_; //!< Number of particles distributed - double mass_ratio_; //!< Total mass of particles [neutron mass] - double A_; //!< Atomic weight ratio - double Q_; //!< Reaction Q-value [eV] -}; - -} // namespace openmc - -#endif // OPENMC_SECONDARY_NBODY_H diff --git a/include/openmc/secondary_thermal.h b/include/openmc/secondary_thermal.h deleted file mode 100644 index 7b876334f..000000000 --- a/include/openmc/secondary_thermal.h +++ /dev/null @@ -1,139 +0,0 @@ -//! \file secondary_thermal.h -//! Angle-energy distributions for thermal scattering - -#ifndef OPENMC_SECONDARY_THERMAL_H -#define OPENMC_SECONDARY_THERMAL_H - -#include "openmc/angle_energy.h" -#include "openmc/endf.h" -#include "openmc/secondary_correlated.h" - -#include -#include "xtensor/xtensor.hpp" - -#include - -namespace openmc { - -//============================================================================== -//! Coherent elastic scattering angle-energy distribution -//============================================================================== - -class CoherentElasticAE : public AngleEnergy { -public: - //! Construct from a coherent elastic scattering cross section - // - //! \param[in] xs Coherent elastic scattering cross section - explicit CoherentElasticAE(const CoherentElasticXS& xs); - - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - const CoherentElasticXS& xs_; //!< Coherent elastic scattering cross section -}; - -//============================================================================== -//! Incoherent elastic scattering angle-energy distribution -//============================================================================== - -class IncoherentElasticAE : public AngleEnergy { -public: - //! Construct from HDF5 file - // - //! \param[in] group HDF5 group - explicit IncoherentElasticAE(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - double debye_waller_; -}; - -//============================================================================== -//! Incoherent elastic scattering angle-energy distribution (discrete) -//============================================================================== - -class IncoherentElasticAEDiscrete : public AngleEnergy { -public: - //! Construct from HDF5 file - // - //! \param[in] group HDF5 group - //! \param[in] energy Energies at which cosines are tabulated - explicit IncoherentElasticAEDiscrete(hid_t group, const std::vector& energy); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - const std::vector& energy_; //!< Energies at which cosines are tabulated - xt::xtensor mu_out_; //!< Cosines for each incident energy -}; - -//============================================================================== -//! Incoherent inelastic scattering angle-energy distribution (discrete) -//============================================================================== - -class IncoherentInelasticAEDiscrete : public AngleEnergy { -public: - //! Construct from HDF5 file - // - //! \param[in] group HDF5 group - //! \param[in] energy Incident energies at which distributions are tabulated - explicit IncoherentInelasticAEDiscrete(hid_t group, const std::vector& energy); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - const std::vector& energy_; //!< Incident energies - xt::xtensor energy_out_; //!< Outgoing energies for each incident energy - xt::xtensor mu_out_; //!< Outgoing cosines for each incident/outgoing energy - bool skewed_; //!< Whether outgoing energy distribution is skewed -}; - -//============================================================================== -//! Incoherent inelastic scattering angle-energy distribution -//============================================================================== - -class IncoherentInelasticAE : public AngleEnergy { -public: - //! Construct from HDF5 file - // - //! \param[in] group HDF5 group - explicit IncoherentInelasticAE(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; -private: - //! Secondary energy/angle distribution - struct DistEnergySab { - std::size_t n_e_out; //!< Number of outgoing energies - xt::xtensor e_out; //!< Outgoing energies - xt::xtensor e_out_pdf; //!< Probability density function - xt::xtensor e_out_cdf; //!< Cumulative distribution function - xt::xtensor mu; //!< Equiprobable angles at each outgoing energy - }; - - std::vector energy_; //!< Incident energies - std::vector distribution_; //!< Secondary angle-energy at - //!< each incident energy -}; - - -} // namespace openmc - -#endif // OPENMC_SECONDARY_THERMAL_H diff --git a/include/openmc/secondary_uncorrelated.h b/include/openmc/secondary_uncorrelated.h deleted file mode 100644 index e430c75c4..000000000 --- a/include/openmc/secondary_uncorrelated.h +++ /dev/null @@ -1,45 +0,0 @@ -//! \file secondary_uncorrelated.h -//! Uncorrelated angle-energy distribution - -#ifndef OPENMC_SECONDARY_UNCORRELATED_H -#define OPENMC_SECONDARY_UNCORRELATED_H - -#include -#include - -#include "hdf5.h" - -#include "openmc/angle_energy.h" -#include "openmc/distribution_angle.h" -#include "openmc/distribution_energy.h" - -namespace openmc { - -//============================================================================== -//! Uncorrelated angle-energy distribution. This corresponds to when an energy -//! distribution is given in ENDF File 5/6 and an angular distribution is given -//! in ENDF File 4. -//============================================================================== - -class UncorrelatedAngleEnergy : public AngleEnergy { -public: - explicit UncorrelatedAngleEnergy(hid_t group); - - //! Sample distribution for an angle and energy - //! \param[in] E_in Incoming energy in [eV] - //! \param[out] E_out Outgoing energy in [eV] - //! \param[out] mu Outgoing cosine with respect to current direction - void sample(double E_in, double& E_out, double& mu) const override; - - // Accessors - AngleDistribution& angle() { return angle_; } - bool& fission() { return fission_; } -private: - AngleDistribution angle_; //!< Angle distribution - std::unique_ptr energy_; //!< Energy distribution - bool fission_ {false}; //!< Whether distribution is use for fission -}; - -} // namespace openmc - -#endif // OPENMC_SECONDARY_UNCORRELATED_H diff --git a/include/openmc/settings.h b/include/openmc/settings.h deleted file mode 100644 index 8f4376717..000000000 --- a/include/openmc/settings.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef OPENMC_SETTINGS_H -#define OPENMC_SETTINGS_H - -//! \file settings.h -//! \brief Settings for OpenMC - -#include -#include -#include -#include -#include - -#include "pugixml.hpp" - -#include "openmc/constants.h" - -namespace openmc { - -//============================================================================== -// Global variable declarations -//============================================================================== - -namespace settings { - -// Boolean flags -extern bool assume_separate; //!< assume tallies are spatially separate? -extern bool check_overlaps; //!< check overlaps in geometry? -extern bool confidence_intervals; //!< use confidence intervals for results? -extern bool create_fission_neutrons; //!< create fission neutrons (fixed source)? -extern "C" bool cmfd_run; //!< is a CMFD run? -extern "C" bool dagmc; //!< indicator of DAGMC geometry -extern "C" bool entropy_on; //!< calculate Shannon entropy? -extern bool legendre_to_tabular; //!< convert Legendre distributions to tabular? -extern bool output_summary; //!< write summary.h5? -extern bool output_tallies; //!< write tallies.out? -extern bool particle_restart_run; //!< particle restart run? -extern "C" bool photon_transport; //!< photon transport turned on? -extern "C" bool reduce_tallies; //!< reduce tallies at end of batch? -extern bool res_scat_on; //!< use resonance upscattering method? -extern "C" bool restart_run; //!< restart run? -extern "C" bool run_CE; //!< run with continuous-energy data? -extern bool source_latest; //!< write latest source at each batch? -extern bool source_separate; //!< write source to separate file? -extern bool source_write; //!< write source in HDF5 files? -extern bool survival_biasing; //!< use survival biasing? -extern bool temperature_multipole; //!< use multipole data? -extern "C" bool trigger_on; //!< tally triggers enabled? -extern bool trigger_predict; //!< predict batches for triggers? -extern bool ufs_on; //!< uniform fission site method on? -extern bool urr_ptables_on; //!< use unresolved resonance prob. tables? -extern bool write_all_tracks; //!< write track files for every particle? -extern bool write_initial_source; //!< write out initial source file? - -// Paths to various files -extern std::string path_cross_sections; //!< path to cross_sections.xml -extern std::string path_input; //!< directory where main .xml files resides -extern std::string path_output; //!< directory where output files are written -extern std::string path_particle_restart; //!< path to a particle restart file -extern std::string path_source; -extern std::string path_sourcepoint; //!< path to a source file -extern "C" std::string path_statepoint; //!< path to a statepoint file - -extern "C" int32_t n_batches; //!< number of (inactive+active) batches -extern "C" int32_t n_inactive; //!< number of inactive batches -extern "C" int32_t gen_per_batch; //!< number of generations per batch -extern "C" int64_t n_particles; //!< number of particles per generation - -extern int electron_treatment; //!< how to treat secondary electrons -extern std::array energy_cutoff; //!< Energy cutoff in [eV] for each particle type -extern int legendre_to_tabular_points; //!< number of points to convert Legendres -extern int max_order; //!< Maximum Legendre order for multigroup data -extern int n_log_bins; //!< number of bins for logarithmic energy grid -extern int n_max_batches; //!< Maximum number of batches -extern ResScatMethod res_scat_method; //!< resonance upscattering method -extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering -extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering -extern std::vector res_scat_nuclides; //!< Nuclides using res. upscattering treatment -extern "C" int run_mode; //!< Run mode (eigenvalue, fixed src, etc.) -extern std::unordered_set sourcepoint_batch; //!< Batches when source should be written -extern std::unordered_set statepoint_batch; //!< Batches when state should be written -extern int temperature_method; //!< method for choosing temperatures -extern double temperature_tolerance; //!< Tolerance in [K] on choosing temperatures -extern double temperature_default; //!< Default T in [K] -extern std::array temperature_range; //!< Min/max T in [K] over which to load xs -extern int trace_batch; //!< Batch to trace particle on -extern int trace_gen; //!< Generation to trace particle on -extern int64_t trace_particle; //!< Particle ID to enable trace on -extern std::vector> track_identifiers; //!< Particle numbers for writing tracks -extern int trigger_batch_interval; //!< Batch interval for triggers -extern "C" int verbosity; //!< How verbose to make output -extern double weight_cutoff; //!< Weight cutoff for Russian roulette -extern double weight_survive; //!< Survival weight after Russian roulette -} // namespace settings - -//============================================================================== -// Functions -//============================================================================== - -//! Read settings from XML file -//! \param[in] root XML node for -void read_settings_xml(); - -void free_memory_settings(); - -} // namespace openmc - -#endif // OPENMC_SETTINGS_H diff --git a/include/openmc/simulation.h b/include/openmc/simulation.h deleted file mode 100644 index 8efac4c7f..000000000 --- a/include/openmc/simulation.h +++ /dev/null @@ -1,95 +0,0 @@ -//! \file simulation.h -//! \brief Variables/functions related to a running simulation - -#ifndef OPENMC_SIMULATION_H -#define OPENMC_SIMULATION_H - -#include "openmc/mesh.h" -#include "openmc/particle.h" - -#include -#include - -namespace openmc { - -constexpr int STATUS_EXIT_NORMAL {0}; -constexpr int STATUS_EXIT_MAX_BATCH {1}; -constexpr int STATUS_EXIT_ON_TRIGGER {2}; - -//============================================================================== -// Global variable declarations -//============================================================================== - -namespace simulation { - -extern "C" int current_batch; //!< current batch -extern "C" int current_gen; //!< current fission generation -extern "C" int64_t current_work; //!< index in source back of current particle -extern "C" bool initialized; //!< has simulation been initialized? -extern "C" double keff; //!< average k over batches -extern "C" double keff_std; //!< standard deviation of average k -extern "C" double k_col_abs; //!< sum over batches of k_collision * k_absorption -extern "C" double k_col_tra; //!< sum over batches of k_collision * k_tracklength -extern "C" double k_abs_tra; //!< sum over batches of k_absorption * k_tracklength -extern double log_spacing; //!< lethargy spacing for energy grid searches -extern "C" int n_lost_particles; //!< cumulative number of lost particles -extern "C" bool need_depletion_rx; //!< need to calculate depletion rx? -extern "C" int restart_batch; //!< batch at which a restart job resumed -extern "C" bool satisfy_triggers; //!< have tally triggers been satisfied? -extern "C" int total_gen; //!< total number of generations simulated -extern double total_weight; //!< Total source weight in a batch -extern int64_t work_per_rank; //!< number of particles per MPI rank - -extern const RegularMesh* entropy_mesh; -extern const RegularMesh* ufs_mesh; - -extern std::vector k_generation; -extern std::vector work_index; - -// Threadprivate variables -extern "C" bool trace; //!< flag to show debug information - -#pragma omp threadprivate(current_work, trace) - -} // namespace simulation - -//============================================================================== -// Functions -//============================================================================== - -//! Allocate space for source and fission banks -void allocate_banks(); - -//! Determine number of particles to transport per process -void calculate_work(); - -//! Initialize a batch -void initialize_batch(); - -//! Initialize a fission generation -void initialize_generation(); - -void initialize_history(Particle* p, int64_t index_source); - -//! Finalize a batch -//! -//! Handles synchronization and accumulation of tallies, calculation of Shannon -//! entropy, getting single-batch estimate of keff, and turning on tallies when -//! appropriate -void finalize_batch(); - -//! Finalize a fission generation -void finalize_generation(); - -//! Determine overall generation number -extern "C" int overall_generation(); - -#ifdef OPENMC_MPI -void broadcast_results(); -#endif - -void free_memory_simulation(); - -} // namespace openmc - -#endif // OPENMC_SIMULATION_H diff --git a/include/openmc/source.h b/include/openmc/source.h deleted file mode 100644 index bdd72e5bf..000000000 --- a/include/openmc/source.h +++ /dev/null @@ -1,73 +0,0 @@ -//! \file source.h -//! \brief External source distributions - -#ifndef OPENMC_SOURCE_H -#define OPENMC_SOURCE_H - -#include -#include - -#include "pugixml.hpp" - -#include "openmc/distribution_multi.h" -#include "openmc/distribution_spatial.h" -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -class SourceDistribution; - -namespace model { - -extern std::vector external_sources; - -} // namespace model - -//============================================================================== -//! External source distribution -//============================================================================== - -class SourceDistribution { -public: - // Constructors - SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy); - explicit SourceDistribution(pugi::xml_node node); - - //! Sample from the external source distribution - //! \return Sampled site - Particle::Bank sample() const; - - // Properties - double strength() const { return strength_; } -private: - Particle::Type particle_ {Particle::Type::neutron}; //!< Type of particle emitted - double strength_ {1.0}; //!< Source strength - UPtrSpace space_; //!< Spatial distribution - UPtrAngle angle_; //!< Angular distribution - UPtrDist energy_; //!< Energy distribution -}; - -//============================================================================== -// Functions -//============================================================================== - -//! Initialize source bank from file/distribution -extern "C" void initialize_source(); - -//! Sample a site from all external source distributions in proportion to their -//! source strength -//! \return Sampled source site -Particle::Bank sample_external_source(); - -//! Fill source bank at end of generation for fixed source simulations -void fill_source_bank_fixedsource(); - -void free_memory_source(); - -} // namespace openmc - -#endif // OPENMC_SOURCE_H diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h deleted file mode 100644 index e44c57f1a..000000000 --- a/include/openmc/state_point.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef OPENMC_STATE_POINT_H -#define OPENMC_STATE_POINT_H - -#include - -#include "hdf5.h" - -#include "openmc/capi.h" - -namespace openmc { - -void load_state_point(); -void write_source_point(const char* filename); -void write_source_bank(hid_t group_id); -void read_source_bank(hid_t group_id); -void write_tally_results_nr(hid_t file_id); -void restart_set_keff(); - -} // namespace openmc -#endif // OPENMC_STATE_POINT_H diff --git a/include/openmc/string_utils.h b/include/openmc/string_utils.h deleted file mode 100644 index a60fd06a8..000000000 --- a/include/openmc/string_utils.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef OPENMC_STRING_UTILS_H -#define OPENMC_STRING_UTILS_H - -#include -#include - -namespace openmc { - -std::string& strtrim(std::string& s); - -char* strtrim(char* c_str); - -std::string to_element(const std::string& name); - -void to_lower(std::string& str); - -int word_count(std::string const& str); - -std::vector split(const std::string& in); - -bool ends_with(const std::string& value, const std::string& ending); - -bool starts_with(const std::string& value, const std::string& beginning); - -} // namespace openmc -#endif // OPENMC_STRING_UTILS_H diff --git a/include/openmc/summary.h b/include/openmc/summary.h deleted file mode 100644 index ff2ab71a8..000000000 --- a/include/openmc/summary.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef OPENMC_SUMMARY_H -#define OPENMC_SUMMARY_H - -#include - -namespace openmc { - -void write_summary(); -void write_header(hid_t file); -void write_nuclides(hid_t file); -void write_geometry(hid_t file); -void write_materials(hid_t file); - -} - -#endif // OPENMC_SUMMARY_H diff --git a/include/openmc/surface.h b/include/openmc/surface.h deleted file mode 100644 index 5272dab3f..000000000 --- a/include/openmc/surface.h +++ /dev/null @@ -1,457 +0,0 @@ -#ifndef OPENMC_SURFACE_H -#define OPENMC_SURFACE_H - -#include // for unique_ptr -#include // For numeric_limits -#include -#include -#include - -#include "hdf5.h" -#include "pugixml.hpp" - -#include "openmc/constants.h" -#include "openmc/position.h" -#include "dagmc.h" - -namespace openmc { - -//============================================================================== -// Module constant declarations (defined in .cpp) -//============================================================================== - -// TODO: Convert to enum -extern "C" const int BC_TRANSMIT; -extern "C" const int BC_VACUUM; -extern "C" const int BC_REFLECT; -extern "C" const int BC_PERIODIC; -extern "C" const int BC_WHITE; - -//============================================================================== -// Global variables -//============================================================================== - -class Surface; - -namespace model { - extern std::vector> surfaces; - extern std::unordered_map surface_map; -} // namespace model - -//============================================================================== -//! Coordinates for an axis-aligned cube that bounds a geometric object. -//============================================================================== - -struct BoundingBox -{ - double xmin = -INFTY; - double xmax = INFTY; - double ymin = -INFTY; - double ymax = INFTY; - double zmin = -INFTY; - double zmax = INFTY; - - - inline BoundingBox operator &(const BoundingBox& other) { - BoundingBox result = *this; - return result &= other; - } - - inline BoundingBox operator |(const BoundingBox& other) { - BoundingBox result = *this; - return result |= other; - } - - // intersect operator - inline BoundingBox& operator &=(const BoundingBox& other) { - xmin = std::max(xmin, other.xmin); - xmax = std::min(xmax, other.xmax); - ymin = std::max(ymin, other.ymin); - ymax = std::min(ymax, other.ymax); - zmin = std::max(zmin, other.zmin); - zmax = std::min(zmax, other.zmax); - return *this; - } - - // union operator - inline BoundingBox& operator |=(const BoundingBox& other) { - xmin = std::min(xmin, other.xmin); - xmax = std::max(xmax, other.xmax); - ymin = std::min(ymin, other.ymin); - ymax = std::max(ymax, other.ymax); - zmin = std::min(zmin, other.zmin); - zmax = std::max(zmax, other.zmax); - return *this; - } - -}; - -//============================================================================== -//! A geometry primitive used to define regions of 3D space. -//============================================================================== - -class Surface -{ -public: - int id_; //!< Unique ID - int bc_; //!< Boundary condition - std::string name_; //!< User-defined name - - explicit Surface(pugi::xml_node surf_node); - Surface(); - - virtual ~Surface() {} - - //! Determine which side of a surface a point lies on. - //! \param r The 3D Cartesian coordinate of a point. - //! \param u A direction used to "break ties" and pick a sense when the - //! point is very close to the surface. - //! \return true if the point is on the "positive" side of the surface and - //! false otherwise. - bool sense(Position r, Direction u) const; - - //! Determine the direction of a ray reflected from the surface. - //! \param[in] r The point at which the ray is incident. - //! \param[in] u Incident direction of the ray - //! \return Outgoing direction of the ray - virtual Direction reflect(Position r, Direction u) const; - - virtual Direction diffuse_reflect(Position r, Direction u) const; - - //! Evaluate the equation describing the surface. - //! - //! Surfaces can be described by some function f(x, y, z) = 0. This member - //! function evaluates that mathematical function. - //! \param r A 3D Cartesian coordinate. - virtual double evaluate(Position r) const = 0; - - //! Compute the distance between a point and the surface along a ray. - //! \param r A 3D Cartesian coordinate. - //! \param u The direction of the ray. - //! \param coincident A hint to the code that the given point should lie - //! exactly on the surface. - virtual double distance(Position r, Direction u, bool coincident) const = 0; - - //! Compute the local outward normal direction of the surface. - //! \param r A 3D Cartesian coordinate. - //! \return Normal direction - virtual Direction normal(Position r) const = 0; - - //! Write all information needed to reconstruct the surface to an HDF5 group. - //! \param group_id An HDF5 group id. - //TODO: this probably needs to include i_periodic for PeriodicSurface - virtual void to_hdf5(hid_t group_id) const = 0; - - //! Get the BoundingBox for this surface. - virtual BoundingBox bounding_box(bool pos_side) const { return {}; } -}; - -class CSGSurface : public Surface -{ -public: - explicit CSGSurface(pugi::xml_node surf_node); - CSGSurface(); - - void to_hdf5(hid_t group_id) const; - -protected: - virtual void to_hdf5_inner(hid_t group_id) const = 0; -}; - -//============================================================================== -//! A `Surface` representing a DAGMC-based surface in DAGMC. -//============================================================================== -#ifdef DAGMC -class DAGSurface : public Surface -{ -public: - DAGSurface(); - - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - Direction reflect(Position r, Direction u) const; - - void to_hdf5(hid_t group_id) const; - - moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance - int32_t dag_index_; //!< DagMC index of surface -}; -#endif -//============================================================================== -//! A `Surface` that supports periodic boundary conditions. -//! -//! Translational periodicity is supported for the `XPlane`, `YPlane`, `ZPlane`, -//! and `Plane` types. Rotational periodicity is supported for -//! `XPlane`-`YPlane` pairs. -//============================================================================== - -class PeriodicSurface : public CSGSurface -{ -public: - int i_periodic_{C_NONE}; //!< Index of corresponding periodic surface - - explicit PeriodicSurface(pugi::xml_node surf_node); - - //! Translate a particle onto this surface from a periodic partner surface. - //! \param other A pointer to the partner surface in this periodic BC. - //! \param r A point on the partner surface that will be translated onto - //! this surface. - //! \param u A direction that will be rotated for systems with rotational - //! periodicity. - //! \return true if this surface and its partner make a rotationally-periodic - //! boundary condition. - virtual bool periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const = 0; - -}; - -//============================================================================== -//! A plane perpendicular to the x-axis. -// -//! The plane is described by the equation \f$x - x_0 = 0\f$ -//============================================================================== - -class SurfaceXPlane : public PeriodicSurface -{ -public: - explicit SurfaceXPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - bool periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const; - BoundingBox bounding_box(bool pos_side) const; - - double x0_; -}; - -//============================================================================== -//! A plane perpendicular to the y-axis. -// -//! The plane is described by the equation \f$y - y_0 = 0\f$ -//============================================================================== - -class SurfaceYPlane : public PeriodicSurface -{ -public: - explicit SurfaceYPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - bool periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const; - BoundingBox bounding_box(bool pos_side) const; - - double y0_; -}; - -//============================================================================== -//! A plane perpendicular to the z-axis. -// -//! The plane is described by the equation \f$z - z_0 = 0\f$ -//============================================================================== - -class SurfaceZPlane : public PeriodicSurface -{ -public: - explicit SurfaceZPlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - bool periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const; - BoundingBox bounding_box(bool pos_side) const; - - double z0_; -}; - -//============================================================================== -//! A general plane. -// -//! The plane is described by the equation \f$A x + B y + C z - D = 0\f$ -//============================================================================== - -class SurfacePlane : public PeriodicSurface -{ -public: - explicit SurfacePlane(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - bool periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const; - - double A_, B_, C_, D_; -}; - -//============================================================================== -//! A cylinder aligned along the x-axis. -// -//! The cylinder is described by the equation -//! \f$(y - y_0)^2 + (z - z_0)^2 - R^2 = 0\f$ -//============================================================================== - -class SurfaceXCylinder : public CSGSurface -{ -public: - explicit SurfaceXCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; - - double y0_, z0_, radius_; -}; - -//============================================================================== -//! A cylinder aligned along the y-axis. -// -//! The cylinder is described by the equation -//! \f$(x - x_0)^2 + (z - z_0)^2 - R^2 = 0\f$ -//============================================================================== - -class SurfaceYCylinder : public CSGSurface -{ -public: - explicit SurfaceYCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; - - double x0_, z0_, radius_; -}; - -//============================================================================== -//! A cylinder aligned along the z-axis. -// -//! The cylinder is described by the equation -//! \f$(x - x_0)^2 + (y - y_0)^2 - R^2 = 0\f$ -//============================================================================== - -class SurfaceZCylinder : public CSGSurface -{ -public: - explicit SurfaceZCylinder(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; - - double x0_, y0_, radius_; -}; - -//============================================================================== -//! A sphere. -// -//! The cylinder is described by the equation -//! \f$(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0\f$ -//============================================================================== - -class SurfaceSphere : public CSGSurface -{ -public: - explicit SurfaceSphere(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - BoundingBox bounding_box(bool pos_side) const; - - double x0_, y0_, z0_, radius_; -}; - -//============================================================================== -//! A cone aligned along the x-axis. -// -//! The cylinder is described by the equation -//! \f$(y - y_0)^2 + (z - z_0)^2 - R^2 (x - x_0)^2 = 0\f$ -//============================================================================== - -class SurfaceXCone : public CSGSurface -{ -public: - explicit SurfaceXCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - - double x0_, y0_, z0_, radius_sq_; -}; - -//============================================================================== -//! A cone aligned along the y-axis. -// -//! The cylinder is described by the equation -//! \f$(x - x_0)^2 + (z - z_0)^2 - R^2 (y - y_0)^2 = 0\f$ -//============================================================================== - -class SurfaceYCone : public CSGSurface -{ -public: - explicit SurfaceYCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - - double x0_, y0_, z0_, radius_sq_; -}; - -//============================================================================== -//! A cone aligned along the z-axis. -// -//! The cylinder is described by the equation -//! \f$(x - x_0)^2 + (y - y_0)^2 - R^2 (z - z_0)^2 = 0\f$ -//============================================================================== - -class SurfaceZCone : public CSGSurface -{ -public: - explicit SurfaceZCone(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - - double x0_, y0_, z0_, radius_sq_; -}; - -//============================================================================== -//! A general surface described by a quadratic equation. -// -//! \f$A x^2 + B y^2 + C z^2 + D x y + E y z + F x z + G x + H y + J z + K = 0\f$ -//============================================================================== - -class SurfaceQuadric : public CSGSurface -{ -public: - explicit SurfaceQuadric(pugi::xml_node surf_node); - double evaluate(Position r) const; - double distance(Position r, Direction u, bool coincident) const; - Direction normal(Position r) const; - void to_hdf5_inner(hid_t group_id) const; - - // Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0 - double A_, B_, C_, D_, E_, F_, G_, H_, J_, K_; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_surfaces(pugi::xml_node node); - -void free_memory_surfaces(); - -} // namespace openmc -#endif // OPENMC_SURFACE_H diff --git a/include/openmc/tallies/derivative.h b/include/openmc/tallies/derivative.h deleted file mode 100644 index 673afb0c9..000000000 --- a/include/openmc/tallies/derivative.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef OPENMC_TALLIES_DERIVATIVE_H -#define OPENMC_TALLIES_DERIVATIVE_H - -#include "openmc/particle.h" - -#include -#include - -#include "pugixml.hpp" - -//============================================================================== -//! Describes a first-order derivative that can be applied to tallies. -//============================================================================== - -namespace openmc { - -struct TallyDerivative { - int id; //!< User-defined identifier - int variable; //!< Independent variable (like temperature) - int diff_material; //!< Material this derivative is applied to - int diff_nuclide; //!< Nuclide this material is applied to - double flux_deriv; //!< Derivative of the current particle's weight - - TallyDerivative() {} - explicit TallyDerivative(pugi::xml_node node); -}; - -//============================================================================== -// Non-method functions -//============================================================================== - -//! Read tally derivatives from a tallies.xml file -void read_tally_derivatives(pugi::xml_node node); - -//! Scale the given score by its logarithmic derivative - -void -apply_derivative_to_score(const Particle* p, int i_tally, int i_nuclide, - double atom_density, int score_bin, double& score); - -//! Adjust diff tally flux derivatives for a particle scattering event. -// -//! Note that this subroutine will be called after absorption events in -//! addition to scattering events, but any flux derivatives scored after an -//! absorption will never be tallied. The paricle will be killed before any -//! further tallies are scored. -// -//! \param p The particle being tracked -void score_collision_derivative(const Particle* p); - -//! Adjust diff tally flux derivatives for a particle tracking event. -// -//! \param p The particle being tracked -//! \param distance The distance in [cm] traveled by the particle -void score_track_derivative(const Particle* p, double distance); - -//! Set the flux derivatives on differential tallies to zero. -void zero_flux_derivs(); - -} // namespace openmc - -//============================================================================== -// Global variables -//============================================================================== - -// Explicit vector template specialization declaration of threadprivate variable -// outside of the openmc namespace for the picky Intel compiler. -extern template class std::vector; - -namespace openmc { - -namespace model { -extern std::vector tally_derivs; -#pragma omp threadprivate(tally_derivs) -extern std::unordered_map tally_deriv_map; -} // namespace model - -// Independent variables -//TODO: convert to enum -constexpr int DIFF_DENSITY {1}; -constexpr int DIFF_NUCLIDE_DENSITY {2}; -constexpr int DIFF_TEMPERATURE {3}; - -} // namespace openmc - -#endif // OPENMC_TALLIES_DERIVATIVE_H diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h deleted file mode 100644 index ba6ca0883..000000000 --- a/include/openmc/tallies/filter.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_H -#define OPENMC_TALLIES_FILTER_H - -#include -#include -#include -#include -#include - -#include - -#include "openmc/hdf5_interface.h" -#include "openmc/particle.h" -#include "pugixml.hpp" - - -namespace openmc { - -//============================================================================== -//! Stores bins and weights for filtered tally events. -//============================================================================== - -class FilterMatch -{ -public: - std::vector bins_; - std::vector weights_; - int i_bin_; - bool bins_present_ {false}; -}; - -} // namespace openmc - -// Without an explicit instantiation of vector, the Intel compiler -// will complain about the threadprivate directive on filter_matches. Note that -// this has to happen *outside* of the openmc namespace -extern template class std::vector; - -namespace openmc { - -//============================================================================== -//! Modifies tally score events. -//============================================================================== - -class Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors, factory functions - - Filter(); - virtual ~Filter(); - - //! Create a new tally filter - // - //! \param[in] type Type of the filter - //! \param[in] id Unique ID for the filter. If none is passed, an ID is - //! automatically assigned - //! \return Pointer to the new filter object - static Filter* create(const std::string& type, int32_t id = -1); - - //! Create a new tally filter from an XML node - // - //! \param[in] node XML node - //! \return Pointer to the new filter object - static Filter* create(pugi::xml_node node); - - //! Uses an XML input to fill the filter's data fields. - virtual void from_xml(pugi::xml_node node) = 0; - - //---------------------------------------------------------------------------- - // Methods - - virtual std::string type() const = 0; - - //! Matches a tally event to a set of filter bins and weights. - //! - //! \param[out] match will contain the matching bins and corresponding - //! weights; note that there may be zero matching bins - virtual void - get_all_bins(const Particle* p, int estimator, FilterMatch& match) const = 0; - - //! Writes data describing this filter to an HDF5 statepoint group. - virtual void - to_statepoint(hid_t filter_group) const - { - write_dataset(filter_group, "type", type()); - write_dataset(filter_group, "n_bins", n_bins_); - } - - //! Return a string describing a filter bin for the tallies.out file. - // - //! For example, an `EnergyFilter` might return the string - //! "Incoming Energy [0.625E-6, 20.0)". - virtual std::string text_label(int bin) const = 0; - - //---------------------------------------------------------------------------- - // Accessors - - //! Get unique ID of filter - //! \return Unique ID - int32_t id() const { return id_; } - - //! Assign a unique ID to the filter - //! \param[in] Unique ID to assign. A value of -1 indicates that an ID should - //! be automatically assigned - void set_id(int32_t id); - - //! Get number of bins - //! \return Number of bins - int n_bins() const { return n_bins_; } - - gsl::index index() const { return index_; } - - //---------------------------------------------------------------------------- - // Data members - -protected: - int n_bins_; -private: - int32_t id_ {-1}; - gsl::index index_; -}; - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -extern std::vector filter_matches; -#pragma omp threadprivate(filter_matches) - -} // namespace simulation - -namespace model { - extern "C" int32_t n_filters; - extern std::vector> tally_filters; - extern std::unordered_map filter_map; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Make sure index corresponds to a valid filter -int verify_filter(int32_t index); - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_H diff --git a/include/openmc/tallies/filter_azimuthal.h b/include/openmc/tallies/filter_azimuthal.h deleted file mode 100644 index 84c2a2d8c..000000000 --- a/include/openmc/tallies/filter_azimuthal.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_AZIMUTHAL_H -#define OPENMC_TALLIES_FILTER_AZIMUTHAL_H - -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins the incident neutron azimuthal angle (relative to the global xy-plane). -//============================================================================== - -class AzimuthalFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~AzimuthalFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "azimuthal";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_bins(gsl::span bins); - -private: - //---------------------------------------------------------------------------- - // Data members - - std::vector bins_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_AZIMUTHAL_H diff --git a/include/openmc/tallies/filter_cell.h b/include/openmc/tallies/filter_cell.h deleted file mode 100644 index b570ee027..000000000 --- a/include/openmc/tallies/filter_cell.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_CELL_H -#define OPENMC_TALLIES_FILTER_CELL_H - -#include -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Specifies which geometric cells tally events reside in. -//============================================================================== - -class CellFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~CellFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "cell";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - const std::vector& cells() const { return cells_; } - - void set_cells(gsl::span cells); - -protected: - //---------------------------------------------------------------------------- - // Data members - - //! The indices of the cells binned by this filter. - std::vector cells_; - - //! A map from cell indices to filter bin indices. - std::unordered_map map_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_CELL_H diff --git a/include/openmc/tallies/filter_cellborn.h b/include/openmc/tallies/filter_cellborn.h deleted file mode 100644 index 706f6c47a..000000000 --- a/include/openmc/tallies/filter_cellborn.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_CELLBORN_H -#define OPENMC_TALLIES_FILTER_CELLBORN_H - -#include - -#include "openmc/tallies/filter_cell.h" - -namespace openmc { - -//============================================================================== -//! Specifies which cell the particle was born in. -//============================================================================== - -class CellbornFilter : public CellFilter -{ -public: - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "cellborn";} - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - std::string text_label(int bin) const override; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_CELLBORN_H diff --git a/include/openmc/tallies/filter_cellfrom.h b/include/openmc/tallies/filter_cellfrom.h deleted file mode 100644 index e86e34854..000000000 --- a/include/openmc/tallies/filter_cellfrom.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_CELLFROM_H -#define OPENMC_TALLIES_FILTER_CELLFROM_H - -#include - -#include "openmc/tallies/filter_cell.h" - -namespace openmc { - -//============================================================================== -//! Specifies which geometric cells particles exit when crossing a surface. -//============================================================================== - -class CellFromFilter : public CellFilter -{ -public: - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "cellfrom";} - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - std::string text_label(int bin) const override; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_CELLFROM_H diff --git a/include/openmc/tallies/filter_delayedgroup.h b/include/openmc/tallies/filter_delayedgroup.h deleted file mode 100644 index 8a2bbeeaa..000000000 --- a/include/openmc/tallies/filter_delayedgroup.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_DELAYEDGROUP_H -#define OPENMC_TALLIES_FILTER_DELAYEDGROUP_H - -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins outgoing fission neutrons in their delayed groups. -//! -//! The get_all_bins functionality is not actually used. The bins are manually -//! iterated over in the scoring subroutines. -//============================================================================== - -class DelayedGroupFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~DelayedGroupFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "delayedgroup";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - const std::vector& groups() const { return groups_; } - - void set_groups(gsl::span groups); - -private: - //---------------------------------------------------------------------------- - // Data members - - std::vector groups_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_DELAYEDGROUP_H diff --git a/include/openmc/tallies/filter_distribcell.h b/include/openmc/tallies/filter_distribcell.h deleted file mode 100644 index 9430a0906..000000000 --- a/include/openmc/tallies/filter_distribcell.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_DISTRIBCELL_H -#define OPENMC_TALLIES_FILTER_DISTRIBCELL_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Specifies which distributed geometric cells tally events reside in. -//============================================================================== - -class DistribcellFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~DistribcellFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "distribcell";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - int32_t cell() const { return cell_; } - - void set_cell(int32_t cell); - -private: - //---------------------------------------------------------------------------- - // Data members - - int32_t cell_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_DISTRIBCELL_H diff --git a/include/openmc/tallies/filter_energy.h b/include/openmc/tallies/filter_energy.h deleted file mode 100644 index af7601721..000000000 --- a/include/openmc/tallies/filter_energy.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_ENERGY_H -#define OPENMC_TALLIES_FILTER_ENERGY_H - -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins the incident neutron energy. -//============================================================================== - -class EnergyFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~EnergyFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "energy";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - const std::vector& bins() const { return bins_; } - void set_bins(gsl::span bins); - - bool matches_transport_groups() const { return matches_transport_groups_; } - -protected: - //---------------------------------------------------------------------------- - // Data members - - std::vector bins_; - - //! True if transport group number can be used directly to get bin number - bool matches_transport_groups_ {false}; -}; - -//============================================================================== -//! Bins the outgoing neutron energy. -//! -//! Only scattering events use the get_all_bins functionality. Nu-fission -//! tallies manually iterate over the filter bins. -//============================================================================== - -class EnergyoutFilter : public EnergyFilter -{ -public: - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "energyout";} - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - std::string text_label(int bin) const override; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_ENERGY_H diff --git a/include/openmc/tallies/filter_energyfunc.h b/include/openmc/tallies/filter_energyfunc.h deleted file mode 100644 index df82e659e..000000000 --- a/include/openmc/tallies/filter_energyfunc.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_ENERGYFUNC_H -#define OPENMC_TALLIES_FILTER_ENERGYFUNC_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Multiplies tally scores by an arbitrary function of incident energy -//! described by a piecewise linear-linear interpolation. -//============================================================================== - -class EnergyFunctionFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - EnergyFunctionFilter() - : Filter {} - { - n_bins_ = 1; - } - - ~EnergyFunctionFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "energyfunction";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - const std::vector& energy() const { return energy_; } - const std::vector& y() const { return y_; } - void set_data(gsl::span energy, gsl::span y); - -private: - //---------------------------------------------------------------------------- - // Data members - - //! Incident neutron energy interpolation grid. - std::vector energy_; - - //! Interpolant values. - std::vector y_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_ENERGYFUNC_H diff --git a/include/openmc/tallies/filter_legendre.h b/include/openmc/tallies/filter_legendre.h deleted file mode 100644 index 3a14ec3cf..000000000 --- a/include/openmc/tallies/filter_legendre.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_LEGENDRE_H -#define OPENMC_TALLIES_FILTER_LEGENDRE_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Gives Legendre moments of the change in scattering angle -//============================================================================== - -class LegendreFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~LegendreFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "legendre";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - int order() const { return order_; } - - void set_order(int order); - -private: - //---------------------------------------------------------------------------- - // Data members - - int order_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_LEGENDRE_H diff --git a/include/openmc/tallies/filter_material.h b/include/openmc/tallies/filter_material.h deleted file mode 100644 index 65cf832a3..000000000 --- a/include/openmc/tallies/filter_material.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_MATERIAL_H -#define OPENMC_TALLIES_FILTER_MATERIAL_H - -#include -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Specifies which material tally events reside in. -//============================================================================== - -class MaterialFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~MaterialFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "material";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - std::vector& materials() { return materials_; } - - const std::vector& materials() const { return materials_; } - - void set_materials(gsl::span materials); - -private: - //---------------------------------------------------------------------------- - // Data members - - //! The indices of the materials binned by this filter. - std::vector materials_; - - //! A map from material indices to filter bin indices. - std::unordered_map map_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_MATERIAL_H diff --git a/include/openmc/tallies/filter_mesh.h b/include/openmc/tallies/filter_mesh.h deleted file mode 100644 index 98dec5d50..000000000 --- a/include/openmc/tallies/filter_mesh.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_MESH_H -#define OPENMC_TALLIES_FILTER_MESH_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Indexes the location of particle events to a regular mesh. For tracklength -//! tallies, it will produce multiple valid bins and the bin weight will -//! correspond to the fraction of the track length that lies in that bin. -//============================================================================== - -class MeshFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~MeshFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "mesh";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - virtual int32_t mesh() const {return mesh_;} - - virtual void set_mesh(int32_t mesh); - -protected: - //---------------------------------------------------------------------------- - // Data members - - int32_t mesh_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_MESH_H diff --git a/include/openmc/tallies/filter_meshsurface.h b/include/openmc/tallies/filter_meshsurface.h deleted file mode 100644 index 19d178c7f..000000000 --- a/include/openmc/tallies/filter_meshsurface.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_MESHSURFACE_H -#define OPENMC_TALLIES_FILTER_MESHSURFACE_H - -#include "openmc/tallies/filter_mesh.h" - -namespace openmc { - -class MeshSurfaceFilter : public MeshFilter -{ -public: - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "meshsurface";} - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_mesh(int32_t mesh) override; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_MESHSURFACE_H diff --git a/include/openmc/tallies/filter_mu.h b/include/openmc/tallies/filter_mu.h deleted file mode 100644 index ae9c3e06a..000000000 --- a/include/openmc/tallies/filter_mu.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_MU_H -#define OPENMC_TALLIES_FILTER_MU_H - -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins the incoming-outgoing direction cosine. This is only used for scatter -//! reactions. -//============================================================================== - -class MuFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~MuFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "mu";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_bins(gsl::span bins); - -private: - //---------------------------------------------------------------------------- - // Data members - - std::vector bins_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_MU_H diff --git a/include/openmc/tallies/filter_particle.h b/include/openmc/tallies/filter_particle.h deleted file mode 100644 index 61aa3106b..000000000 --- a/include/openmc/tallies/filter_particle.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_PARTICLE_H -#define OPENMC_TALLIES_FILTER_PARTICLE_H - -#include - -#include "openmc/particle.h" -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins by type of particle (e.g. neutron, photon). -//============================================================================== - -class ParticleFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~ParticleFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "particle";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - const std::vector& particles() const { return particles_; } - - void set_particles(gsl::span particles); - -private: - //---------------------------------------------------------------------------- - // Data members - - std::vector particles_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_PARTICLE_H diff --git a/include/openmc/tallies/filter_polar.h b/include/openmc/tallies/filter_polar.h deleted file mode 100644 index 965950456..000000000 --- a/include/openmc/tallies/filter_polar.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_POLAR_H -#define OPENMC_TALLIES_FILTER_POLAR_H - -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Bins the incident neutron polar angle (relative to the global z-axis). -//============================================================================== - -class PolarFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~PolarFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "polar";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_bins(gsl::span bins); - -private: - //---------------------------------------------------------------------------- - // Data members - - std::vector bins_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_POLAR_H diff --git a/include/openmc/tallies/filter_sph_harm.h b/include/openmc/tallies/filter_sph_harm.h deleted file mode 100644 index 80f998b2f..000000000 --- a/include/openmc/tallies/filter_sph_harm.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_SPH_HARM_H -#define OPENMC_TALLIES_FILTER_SPH_HARM_H - -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -enum class SphericalHarmonicsCosine { - scatter, particle -}; - -//============================================================================== -//! Gives spherical harmonics expansion moments of a tally score -//============================================================================== - -class SphericalHarmonicsFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~SphericalHarmonicsFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "sphericalharmonics";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - int order() const { return order_; } - - void set_order(int order); - - SphericalHarmonicsCosine cosine() const { return cosine_; } - - void set_cosine(gsl::cstring_span cosine); - -private: - //---------------------------------------------------------------------------- - // Data members - - int order_; - - //! The type of angle that this filter measures when binning events. - SphericalHarmonicsCosine cosine_ {SphericalHarmonicsCosine::particle}; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_SPH_HARM_H diff --git a/include/openmc/tallies/filter_sptl_legendre.h b/include/openmc/tallies/filter_sptl_legendre.h deleted file mode 100644 index fea727515..000000000 --- a/include/openmc/tallies/filter_sptl_legendre.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H -#define OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -enum class LegendreAxis { - x, y, z -}; - -//============================================================================== -//! Gives Legendre moments of the particle's normalized position along an axis -//============================================================================== - -class SpatialLegendreFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~SpatialLegendreFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "spatiallegendre";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - int order() const { return order_; } - void set_order(int order); - - LegendreAxis axis() const { return axis_; } - void set_axis(LegendreAxis axis); - - double min() const { return min_; } - double max() const { return max_; } - void set_minmax(double min, double max); - -private: - //---------------------------------------------------------------------------- - // Data members - - int order_; - - //! The Cartesian coordinate axis that the Legendre expansion is applied to. - LegendreAxis axis_; - - //! The minimum coordinate along the reference axis that the expansion covers. - double min_; - - //! The maximum coordinate along the reference axis that the expansion covers. - double max_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H diff --git a/include/openmc/tallies/filter_surface.h b/include/openmc/tallies/filter_surface.h deleted file mode 100644 index 23b9be33d..000000000 --- a/include/openmc/tallies/filter_surface.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_SURFACE_H -#define OPENMC_TALLIES_FILTER_SURFACE_H - -#include -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Specifies which surface particles are crossing -//============================================================================== - -class SurfaceFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~SurfaceFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "surface";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_surfaces(gsl::span surfaces); - -private: - //---------------------------------------------------------------------------- - // Data members - - //! The indices of the surfaces binned by this filter. - std::vector surfaces_; - - //! A map from surface indices to filter bin indices. - std::unordered_map map_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_SURFACE_H diff --git a/include/openmc/tallies/filter_universe.h b/include/openmc/tallies/filter_universe.h deleted file mode 100644 index fc2ace18f..000000000 --- a/include/openmc/tallies/filter_universe.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_UNIVERSE_H -#define OPENMC_TALLIES_FILTER_UNIVERSE_H - -#include -#include -#include - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Specifies which geometric universes tally events reside in. -//============================================================================== - -class UniverseFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~UniverseFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "universe";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_universes(gsl::span universes); - -private: - //---------------------------------------------------------------------------- - // Data members - - //! The indices of the universes binned by this filter. - std::vector universes_; - - //! A map from universe indices to filter bin indices. - std::unordered_map map_; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_UNIVERSE_H diff --git a/include/openmc/tallies/filter_zernike.h b/include/openmc/tallies/filter_zernike.h deleted file mode 100644 index e3ae89dec..000000000 --- a/include/openmc/tallies/filter_zernike.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef OPENMC_TALLIES_FILTER_ZERNIKE_H -#define OPENMC_TALLIES_FILTER_ZERNIKE_H - -#include - -#include "openmc/tallies/filter.h" - -namespace openmc { - -//============================================================================== -//! Gives Zernike polynomial moments of a particle's position -//============================================================================== - -class ZernikeFilter : public Filter -{ -public: - //---------------------------------------------------------------------------- - // Constructors, destructors - - ~ZernikeFilter() = default; - - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "zernike";} - - void from_xml(pugi::xml_node node) override; - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - void to_statepoint(hid_t filter_group) const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - int order() const { return order_; } - virtual void set_order(int order); - - double x() const { return x_; } - void set_x(double x) { x_ = x; } - - double y() const { return y_; } - void set_y(double y) { y_ = y; } - - double r() const { return r_; } - void set_r(double r) { r_ = r; } - - //---------------------------------------------------------------------------- - // Data members - -protected: - //! Cartesian x coordinate for the origin of this expansion. - double x_; - - //! Cartesian y coordinate for the origin of this expansion. - double y_; - - //! Maximum radius from the origin covered by this expansion. - double r_; - - int order_; -}; - -//============================================================================== -//! Gives even order radial Zernike polynomial moments of a particle's position -//============================================================================== - -class ZernikeRadialFilter : public ZernikeFilter -{ -public: - //---------------------------------------------------------------------------- - // Methods - - std::string type() const override {return "zernikeradial";} - - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) - const override; - - std::string text_label(int bin) const override; - - //---------------------------------------------------------------------------- - // Accessors - - void set_order(int order) override; -}; - -} // namespace openmc -#endif // OPENMC_TALLIES_FILTER_ZERNIKE_H diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h deleted file mode 100644 index dc7cd8ce2..000000000 --- a/include/openmc/tallies/tally.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef OPENMC_TALLIES_TALLY_H -#define OPENMC_TALLIES_TALLY_H - -#include "openmc/constants.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/trigger.h" - -#include -#include "pugixml.hpp" -#include "xtensor/xfixed.hpp" -#include "xtensor/xtensor.hpp" - -#include // for unique_ptr -#include -#include -#include - -namespace openmc { - -//============================================================================== -//! A user-specified flux-weighted (or current) measurement. -//============================================================================== - -class Tally { -public: - //---------------------------------------------------------------------------- - // Constructors, destructors, factory functions - explicit Tally(int32_t id); - explicit Tally(pugi::xml_node node); - ~Tally(); - static Tally* create(int32_t id = -1); - - //---------------------------------------------------------------------------- - // Accessors - - void set_id(int32_t id); - - void set_active(bool active) { active_ = active; } - - void set_writable(bool writable) { writable_ = writable; } - - void set_scores(pugi::xml_node node); - - void set_scores(const std::vector& scores); - - void set_nuclides(pugi::xml_node node); - - void set_nuclides(const std::vector& nuclides); - - const std::vector& filters() const {return filters_;} - - int32_t filters(int i) const {return filters_[i];} - - void set_filters(gsl::span filters); - - int32_t strides(int i) const {return strides_[i];} - - int32_t n_filter_bins() const {return n_filter_bins_;} - - bool writable() const { return writable_;} - - //---------------------------------------------------------------------------- - // Other methods. - - void init_triggers(pugi::xml_node node); - - void init_results(); - - void reset(); - - void accumulate(); - - //---------------------------------------------------------------------------- - // Major public data members. - - int id_; //!< User-defined identifier - - std::string name_; //!< User-defined name - - int type_ {TALLY_VOLUME}; //!< e.g. volume, surface current - - //! Event type that contributes to this tally - int estimator_ {ESTIMATOR_TRACKLENGTH}; - - //! Whether this tally is currently being updated - bool active_ {false}; - - //! Number of realizations - int n_realizations_ {0}; - - std::vector scores_; //!< Filter integrands (e.g. flux, fission) - - //! Index of each nuclide to be tallied. -1 indicates total material. - std::vector nuclides_ {-1}; - - //! True if this tally has a bin for every nuclide in the problem - bool all_nuclides_ {false}; - - //! Results for each bin -- the first dimension of the array is for scores - //! (e.g. flux, total reaction rate, fission reaction rate, etc.) and the - //! second dimension of the array is for the combination of filters - //! (e.g. specific cell, specific energy group, etc.) - xt::xtensor results_; - - //! True if this tally should be written to statepoint files - bool writable_ {true}; - - //---------------------------------------------------------------------------- - // Miscellaneous public members. - - // We need to have quick access to some filters. The following gives indices - // for various filters that could be in the tally or C_NONE if they are not - // present. - int energyout_filter_ {C_NONE}; - int delayedgroup_filter_ {C_NONE}; - - bool depletion_rx_ {false}; //!< Has depletion reactions (e.g. (n,2n)) - - std::vector triggers_; - - int deriv_ {C_NONE}; //!< Index of a TallyDerivative object for diff tallies. - -private: - //---------------------------------------------------------------------------- - // Private data. - - std::vector filters_; //!< Filter indices in global filters array - - //! Index strides assigned to each filter to support 1D indexing. - std::vector strides_; - - int32_t n_filter_bins_ {0}; - - gsl::index index_; -}; - -//============================================================================== -// Global variable declarations -//============================================================================== - -namespace model { - extern std::vector> tallies; - extern std::vector active_tallies; - extern std::vector active_analog_tallies; - extern std::vector active_tracklength_tallies; - extern std::vector active_collision_tallies; - extern std::vector active_meshsurf_tallies; - extern std::vector active_surface_tallies; - - extern std::unordered_map tally_map; -} - -namespace simulation { - //! Global tallies (such as k-effective estimators) - extern xt::xtensor_fixed> global_tallies; - - //! Number of realizations for global tallies - extern "C" int32_t n_realizations; -} - -// It is possible to protect accumulate operations on global tallies by using an -// atomic update. However, when multiple threads accumulate to the same global -// tally, it can cause a higher cache miss rate due to invalidation. Thus, we -// use threadprivate variables to accumulate global tallies and then reduce at -// the end of a generation. -extern double global_tally_absorption; -extern double global_tally_collision; -extern double global_tally_tracklength; -extern double global_tally_leakage; -#pragma omp threadprivate(global_tally_absorption, global_tally_collision, \ - global_tally_tracklength, global_tally_leakage) - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Read tally specification from tallies.xml -void read_tallies_xml(); - -//! \brief Accumulate the sum of the contributions from each history within the -//! batch to a new random variable -void accumulate_tallies(); - -//! Determine which tallies should be active -void setup_active_tallies(); - -// Alias for the type returned by xt::adapt(...). N is the dimension of the -// multidimensional array -template -using adaptor_type = xt::xtensor_adaptor, N>; - -#ifdef OPENMC_MPI -//! Collect all tally results onto master process -void reduce_tally_results(); -#endif - -void free_memory_tally(); - -} // namespace openmc - -#endif // OPENMC_TALLIES_TALLY_H diff --git a/include/openmc/tallies/tally_scoring.h b/include/openmc/tallies/tally_scoring.h deleted file mode 100644 index 2c5a29c17..000000000 --- a/include/openmc/tallies/tally_scoring.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef OPENMC_TALLIES_TALLY_SCORING_H -#define OPENMC_TALLIES_TALLY_SCORING_H - -#include "openmc/particle.h" -#include "openmc/tallies/tally.h" - -namespace openmc { - -//============================================================================== -//! An iterator over all combinations of a tally's matching filter bins. -// -//! This iterator handles two distinct tasks. First, it maps the N-dimensional -//! space created by the indices of N filters onto a 1D sequence. In other -//! words, it provides a single number that uniquely identifies a combination of -//! bins for many filters. Second, it handles the task of finding each valid -//! combination of filter bins given that each filter can have 1 or 2 or many -//! bins that are valid for the current tally event. -//============================================================================== - -class FilterBinIter -{ -public: - - //! Construct an iterator over bins that match a given particle's state. - FilterBinIter(const Tally& tally, const Particle* p); - - //! Construct an iterator over all filter bin combinations. - // - //! \param end if true, the returned iterator indicates the end of a loop. - FilterBinIter(const Tally& tally, bool end); - - bool operator==(const FilterBinIter& other) const - {return index_ == other.index_;} - - bool operator!=(const FilterBinIter& other) const - {return !(*this == other);} - - FilterBinIter& operator++(); - - int index_ {1}; - double weight_ {1.}; - -private: - void compute_index_weight(); - - const Tally& tally_; -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Score tallies using a 1 / Sigma_t estimate of the flux. -// -//! This is triggered after every collision. It is invalid for tallies that -//! require post-collison information because it can score reactions that didn't -//! actually occur, and we don't a priori know what the outcome will be for -//! reactions that we didn't sample. It is assumed the material is not void -//! since collisions do not occur in voids. -// -//! \param p The particle being tracked -void score_collision_tally(Particle* p); - -//! Score tallies based on a simple count of events (for continuous energy). -// -//! Analog tallies are triggered at every collision, not every event. -// -//! \param p The particle being tracked -void score_analog_tally_ce(Particle* p); - -//! Score tallies based on a simple count of events (for multigroup). -// -//! Analog tallies are triggered at every collision, not every event. -// -//! \param p The particle being tracked -void score_analog_tally_mg(const Particle* p); - -//! Score tallies using a tracklength estimate of the flux. -// -//! This is triggered at every event (surface crossing, lattice crossing, or -//! collision) and thus cannot be done for tallies that require post-collision -//! information. -// -//! \param p The particle being tracked -//! \param distance The distance in [cm] traveled by the particle -void score_tracklength_tally(Particle* p, double distance); - -//! Score surface or mesh-surface tallies for particle currents. -// -//! \param p The particle being tracked -//! \param tallies A vector of tallies to score to -void score_surface_tally(const Particle* p, const std::vector& tallies); - -} // namespace openmc - -#endif // OPENMC_TALLIES_TALLY_SCORING_H diff --git a/include/openmc/tallies/trigger.h b/include/openmc/tallies/trigger.h deleted file mode 100644 index a11759114..000000000 --- a/include/openmc/tallies/trigger.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef OPENMC_TALLIES_TRIGGER_H -#define OPENMC_TALLIES_TRIGGER_H - -#include - -#include "pugixml.hpp" - -namespace openmc { - -//============================================================================== -// Type definitions -//============================================================================== - -enum class TriggerMetric { - variance, relative_error, standard_deviation, not_active -}; - -//! Stops the simulation early if a desired tally uncertainty is reached. - -struct Trigger { - TriggerMetric metric; //!< The type of uncertainty (e.g. std dev) measured - double threshold; //!< Uncertainty value below which trigger is satisfied - int score_index; //!< Index of the relevant score in the tally's arrays -}; - -//! Stops the simulation early if a desired k-effective uncertainty is reached. - -struct KTrigger -{ - TriggerMetric metric {TriggerMetric::not_active}; - double threshold {0.}; -}; - -//============================================================================== -// Global variable declarations -//============================================================================== - -//TODO: consider a different namespace -namespace settings { - extern KTrigger keff_trigger; -} - -//============================================================================== -// Non-memeber functions -//============================================================================== - -void check_triggers(); - -} // namespace openmc -#endif // OPENMC_TALLIES_TRIGGER_H diff --git a/include/openmc/thermal.h b/include/openmc/thermal.h deleted file mode 100644 index cb6a7ce7b..000000000 --- a/include/openmc/thermal.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef OPENMC_THERMAL_H -#define OPENMC_THERMAL_H - -#include -#include -#include -#include -#include - -#include "xtensor/xtensor.hpp" - -#include "openmc/angle_energy.h" -#include "openmc/endf.h" -#include "openmc/hdf5_interface.h" -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -// Constants -//============================================================================== - -// Secondary energy mode for S(a,b) inelastic scattering -// TODO: Convert to enum -constexpr int SAB_SECONDARY_EQUAL {0}; // Equally-likely outgoing energy bins -constexpr int SAB_SECONDARY_SKEWED {1}; // Skewed outgoing energy bins -constexpr int SAB_SECONDARY_CONT {2}; // Continuous, linear-linear interpolation - -// Elastic mode for S(a,b) elastic scattering -// TODO: Convert to enum -constexpr int SAB_ELASTIC_INCOHERENT {3}; // Incoherent elastic scattering -constexpr int SAB_ELASTIC_COHERENT {4}; // Coherent elastic scattering (Bragg edges) - -//============================================================================== -// Global variables -//============================================================================== - -class ThermalScattering; - -namespace data { -extern std::vector> thermal_scatt; -extern std::unordered_map thermal_scatt_map; -} - -//============================================================================== -//! Secondary angle-energy data for thermal neutron scattering at a single -//! temperature -//============================================================================== - -class ThermalData { -public: - ThermalData(hid_t group); - - //! Calculate the cross section - // - //! \param[in] E Incident neutron energy in [eV] - //! \param[out] elastic Elastic scattering cross section in [b] - //! \param[out] inelastic Inelastic scattering cross section in [b] - void calculate_xs(double E, double* elastic, double* inelastic) const; - - //! Sample an outgoing energy and angle - // - //! \param[in] micro_xs Microscopic cross sections - //! \param[in] E_in Incident neutron energy in [eV] - //! \param[out] E_out Outgoing neutron energy in [eV] - //! \param[out] mu Outgoing scattering angle cosine - void sample(const NuclideMicroXS& micro_xs, double E_in, - double* E_out, double* mu); -private: - struct Reaction { - // Default constructor - Reaction() { } - - // Data members - std::unique_ptr xs; //!< Cross section - std::unique_ptr distribution; //!< Secondary angle-energy distribution - }; - - // Inelastic scattering data - Reaction elastic_; - Reaction inelastic_; - - // ThermalScattering needs access to private data members - friend class ThermalScattering; -}; - -//============================================================================== -//! Data for thermal neutron scattering, typically off light isotopes in -//! moderating materials such as water, graphite, BeO, etc. -//============================================================================== - -class ThermalScattering { -public: - ThermalScattering(hid_t group, const std::vector& temperature); - - //! Determine inelastic/elastic cross section at given energy - //! - //! \param[in] E incoming energy in [eV] - //! \param[in] sqrtkT square-root of temperature multipled by Boltzmann's constant - //! \param[out] i_temp corresponding temperature index - //! \param[out] elastic Thermal elastic scattering cross section - //! \param[out] inelastic Thermal inelastic scattering cross section - void calculate_xs(double E, double sqrtkT, int* i_temp, double* elastic, - double* inelastic) const; - - //! Determine whether table applies to a particular nuclide - //! - //! \param[in] name Name of the nuclide, e.g., "H1" - //! \return Whether table applies to the nuclide - bool has_nuclide(const char* name) const; - - // Sample an outgoing energy and angle - void sample(const NuclideMicroXS& micro_xs, double E_in, - double* E_out, double* mu); - - std::string name_; //!< name of table, e.g. "c_H_in_H2O" - double awr_; //!< weight of nucleus in neutron masses - double energy_max_; //!< maximum energy for thermal scattering in [eV] - std::vector kTs_; //!< temperatures in [eV] (k*T) - std::vector nuclides_; //!< Valid nuclides - - //! cross sections and distributions at each temperature - std::vector data_; -}; - -void free_memory_thermal(); - -} // namespace openmc - -#endif // OPENMC_THERMAL_H diff --git a/include/openmc/timer.h b/include/openmc/timer.h deleted file mode 100644 index 9149c4ef7..000000000 --- a/include/openmc/timer.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef OPENMC_TIMER_H -#define OPENMC_TIMER_H - -#include - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -class Timer; - -namespace simulation { - -extern Timer time_active; -extern Timer time_bank; -extern Timer time_bank_sample; -extern Timer time_bank_sendrecv; -extern Timer time_finalize; -extern Timer time_inactive; -extern Timer time_initialize; -extern Timer time_read_xs; -extern Timer time_tallies; -extern Timer time_total; -extern Timer time_transport; - -} // namespace simulation - -//============================================================================== -//! Class for measuring time elapsed -//============================================================================== - -class Timer { -public: - using clock = std::chrono::high_resolution_clock; - - Timer() {}; - - //! Start running the timer - void start(); - - //! Get total elapsed time in seconds - //! \return Elapsed time in [s] - double elapsed(); - - //! Stop running the timer - void stop(); - - //! Stop the timer and reset its elapsed time - void reset(); - -private: - bool running_ {false}; //!< is timer running? - std::chrono::time_point start_; //!< starting point for clock - double elapsed_ {0.0}; //!< elapsed time in [s] -}; - -//============================================================================== -// Non-member functions -//============================================================================== - -void reset_timers(); - -} // namespace openmc - -#endif // OPENMC_TIMER_H diff --git a/include/openmc/track_output.h b/include/openmc/track_output.h deleted file mode 100644 index f32529bc2..000000000 --- a/include/openmc/track_output.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef OPENMC_TRACK_OUTPUT_H -#define OPENMC_TRACK_OUTPUT_H - -#include "openmc/particle.h" - -namespace openmc { - -//============================================================================== -// Non-member functions -//============================================================================== - -void add_particle_track(); -void write_particle_track(const Particle& p); -void finalize_particle_track(const Particle& p); - -} // namespace openmc - -#endif // OPENMC_TRACK_OUTPUT_H diff --git a/include/openmc/urr.h b/include/openmc/urr.h deleted file mode 100644 index 676425442..000000000 --- a/include/openmc/urr.h +++ /dev/null @@ -1,33 +0,0 @@ -//! \brief UrrData information for the unresolved resonance treatment - -#ifndef OPENMC_URR_H -#define OPENMC_URR_H - -#include "xtensor/xtensor.hpp" - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" - -namespace openmc { - -//============================================================================== -//! UrrData contains probability tables for the unresolved resonance range. -//============================================================================== - -class UrrData{ -public: - Interpolation interp_; //!< interpolation type - int inelastic_flag_; //!< inelastic competition flag - int absorption_flag_; //!< other absorption flag - bool multiply_smooth_; //!< multiply by smooth cross section? - int n_energy_; //!< number of energy points - xt::xtensor energy_; //!< incident energies - xt::xtensor prob_; //!< Actual probability tables - - //! \brief Load the URR data from the provided HDF5 group - explicit UrrData(hid_t group_id); -}; - -} // namespace openmc - -#endif // OPENMC_URR_H diff --git a/include/openmc/volume_calc.h b/include/openmc/volume_calc.h deleted file mode 100644 index 7ee660d8b..000000000 --- a/include/openmc/volume_calc.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef OPENMC_VOLUME_CALC_H -#define OPENMC_VOLUME_CALC_H - -#include "openmc/position.h" - -#include "pugixml.hpp" -#include "xtensor/xtensor.hpp" - -#include -#include - -namespace openmc { - -//============================================================================== -// Volume calculation class -//============================================================================== - -class VolumeCalculation { -public: - // Aliases, types - struct Result { - std::array volume; //!< Mean/standard deviation of volume - std::vector nuclides; //!< Index of nuclides - std::vector atoms; //!< Number of atoms for each nuclide - std::vector uncertainty; //!< Uncertainty on number of atoms - }; // Results for a single domain - - // Constructors - VolumeCalculation(pugi::xml_node node); - - // Methods - - //! \brief Stochastically determine the volume of a set of domains along with the - //! average number densities of nuclides within the domain - // - //! \return Vector of results for each user-specified domain - std::vector execute() const; - - //! \brief Write volume calculation results to HDF5 file - // - //! \param[in] filename Path to HDF5 file to write - //! \param[in] results Vector of results for each domain - void to_hdf5(const std::string& filename, const std::vector& results) const; - - // Data members - int domain_type_; //!< Type of domain (cell, material, etc.) - int n_samples_; //!< Number of samples to use - Position lower_left_; //!< Lower-left position of bounding box - Position upper_right_; //!< Upper-right position of bounding box - std::vector domain_ids_; //!< IDs of domains to find volumes of - -private: - //! \brief Check whether a material has already been hit for a given domain. - //! If not, add new entries to the vectors - // - //! \param[in] i_material Index in global materials vector - //! \param[in,out] indices Vector of material indices - //! \param[in,out] hits Number of hits corresponding to each material - void check_hit(int i_material, std::vector& indices, - std::vector& hits) const; - -}; - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - extern std::vector volume_calcs; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void free_memory_volume(); - -} // namespace openmc - -#endif // OPENMC_VOLUME_CALC_H diff --git a/include/openmc/wmp.h b/include/openmc/wmp.h deleted file mode 100644 index 97377242a..000000000 --- a/include/openmc/wmp.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef OPENMC_WMP_H -#define OPENMC_WMP_H - -#include "hdf5.h" -#include "xtensor/xtensor.hpp" - -#include -#include -#include -#include - -namespace openmc { - -//======================================================================== -// Constants -//======================================================================== - -// Constants that determine which value to access -constexpr int MP_EA {0}; // Pole -constexpr int MP_RS {1}; // Residue scattering -constexpr int MP_RA {2}; // Residue absorption -constexpr int MP_RF {3}; // Residue fission - -// Polynomial fit indices -constexpr int FIT_S {0}; // Scattering -constexpr int FIT_A {1}; // Absorption -constexpr int FIT_F {2}; // Fission - -// Multipole HDF5 file version -constexpr std::array WMP_VERSION {1, 1}; - -//======================================================================== -// Windowed multipole data -//======================================================================== - -class WindowedMultipole { -public: - // Constructors, destructors - WindowedMultipole(hid_t group); - - // Methods - - //! \brief Evaluate the windowed multipole equations for cross sections in the - //! resolved resonance regions - //! - //! \param E Incident neutron energy in [eV] - //! \param sqrtkT Square root of temperature times Boltzmann constant - //! \return Tuple of elastic scattering, absorption, and fission cross sections in [b] - std::tuple evaluate(double E, double sqrtkT); - - //! \brief Evaluates the windowed multipole equations for the derivative of - //! cross sections in the resolved resonance regions with respect to - //! temperature. - //! - //! \param E Incident neutron energy in [eV] - //! \param sqrtkT Square root of temperature times Boltzmann constant - //! \return Tuple of derivatives of elastic scattering, absorption, and - //! fission cross sections in [b/K] - std::tuple evaluate_deriv(double E, double sqrtkT); - - // Data members - std::string name_; //!< Name of nuclide - bool fissionable_; //!< Is the nuclide fissionable? - xt::xtensor, 2> data_; //!< Poles and residues - double sqrt_awr_; //!< Square root of atomic weight ratio - double E_min_; //!< Minimum energy in [eV] - double E_max_; //!< Maximum energy in [eV] - double spacing_; //!< Spacing in sqrt(E) space - int fit_order_; //!< Order of the fit - xt::xtensor windows_; //!< Indices of pole at start/end of window - xt::xtensor curvefit_; //!< Fitting function (reaction, coeff index, window index) - xt::xtensor broaden_poly_; //!< Whether to broaden curvefit -}; - -//======================================================================== -// Non-member functions -//======================================================================== - -//! Check to make sure WMP library data version matches -//! -//! \param[in] file HDF5 file object -void check_wmp_version(hid_t file); - -//! \brief Checks for the existence of a multipole library in the directory and -//! loads it -//! -//! \param[in] i_nuclide Index in global nuclides array -void read_multipole_data(int i_nuclide); - -} // namespace openmc - -#endif // OPENMC_WMP_H diff --git a/include/openmc/xml_interface.h b/include/openmc/xml_interface.h deleted file mode 100644 index 6ab8c148c..000000000 --- a/include/openmc/xml_interface.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef OPENMC_XML_INTERFACE_H -#define OPENMC_XML_INTERFACE_H - -#include // for size_t -#include // for stringstream -#include -#include - -#include "pugixml.hpp" -#include "xtensor/xarray.hpp" -#include "xtensor/xadapt.hpp" - -namespace openmc { - -inline bool -check_for_node(pugi::xml_node node, const char *name) -{ - return node.attribute(name) || node.child(name); -} - -std::string get_node_value(pugi::xml_node node, const char* name, - bool lowercase=false, bool strip=false); - -bool get_node_value_bool(pugi::xml_node node, const char* name); - -template -std::vector get_node_array(pugi::xml_node node, const char* name, - bool lowercase=false) -{ - // Get value of node attribute/child - std::string s {get_node_value(node, name, lowercase)}; - - // Read values one by one into vector - std::stringstream iss {s}; - T value; - std::vector values; - while (iss >> value) - values.push_back(value); - - return values; -} - -template -xt::xarray get_node_xarray(pugi::xml_node node, const char* name, - bool lowercase=false) -{ - std::vector v = get_node_array(node, name, lowercase); - std::vector shape = {v.size()}; - return xt::adapt(v, shape); -} - -} // namespace openmc -#endif // OPENMC_XML_INTERFACE_H diff --git a/include/openmc/xsdata.h b/include/openmc/xsdata.h deleted file mode 100644 index a8aed5d17..000000000 --- a/include/openmc/xsdata.h +++ /dev/null @@ -1,140 +0,0 @@ -//! \file xsdata.h -//! A collection of classes for containing the Multi-Group Cross Section data - -#ifndef OPENMC_XSDATA_H -#define OPENMC_XSDATA_H - -#include -#include - -#include "xtensor/xtensor.hpp" - -#include "openmc/hdf5_interface.h" -#include "openmc/scattdata.h" - - -namespace openmc { - -//============================================================================== -// XSDATA contains the temperature-independent cross section data for an MGXS -//============================================================================== - -class XsData { - - private: - //! \brief Reads scattering data from the HDF5 file - void - scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang, - int scatter_format, int final_scatter_format, int order_data); - - //! \brief Reads fission data from the HDF5 file - void - fission_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic); - - //! \brief Reads fission data formatted as chi and nu-fission vectors from - // the HDF5 file when beta is provided. - void - fission_vector_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic); - - //! \brief Reads fission data formatted as chi and nu-fission vectors from - // the HDF5 file when beta is not provided. - void - fission_vector_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang); - - //! \brief Reads fission data formatted as chi and nu-fission vectors from - // the HDF5 file when no delayed data is provided. - void - fission_vector_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang); - - //! \brief Reads fission data formatted as a nu-fission matrix from - // the HDF5 file when beta is provided. - void - fission_matrix_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic); - - //! \brief Reads fission data formatted as a nu-fission matrix from - // the HDF5 file when beta is not provided. - void - fission_matrix_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang); - - //! \brief Reads fission data formatted as a nu-fission matrix from - // the HDF5 file when no delayed data is provided. - void - fission_matrix_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang); - - public: - - // The following quantities have the following dimensions: - // [angle][incoming group] - xt::xtensor total; - xt::xtensor absorption; - xt::xtensor nu_fission; - xt::xtensor prompt_nu_fission; - xt::xtensor kappa_fission; - xt::xtensor fission; - xt::xtensor inverse_velocity; - - // decay_rate has the following dimensions: - // [angle][delayed group] - xt::xtensor decay_rate; - // delayed_nu_fission has the following dimensions: - // [angle][delayed group][incoming group] - xt::xtensor delayed_nu_fission; - // chi_prompt has the following dimensions: - // [angle][incoming group][outgoing group] - xt::xtensor chi_prompt; - // chi_delayed has the following dimensions: - // [angle][incoming group][outgoing group][delayed group] - xt::xtensor chi_delayed; - // scatter has the following dimensions: [angle] - std::vector> scatter; - - XsData() = default; - - //! \brief Constructs the XsData object metadata. - //! - //! @param num_groups Number of energy groups. - //! @param num_delayed_groups Number of delayed groups. - //! @param fissionable Is this a fissionable data set or not. - //! @param scatter_format The scattering representation of the file. - //! @param n_pol Number of polar angles. - //! @param n_azi Number of azimuthal angles. - XsData(bool fissionable, int scatter_format, int n_pol, int n_azi); - - //! \brief Loads the XsData object from the HDF5 file - //! - //! @param xs_id HDF5 group id for the cross section data. - //! @param fissionable Is this a fissionable data set or not. - //! @param scatter_format The scattering representation of the file. - //! @param final_scatter_format The scattering representation after reading; - //! this is different from scatter_format if converting a Legendre to - //! a tabular representation. - //! @param order_data The dimensionality of the scattering data in the file. - //! @param is_isotropic Is this an isotropic or angular with respect to - //! the incoming particle. - //! @param n_pol Number of polar angles. - //! @param n_azi Number of azimuthal angles. - void - from_hdf5(hid_t xsdata_grp, bool fissionable, int scatter_format, - int final_scatter_format, int order_data, bool is_isotropic, int n_pol, - int n_azi); - - //! \brief Combines the microscopic data to a macroscopic object. - //! - //! @param micros Microscopic objects to combine. - //! @param scalars Scalars to multiply the microscopic data by. - void - combine(const std::vector& those_xs, const std::vector& scalars); - - //! \brief Checks to see if this and that are able to be combined - //! - //! This comparison is used when building macroscopic cross sections - //! from microscopic cross sections. - //! @param that The other XsData to compare to this one. - //! @return True if they can be combined. - bool - equiv(const XsData& that); -}; - - -} //namespace openmc -#endif // OPENMC_XSDATA_H diff --git a/man/man1/openmc.1 b/man/man1/openmc.1 deleted file mode 100644 index 229b64fd1..000000000 --- a/man/man1/openmc.1 +++ /dev/null @@ -1,83 +0,0 @@ -.TH openmc 1 "November 2012" " " "OpenMC" -.SH NAME -openmc \- Executes the OpenMC Monte Carlo code -.SH DESCRIPTION -This command is used to execute the OpenMC Monte Carlo code. It is assumed that -a set of XML input files has already been created and that HDF5 format cross -sections are available. -.SH SYNOPSIS -\fBopenmc\fR [\fIoptions\fR] [\fIpath\fR] -.PP -It is assumed that if no -.I path -is specified, the XML input files are present in the current directory. -.SH OPTIONS -.TP -.B "\-c\fR, \fP\-\-volume" -Run in stochastic volume calculation mode -.TP -.B "\-g\fR, \fP\-\-geometry-debug" -Run with geometry debugging turned on, where cell overlaps are checked for after -each move of a particle -.TP -.B "\-p\fR, \fP\-\-plot" -Run in plotting mode -.TP -.BI \-r " binaryFile" "\fR,\fP \-\-restart" " binaryFile" -Restart a previous run from a state point or a particle restart file named -\fIbinaryFile\fP. -.TP -.BI \-s " N" "\fR,\fP \-\-threads" " N" -Use \fIN\fP OpenMP threads. -.TP -.B "\-t\fR, \fP\-\-track" -Write tracks for all particles. -.TP -.B "\-v\fR, \fP\-\-version" -Show version information. -.TP -.B "\-h\fR, \fP\-\-help" -Show help message. -.SH ENVIRONMENT VARIABLES -The behavior of -.B openmc -is affected by the following environment variables. -.TP -.B OPENMC_CROSS_SECTIONS -Indicates the default path to the cross_sections.xml summary file that is used -to locate HDF5 format cross section libraries if the user has not specified the - tag in -.I materials.xml\fP. -.TP -.B OPENMC_MG_CROSS_SECTIONS -Indicates the default path to an HDF5 file that contains multi-group cross -section libraries if the user has not specified the tag in -.I materials.xml\fP. -.SH LICENSE -Copyright \(co 2011-2019 Massachusetts Institute of Technology and OpenMC -contributors. -.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 -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: -.PP -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -.PP -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -.SH REPORTING BUGS -The OpenMC source code is hosted on GitHub at -https://github.com/openmc-dev/openmc. With a github account, you can submit issues -directly on the github repository that will then be reviewed by OpenMC -developers. Alternatively, you can send a bug report to -.I openmc-users@googlegroups.com\fP. -.SH AUTHOR -Paul K. Romano (\fIpaul.k.romano@gmail.com\fP) diff --git a/openmc/__init__.py b/openmc/__init__.py deleted file mode 100644 index f1703dfea..000000000 --- a/openmc/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -from openmc.arithmetic import * -from openmc.cell import * -from openmc.checkvalue import * -from openmc.mesh import * -from openmc.element import * -from openmc.geometry import * -from openmc.nuclide import * -from openmc.macroscopic import * -from openmc.material import * -from openmc.plots import * -from openmc.region import * -from openmc.volume import * -from openmc.source import * -from openmc.settings import * -from openmc.surface import * -from openmc.universe import * -from openmc.lattice import * -from openmc.filter import * -from openmc.filter_expansion import * -from openmc.trigger import * -from openmc.tally_derivative import * -from openmc.tallies import * -from openmc.mgxs_library import * -from openmc.executor import * -from openmc.statepoint import * -from openmc.summary import * -from openmc.particle_restart import * -from openmc.mixin import * -from openmc.plotter import * -from openmc.search import * -from openmc.polynomial import * -from . import examples - -# Import a few convencience functions that used to be here -from openmc.model import rectangular_prism, hexagonal_prism - -__version__ = '0.11.0' diff --git a/openmc/_utils.py b/openmc/_utils.py deleted file mode 100644 index 97c253f39..000000000 --- a/openmc/_utils.py +++ /dev/null @@ -1,68 +0,0 @@ -import hashlib -import os.path -from pathlib import Path -from urllib.parse import urlparse -from urllib.request import urlopen, Request - -_BLOCK_SIZE = 16384 - - -def download(url, checksum=None, as_browser=False, **kwargs): - """Download file from a URL - - Parameters - ---------- - url : str - URL from which to download - checksum : str or None - MD5 checksum to check against - as_browser : bool - Change User-Agent header to appear as a browser - kwargs : dict - Keyword arguments passed to :func:urllib.request.urlopen - - Returns - ------- - basename : str - Name of file written locally - - """ - if as_browser: - page = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) - else: - page = url - req = urlopen(page, **kwargs) - # 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('') - - if checksum is not None: - downloadsum = hashlib.md5(open(basename, 'rb').read()).hexdigest() - if downloadsum != checksum: - raise IOError("MD5 checksum for {} does not match. If this is your first " - "time receiving this message, please re-run the script. " - "Otherwise, please contact OpenMC developers by emailing " - "openmc-users@googlegroups.com.".format(basename)) - - return basename diff --git a/openmc/_xml.py b/openmc/_xml.py deleted file mode 100644 index 9c6c219e2..000000000 --- a/openmc/_xml.py +++ /dev/null @@ -1,51 +0,0 @@ -def clean_indentation(element, level=0, spaces_per_level=2): - """ - copy and paste from http://effbot.org/zone/elementent-lib.htm#prettyprint - it basically walks your tree and adds spaces and newlines so the tree is - printed in a nice way - """ - - i = "\n" + level*spaces_per_level*" " - - if len(element): - - if not element.text or not element.text.strip(): - element.text = i + spaces_per_level*" " - - if not element.tail or not element.tail.strip(): - element.tail = i - - for sub_element in element: - clean_indentation(sub_element, level+1, spaces_per_level) - - if not sub_element.tail or not sub_element.tail.strip(): - sub_element.tail = i - - else: - if level and (not element.tail or not element.tail.strip()): - element.tail = i - - -def get_text(elem, name, default=None): - """Retrieve text of an attribute or subelement. - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - Element from which to search - name : str - Name of attribute/subelement - default : object - A defult value to return if matching attribute/subelement exists - - Returns - ------- - str - Text of attribute or subelement - - """ - if name in elem.attrib: - return elem.get(name, default) - else: - child = elem.find(name) - return child.text if child is not None else default diff --git a/openmc/arithmetic.py b/openmc/arithmetic.py deleted file mode 100644 index 91e2f1ed4..000000000 --- a/openmc/arithmetic.py +++ /dev/null @@ -1,842 +0,0 @@ -import sys -import copy -from collections.abc import Iterable - -import numpy as np -import pandas as pd - -import openmc -from openmc.filter import _FILTER_TYPES -import openmc.checkvalue as cv - - -# Acceptable tally arithmetic binary operations -_TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^'] - -# Acceptable tally aggregation operations -_TALLY_AGGREGATE_OPS = ['sum', 'avg'] - - -class CrossScore(object): - """A special-purpose tally score used to encapsulate all combinations of two - tally's scores as an outer product for tally arithmetic. - - Parameters - ---------- - left_score : str or CrossScore - The left score in the outer product - right_score : str or CrossScore - The right score in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's scores with this CrossNuclide - - Attributes - ---------- - left_score : str or CrossScore - The left score in the outer product - right_score : str or CrossScore - The right score in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's scores with this CrossScore - - """ - - def __init__(self, left_score=None, right_score=None, binary_op=None): - - self._left_score = None - self._right_score = None - self._binary_op = None - - if left_score is not None: - self.left_score = left_score - if right_score is not None: - self.right_score = right_score - if binary_op is not None: - self.binary_op = binary_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - string = '({0} {1} {2})'.format(self.left_score, - self.binary_op, self.right_score) - return string - - @property - def left_score(self): - return self._left_score - - @property - def right_score(self): - return self._right_score - - @property - def binary_op(self): - return self._binary_op - - @left_score.setter - def left_score(self, left_score): - cv.check_type('left_score', left_score, - (str, CrossScore, AggregateScore)) - self._left_score = left_score - - @right_score.setter - def right_score(self, right_score): - cv.check_type('right_score', right_score, - (str, CrossScore, AggregateScore)) - self._right_score = right_score - - @binary_op.setter - def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, str) - cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) - self._binary_op = binary_op - - -class CrossNuclide(object): - """A special-purpose nuclide used to encapsulate all combinations of two - tally's nuclides as an outer product for tally arithmetic. - - Parameters - ---------- - left_nuclide : openmc.Nuclide or CrossNuclide - The left nuclide in the outer product - right_nuclide : openmc.Nuclide or CrossNuclide - The right nuclide in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's nuclides with this CrossNuclide - - Attributes - ---------- - left_nuclide : openmc.Nuclide or CrossNuclide - The left nuclide in the outer product - right_nuclide : openmc.Nuclide or CrossNuclide - The right nuclide in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's nuclides with this CrossNuclide - - """ - - def __init__(self, left_nuclide=None, right_nuclide=None, binary_op=None): - - self._left_nuclide = None - self._right_nuclide = None - self._binary_op = None - - if left_nuclide is not None: - self.left_nuclide = left_nuclide - if right_nuclide is not None: - self.right_nuclide = right_nuclide - if binary_op is not None: - self.binary_op = binary_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - return self.name - - @property - def left_nuclide(self): - return self._left_nuclide - - @property - def right_nuclide(self): - return self._right_nuclide - - @property - def binary_op(self): - return self._binary_op - - @property - def name(self): - - string = '' - - # If the Summary was linked, the left nuclide is a Nuclide object - if isinstance(self.left_nuclide, openmc.Nuclide): - string += '(' + self.left_nuclide.name - # If the Summary was not linked, the left nuclide is the ZAID - else: - string += '(' + str(self.left_nuclide) - - string += ' ' + self.binary_op + ' ' - - # If the Summary was linked, the right nuclide is a Nuclide object - if isinstance(self.right_nuclide, openmc.Nuclide): - string += self.right_nuclide.name + ')' - # If the Summary was not linked, the right nuclide is the ZAID - else: - string += str(self.right_nuclide) + ')' - - return string - - @left_nuclide.setter - def left_nuclide(self, left_nuclide): - cv.check_type('left_nuclide', left_nuclide, - (openmc.Nuclide, CrossNuclide, AggregateNuclide)) - self._left_nuclide = left_nuclide - - @right_nuclide.setter - def right_nuclide(self, right_nuclide): - cv.check_type('right_nuclide', right_nuclide, - (openmc.Nuclide, CrossNuclide, AggregateNuclide)) - self._right_nuclide = right_nuclide - - @binary_op.setter - def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, str) - cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) - self._binary_op = binary_op - - -class CrossFilter(object): - """A special-purpose filter used to encapsulate all combinations of two - tally's filter bins as an outer product for tally arithmetic. - - Parameters - ---------- - left_filter : Filter or CrossFilter - The left filter in the outer product - right_filter : Filter or CrossFilter - The right filter in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's filter bins with this CrossFilter - - Attributes - ---------- - type : str - The type of the crossfilter (e.g., 'energy / energy') - left_filter : Filter or CrossFilter - The left filter in the outer product - right_filter : Filter or CrossFilter - The right filter in the outer product - binary_op : str - The tally arithmetic binary operator (e.g., '+', '-', etc.) used to - combine two tally's filter bins with this CrossFilter - bins : dict of Iterable - A dictionary of the bins from each filter keyed by the types of the - left / right filters - num_bins : Integral - The number of filter bins (always 1 if aggregate_filter is defined) - - """ - - def __init__(self, left_filter=None, right_filter=None, binary_op=None): - - left_type = left_filter.type - right_type = right_filter.type - self._type = '({0} {1} {2})'.format(left_type, binary_op, right_type) - - self._bins = {} - - self._left_filter = None - self._right_filter = None - self._binary_op = None - - if left_filter is not None: - self.left_filter = left_filter - self._bins['left'] = left_filter.bins - if right_filter is not None: - self.right_filter = right_filter - self._bins['right'] = right_filter.bins - if binary_op is not None: - self.binary_op = binary_op - - def __hash__(self): - return hash((self.left_filter, self.right_filter)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - - string = 'CrossFilter\n' - filter_type = '({0} {1} {2})'.format(self.left_filter.type, - self.binary_op, - self.right_filter.type) - filter_bins = '({0} {1} {2})'.format(self.left_filter.bins, - self.binary_op, - self.right_filter.bins) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', filter_type) - string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', filter_bins) - return string - - @property - def left_filter(self): - return self._left_filter - - @property - def right_filter(self): - return self._right_filter - - @property - def binary_op(self): - return self._binary_op - - @property - def type(self): - return self._type - - @property - def bins(self): - return self._bins['left'], self._bins['right'] - - @property - def num_bins(self): - if self.left_filter is not None and self.right_filter is not None: - return self.left_filter.num_bins * self.right_filter.num_bins - else: - return 0 - - @type.setter - def type(self, filter_type): - if filter_type not in _FILTER_TYPES: - msg = 'Unable to set CrossFilter type to "{0}" since it ' \ - 'is not one of the supported types'.format(filter_type) - raise ValueError(msg) - - self._type = filter_type - - @left_filter.setter - def left_filter(self, left_filter): - cv.check_type('left_filter', left_filter, - (openmc.Filter, CrossFilter, AggregateFilter)) - self._left_filter = left_filter - self._bins['left'] = left_filter.bins - - @right_filter.setter - def right_filter(self, right_filter): - cv.check_type('right_filter', right_filter, - (openmc.Filter, CrossFilter, AggregateFilter)) - self._right_filter = right_filter - self._bins['right'] = right_filter.bins - - @binary_op.setter - def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, str) - cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) - self._binary_op = binary_op - - def get_bin_index(self, filter_bin): - """Returns the index in the CrossFilter for some bin. - - Parameters - ---------- - filter_bin : 2-tuple - A 2-tuple where each value corresponds to the bin of interest - in the left and right filter, respectively. A bin is the integer - ID for 'material', 'surface', 'cell', 'cellborn', and 'universe' - Filters. The bin is an integer for the cell instance ID for - 'distribcell' Filters. The bin is a 2-tuple of floats for 'energy' - and 'energyout' filters corresponding to the energy boundaries of - the bin of interest. The bin is a (x,y,z) 3-tuple for 'mesh' - filters corresponding to the mesh cell of interest. - - Returns - ------- - filter_index : Integral - The index in the Tally data array for this filter bin. - - """ - - left_index = self.left_filter.get_bin_index(filter_bin[0]) - right_index = self.right_filter.get_bin_index(filter_bin[0]) - filter_index = left_index * self.right_filter.num_bins + right_index - return filter_index - - def get_pandas_dataframe(self, data_size, summary=None): - """Builds a Pandas DataFrame for the CrossFilter's bins. - - This method constructs a Pandas DataFrame object for the CrossFilter - with columns annotated by filter bin information. This is a helper - method for the Tally.get_pandas_dataframe(...) method. This method - recursively builds and concatenates Pandas DataFrames for the left - and right filters and crossfilters. - - This capability has been tested for Pandas >=0.13.1. However, it is - recommended to use v0.16 or newer versions of Pandas since this method - uses Pandas' Multi-index functionality. - - Parameters - ---------- - data_size : Integral - The total number of bins in the tally corresponding to this filter - summary : None or Summary - An optional Summary object to be used to construct columns for - distribcell tally filters (default is None). The geometric - information in the Summary object is embedded into a Multi-index - column with a geometric "path" to each distribcell instance. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with columns of strings that characterize the - crossfilter's bins. Each entry in the DataFrame will include one - or more binary operations used to construct the crossfilter's bins. - The number of rows in the DataFrame is the same as the total number - of bins in the corresponding tally, with the filter bins - appropriately tiled to map to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe() - - """ - - # If left and right filters are identical, do not combine bins - if self.left_filter == self.right_filter: - df = self.left_filter.get_pandas_dataframe(data_size, summary) - - # If left and right filters are different, combine their bins - else: - left_df = self.left_filter.get_pandas_dataframe(data_size, summary) - right_df = self.right_filter.get_pandas_dataframe(data_size, summary) - left_df = left_df.astype(str) - right_df = right_df.astype(str) - df = '(' + left_df + ' ' + self.binary_op + ' ' + right_df + ')' - - return df - -class AggregateScore(object): - """A special-purpose tally score used to encapsulate an aggregate of a - subset or all of tally's scores for tally aggregation. - - Parameters - ---------- - scores : Iterable of str or CrossScore - The scores included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally's scores with this AggregateScore - - Attributes - ---------- - scores : Iterable of str or CrossScore - The scores included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally's scores with this AggregateScore - - """ - - def __init__(self, scores=None, aggregate_op=None): - - self._scores = None - self._aggregate_op = None - - if scores is not None: - self.scores = scores - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - string = ', '.join(map(str, self.scores)) - string = '{0}({1})'.format(self.aggregate_op, string) - return string - - @property - def scores(self): - return self._scores - - @property - def aggregate_op(self): - return self._aggregate_op - - @property - def name(self): - - # Append each score in the aggregate to the string - string = '(' + ', '.join(self.scores) + ')' - return string - - @scores.setter - def scores(self, scores): - 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, (str, CrossScore)) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - -class AggregateNuclide(object): - """A special-purpose tally nuclide used to encapsulate an aggregate of a - subset or all of tally's nuclides for tally aggregation. - - Parameters - ---------- - nuclides : Iterable of str or openmc.Nuclide or CrossNuclide - The nuclides included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally's nuclides with this AggregateNuclide - - Attributes - ---------- - nuclides : Iterable of str or openmc.Nuclide or CrossNuclide - The nuclides included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally's nuclides with this AggregateNuclide - - """ - - def __init__(self, nuclides=None, aggregate_op=None): - - self._nuclides = None - self._aggregate_op = None - - if nuclides is not None: - self.nuclides = nuclides - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - - # Append each nuclide in the aggregate to the string - string = '{0}('.format(self.aggregate_op) - names = [nuclide.name if isinstance(nuclide, openmc.Nuclide) - else str(nuclide) for nuclide in self.nuclides] - string += ', '.join(map(str, names)) + ')' - return string - - @property - def nuclides(self): - return self._nuclides - - @property - def aggregate_op(self): - return self._aggregate_op - - @property - def name(self): - - # Append each nuclide in the aggregate to the string - names = [nuclide.name if isinstance(nuclide, openmc.Nuclide) - else str(nuclide) for nuclide in self.nuclides] - string = '(' + ', '.join(map(str, names)) + ')' - return string - - @nuclides.setter - def nuclides(self, nuclides): - 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, str) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - -class AggregateFilter(object): - """A special-purpose tally filter used to encapsulate an aggregate of a - subset or all of a tally filter's bins for tally aggregation. - - Parameters - ---------- - aggregate_filter : Filter or CrossFilter - The filter included in the aggregation - bins : Iterable of tuple - The filter bins included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally filter's bins with this AggregateFilter - - Attributes - ---------- - type : str - The type of the aggregatefilter (e.g., 'sum(energy)', 'sum(cell)') - aggregate_filter : filter - The filter included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'avg', etc.) used - to aggregate across a tally filter's bins with this AggregateFilter - bins : Iterable of tuple - The filter bins included in the aggregation - num_bins : Integral - The number of filter bins (always 1 if aggregate_filter is defined) - - """ - - def __init__(self, aggregate_filter=None, bins=None, aggregate_op=None): - - self._type = '{0}({1})'.format(aggregate_op, - aggregate_filter.short_name.lower()) - self._bins = None - - self._aggregate_filter = None - self._aggregate_op = None - - if aggregate_filter is not None: - self.aggregate_filter = aggregate_filter - if bins is not None: - self.bins = bins - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __gt__(self, other): - if self.type != other.type: - if self.aggregate_filter.type in _FILTER_TYPES and \ - other.aggregate_filter.type in _FILTER_TYPES: - delta = _FILTER_TYPES.index(self.aggregate_filter.type) - \ - _FILTER_TYPES.index(other.aggregate_filter.type) - return delta > 0 - else: - return False - else: - return False - - def __lt__(self, other): - return not self > other - - def __repr__(self): - string = 'AggregateFilter\n' - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type) - string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins) - return string - - @property - def aggregate_filter(self): - return self._aggregate_filter - - @property - def aggregate_op(self): - return self._aggregate_op - - @property - def type(self): - return self._type - - @property - def bins(self): - return self._bins - - @property - def num_bins(self): - return len(self.bins) if self.aggregate_filter else 0 - - @type.setter - def type(self, filter_type): - if filter_type not in _FILTER_TYPES: - msg = 'Unable to set AggregateFilter type to "{0}" since it ' \ - 'is not one of the supported types'.format(filter_type) - raise ValueError(msg) - - self._type = filter_type - - @aggregate_filter.setter - def aggregate_filter(self, aggregate_filter): - cv.check_type('aggregate_filter', aggregate_filter, - (openmc.Filter, CrossFilter)) - self._aggregate_filter = aggregate_filter - - @bins.setter - def bins(self, bins): - cv.check_iterable_type('bins', bins, Iterable) - self._bins = list(map(tuple, bins)) - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, str) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - def get_bin_index(self, filter_bin): - """Returns the index in the AggregateFilter for some bin. - - Parameters - ---------- - filter_bin : Integral or tuple of Real - A tuple of value(s) corresponding to the bin of interest in - the aggregated filter. The bin is the integer ID for 'material', - 'surface', 'cell', 'cellborn', and 'universe' Filters. The bin - is the integer cell instance ID for 'distribcell' Filters. The - bin is a 2-tuple of floats for 'energy' and 'energyout' filters - corresponding to the energy boundaries of the bin of interest. - The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to - the mesh cell of interest. - - Returns - ------- - filter_index : Integral - The index in the Tally data array for this filter bin. For an - AggregateTally the filter bin index is always unity. - - Raises - ------ - ValueError - When the filter_bin is not part of the aggregated filter's bins - - """ - - if filter_bin not in self.bins: - msg = 'Unable to get the bin index for AggregateFilter since ' \ - '"{0}" is not one of the bins'.format(filter_bin) - raise ValueError(msg) - else: - return self.bins.index(filter_bin) - - 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 - with columns annotated by filter bin information. This is a helper - method for the Tally.get_pandas_dataframe(...) method. - - Parameters - ---------- - 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 - is not used by the AggregateFilter and simply mirrors the method - signature for the CrossFilter. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with columns of strings that characterize the - aggregatefilter's bins. Each entry in the DataFrame will include - one or more aggregation operations used to construct the - aggregatefilter's bins. The number of rows in the DataFrame is the - same as the total number of bins in the corresponding tally, with - the filter bins appropriately tiled to map to the corresponding - tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe(), - CrossFilter.get_pandas_dataframe() - - """ - # Create NumPy array of the bin tuples for repeating / tiling - filter_bins = np.empty(self.num_bins, dtype=tuple) - for i, bin in enumerate(self.bins): - filter_bins[i] = bin - - # Repeat and tile bins as needed for DataFrame - filter_bins = np.repeat(filter_bins, stride) - tile_factor = data_size / len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - - # Create DataFrame with aggregated bins - df = pd.DataFrame({self.type: filter_bins}) - return df - - def can_merge(self, other): - """Determine if AggregateFilter can be merged with another. - - Parameters - ---------- - other : AggregateFilter - Filter to compare with - - Returns - ------- - bool - Whether the filter can be merged - - """ - - if not isinstance(other, AggregateFilter): - return False - - # Filters must be of the same type - elif self.type != other.type: - return False - - # None of the bins in this filter should match in the other filter - for bin in self.bins: - if bin in other.bins: - return False - - # If all conditional checks passed then filters are mergeable - return True - - def merge(self, other): - """Merge this aggregatefilter with another. - - Parameters - ---------- - other : AggregateFilter - Filter to merge with - - Returns - ------- - merged_filter : AggregateFilter - Filter resulting from the merge - - """ - - if not self.can_merge(other): - msg = 'Unable to merge "{0}" with "{1}" ' \ - 'filters'.format(self.type, other.type) - raise ValueError(msg) - - # Create deep copy of filter to return as merged filter - merged_filter = copy.deepcopy(self) - - # Merge unique filter bins - merged_bins = self.bins + other.bins - - # Sort energy bin edges - if 'energy' in self.type: - merged_bins = sorted(merged_bins) - - # Assign merged bins to merged filter - merged_filter.bins = list(merged_bins) - return merged_filter diff --git a/openmc/cell.py b/openmc/cell.py deleted file mode 100644 index 3fd70b345..000000000 --- a/openmc/cell.py +++ /dev/null @@ -1,582 +0,0 @@ -from collections import OrderedDict -from collections.abc import Iterable -from copy import deepcopy -from math import cos, sin, pi -from numbers import Real, Integral -from xml.etree import ElementTree as ET -import sys -import warnings - -import numpy as np - -import openmc -import openmc.checkvalue as cv -from openmc.surface import Halfspace -from openmc.region import Region, Intersection, Complement -from openmc._xml import get_text -from .mixin import IDManagerMixin - - -class Cell(IDManagerMixin): - r"""A region of space defined as the intersection of half-space created by - quadric surfaces. - - Parameters - ---------- - cell_id : int, optional - Unique identifier for the cell. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the cell. If not specified, the name is the empty string. - fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material, optional - Indicates what the region of space is filled with - region : openmc.Region, optional - Region of space that is assigned to the cell. - - Attributes - ---------- - id : int - Unique identifier for the cell - name : str - Name of the cell - fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material - Indicates what the region of space is filled with. If None, the cell is - treated as a void. An iterable of materials is used to fill repeated - instances of a cell with different materials. - fill_type : {'material', 'universe', 'lattice', 'distribmat', 'void'} - Indicates what the cell is filled with. - region : openmc.Region or None - Region of space that is assigned to the cell. - rotation : Iterable of float - If the cell is filled with a universe, this array specifies the angles - in degrees about the x, y, and z axes that the filled universe should be - rotated. The rotation applied is an intrinsic rotation with specified - Tait-Bryan angles. That is to say, if the angles are :math:`(\phi, - \theta, \psi)`, then the rotation matrix applied is :math:`R_z(\psi) - R_y(\theta) R_x(\phi)` or - - .. math:: - - \left [ \begin{array}{ccc} \cos\theta \cos\psi & -\cos\phi \sin\psi - + \sin\phi \sin\theta \cos\psi & \sin\phi \sin\psi + \cos\phi - \sin\theta \cos\psi \\ \cos\theta \sin\psi & \cos\phi \cos\psi + - \sin\phi \sin\theta \sin\psi & -\sin\phi \cos\psi + \cos\phi - \sin\theta \sin\psi \\ -\sin\theta & \sin\phi \cos\theta & \cos\phi - \cos\theta \end{array} \right ] - rotation_matrix : numpy.ndarray - The rotation matrix defined by the angles specified in the - :attr:`Cell.rotation` property. - temperature : float or iterable of float - Temperature of the cell in Kelvin. Multiple temperatures can be given - to give each distributed cell instance a unique temperature. - translation : Iterable of float - If the cell is filled with a universe, this array specifies a vector - that is used to translate (shift) the universe. - paths : list of str - The paths traversed through the CSG tree to reach each cell - instance. This property is initialized by calling the - :meth:`Geometry.determine_paths` method. - num_instances : int - The number of instances of this cell throughout the geometry. - volume : float - Volume of the cell in cm^3. This can either be set manually or - calculated in a stochastic volume calculation and added via the - :meth:`Cell.add_volume_information` method. - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, cell_id=None, name='', fill=None, region=None): - # Initialize Cell class attributes - self.id = cell_id - self.name = name - self.fill = fill - self.region = region - self._rotation = None - self._rotation_matrix = None - self._temperature = None - self._translation = None - self._paths = None - self._num_instances = None - self._volume = None - self._atoms = None - - def __contains__(self, point): - if self.region is None: - return True - else: - return point in self.region - - def __repr__(self): - string = 'Cell\n' - string += '{: <16}=\t{}\n'.format('\tID', self.id) - string += '{: <16}=\t{}\n'.format('\tName', self.name) - - if self.fill_type == 'material': - string += '{: <16}=\tMaterial {}\n'.format('\tFill', self.fill.id) - elif self.fill_type == 'void': - string += '{: <16}=\tNone\n'.format('\tFill') - elif self.fill_type == 'distribmat': - string += '{: <16}=\t{}\n'.format('\tFill', list(map( - lambda m: m if m is None else m.id, self.fill))) - else: - string += '{: <16}=\t{}\n'.format('\tFill', self.fill.id) - - string += '{: <16}=\t{}\n'.format('\tRegion', self.region) - string += '{: <16}=\t{}\n'.format('\tRotation', self.rotation) - if self.fill_type == 'material': - string += '\t{0: <15}=\t{1}\n'.format('Temperature', - self.temperature) - string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) - - return string - - @property - def name(self): - return self._name - - @property - def fill(self): - return self._fill - - @property - def fill_type(self): - if isinstance(self.fill, openmc.Material): - return 'material' - elif isinstance(self.fill, openmc.Universe): - return 'universe' - elif isinstance(self.fill, openmc.Lattice): - return 'lattice' - elif isinstance(self.fill, Iterable): - return 'distribmat' - else: - return 'void' - - @property - def region(self): - return self._region - - @property - def rotation(self): - return self._rotation - - @property - def rotation_matrix(self): - return self._rotation_matrix - - @property - def temperature(self): - return self._temperature - - @property - def translation(self): - return self._translation - - @property - def volume(self): - return self._volume - - @property - def paths(self): - if self._paths is None: - raise ValueError('Cell instance paths have not been determined. ' - 'Call the Geometry.determine_paths() method.') - return self._paths - - @property - def bounding_box(self): - if self.region is not None: - return self.region.bounding_box - else: - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - @property - def num_instances(self): - if self._num_instances is None: - raise ValueError( - 'Number of cell instances have not been determined. Call the ' - 'Geometry.determine_paths() method.') - return self._num_instances - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('cell name', name, str) - self._name = name - else: - self._name = '' - - @fill.setter - def fill(self, fill): - if fill is not None: - if isinstance(fill, Iterable): - for i, f in enumerate(fill): - if f is not None: - cv.check_type('cell.fill[i]', f, openmc.Material) - - elif not isinstance(fill, (openmc.Material, openmc.Lattice, - openmc.Universe)): - msg = 'Unable to set Cell ID="{0}" to use a non-Material or ' \ - 'Universe fill "{1}"'.format(self._id, fill) - raise ValueError(msg) - - self._fill = fill - - @rotation.setter - def rotation(self, rotation): - cv.check_type('cell rotation', rotation, Iterable, Real) - cv.check_length('cell rotation', rotation, 3) - self._rotation = np.asarray(rotation) - - # Save rotation matrix -- the reason we do this instead of having it be - # automatically calculated when the rotation_matrix property is accessed - # is so that plotting on a rotated geometry can be done faster. - phi, theta, psi = self.rotation*(-pi/180.) - c3, s3 = cos(phi), sin(phi) - c2, s2 = cos(theta), sin(theta) - c1, s1 = cos(psi), sin(psi) - self._rotation_matrix = np.array([ - [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], - [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], - [-s2, c2*s3, c2*c3]]) - - @translation.setter - def translation(self, translation): - cv.check_type('cell translation', translation, Iterable, Real) - cv.check_length('cell translation', translation, 3) - self._translation = np.asarray(translation) - - @temperature.setter - def temperature(self, temperature): - # Make sure temperatures are positive - cv.check_type('cell temperature', temperature, (Iterable, Real)) - if isinstance(temperature, Iterable): - cv.check_type('cell temperature', temperature, Iterable, Real) - for T in temperature: - cv.check_greater_than('cell temperature', T, 0.0, True) - else: - cv.check_greater_than('cell temperature', temperature, 0.0, True) - - # If this cell is filled with a universe or lattice, propagate - # temperatures to all cells contained. Otherwise, simply assign it. - if self.fill_type in ('universe', 'lattice'): - for c in self.get_all_cells().values(): - if c.fill_type == 'material': - c._temperature = temperature - else: - self._temperature = temperature - - @region.setter - def region(self, region): - if region is not None: - cv.check_type('cell region', region, Region) - self._region = region - - @volume.setter - def volume(self, volume): - if volume is not None: - cv.check_type('cell volume', volume, Real) - self._volume = volume - - def add_volume_information(self, volume_calc): - """Add volume information to a cell. - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if volume_calc.domain_type == 'cell': - if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id].n - self._atoms = volume_calc.atoms[self.id] - else: - raise ValueError('No volume information found for this cell.') - else: - raise ValueError('No volume information found for this cell.') - - def get_nuclides(self): - """Returns all nuclides in the cell - - Returns - ------- - nuclides : list of str - List of nuclide names - - """ - return self.fill.get_nuclides() if self.fill_type != 'void' else [] - - def get_nuclide_densities(self): - """Return all nuclides contained in the cell and their densities - - Returns - ------- - nuclides : collections.OrderedDict - Dictionary whose keys are nuclide names and values are 2-tuples of - (nuclide, density) - - """ - - nuclides = OrderedDict() - - if self.fill_type == 'material': - nuclides.update(self.fill.get_nuclide_densities()) - elif self.fill_type == 'void': - pass - else: - if self._atoms is not None: - volume = self.volume - for name, atoms in self._atoms.items(): - nuclide = openmc.Nuclide(name) - density = 1.0e-24 * atoms.n/volume # density in atoms/b-cm - nuclides[name] = (nuclide, density) - else: - raise RuntimeError( - 'Volume information is needed to calculate microscopic cross ' - 'sections for cell {}. This can be done by running a ' - 'stochastic volume calculation via the ' - 'openmc.VolumeCalculation object'.format(self.id)) - - return nuclides - - def get_all_cells(self): - """Return all cells that are contained within this one if it is filled with a - universe or lattice - - Returns - ------- - cells : collections.orderedDict - Dictionary whose keys are cell IDs and values are :class:`Cell` - instances - - """ - - cells = OrderedDict() - - if self.fill_type in ('universe', 'lattice'): - cells.update(self.fill.get_all_cells()) - - return cells - - def get_all_materials(self): - """Return all materials that are contained within the cell - - Returns - ------- - materials : collections.OrderedDict - Dictionary whose keys are material IDs and values are - :class:`Material` instances - - """ - materials = OrderedDict() - if self.fill_type == 'material': - materials[self.fill.id] = self.fill - elif self.fill_type == 'distribmat': - for m in self.fill: - if m is not None: - materials[m.id] = m - else: - # Append all Cells in each Cell in the Universe to the dictionary - cells = self.get_all_cells() - for cell in cells.values(): - materials.update(cell.get_all_materials()) - - return materials - - def get_all_universes(self): - """Return all universes that are contained within this one if any of - its cells are filled with a universe or lattice. - - Returns - ------- - universes : collections.OrderedDict - Dictionary whose keys are universe IDs and values are - :class:`Universe` instances - - """ - - universes = OrderedDict() - - if self.fill_type == 'universe': - universes[self.fill.id] = self.fill - universes.update(self.fill.get_all_universes()) - elif self.fill_type == 'lattice': - universes.update(self.fill.get_all_universes()) - - return universes - - def clone(self, memo=None): - """Create a copy of this cell with a new unique ID, and clones - the cell's region and fill. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Cell - The clone of this cell - - """ - - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - # Temporarily remove paths - paths = self._paths - self._paths = None - - clone = deepcopy(self) - clone.id = None - clone._num_instances = None - - # Restore paths on original instance - self._paths = paths - - if self.region is not None: - clone.region = self.region.clone(memo) - if self.fill is not None: - if self.fill_type == 'distribmat': - clone.fill = [fill.clone(memo) if fill is not None else None - for fill in self.fill] - else: - clone.fill = self.fill.clone(memo) - - # Memoize the clone - memo[self] = clone - - return memo[self] - - def create_xml_subelement(self, xml_element): - element = ET.Element("cell") - element.set("id", str(self.id)) - - if len(self._name) > 0: - element.set("name", str(self.name)) - - if self.fill_type == 'void': - element.set("material", "void") - - elif self.fill_type == 'material': - element.set("material", str(self.fill.id)) - - elif self.fill_type == 'distribmat': - element.set("material", ' '.join(['void' if m is None else str(m.id) - for m in self.fill])) - - elif self.fill_type in ('universe', 'lattice'): - element.set("fill", str(self.fill.id)) - self.fill.create_xml_subelement(xml_element) - - if self.region is not None: - # Set the region attribute with the region specification - region = str(self.region) - if region.startswith('('): - region = region[1:-1] - if len(region) > 0: - element.set("region", region) - - # Only surfaces that appear in a region are added to the geometry - # file, so the appropriate check is performed here. First we create - # a function which is called recursively to navigate through the CSG - # tree. When it reaches a leaf (a Halfspace), it creates a - # element for the corresponding surface if none has been created - # thus far. - def create_surface_elements(node, element): - if isinstance(node, Halfspace): - path = "./surface[@id='{}']".format(node.surface.id) - if xml_element.find(path) is None: - xml_element.append(node.surface.to_xml_element()) - elif isinstance(node, Complement): - create_surface_elements(node.node, element) - else: - for subnode in node: - create_surface_elements(subnode, element) - - # Call the recursive function from the top node - create_surface_elements(self.region, xml_element) - - if self.temperature is not None: - if isinstance(self.temperature, Iterable): - element.set("temperature", ' '.join( - str(t) for t in self.temperature)) - else: - element.set("temperature", str(self.temperature)) - - if self.translation is not None: - element.set("translation", ' '.join(map(str, self.translation))) - - if self.rotation is not None: - element.set("rotation", ' '.join(map(str, self.rotation))) - - return element - - @classmethod - def from_xml_element(cls, elem, surfaces, materials, get_universe): - """Generate cell from XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - `` element - surfaces : dict - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - materials : dict - Dictionary mapping material IDs to :class:`openmc.Material` - instances (defined in :math:`openmc.Geometry.from_xml`) - get_universe : function - Function returning universe (defined in - :meth:`openmc.Geometry.from_xml`) - - Returns - ------- - Cell - Cell instance - - """ - cell_id = int(get_text(elem, 'id')) - name = get_text(elem, 'name') - c = cls(cell_id, name) - - # Assign material/distributed materials or fill - mat_text = get_text(elem, 'material') - if mat_text is not None: - mat_ids = mat_text.split() - if len(mat_ids) > 1: - c.fill = [materials[i] for i in mat_ids] - else: - c.fill = materials[mat_ids[0]] - else: - fill_id = int(get_text(elem, 'fill')) - c.fill = get_universe(fill_id) - - # Assign region - region = get_text(elem, 'region') - if region is not None: - c.region = Region.from_expression(region, surfaces) - - # Check for other attributes - t = get_text(elem, 'temperature') - if t is not None: - if ' ' in t: - c.temperature = [float(t_i) for t_i in t.split()] - else: - c.temperature = float(t) - for key in ('temperature', 'rotation', 'translation'): - value = get_text(elem, key) - if value is not None: - setattr(c, key, [float(x) for x in value.split()]) - - # Add this cell to appropriate universe - univ_id = int(get_text(elem, 'universe', 0)) - get_universe(univ_id).add_cell(c) - return c diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py deleted file mode 100644 index cbeac9c37..000000000 --- a/openmc/checkvalue.py +++ /dev/null @@ -1,337 +0,0 @@ -import copy -from collections.abc import Iterable - -import numpy as np - - -def check_type(name, value, expected_type, expected_iter_type=None): - """Ensure that an object is of an expected type. Optionally, if the object is - iterable, check that each element is of a particular type. - - Parameters - ---------- - name : str - Description of value being checked - value : object - Object to check type of - expected_type : type or Iterable of type - type to check object against - expected_iter_type : type or Iterable of type or None, optional - Expected type of each element in value, assuming it is iterable. If - None, no check will be performed. - - """ - - if not isinstance(value, expected_type): - if isinstance(expected_type, Iterable): - msg = 'Unable to set "{0}" to "{1}" which is not one of the ' \ - 'following types: "{2}"'.format(name, value, ', '.join( - [t.__name__ for t in expected_type])) - else: - msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format( - name, value, expected_type.__name__) - raise TypeError(msg) - - if expected_iter_type: - if isinstance(value, np.ndarray): - if not issubclass(value.dtype.type, expected_iter_type): - msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ - 'of type "{2}"'.format(name, value, - expected_iter_type.__name__) - else: - return - - for item in value: - if not isinstance(item, expected_iter_type): - if isinstance(expected_iter_type, Iterable): - msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ - 'one of the following types: "{2}"'.format( - name, value, ', '.join([t.__name__ for t in - expected_iter_type])) - else: - msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ - 'of type "{2}"'.format(name, value, - expected_iter_type.__name__) - raise TypeError(msg) - - -def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1): - """Ensure that an object is an iterable containing an expected type. - - Parameters - ---------- - name : str - Description of value being checked - value : Iterable - Iterable, possibly of other iterables, that should ultimately contain - the expected type - expected_type : type - type that the iterable should contain - min_depth : int - The minimum number of layers of nested iterables there should be before - reaching the ultimately contained items - max_depth : int - The maximum number of layers of nested iterables there should be before - reaching the ultimately contained items - """ - # Initialize the tree at the very first item. - tree = [value] - index = [0] - - # Traverse the tree. - while index[0] != len(tree[0]): - # If we are done with this level of the tree, go to the next branch on - # the level above this one. - if index[-1] == len(tree[-1]): - del index[-1] - del tree[-1] - index[-1] += 1 - continue - - # Get a string representation of the current index in case we raise an - # exception. - form = '[' + '{:d}, '*(len(index)-1) + '{:d}]' - ind_str = form.format(*index) - - # What is the current item we are looking at? - current_item = tree[-1][index[-1]] - - # If this item is of the expected type, then we've reached the bottom - # level of this branch. - if isinstance(current_item, expected_type): - # Is this deep enough? - if len(tree) < min_depth: - msg = 'Error setting "{0}": The item at {1} does not meet the '\ - 'minimum depth of {2}'.format(name, ind_str, min_depth) - raise TypeError(msg) - - # This item is okay. Move on to the next item. - index[-1] += 1 - - # If this item is not of the expected type, then it's either an error or - # another level of the tree that we need to pursue deeper. - else: - if isinstance(current_item, Iterable): - # The tree goes deeper here, let's explore it. - tree.append(current_item) - index.append(0) - - # But first, have we exceeded the max depth? - if len(tree) > max_depth: - msg = 'Error setting {0}: Found an iterable at {1}, items '\ - 'in that iterable exceed the maximum depth of {2}' \ - .format(name, ind_str, max_depth) - raise TypeError(msg) - - else: - # This item is completely unexpected. - msg = "Error setting {0}: Items must be of type '{1}', but " \ - "item at {2} is of type '{3}'"\ - .format(name, expected_type.__name__, ind_str, - type(current_item).__name__) - raise TypeError(msg) - - -def check_length(name, value, length_min, length_max=None): - """Ensure that a sized object has length within a given range. - - Parameters - ---------- - name : str - Description of value being checked - value : collections.Sized - Object to check length of - length_min : int - Minimum length of object - length_max : int or None, optional - Maximum length of object. If None, it is assumed object must be of - length length_min. - - """ - - if length_max is None: - if len(value) != length_min: - msg = 'Unable to set "{0}" to "{1}" since it must be of ' \ - 'length "{2}"'.format(name, value, length_min) - raise ValueError(msg) - elif not length_min <= len(value) <= length_max: - if length_min == length_max: - msg = 'Unable to set "{0}" to "{1}" since it must be of ' \ - 'length "{2}"'.format(name, value, length_min) - else: - msg = 'Unable to set "{0}" to "{1}" since it must have length ' \ - 'between "{2}" and "{3}"'.format(name, value, length_min, - length_max) - raise ValueError(msg) - - -def check_value(name, value, accepted_values): - """Ensure that an object's value is contained in a set of acceptable values. - - Parameters - ---------- - name : str - Description of value being checked - value : collections.Iterable - Object to check - accepted_values : collections.Container - Container of acceptable values - - """ - - if value not in accepted_values: - msg = 'Unable to set "{0}" to "{1}" since it is not in "{2}"'.format( - name, value, accepted_values) - raise ValueError(msg) - -def check_less_than(name, value, maximum, equality=False): - """Ensure that an object's value is less than a given value. - - Parameters - ---------- - name : str - Description of the value being checked - value : object - Object to check - maximum : object - Maximum value to check against - equality : bool, optional - Whether equality is allowed. Defaults to False. - - """ - - if equality: - if value > maximum: - msg = 'Unable to set "{0}" to "{1}" since it is greater than ' \ - '"{2}"'.format(name, value, maximum) - raise ValueError(msg) - else: - if value >= maximum: - msg = 'Unable to set "{0}" to "{1}" since it is greater than ' \ - 'or equal to "{2}"'.format(name, value, maximum) - raise ValueError(msg) - -def check_greater_than(name, value, minimum, equality=False): - """Ensure that an object's value is greater than a given value. - - Parameters - ---------- - name : str - Description of the value being checked - value : object - Object to check - minimum : object - Minimum value to check against - equality : bool, optional - Whether equality is allowed. Defaults to False. - - """ - - if equality: - if value < minimum: - msg = 'Unable to set "{0}" to "{1}" since it is less than ' \ - '"{2}"'.format(name, value, minimum) - raise ValueError(msg) - else: - if value <= minimum: - msg = 'Unable to set "{0}" to "{1}" since it is less than ' \ - 'or equal to "{2}"'.format(name, value, minimum) - raise ValueError(msg) - - -def check_filetype_version(obj, expected_type, expected_version): - """Check filetype and version of an HDF5 file. - - Parameters - ---------- - obj : h5py.File - HDF5 file to check - expected_type : str - Expected file type, e.g. 'statepoint' - expected_version : int - Expected major version number. - - """ - try: - this_filetype = obj.attrs['filetype'].decode() - this_version = obj.attrs['version'] - - # Check filetype - if this_filetype != expected_type: - raise IOError('{} is not a {} file.'.format( - obj.filename, expected_type)) - - # Check version - if this_version[0] != expected_version: - raise IOError('{} file has a version of {} which is not ' - 'consistent with the version expected by OpenMC, {}' - .format(this_filetype, - '.'.join(str(v) for v in this_version), - expected_version)) - except AttributeError: - raise IOError('Could not read {} file. This most likely means the {} ' - 'file was produced by a different version of OpenMC than ' - 'the one you are using.'.format(expected_type)) - - -class CheckedList(list): - """A list for which each element is type-checked as it's added - - Parameters - ---------- - expected_type : type or Iterable of type - Type(s) which each element should be - name : str - Name of data being checked - items : Iterable, optional - Items to initialize the list with - - """ - - def __init__(self, expected_type, name, items=[]): - super().__init__() - self.expected_type = expected_type - self.name = name - for item in items: - self.append(item) - - def __add__(self, other): - new_instance = copy.copy(self) - new_instance += other - return new_instance - - def __radd__(self, other): - return self + other - - def __iadd__(self, other): - check_type('CheckedList add operand', other, Iterable, - self.expected_type) - for item in other: - self.append(item) - return self - - def append(self, item): - """Append item to list - - Parameters - ---------- - item : object - Item to append - - """ - check_type(self.name, item, self.expected_type) - super().append(item) - - def insert(self, index, item): - """Insert item before index - - Parameters - ---------- - index : int - Index in list - item : object - Item to insert - - """ - check_type(self.name, item, self.expected_type) - super().insert(index, item) diff --git a/openmc/cmfd.py b/openmc/cmfd.py deleted file mode 100644 index b215d2058..000000000 --- a/openmc/cmfd.py +++ /dev/null @@ -1,3072 +0,0 @@ -"""This module can be used to specify parameters used for coarse mesh finite -difference (CMFD) acceleration in OpenMC. CMFD was first proposed by [Smith]_ -and is widely used in accelerating neutron transport problems. - -References ----------- - -.. [Smith] K. Smith, "Nodal method storage reduction by non-linear - iteration", *Trans. Am. Nucl. Soc.*, **44**, 265 (1983). - -""" - -from contextlib import contextmanager -from collections.abc import Iterable, Mapping -from numbers import Real, Integral -import sys -import time -from ctypes import c_int -import warnings - -import numpy as np -from scipy import sparse -import h5py - -import openmc.lib -from openmc.checkvalue import (check_type, check_length, check_value, - check_greater_than, check_less_than) -from openmc.exceptions import OpenMCError - -# See if mpi4py module can be imported, define have_mpi global variable -try: - from mpi4py import MPI - have_mpi = True -except ImportError: - have_mpi = False - -# Maximum/minimum neutron energies -_ENERGY_MAX_NEUTRON = np.inf -_ENERGY_MIN_NEUTRON = 0. - -# Tolerance for detecting zero flux values -_TINY_BIT = 1.e-8 - -# For non-accelerated regions on coarse mesh overlay -_CMFD_NOACCEL = -1 - -# Constant to represent a zero flux "albedo" -_ZERO_FLUX = 999.0 - -# Map that returns index of current direction in numpy current matrix -_CURRENTS = { - 'out_left': 0, 'in_left': 1, 'out_right': 2, 'in_right': 3, - 'out_back': 4, 'in_back': 5, 'out_front': 6, 'in_front': 7, - 'out_bottom': 8, 'in_bottom': 9, 'out_top': 10, 'in_top': 11 -} - - -class CMFDMesh(object): - """A structured Cartesian mesh used for CMFD acceleration. - - Attributes - ---------- - lower_left : Iterable of float - The lower-left corner of the structured mesh. If only two coordinates - are given, it is assumed that the mesh is an x-y mesh. - upper_right : Iterable of float - The upper-right corner of the structrued mesh. If only two coordinates - are given, it is assumed that the mesh is an x-y mesh. - dimension : Iterable of int - The number of mesh cells in each direction. - width : Iterable of float - The width of mesh cells in each direction. - energy : Iterable of float - Energy bins in eV, listed in ascending order (e.g. [0.0, 0.625e-1, - 20.0e6]) for CMFD tallies and acceleration. If no energy bins are - listed, OpenMC automatically assumes a one energy group calculation - over the entire energy range. - albedo : Iterable of float - Surface ratio of incoming to outgoing partial currents on global - boundary conditions. They are listed in the following order: -x +x -y - +y -z +z. - map : Iterable of int - An optional acceleration map can be specified to overlay on the coarse - mesh spatial grid. If this option is used, a ``0`` is used for a - non-accelerated region and a ``1`` is used for an accelerated region. - For a simple 4x4 coarse mesh with a 2x2 fuel lattice surrounded by - reflector, the map is: - - :: - - [0, 0, 0, 0, - 0, 1, 1, 0, - 0, 1, 1, 0, - 0, 0, 0, 0] - - Therefore a 2x2 system of equations is solved rather than a 4x4. This - is extremely important to use in reflectors as neutrons will not - contribute to any tallies far away from fission source neutron regions. - A ``1`` must be used to identify any fission source region. - - """ - - def __init__(self): - self._lower_left = None - self._upper_right = None - self._dimension = None - self._width = None - self._energy = None - self._albedo = None - self._map = None - - @property - def lower_left(self): - return self._lower_left - - @property - def upper_right(self): - return self._upper_right - - @property - def dimension(self): - return self._dimension - - @property - def width(self): - return self._width - - @property - def energy(self): - return self._energy - - @property - def albedo(self): - return self._albedo - - @property - def map(self): - return self._map - - @lower_left.setter - def lower_left(self, lower_left): - check_type('CMFD mesh lower_left', lower_left, Iterable, Real) - check_length('CMFD mesh lower_left', lower_left, 2, 3) - self._lower_left = lower_left - - @upper_right.setter - def upper_right(self, upper_right): - check_type('CMFD mesh upper_right', upper_right, Iterable, Real) - check_length('CMFD mesh upper_right', upper_right, 2, 3) - self._upper_right = upper_right - - @dimension.setter - def dimension(self, dimension): - check_type('CMFD mesh dimension', dimension, Iterable, Integral) - check_length('CMFD mesh dimension', dimension, 2, 3) - for d in dimension: - check_greater_than('CMFD mesh dimension', d, 0) - self._dimension = dimension - - @width.setter - def width(self, width): - check_type('CMFD mesh width', width, Iterable, Real) - check_length('CMFD mesh width', width, 2, 3) - for w in width: - check_greater_than('CMFD mesh width', w, 0) - self._width = width - - @energy.setter - def energy(self, energy): - check_type('CMFD mesh energy', energy, Iterable, Real) - for e in energy: - check_greater_than('CMFD mesh energy', e, 0, True) - self._energy = energy - - @albedo.setter - def albedo(self, albedo): - check_type('CMFD mesh albedo', albedo, Iterable, Real) - check_length('CMFD mesh albedo', albedo, 6) - for a in albedo: - check_greater_than('CMFD mesh albedo', a, 0, True) - check_less_than('CMFD mesh albedo', a, 1, True) - self._albedo = albedo - - @map.setter - def map(self, meshmap): - check_type('CMFD mesh map', meshmap, Iterable, Integral) - for m in meshmap: - check_value('CMFD mesh map', m, [0, 1]) - self._map = meshmap - - -class CMFDRun(object): - r"""Class for running CMFD acceleration through the C API. - - Attributes - ---------- - tally_begin : int - Batch number at which CMFD tallies should begin accummulating - feedback_begin: int - Batch number at which CMFD feedback should be turned on - ref_d : list of floats - List of reference diffusion coefficients to fix CMFD parameters to - dhat_reset : bool - Indicate whether :math:`\widehat{D}` nonlinear CMFD parameters should - be reset to zero before solving CMFD eigenproblem. - display : dict - Dictionary indicating which CMFD results to output. Note that CMFD - k-effective will always be outputted. Acceptable keys are: - - * "balance" - Whether to output RMS [%] of the resdiual from the - neutron balance equation on CMFD tallies (bool) - * "dominance" - Whether to output the estimated dominance ratio from - the CMFD iterations (bool) - * "entropy" - Whether to output the *entropy* of the CMFD predicted - fission source (bool) - * "source" - Whether to ouput the RMS [%] between the OpenMC fission - source and CMFD fission source (bool) - - downscatter : bool - Indicate whether an effective downscatter cross section should be used - when using 2-group CMFD. - feedback : bool - Indicate or not the CMFD diffusion result is used to adjust the weight - of fission source neutrons on the next OpenMC batch. Defaults to False. - cmfd_ktol : float - Tolerance on the eigenvalue when performing CMFD power iteration - mesh : openmc.cmfd.CMFDMesh - Structured mesh to be used for acceleration - norm : float - Normalization factor applied to the CMFD fission source distribution - power_monitor : bool - View convergence of power iteration during CMFD acceleration - run_adjoint : bool - Perform adjoint calculation on the last batch - w_shift : float - Optional Wielandt shift parameter for accelerating power iterations. By - default, it is very large so there is effectively no impact. - stol : float - Tolerance on the fission source when performing CMFD power iteration - reset : list of int - List of batch numbers at which CMFD tallies should be reset - write_matrices : bool - Write sparse matrices that are used during CMFD acceleration (loss, - production) and resultant normalized flux vector phi to file - spectral : float - Optional spectral radius that can be used to accelerate the convergence - of Gauss-Seidel iterations during CMFD power iteration. - gauss_seidel_tolerance : Iterable of float - Two parameters specifying the absolute inner tolerance and the relative - inner tolerance for Gauss-Seidel iterations when performing CMFD. - adjoint_type : {'physical', 'math'} - Stores type of adjoint calculation that should be performed. - ``run_adjoint`` must be true for an adjoint calculation to be - perfomed. Options are: - - * "physical" - Create adjoint matrices from physical parameters of - CMFD problem - * "math" - Create adjoint matrices mathematically as the transpose of - loss and production CMFD matrices - - window_type : {'expanding', 'rolling', 'none'} - Specifies type of tally window scheme to use to accumulate CMFD - tallies. Options are: - - * "expanding" - Have an expanding window that doubles in size - to give more weight to more recent tallies as more generations are - simulated - * "rolling" - Have a fixed window size that aggregates tallies from - the same number of previous generations tallied - * "none" - Don't use a windowing scheme so that all tallies from last - time they were reset are used for the CMFD algorithm. - - window_size : int - Size of window to use for tally window scheme. Only relevant when - window_type is set to "rolling" - indices : numpy.ndarray - Stores spatial and group dimensions as [nx, ny, nz, ng] - cmfd_src : numpy.ndarray - CMFD source distribution calculated from solving CMFD equations - entropy : list of floats - "Shannon entropy" from CMFD fission source, stored for each generation - that CMFD is invoked - balance : list of floats - RMS of neutron balance equations, stored for each generation that CMFD - is invoked - src_cmp : list of floats - RMS deviation of OpenMC and CMFD normalized source, stored for each - generation that CMFD is invoked - dom : list of floats - Dominance ratio from solving CMFD matrix equations, stored for each - generation that CMFD is invoked - k_cmfd : list of floats - List of CMFD k-effectives, stored for each generation that CMFD is - invoked - time_cmfd : float - Time for entire CMFD calculation, in seconds - time_cmfdbuild : float - Time for building CMFD matrices, in seconds - time_cmfdsolve : float - Time for solving CMFD matrix equations, in seconds - intracomm : mpi4py.MPI.Intracomm or None - MPI intercommunicator for running MPI commands - - """ - - def __init__(self): - """Constructor for CMFDRun class. Default values for instance variables - set in this method. - - """ - # Variables that users can modify - self._tally_begin = 1 - self._feedback_begin = 1 - self._ref_d = [] - self._dhat_reset = False - self._display = {'balance': False, 'dominance': False, - 'entropy': False, 'source': False} - self._downscatter = False - self._feedback = False - self._cmfd_ktol = 1.e-8 - self._mesh = None - self._norm = 1. - self._power_monitor = False - self._run_adjoint = False - self._w_shift = 1.e6 - self._stol = 1.e-8 - self._reset = [] - self._write_matrices = False - self._spectral = 0.0 - self._gauss_seidel_tolerance = [1.e-10, 1.e-5] - self._adjoint_type = 'physical' - self._window_type = 'none' - self._window_size = 10 - self._intracomm = None - - # External variables used during runtime but users cannot control - self._set_reference_params = False - self._indices = np.zeros(4, dtype=np.int32) - self._egrid = None - self._albedo = None - self._coremap = None - self._n_resets = 0 - self._mesh_id = None - self._tally_ids = None - self._energy_filters = None - self._cmfd_on = False - self._mat_dim = _CMFD_NOACCEL - self._keff_bal = None - self._keff = None - self._adj_keff = None - self._phi = None - self._adj_phi = None - self._openmc_src_rate = None - self._flux_rate = None - self._total_rate = None - self._p1scatt_rate = None - self._scatt_rate = None - self._nfiss_rate = None - self._current_rate = None - self._flux = None - self._totalxs = None - self._p1scattxs = None - self._scattxs = None - self._nfissxs = None - self._diffcof = None - self._dtilde = None - self._dhat = None - self._hxyz = None - self._current = None - self._cmfd_src = None - self._openmc_src = None - self._sourcecounts = None - self._weightfactors = None - self._entropy = [] - self._balance = [] - self._src_cmp = [] - self._dom = [] - self._k_cmfd = [] - self._resnb = None - self._reset_every = None - self._time_cmfd = None - self._time_cmfdbuild = None - self._time_cmfdsolve = None - - # All index-related variables, for numpy vectorization - self._first_x_accel = None - self._last_x_accel = None - self._first_y_accel = None - self._last_y_accel = None - self._first_z_accel = None - self._last_z_accel = None - self._notfirst_x_accel = None - self._notlast_x_accel = None - self._notfirst_y_accel = None - self._notlast_y_accel = None - self._notfirst_z_accel = None - self._notlast_z_accel = None - self._is_adj_ref_left = None - self._is_adj_ref_right = None - self._is_adj_ref_back = None - self._is_adj_ref_front = None - self._is_adj_ref_bottom = None - self._is_adj_ref_top = None - self._accel_idxs = None - self._accel_neig_left_idxs = None - self._accel_neig_right_idxs = None - self._accel_neig_back_idxs = None - self._accel_neig_front_idxs = None - self._accel_neig_bot_idxs = None - self._accel_neig_top_idxs = None - self._loss_row = None - self._loss_col = None - self._prod_row = None - self._prod_col = None - - @property - def tally_begin(self): - return self._tally_begin - - @property - def feedback_begin(self): - return self._feedback_begin - - @property - def ref_d(self): - return self._ref_d - - @property - def dhat_reset(self): - return self._dhat_reset - - @property - def display(self): - return self._display - - @property - def downscatter(self): - return self._downscatter - - @property - def feedback(self): - return self._feedback - - @property - def cmfd_ktol(self): - return self._cmfd_ktol - - @property - def mesh(self): - return self._mesh - - @property - def norm(self): - return self._norm - - @property - def adjoint_type(self): - return self._adjoint_type - - @property - def window_type(self): - return self._window_type - - @property - def window_size(self): - return self._window_size - - @property - def power_monitor(self): - return self._power_monitor - - @property - def run_adjoint(self): - return self._run_adjoint - - @property - def w_shift(self): - return self._w_shift - - @property - def stol(self): - return self._stol - - @property - def spectral(self): - return self._spectral - - @property - def reset(self): - return self._reset - - @property - def write_matrices(self): - return self._write_matrices - - @property - def gauss_seidel_tolerance(self): - return self._gauss_seidel_tolerance - - @property - def indices(self): - return self._indices - - @property - def cmfd_src(self): - return self._cmfd_src - - @property - def dom(self): - return self._dom - - @property - def src_cmp(self): - return self._src_cmp - - @property - def balance(self): - return self._balance - - @property - def entropy(self): - return self._entropy - - @property - def k_cmfd(self): - return self._k_cmfd - - @tally_begin.setter - def tally_begin(self, begin): - check_type('CMFD tally begin batch', begin, Integral) - check_greater_than('CMFD tally begin batch', begin, 0) - self._tally_begin = begin - - @feedback_begin.setter - def feedback_begin(self, begin): - check_type('CMFD feedback begin batch', begin, Integral) - check_greater_than('CMFD feedback begin batch', begin, 0) - self._feedback_begin = begin - - @ref_d.setter - def ref_d(self, diff_params): - check_type('Reference diffusion params', diff_params, - Iterable, Real) - self._ref_d = np.array(diff_params) - - @dhat_reset.setter - def dhat_reset(self, dhat_reset): - check_type('CMFD Dhat reset', dhat_reset, bool) - self._dhat_reset = dhat_reset - - @display.setter - def display(self, display): - check_type('display', display, Mapping) - for key, value in display.items(): - check_value('display key', key, - ('balance', 'entropy', 'dominance', 'source')) - check_type("display['{}']".format(key), value, bool) - self._display[key] = value - - @downscatter.setter - def downscatter(self, downscatter): - check_type('CMFD downscatter', downscatter, bool) - self._downscatter = downscatter - - @feedback.setter - def feedback(self, feedback): - check_type('CMFD feedback', feedback, bool) - self._feedback = feedback - - @cmfd_ktol.setter - def cmfd_ktol(self, cmfd_ktol): - check_type('CMFD eigenvalue tolerance', cmfd_ktol, Real) - self._cmfd_ktol = cmfd_ktol - - @mesh.setter - def mesh(self, cmfd_mesh): - check_type('CMFD mesh', cmfd_mesh, CMFDMesh) - - # Check dimension defined - if cmfd_mesh.dimension is None: - raise ValueError('CMFD mesh requires spatial ' - 'dimensions to be specified') - - # Check lower left defined - if cmfd_mesh.lower_left is None: - raise ValueError('CMFD mesh requires lower left coordinates ' - 'to be specified') - - # Check that both upper right and width both not defined - if cmfd_mesh.upper_right is not None and cmfd_mesh.width is not None: - raise ValueError('Both upper right coordinates and width ' - 'cannot be specified for CMFD mesh') - - # Check that at least one of width or upper right is defined - if cmfd_mesh.upper_right is None and cmfd_mesh.width is None: - raise ValueError('CMFD mesh requires either upper right ' - 'coordinates or width to be specified') - - # Check width and lower length are same dimension and define - # upper_right - if cmfd_mesh.width is not None: - check_length('CMFD mesh width', cmfd_mesh.width, - len(cmfd_mesh.lower_left)) - cmfd_mesh.upper_right = np.array(cmfd_mesh.lower_left) + \ - np.array(cmfd_mesh.width) * np.array(cmfd_mesh.dimension) - - # Check upper_right and lower length are same dimension and define - # width - elif cmfd_mesh.upper_right is not None: - check_length('CMFD mesh upper right', cmfd_mesh.upper_right, - len(cmfd_mesh.lower_left)) - # Check upper right coordinates are greater than lower left - if np.any(np.array(cmfd_mesh.upper_right) <= - np.array(cmfd_mesh.lower_left)): - raise ValueError('CMFD mesh requires upper right ' - 'coordinates to be greater than lower ' - 'left coordinates') - cmfd_mesh.width = np.true_divide((np.array(cmfd_mesh.upper_right) - - np.array(cmfd_mesh.lower_left)), - np.array(cmfd_mesh.dimension)) - self._mesh = cmfd_mesh - - @norm.setter - def norm(self, norm): - check_type('CMFD norm', norm, Real) - self._norm = norm - - @adjoint_type.setter - def adjoint_type(self, adjoint_type): - check_type('CMFD adjoint type', adjoint_type, str) - check_value('CMFD adjoint type', adjoint_type, - ['math', 'physical']) - self._adjoint_type = adjoint_type - - @window_type.setter - def window_type(self, window_type): - check_type('CMFD window type', window_type, str) - check_value('CMFD window type', window_type, - ['none', 'rolling', 'expanding']) - self._window_type = window_type - - @window_size.setter - def window_size(self, window_size): - check_type('CMFD window size', window_size, Integral) - check_greater_than('CMFD window size', window_size, 0) - if self._window_type != 'rolling': - warn_msg = 'Window size will have no effect on CMFD simulation ' \ - 'unless window type is set to "rolling".' - warnings.warn(warn_msg, RuntimeWarning) - self._window_size = window_size - - @power_monitor.setter - def power_monitor(self, power_monitor): - check_type('CMFD power monitor', power_monitor, bool) - self._power_monitor = power_monitor - - @run_adjoint.setter - def run_adjoint(self, run_adjoint): - check_type('CMFD run adjoint', run_adjoint, bool) - self._run_adjoint = run_adjoint - - @w_shift.setter - def w_shift(self, w_shift): - check_type('CMFD Wielandt shift', w_shift, Real) - self._w_shift = w_shift - - @stol.setter - def stol(self, stol): - check_type('CMFD fission source tolerance', stol, Real) - self._stol = stol - - @spectral.setter - def spectral(self, spectral): - check_type('CMFD spectral radius', spectral, Real) - self._spectral = spectral - - @reset.setter - def reset(self, reset): - check_type('tally reset batches', reset, Iterable, Integral) - self._reset = reset - - @write_matrices.setter - def write_matrices(self, write_matrices): - check_type('CMFD write matrices', write_matrices, bool) - self._write_matrices = write_matrices - - @gauss_seidel_tolerance.setter - def gauss_seidel_tolerance(self, gauss_seidel_tolerance): - check_type('CMFD Gauss-Seidel tolerance', gauss_seidel_tolerance, - Iterable, Real) - check_length('Gauss-Seidel tolerance', gauss_seidel_tolerance, 2) - self._gauss_seidel_tolerance = gauss_seidel_tolerance - - def run(self, **kwargs): - """Run OpenMC with coarse mesh finite difference acceleration - - This method is called by user to run CMFD once instance variables of - CMFDRun class are set - - Parameters - ---------- - **kwargs - All keyword arguments are passed to - :func:`openmc.lib.run_in_memory`. - - """ - with self.run_in_memory(**kwargs): - for _ in self.iter_batches(): - pass - - @contextmanager - def run_in_memory(self, **kwargs): - """ Context manager for running CMFD functions with OpenMC shared - library functions. - - This function can be used with a 'with' statement to ensure the - CMFDRun class is properly initialized/finalized. For example:: - - from openmc import cmfd - cmfd_run = cmfd.CMFDRun() - with cmfd_run.run_in_memory(): - do_stuff_before_simulation_start() - for _ in cmfd_run.iter_batches(): - do_stuff_between_batches() - - Parameters - ---------- - **kwargs - All keyword arguments passed to :func:`openmc.lib.run_in_memory`. - - """ - # Store intracomm for part of CMFD routine where MPI reduce and - # broadcast calls are made - if 'intracomm' in kwargs and kwargs['intracomm'] is not None: - self._intracomm = kwargs['intracomm'] - elif have_mpi: - self._intracomm = MPI.COMM_WORLD - - # Run and pass arguments to C API run_in_memory function - with openmc.lib.run_in_memory(**kwargs): - self.init() - yield - self.finalize() - - def iter_batches(self): - """ Iterator over batches. - - This function returns a generator-iterator that allows Python code to - be run between batches when running an OpenMC simulation with CMFD. - It should be used in conjunction with - :func`openmc.cmfd.CMFDRun.run_in_memory` to ensure proper - initialization/finalization of CMFDRun instance. - - """ - status = 0 - while status == 0: - status = self.next_batch() - yield - - def init(self): - """ Initialize CMFDRun instance by setting up CMFD parameters and - calling :func:`openmc.lib.simulation_init` - - """ - # Configure CMFD parameters and tallies - self._configure_cmfd() - - # Initialize all arrays used for CMFD solver - self._allocate_cmfd() - - # Compute and store array indices used to build cross section - # arrays - self._precompute_array_indices() - - # Compute and store row and column indices used to build CMFD - # matrices - self._precompute_matrix_indices() - - # Initialize all variables used for linear solver in C++ - self._initialize_linsolver() - - # Initialize simulation - openmc.lib.simulation_init() - - # Set cmfd_run variable to True through C API - openmc.lib.settings.cmfd_run = True - - def next_batch(self): - """ Run next batch for CMFDRun. - - Returns - ------- - int - Status after running a batch (0=normal, 1=reached maximum number of - batches, 2=tally triggers reached) - - """ - # Initialize CMFD batch - self._cmfd_init_batch() - - # Run next batch - status = openmc.lib.next_batch() - - # Perform CMFD calculation if on - if self._cmfd_on: - self._execute_cmfd() - - # Write CMFD output if CMFD on for current batch - if openmc.lib.master(): - self._write_cmfd_output() - - # Write CMFD data to statepoint - if openmc.lib.is_statepoint_batch(): - self.statepoint_write() - return status - - def finalize(self): - """ Finalize simulation by calling - :func:`openmc.lib.simulation_finalize` and print out CMFD timing - information. - - """ - # Finalize simuation - openmc.lib.simulation_finalize() - - # Print out CMFD timing statistics - self._write_cmfd_timing_stats() - - def statepoint_write(self, filename=None): - """Write all simulation parameters to statepoint - - Parameters - ---------- - filename : str - Filename of statepoint - - """ - if filename is None: - batch_str_len = len(str(openmc.lib.settings.batches)) - batch_str = str(openmc.lib.current_batch()).zfill(batch_str_len) - filename = 'statepoint.{}.h5'.format(batch_str) - - # Call C API statepoint_write to save source distribution with CMFD - # feedback - openmc.lib.statepoint_write(filename=filename) - - # Append CMFD data to statepoint file using h5py - self._write_cmfd_statepoint(filename) - - def _write_cmfd_statepoint(self, filename): - """Append all CNFD simulation parameters to existing statepoint - - Parameters - ---------- - filename : str - Filename of statepoint - - """ - if openmc.lib.master(): - with h5py.File(filename, 'a') as f: - if 'cmfd' not in f: - if openmc.lib.settings.verbosity >= 5: - print(' Writing CMFD data to {}...'.format(filename)) - sys.stdout.flush() - cmfd_group = f.create_group("cmfd") - cmfd_group.attrs['cmfd_on'] = self._cmfd_on - cmfd_group.attrs['feedback'] = self._feedback - cmfd_group.attrs['feedback_begin'] = self._feedback_begin - cmfd_group.attrs['mesh_id'] = self._mesh_id - cmfd_group.attrs['tally_begin'] = self._tally_begin - cmfd_group.attrs['time_cmfd'] = self._time_cmfd - cmfd_group.attrs['time_cmfdbuild'] = self._time_cmfdbuild - cmfd_group.attrs['time_cmfdsolve'] = self._time_cmfdsolve - cmfd_group.attrs['window_size'] = self._window_size - cmfd_group.attrs['window_type'] = self._window_type - cmfd_group.create_dataset('k_cmfd', data=self._k_cmfd) - cmfd_group.create_dataset('dom', data=self._dom) - cmfd_group.create_dataset('src_cmp', data=self._src_cmp) - cmfd_group.create_dataset('balance', data=self._balance) - cmfd_group.create_dataset('entropy', data=self._entropy) - cmfd_group.create_dataset('reset', data=self._reset) - cmfd_group.create_dataset('albedo', data=self._albedo) - cmfd_group.create_dataset('coremap', data=self._coremap) - cmfd_group.create_dataset('egrid', data=self._egrid) - cmfd_group.create_dataset('indices', data=self._indices) - cmfd_group.create_dataset('tally_ids', - data=self._tally_ids) - cmfd_group.create_dataset('current_rate', - data=self._current_rate) - cmfd_group.create_dataset('flux_rate', - data=self._flux_rate) - cmfd_group.create_dataset('nfiss_rate', - data=self._nfiss_rate) - cmfd_group.create_dataset('openmc_src_rate', - data=self._openmc_src_rate) - cmfd_group.create_dataset('p1scatt_rate', - data=self._p1scatt_rate) - cmfd_group.create_dataset('scatt_rate', - data=self._scatt_rate) - cmfd_group.create_dataset('total_rate', - data=self._total_rate) - elif openmc.settings.verbosity >= 5: - print(' CMFD data not written to statepoint file' - 'as it already exists in {}'.format(filename)) - sys.stdout.flush() - - def _initialize_linsolver(self): - # Determine number of rows in CMFD matrix - ng = self._indices[3] - n = self._mat_dim*ng - - # Create temp loss matrix to pass row/col indices to C++ linear solver - loss_row = self._loss_row - loss_col = self._loss_col - temp_data = np.ones(len(loss_row)) - temp_loss = sparse.csr_matrix((temp_data, (loss_row, loss_col)), - shape=(n, n)) - - # Pass coremap as 1-d array of 32-bit integers - coremap = np.swapaxes(self._coremap, 0, 2).flatten().astype(np.int32) - - args = temp_loss.indptr, len(temp_loss.indptr), \ - temp_loss.indices, len(temp_loss.indices), n, \ - self._spectral, self._indices, coremap - return openmc.lib._dll.openmc_initialize_linsolver(*args) - - def _write_cmfd_output(self): - """Write CMFD output to buffer at the end of each batch""" - # Display CMFD k-effective - outstr = '{:>11s}CMFD k: {:0.5f}'.format('', self._k_cmfd[-1]) - # Display value of additional fields based on display dict - outstr += '\n' - if self._display['dominance']: - outstr += ('{:>11s}Dom Rat: {:0.5f}\n' - .format('', self._dom[-1])) - if self._display['entropy']: - outstr += ('{:>11s}CMFD Ent: {:0.5f}\n' - .format('', self._entropy[-1])) - if self._display['source']: - outstr += ('{:>11s}RMS Src: {:0.5f}\n' - .format('', self._src_cmp[-1])) - if self._display['balance']: - outstr += ('{:>11s}RMS Bal: {:0.5f}\n' - .format('', self._balance[-1])) - - print(outstr) - sys.stdout.flush() - - def _write_cmfd_timing_stats(self): - """Write CMFD timing stats to buffer after finalizing simulation""" - if openmc.lib.master(): - outstr = ("=====================> " - "CMFD TIMING STATISTICS <====================\n\n" - " Time in CMFD = {:.5E} seconds\n" - " Building matrices = {:.5E} seconds\n" - " Solving matrices = {:.5E} seconds\n") - print(outstr.format(self._time_cmfd, self._time_cmfdbuild, - self._time_cmfdsolve)) - sys.stdout.flush() - - def _configure_cmfd(self): - """Initialize CMFD parameters and set CMFD input variables""" - # Check if restarting simulation from statepoint file - if not openmc.lib.settings.restart_run: - # Read in cmfd input defined in Python - self._read_cmfd_input() - - # Set up CMFD coremap - self._set_coremap() - - # Extract spatial and energy indices - nx, ny, nz, ng = self._indices - - # Allocate parameters that need to stored for tally window - self._openmc_src_rate = np.zeros((nx, ny, nz, ng, 0)) - self._flux_rate = np.zeros((nx, ny, nz, ng, 0)) - self._total_rate = np.zeros((nx, ny, nz, ng, 0)) - self._p1scatt_rate = np.zeros((nx, ny, nz, ng, 0)) - self._scatt_rate = np.zeros((nx, ny, nz, ng, ng, 0)) - self._nfiss_rate = np.zeros((nx, ny, nz, ng, ng, 0)) - self._current_rate = np.zeros((nx, ny, nz, 12, ng, 0)) - - # Initialize timers - self._time_cmfd = 0.0 - self._time_cmfdbuild = 0.0 - self._time_cmfdsolve = 0.0 - - # Initialize parameters for CMFD tally windows - self._set_tally_window() - - else: - # Reset CMFD parameters from statepoint file - path_statepoint = openmc.lib.settings.path_statepoint - self._reset_cmfd(path_statepoint) - - def _read_cmfd_input(self): - """Sets values of additional instance variables based on user input""" - # Print message to user and flush output to stdout - if openmc.lib.settings.verbosity >= 7 and openmc.lib.master(): - print(' Configuring CMFD parameters for simulation') - sys.stdout.flush() - - # Check if CMFD mesh is defined - if self._mesh is None: - raise ValueError('No CMFD mesh has been specified for ' - 'simulation') - - # Set spatial dimensions of CMFD object - for i, n in enumerate(self._mesh.dimension): - self._indices[i] = n - - # Check if in continuous energy mode - if not openmc.lib.settings.run_CE: - raise OpenMCError('CMFD must be run in continuous energy mode') - - # Set number of energy groups - if self._mesh.energy is not None: - ng = len(self._mesh.energy) - self._egrid = np.array(self._mesh.energy) - self._indices[3] = ng - 1 - self._energy_filters = True - else: - self._egrid = np.array([_ENERGY_MIN_NEUTRON, _ENERGY_MAX_NEUTRON]) - self._indices[3] = 1 - self._energy_filters = False - - # Set global albedo - if self._mesh.albedo is not None: - self._albedo = np.array(self._mesh.albedo) - else: - self._albedo = np.array([1., 1., 1., 1., 1., 1.]) - - # Get acceleration map, otherwise set all regions to be accelerated - if self._mesh.map is not None: - check_length('CMFD coremap', self._mesh.map, - np.product(self._indices[0:3])) - self._coremap = np.array(self._mesh.map) - else: - self._coremap = np.ones((np.product(self._indices[0:3])), - dtype=int) - - # Check CMFD tallies accummulated before feedback turned on - if self._feedback and self._feedback_begin < self._tally_begin: - raise ValueError('Tally begin must be less than or equal to ' - 'feedback begin') - - # Set number of batches where cmfd tallies should be reset - self._n_resets = len(self._reset) - - # Create tally objects - self._create_cmfd_tally() - - def _reset_cmfd(self, filename): - """Reset all CMFD parameters from statepoint - - Parameters - ---------- - filename : str - Filename of statepoint to read from - - """ - with h5py.File(filename, 'r') as f: - if 'cmfd' not in f: - raise OpenMCError('Could not find CMFD parameters in ', - 'file {}'.format(filename)) - else: - # Overwrite CMFD values from statepoint - if (openmc.lib.master() and - openmc.lib.settings.verbosity >= 5): - print(' Loading CMFD data from {}...'.format(filename)) - sys.stdout.flush() - cmfd_group = f['cmfd'] - self._cmfd_on = cmfd_group.attrs['cmfd_on'] - self._feedback = cmfd_group.attrs['feedback'] - self._feedback_begin = cmfd_group.attrs['feedback_begin'] - self._tally_begin = cmfd_group.attrs['tally_begin'] - self._time_cmfd = cmfd_group.attrs['time_cmfd'] - self._time_cmfdbuild = cmfd_group.attrs['time_cmfdbuild'] - self._time_cmfdsolve = cmfd_group.attrs['time_cmfdsolve'] - self._window_size = cmfd_group.attrs['window_size'] - self._window_type = cmfd_group.attrs['window_type'] - self._k_cmfd = list(cmfd_group['k_cmfd']) - self._dom = list(cmfd_group['dom']) - self._src_cmp = list(cmfd_group['src_cmp']) - self._balance = list(cmfd_group['balance']) - self._entropy = list(cmfd_group['entropy']) - self._reset = list(cmfd_group['reset']) - self._albedo = cmfd_group['albedo'][()] - self._coremap = cmfd_group['coremap'][()] - self._egrid = cmfd_group['egrid'][()] - self._indices = cmfd_group['indices'][()] - self._current_rate = cmfd_group['current_rate'][()] - self._flux_rate = cmfd_group['flux_rate'][()] - self._nfiss_rate = cmfd_group['nfiss_rate'][()] - self._openmc_src_rate = cmfd_group['openmc_src_rate'][()] - self._p1scatt_rate = cmfd_group['p1scatt_rate'][()] - self._scatt_rate = cmfd_group['scatt_rate'][()] - self._total_rate = cmfd_group['total_rate'][()] - - # Overwrite CMFD mesh properties - cmfd_mesh_name = 'mesh ' + str(cmfd_group.attrs['mesh_id']) - cmfd_mesh = f['tallies']['meshes'][cmfd_mesh_name] - self._mesh.dimension = cmfd_mesh['dimension'][()] - self._mesh.lower_left = cmfd_mesh['lower_left'][()] - self._mesh.upper_right = cmfd_mesh['upper_right'][()] - self._mesh.width = cmfd_mesh['width'][()] - - # Store tally ids from statepoint run - sp_tally_ids = list(cmfd_group['tally_ids']) - - # Set CMFD variables not in statepoint file - default_egrid = np.array([_ENERGY_MIN_NEUTRON, _ENERGY_MAX_NEUTRON]) - self._energy_filters = not np.array_equal(self._egrid, default_egrid) - self._n_resets = len(self._reset) - self._mat_dim = np.max(self._coremap) + 1 - self._reset_every = (self._window_type == 'expanding' or - self._window_type == 'rolling') - - # Recreate CMFD tallies in memory - self._create_cmfd_tally() - - def _allocate_cmfd(self): - """Allocates all numpy arrays and lists used in CMFD algorithm""" - # Extract spatial and energy indices - nx, ny, nz, ng = self._indices - - # Allocate dimensions for each mesh cell - self._hxyz = np.zeros((nx, ny, nz, 3)) - self._hxyz[:] = openmc.lib.meshes[self._mesh_id].width - - # Allocate flux, cross sections and diffusion coefficient - self._flux = np.zeros((nx, ny, nz, ng)) - self._totalxs = np.zeros((nx, ny, nz, ng)) - self._p1scattxs = np.zeros((nx, ny, nz, ng)) - self._scattxs = np.zeros((nx, ny, nz, ng, ng)) # Incoming, outgoing - self._nfissxs = np.zeros((nx, ny, nz, ng, ng)) # Incoming, outgoing - self._diffcof = np.zeros((nx, ny, nz, ng)) - - # Allocate dtilde and dhat - self._dtilde = np.zeros((nx, ny, nz, ng, 6)) - self._dhat = np.zeros((nx, ny, nz, ng, 6)) - - # Set reference diffusion parameters - if self._ref_d: - self._set_reference_params = True - # Check length of reference diffusion parameters equal to number of - # energy groups - if len(self._ref_d) != self._indices[3]: - raise OpenMCError('Number of reference diffusion parameters ' - 'must equal number of CMFD energy groups') - - def _set_tally_window(self): - """Sets parameters to handle different tally window options""" - # Set parameters for expanding window - if self._window_type == 'expanding': - self._reset_every = True - self._window_size = 1 - # Set parameters for rolling window - elif self.window_type == 'rolling': - self._reset_every = True - # Set parameters for default case, with no window - else: - self._window_size = 1 - self._reset_every = False - - def _cmfd_init_batch(self): - """Handles CMFD options at the beginning of each batch""" - # Get current batch through C API - # Add 1 as next_batch has not been called yet - current_batch = openmc.lib.current_batch() + 1 - - # Check to activate CMFD diffusion and possible feedback - # Check to activate CMFD tallies - if self._tally_begin == current_batch: - self._cmfd_on = True - - # Check to reset tallies - if ((self._n_resets > 0 and current_batch in self._reset) - or self._reset_every): - self._cmfd_tally_reset() - - def _execute_cmfd(self): - """Runs CMFD calculation on master node""" - # Run CMFD on single processor on master - if openmc.lib.master(): - # Start CMFD timer - time_start_cmfd = time.time() - - # Create CMFD data from OpenMC tallies - self._set_up_cmfd() - - # Call solver - self._cmfd_solver_execute() - - # Store k-effective - self._k_cmfd.append(self._keff) - - # Check to perform adjoint on last batch - if (openmc.lib.current_batch() == openmc.lib.settings.batches - and self._run_adjoint): - self._cmfd_solver_execute(adjoint=True) - - # Calculate fission source - self._calc_fission_source() - - # Calculate weight factors - self._cmfd_reweight(True) - - # Stop CMFD timer - if openmc.lib.master(): - time_stop_cmfd = time.time() - self._time_cmfd += time_stop_cmfd - time_start_cmfd - - def _cmfd_tally_reset(self): - """Resets all CMFD tallies in memory""" - # Print message - if (openmc.lib.settings.verbosity >= 6 and openmc.lib.master() and - not self._reset_every): - print(' CMFD tallies reset') - sys.stdout.flush() - - # Reset CMFD tallies - tallies = openmc.lib.tallies - for tally_id in self._tally_ids: - tallies[tally_id].reset() - - def _set_up_cmfd(self): - """Configures CMFD object for a CMFD eigenvalue calculation - - """ - # Calculate all cross sections based on tally window averages - self._compute_xs() - - # Compute effective downscatter cross section - if self._downscatter: - self._compute_effective_downscatter() - - # Check neutron balance - self._neutron_balance() - - # Calculate dtilde - self._compute_dtilde() - - # Calculate dhat - self._compute_dhat() - - def _cmfd_solver_execute(self, adjoint=False): - """Sets up and runs power iteration solver for CMFD - - Parameters - ---------- - adjoint : bool - Whether or not to run an adjoint calculation - - """ - # Check for physical adjoint - physical_adjoint = adjoint and self._adjoint_type == 'physical' - - # Start timer for build - time_start_buildcmfd = time.time() - - # Build the loss and production matrices - if not adjoint: - # Build matrices without adjoint calculation - loss = self._build_loss_matrix(False) - prod = self._build_prod_matrix(False) - else: - # Build adjoint matrices by running adjoint calculation - if self._adjoint_type == 'physical': - loss = self._build_loss_matrix(True) - prod = self._build_prod_matrix(True) - # Build adjoint matrices as transpose of non-adjoint matrices - else: - loss = self._build_loss_matrix(False).transpose() - prod = self._build_prod_matrix(False).transpose() - - # Write out the matrices. - if self._write_matrices: - if not adjoint: - self._write_matrix(loss, 'loss') - self._write_matrix(prod, 'prod') - else: - self._write_matrix(loss, 'adj_loss') - self._write_matrix(prod, 'adj_prod') - - # Stop timer for build - time_stop_buildcmfd = time.time() - self._time_cmfdbuild += time_stop_buildcmfd - time_start_buildcmfd - - # Begin power iteration - time_start_solvecmfd = time.time() - phi, keff, dom = self._execute_power_iter(loss, prod) - time_stop_solvecmfd = time.time() - self._time_cmfdsolve += time_stop_solvecmfd - time_start_solvecmfd - - # Save results, normalizing phi to sum to 1 - if adjoint: - self._adj_keff = keff - self._adj_phi = phi/np.sqrt(np.sum(phi*phi)) - else: - self._keff = keff - self._phi = phi/np.sqrt(np.sum(phi*phi)) - - self._dom.append(dom) - - # Write out flux vector - if self._write_matrices: - if adjoint: - self._write_vector(self._adj_phi, 'adj_fluxvec') - else: - self._write_vector(self._phi, 'fluxvec') - - def _write_vector(self, vector, base_filename): - """Write a 1-D numpy array to file and also save it in .npy format. - This particular format allows users to load the variable directly in a - Python session with np.load() - - Parameters - ---------- - vector : numpy.ndarray - Vector that will be saved - base_filename : str - Filename to save vector as, without any file extension at the end. - Vector will be saved to file [base_filename].dat and in numpy - format as [base_filename].npy - - """ - # Write each element in vector to file - with open(base_filename+'.dat', 'w') as fh: - for val in vector: - fh.write('{:0.8f}\n'.format(val)) - - # Save as numpy format - np.save(base_filename, vector) - - def _write_matrix(self, matrix, base_filename): - """Write a numpy matrix to file and also save it in .npz format. This - particular format allows users to load the variable directly in a - Python session with scipy.sparse.load_npz() - - Parameters - ---------- - matrix : scipy.sparse.spmatrix - Sparse matrix that will be saved - base_filename : str - Filename to save matrix entries, without any file extension at the - end. Matrix entries will be saved to file [base_filename].dat and - in scipy format as [base_filename].npz - - """ - # Write row, col, and data of each entry in sparse matrix. This ignores - # all zero-entries, and indices are written with zero-based indexing - with open(base_filename+'.dat', 'w') as fh: - for row in range(matrix.shape[0]): - # Get all cols for particular row in matrix - cols = matrix.indices[matrix.indptr[row]:matrix.indptr[row+1]] - # Get all data entries for particular row in matrix - data = matrix.data[matrix.indptr[row]:matrix.indptr[row+1]] - for i in range(len(cols)): - fh.write('{:3d}, {:3d}, {:0.8f}\n'.format( - row, cols[i], data[i])) - - # Save matrix in scipy format - sparse.save_npz(base_filename, matrix) - - def _calc_fission_source(self): - """Calculates CMFD fission source from CMFD flux. If a coremap is - defined, there will be a discrepancy between the spatial indices in the - variables ``phi`` and ``nfissxs``, so ``phi`` needs to be mapped to the - spatial indices of the cross sections. This can be done in a vectorized - numpy manner or with for loops - - """ - # Extract number of groups and number of accelerated regions - nx, ny, nz, ng = self._indices - n = self._mat_dim - - # Compute cmfd_src in a vecotorized manner by phi to the spatial - # indices of the actual problem so that cmfd_flux can be multiplied by - # nfissxs - - # Calculate volume - vol = np.product(self._hxyz, axis=3) - - # Reshape phi by number of groups - phi = self._phi.reshape((n, ng)) - - # Extract indices of coremap that are accelerated - idx = self._accel_idxs - - # Initialize CMFD flux map that maps phi to actual spatial and - # group indices of problem - cmfd_flux = np.zeros((nx, ny, nz, ng)) - - # Loop over all groups and set CMFD flux based on indices of - # coremap and values of phi - for g in range(ng): - phi_g = phi[:,g] - cmfd_flux[idx + (g,)] = phi_g[self._coremap[idx]] - - # Compute fission source - cmfd_src = (np.sum(self._nfissxs[:,:,:,:,:] * - cmfd_flux[:,:,:,:,np.newaxis], axis=3) * - vol[:,:,:,np.newaxis]) - - # Normalize source such that it sums to 1.0 - self._cmfd_src = cmfd_src / np.sum(cmfd_src) - - # Compute entropy - if openmc.lib.settings.entropy_on: - # Compute source times log_2(source) - source = self._cmfd_src[self._cmfd_src > 0] \ - * np.log(self._cmfd_src[self._cmfd_src > 0])/np.log(2) - - # Sum source and store - self._entropy.append(-1.0 * np.sum(source)) - - # Normalize source so average is 1.0 - self._cmfd_src = self._cmfd_src/np.sum(self._cmfd_src) * self._norm - - # Calculate differences between normalized sources - self._src_cmp.append(np.sqrt(1.0 / self._norm - * np.sum((self._cmfd_src - self._openmc_src)**2))) - - def _cmfd_reweight(self, new_weights): - """Performs weighting of particles in source bank - - Parameters - ---------- - new_weights : bool - Whether to reweight particles or not - - """ - # Compute new weight factors - if new_weights: - - # Get spatial dimensions and energy groups - nx, ny, nz, ng = self._indices - - # Count bank site in mesh and reverse due to egrid structured - outside = self._count_bank_sites() - - # Check and raise error if source sites exist outside of CMFD mesh - if openmc.lib.master() and outside: - raise OpenMCError('Source sites outside of the CMFD mesh') - - # Have master compute weight factors, ignore any zeros in - # sourcecounts or cmfd_src - if openmc.lib.master(): - # Compute normalization factor - norm = np.sum(self._sourcecounts) / np.sum(self._cmfd_src) - - # Define target reshape dimensions for sourcecounts. This - # defines how self._sourcecounts is ordered by dimension - target_shape = [nz, ny, nx, ng] - - # Reshape sourcecounts to target shape. Swap x and z axes so - # that the shape is now [nx, ny, nz, ng] - sourcecounts = np.swapaxes( - self._sourcecounts.reshape(target_shape), 0, 2) - - # Flip index of energy dimension - sourcecounts = np.flip(sourcecounts, axis=3) - - # Compute weight factors - div_condition = np.logical_and(sourcecounts > 0, - self._cmfd_src > 0) - self._weightfactors = (np.divide(self._cmfd_src * norm, - sourcecounts, where=div_condition, - out=np.ones_like(self._cmfd_src), - dtype=np.float32)) - - if (not self._feedback - or openmc.lib.current_batch() < self._feedback_begin): - return - - # Broadcast weight factors to all procs - if have_mpi: - self._weightfactors = self._intracomm.bcast( - self._weightfactors) - - m = openmc.lib.meshes[self._mesh_id] - energy = self._egrid - ng = self._indices[3] - - # Get locations and energies of all particles in source bank - source_xyz = openmc.lib.source_bank()['r'] - source_energies = openmc.lib.source_bank()['E'] - - # Convert xyz location to the CMFD mesh index - mesh_ijk = np.floor((source_xyz-m.lower_left)/m.width).astype(int) - - # Determine which energy bin each particle's energy belongs to - # Separate into cases bases on where source energies lies on egrid - energy_bins = np.zeros(len(source_energies), dtype=int) - idx = np.where(source_energies < energy[0]) - energy_bins[idx] = ng - 1 - idx = np.where(source_energies > energy[-1]) - energy_bins[idx] = 0 - idx = np.where((source_energies >= energy[0]) & - (source_energies <= energy[-1])) - energy_bins[idx] = ng - np.digitize(source_energies, energy) - - # Determine weight factor of each particle based on its mesh index - # and energy bin and updates its weight - openmc.lib.source_bank()['wgt'] *= self._weightfactors[ - mesh_ijk[:,0], mesh_ijk[:,1], mesh_ijk[:,2], energy_bins] - - if openmc.lib.master() and np.any(source_energies < energy[0]): - print(' WARNING: Source pt below energy grid') - sys.stdout.flush() - if openmc.lib.master() and np.any(source_energies > energy[-1]): - print(' WARNING: Source pt above energy grid') - sys.stdout.flush() - - def _count_bank_sites(self): - """Determines the number of fission bank sites in each cell of a given - mesh and energy group structure. - Returns - ------- - bool - Wheter any source sites outside of CMFD mesh were found - - """ - # Initialize variables - m = openmc.lib.meshes[self._mesh_id] - bank = openmc.lib.source_bank() - energy = self._egrid - sites_outside = np.zeros(1, dtype=bool) - nxnynz = np.prod(self._indices[0:3]) - ng = self._indices[3] - - outside = np.zeros(1, dtype=bool) - self._sourcecounts = np.zeros((nxnynz, ng)) - count = np.zeros(self._sourcecounts.shape) - - # Get location and energy of each particle in source bank - source_xyz = openmc.lib.source_bank()['r'] - source_energies = openmc.lib.source_bank()['E'] - - # Convert xyz location to mesh index and ravel index to scalar - mesh_locations = np.floor((source_xyz - m.lower_left) / m.width) - mesh_bins = mesh_locations[:,2] * m.dimension[1] * m.dimension[0] + \ - mesh_locations[:,1] * m.dimension[0] + mesh_locations[:,0] - - # Check if any source locations lie outside of defined CMFD mesh - if np.any(mesh_bins < 0) or np.any(mesh_bins >= np.prod(m.dimension)): - outside[0] = True - - # Determine which energy bin each particle's energy belongs to - # Separate into cases bases on where source energies lies on egrid - energy_bins = np.zeros(len(source_energies), dtype=int) - idx = np.where(source_energies < energy[0]) - energy_bins[idx] = 0 - idx = np.where(source_energies > energy[-1]) - energy_bins[idx] = ng - 1 - idx = np.where((source_energies >= energy[0]) & - (source_energies <= energy[-1])) - energy_bins[idx] = np.digitize(source_energies, energy) - 1 - - # Determine all unique combinations of mesh bin and energy bin, and - # count number of particles that belong to these combinations - idx, counts = np.unique(np.array([mesh_bins, energy_bins]), axis=1, - return_counts=True) - - # Store counts to appropriate mesh-energy combination - count[idx[0].astype(int), idx[1].astype(int)] = counts - - if have_mpi: - # Collect values of count from all processors - self._intracomm.Reduce(count, self._sourcecounts, MPI.SUM) - # Check if there were sites outside the mesh for any processor - self._intracomm.Reduce(outside, sites_outside, MPI.LOR) - # Deal with case if MPI not defined (only one proc) - else: - sites_outside = outside - self._sourcecounts = count - - return sites_outside[0] - - def _build_loss_matrix(self, adjoint): - # Extract spatial and energy indices and define matrix dimension - ng = self._indices[3] - n = self._mat_dim*ng - - # Define data entries used to build csr matrix - data = np.array([]) - - dtilde_left = self._dtilde[:,:,:,:,0] - dtilde_right = self._dtilde[:,:,:,:,1] - dtilde_back = self._dtilde[:,:,:,:,2] - dtilde_front = self._dtilde[:,:,:,:,3] - dtilde_bottom = self._dtilde[:,:,:,:,4] - dtilde_top = self._dtilde[:,:,:,:,5] - dhat_left = self._dhat[:,:,:,:,0] - dhat_right = self._dhat[:,:,:,:,1] - dhat_back = self._dhat[:,:,:,:,2] - dhat_front = self._dhat[:,:,:,:,3] - dhat_bottom = self._dhat[:,:,:,:,4] - dhat_top = self._dhat[:,:,:,:,5] - - dx = self._hxyz[:,:,:,np.newaxis,0] - dy = self._hxyz[:,:,:,np.newaxis,1] - dz = self._hxyz[:,:,:,np.newaxis,2] - - # Define net leakage coefficient for each surface in each matrix - # element - jnet = (((dtilde_right + dhat_right)-(-1.0 * dtilde_left + dhat_left)) - / dx + - ((dtilde_front + dhat_front)-(-1.0 * dtilde_back + dhat_back)) - / dy + - ((dtilde_top + dhat_top)-(-1.0 * dtilde_bottom + dhat_bottom)) - / dz) - - for g in range(ng): - # Define leakage terms that relate terms to their neighbors to the - # left - dtilde = self._dtilde[:,:,:,g,0][self._accel_neig_left_idxs] - dhat = self._dhat[:,:,:,g,0][self._accel_neig_left_idxs] - dx = self._hxyz[:,:,:,0][self._accel_neig_left_idxs] - vals = (-1.0 * dtilde - dhat) / dx - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define leakage terms that relate terms to their neighbors to the - # right - dtilde = self._dtilde[:,:,:,g,1][self._accel_neig_right_idxs] - dhat = self._dhat[:,:,:,g,1][self._accel_neig_right_idxs] - dx = self._hxyz[:,:,:,0][self._accel_neig_right_idxs] - vals = (-1.0 * dtilde + dhat) / dx - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define leakage terms that relate terms to their neighbors in the - # back - dtilde = self._dtilde[:,:,:,g,2][self._accel_neig_back_idxs] - dhat = self._dhat[:,:,:,g,2][self._accel_neig_back_idxs] - dy = self._hxyz[:,:,:,1][self._accel_neig_back_idxs] - vals = (-1.0 * dtilde - dhat) / dy - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define leakage terms that relate terms to their neighbors in the - # front - dtilde = self._dtilde[:,:,:,g,3][self._accel_neig_front_idxs] - dhat = self._dhat[:,:,:,g,3][self._accel_neig_front_idxs] - dy = self._hxyz[:,:,:,1][self._accel_neig_front_idxs] - vals = (-1.0 * dtilde + dhat) / dy - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define leakage terms that relate terms to their neighbors to the - # bottom - dtilde = self._dtilde[:,:,:,g,4][self._accel_neig_bot_idxs] - dhat = self._dhat[:,:,:,g,4][self._accel_neig_bot_idxs] - dz = self._hxyz[:,:,:,2][self._accel_neig_bot_idxs] - vals = (-1.0 * dtilde - dhat) / dz - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define leakage terms that relate terms to their neighbors to the - # top - dtilde = self._dtilde[:,:,:,g,5][self._accel_neig_top_idxs] - dhat = self._dhat[:,:,:,g,5][self._accel_neig_top_idxs] - dz = self._hxyz[:,:,:,2][self._accel_neig_top_idxs] - vals = (-1.0 * dtilde + dhat) / dz - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define terms that relate to loss of neutrons in a cell. These - # correspond to all the diagonal entries of the loss matrix - jnet_g = jnet[:,:,:,g][self._accel_idxs] - total_xs = self._totalxs[:,:,:,g][self._accel_idxs] - scatt_xs = self._scattxs[:,:,:,g,g][self._accel_idxs] - vals = jnet_g + total_xs - scatt_xs - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Define terms that relate to in-scattering from group to group. - # These terms relate a mesh index to all mesh indices with the same - # spatial dimensions but belong to a different energy group - for h in range(ng): - if h != g: - # Get scattering macro xs, transposed - if adjoint: - scatt_xs = self._scattxs[:,:,:,g,h][self._accel_idxs] - # Get scattering macro xs - else: - scatt_xs = self._scattxs[:,:,:,h,g][self._accel_idxs] - vals = -1.0 * scatt_xs - # Store data to add to CSR matrix - data = np.append(data, vals) - - # Create csr matrix - loss_row = self._loss_row - loss_col = self._loss_col - loss = sparse.csr_matrix((data, (loss_row, loss_col)), shape=(n, n)) - return loss - - def _build_prod_matrix(self, adjoint): - # Extract spatial and energy indices and define matrix dimension - ng = self._indices[3] - n = self._mat_dim*ng - - # Define rows, columns, and data used to build csr matrix - data = np.array([]) - - # Define terms that relate to fission production from group to group. - for g in range(ng): - for h in range(ng): - # Get nu-fission macro xs, transposed - if adjoint: - vals = (self._nfissxs[:, :, :, g, h])[self._accel_idxs] - # Get nu-fission macro xs - else: - vals = (self._nfissxs[:, :, :, h, g])[self._accel_idxs] - # Store rows, cols, and data to add to CSR matrix - data = np.append(data, vals) - - # Create csr matrix - prod_row = self._prod_row - prod_col = self._prod_col - prod = sparse.csr_matrix((data, (prod_row, prod_col)), shape=(n, n)) - return prod - - def _execute_power_iter(self, loss, prod): - """Main power iteration routine for the CMFD calculation - - Parameters - ---------- - loss : scipy.sparse.spmatrix - Sparse matrix storing elements of CMFD loss matrix - prod : scipy.sparse.spmatrix - Sparse matrix storing elements of CMFD production matrix - - Returns - ------- - phi_n : numpy.ndarray - Flux vector of CMFD problem - k_n : float - Eigenvalue of CMFD problem - dom : float - Dominance ratio of CMFD problem - - """ - # Get problem size - n = loss.shape[0] - - # Set up tolerances for C++ solver - atoli = self._gauss_seidel_tolerance[0] - rtoli = self._gauss_seidel_tolerance[1] - toli = rtoli * 100 - - # Set up flux vectors, intital guess set to 1 - phi_n = np.ones((n,)) - phi_o = np.ones((n,)) - - # Set up source vectors - s_n = np.zeros((n,)) - s_o = np.zeros((n,)) - - # Set initial guess - k_n = openmc.lib.keff()[0] - k_o = k_n - dw = self._w_shift - k_s = k_o + dw - k_ln = 1.0/(1.0/k_n - 1.0/k_s) - k_lo = k_ln - - # Set norms to 0 - norm_n = 0.0 - norm_o = 0.0 - - # Maximum number of power iterations - maxits = 10000 - - # Perform Wielandt shift - loss -= 1.0/k_s*prod - - # Begin power iteration - for i in range(maxits): - # Check if reach max number of iterations - if i == maxits - 1: - raise OpenMCError('Reached maximum iterations in CMFD power ' - 'iteration solver.') - - # Compute source vector - s_o = prod.dot(phi_o) - - # Normalize source vector - s_o /= k_lo - - # Compute new flux with C++ solver - innerits = openmc.lib._dll.openmc_run_linsolver(loss.data, s_o, - phi_n, toli) - - # Compute new source vector - s_n = prod.dot(phi_n) - - # Compute new shifted eigenvalue - k_ln = np.sum(s_n) / np.sum(s_o) - - # Compute new eigenvalue - k_n = 1.0/(1.0/k_ln + 1.0/k_s) - - # Renormalize the old source - s_o *= k_lo - - # Check convergence - iconv, norm_n = self._check_convergence(s_n, s_o, k_n, k_o, i+1, - innerits) - - # If converged, calculate dominance ratio and break from loop - if iconv: - dom = norm_n / norm_o - return phi_n, k_n, dom - - # Record old values if not converged - phi_o = phi_n - k_o = k_n - k_lo = k_ln - norm_o = norm_n - - # Update tolerance for inner iterations - toli = max(atoli, rtoli*norm_n) - - def _check_convergence(self, s_n, s_o, k_n, k_o, iter, innerits): - """Checks the convergence of the CMFD problem - - Parameters - ---------- - s_n : numpy.ndarray - Source vector from current iteration - s_o : numpy.ndarray - Source vector from previous iteration - k_n : float - K-effective from current iteration - k_o : float - K-effective from previous iteration - iter: int - Iteration number - innerits: int - Number of iterations required for convergence in inner GS loop - - Returns - ------- - iconv : bool - Whether the power iteration has reached convergence - serr : float - Error in source from previous iteration to current iteration, used - for dominance ratio calculations - - """ - # Calculate error in keff - kerr = abs(k_o - k_n) / k_n - - # Calculate max error in source - with np.errstate(divide='ignore', invalid='ignore'): - serr = np.sqrt(np.sum(np.where(s_n > 0, ((s_n-s_o) / s_n)**2, 0)) - / len(s_n)) - - # Check for convergence - iconv = kerr < self._cmfd_ktol and serr < self._stol - - # Print out to user - if self._power_monitor and openmc.lib.master(): - str1 = ' {:d}:'.format(iter) - str2 = 'k-eff: {:0.8f}'.format(k_n) - str3 = 'k-error: {:.5E}'.format(kerr) - str4 = 'src-error: {:.5E}'.format(serr) - str5 = ' {:d}'.format(innerits) - print('{:8s}{:20s}{:25s}{:s}{:s}'.format(str1, str2, str3, str4, - str5)) - sys.stdout.flush() - - return iconv, serr - - def _set_coremap(self): - """Sets the core mapping information. All regions marked with zero - are set to CMFD_NOACCEL, while all regions marked with 1 are set to a - unique index that maps each fuel region to a row number when building - CMFD matrices - - """ - # Set number of accelerated regions in problem. This will be related to - # the dimension of CMFD matrices - self._mat_dim = np.sum(self._coremap) - - # Define coremap as cumulative sum over accelerated regions, - # otherwise set value to _CMFD_NOACCEL - self._coremap = np.where(self._coremap == 0, _CMFD_NOACCEL, - np.cumsum(self._coremap)-1) - - # Reshape coremap to three dimensional array - # Indices of coremap in user input switched in x and z axes - nx, ny, nz = self._indices[:3] - self._coremap = self._coremap.reshape(nz, ny, nx) - self._coremap = np.swapaxes(self._coremap, 0, 2) - - def _compute_xs(self): - """Takes CMFD tallies from OpenMC and computes macroscopic cross - sections, flux, and diffusion coefficients for each mesh cell using - a tally window scheme - - """ - # Update window size for expanding window if necessary - num_cmfd_batches = openmc.lib.current_batch() - self._tally_begin + 1 - if (self._window_type == 'expanding' and - num_cmfd_batches == self._window_size * 2): - self._window_size *= 2 - - # Discard tallies from oldest batch if window limit reached - tally_windows = self._flux_rate.shape[-1] + 1 - if tally_windows > self._window_size: - self._flux_rate = self._flux_rate[...,1:] - self._total_rate = self._total_rate[...,1:] - self._p1scatt_rate = self._p1scatt_rate[...,1:] - self._scatt_rate = self._scatt_rate[...,1:] - self._nfiss_rate = self._nfiss_rate[...,1:] - self._current_rate = self._current_rate[...,1:] - self._openmc_src_rate = self._openmc_src_rate[...,1:] - tally_windows -= 1 - - # Extract spatial and energy indices - nx, ny, nz, ng = self._indices - - # Get tallies in-memory - tallies = openmc.lib.tallies - - # Ravel coremap as 1d array similar to how tally data is arranged - coremap = np.ravel(self._coremap.swapaxes(0, 2)) - - # Set conditional numpy array as boolean vector based on coremap - # Repeat each value for number of groups in problem - is_cmfd_accel = np.repeat(coremap != _CMFD_NOACCEL, ng) - - # Get flux from CMFD tally 0 - tally_id = self._tally_ids[0] - tally_results = tallies[tally_id].results[:,0,1] - flux = np.where(is_cmfd_accel, tally_results, 0.) - - # Detect zero flux, abort if located - if np.any(flux[is_cmfd_accel] < _TINY_BIT): - # Get index of zero flux in flux array - idx = np.argmax(np.where(is_cmfd_accel, flux, 1) < _TINY_BIT) - - # Convert scalar idx to index in flux matrix - mat_idx = np.unravel_index(idx, self._flux.shape) - - # Throw error message (one-based indexing) - # Index of group is flipped - err_message = 'Detected zero flux without coremap overlay' + \ - ' at mesh: (' + \ - ', '.join(str(i+1) for i in mat_idx[:-1]) + \ - ') in group ' + str(ng-mat_idx[-1]) - raise OpenMCError(err_message) - - # Define target tally reshape dimensions. This defines how openmc - # tallies are ordered by dimension - target_tally_shape = [nz, ny, nx, ng, 1] - - # Reshape flux array to target shape. Swap x and z axes so that - # flux shape is now [nx, ny, nz, ng, 1] - reshape_flux = np.swapaxes(flux.reshape(target_tally_shape), 0, 2) - - # Flip energy axis as tally results are given in reverse order of - # energy group - reshape_flux = np.flip(reshape_flux, axis=3) - - # Bank flux to flux_rate - self._flux_rate = np.append(self._flux_rate, reshape_flux, axis=4) - - # Compute flux as aggregate of banked flux_rate over tally window - self._flux = np.sum(self._flux_rate, axis=4) - - # Get total rr from CMFD tally 0 - totalrr = tallies[tally_id].results[:,1,1] - - # Reshape totalrr array to target shape. Swap x and z axes so that - # shape is now [nx, ny, nz, ng, 1] - reshape_totalrr = np.swapaxes(totalrr.reshape(target_tally_shape), - 0, 2) - - # Total rr is flipped in energy axis as tally results are given in - # reverse order of energy group - reshape_totalrr = np.flip(reshape_totalrr, axis=3) - - # Bank total rr to total_rate - self._total_rate = np.append(self._total_rate, reshape_totalrr, - axis=4) - - # Compute total xs as aggregate of banked total_rate over tally window - # divided by flux - self._totalxs = np.divide(np.sum(self._total_rate, axis=4), - self._flux, where=self._flux > 0, - out=np.zeros_like(self._totalxs)) - - # Get scattering rr from CMFD tally 1 - # flux is repeated to account for extra dimensionality of scattering xs - tally_id = self._tally_ids[1] - scattrr = tallies[tally_id].results[:,0,1] - - # Define target tally reshape dimensions for xs with incoming - # and outgoing energies - target_tally_shape = [nz, ny, nx, ng, ng, 1] - - # Reshape scattrr array to target shape. Swap x and z axes so that - # shape is now [nx, ny, nz, ng, ng, 1] - reshape_scattrr = np.swapaxes(scattrr.reshape(target_tally_shape), - 0, 2) - - # Scattering rr is flipped in both incoming and outgoing energy axes - # as tally results are given in reverse order of energy group - reshape_scattrr = np.flip(reshape_scattrr, axis=3) - reshape_scattrr = np.flip(reshape_scattrr, axis=4) - - # Bank scattering rr to scatt_rate - self._scatt_rate = np.append(self._scatt_rate, reshape_scattrr, - axis=5) - - # Compute scattering xs as aggregate of banked scatt_rate over tally - # window divided by flux. Flux dimensionality increased to account for - # extra dimensionality of scattering xs - extended_flux = self._flux[:,:,:,:,np.newaxis] - self._scattxs = np.divide(np.sum(self._scatt_rate, axis=5), - extended_flux, where=extended_flux > 0, - out=np.zeros_like(self._scattxs)) - - # Get nu-fission rr from CMFD tally 1 - nfissrr = tallies[tally_id].results[:,1,1] - num_realizations = tallies[tally_id].num_realizations - - # Reshape nfissrr array to target shape. Swap x and z axes so that - # shape is now [nx, ny, nz, ng, ng, 1] - reshape_nfissrr = np.swapaxes(nfissrr.reshape(target_tally_shape), - 0, 2) - - # Nu-fission rr is flipped in both incoming and outgoing energy axes - # as tally results are given in reverse order of energy group - reshape_nfissrr = np.flip(reshape_nfissrr, axis=3) - reshape_nfissrr = np.flip(reshape_nfissrr, axis=4) - - # Bank nu-fission rr to nfiss_rate - self._nfiss_rate = np.append(self._nfiss_rate, reshape_nfissrr, - axis=5) - - # Compute nu-fission xs as aggregate of banked nfiss_rate over tally - # window divided by flux. Flux dimensionality increased to account for - # extra dimensionality of nu-fission xs - self._nfissxs = np.divide(np.sum(self._nfiss_rate, axis=5), - extended_flux, where=extended_flux > 0, - out=np.zeros_like(self._nfissxs)) - - # Openmc source distribution is sum of nu-fission rr in incoming - # energies - openmc_src = np.sum(reshape_nfissrr, axis=3) - - # Bank OpenMC source distribution from current batch to - # openmc_src_rate - self._openmc_src_rate = np.append(self._openmc_src_rate, openmc_src, - axis=4) - - # Compute source distribution over entire tally window - self._openmc_src = np.sum(self._openmc_src_rate, axis=4) - - # Compute k_eff from source distribution - self._keff_bal = (np.sum(self._openmc_src) / num_realizations / - tally_windows) - - # Normalize openmc source distribution - self._openmc_src /= np.sum(self._openmc_src) * self._norm - - # Get surface currents from CMFD tally 2 - tally_id = self._tally_ids[2] - tally_results = tallies[tally_id].results[:,0,1] - - # Filter tally results to include only accelerated regions - current = np.where(np.repeat(is_cmfd_accel, 12), tally_results, 0.) - - # Define target tally reshape dimensions for current - target_tally_shape = [nz, ny, nx, 12, ng, 1] - - # Reshape current array to target shape. Swap x and z axes so that - # shape is now [nx, ny, nz, 12, ng, 1] - reshape_current = np.swapaxes(current.reshape(target_tally_shape), - 0, 2) - - # Current is flipped in energy axis as tally results are given in - # reverse order of energy group - reshape_current = np.flip(reshape_current, axis=4) - - # Bank current to current_rate - self._current_rate = np.append(self._current_rate, reshape_current, - axis=5) - - # Compute current as aggregate of banked current_rate over tally window - self._current = np.sum(self._current_rate, axis=5) - - # Get p1 scatter rr from CMFD tally 3 - tally_id = self._tally_ids[3] - p1scattrr = tallies[tally_id].results[:,0,1] - - # Define target tally reshape dimensions for p1 scatter tally - target_tally_shape = [nz, ny, nx, 2, ng, 1] - - # Reshape and extract only p1 data from tally results as there is - # no need for p0 data - reshape_p1scattrr = np.swapaxes(p1scattrr.reshape(target_tally_shape), - 0, 2)[:,:,:,1,:,:] - - # p1-scatter rr is flipped in energy axis as tally results are given in - # reverse order of energy group - reshape_p1scattrr = np.flip(reshape_p1scattrr, axis=3) - - # Bank p1-scatter rr to p1scatt_rate - self._p1scatt_rate = np.append(self._p1scatt_rate, reshape_p1scattrr, - axis=4) - - # Compute p1-scatter xs as aggregate of banked p1scatt_rate over tally - # window divided by flux - self._p1scattxs = np.divide(np.sum(self._p1scatt_rate, axis=4), - self._flux, where=self._flux > 0, - out=np.zeros_like(self._p1scattxs)) - - if self._set_reference_params: - # Set diffusion coefficients based on reference value - self._diffcof = np.where(self._flux > 0, - self._ref_d[None, None, None, :], 0.0) - else: - # Calculate and store diffusion coefficient - with np.errstate(divide='ignore', invalid='ignore'): - self._diffcof = np.where(self._flux > 0, 1.0 / (3.0 * - (self._totalxs-self._p1scattxs)), 0.) - - def _compute_effective_downscatter(self): - """Changes downscatter rate for zero upscatter""" - # Extract energy index - ng = self._indices[3] - - # Return if not two groups - if ng != 2: - return - - # Extract cross sections and flux for each group - flux1 = self._flux[:,:,:,0] - flux2 = self._flux[:,:,:,1] - sigt1 = self._totalxs[:,:,:,0] - sigt2 = self._totalxs[:,:,:,1] - - # First energy index is incoming energy, second is outgoing energy - sigs11 = self._scattxs[:,:,:,0,0] - sigs21 = self._scattxs[:,:,:,1,0] - sigs12 = self._scattxs[:,:,:,0,1] - sigs22 = self._scattxs[:,:,:,1,1] - - # Compute absorption xs - siga1 = sigt1 - sigs11 - sigs12 - siga2 = sigt2 - sigs22 - sigs21 - - # Compute effective downscatter XS - sigs12_eff = sigs12 - sigs21 * np.divide(flux2, flux1, - where=flux1 > 0, - out=np.zeros_like(flux2)) - - # Recompute total cross sections and record - self._totalxs[:,:,:,0] = siga1 + sigs11 + sigs12_eff - self._totalxs[:,:,:,1] = siga2 + sigs22 - - # Record effective dowmscatter xs - self._scattxs[:,:,:,0,1] = sigs12_eff - - # Zero out upscatter cross section - self._scattxs[:,:,:,1,0] = 0.0 - - def _neutron_balance(self): - """Computes the RMS neutron balance over the CMFD mesh""" - # Extract energy indices - ng = self._indices[3] - - # Get number of accelerated regions - num_accel = self._mat_dim - - # Get openmc k-effective - keff = openmc.lib.keff()[0] - - # Define leakage in each mesh cell and energy group - leakage = (((self._current[:,:,:,_CURRENTS['out_right'],:] - - self._current[:,:,:,_CURRENTS['in_right'],:]) - - (self._current[:,:,:,_CURRENTS['in_left'],:] - - self._current[:,:,:,_CURRENTS['out_left'],:])) + - ((self._current[:,:,:,_CURRENTS['out_front'],:] - - self._current[:,:,:,_CURRENTS['in_front'],:]) - - (self._current[:,:,:,_CURRENTS['in_back'],:] - - self._current[:,:,:,_CURRENTS['out_back'],:])) + - ((self._current[:,:,:,_CURRENTS['out_top'],:] - - self._current[:,:,:,_CURRENTS['in_top'],:]) - - (self._current[:,:,:,_CURRENTS['in_bottom'],:] - - self._current[:,:,:,_CURRENTS['out_bottom'],:]))) - - # Compute total rr - interactions = self._totalxs * self._flux - - # Compute scattering rr by broadcasting flux in outgoing energy and - # summing over incoming energy - scattering = np.sum(self._scattxs * self._flux[:,:,:,:,np.newaxis], - axis=3) - - # Compute fission rr by broadcasting flux in outgoing energy and - # summing over incoming energy - fission = np.sum(self._nfissxs * self._flux[:,:,:,:,np.newaxis], - axis=3) - - # Compute residual - res = leakage + interactions - scattering - (1.0 / keff) * fission - - # Normalize res by flux and bank res - self._resnb = np.divide(res, self._flux, where=self._flux > 0) - - # Calculate RMS and record for this batch - self._balance.append(np.sqrt( - np.sum(np.multiply(self._resnb, self._resnb)) / - (ng * num_accel))) - - def _precompute_array_indices(self): - """Computes the indices used to populate certain cross section arrays. - These indices are used in _compute_dtilde and _compute_dhat - - """ - # Extract spatial indices - nx, ny, nz = self._indices[:3] - - # Logical for determining whether region of interest is accelerated - # region - is_accel = self._coremap != _CMFD_NOACCEL - # Logical for determining whether a zero flux "albedo" b.c. should be - # applied - is_zero_flux_alb = abs(self._albedo - _ZERO_FLUX) < _TINY_BIT - x_inds, y_inds, z_inds = np.indices((nx, ny, nz)) - - # Define slice equivalent to is_accel[0,:,:] - slice_x = x_inds[:1,:,:] - slice_y = y_inds[:1,:,:] - slice_z = z_inds[:1,:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._first_x_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[-1,:,:] - slice_x = x_inds[-1:,:,:] - slice_y = y_inds[-1:,:,:] - slice_z = z_inds[-1:,:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._last_x_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,0,:] - slice_x = x_inds[:,:1,:] - slice_y = y_inds[:,:1,:] - slice_z = z_inds[:,:1,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._first_y_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,-1,:] - slice_x = x_inds[:,-1:,:] - slice_y = y_inds[:,-1:,:] - slice_z = z_inds[:,-1:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._last_y_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,:,0] - slice_x = x_inds[:,:,:1] - slice_y = y_inds[:,:,:1] - slice_z = z_inds[:,:,:1] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._first_z_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,:,-1] - slice_x = x_inds[:,:,-1:] - slice_y = y_inds[:,:,-1:] - slice_z = z_inds[:,:,-1:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._last_z_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[1:,:,:] - slice_x = x_inds[1:,:,:] - slice_y = y_inds[1:,:,:] - slice_z = z_inds[1:,:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notfirst_x_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:-1,:,:] - slice_x = x_inds[:-1,:,:] - slice_y = y_inds[:-1,:,:] - slice_z = z_inds[:-1,:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notlast_x_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,1:,:] - slice_x = x_inds[:,1:,:] - slice_y = y_inds[:,1:,:] - slice_z = z_inds[:,1:,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notfirst_y_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,:-1,:] - slice_x = x_inds[:,:-1,:] - slice_y = y_inds[:,:-1,:] - slice_z = z_inds[:,:-1,:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notlast_y_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,:,1:] - slice_x = x_inds[:,:,1:] - slice_y = y_inds[:,:,1:] - slice_z = z_inds[:,:,1:] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notfirst_z_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Define slice equivalent to is_accel[:,:,:-1] - slice_x = x_inds[:,:,:-1] - slice_y = y_inds[:,:,:-1] - slice_z = z_inds[:,:,:-1] - bndry_accel = is_accel[(slice_x, slice_y, slice_z)] - self._notlast_z_accel = (slice_x[bndry_accel], slice_y[bndry_accel], - slice_z[bndry_accel]) - - # Store logical for whether neighboring cell is reflector region - # in all directions - adj_reflector_left = np.roll(self._coremap, 1, axis=0) == _CMFD_NOACCEL - self._is_adj_ref_left = adj_reflector_left[ - self._notfirst_x_accel + (np.newaxis,)] - - adj_reflector_right = np.roll(self._coremap, -1, axis=0) == \ - _CMFD_NOACCEL - self._is_adj_ref_right = adj_reflector_right[ - self._notlast_x_accel + (np.newaxis,)] - - adj_reflector_back = np.roll(self._coremap, 1, axis=1) == \ - _CMFD_NOACCEL - self._is_adj_ref_back = adj_reflector_back[ - self._notfirst_y_accel + (np.newaxis,)] - - adj_reflector_front = np.roll(self._coremap, -1, axis=1) == \ - _CMFD_NOACCEL - self._is_adj_ref_front = adj_reflector_front[ - self._notlast_y_accel + (np.newaxis,)] - - adj_reflector_bottom = np.roll(self._coremap, 1, axis=2) == \ - _CMFD_NOACCEL - self._is_adj_ref_bottom = adj_reflector_bottom[ - self._notfirst_z_accel + (np.newaxis,)] - - adj_reflector_top = np.roll(self._coremap, -1, axis=2) == \ - _CMFD_NOACCEL - self._is_adj_ref_top = adj_reflector_top[ - self._notlast_z_accel + (np.newaxis,)] - - def _precompute_matrix_indices(self): - """Computes the indices and row/column data used to populate CMFD CSR - matrices. These indices are used in _build_loss_matrix and - _build_prod_matrix. - - """ - # Extract energy group indices - ng = self._indices[3] - - # Shift coremap in all directions to determine whether leakage term - # should be defined for particular cell in matrix - coremap_shift_left = np.pad(self._coremap, ((1,0),(0,0),(0,0)), - mode='constant', - constant_values=_CMFD_NOACCEL)[:-1,:,:] - - coremap_shift_right = np.pad(self._coremap, ((0,1),(0,0),(0,0)), - mode='constant', - constant_values=_CMFD_NOACCEL)[1:,:,:] - - coremap_shift_back = np.pad(self._coremap, ((0,0),(1,0),(0,0)), - mode='constant', - constant_values=_CMFD_NOACCEL)[:,:-1,:] - - coremap_shift_front = np.pad(self._coremap, ((0,0),(0,1),(0,0)), - mode='constant', - constant_values=_CMFD_NOACCEL)[:,1:,:] - - coremap_shift_bottom = np.pad(self._coremap, ((0,0),(0,0),(1,0)), - mode='constant', - constant_values=_CMFD_NOACCEL)[:,:,:-1] - - coremap_shift_top = np.pad(self._coremap, ((0,0),(0,0),(0,1)), - mode='constant', - constant_values=_CMFD_NOACCEL)[:,:,1:] - - # Create empty row and column vectors to store for loss matrix - row = np.array([]) - col = np.array([]) - - # Store all indices used to populate production and loss matrix - is_accel = self._coremap != _CMFD_NOACCEL - self._accel_idxs = np.where(is_accel) - self._accel_neig_left_idxs = (np.where(is_accel & - (coremap_shift_left != _CMFD_NOACCEL))) - self._accel_neig_right_idxs = (np.where(is_accel & - (coremap_shift_right != _CMFD_NOACCEL))) - self._accel_neig_back_idxs = (np.where(is_accel & - (coremap_shift_back != _CMFD_NOACCEL))) - self._accel_neig_front_idxs = (np.where(is_accel & - (coremap_shift_front != _CMFD_NOACCEL))) - self._accel_neig_bot_idxs = (np.where(is_accel & - (coremap_shift_bottom != _CMFD_NOACCEL))) - self._accel_neig_top_idxs = (np.where(is_accel & - (coremap_shift_top != _CMFD_NOACCEL))) - - for g in range(ng): - # Extract row and column data of regions where a cell and its - # neighbor to the left are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_left_idxs]) + g - idx_y = ng * (coremap_shift_left[self._accel_neig_left_idxs]) + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract row and column data of regions where a cell and its - # neighbor to the right are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_right_idxs]) + g - idx_y = ng * (coremap_shift_right[self._accel_neig_right_idxs]) + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract row and column data of regions where a cell and its - # neighbor to the back are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_back_idxs]) + g - idx_y = ng * (coremap_shift_back[self._accel_neig_back_idxs]) + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract row and column data of regions where a cell and its - # neighbor to the front are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_front_idxs]) + g - idx_y = ng * (coremap_shift_front[self._accel_neig_front_idxs]) + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract row and column data of regions where a cell and its - # neighbor to the bottom are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_bot_idxs]) + g - idx_y = ng * (coremap_shift_bottom[self._accel_neig_bot_idxs]) \ - + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract row and column data of regions where a cell and its - # neighbor to the top are both fuel regions - idx_x = ng * (self._coremap[self._accel_neig_top_idxs]) + g - idx_y = ng * (coremap_shift_top[self._accel_neig_top_idxs]) + g - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Extract all regions where a cell is a fuel region - idx_x = ng * (self._coremap[self._accel_idxs]) + g - idx_y = idx_x - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - for h in range(ng): - if h != g: - # Extract all regions where a cell is a fuel region - idx_x = ng * (self._coremap[self._accel_idxs]) + g - idx_y = ng * (self._coremap[self._accel_idxs]) + h - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Store row and col as rows and columns of production matrix - self._loss_row = row - self._loss_col = col - - # Create empty row and column vectors to store for production matrix - row = np.array([], dtype=int) - col = np.array([], dtype=int) - - for g in range(ng): - for h in range(ng): - # Extract all regions where a cell is a fuel region - idx_x = ng * (self._coremap[self._accel_idxs]) + g - idx_y = ng * (self._coremap[self._accel_idxs]) + h - # Store rows, cols, and data to add to CSR matrix - row = np.append(row, idx_x) - col = np.append(col, idx_y) - - # Store row and col as rows and columns of production matrix - self._prod_row = row - self._prod_col = col - - def _compute_dtilde(self): - """Computes the diffusion coupling coefficient using a vectorized numpy - approach. Aggregate values for the dtilde multidimensional array are - populated by first defining values on the problem boundary, and then - for all other regions. For indices not lying on a boundary, dtilde - values are distinguished between regions that neighbor a reflector - region and regions that don't neighbor a reflector - - """ - # Logical for determining whether a zero flux "albedo" b.c. should be - # applied - is_zero_flux_alb = abs(self._albedo - _ZERO_FLUX) < _TINY_BIT - - # Define dtilde at left surface for all mesh cells on left boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._first_x_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dx = self._hxyz[boundary + (np.newaxis, 0)] - if is_zero_flux_alb[0]: - self._dtilde[boundary_grps + (0,)] = 2.0 * D / dx - else: - alb = self._albedo[0] - self._dtilde[boundary_grps + (0,)] = ((2.0 * D * (1.0 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dx)) - - # Define dtilde at right surface for all mesh cells on right boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._last_x_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dx = self._hxyz[boundary + (np.newaxis, 0)] - if is_zero_flux_alb[1]: - self._dtilde[boundary_grps + (1,)] = 2.0 * D / dx - else: - alb = self._albedo[1] - self._dtilde[boundary_grps + (1,)] = ((2.0 * D * (1.0 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dx)) - - # Define dtilde at back surface for all mesh cells on back boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._first_y_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dy = self._hxyz[boundary + (np.newaxis, 1)] - if is_zero_flux_alb[2]: - self._dtilde[boundary_grps + (2,)] = 2.0 * D / dy - else: - alb = self._albedo[2] - self._dtilde[boundary_grps + (2,)] = ((2.0 * D * (1.0 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dy)) - - # Define dtilde at front surface for all mesh cells on front boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._last_y_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dy = self._hxyz[boundary + (np.newaxis, 1)] - if is_zero_flux_alb[3]: - self._dtilde[boundary_grps + (3,)] = 2.0 * D / dy - else: - alb = self._albedo[3] - self._dtilde[boundary_grps + (3,)] = ((2.0 * D * (1.0 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dy)) - - # Define dtilde at bottom surface for all mesh cells on bottom boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._first_z_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dz = self._hxyz[boundary + (np.newaxis, 2)] - if is_zero_flux_alb[4]: - self._dtilde[boundary_grps + (4,)] = 2.0 * D / dz - else: - alb = self._albedo[4] - self._dtilde[boundary_grps + (4,)] = ((2.0 * D * (1.0 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dz)) - - # Define dtilde at top surface for all mesh cells on top boundary - # Separate between zero flux b.c. and alebdo b.c. - boundary = self._last_z_accel - boundary_grps = boundary + (slice(None),) - - D = self._diffcof[boundary_grps] - dz = self._hxyz[boundary + (np.newaxis, 2)] - if is_zero_flux_alb[5]: - self._dtilde[boundary_grps + (5,)] = 2.0 * D / dz - else: - alb = self._albedo[5] - self._dtilde[boundary_grps + (5,)] = ((2.0 * D * (1 - alb)) - / (4.0 * D * (1.0 + alb) + - (1.0 - alb) * dz)) - - # Define reflector albedo for all cells on the left surface, in case - # a cell borders a reflector region on the left - current_in_left = self._current[:,:,:,_CURRENTS['in_left'],:] - current_out_left = self._current[:,:,:,_CURRENTS['out_left'],:] - ref_albedo = np.divide(current_in_left, current_out_left, - where=current_out_left > 1.0e-10, - out=np.ones_like(current_out_left)) - - # Diffusion coefficient of neighbor to left - neig_dc = np.roll(self._diffcof, 1, axis=0) - # Cell dimensions of neighbor to left - neig_hxyz = np.roll(self._hxyz, 1, axis=0) - - # Define dtilde at left surface for all mesh cells not on left boundary - # Dtilde is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notfirst_x_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dx = self._hxyz[boundary + (np.newaxis, 0)] - neig_D = neig_dc[boundary_grps] - neig_dx = neig_hxyz[boundary + (np.newaxis, 0)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_left - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dx), - (2.0 * D * neig_D) / (neig_dx * D + dx * neig_D)) - self._dtilde[boundary_grps + (0,)] = dtilde - - # Define reflector albedo for all cells on the right surface, in case - # a cell borders a reflector region on the right - current_in_right = self._current[:,:,:,_CURRENTS['in_right'],:] - current_out_right = self._current[:,:,:,_CURRENTS['out_right'],:] - ref_albedo = np.divide(current_in_right, current_out_right, - where=current_out_right > 1.0e-10, - out=np.ones_like(current_out_right)) - - # Diffusion coefficient of neighbor to right - neig_dc = np.roll(self._diffcof, -1, axis=0) - # Cell dimensions of neighbor to right - neig_hxyz = np.roll(self._hxyz, -1, axis=0) - - # Define dtilde at right surface for all mesh cells not on right - # boundary. Dtilde is defined differently for regions that do and don't - # neighbor reflector regions - boundary = self._notlast_x_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dx = self._hxyz[boundary + (np.newaxis, 0)] - neig_D = neig_dc[boundary_grps] - neig_dx = neig_hxyz[boundary + (np.newaxis, 0)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_right - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dx), - (2.0 * D * neig_D) / (neig_dx * D + dx * neig_D)) - self._dtilde[boundary_grps + (1,)] = dtilde - - # Define reflector albedo for all cells on the back surface, in case - # a cell borders a reflector region on the back - current_in_back = self._current[:,:,:,_CURRENTS['in_back'],:] - current_out_back = self._current[:,:,:,_CURRENTS['out_back'],:] - ref_albedo = np.divide(current_in_back, current_out_back, - where=current_out_back > 1.0e-10, - out=np.ones_like(current_out_back)) - - # Diffusion coefficient of neighbor to back - neig_dc = np.roll(self._diffcof, 1, axis=1) - # Cell dimensions of neighbor to back - neig_hxyz = np.roll(self._hxyz, 1, axis=1) - - # Define dtilde at back surface for all mesh cells not on back boundary - # Dtilde is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notfirst_y_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dy = self._hxyz[boundary + (np.newaxis, 1)] - neig_D = neig_dc[boundary_grps] - neig_dy = neig_hxyz[boundary + (np.newaxis, 1)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_back - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dy), - (2.0 * D * neig_D) / (neig_dy * D + dy * neig_D)) - self._dtilde[boundary_grps + (2,)] = dtilde - - # Define reflector albedo for all cells on the front surface, in case - # a cell borders a reflector region in the front - current_in_front = self._current[:,:,:,_CURRENTS['in_front'],:] - current_out_front = self._current[:,:,:,_CURRENTS['out_front'],:] - ref_albedo = np.divide(current_in_front, current_out_front, - where=current_out_front > 1.0e-10, - out=np.ones_like(current_out_front)) - - # Diffusion coefficient of neighbor to front - neig_dc = np.roll(self._diffcof, -1, axis=1) - # Cell dimensions of neighbor to front - neig_hxyz = np.roll(self._hxyz, -1, axis=1) - - # Define dtilde at front surface for all mesh cells not on front - # boundary. Dtilde is defined differently for regions that do and don't - # neighbor reflector regions - boundary = self._notlast_y_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dy = self._hxyz[boundary + (np.newaxis, 1)] - neig_D = neig_dc[boundary_grps] - neig_dy = neig_hxyz[boundary + (np.newaxis, 1)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_front - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dy), - (2.0 * D * neig_D) / (neig_dy * D + dy * neig_D)) - self._dtilde[boundary_grps + (3,)] = dtilde - - # Define reflector albedo for all cells on the bottom surface, in case - # a cell borders a reflector region on the bottom - current_in_bottom = self._current[:,:,:,_CURRENTS['in_bottom'],:] - current_out_bottom = self._current[:,:,:,_CURRENTS['out_bottom'],:] - ref_albedo = np.divide(current_in_bottom, current_out_bottom, - where=current_out_bottom > 1.0e-10, - out=np.ones_like(current_out_bottom)) - - # Diffusion coefficient of neighbor to bottom - neig_dc = np.roll(self._diffcof, 1, axis=2) - # Cell dimensions of neighbor to bottom - neig_hxyz = np.roll(self._hxyz, 1, axis=2) - - # Define dtilde at bottom surface for all mesh cells not on bottom - # boundary. Dtilde is defined differently for regions that do and don't - # neighbor reflector regions - boundary = self._notfirst_z_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dz = self._hxyz[boundary + (np.newaxis, 2)] - neig_D = neig_dc[boundary_grps] - neig_dz = neig_hxyz[boundary + (np.newaxis, 2)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_bottom - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dz), - (2.0 * D * neig_D) / (neig_dz * D + dz * neig_D)) - self._dtilde[boundary_grps + (4,)] = dtilde - - # Define reflector albedo for all cells on the top surface, in case - # a cell borders a reflector region on the top - current_in_top = self._current[:,:,:,_CURRENTS['in_top'],:] - current_out_top = self._current[:,:,:,_CURRENTS['out_top'],:] - ref_albedo = np.divide(current_in_top, current_out_top, - where=current_out_top > 1.0e-10, - out=np.ones_like(current_out_top)) - - # Diffusion coefficient of neighbor to top - neig_dc = np.roll(self._diffcof, -1, axis=2) - # Cell dimensions of neighbor to top - neig_hxyz = np.roll(self._hxyz, -1, axis=2) - - # Define dtilde at top surface for all mesh cells not on top boundary - # Dtilde is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notlast_z_accel - boundary_grps = boundary + (slice(None),) - D = self._diffcof[boundary_grps] - dz = self._hxyz[boundary + (np.newaxis, 2)] - neig_D = neig_dc[boundary_grps] - neig_dz = neig_hxyz[boundary + (np.newaxis, 2)] - alb = ref_albedo[boundary_grps] - is_adj_ref = self._is_adj_ref_top - dtilde = np.where(is_adj_ref, (2.0 * D * (1.0 - alb)) / - (4.0 * D * (1.0 + alb) + (1.0 - alb) * dz), - (2.0 * D * neig_D) / (neig_dz * D + dz * neig_D)) - self._dtilde[boundary_grps + (5,)] = dtilde - - def _compute_dhat(self): - """Computes the nonlinear coupling coefficient using a vectorized numpy - approach. Aggregate values for the dhat multidimensional array are - populated by first defining values on the problem boundary, and then - for all other regions. For indices not lying by a boundary, dhat values - are distinguished between regions that neighbor a reflector region and - regions that don't neighbor a reflector - - """ - # Define current in each direction - current_in_left = self._current[:,:,:,_CURRENTS['in_left'],:] - current_out_left = self._current[:,:,:,_CURRENTS['out_left'],:] - current_in_right = self._current[:,:,:,_CURRENTS['in_right'],:] - current_out_right = self._current[:,:,:,_CURRENTS['out_right'],:] - current_in_back = self._current[:,:,:,_CURRENTS['in_back'],:] - current_out_back = self._current[:,:,:,_CURRENTS['out_back'],:] - current_in_front = self._current[:,:,:,_CURRENTS['in_front'],:] - current_out_front = self._current[:,:,:,_CURRENTS['out_front'],:] - current_in_bottom = self._current[:,:,:,_CURRENTS['in_bottom'],:] - current_out_bottom = self._current[:,:,:,_CURRENTS['out_bottom'],:] - current_in_top = self._current[:,:,:,_CURRENTS['in_top'],:] - current_out_top = self._current[:,:,:,_CURRENTS['out_top'],:] - - dx = self._hxyz[:,:,:,np.newaxis,0] - dy = self._hxyz[:,:,:,np.newaxis,1] - dz = self._hxyz[:,:,:,np.newaxis,2] - dxdydz = np.prod(self._hxyz, axis=3)[:,:,:,np.newaxis] - - # Define net current on each face - net_current_left = (current_in_left - current_out_left) / dxdydz * dx - net_current_right = (current_out_right - current_in_right) / dxdydz * \ - dx - net_current_back = (current_in_back - current_out_back) / dxdydz * dy - net_current_front = (current_out_front - current_in_front) / dxdydz * \ - dy - net_current_bottom = (current_in_bottom - current_out_bottom) / \ - dxdydz * dz - net_current_top = (current_out_top - current_in_top) / dxdydz * dz - - # Define flux in each cell - cell_flux = self._flux / dxdydz - # Extract indices of coremap that are accelerated - is_accel = self._coremap != _CMFD_NOACCEL - - # Define dhat at left surface for all mesh cells on left boundary - boundary = self._first_x_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_left[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 0)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (0,)] = (net_current + dtilde * flux) / flux - - # Define dhat at right surface for all mesh cells on right boundary - boundary = self._last_x_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_right[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 1)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (1,)] = (net_current - dtilde * flux) / flux - - # Define dhat at back surface for all mesh cells on back boundary - boundary = self._first_y_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_back[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 2)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (2,)] = (net_current + dtilde * flux) / flux - - # Define dhat at front surface for all mesh cells on front boundary - boundary = self._last_y_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_front[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 3)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (3,)] = (net_current - dtilde * flux) / flux - - # Define dhat at bottom surface for all mesh cells on bottom boundary - boundary = self._first_z_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_bottom[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 4)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (4,)] = (net_current + dtilde * flux) / flux - - # Define dhat at top surface for all mesh cells on top boundary - boundary = self._last_z_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_top[boundary_grps] - dtilde = self._dtilde[boundary + (slice(None), 5)] - flux = cell_flux[boundary_grps] - self._dhat[boundary_grps + (5,)] = (net_current - dtilde * flux) / flux - - # Cell flux of neighbor to left - neig_flux = np.roll(self._flux, 1, axis=0) / dxdydz - - # Define dhat at left surface for all mesh cells not on left boundary - # Dhat is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notfirst_x_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_left[boundary_grps] - dtilde = self._dtilde[boundary_grps + (0,)] - flux = cell_flux[boundary_grps] - flux_left = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_left - dhat = np.where(is_adj_ref, (net_current + dtilde * flux) / flux, - (net_current - dtilde * (flux_left - flux)) / - (flux_left + flux)) - self._dhat[boundary_grps + (0,)] = dhat - - # Cell flux of neighbor to right - neig_flux = np.roll(self._flux, -1, axis=0) / dxdydz - - # Define dhat at right surface for all mesh cells not on right boundary - # Dhat is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notlast_x_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_right[boundary_grps] - dtilde = self._dtilde[boundary_grps + (1,)] - flux = cell_flux[boundary_grps] - flux_right = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_right - dhat = np.where(is_adj_ref, (net_current - dtilde * flux) / flux, - (net_current + dtilde * (flux_right - flux)) / - (flux_right + flux)) - self._dhat[boundary_grps + (1,)] = dhat - - # Cell flux of neighbor to back - neig_flux = np.roll(self._flux, 1, axis=1) / dxdydz - - # Define dhat at back surface for all mesh cells not on back boundary - # Dhat is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notfirst_y_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_back[boundary_grps] - dtilde = self._dtilde[boundary_grps + (2,)] - flux = cell_flux[boundary_grps] - flux_back = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_back - dhat = np.where(is_adj_ref, (net_current + dtilde * flux) / flux, - (net_current - dtilde * (flux_back - flux)) / - (flux_back + flux)) - self._dhat[boundary_grps + (2,)] = dhat - - # Cell flux of neighbor to front - neig_flux = np.roll(self._flux, -1, axis=1) / dxdydz - - # Define dhat at front surface for all mesh cells not on front boundary - # Dhat is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notlast_y_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_front[boundary_grps] - dtilde = self._dtilde[boundary_grps + (3,)] - flux = cell_flux[boundary_grps] - flux_front = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_front - dhat = np.where(is_adj_ref, (net_current - dtilde * flux) / flux, - (net_current + dtilde * (flux_front - flux)) / - (flux_front + flux)) - self._dhat[boundary_grps + (3,)] = dhat - - # Cell flux of neighbor to bottom - neig_flux = np.roll(self._flux, 1, axis=2) / dxdydz - - # Define dhat at bottom surface for all mesh cells not on bottom - # boundary. Dhat is defined differently for regions that do and don't - # neighbor reflector regions - boundary = self._notfirst_z_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_bottom[boundary_grps] - dtilde = self._dtilde[boundary_grps + (4,)] - flux = cell_flux[boundary_grps] - flux_bottom = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_bottom - dhat = np.where(is_adj_ref, (net_current + dtilde * flux) / flux, - (net_current - dtilde * (flux_bottom - flux)) / - (flux_bottom + flux)) - self._dhat[boundary_grps + (4,)] = dhat - - # Cell flux of neighbor to top - neig_flux = np.roll(self._flux, -1, axis=2) / dxdydz - - # Define dhat at top surface for all mesh cells not on top boundary - # Dhat is defined differently for regions that do and don't neighbor - # reflector regions - boundary = self._notlast_z_accel - boundary_grps = boundary + (slice(None),) - net_current = net_current_top[boundary_grps] - dtilde = self._dtilde[boundary_grps + (5,)] - flux = cell_flux[boundary_grps] - flux_top = neig_flux[boundary_grps] - is_adj_ref = self._is_adj_ref_top - dhat = np.where(is_adj_ref, (net_current - dtilde * flux) / flux, - (net_current + dtilde * (flux_top - flux)) / - (flux_top + flux)) - self._dhat[boundary_grps + (5,)] = dhat - - def _create_cmfd_tally(self): - """Creates all tallies in-memory that are used to solve CMFD problem""" - # Create Mesh object based on CMFDMesh, stored internally - cmfd_mesh = openmc.lib.RegularMesh() - # Store id of mesh object - self._mesh_id = cmfd_mesh.id - # Set dimension and parameters of mesh object - cmfd_mesh.dimension = self._mesh.dimension - cmfd_mesh.set_parameters(lower_left=self._mesh.lower_left, - upper_right=self._mesh.upper_right, - width=self._mesh.width) - - # Create mesh Filter object, stored internally - mesh_filter = openmc.lib.MeshFilter() - # Set mesh for Mesh Filter - mesh_filter.mesh = cmfd_mesh - - # Set up energy filters, if applicable - if self._energy_filters: - # Create Energy Filter object, stored internally - energy_filter = openmc.lib.EnergyFilter() - # Set bins for Energy Filter - energy_filter.bins = self._egrid - - # Create Energy Out Filter object, stored internally - energyout_filter = openmc.lib.EnergyoutFilter() - # Set bins for Energy Filter - energyout_filter.bins = self._egrid - - # Create Mesh Surface Filter object, stored internally - meshsurface_filter = openmc.lib.MeshSurfaceFilter() - # Set mesh for Mesh Surface Filter - meshsurface_filter.mesh = cmfd_mesh - - # Create Legendre Filter object, stored internally - legendre_filter = openmc.lib.LegendreFilter() - # Set order for Legendre Filter - legendre_filter.order = 1 - - # Create CMFD tallies, stored internally - n_tallies = 4 - self._tally_ids = [] - for i in range(n_tallies): - cmfd_tally = openmc.lib.Tally() - # Set nuclide bins - cmfd_tally.nuclides = ['total'] - self._tally_ids.append(cmfd_tally.id) - - # Set attributes of CMFD flux, total tally - if i == 0: - # Set filters for tally - if self._energy_filters: - cmfd_tally.filters = [mesh_filter, energy_filter] - else: - cmfd_tally.filters = [mesh_filter] - # Set scores, type, and estimator for tally - cmfd_tally.scores = ['flux', 'total'] - cmfd_tally.type = 'volume' - cmfd_tally.estimator = 'analog' - - # Set attributes of CMFD neutron production tally - elif i == 1: - # Set filters for tally - if self._energy_filters: - cmfd_tally.filters = [mesh_filter, energy_filter, - energyout_filter] - else: - cmfd_tally.filters = [mesh_filter] - # Set scores, type, and estimator for tally - cmfd_tally.scores = ['nu-scatter', 'nu-fission'] - cmfd_tally.type = 'volume' - cmfd_tally.estimator = 'analog' - - # Set attributes of CMFD surface current tally - elif i == 2: - # Set filters for tally - if self._energy_filters: - cmfd_tally.filters = [meshsurface_filter, energy_filter] - else: - cmfd_tally.filters = [meshsurface_filter] - # Set scores, type, and estimator for tally - cmfd_tally.scores = ['current'] - cmfd_tally.type = 'mesh-surface' - cmfd_tally.estimator = 'analog' - - # Set attributes of CMFD P1 scatter tally - elif i == 3: - # Set filters for tally - if self._energy_filters: - cmfd_tally.filters = [mesh_filter, legendre_filter, - energy_filter] - else: - cmfd_tally.filters = [mesh_filter, legendre_filter] - # Set scores for tally - cmfd_tally.scores = ['scatter'] - cmfd_tally.type = 'volume' - cmfd_tally.estimator = 'analog' - - # Set all tallies to be active from beginning - cmfd_tally.active = True diff --git a/openmc/data/BREMX.DAT b/openmc/data/BREMX.DAT deleted file mode 100644 index 612dd728e..000000000 --- a/openmc/data/BREMX.DAT +++ /dev/null @@ -1,28521 +0,0 @@ - BREMSPEC-2 @D TOTAL ELECTRON-ATOM BREMSSTRAHLUNG SPECTRA, - (BETA**2/Z**2)*K*(DSIGMA/DK) IN MB, FOR Z = 1 TO 100 AND FOR - INCIDENT ELECTRON KINETIC ENERGIES FROM 1 KEV TO 10 GEV. - S. M. SELTZER, NATIONAL BUREAU OF STANDARDS, 5 SEP 84. - 57 30 - 0.00100 0.00150 0.00200 0.00300 0.00400 0.00500 - 0.00600 0.00800 0.01000 0.01500 0.02000 0.03000 - 0.04000 0.05000 0.06000 0.08000 0.10000 0.15000 - 0.20000 0.30000 0.40000 0.50000 0.60000 0.80000 - 1.00000 1.50000 2.00000 3.00000 4.00000 5.00000 - 6.00000 8.00000 10.00000 15.00000 20.00000 30.00000 - 40.00000 50.00000 60.00000 80.00000 100.00000 150.00000 - 200.00000 300.00000 400.00000 500.00000 600.00000 800.00000 - 1000.00000 1500.00000 2000.00000 3000.00000 4000.00000 5000.00000 - 6000.00000 8000.00000 10000.00000 - 0.00000 0.05000 0.10000 0.15000 0.20000 0.25000 - 0.30000 0.35000 0.40000 0.45000 0.50000 0.55000 - 0.60000 0.65000 0.70000 0.75000 0.80000 0.85000 - 0.90000 0.92500 0.95000 0.97000 0.99000 0.99500 - 0.99900 0.99950 0.99990 0.99995 0.99999 1.00000 - 7.85327 7.83328 7.74599 7.61411 7.44648 7.25292 - 7.03983 6.81482 6.58628 6.35593 6.12420 5.89276 - 5.66431 5.44261 5.22956 5.02806 4.84142 4.67199 - 4.52130 4.45442 4.40017 4.37233 4.36154 4.36352 - 4.36397 4.36376 4.36476 4.36555 4.36623 4.36018 - 8.38529 8.39187 8.27239 8.07164 7.81859 7.54226 - 7.25267 6.95767 6.66559 6.37667 6.08974 5.80585 - 5.52694 5.25608 4.99307 4.73698 4.48638 4.23887 - 4.00420 3.90445 3.82824 3.79020 3.75410 3.74301 - 3.74069 3.74125 3.73944 3.73793 3.73665 3.75587 - 8.80528 8.80075 8.63765 8.37704 8.05882 7.72174 - 7.37749 7.03399 6.69913 6.37253 6.05210 5.73860 - 5.43147 5.13207 4.83927 4.55066 4.26311 3.97230 - 3.68231 3.54818 3.43720 3.37442 3.32562 3.31227 - 3.30778 3.30809 3.30606 3.30449 3.30320 3.32040 - 9.44642 9.39057 9.13992 8.78090 8.36532 7.94143 - 7.52170 7.11342 6.72301 6.34907 5.98809 5.64072 - 5.30179 4.96954 4.64206 4.31596 3.98685 3.64834 - 3.29150 3.10925 2.94438 2.83802 2.76388 2.74751 - 2.73747 2.73670 2.73498 2.73407 2.73342 2.73968 - 9.92979 9.81696 9.48791 9.05010 8.56198 8.07642 - 7.60536 7.15446 6.72841 6.32441 5.93852 5.57117 - 5.21388 4.86271 4.51537 4.16819 3.81616 3.45146 - 3.05658 2.84577 2.64672 2.50927 2.40890 2.38760 - 2.37152 2.36967 2.36798 2.36753 2.36730 2.36695 - 10.31651 10.15055 9.75274 9.24941 8.70338 8.17030 - 7.66113 7.17936 6.72780 6.30223 5.89892 5.51753 - 5.14787 4.78416 4.42392 4.06325 3.69669 3.31538 - 2.89659 2.66790 2.44621 2.28613 2.16150 2.13454 - 2.11267 2.10989 2.10799 2.10778 2.10776 2.10417 - 10.63768 10.42400 9.96565 9.40625 8.81204 8.24059 - 7.70162 7.19621 6.72507 6.28299 5.86644 5.47405 - 5.09523 4.72252 4.35324 3.98327 3.60676 3.21401 - 2.77933 2.53906 2.30166 2.12438 1.97783 1.94509 - 1.91795 1.91438 1.91213 1.91201 1.91206 1.90727 - 11.14991 10.85602 10.29567 9.64392 8.97229 8.34139 - 7.75783 7.21810 6.71838 6.25196 5.81568 5.40617 - 5.01426 4.62938 4.24845 3.86677 3.47771 3.07040 - 2.61730 2.36447 2.10745 1.90541 1.72107 1.67740 - 1.64123 1.63642 1.63332 1.63313 1.63311 1.62900 - 11.55073 11.18994 10.54520 9.81903 9.08677 8.41120 - 7.79509 7.23094 6.71118 6.22636 5.77566 5.35307 - 4.95213 4.55943 4.17153 3.78303 3.38660 2.97075 - 2.50858 2.25027 1.98179 1.76244 1.54766 1.49466 - 1.45120 1.44545 1.44153 1.44117 1.44100 1.43872 - 12.29079 11.78779 10.97502 10.10980 9.26918 8.51677 - 7.84625 7.24114 6.68847 6.16939 5.69531 5.24968 - 4.83535 4.43235 4.03605 3.63949 3.23420 2.80880 - 2.34021 2.07873 1.79537 1.54855 1.28189 1.21231 - 1.15595 1.14858 1.14311 1.14237 1.14187 1.14276 - 13.06510 12.13155 11.10834 10.19703 9.36966 8.61214 - 7.91526 7.27162 6.67443 6.11665 5.61692 5.15458 - 4.73425 4.32892 3.93286 3.54035 3.14124 2.71550 - 2.23943 1.97444 1.68362 1.42449 1.12865 1.04464 - 0.98097 0.97364 0.96670 0.96568 0.96479 0.96670 - 13.83092 12.70853 11.49943 10.45149 9.51904 8.67719 - 7.91473 7.22469 6.58019 5.99878 5.48748 5.01611 - 4.59200 4.18824 3.79203 3.39849 2.99905 2.57710 - 2.10901 1.84578 1.54922 1.27600 0.94702 0.84875 - 0.77610 0.76780 0.75968 0.75848 0.75736 0.75856 - 14.40859 13.11946 11.76323 10.61131 9.60026 8.69773 - 7.88742 7.16059 6.48788 5.88807 5.37302 4.89803 - 4.46954 4.07056 3.67769 3.28673 2.89039 2.47464 - 2.01634 1.75717 1.46066 1.18207 0.83688 0.73180 - 0.65460 0.64571 0.63710 0.63591 0.63478 0.63488 - 14.90026 13.41782 11.92174 10.68494 9.62016 8.68659 - 7.85752 7.11100 6.42614 5.81540 5.29513 4.81166 - 4.37024 3.97017 3.57475 3.17836 2.77700 2.36995 - 1.93962 1.69464 1.40109 1.11246 0.75437 0.65417 - 0.57239 0.56197 0.55364 0.55265 0.55175 0.55079 - 15.35082 13.68326 12.06199 10.74995 9.63605 8.67348 - 7.82683 7.05764 6.35576 5.73676 5.20765 4.71492 - 4.26168 3.86279 3.47453 3.09009 2.70378 2.30686 - 1.87668 1.63000 1.33739 1.05345 0.70046 0.59640 - 0.50947 0.49914 0.49273 0.49200 0.49043 0.48896 - 16.19688 14.15639 12.30348 10.85188 9.64741 8.62750 - 7.74516 6.94383 6.21365 5.59476 5.06022 4.56222 - 4.09769 3.69812 3.31846 2.93816 2.55313 2.16640 - 1.76286 1.53304 1.25404 0.97190 0.60884 0.50823 - 0.42480 0.41392 0.40568 0.40486 0.40420 0.40215 - 16.93994 14.54746 12.51018 10.95374 9.68561 8.61574 - 7.68902 6.85892 6.10705 5.48147 4.93742 4.42741 - 3.95051 3.54457 3.17904 2.81232 2.43771 2.05965 - 1.66956 1.45024 1.17971 0.90312 0.54756 0.44837 - 0.36484 0.35362 0.34590 0.34523 0.34458 0.34276 - 18.73528 15.40073 12.95641 11.18537 9.79845 8.62800 - 7.59189 6.68532 5.91765 5.27548 4.71613 4.19262 - 3.69869 3.26130 2.90125 2.55315 2.20083 1.84924 - 1.49031 1.28883 1.03867 0.78035 0.44445 0.34997 - 0.27040 0.25974 0.25217 0.25134 0.25037 0.25056 - 20.30812 16.24655 13.46393 11.44636 9.87265 8.59427 - 7.50890 6.57378 5.80803 5.16658 4.59548 4.05972 - 3.54913 3.08097 2.69354 2.35514 2.02247 1.69651 - 1.36181 1.17128 0.93752 0.69742 0.38029 0.28903 - 0.21510 0.20557 0.19788 0.19662 0.19574 0.19736 - 23.25490 17.49451 14.20286 11.95736 10.20457 8.74324 - 7.55480 6.56122 5.74637 5.07201 4.47291 3.91521 - 3.38858 2.89818 2.46792 2.12401 1.80810 1.50088 - 1.19416 1.02371 0.81248 0.59325 0.30563 0.22444 - 0.15659 0.14751 0.14062 0.13965 0.13840 0.14057 - 25.73999 18.65190 14.96648 12.45346 10.52676 8.91933 - 7.65840 6.65026 5.81635 5.10944 4.48261 3.90504 - 3.36210 2.85178 2.38848 2.00381 1.69553 1.39277 - 1.09616 0.94182 0.74576 0.53805 0.26675 0.19040 - 0.12737 0.11900 0.11240 0.11144 0.11064 0.11164 - 27.89619 19.67752 15.68138 12.91435 10.84461 9.14726 - 7.83063 6.79875 5.94536 5.20942 4.55527 3.95813 - 3.39965 2.87286 2.38574 1.96227 1.63388 1.33553 - 1.04524 0.89566 0.70623 0.50542 0.24420 0.17165 - 0.11057 0.10236 0.09614 0.09539 0.09474 0.09447 - 29.80029 20.59290 16.33705 13.33606 11.13591 9.39107 - 8.04152 6.98293 6.10459 5.34166 4.66250 4.04611 - 3.47232 2.93068 2.42441 1.96998 1.60535 1.30772 - 1.01954 0.87154 0.68462 0.48684 0.23085 0.16021 - 0.09989 0.09175 0.08578 0.08518 0.08465 0.08346 - 32.99527 22.15825 17.47101 14.09663 11.67971 9.88116 - 8.49911 7.39585 6.46656 5.65523 4.93383 4.28220 - 3.67859 3.10903 2.57051 2.06955 1.63370 1.30432 - 1.01235 0.86259 0.67412 0.47545 0.21913 0.14830 - 0.08758 0.07944 0.07362 0.07316 0.07277 0.07106 - 35.56744 23.45410 18.40639 14.76335 12.21226 10.36761 - 8.96008 7.82075 6.84914 5.99783 5.24143 4.55847 - 3.92651 3.33016 2.76279 2.22429 1.73213 1.33973 - 1.03784 0.88284 0.68809 0.48310 0.21775 0.14378 - 0.08129 0.07302 0.06707 0.06658 0.06621 0.06494 - 40.25667 25.88895 20.16734 16.11061 13.49273 11.54986 - 10.05522 8.82601 7.77255 6.84719 6.02094 5.27030 - 4.57487 3.91872 3.28973 2.67767 2.08530 1.54736 - 1.15454 0.98002 0.76033 0.52957 0.23020 0.14592 - 0.07648 0.06743 0.06039 0.05956 0.05892 0.05899 - 43.42175 27.55630 21.44513 17.21954 14.61232 12.60693 - 11.03273 9.72429 8.60526 7.62343 6.74383 5.94048 - 5.19452 4.48945 3.80939 3.13809 2.47190 1.83722 - 1.30579 1.09742 0.84623 0.58720 0.25009 0.15595 - 0.07837 0.06793 0.05907 0.05779 0.05640 0.05726 - 47.38277 29.69830 23.28105 19.06989 16.37830 14.28566 - 12.62539 11.23433 10.03020 8.96246 8.00033 7.11840 - 6.29465 5.51005 4.74790 3.99052 3.22514 2.45271 - 1.69363 1.34656 1.02416 0.70299 0.29812 0.18437 - 0.08723 0.07389 0.06126 0.05855 0.05605 0.05579 - 49.85606 30.87401 24.48538 20.48300 17.77687 15.63906 - 13.91354 12.45251 11.17929 10.04591 9.02231 8.08278 - 7.20426 6.36676 5.55297 4.74400 3.91790 3.04821 - 2.11498 1.63400 1.18978 0.81530 0.34864 0.21560 - 0.09954 0.08228 0.06492 0.06137 0.05645 0.05485 - 51.30644 31.58098 25.49998 21.70885 18.99536 16.78514 - 14.96173 13.40592 12.06142 10.88062 9.82781 8.87048 - 7.97681 7.12012 6.28055 5.43532 4.55462 3.59563 - 2.51474 1.92775 1.34576 0.92727 0.40154 0.24765 - 0.11227 0.09140 0.06910 0.06422 0.05738 0.05424 - 52.54506 32.03690 26.23207 22.56586 19.88246 17.66672 - 15.82393 14.24097 12.86573 11.65269 10.56772 9.57924 - 8.65608 7.77118 6.90295 6.02553 5.10371 4.08368 - 2.90038 2.23157 1.53470 1.03380 0.45249 0.27999 - 0.12548 0.10081 0.07333 0.06707 0.05827 0.05382 - 54.20055 32.57617 27.34602 23.85966 21.25040 19.04692 - 17.18927 15.57602 14.16337 12.90956 11.78294 10.75335 - 9.79073 8.86753 7.95971 7.03709 6.05640 4.94737 - 3.61085 2.81673 1.93098 1.23594 0.55212 0.34435 - 0.15212 0.11965 0.08154 0.07256 0.05994 0.05329 - 55.23288 32.90854 28.13725 24.79907 22.26366 20.08841 - 18.23386 16.60938 15.17811 13.90189 12.75129 11.69752 - 10.71123 9.76466 8.83214 7.88056 6.86111 5.69170 - 4.24688 3.36122 2.33165 1.44283 0.64765 0.40715 - 0.17838 0.13805 0.08926 0.07764 0.06143 0.05297 - 56.59717 33.44591 29.34048 26.31750 23.94151 21.85629 - 20.04164 18.42796 16.98950 15.69609 14.52344 13.44566 - 12.43488 11.46299 10.50227 9.51547 8.44520 7.19076 - 5.58062 4.54636 3.26893 2.04801 0.86644 0.55403 - 0.24026 0.18080 0.10635 0.08862 0.06449 0.05254 - 57.28667 33.74335 30.02148 27.23167 24.98212 22.98299 - 21.22021 19.63779 18.21573 16.92958 15.75884 14.68028 - 13.66785 12.69407 11.73065 10.73790 9.65246 8.35935 - 6.65321 5.52372 4.08081 2.62456 1.06249 0.69257 - 0.29732 0.21925 0.12086 0.09768 0.06676 0.05232 - 58.04907 34.01364 30.77324 28.27583 26.20395 24.34190 - 22.67947 21.17416 19.81056 18.56888 17.43202 16.37946 - 15.38658 14.42722 13.47439 12.48783 11.40030 10.08466 - 8.30017 7.07887 5.45575 3.69734 1.39844 0.92716 - 0.39448 0.28464 0.14540 0.11314 0.07125 0.05210 - 58.33458 34.11751 31.17714 28.85959 26.90665 25.14401 - 23.56207 22.12527 20.81979 19.62790 18.53383 17.51823 - 16.55711 15.62497 14.69620 13.73101 12.66083 11.35255 - 9.54526 8.28171 6.56120 4.61666 1.77992 1.12564 - 0.47553 0.33873 0.16559 0.12599 0.07538 0.05199 - 58.35318 34.17593 31.43628 29.23988 27.36916 25.67786 - 24.15616 22.77318 21.51595 20.36845 19.31535 18.33842 - 17.41402 16.51697 15.62189 14.68819 13.64421 12.34736 - 10.52625 9.24542 7.49286 5.44694 2.19893 1.29066 - 0.54160 0.38343 0.18374 0.13820 0.07929 0.05192 - 58.16777 34.18411 31.59810 29.49982 27.69815 26.06653 - 24.59547 23.25774 22.04124 20.93132 19.91396 18.97293 - 18.08728 17.23119 16.37155 15.46081 14.42712 13.14255 - 11.34367 10.06587 8.28231 6.14301 2.60414 1.46794 - 0.60140 0.42402 0.19964 0.14836 0.08307 0.05187 - 57.72517 34.22028 31.82518 29.84866 28.13231 26.57756 - 25.17564 23.90450 22.75354 21.70914 20.75758 19.88190 - 19.05864 18.26237 17.46735 16.63220 15.68130 14.45747 - 12.66386 11.36650 9.55105 7.32795 3.35735 1.86065 - 0.70502 0.49289 0.22755 0.16694 0.09026 0.05181 - 57.29999 34.23114 31.96207 30.06836 28.41154 26.91077 - 25.55788 24.33440 23.23079 22.23457 21.33315 20.51007 - 19.74203 19.00388 18.26953 17.49715 16.60915 15.44178 - 13.68767 12.39874 10.57349 8.29436 4.02904 2.28102 - 0.79416 0.55215 0.25193 0.18353 0.09705 0.05178 - 56.36497 34.24174 32.15471 30.38057 28.81133 27.39099 - 26.11267 24.96291 23.93430 23.01688 22.20015 21.46971 - 20.80415 20.17987 19.57156 18.93640 18.19319 17.16623 - 15.53043 14.28423 12.47212 10.13600 5.44035 3.27351 - 0.98283 0.67674 0.30369 0.21964 0.11233 0.05173 - 55.00314 34.23216 32.25624 30.55406 29.03616 27.66081 - 26.42238 25.31160 24.32324 23.45021 22.68407 22.01373 - 21.42223 20.88736 20.37968 19.84465 19.19563 18.28166 - 16.79440 15.61748 13.83292 11.47762 6.57858 4.13235 - 1.14507 0.78428 0.34777 0.25050 0.12560 0.05171 - 51.63249 34.23053 32.36130 30.72900 29.26424 27.94012 - 26.75044 25.68893 24.75133 23.93246 23.22667 22.62531 - 22.11482 21.67735 21.28847 20.89986 20.43091 19.73311 - 18.48740 17.42624 15.72999 13.40457 8.31845 5.55428 - 1.43650 0.97519 0.42275 0.30314 0.14769 0.05168 - 48.77057 34.22855 32.41925 30.82349 29.38573 28.08788 - 26.92427 25.88976 24.98137 24.19441 23.52403 22.96255 - 22.49931 22.11942 21.80278 21.50737 21.16147 20.62843 - 19.58855 18.63455 17.03867 14.77357 9.63203 6.68947 - 1.69480 1.14644 0.48774 0.34768 0.16630 0.05167 - 46.69637 34.22485 32.45363 30.88148 29.46185 28.18111 - 27.03407 26.01698 25.12730 24.36076 23.71236 23.17590 - 22.74295 22.40189 22.13564 21.90648 21.64978 21.24088 - 20.36609 19.50638 18.01341 15.83267 10.69648 7.61731 - 1.92679 1.30450 0.54619 0.38644 0.18323 0.05166 - 45.26547 34.22159 32.47687 30.92085 29.51436 28.24532 - 27.10957 26.10442 25.22743 24.47499 23.84259 23.32471 - 22.91406 22.60091 22.37029 22.18822 21.99632 21.68098 - 20.94594 20.17708 18.78357 16.67441 11.56540 8.41652 - 2.27724 1.44754 0.59956 0.42257 0.19852 0.05166 - 43.44806 34.21634 32.50523 30.97049 29.58144 28.32770 - 27.20708 26.21764 25.35756 24.62350 24.01228 23.51930 - 23.13873 22.86287 22.68027 22.56180 22.45842 22.27568 - 21.75429 21.13809 19.92796 17.96545 12.94739 9.72741 - 3.14080 1.70525 0.69602 0.48776 0.22608 0.05165 - 42.29637 34.21248 32.52179 30.99998 29.62209 28.37820 - 27.26720 26.28775 25.43828 24.71614 24.11839 23.64120 - 23.27992 23.02805 22.87636 22.79912 22.75363 22.66026 - 22.29260 21.79578 20.74336 18.92307 14.01616 10.76949 - 3.86979 1.93408 0.78283 0.54640 0.25067 0.05165 - 40.54385 34.20581 32.54314 31.03979 29.67651 28.44693 - 27.35011 26.38519 25.55031 24.84444 24.26559 23.81078 - 23.47696 23.25975 23.15286 23.13493 23.17325 23.21297 - 23.08815 22.79489 22.03224 20.51541 15.94843 12.73875 - 5.36966 2.70205 0.97495 0.67818 0.30385 0.05164 - 39.54947 34.20168 32.55397 31.06010 29.70422 28.48216 - 27.39304 26.43573 25.60854 24.91138 24.34242 23.89948 - 23.58015 23.38133 23.29852 23.31380 23.39995 23.51427 - 23.52628 23.35544 22.78870 21.51370 17.27647 14.14412 - 6.54000 3.72020 1.14232 0.79305 0.34867 0.05164 - 38.48796 34.19731 32.56569 31.08153 29.73312 28.51869 - 27.43698 26.48697 25.66748 24.97920 24.42145 23.99309 - 23.68944 23.50810 23.44817 23.49904 23.64238 23.84338 - 23.99226 23.94449 23.62932 22.75015 19.07617 15.99422 - 8.36108 5.35448 1.43126 0.97855 0.42550 0.05164 - 37.92909 34.19489 32.57170 31.09209 29.74760 28.53699 - 27.45908 26.51297 25.69827 25.01498 24.46262 24.04085 - 23.74489 23.57343 23.52658 23.59593 23.76659 24.01219 - 24.24400 24.27130 24.09012 23.43474 20.26799 17.35123 - 9.72223 6.61994 1.68446 1.15120 0.49128 0.05164 - 37.57637 34.19319 32.57539 31.09863 29.75655 28.54802 - 27.47243 26.52901 25.71732 25.03723 24.48824 24.07027 - 23.77910 23.61385 23.57539 23.65584 23.84277 24.11639 - 24.40245 24.47861 24.38400 23.88087 21.11858 18.36079 - 10.77621 7.60184 1.91195 1.30895 0.54992 0.05164 - 37.32846 34.19212 32.57782 31.10303 29.76256 28.55576 - 27.48174 26.53995 25.73036 25.05235 24.50578 24.09050 - 23.80263 23.64156 23.60889 23.69702 23.89507 24.18768 - 24.51196 24.62308 24.58969 24.19562 21.75807 19.15221 - 11.65465 8.44425 2.60220 1.45514 0.60352 0.05164 - 37.00685 34.19043 32.58044 31.10847 29.77040 28.56567 - 27.49367 26.55379 25.74638 25.07098 24.52740 24.11542 - 23.83183 23.67656 23.65149 23.74953 23.96214 24.27847 - 24.65137 24.81023 24.85995 24.61082 22.65410 20.32286 - 13.04413 9.80037 3.74580 1.79592 0.70018 0.05164 - 36.81818 34.18954 32.58064 31.11049 29.77469 28.57158 - 27.50078 26.56229 25.75638 25.08269 24.54010 24.12822 - 23.84654 23.69566 23.67749 23.78223 24.00125 24.32928 - 24.73828 24.93436 25.02962 24.83568 23.24554 21.28584 - 14.07366 10.75739 4.57677 2.48366 0.78238 0.05164 - 7.16705 7.20584 7.18068 7.10813 7.00066 6.87162 - 6.72642 6.57031 6.40930 6.24474 6.07697 5.90752 - 5.73968 5.57726 5.42249 5.27875 5.14963 5.03663 - 4.93873 4.89471 4.85757 4.83659 4.82450 4.82307 - 4.82211 4.82195 4.82183 4.82182 4.82180 4.82131 - 7.78795 7.80440 7.73566 7.60649 7.43471 7.23902 - 7.02701 6.80571 6.58294 6.36005 6.13711 5.91567 - 5.69839 5.48849 5.28671 5.09363 4.90999 4.73628 - 4.57908 4.51263 4.45771 4.42584 4.39987 4.39234 - 4.38845 4.38845 4.38832 4.38817 4.38825 4.39219 - 8.23235 8.22866 8.11995 7.93999 7.71295 7.46332 - 7.20030 6.93184 6.66630 6.40481 6.14683 5.89345 - 5.64581 5.40581 5.17340 4.94784 4.72853 4.51529 - 4.31338 4.22272 4.14536 4.09892 4.06418 4.05558 - 4.05063 4.05043 4.05020 4.05006 4.05011 4.05327 - 8.86523 8.82442 8.64550 8.37990 8.06361 7.73140 - 7.39433 7.06054 6.73795 6.42675 6.12476 5.83230 - 5.54753 5.27020 4.99934 4.73301 4.46920 4.20642 - 3.94374 3.81581 3.70153 3.62886 3.57734 3.56696 - 3.55969 3.55894 3.55838 3.55826 3.55824 3.55896 - 9.32053 9.24515 9.00566 8.66998 8.28397 7.89040 - 7.50099 7.12295 6.76292 6.41966 6.08992 5.77314 - 5.46547 5.16512 4.87064 4.57943 4.28864 3.99546 - 3.69387 3.54092 3.40044 3.30708 3.23879 3.22528 - 3.21499 3.21372 3.21281 3.21267 3.21260 3.21212 - 9.67757 9.56932 9.27635 8.88156 8.43887 7.99717 - 7.56820 7.15756 6.77035 6.40400 6.05452 5.72042 - 5.39670 5.08041 4.76974 4.46163 4.15258 3.83866 - 3.51020 3.33981 3.18016 3.07031 2.98616 2.96892 - 2.95542 2.95368 2.95240 2.95223 2.95212 2.95119 - 9.97199 9.83224 9.49114 9.04537 8.55531 8.07446 - 7.61415 7.17823 6.77010 6.38602 6.02146 5.67395 - 5.33810 5.00996 4.68744 4.36707 4.04479 3.71578 - 3.36782 3.18476 3.01053 2.88717 2.78834 2.76724 - 2.75055 2.74839 2.74678 2.74656 2.74642 2.74544 - 10.44252 10.24303 9.81746 9.28695 8.72123 8.17991 - 7.67258 7.19962 6.76079 6.35062 5.96377 5.59607 - 5.24268 4.89788 4.55911 4.22218 3.88208 3.53258 - 3.15856 2.95879 2.76389 2.61941 2.49463 2.46607 - 2.44346 2.44056 2.43838 2.43806 2.43788 2.43735 - 10.81191 10.55588 10.05748 9.45839 8.83421 8.24785 - 7.70642 7.20715 6.74664 6.31736 5.91442 5.53194 - 5.16633 4.81031 4.46095 4.11337 3.76185 3.39922 - 3.00902 2.79900 2.59001 2.42953 2.28299 2.24789 - 2.22012 2.21659 2.21392 2.21352 2.21330 2.21331 - 11.48580 11.10040 10.45283 9.72562 8.99894 8.33682 - 7.73973 7.19783 6.70246 6.24017 5.81141 5.40447 - 5.02019 4.64780 4.28345 3.92101 3.55357 3.17324 - 2.76250 2.53909 2.30844 2.12039 1.93340 1.88625 - 1.84859 1.84376 1.84015 1.83962 1.83933 1.83960 - 12.17797 11.39706 10.55299 9.77771 9.06203 8.39911 - 7.78379 7.21146 6.67777 6.17817 5.72074 5.29371 - 4.89749 4.51684 4.14764 3.78500 3.41974 3.03289 - 2.60519 2.37359 2.13111 1.92668 1.71106 1.65693 - 1.61194 1.60638 1.60195 1.60136 1.60097 1.60047 - 12.78863 11.86072 10.86011 9.96277 9.15101 8.41159 - 7.73712 7.12214 6.55115 6.03079 5.56219 5.12736 - 4.72631 4.34261 3.96839 3.59903 3.22610 2.83262 - 2.39917 2.16194 1.90663 1.68338 1.43446 1.36667 - 1.31401 1.30776 1.30212 1.30145 1.30076 1.29887 - 13.19144 12.15092 11.03389 10.04925 9.17055 8.37979 - 7.66605 7.02208 6.43032 5.89716 5.42530 4.98857 - 4.58529 4.20315 3.82894 3.45837 3.08375 2.68993 - 2.25777 2.01990 1.75981 1.52751 1.25912 1.18266 - 1.12521 1.11856 1.11218 1.11142 1.11057 1.10866 - 13.48616 12.33066 11.11230 10.06128 9.13878 8.32135 - 7.59166 6.93467 6.33598 5.79796 5.32461 4.88425 - 4.47327 4.08698 3.70657 3.32885 2.94950 2.56146 - 2.14830 1.91901 1.65706 1.41316 1.13034 1.05369 - 0.99129 0.98346 0.97698 0.97625 0.97549 0.97425 - 13.74900 12.47863 11.16605 10.05543 9.09460 8.25512 - 7.51346 6.84463 6.23803 5.69707 5.22088 4.77752 - 4.36205 3.97714 3.59974 3.22504 2.84870 2.46492 - 2.05775 1.83134 1.57081 1.32533 1.03408 0.95393 - 0.88918 0.88112 0.87439 0.87360 0.87280 0.87268 - 14.17453 12.70040 11.23214 10.02570 9.00469 8.12948 - 7.36791 6.68310 6.06223 5.52063 5.04073 4.59381 - 4.17240 3.78810 3.41767 3.05011 2.68109 2.30673 - 1.91204 1.69222 1.43703 1.19256 0.89305 0.80904 - 0.74180 0.73351 0.72653 0.72566 0.72483 0.72623 - 14.53869 12.87799 11.28071 9.99592 8.92818 8.02316 - 7.24089 6.54552 5.91669 5.37390 4.89188 4.44210 - 4.01652 3.62918 3.26520 2.90474 2.54361 2.17903 - 1.79659 1.58339 1.33430 1.09305 0.79204 0.70696 - 0.63897 0.63057 0.62353 0.62264 0.62182 0.62360 - 15.34610 13.22547 11.37727 9.95600 8.81323 7.85196 - 7.01509 6.28436 5.65046 5.10054 4.60889 4.14864 - 3.71454 3.31795 2.96695 2.62537 2.28208 1.93772 - 1.58192 1.38428 1.14905 0.91748 0.62664 0.54451 - 0.47733 0.46857 0.46211 0.46129 0.46071 0.46083 - 16.11877 13.54439 11.48871 9.95964 8.74712 7.73726 - 6.86792 6.11119 5.47039 4.91711 4.41830 3.95252 - 3.51348 3.10778 2.75067 2.42050 2.09193 1.76645 - 1.43300 1.24690 1.02347 0.80224 0.52492 0.44711 - 0.38269 0.37415 0.36794 0.36722 0.36662 0.36529 - 17.54485 14.15758 11.78368 10.08445 8.74634 7.63795 - 6.72716 5.95448 5.29493 4.72518 4.21178 3.73616 - 3.29025 2.87406 2.49735 2.17016 1.85944 1.55040 - 1.24165 1.07714 0.87465 0.66882 0.40986 0.33828 - 0.27832 0.27031 0.26445 0.26372 0.26319 0.26233 - 18.80849 14.73368 12.13193 10.28853 8.85801 7.66981 - 6.71495 5.92807 5.25475 4.66698 4.13978 3.65525 - 3.20236 2.77707 2.38460 2.03815 1.73396 1.43400 - 1.13769 0.98300 0.79247 0.59760 0.35018 0.28132 - 0.22408 0.21649 0.21084 0.21011 0.20960 0.20957 - 19.94119 15.27370 12.49647 10.51962 9.01342 7.77367 - 6.78265 5.97625 5.28816 4.68303 4.14048 3.64502 - 3.18355 2.74950 2.34499 1.97965 1.66661 1.37050 - 1.08010 0.92997 0.74520 0.55587 0.31502 0.24805 - 0.19235 0.18494 0.17933 0.17858 0.17807 0.17821 - 20.95639 15.77181 12.85284 10.75423 9.17886 7.90918 - 6.89401 6.06718 5.36166 4.73984 4.18248 3.67549 - 3.20479 2.76208 2.34705 1.96556 1.63410 1.33848 - 1.04998 0.90135 0.71863 0.53137 0.29333 0.22731 - 0.17224 0.16486 0.15925 0.15850 0.15797 0.15802 - 22.66953 16.64464 13.50235 11.20971 9.51841 8.21264 - 7.17059 6.31133 5.57199 4.91933 4.33556 3.80664 - 3.31735 2.85729 2.42290 2.01483 1.64435 1.32998 - 1.03757 0.88713 0.70233 0.51291 0.27212 0.20539 - 0.14958 0.14210 0.13645 0.13572 0.13518 0.13497 - 24.04424 17.37868 14.06240 11.63051 9.86536 8.53059 - 7.47013 6.58708 5.82034 5.14151 4.53494 3.98616 - 3.47899 3.00184 2.54904 2.11758 1.71368 1.36252 - 1.06024 0.90457 0.71313 0.51661 0.26615 0.19652 - 0.13839 0.13067 0.12493 0.12422 0.12369 0.12332 - 26.50581 18.76385 15.15998 12.52312 10.71276 9.31751 - 8.20382 7.26687 6.44947 5.72339 5.07170 4.47934 - 3.93144 3.41592 2.92337 2.44424 1.97675 1.53757 - 1.17328 0.99824 0.78163 0.55842 0.27368 0.19443 - 0.12845 0.11974 0.11327 0.11250 0.11191 0.11164 - 28.11377 19.70720 15.97607 13.27151 11.46200 10.02609 - 8.86350 7.87967 7.02458 6.26615 5.58228 4.95615 - 4.37537 3.82832 3.30269 2.78431 2.26808 1.76964 - 1.32045 1.11454 0.86581 0.61323 0.29171 0.20293 - 0.12813 0.11790 0.11005 0.10914 0.10813 0.10835 - 30.05812 20.89108 17.12926 14.48073 12.63925 11.15798 - 9.94749 8.91634 8.01224 7.20439 6.47289 5.80013 - 5.16936 4.56733 3.98510 3.41324 2.84181 2.26092 - 1.66241 1.35804 1.03778 0.72291 0.33770 0.23036 - 0.13650 0.12269 0.11059 0.10874 0.10658 0.10699 - 31.28258 21.51138 17.84151 15.35440 13.54007 12.05229 - 10.81409 9.74724 8.80629 7.96290 7.19779 6.49316 - 5.83162 5.19869 4.58387 3.97512 3.35726 2.70900 - 2.00055 1.61240 1.20591 0.83661 0.38747 0.26172 - 0.14900 0.13127 0.11372 0.11054 0.10689 0.10676 - 32.09668 21.87619 18.36194 16.00999 14.23282 12.75119 - 11.50228 10.41664 9.45455 8.58978 7.80370 7.07858 - 6.39643 5.74187 5.10326 4.46668 3.81303 3.11251 - 2.31853 1.86426 1.36423 0.94553 0.43893 0.29536 - 0.16317 0.14110 0.11726 0.11251 0.10698 0.10645 - 32.67142 22.09608 18.76820 16.51718 14.78255 13.31473 - 12.06499 10.97046 9.99682 9.11956 8.32075 7.58266 - 6.88678 6.21697 5.56067 4.90247 4.22020 3.47752 - 2.61440 2.10577 1.52946 1.04967 0.49068 0.32984 - 0.17791 0.15128 0.12084 0.11442 0.10692 0.10606 - 33.41573 22.33289 19.35973 17.25638 15.60381 14.17350 - 12.93676 11.84081 10.86021 9.97339 9.16348 8.41289 - 7.70231 7.01430 6.33500 5.64659 4.92238 4.11656 - 3.14843 2.55601 1.85553 1.24619 0.59242 0.39862 - 0.20730 0.17137 0.12772 0.11807 0.10668 0.10530 - 33.80606 22.44928 19.77501 17.79675 16.21535 14.81874 - 13.59253 12.49525 11.51072 10.62027 9.80814 9.05716 - 8.34805 7.66229 6.98356 6.28931 5.54371 4.68240 - 3.60656 2.93947 2.14927 1.43522 0.69807 0.46724 - 0.23447 0.18993 0.13450 0.12172 0.10581 0.10465 - 34.40663 22.63660 20.33281 18.56010 17.11078 15.81192 - 14.65561 13.60898 12.66012 11.79410 10.99790 10.25641 - 9.55139 8.86446 8.17852 7.46856 6.69292 5.77401 - 4.58236 3.81321 2.85850 1.92999 0.91899 0.61750 - 0.29563 0.23087 0.14871 0.12968 0.10597 0.10358 - 34.69957 22.72505 20.62643 18.99135 17.63155 16.40512 - 15.30616 14.30674 13.39653 12.56257 11.79310 11.07394 - 10.38709 9.71416 9.03778 8.33187 7.55154 6.61106 - 5.36014 4.53099 3.47112 2.38912 1.11084 0.74831 - 0.34762 0.26529 0.16077 0.13673 0.10680 0.10295 - 35.01132 22.77782 20.92986 19.45930 18.21255 17.08325 - 16.06664 15.14068 14.29650 13.52288 12.80890 12.14077 - 11.50004 10.86777 10.22666 9.54975 8.78924 7.85011 - 6.55551 5.66506 4.48156 3.19501 1.43553 0.97023 - 0.43405 0.32213 0.18111 0.14913 0.10945 0.10223 - 35.13283 22.79478 21.09457 19.71637 18.53470 17.46367 - 16.49847 15.62088 14.82296 14.09462 13.42563 12.80278 - 12.20791 11.62217 11.02784 10.39640 9.67539 8.75677 - 7.44726 6.53190 5.30091 3.90076 1.75391 1.14570 - 0.50534 0.37000 0.19827 0.15966 0.11324 0.10183 - 35.10747 22.78568 21.18788 19.87460 18.73981 17.71112 - 16.78386 15.94246 15.17985 14.48664 13.85341 13.26748 - 12.71130 12.16632 11.61478 11.02744 10.34904 9.46298 - 8.16151 7.23349 5.96612 4.48478 2.07922 1.31025 - 0.56516 0.40941 0.21403 0.17008 0.11645 0.10157 - 35.01187 22.77744 21.25084 19.98386 18.88261 17.88445 - 16.98518 16.17087 15.43527 14.76969 14.16537 13.61024 - 13.08735 12.57851 12.06608 11.52034 10.88401 10.03408 - 8.75182 7.82129 6.53321 4.99500 2.38621 1.46868 - 0.61875 0.44473 0.22840 0.17971 0.11965 0.10138 - 34.76907 22.76697 21.33353 20.12804 19.07133 18.11443 - 17.25331 16.47678 15.77938 15.15397 14.59270 14.08490 - 13.61470 13.16491 12.71845 12.24554 11.68681 10.91106 - 9.68404 8.76505 7.46175 5.85282 2.94490 1.79218 - 0.71415 0.50753 0.25419 0.19721 0.12587 0.10115 - 34.55391 22.76323 21.38895 20.22237 19.19421 18.26372 - 17.42725 16.67543 16.00354 15.40527 14.87399 14.39984 - 13.96827 13.56320 13.16854 12.75536 12.26408 11.55958 - 10.39744 9.50130 8.20153 6.55522 3.44042 2.11636 - 0.79962 0.56367 0.27717 0.21293 0.13175 0.10101 - 34.06743 22.75293 21.47311 20.36682 19.38106 18.48825 - 17.68535 16.96635 16.32857 15.76817 15.28061 14.85934 - 14.49395 14.17112 13.87303 13.56363 13.18248 12.61785 - 11.63643 10.82529 9.56453 7.88651 4.48394 2.85684 - 0.98708 0.68680 0.32683 0.24705 0.14513 0.10081 - 33.40053 22.75642 21.52472 20.44531 19.47757 18.60258 - 17.81761 17.11839 16.50273 15.96701 15.50689 15.11669 - 14.78767 14.50883 14.26529 14.02486 13.73352 13.29038 - 12.45788 11.71820 10.51657 8.85846 5.31516 3.49132 - 1.15196 0.79587 0.36947 0.27623 0.15689 0.10072 - 31.71582 22.74756 21.56589 20.52118 19.57991 18.72824 - 17.96426 17.28552 16.69138 16.17957 15.74779 15.39184 - 15.10453 14.87721 14.69919 14.54470 14.36848 14.08113 - 13.46951 12.87092 11.80962 10.23034 6.58080 4.53789 - 1.44583 0.98640 0.44193 0.32609 0.17752 0.10062 - 30.28618 22.74104 21.58504 20.55728 19.62918 18.79007 - 18.03862 17.37260 16.79158 16.29391 15.87798 15.54046 - 15.27562 15.07656 14.93502 14.82898 14.72037 14.53491 - 14.08261 13.59264 12.65892 11.17934 7.53414 5.36873 - 1.70367 1.15613 0.50462 0.36859 0.19532 0.10057 - 29.24902 22.73805 21.59811 20.57912 19.65721 18.82524 - 18.08174 17.42479 16.85332 16.36609 15.96111 15.63557 - 15.38451 15.20243 15.08310 15.00808 14.94535 14.83166 - 14.49484 14.08838 13.26675 11.89013 8.29094 6.05567 - 1.93471 1.31148 0.56162 0.40598 0.21129 0.10054 - 28.53503 22.73361 21.60472 20.59297 19.67709 18.85098 - 18.11322 17.46208 16.89696 16.41634 16.01797 15.69941 - 15.45739 15.28830 15.18654 15.13458 15.10364 15.04149 - 14.79129 14.44874 13.71845 12.44686 8.93062 6.62378 - 2.21319 1.45724 0.61406 0.43937 0.22637 0.10052 - 27.62552 22.72888 21.61545 20.61284 19.70403 18.88506 - 18.15425 17.50972 16.95123 16.47806 16.08940 15.78327 - 15.55569 15.40289 15.32180 15.29926 15.31259 15.31624 - 15.18231 14.94342 14.37013 13.26169 9.89757 7.58607 - 2.83534 1.71311 0.70842 0.50296 0.25212 0.10049 - 27.04918 22.72617 21.62231 20.62514 19.72069 18.90590 - 18.17935 17.53902 16.98499 16.51695 16.13419 15.83510 - 15.61595 15.47376 15.40642 15.40286 15.44385 15.49086 - 15.43432 15.26360 14.80385 13.83916 10.65080 8.33776 - 3.36342 1.94444 0.79426 0.55918 0.27550 0.10047 - 26.20023 22.73157 21.63029 20.63597 19.73663 18.92830 - 18.20898 17.57687 17.03154 16.57260 16.19858 15.90771 - 15.69572 15.56055 15.50663 15.53655 15.64104 15.76635 - 15.80459 15.72055 15.43546 14.73952 11.98212 9.72129 - 4.45402 2.57581 0.98436 0.68327 0.32580 0.10045 - 25.70253 22.72910 21.63480 20.64458 19.74854 18.94315 - 18.22650 17.59749 17.05554 16.60025 16.23033 15.94431 - 15.73846 15.61126 15.56783 15.61222 15.73776 15.89580 - 15.99536 15.97079 15.79516 15.26821 12.85109 10.70060 - 5.30785 3.29162 1.15158 0.79282 0.36880 0.10044 - 25.17238 22.72620 21.63910 20.65294 19.76028 18.95787 - 18.24431 17.61850 17.07991 16.62827 16.26257 15.98175 - 15.78229 15.66342 15.63091 15.69027 15.83791 16.03127 - 16.19731 16.23619 16.17896 15.85328 13.95497 12.03045 - 6.60889 4.41883 1.44349 0.98588 0.44214 0.10043 - 24.86823 22.71573 21.64171 20.66193 19.77167 18.97006 - 18.25650 17.63054 17.09270 16.64226 16.27811 15.99974 - 15.80683 15.70024 15.68030 15.74057 15.87325 16.06955 - 16.29764 16.38957 16.39182 16.15100 14.62366 12.96114 - 7.58729 5.28732 1.69621 1.16565 0.50448 0.10043 - 24.69154 22.71429 21.64276 20.66429 19.77502 18.97443 - 18.26181 17.63670 17.09937 16.64967 16.28738 16.01224 - 15.82226 15.71778 15.69961 15.76367 15.90434 16.11435 - 16.36380 16.47351 16.51486 16.36212 15.09609 13.53066 - 8.35516 6.03237 1.92573 1.31237 0.56210 0.10043 - 24.56738 22.71321 21.64326 20.66570 19.77715 18.97723 - 18.26538 17.64102 17.10443 16.65558 16.29434 16.02040 - 15.83187 15.72896 15.71312 15.78037 15.92594 16.14339 - 16.40860 16.53421 16.60303 16.49907 15.42327 14.00061 - 8.98564 6.64593 2.39709 1.45691 0.61425 0.10042 - 24.40454 22.71211 21.64482 20.66846 19.78085 18.98160 - 18.27040 17.64674 17.11095 16.66295 16.30295 16.03050 - 15.84382 15.74303 15.73012 15.80142 15.95313 16.18044 - 16.46533 16.61043 16.71722 16.68074 15.86301 14.65723 - 9.97553 7.64297 3.20514 1.83336 0.70930 0.10042 - 24.30714 22.70926 21.64442 20.67111 19.78615 18.98825 - 18.27686 17.65239 17.11549 16.66664 16.30624 16.03421 - 15.84898 15.75032 15.74045 15.81558 15.97143 16.20149 - 16.49585 16.65593 16.78885 16.79895 16.15546 15.07921 - 10.71691 8.44659 3.84067 2.32313 0.79589 0.10042 - 6.53125 6.59910 6.61998 6.60421 6.56004 6.49684 - 6.41846 6.32910 6.23373 6.13361 6.02927 5.92206 - 5.81511 5.71203 5.61535 5.52921 5.45769 5.40122 - 5.35588 5.33442 5.31414 5.29979 5.28759 5.28478 - 5.28260 5.28244 5.28258 5.28264 5.28259 5.28218 - 7.17462 7.22507 7.21266 7.15272 7.05718 6.93909 - 6.80363 6.65577 6.50162 6.34351 6.18364 6.02470 - 5.86908 5.71983 5.57875 5.44838 5.33162 5.23046 - 5.14914 5.11715 5.08740 5.06469 5.04217 5.03700 - 5.03296 5.03198 5.03021 5.02981 5.02992 5.03157 - 7.63255 7.66788 7.62363 7.52123 7.37753 7.21053 - 7.02698 6.83312 6.63605 6.43816 6.24129 6.04797 - 5.85975 5.67895 5.50666 5.34406 5.19306 5.05665 - 4.94166 4.89506 4.85367 4.82501 4.79902 4.79336 - 4.78904 4.78807 4.78642 4.78605 4.78614 4.78763 - 8.28008 8.28663 8.18422 8.00664 7.78080 7.53423 - 7.27641 7.01502 6.75812 6.50725 6.26210 6.02413 - 5.79338 5.57094 5.35682 5.15040 4.95211 4.76524 - 4.59664 4.52296 4.45936 4.41968 4.38922 4.38319 - 4.37881 4.37810 4.37716 4.37697 4.37699 4.37765 - 8.74202 8.72020 8.56599 8.32472 8.03232 7.72428 - 7.41170 7.10261 6.80499 6.51895 6.24239 5.97550 - 5.71726 5.46776 5.22636 4.99133 4.76196 4.54089 - 4.33297 4.23770 4.15526 4.10489 4.06901 4.06224 - 4.05745 4.05681 4.05616 4.05603 4.05603 4.05632 - 9.10193 9.05204 8.85109 8.55503 8.20744 7.85023 - 7.49534 7.15035 6.82256 6.51074 6.21142 5.92365 - 5.64569 5.37683 5.11594 4.86056 4.60914 4.36330 - 4.12566 4.01332 3.91512 3.85467 3.81234 3.80439 - 3.79875 3.79807 3.79746 3.79734 3.79733 3.79749 - 9.39713 9.31956 9.07598 8.73204 8.33774 7.94008 - 7.55132 7.17813 6.82680 6.49492 6.17803 5.87407 - 5.58101 5.29743 5.02181 4.75115 4.48321 4.21858 - 3.95771 3.83162 3.72010 3.65024 3.60096 3.59155 - 3.58481 3.58398 3.58328 3.58315 3.58313 3.58329 - 9.86586 9.73415 9.41477 8.99027 8.52058 8.05990 - 7.61995 7.20504 6.81878 6.45705 6.11402 5.78596 - 5.47098 5.16620 4.86961 4.57745 4.28637 3.99508 - 3.70020 3.55329 3.42033 3.33370 3.27017 3.25747 - 3.24815 3.24697 3.24591 3.24572 3.24570 3.24597 - 10.23118 10.04721 9.66171 9.17130 8.64275 8.13477 - 7.65757 7.21291 6.80172 6.41807 6.05615 5.71071 - 5.38035 5.06091 4.75001 4.44337 4.13678 3.82748 - 3.50903 3.34714 3.19767 3.09674 3.01950 3.00339 - 2.99131 2.98976 2.98837 2.98811 2.98808 2.98840 - 10.89212 10.58656 10.06492 9.44994 8.81683 8.22855 - 7.69032 7.19761 6.74617 6.32547 5.93293 5.55904 - 5.20473 4.86300 4.53065 4.20234 3.87260 3.53680 - 3.18337 2.99798 2.82013 2.69174 2.58448 2.56030 - 2.54152 2.53922 2.53761 2.53738 2.53724 2.53696 - 11.35382 10.93852 10.30824 9.60371 8.90097 8.26129 - 7.68561 7.16403 6.68658 6.24338 5.83194 5.44062 - 5.07232 4.71835 4.37439 4.03415 3.69152 3.34185 - 2.97048 2.77184 2.57587 2.42777 2.29625 2.26515 - 2.24053 2.23775 2.23649 2.23641 2.23611 2.23465 - 12.16897 11.31833 10.45745 9.67205 8.95118 8.28680 - 7.67418 7.10971 6.58292 6.09807 5.65561 5.24325 - 4.86044 4.49565 4.14291 3.79786 3.45219 3.08830 - 2.68996 2.47823 2.26347 2.09032 1.92014 1.88228 - 1.84745 1.84355 1.84283 1.84300 1.84254 1.83939 - 12.55323 11.58406 10.61661 9.74776 8.96118 8.24551 - 7.59327 6.99916 6.45091 5.95214 5.50384 5.08755 - 4.70084 4.33429 3.97818 3.62820 3.27626 2.90582 - 2.50060 2.28363 2.05929 1.87291 1.67954 1.63212 - 1.59199 1.58764 1.58595 1.58599 1.58535 1.58251 - 12.82589 11.75876 10.70709 9.77401 8.93773 8.18472 - 7.50453 6.88811 6.32642 5.81994 5.36971 4.95264 - 4.56390 4.19825 3.84180 3.49029 3.13606 2.76364 - 2.35708 2.13852 1.90975 1.71586 1.50655 1.45201 - 1.40830 1.40342 1.40017 1.39989 1.39922 1.39767 - 13.02596 11.86302 10.73805 9.75498 8.88451 8.11016 - 7.41765 6.79143 6.22501 5.71864 5.26873 4.85040 - 4.45570 4.08343 3.71879 3.35979 3.00222 2.63492 - 2.24241 2.02939 1.79707 1.59279 1.37281 1.31479 - 1.26799 1.26228 1.25745 1.25687 1.25632 1.25628 - 13.38781 12.02856 10.76702 9.69582 8.76934 7.96200 - 7.25165 6.61275 6.03550 5.52753 5.07395 4.65186 - 4.25148 3.87767 3.51587 3.16048 2.80754 2.44660 - 2.06203 1.85237 1.62073 1.41220 1.17684 1.11377 - 1.06323 1.05649 1.04958 1.04857 1.04810 1.05013 - 13.68067 12.14743 10.77523 9.63402 8.66563 7.83291 - 7.10672 6.46037 5.87754 5.36828 4.91259 4.48779 - 4.08385 3.70742 3.34959 2.99897 2.65174 2.29831 - 1.92316 1.71802 1.48909 1.27963 1.03658 0.97077 - 0.91807 0.91090 0.90333 0.90219 0.90172 0.90428 - 14.29646 12.37570 10.78694 9.51101 8.46521 7.58646 - 6.82716 6.16416 5.58178 5.06884 4.60734 4.17646 - 3.76667 3.38241 3.03130 2.69302 2.36034 2.02570 - 1.67404 1.48056 1.26022 1.05376 0.80747 0.73972 - 0.68510 0.67813 0.67194 0.67115 0.67052 0.67110 - 14.83944 12.54255 10.79691 9.44389 8.35232 7.43987 - 6.65554 5.97132 5.38114 4.86258 4.39140 3.95156 - 3.53775 3.15315 2.80650 2.48131 2.15851 1.83694 - 1.50467 1.32139 1.10979 0.90937 0.66851 0.60142 - 0.54697 0.54020 0.53597 0.53557 0.53496 0.53336 - 15.86114 12.91874 10.92739 9.44197 8.25980 7.27883 - 6.46540 5.76875 5.16266 4.62935 4.14628 3.70003 - 3.28320 2.89384 2.53664 2.21580 1.90752 1.60181 - 1.29408 1.12946 0.93437 0.74432 0.51349 0.45001 - 0.39751 0.39078 0.38631 0.38580 0.38524 0.38423 - 16.76633 13.30378 11.14277 9.54991 8.30016 7.26015 - 6.41185 5.70122 5.08300 4.53626 4.04380 3.59206 - 3.17055 2.77431 2.40594 2.07321 1.77219 1.47527 - 1.17917 1.02404 0.83930 0.65728 0.43323 0.37162 - 0.32063 0.31381 0.30862 0.30791 0.30747 0.30753 - 17.58179 13.68588 11.39709 9.70690 8.40065 7.31937 - 6.44043 5.71181 5.08121 4.52194 4.01858 3.55855 - 3.13022 2.72720 2.35025 2.00503 1.69892 1.40551 - 1.11496 0.96425 0.78436 0.60622 0.38574 0.32511 - 0.27486 0.26807 0.26277 0.26203 0.26162 0.26182 - 18.31482 14.04897 11.65825 9.88074 8.52309 7.41558 - 6.51464 5.76790 5.12337 4.55195 4.03757 3.56815 - 3.13216 2.72241 2.33788 1.98145 1.66257 1.36928 - 1.08046 0.93120 0.75279 0.57569 0.35604 0.29560 - 0.24543 0.23869 0.23347 0.23275 0.23234 0.23238 - 19.55463 14.69712 12.14785 10.23383 8.79219 7.65241 - 6.72572 5.95095 5.27960 4.68458 4.14943 3.66180 - 3.21035 2.78693 2.38779 2.01150 1.66383 1.35560 - 1.06279 0.91172 0.73061 0.55015 0.32559 0.26368 - 0.21218 0.20532 0.20019 0.19951 0.19905 0.19881 - 20.55115 15.24844 12.57705 10.56771 9.07425 7.91178 - 6.96942 6.17514 5.48158 4.86515 4.31118 3.80718 - 3.34116 2.90405 2.49027 2.09539 1.72170 1.38516 - 1.08253 0.92627 0.73822 0.54998 0.31484 0.24989 - 0.19578 0.18862 0.18336 0.18269 0.18217 0.18187 - 22.33345 16.30057 13.43114 11.28857 9.76589 8.56208 - 7.58162 6.74630 6.01103 5.35409 4.76246 4.22391 - 3.72573 3.25740 2.81071 2.37660 1.95182 1.54677 - 1.19193 1.01637 0.80287 0.58741 0.31716 0.24246 - 0.18029 0.17207 0.16602 0.16526 0.16469 0.16449 - 23.49261 17.02875 14.07649 11.89844 10.38105 9.15027 - 8.13424 7.26332 6.49856 5.81580 5.19830 4.63269 - 4.10827 3.61479 3.14147 2.67523 2.21048 1.75841 - 1.33626 1.13107 0.88535 0.64028 0.33356 0.24904 - 0.17760 0.16785 0.16064 0.15986 0.15898 0.15880 - 24.86682 17.98862 15.02930 12.89285 11.34964 10.08609 - 9.03664 8.13260 7.33263 6.61344 5.96002 5.35854 - 4.79538 4.25932 3.74225 3.23481 2.72668 2.20638 - 1.65910 1.36987 1.05455 0.74877 0.37934 0.27549 - 0.18395 0.17053 0.15936 0.15790 0.15626 0.15451 - 25.73465 18.51350 15.62937 13.61366 12.09515 10.82844 - 9.75743 8.82488 7.99640 7.25087 6.57357 5.95043 - 5.36704 4.81087 4.27180 3.73707 3.19117 2.61329 - 1.97157 1.61156 1.22006 0.86032 0.42873 0.30687 - 0.19571 0.17792 0.16101 0.15850 0.15627 0.15248 - 26.30757 18.83856 16.07104 14.15446 12.66530 11.40371 - 10.32377 9.37603 8.53192 7.77186 7.08145 6.44632 - 5.85135 5.28282 4.72911 4.17481 3.60025 2.97737 - 2.26085 1.84410 1.37448 0.96687 0.47974 0.34048 - 0.20903 0.18644 0.16293 0.15911 0.15605 0.15128 - 26.63371 19.03152 16.43309 14.60337 13.14489 11.88395 - 10.78936 9.82249 8.96397 8.19537 7.50097 6.86459 - 6.26844 5.69685 5.13790 4.57548 3.98392 3.31741 - 2.51643 2.04375 1.51473 1.06791 0.53803 0.37645 - 0.22177 0.19473 0.16534 0.15994 0.15457 0.15049 - 27.21149 19.28191 16.91005 15.17745 13.78182 12.55994 - 11.48966 10.53562 9.68189 8.91212 8.21246 7.56808 - 6.96210 6.37892 5.80545 5.22317 4.60143 3.88370 - 2.99141 2.44665 1.81464 1.26116 0.63905 0.44387 - 0.24808 0.21156 0.16945 0.16133 0.15349 0.14954 - 27.53784 19.44083 17.26323 15.60866 14.25866 13.06153 - 12.00333 11.05531 10.20693 9.44306 8.74976 8.11168 - 7.51068 6.92925 6.35167 5.75468 5.10613 4.35694 - 3.42009 2.82969 2.11159 1.44280 0.72589 0.50682 - 0.27485 0.22819 0.17255 0.16210 0.15360 0.14898 - 27.92067 19.67194 17.78250 16.26624 14.99044 13.84665 - 12.83009 11.92004 11.10996 10.38271 9.71924 9.10234 - 8.51718 7.94765 7.37510 6.76985 6.09480 5.30149 - 4.27785 3.60310 2.74697 1.89676 0.93650 0.65089 - 0.33008 0.26293 0.18199 0.16624 0.15183 0.14821 - 28.11548 19.74965 18.02061 16.62415 15.43171 14.34872 - 13.37368 12.49210 11.70147 10.99028 10.34578 9.75310 - 9.19301 8.64604 8.09377 7.50654 6.84171 6.03226 - 4.94970 4.22365 3.28207 2.30938 1.12581 0.77565 - 0.37611 0.29242 0.19102 0.17080 0.15101 0.14780 - 28.32518 19.82677 18.28761 17.01770 15.91355 14.90612 - 13.99500 13.16988 12.42912 11.76338 11.16170 10.61059 - 10.09185 9.58624 9.07435 8.52380 7.88721 7.08889 - 5.97888 5.20679 4.16803 3.02793 1.44367 0.98779 - 0.45376 0.34223 0.20772 0.18026 0.15099 0.14738 - 28.40642 19.85237 18.42239 17.22627 16.17892 15.22367 - 14.35935 13.57672 12.87370 12.24236 11.67337 11.15479 - 10.67002 10.20079 9.72715 9.21504 8.61415 7.84404 - 6.74367 5.96031 4.88090 3.63957 1.74091 1.16245 - 0.52102 0.38606 0.22250 0.18882 0.15246 0.14717 - 28.40434 19.86348 18.50447 17.35783 16.35008 15.43274 - 14.60332 13.85293 13.17852 12.57317 12.02897 11.53539 - 11.07761 10.63864 10.19905 9.72458 9.16345 8.43043 - 7.35382 6.56917 5.46467 4.15509 2.03422 1.32105 - 0.57809 0.42330 0.23672 0.19784 0.15426 0.14704 - 28.35431 19.87141 18.56160 17.45042 16.47198 15.58332 - 14.78076 14.05506 13.40215 12.81595 12.28998 11.81549 - 11.37998 10.96831 10.56142 10.12443 9.60316 8.90585 - 7.85180 7.07034 5.95754 4.60992 2.31219 1.46765 - 0.62960 0.45849 0.25024 0.20577 0.15647 0.14696 - 28.20488 19.88275 18.64055 17.57870 16.64024 15.79030 - 15.02441 14.33336 13.71248 13.15636 12.66002 12.21636 - 11.81496 11.44283 11.08298 10.70270 10.24852 9.62448 - 8.63833 7.87931 6.76332 5.36135 2.81003 1.76604 - 0.72303 0.51979 0.27451 0.22171 0.16092 0.14685 - 28.06505 19.89423 18.69922 17.67043 16.75760 15.93178 - 15.18815 14.51873 13.91868 13.38356 12.90897 12.48878 - 12.11363 11.77188 11.44813 11.11158 10.71058 10.14963 - 9.23216 8.50304 7.40027 5.97343 3.24938 2.05812 - 0.80771 0.57513 0.29644 0.23632 0.16543 0.14679 - 27.75345 19.91769 18.79771 17.81850 16.94214 16.14859 - 15.43421 14.79364 14.22401 13.72181 13.28345 12.90372 - 12.57431 12.28504 12.02333 11.76199 11.45501 11.01542 - 10.25000 9.60026 8.55753 7.12887 4.16330 2.71986 - 0.99550 0.69738 0.34442 0.26857 0.17629 0.14670 - 27.30722 19.93417 18.85745 17.90364 17.04475 16.26709 - 15.56796 14.94387 14.39296 13.91206 13.49722 13.14335 - 12.84279 12.58662 12.36409 12.15064 11.90582 11.55428 - 10.90975 10.32849 9.35376 7.96150 4.89291 3.28222 - 1.16077 0.80587 0.38596 0.29658 0.18628 0.14666 - 26.18188 19.94308 18.91049 17.98595 17.14957 16.39236 - 15.71242 15.10804 14.57881 14.12189 13.73383 13.41004 - 13.14434 12.92960 12.75740 12.60678 12.44316 12.20234 - 11.72051 11.25115 10.40987 9.11997 6.00103 4.20053 - 1.45246 0.99661 0.45755 0.34442 0.20445 0.14661 - 25.22911 19.94308 18.93230 18.02328 17.20018 16.45573 - 15.78818 15.19639 14.67983 14.23629 13.86315 13.55683 - 13.31185 13.12216 12.98087 12.86944 12.75716 12.58697 - 12.21310 11.82462 11.09309 9.90783 6.82783 4.92828 - 1.70828 1.16527 0.51959 0.38561 0.22062 0.14659 - 24.53964 19.94168 18.94370 18.04433 17.22984 16.49396 - 15.83500 15.25220 14.74447 14.31005 13.94612 13.64988 - 13.41770 13.24518 13.12619 13.04269 12.96619 12.84693 - 12.55076 12.21945 11.57450 10.49452 7.49443 5.51312 - 1.93744 1.32239 0.57585 0.42126 0.23571 0.14658 - 24.06345 19.94057 18.95190 18.05960 17.25087 16.52069 - 15.86739 15.29047 14.78864 14.36035 14.00332 13.71516 - 13.49279 13.33245 13.22890 13.16546 13.11586 13.03477 - 12.79939 12.51582 11.94033 10.94063 8.02952 6.02254 - 2.19256 1.46422 0.62752 0.45508 0.24940 0.14657 - 23.45822 19.94011 18.96399 18.08078 17.27927 16.55606 - 15.90978 15.34037 14.84611 14.42585 14.07801 13.80080 - 13.59159 13.44760 13.36505 13.32936 13.31790 13.29193 - 13.14509 12.93156 12.46090 11.59109 8.86353 6.85482 - 2.72771 1.72099 0.72160 0.51653 0.27421 0.14656 - 23.07419 19.94043 18.97240 18.09477 17.29758 16.57849 - 15.93635 15.37137 14.88171 14.46669 14.12488 13.85462 - 13.65381 13.52031 13.45134 13.43405 13.44835 13.46056 - 13.37605 13.21235 12.81787 12.04784 9.49232 7.51389 - 3.18694 1.95009 0.80690 0.57222 0.29649 0.14655 - 22.48872 19.94121 18.98518 18.11501 17.32385 16.61038 - 15.97382 15.41401 14.93008 14.52192 14.18951 13.93058 - 13.74254 13.62350 13.57264 13.58104 13.63437 13.70654 - 13.71998 13.63510 13.36930 12.77746 10.56909 8.70435 - 4.14421 2.52753 0.99541 0.69539 0.34428 0.14654 - 22.15681 19.94106 18.99103 18.12459 17.33678 16.62663 - 15.99319 15.43619 14.95583 14.55143 14.22388 13.97020 - 13.78845 13.67735 13.63706 13.65997 13.73418 13.83946 - 13.91142 13.87571 13.68904 13.21281 11.27485 9.52328 - 4.88989 3.14363 1.16177 0.80333 0.38607 0.14654 - 21.80292 19.93993 18.99593 18.13348 17.34912 16.64241 - 16.01245 15.45906 14.98244 14.58247 14.25932 14.01119 - 13.83621 13.73352 13.70452 13.74279 13.83919 13.97999 - 14.11813 14.14095 14.05145 13.72064 12.15752 10.60735 - 6.02376 4.12465 1.45252 0.99377 0.45793 0.14653 - 21.61671 19.93883 18.99759 18.13712 17.35461 16.64973 - 16.02202 15.47080 14.99643 14.59850 14.27744 14.03219 - 13.86087 13.76268 13.73967 13.78611 13.89431 14.05446 - 14.22897 14.28534 14.25367 14.01296 12.69950 11.30894 - 6.87327 4.90565 1.70637 1.16283 0.52012 0.14653 - 21.49950 19.93790 18.99828 18.13892 17.35751 16.65404 - 16.02774 15.47807 15.00498 14.60845 14.28865 14.04516 - 13.87620 13.78084 13.76158 13.81315 13.92888 14.10146 - 14.29911 14.37687 14.38368 14.20492 13.07052 11.80453 - 7.53197 5.52943 1.96509 1.31750 0.57610 0.14653 - 21.41711 19.93738 18.99890 18.14034 17.35976 16.65709 - 16.03171 15.48302 15.01076 14.61512 14.29623 14.05414 - 13.88670 13.79335 13.77663 13.83168 13.95270 14.13393 - 14.34769 14.44013 14.47437 14.34126 13.34356 12.17894 - 8.07267 6.06116 2.36995 1.46104 0.62767 0.14653 - 21.31026 19.93761 19.00073 18.14326 17.36357 16.66164 - 16.03679 15.48886 15.01760 14.62347 14.30604 14.06548 - 13.90003 13.80918 13.79554 13.85502 13.98273 14.17513 - 14.40935 14.52147 14.59235 14.52240 13.72317 12.71540 - 8.91577 6.92030 3.03740 1.85709 0.72154 0.14653 - 21.24706 19.93901 19.00360 18.14700 17.36766 16.66544 - 16.04005 15.49166 15.02113 14.62803 14.31197 14.07241 - 13.90795 13.81848 13.80649 13.86841 14.00004 14.19889 - 14.44563 14.57068 14.66534 14.63747 13.97874 13.08921 - 9.55379 7.59348 3.56403 2.26487 0.80670 0.14653 - 6.05804 6.14022 6.18636 6.20347 6.19673 6.17238 - 6.13343 6.08357 6.02734 5.96559 5.89835 5.82647 - 5.75308 5.68153 5.61373 5.55282 5.50199 5.46186 - 5.42980 5.41430 5.39840 5.38552 5.37296 5.36981 - 5.36728 5.36697 5.36675 5.36671 5.36669 5.36670 - 6.71333 6.79258 6.81756 6.80037 6.75105 6.68085 - 6.59398 6.49459 6.38777 6.27525 6.15856 6.04009 - 5.92351 5.81257 5.70869 5.61332 5.52851 5.45658 - 5.39647 5.36785 5.33863 5.31555 5.29576 5.29096 - 5.28701 5.28650 5.28606 5.28599 5.28599 5.28588 - 7.18026 7.25081 7.25123 7.19874 7.10800 6.99493 - 6.86519 6.72390 6.57720 6.42714 6.27523 6.12421 - 5.97698 5.83689 5.70498 5.58201 5.46956 5.37067 - 5.28699 5.24958 5.21366 5.18685 5.16311 5.15745 - 5.15291 5.15232 5.15183 5.15175 5.15173 5.15164 - 7.83955 7.88660 7.83762 7.71968 7.55586 7.37019 - 7.17086 6.96468 6.75906 6.55583 6.35547 6.15998 - 5.97071 5.78967 5.61746 5.45408 5.30049 5.15991 - 5.03795 4.98603 4.94003 4.90897 4.88092 4.87460 - 4.86973 4.86909 4.86861 4.86854 4.86850 4.86847 - 8.30803 8.32913 8.23380 8.05850 7.83357 7.58979 - 7.33708 7.08295 6.83535 6.59527 6.36190 6.13624 - 5.91842 5.70948 5.50955 5.31803 5.13525 4.96415 - 4.81199 4.74714 4.69144 4.65593 4.62502 4.61844 - 4.61353 4.61289 4.61244 4.61237 4.61231 4.61231 - 8.67147 8.66635 8.52838 8.30266 8.02594 7.73452 - 7.43940 7.14822 6.86871 6.60098 6.34308 6.09496 - 5.85601 5.62647 5.40608 5.19367 4.98896 4.79447 - 4.61782 4.54130 4.47604 4.43550 4.40180 4.39492 - 4.38989 4.38925 4.38879 4.38873 4.38867 4.38868 - 8.96840 8.93754 8.76024 8.48979 8.16844 7.83707 - 7.50732 7.18645 6.88165 6.59210 6.31492 6.04906 - 5.79358 5.54803 5.31180 5.08317 4.86129 4.64823 - 4.45114 4.36406 4.28956 4.24362 4.20700 4.19973 - 4.19449 4.19383 4.19336 4.19330 4.19325 4.19324 - 9.43733 9.35697 9.10933 8.76232 8.36731 7.97227 - 7.58901 7.22330 6.88050 6.55818 6.25198 5.95926 - 5.67912 5.40998 5.15058 4.89820 4.65092 4.40999 - 4.18043 4.07493 3.98324 3.92624 3.88352 3.87526 - 3.86934 3.86862 3.86810 3.86802 3.86797 3.86796 - 9.80044 9.67332 9.36409 8.95337 8.49951 8.05554 - 7.63246 7.23416 6.86390 6.51753 6.19017 5.87771 - 5.57981 5.29389 5.01818 4.74905 4.48372 4.22278 - 3.96856 3.84786 3.74110 3.67354 3.62429 3.61475 - 3.60784 3.60701 3.60640 3.60630 3.60626 3.60621 - 10.45252 10.21832 9.78169 9.24841 8.68732 8.15812 - 7.66835 7.21665 6.80159 6.41481 6.05281 5.70781 - 5.38133 5.06864 4.76697 4.47128 4.17739 3.88472 - 3.58941 3.44137 3.30565 3.21539 3.14869 3.13503 - 3.12482 3.12360 3.12268 3.12252 3.12246 3.12241 - 10.90434 10.57414 10.03567 9.41264 8.77818 8.19326 - 7.66188 7.17775 6.73415 6.32256 5.93918 5.57419 - 5.23042 4.90174 4.58450 4.27296 3.96231 3.65133 - 3.33119 3.16538 3.00933 2.90117 2.81747 2.79937 - 2.78554 2.78388 2.78262 2.78242 2.78234 2.78230 - 11.71330 10.95657 10.18781 9.47973 8.82369 8.21392 - 7.64719 7.12098 6.62764 6.17049 5.75008 5.35728 - 4.99186 4.64523 4.31280 3.99103 3.67264 3.34134 - 2.98381 2.79853 2.61908 2.48470 2.36773 2.34827 - 2.32553 2.32207 2.32062 2.32038 2.32048 2.32030 - 12.09014 11.21944 10.34725 9.55627 8.83373 8.17108 - 7.56280 7.00489 6.48803 6.01474 5.58554 5.18625 - 4.81458 4.46300 4.12392 3.79352 3.46431 3.12028 - 2.74775 2.55298 2.36063 2.21141 2.07235 2.04481 - 2.01727 2.01340 2.01128 2.01098 2.01088 2.01078 - 12.35310 11.38931 10.43566 9.58123 8.80867 8.10766 - 7.47021 6.88926 6.35758 5.87512 5.44205 5.04036 - 4.66543 4.31248 3.97066 3.63601 3.30113 2.95053 - 2.57067 2.37113 2.17158 2.01303 1.85730 1.82284 - 1.79165 1.78753 1.78482 1.78446 1.78421 1.78413 - 12.54843 11.50521 10.48440 9.57905 8.76679 8.03617 - 7.37709 6.77849 6.23590 5.74899 5.31428 4.91226 - 4.53589 4.18292 3.84046 3.50401 3.16635 2.81266 - 2.42972 2.22801 2.02448 1.85989 1.69137 1.65112 - 1.61713 1.61286 1.60963 1.60922 1.60885 1.60878 - 12.84538 11.63804 10.49736 9.51160 8.64614 7.88259 - 7.20492 6.59430 6.04342 5.55652 5.12038 4.71537 - 4.33100 3.96872 3.61768 3.27397 2.93372 2.58517 - 2.21474 2.01731 1.80850 1.63109 1.44605 1.39841 - 1.36015 1.35549 1.35154 1.35107 1.35063 1.35050 - 13.09983 11.73620 10.49131 9.43874 8.53266 7.74481 - 7.05260 6.43505 5.87871 5.38944 4.95020 4.54165 - 4.15324 3.78793 3.43896 3.09794 2.76092 2.41680 - 2.05191 1.85659 1.64745 1.46599 1.26947 1.21800 - 1.17671 1.17165 1.16734 1.16685 1.16635 1.16620 - 13.60005 11.90315 10.46086 9.28423 8.30582 7.47571 - 6.75522 6.12378 5.56650 5.07287 4.62741 4.21218 - 3.81727 3.44420 3.09899 2.76699 2.44185 2.11326 - 1.76682 1.57949 1.37363 1.18916 0.98142 0.92567 - 0.88082 0.87530 0.87064 0.87010 0.86955 0.86947 - 14.00613 12.02068 10.44137 9.18802 8.16139 7.29989 - 6.55993 5.91417 5.35229 4.85447 4.40011 3.97532 - 3.57508 3.20112 2.85989 2.53890 2.22265 1.90661 - 1.57771 1.39825 1.19800 1.01583 0.80712 0.75040 - 0.70467 0.69867 0.69424 0.69369 0.69326 0.69313 - 14.78435 12.27953 10.49314 9.13114 8.03053 7.11025 - 6.34095 5.68043 5.10501 4.59682 4.13404 3.70385 - 3.30069 2.92310 2.57436 2.25727 1.95347 1.65427 - 1.34820 1.18195 0.99399 0.81977 0.61465 0.55817 - 0.51245 0.50649 0.50210 0.50154 0.50113 0.50100 - 15.48595 12.56883 10.63661 9.18401 8.02783 7.06243 - 6.26756 5.59597 5.00788 4.48475 4.01163 3.57675 - 3.17102 2.78975 2.43416 2.10912 1.81056 1.51618 - 1.22064 1.06569 0.88688 0.71673 0.51375 0.45855 - 0.41312 0.40712 0.40266 0.40206 0.40165 0.40150 - 16.12294 12.86506 10.82683 9.29745 8.09644 7.09740 - 6.27652 5.58847 4.98846 4.45380 3.97097 3.52886 - 3.11748 2.73091 2.36883 2.03435 1.73180 1.44009 - 1.14974 0.99904 0.82417 0.65633 0.45418 0.39909 - 0.35366 0.34763 0.34315 0.34255 0.34214 0.34191 - 16.70036 13.15386 11.03203 9.43445 8.19302 7.17212 - 6.33216 5.62789 5.01497 4.46908 3.97640 3.52621 - 3.10824 2.71585 2.34740 2.00393 1.69143 1.39965 - 1.11091 0.96157 0.78759 0.61977 0.41664 0.36119 - 0.31537 0.30929 0.30475 0.30414 0.30374 0.30346 - 17.68407 13.68275 11.43295 9.72902 8.42132 7.37275 - 6.50963 5.78029 5.14328 4.57605 4.06492 3.59892 - 3.16742 2.76277 2.38136 2.02113 1.68537 1.38091 - 1.08808 0.93683 0.75950 0.58722 0.37725 0.31975 - 0.27213 0.26580 0.26106 0.26043 0.26001 0.25980 - 18.48064 14.14356 11.79739 10.01900 8.66958 7.60120 - 6.72344 5.97661 5.32007 4.73410 4.20645 3.72605 - 3.28165 2.86470 2.47019 2.09373 1.73596 1.40765 - 1.10493 0.94841 0.76383 0.58331 0.36200 0.30124 - 0.25085 0.24415 0.23914 0.23848 0.23803 0.23794 - 19.92558 15.04511 12.54633 10.66364 9.28744 8.18243 - 7.27006 6.48678 5.79419 5.17366 4.61359 4.10293 - 3.63016 3.18567 2.76204 2.35076 1.94799 1.56075 - 1.21064 1.03470 0.82436 0.61628 0.35947 0.28884 - 0.23025 0.22251 0.21680 0.21606 0.21552 0.21540 - 20.88530 15.68520 13.12451 11.21329 9.83895 8.71014 - 7.76664 6.95243 6.23453 5.59213 5.01009 4.47619 - 3.98064 3.51412 3.06703 2.62738 2.18944 1.76121 - 1.35224 1.14739 0.90476 0.66696 0.37402 0.29340 - 0.22536 0.21615 0.20955 0.20885 0.20804 0.20754 - 22.04337 16.54626 13.98291 12.09480 10.69600 9.54227 - 8.57556 7.73745 6.99099 6.31672 5.70227 5.13596 - 4.60605 4.10266 3.61849 3.14472 2.67082 2.18300 - 1.66257 1.38187 1.07113 0.77330 0.41775 0.31730 - 0.22854 0.21556 0.20489 0.20363 0.20255 0.20102 - 22.78297 17.02521 14.52199 12.72485 11.34741 10.19532 - 9.21635 8.35926 7.59130 6.89499 6.25892 5.67213 - 5.12328 4.60219 4.09990 3.60475 3.10110 2.56496 - 1.96090 1.61643 1.23398 0.88158 0.46472 0.34665 - 0.23787 0.22013 0.20331 0.20116 0.20042 0.19777 - 23.08434 17.29358 14.96628 13.27722 11.92026 10.74924 - 9.73207 8.83520 8.04018 7.33006 6.69010 6.10535 - 5.55935 5.03807 4.53150 4.02617 3.50030 2.91466 - 2.22114 1.81819 1.37171 0.98629 0.52116 0.38015 - 0.24776 0.22568 0.20358 0.20014 0.19757 0.19592 - 23.44180 17.48593 15.25735 13.62582 12.29874 11.14445 - 10.13608 9.24202 8.44545 7.73067 7.08405 6.49158 - 5.93761 5.40830 4.89286 4.37623 3.83336 3.21794 - 2.47053 2.02555 1.52190 1.08693 0.57079 0.41238 - 0.25924 0.23231 0.20390 0.19937 0.19653 0.19477 - 23.98135 17.76193 15.69898 14.13591 12.85191 11.72470 - 10.73481 9.85282 9.06384 8.35303 7.70750 7.11346 - 6.55498 6.01782 5.49107 4.95901 4.39497 3.74804 - 2.93834 2.43104 1.82159 1.27172 0.65734 0.47071 - 0.28602 0.24854 0.20403 0.19727 0.19625 0.19348 - 24.18253 17.85437 15.96332 14.48489 13.25880 12.17083 - 11.20721 10.34185 9.56242 8.85595 8.21127 7.61632 - 7.05701 6.51980 5.99234 5.45578 4.87691 4.19061 - 3.30422 2.74539 2.07624 1.45519 0.75964 0.53691 - 0.30415 0.25913 0.20787 0.19913 0.19393 0.19279 - 24.52443 18.04681 16.37801 15.02938 13.88984 12.86758 - 11.95385 11.12802 10.38040 9.70003 9.07703 8.50014 - 7.95569 7.42996 6.90989 6.37477 5.78652 5.06785 - 4.09959 3.46369 2.66969 1.88766 0.96705 0.67384 - 0.35311 0.28917 0.21495 0.20162 0.19207 0.19190 - 24.68111 18.13901 16.59955 15.34046 14.26193 13.28897 - 12.41496 11.62295 10.90465 10.25044 9.65115 9.09602 - 8.57130 8.06312 7.55820 7.03501 6.45315 5.72877 - 4.72531 4.04727 3.17505 2.27748 1.14892 0.79371 - 0.39566 0.31572 0.22248 0.20517 0.19103 0.19143 - 24.83238 18.20898 16.83086 15.68361 14.68582 13.78163 - 12.96598 12.22573 11.55421 10.94343 10.38529 9.86963 - 9.38271 8.91053 8.43997 7.94917 7.39590 6.69032 - 5.67515 4.96068 4.00086 2.94935 1.46102 1.00004 - 0.46885 0.36197 0.23716 0.21309 0.19042 0.19096 - 24.88239 18.23367 16.95129 15.86961 14.92199 14.06264 - 13.28703 12.58406 11.94768 11.37081 10.84584 10.36283 - 9.90768 9.46615 9.02583 8.56558 8.04401 7.37159 - 6.38180 5.66406 4.66598 3.51569 1.74232 1.17025 - 0.53675 0.40511 0.24916 0.21924 0.19200 0.19074 - 24.84901 18.24203 17.03532 16.00406 15.09238 14.26231 - 13.51037 12.82769 12.20992 11.65149 11.14650 10.68722 - 10.26249 9.85923 9.46171 9.04103 8.54987 7.90267 - 6.93323 6.21852 5.20639 3.99993 2.01781 1.32350 - 0.59289 0.44266 0.26257 0.22641 0.19290 0.19061 - 24.79501 18.24380 17.08371 16.08585 15.20091 14.39585 - 13.66682 13.00590 12.40883 11.87054 11.38560 10.94679 - 10.54345 10.16301 9.79026 9.39654 8.93503 8.32105 - 7.38486 6.68076 5.66313 4.41787 2.27723 1.47165 - 0.64350 0.47561 0.27503 0.23415 0.19414 0.19054 - 24.66566 18.24799 17.14978 16.19728 15.34865 14.57733 - 13.87999 13.24967 12.68255 12.17412 11.71961 11.31256 - 10.94308 10.59946 10.26755 9.91955 9.51010 8.95728 - 8.08853 7.41284 6.40288 5.11540 2.74383 1.75926 - 0.73547 0.53548 0.29799 0.24875 0.19709 0.19045 - 24.55406 18.25522 17.19759 16.27434 15.44858 14.69862 - 14.02120 13.41059 12.86337 12.37561 11.94301 11.55954 - 11.21596 10.90122 10.60203 10.29135 9.92531 9.42484 - 8.61791 7.97284 6.98278 5.68047 3.15407 2.03535 - 0.81908 0.58975 0.31891 0.26231 0.20034 0.19039 - 24.31941 18.27412 17.27608 16.39444 15.60071 14.88003 - 14.23007 13.64702 13.12877 12.67251 12.27481 11.93060 - 11.63169 11.36818 11.12841 10.88693 10.60285 10.20351 - 9.52372 8.95037 8.02578 6.73869 4.00407 2.65372 - 1.00494 0.71008 0.36501 0.29265 0.20879 0.19031 - 23.98978 18.28709 17.32114 16.46146 15.68451 14.97959 - 14.34427 13.77630 13.27434 12.83642 12.45951 12.13942 - 11.86870 11.63860 11.43866 11.24498 11.01916 10.69353 - 10.11087 9.59768 8.73893 7.49435 4.67787 3.17908 - 1.16944 0.81655 0.40517 0.31930 0.21714 0.19026 - 23.15260 18.29796 17.36446 16.52750 15.76877 15.08193 - 14.46419 13.91419 13.43159 13.01480 12.66195 12.36971 - 12.13204 11.94200 11.79150 11.65957 11.51233 11.28892 - 10.84577 10.42474 9.67854 8.53285 5.70277 4.03303 - 1.45963 1.00502 0.47465 0.36547 0.23297 0.19023 - 22.44159 18.30092 17.38356 16.55815 15.80948 15.13318 - 14.52575 13.98649 13.51522 13.11069 12.77135 12.49481 - 12.27595 12.10919 11.98816 11.89457 11.79812 11.64332 - 11.29783 10.94469 10.28747 9.23335 6.46404 4.70915 - 1.71445 1.17215 0.53517 0.40552 0.24756 0.19021 - 21.92546 18.30154 17.39412 16.57613 15.83383 15.16409 - 14.56336 14.03129 13.56734 13.17068 12.84016 12.57372 - 12.36708 12.21558 12.11418 12.04660 11.98564 11.88051 - 11.60876 11.30854 10.72306 9.74828 7.06232 5.26591 - 1.94386 1.32456 0.58994 0.44152 0.26108 0.19020 - 21.56851 18.30141 17.40131 16.58841 15.85085 15.18554 - 14.58933 14.06204 13.60329 13.21208 12.88766 12.62836 - 12.43037 12.28965 12.20213 12.15324 12.11828 12.05090 - 11.83752 11.58017 11.05387 10.14718 7.54890 5.73513 - 2.18707 1.46590 0.64060 0.47460 0.27374 0.19019 - 21.11317 18.30072 17.41072 16.60503 15.87371 15.21380 - 14.62335 14.10208 13.64977 13.26562 12.94922 12.69941 - 12.51290 12.38644 12.31734 12.29335 12.29385 12.28009 - 12.15383 11.96227 11.52896 10.73334 8.30311 6.49382 - 2.68193 1.72316 0.73319 0.53454 0.29704 0.19018 - 20.82338 18.30008 17.41685 16.61581 15.88847 15.23185 - 14.64462 14.12688 13.67846 13.29867 12.98729 12.74360 - 12.56436 12.44689 12.38941 12.38133 12.40489 12.42735 - 12.36286 12.21984 11.85724 11.14915 8.86871 7.08787 - 3.10813 1.95389 0.81745 0.58872 0.31822 0.19017 - 20.38074 18.30231 17.42894 16.63193 15.90707 15.25387 - 14.67144 14.15939 13.71734 13.34472 13.04134 12.80662 - 12.63724 12.53128 12.48886 12.50234 12.55949 12.63824 - 12.66959 12.60247 12.36370 11.81762 9.82994 8.16444 - 3.98936 2.50982 1.00523 0.70807 0.36507 0.19016 - 20.13216 18.30211 17.43340 16.63951 15.91732 15.26668 - 14.68672 14.17702 13.73755 13.36815 13.06846 12.83832 - 12.67426 12.57504 12.54157 12.56742 12.64254 12.75007 - 12.83463 12.81489 12.65519 12.21864 10.45743 8.89707 - 4.67940 3.07628 1.17049 0.81443 0.40558 0.19016 - 19.89723 18.31097 17.43520 16.63977 15.91979 15.27293 - 14.69778 14.19322 13.75875 13.39406 13.09864 12.87160 - 12.70853 12.60876 12.57878 12.62493 12.74412 12.89810 - 13.02016 13.03666 12.96202 12.67763 11.26671 9.85536 - 5.72113 3.98207 1.46031 1.00279 0.47530 0.19015 - 19.73041 18.30135 17.43845 16.64941 15.93174 15.28526 - 14.70932 14.20395 13.76945 13.40548 13.11154 12.88709 - 12.73082 12.64268 12.62411 12.66992 12.77237 12.92561 - 13.10423 13.17172 13.15312 12.92715 11.73679 10.53653 - 6.49866 4.67266 1.71252 1.17600 0.53574 0.19015 - 19.64166 18.30083 17.43961 16.65141 15.93467 15.28924 - 14.71436 14.20991 13.77581 13.41226 13.11939 12.89674 - 12.74268 12.65682 12.64095 12.69133 12.80161 12.96605 - 13.15849 13.23931 13.26343 13.12056 12.08418 10.93956 - 7.10820 5.26699 1.97989 1.32343 0.59090 0.19015 - 19.57948 18.30049 17.44029 16.65280 15.93652 15.29167 - 14.71754 14.21379 13.78042 13.41762 13.12545 12.90359 - 12.75064 12.66625 12.65239 12.70561 12.82026 12.99225 - 13.19844 13.29168 13.33924 13.23975 12.33722 11.28018 - 7.60049 5.75256 2.33416 1.46590 0.64141 0.19015 - 19.49872 18.30063 17.44179 16.65504 15.93946 15.29513 - 14.72152 14.21850 13.78610 13.42445 13.13338 12.91263 - 12.76094 12.67820 12.66677 12.72344 12.84372 13.02507 - 13.24872 13.35841 13.43623 13.39390 12.68857 11.77183 - 8.36328 6.53390 2.92236 1.83702 0.73369 0.19015 - 19.45152 18.30191 17.44398 16.65770 15.94233 15.29780 - 14.72410 14.22105 13.78932 13.42858 13.13845 12.91859 - 12.76755 12.68552 12.67529 12.73384 12.85775 13.04407 - 13.27727 13.39802 13.49499 13.48802 12.92142 12.11608 - 8.93565 7.14255 3.39184 2.19428 0.81783 0.19015 - 5.66971 5.75923 5.81961 5.85588 5.87147 5.87069 - 5.85583 5.82996 5.79705 5.75799 5.71313 5.66312 - 5.60984 5.55551 5.50188 5.45243 5.41061 5.37703 - 5.34986 5.33673 5.32284 5.31107 5.29913 5.29605 - 5.29356 5.29325 5.29303 5.29298 5.29295 5.29296 - 6.34370 6.42204 6.46840 6.48731 6.47920 6.44579 - 6.39065 6.31983 6.24094 6.15630 6.06736 5.97627 - 5.88624 5.80037 5.71927 5.64303 5.57195 5.50692 - 5.44929 5.42269 5.39372 5.36943 5.35196 5.34792 - 5.34411 5.34363 5.34326 5.34319 5.34322 5.34314 - 6.81394 6.90284 6.93219 6.91528 6.86348 6.78959 - 6.69843 6.59481 6.48449 6.36917 6.24980 6.12875 - 6.00967 5.89627 5.78928 5.68885 5.59574 5.51218 - 5.43757 5.40147 5.36629 5.34022 5.31762 5.31208 - 5.30760 5.30702 5.30656 5.30650 5.30647 5.30642 - 7.48409 7.55675 7.54533 7.47161 7.35477 7.21526 - 7.06034 6.89630 6.73034 6.56433 6.39887 6.23611 - 6.07809 5.92737 5.78452 5.64954 5.52306 5.40742 - 5.30660 5.26301 5.22300 5.19411 5.16571 5.15895 - 5.15364 5.15292 5.15238 5.15232 5.15228 5.15226 - 7.95842 8.01038 7.95851 7.83281 7.65938 7.46523 - 7.25933 7.04877 6.84137 6.63862 6.44043 6.24823 - 6.06277 5.88558 5.71707 5.55706 5.40601 5.26637 - 5.14499 5.09470 5.05024 5.01923 4.98789 4.98066 - 4.97508 4.97433 4.97379 4.97371 4.97365 4.97365 - 8.32519 8.35496 8.26478 8.09239 7.86993 7.62992 - 7.38247 7.13498 6.89527 6.66424 6.44104 6.22626 - 6.01986 5.82255 5.63452 5.45525 5.28500 5.12621 - 4.98726 4.93003 4.88037 4.84684 4.81363 4.80622 - 4.80058 4.79982 4.79927 4.79921 4.79915 4.79916 - 8.62404 8.63131 8.50520 8.29073 8.02541 7.74626 - 7.46426 7.18661 6.92083 6.66714 6.42392 6.19092 - 5.96771 5.75437 5.55082 5.35614 5.17021 4.99556 - 4.84106 4.77673 4.72130 4.68478 4.65020 4.64271 - 4.63709 4.63633 4.63580 4.63574 4.63568 4.63568 - 9.09430 9.05720 8.86581 8.57837 8.24122 7.89860 - 7.56207 7.23792 6.93233 6.64414 6.37025 6.10889 - 5.85980 5.62214 5.39522 5.17707 4.96672 4.76681 - 4.58551 4.50703 4.43927 4.39602 4.35932 4.35176 - 4.34619 4.34547 4.34495 4.34490 4.34484 4.34484 - 9.45722 9.37736 9.12807 8.77911 8.38379 7.99150 - 7.61355 7.25490 6.92009 6.60634 6.30970 6.02705 - 5.75870 5.50316 5.25915 5.02366 4.79490 4.57561 - 4.37210 4.28051 4.20070 4.15038 4.11133 4.10357 - 4.09790 4.09720 4.09668 4.09661 4.09657 4.09655 - 10.10666 9.92778 9.55739 9.08855 8.58550 8.10511 - 7.65630 7.23998 6.85678 6.49983 6.16538 5.84679 - 5.54635 5.26098 4.98833 4.72363 4.46369 4.21103 - 3.96653 3.84859 3.74316 3.67599 3.62860 3.61926 - 3.61246 3.61167 3.61106 3.61095 3.61092 3.61088 - 10.55547 10.28742 9.81931 9.26156 8.68355 8.14449 - 7.65058 7.19850 6.78430 6.40051 6.04239 5.70143 - 5.38091 5.07666 4.78549 4.50199 4.22230 3.94830 - 3.67585 3.53886 3.41382 3.33215 3.27457 3.26288 - 3.25423 3.25324 3.25248 3.25235 3.25232 3.25228 - 11.15957 10.73562 10.11504 9.43104 8.75410 8.14085 - 7.59187 7.09774 6.64470 6.22871 5.84253 5.47551 - 5.13096 4.80420 4.49036 4.18404 3.88104 3.58128 - 3.27378 3.11266 2.96123 2.85734 2.77907 2.76213 - 2.74926 2.74776 2.74662 2.74642 2.74635 2.74633 - 11.73771 10.94314 10.14344 9.41282 8.74089 8.12089 - 7.54852 7.02068 6.52997 6.07849 5.66665 5.28313 - 4.92606 4.58936 4.26697 3.95575 3.64920 3.33249 - 2.99424 2.82123 2.65680 2.53711 2.43603 2.42058 - 2.40135 2.39832 2.39723 2.39704 2.39714 2.39693 - 11.99857 11.11404 10.23429 9.44030 8.71765 8.05801 - 7.45498 6.90279 6.39557 5.93307 5.51525 5.12739 - 4.76533 4.42488 4.09724 3.77897 3.46342 3.13598 - 2.78527 2.60491 2.43144 2.30187 2.18538 2.16413 - 2.14174 2.13848 2.13689 2.13666 2.13662 2.13646 - 12.19004 11.22965 10.28434 9.43965 8.67697 7.98687 - 7.36105 6.79046 6.27120 5.80266 5.38164 4.99196 - 4.62722 4.28499 3.95474 3.63250 3.31157 2.97771 - 2.61978 2.43506 2.25582 2.11921 1.99005 1.96357 - 1.93856 1.93515 1.93310 1.93283 1.93267 1.93254 - 12.45485 11.35972 10.30809 9.38663 8.56805 7.83858 - 7.18637 6.59737 6.06634 5.59571 5.17341 4.78186 - 4.41015 4.05786 3.71657 3.38379 3.05621 2.72189 - 2.36916 2.18496 1.99727 1.84622 1.70050 1.66471 - 1.63603 1.63258 1.62967 1.62931 1.62901 1.62893 - 12.69089 11.45046 10.29832 9.31123 8.45187 7.69771 - 7.03072 6.43414 5.89697 5.42271 4.99617 4.59997 - 4.22326 3.86683 3.52555 3.19336 2.86672 2.53373 - 2.18219 1.99754 1.80684 1.64951 1.49043 1.45038 - 1.41832 1.41443 1.41113 1.41074 1.41038 1.41029 - 13.13356 11.59055 10.24979 9.14259 8.21169 7.41543 - 6.72129 6.11107 5.57115 5.09146 4.65801 4.25453 - 3.87068 3.50622 3.16634 2.84008 2.52186 2.19986 - 1.86058 1.68007 1.48795 1.32289 1.14737 1.10159 - 1.06481 1.06032 1.05653 1.05608 1.05565 1.05558 - 13.49116 11.69542 10.21704 9.02484 8.03947 7.21203 - 6.50260 5.88347 5.34133 4.85929 4.42083 4.01251 - 3.62460 3.25577 2.91419 2.59473 2.28600 1.97638 - 1.65143 1.47702 1.28740 1.12075 0.93997 0.89194 - 0.85323 0.84850 0.84453 0.84405 0.84360 0.84356 - 14.13367 11.88420 10.22075 8.93671 7.89067 7.01189 - 6.27284 5.63610 5.07937 4.58597 4.13619 3.71804 - 3.32583 2.95754 2.61565 2.30218 2.00161 1.70482 - 1.40033 1.23669 1.05655 0.89479 0.71134 0.66175 - 0.62183 0.61660 0.61275 0.61227 0.61189 0.61176 - 14.72696 12.12535 10.32829 8.96251 7.86684 6.94923 - 6.18808 5.54080 4.97134 4.46302 4.00259 3.57924 - 3.18419 2.81259 2.46513 2.14535 1.84923 1.55726 - 1.26255 1.10830 0.93534 0.77600 0.59176 0.54228 - 0.50179 0.49645 0.49248 0.49195 0.49158 0.49145 - 15.26876 12.38216 10.48895 9.05437 7.91823 6.97135 - 6.18812 5.52626 4.94489 4.42434 3.95324 3.52184 - 3.12079 2.74432 2.39157 2.06428 1.76492 1.47511 - 1.18503 1.03453 0.86451 0.70616 0.52078 0.47083 - 0.42984 0.42443 0.42039 0.41985 0.41948 0.41932 - 15.71508 12.70008 10.73024 9.18839 7.97226 6.99320 - 6.20275 5.54393 4.96441 4.44125 3.96330 3.52226 - 3.11065 2.72380 2.36096 2.02372 1.71716 1.43200 - 1.14466 0.99173 0.82126 0.66384 0.47624 0.42480 - 0.38330 0.37808 0.37379 0.37328 0.37279 0.37268 - 16.55174 13.17193 11.09013 9.45237 8.17468 7.16908 - 6.35810 5.67787 5.07697 4.53394 4.03813 3.58146 - 3.15662 2.75827 2.38369 2.03156 1.70472 1.40831 - 1.11685 0.96153 0.78705 0.62434 0.42835 0.37436 - 0.33063 0.32509 0.32057 0.32003 0.31953 0.31941 - 17.23419 13.57787 11.41439 9.71371 8.39986 7.37535 - 6.54959 5.85286 5.23482 4.67583 4.16584 3.69640 - 3.25986 2.85022 2.46351 2.09629 1.74941 1.43204 - 1.13099 0.97014 0.78815 0.61695 0.40876 0.35121 - 0.30448 0.29852 0.29372 0.29313 0.29260 0.29251 - 18.52805 14.29442 12.00925 10.28061 8.99693 7.95448 - 7.08452 6.33301 5.66633 5.06810 4.52786 4.03519 - 3.57856 3.14866 2.73884 2.34142 1.95245 1.57654 - 1.22933 1.05329 0.84626 0.64527 0.40109 0.33427 - 0.27906 0.27179 0.26642 0.26570 0.26519 0.26505 - 19.33754 14.85605 12.53026 10.78348 9.50382 8.44221 - 7.54546 6.76659 6.07725 5.45925 4.89912 4.38538 - 3.90809 3.45814 3.02693 2.60364 2.18253 1.76914 - 1.36791 1.16338 0.92404 0.69347 0.41400 0.33726 - 0.27273 0.26405 0.25789 0.25723 0.25650 0.25628 - 20.28712 15.63392 13.33355 11.60575 10.29965 9.21529 - 8.30047 7.50326 6.78964 6.14253 5.55132 5.00588 - 4.49597 4.01267 3.54894 3.09594 2.64261 2.17343 - 1.66790 1.39253 1.08662 0.79731 0.45656 0.36006 - 0.27498 0.26277 0.25300 0.25193 0.25118 0.25027 - 20.90337 16.07014 13.84079 12.19824 10.91449 9.83223 - 8.90571 8.09001 7.35545 6.68683 6.07455 5.50935 - 4.98167 4.48249 4.00314 3.53189 3.05238 2.53858 - 1.95441 1.61993 1.24726 0.90536 0.50253 0.38720 - 0.28404 0.26735 0.25117 0.24929 0.24986 0.24753 - 21.14636 16.31961 14.25507 12.71193 11.44908 10.35080 - 9.39018 8.53893 7.78082 7.10086 6.48592 5.92259 - 5.39597 4.89338 4.40582 3.92094 3.41856 2.86173 - 2.20438 1.82183 1.39399 1.01632 0.55394 0.41553 - 0.29396 0.27301 0.25024 0.24734 0.24879 0.24561 - 21.44920 16.50160 14.52752 13.03885 11.80566 10.72383 - 9.77159 8.92268 8.16254 7.47748 6.85547 6.28413 - 5.74964 5.23965 4.74445 4.25017 3.73347 3.15043 - 2.44392 2.02243 1.54109 1.11543 0.60189 0.44654 - 0.30476 0.27879 0.24964 0.24585 0.24764 0.24410 - 21.84436 16.72629 14.91970 13.51280 12.33283 11.28421 - 10.35273 9.51521 8.75981 8.07454 7.44894 6.87198 - 6.33121 5.81476 5.31200 4.80693 4.27155 3.65127 - 2.87081 2.38858 1.81965 1.30167 0.69529 0.50753 - 0.32606 0.29047 0.24934 0.24375 0.24567 0.24186 - 22.08244 16.86151 15.18435 13.84074 12.70518 11.68753 - 10.77773 9.95516 9.20980 8.53090 7.90901 7.33393 - 6.79393 6.27746 5.77325 5.26397 4.71845 4.07444 - 3.24235 2.71537 2.07876 1.47766 0.78401 0.56561 - 0.34622 0.30179 0.24989 0.24256 0.24401 0.24027 - 22.37747 17.04840 15.56354 14.33807 13.28463 12.33055 - 11.46960 10.68558 9.97091 9.31693 8.71562 8.15781 - 7.63241 7.12784 6.63228 6.12658 5.57518 4.90456 - 3.99999 3.40243 2.64926 1.89652 0.98451 0.69626 - 0.39110 0.32777 0.25342 0.24207 0.24079 0.23785 - 22.51248 17.13589 15.76105 14.61482 13.61818 12.71150 - 11.88983 11.13969 10.45462 9.82708 9.24974 8.71382 - 8.20816 7.72100 7.24040 6.74666 6.20224 5.52804 - 4.59338 3.95796 3.13265 2.27165 1.16131 0.81111 - 0.43020 0.35107 0.25837 0.24343 0.23856 0.23647 - 22.64140 17.20096 15.96042 14.91093 13.98776 13.14605 - 12.38165 11.68390 11.04730 10.46534 9.93121 9.43639 - 8.96912 8.51731 8.06950 7.60606 7.08841 6.43280 - 5.49016 4.82299 3.91836 2.91457 1.46719 1.01072 - 0.49795 0.39242 0.26964 0.24847 0.23600 0.23495 - 22.67867 17.21980 16.05946 15.06727 14.18959 13.39000 - 12.66447 12.00384 11.40304 10.85602 10.35629 9.89523 - 9.46062 9.04010 8.62287 8.18992 7.70301 7.07726 - 6.15376 5.48062 4.53890 3.44733 1.74901 1.18381 - 0.55696 0.42916 0.28131 0.25473 0.23492 0.23413 - 22.65166 17.22713 16.12897 15.17903 14.33264 13.55945 - 12.85640 12.21672 11.63651 11.11098 10.63456 10.19999 - 9.79663 9.41243 9.03350 8.63389 8.17167 7.57147 - 6.67740 6.01063 5.05013 3.89722 2.01241 1.34009 - 0.61047 0.46269 0.29274 0.26136 0.23462 0.23362 - 22.61229 17.22961 16.16792 15.24524 14.42192 13.67118 - 12.99000 12.37167 11.81254 11.30794 10.85275 10.44000 - 10.05936 9.69901 9.34521 8.97186 8.53658 7.96327 - 7.09438 6.43843 5.48238 4.30322 2.26074 1.48008 - 0.66014 0.49585 0.30398 0.26689 0.23502 0.23327 - 22.50931 17.23212 16.22064 15.33590 14.54436 13.82464 - 13.17353 12.58530 12.05644 11.58278 11.15955 10.78010 - 10.43417 10.11013 9.79500 9.46331 9.07451 8.55672 - 7.75261 7.12612 6.18121 4.96193 2.70238 1.76322 - 0.75059 0.55218 0.32448 0.28041 0.23623 0.23283 - 22.44475 17.25262 16.26686 15.40138 14.62654 13.92410 - 13.29078 12.72148 12.21277 11.76051 11.35988 11.00389 - 10.68160 10.38217 10.09739 9.81081 9.48449 9.02381 - 8.25035 7.63668 6.71686 5.50232 3.09373 2.02719 - 0.83298 0.60581 0.34388 0.29182 0.23848 0.23256 - 22.26534 17.27368 16.33534 15.50489 14.75838 14.08310 - 13.47615 12.93353 12.45254 12.02984 11.66171 11.34230 - 11.06195 10.81140 10.58437 10.36684 10.12350 9.76058 - 9.10042 8.54982 7.69238 6.49890 3.90235 2.62036 - 1.01684 0.72353 0.38720 0.31943 0.24454 0.23219 - 21.97453 17.27974 16.37952 15.57229 14.84039 14.17731 - 13.58144 13.05025 12.58241 12.17530 11.82564 11.52901 - 11.27896 11.06763 10.88511 10.70805 10.49978 10.19700 - 9.64925 9.16525 8.36205 7.20182 4.55273 3.11848 - 1.17892 0.82903 0.42557 0.34414 0.25106 0.23201 - 21.30363 17.28912 16.41681 15.62951 14.91387 14.26684 - 13.68655 13.17159 12.72113 12.33312 12.00472 11.73238 - 11.51195 11.33816 11.20349 11.08779 10.95850 10.75769 - 10.34167 9.94009 9.24155 8.18298 5.52868 3.92174 - 1.46721 1.01707 0.49277 0.38711 0.26449 0.23182 - 20.73254 17.28932 16.43120 15.65465 14.94871 14.31103 - 13.73975 13.23363 12.79235 12.41458 12.09862 11.84172 - 11.63946 11.48696 11.37880 11.29837 11.21792 11.08587 - 10.77057 10.43637 9.81539 8.82854 6.24088 4.57463 - 1.72017 1.18108 0.55161 0.42562 0.27727 0.23172 - 20.31871 17.28812 16.43823 15.66833 14.96865 14.33714 - 13.77206 13.27200 12.83694 12.46586 12.15757 11.90993 - 11.71883 11.58006 11.48967 11.43349 11.38721 11.30422 - 11.06216 10.77947 10.22597 9.31131 6.80219 5.10259 - 1.94840 1.33240 0.60522 0.46012 0.28947 0.23167 - 20.03360 17.28693 16.44272 15.67733 14.98220 14.35483 - 13.79379 13.29827 12.86834 12.50273 12.19943 11.95669 - 11.77208 11.64310 11.56641 11.52851 11.50707 11.46078 - 11.27404 11.03008 10.53423 9.69383 7.26996 5.53368 - 2.18179 1.47557 0.65533 0.49090 0.30159 0.23163 - 19.66924 17.28656 16.45058 15.69114 15.00121 14.37883 - 13.82278 13.33243 12.90834 12.54889 12.25256 12.01799 - 11.84346 11.72719 11.66702 11.65135 11.66175 11.66560 - 11.56510 11.38756 10.98187 10.24212 7.97401 6.25440 - 2.64997 1.73060 0.74658 0.54913 0.32337 0.23158 - 19.43774 17.28697 16.45644 15.70064 15.01360 14.39404 - 13.84094 13.35381 12.93320 12.57760 12.28558 12.05615 - 11.88791 11.77959 11.72975 11.72794 11.75835 11.79496 - 11.75476 11.62652 11.29043 10.63068 8.49970 6.81978 - 3.05452 1.95882 0.82977 0.60228 0.34334 0.23155 - 19.08485 17.28810 16.46584 15.71477 15.03162 14.41564 - 13.86638 13.38325 12.96655 12.61576 12.33023 12.10928 - 11.95079 11.85301 11.81627 11.83347 11.89341 11.97722 - 12.02460 11.97556 11.76661 11.25997 9.38604 7.83091 - 3.89694 2.50145 1.01469 0.72104 0.38679 0.23151 - 18.91541 17.29723 16.46727 15.71414 15.03252 14.41994 - 13.87510 13.39674 12.98440 12.63759 12.35578 12.13768 - 11.97952 11.87974 11.84439 11.87890 11.97958 12.10608 - 12.18286 12.15946 12.01420 11.62595 9.99913 8.50601 - 4.54719 3.03965 1.17913 0.82590 0.42536 0.23149 - 18.70299 17.29675 16.47072 15.72016 15.04090 14.43053 - 13.88801 13.41208 13.00214 12.65817 12.37973 12.16556 - 12.01221 11.91863 11.89150 11.93736 12.05465 12.20678 - 12.33268 12.35840 12.30570 12.05816 10.74037 9.41702 - 5.53918 3.89134 1.46736 1.01199 0.49279 0.23148 - 18.59045 17.29585 16.47189 15.72273 15.04457 14.43545 - 13.89404 13.41938 13.01090 12.66840 12.39173 12.17963 - 12.02878 11.93850 11.91573 11.96755 12.09347 12.25868 - 12.41003 12.46212 12.46170 12.29986 11.19925 10.01201 - 6.27556 4.56362 1.71977 1.17792 0.55184 0.23147 - 18.49396 17.28633 16.47321 15.72936 15.05288 14.44373 - 13.90139 13.42579 13.01697 12.67465 12.39799 12.18674 - 12.04071 11.96060 11.94792 11.99716 12.10216 12.25852 - 12.45044 12.53972 12.57366 12.43959 11.49458 10.48663 - 6.84457 5.07695 1.97813 1.33697 0.60479 0.23146 - 18.44437 17.28587 16.47350 15.73004 15.05418 14.44552 - 13.90376 13.42863 13.02053 12.67887 12.40300 12.19264 - 12.04764 11.96881 11.95784 12.00947 12.11817 12.28077 - 12.48420 12.58404 12.63926 12.54545 11.72879 10.80800 - 7.30868 5.53208 2.30187 1.47971 0.65405 0.23146 - 18.37973 17.28610 16.47496 15.73225 15.05676 14.44852 - 13.90710 13.43252 13.02500 12.68424 12.40930 12.20006 - 12.05634 11.97910 11.97028 12.02503 12.13853 12.30910 - 12.52688 12.64009 12.72261 12.68361 12.05437 11.26618 - 8.02532 6.26567 2.84498 1.82960 0.74431 0.23145 - 18.34068 17.28772 16.47821 15.73587 15.06034 14.45176 - 13.90978 13.43464 13.02682 12.68622 12.41246 12.20513 - 12.06301 11.98613 11.97722 12.03324 12.15089 12.32781 - 12.55206 12.67011 12.76995 12.77957 12.28961 11.54551 - 8.55596 6.86318 3.28702 2.15181 0.82898 0.23145 - 5.33622 5.42716 5.49406 5.54076 5.56969 5.58398 - 5.58507 5.57515 5.55713 5.53207 5.50116 5.46525 - 5.42518 5.38222 5.33786 5.29554 5.25886 5.22912 - 5.20617 5.19597 5.18507 5.17521 5.16376 5.16067 - 5.15821 5.15788 5.15765 5.15762 5.15759 5.15760 - 6.01520 6.11555 6.17674 6.20601 6.20923 6.19348 - 6.16180 6.11781 6.06607 6.00713 5.94065 5.86782 - 5.79303 5.72030 5.65002 5.58202 5.51702 5.45833 - 5.40413 5.37492 5.34642 5.32641 5.31139 5.30768 - 5.30470 5.30433 5.30402 5.30397 5.30397 5.30391 - 6.49833 6.59962 6.64785 6.65407 6.62812 6.58119 - 6.51756 6.44157 6.35852 6.26945 6.17442 6.07523 - 5.97601 5.88075 5.78970 5.70224 5.61849 5.54133 - 5.47001 5.43403 5.39963 5.37535 5.35535 5.35051 - 5.34666 5.34618 5.34579 5.34573 5.34571 5.34565 - 7.17762 7.26920 7.28466 7.24258 7.15992 7.05507 - 6.93439 6.80347 6.66880 6.53213 6.39407 6.25671 - 6.12245 5.99401 5.87188 5.75581 5.64596 5.54380 - 5.45213 5.41133 5.37338 5.34562 5.31825 5.31172 - 5.30655 5.30586 5.30536 5.30530 5.30525 5.30523 - 7.65740 7.73251 7.71324 7.62521 7.49153 7.33654 - 7.16827 6.99316 6.81849 6.64606 6.47634 6.31112 - 6.15139 5.99884 5.85403 5.71701 5.58801 5.46781 - 5.36193 5.31796 5.27796 5.24843 5.21698 5.20956 - 5.20373 5.20293 5.20237 5.20231 5.20224 5.20223 - 8.02772 8.08378 8.03050 7.90017 7.72126 7.52306 - 7.31485 7.10362 6.89703 6.69654 6.50216 6.31499 - 6.13525 5.96389 5.80145 5.64786 5.50335 5.36852 - 5.25062 5.20299 5.16037 5.12921 5.09552 5.08767 - 5.08153 5.08069 5.08010 5.08003 5.07996 5.07996 - 8.32903 8.36504 8.27920 8.11012 7.89094 7.65513 - 7.41294 7.17160 6.93884 6.71560 6.50120 6.29593 - 6.09973 5.91304 5.73623 5.56897 5.41126 5.26391 - 5.13506 5.08314 5.03717 5.00424 4.96933 4.96133 - 4.95512 4.95428 4.95368 4.95360 4.95353 4.95354 - 8.80253 8.79795 8.65173 8.41408 8.12607 7.82780 - 7.53067 7.24182 6.96848 6.71028 6.46474 6.23067 - 6.00835 5.79767 5.59848 5.40942 5.22985 5.06147 - 4.91266 4.85089 4.79675 4.75982 4.72421 4.71633 - 4.71028 4.70947 4.70890 4.70883 4.70877 4.70875 - 9.16746 9.12311 8.92240 8.62584 8.28089 7.93264 - 7.59280 7.26793 6.96439 6.68006 6.41111 6.15487 - 5.91248 5.68356 5.46735 5.26134 5.06416 4.87859 - 4.71202 4.64002 4.57697 4.53560 4.49977 4.49210 - 4.48631 4.48556 4.48502 4.48496 4.48491 4.48487 - 10.09574 9.67954 9.24416 8.82506 8.42105 8.03148 - 7.65574 7.29357 6.94523 6.60948 6.29026 5.98645 - 5.69945 5.42706 5.16997 4.92896 4.70427 4.49341 - 4.29902 4.21400 4.14364 4.09801 4.03303 4.01254 - 4.01724 4.02046 4.01873 4.01765 4.01957 4.01831 - 10.27027 10.04963 9.63832 9.13548 8.60589 8.10586 - 7.64369 7.21931 6.83176 6.47392 6.13955 5.82061 - 5.52153 5.24002 4.97327 4.71590 4.46478 4.22442 - 3.99392 3.88080 3.77930 3.71510 3.67140 3.66269 - 3.65635 3.65565 3.65510 3.65499 3.65497 3.65495 - 10.87590 10.50970 9.94924 9.31792 8.68490 8.10663 - 7.58599 7.11629 6.68690 6.29331 5.92735 5.57922 - 5.25284 4.94512 4.65173 4.36733 4.08852 3.81813 - 3.54889 3.41064 3.28383 3.20108 3.14384 3.13210 - 3.12345 3.12250 3.12175 3.12161 3.12158 3.12159 - 11.45852 10.72558 9.98356 9.30113 8.67023 8.08537 - 7.54310 7.04096 6.57290 6.14078 5.74510 5.37655 - 5.03370 4.71166 4.40555 4.11297 3.82847 3.53871 - 3.23421 3.08158 2.94083 2.84376 2.76803 2.75933 - 2.74547 2.74310 2.74257 2.74243 2.74264 2.74244 - 11.72063 10.90044 10.07917 9.33307 8.65056 8.02470 - 7.45017 6.92216 6.43575 5.99073 5.58696 5.21208 - 4.86243 4.53438 4.22066 3.91848 3.62205 3.31798 - 2.99682 2.83486 2.68409 2.57755 2.48860 2.47537 - 2.45899 2.45642 2.45551 2.45535 2.45543 2.45526 - 11.91126 11.01830 10.13257 9.33578 8.61277 7.95548 - 7.35697 6.80954 6.30981 5.85709 5.44849 5.07020 - 4.71646 4.38489 4.06668 3.75846 3.45424 3.14077 - 2.80871 2.64059 2.48287 2.36915 2.26874 2.25113 - 2.23250 2.22979 2.22850 2.22831 2.22829 2.22813 - 12.15498 11.14958 10.16768 9.29687 8.51586 7.81417 - 7.18294 6.61158 6.09654 5.63926 5.22857 4.84844 - 4.48795 4.14546 3.81409 3.49214 3.17690 2.85736 - 2.52410 2.35350 2.18523 2.05641 1.94056 1.91347 - 1.89184 1.88928 1.88713 1.88685 1.88664 1.88655 - 12.37867 11.23762 10.15836 9.22272 8.40044 7.67313 - 7.02623 6.44614 5.92390 5.46160 5.04543 4.65945 - 4.29275 3.94472 3.61129 3.28784 2.97132 2.65007 - 2.31365 2.14014 1.96669 1.83028 1.70072 1.66943 - 1.64446 1.64147 1.63894 1.63863 1.63836 1.63826 - 12.78384 11.36329 10.10151 9.04790 8.15379 7.38356 - 6.70924 6.11475 5.58771 5.11857 4.69438 4.30003 - 3.92496 3.56779 3.23316 2.91259 2.60116 2.28638 - 1.95578 1.78253 1.60345 1.45570 1.30702 1.26943 - 1.23925 1.23560 1.23252 1.23215 1.23181 1.23174 - 13.10084 11.44961 10.05519 8.91868 7.97134 7.17044 - 6.48087 5.87760 5.34772 4.87572 4.44649 4.04723 - 3.66790 3.30626 2.96953 2.65420 2.35048 2.04573 - 1.72620 1.55691 1.37749 1.22518 1.06831 1.02769 - 0.99495 0.99099 0.98766 0.98724 0.98688 0.98686 - 13.65273 11.61174 10.04162 8.80980 7.79874 6.94919 - 6.23369 5.61608 5.07342 4.59023 4.14925 3.73943 - 3.35496 2.99343 2.65677 2.34654 2.04916 1.75526 - 1.45341 1.29264 1.11968 0.96893 0.80476 0.76141 - 0.72658 0.72199 0.71862 0.71821 0.71785 0.71779 - 14.17338 11.81515 10.12231 8.81946 7.76530 6.87878 - 6.13909 5.50839 4.95422 4.45931 4.00888 3.59227 - 3.20328 2.83830 2.49705 2.18123 1.88692 1.59855 - 1.30596 1.15133 0.98359 0.83489 0.66764 0.62273 - 0.58676 0.58205 0.57856 0.57812 0.57779 0.57765 - 14.65365 12.04039 10.25857 8.89527 7.80594 6.89286 - 6.13206 5.48664 4.92061 4.41399 3.95307 3.52807 - 3.13270 2.76279 2.41660 2.09400 1.79657 1.51045 - 1.22225 1.07034 0.90445 0.75580 0.58583 0.53981 - 0.50289 0.49806 0.49447 0.49402 0.49369 0.49349 - 15.09148 12.26655 10.41616 9.00053 7.87991 6.94863 - 6.17161 5.51190 4.93375 4.41612 3.94526 3.51179 - 3.10960 2.73415 2.38258 2.05315 1.74844 1.46207 - 1.17491 1.02353 0.85725 0.70712 0.53379 0.48664 - 0.44867 0.44370 0.44002 0.43955 0.43922 0.43898 - 15.79003 12.75245 10.79777 9.25117 8.03456 7.06898 - 6.28415 5.62178 5.03466 4.50328 4.01772 3.57015 - 3.15327 2.76195 2.39413 2.04907 1.72849 1.43399 - 1.14227 0.98778 0.81688 0.66076 0.47737 0.42729 - 0.38688 0.38180 0.37762 0.37713 0.37665 0.37654 - 16.38916 13.11898 11.09423 9.49220 8.24269 7.25889 - 6.45955 5.78158 5.17872 4.63288 4.13455 3.67551 - 3.24800 2.84623 2.46706 2.10784 1.76867 1.45481 - 1.15327 0.99309 0.81444 0.64953 0.45335 0.39948 - 0.35592 0.35043 0.34593 0.34539 0.34489 0.34484 - 17.46187 13.82465 11.70498 10.03678 8.76966 7.75671 - 6.92657 6.21629 5.58312 5.00971 4.48652 4.00461 - 3.55513 3.13087 2.72661 2.33644 1.95772 1.59497 - 1.25129 1.07100 0.86616 0.67358 0.44112 0.37704 - 0.32515 0.31859 0.31335 0.31268 0.31210 0.31207 - 18.13602 14.31433 12.18211 10.51161 9.25376 8.22525 - 7.36971 6.63159 5.97378 5.37898 4.83659 4.33655 - 3.86858 3.42457 2.99948 2.58750 2.18348 1.78395 - 1.38534 1.17890 0.94222 0.71952 0.45256 0.37755 - 0.31660 0.30892 0.30287 0.30207 0.30164 0.30118 - 18.99329 14.95482 12.86444 11.26228 10.02606 8.98967 - 8.10827 7.33699 6.64588 6.01933 5.44710 4.91937 - 4.42587 3.95780 3.50837 3.06874 2.62784 2.16999 - 1.67501 1.40505 1.10593 0.82500 0.49201 0.39653 - 0.31657 0.30550 0.29608 0.29498 0.29488 0.29313 - 19.50800 15.33353 13.32780 11.81979 10.61484 9.57912 - 8.67968 7.88551 7.17647 6.53602 5.94971 5.40562 - 4.89463 4.40852 3.94001 3.47929 3.01346 2.52266 - 1.96386 1.63567 1.26567 0.92642 0.53414 0.42423 - 0.32350 0.30747 0.29336 0.29191 0.29197 0.28930 - 19.72784 15.56973 13.70370 12.27685 11.09147 10.05255 - 9.13787 8.32349 7.59509 6.93937 6.34446 5.79819 - 5.28699 4.79921 4.32646 3.85704 3.37149 2.83375 - 2.19862 1.82817 1.41156 1.04030 0.58563 0.44896 - 0.33090 0.31160 0.29166 0.28929 0.29050 0.28675 - 19.98576 15.73590 13.95488 12.58146 11.42669 10.40553 - 9.50031 8.68907 7.95927 7.29889 6.69728 6.14330 - 5.62453 5.12975 4.64989 4.17184 3.67322 3.11146 - 2.43078 2.02391 1.55674 1.13866 0.63174 0.47782 - 0.33975 0.31581 0.29039 0.28736 0.28896 0.28484 - 20.32376 15.94472 14.31720 13.02390 11.92310 10.93673 - 10.05345 9.25439 8.52971 7.86927 7.26403 6.70436 - 6.17931 5.67829 5.19136 4.70347 4.18797 3.59233 - 2.84348 2.37989 1.83002 1.32328 0.72156 0.53481 - 0.35769 0.32484 0.28894 0.28452 0.28653 0.28215 - 20.52936 16.07274 14.56219 13.33009 12.27348 11.31850 - 10.45747 9.67374 8.95922 8.30502 7.70321 7.14507 - 6.62055 6.11940 5.63120 5.13963 4.61512 3.99810 - 3.20187 2.69652 2.08267 1.49693 0.80704 0.58939 - 0.37513 0.33403 0.28851 0.28268 0.28464 0.28033 - 20.79144 16.25334 14.91427 13.79173 12.81421 11.92188 - 11.10986 10.36522 9.68190 9.05283 8.47148 7.93027 - 7.41991 6.93044 6.45088 5.96335 5.43422 4.79352 - 3.93082 3.35960 2.63560 1.90528 1.00145 0.71374 - 0.41528 0.35623 0.28993 0.28069 0.28122 0.27758 - 20.91750 16.34102 15.09748 14.04559 13.12074 12.27349 - 11.50014 10.78949 10.13632 9.53438 8.97766 8.45886 - 7.96854 7.49653 7.03189 6.55622 6.03423 5.39081 - 4.50059 3.89395 3.10177 2.26858 1.17424 0.82464 - 0.45139 0.37701 0.29317 0.28075 0.27895 0.27603 - 21.04521 16.41216 15.28074 14.31222 13.45310 12.66598 - 11.94742 11.28858 10.68457 10.12979 9.61837 9.14270 - 8.69239 8.25658 7.82479 7.37890 6.88284 6.25759 - 5.36041 4.72397 3.85686 2.88850 1.47537 1.01985 - 0.51552 0.41506 0.30184 0.28373 0.27624 0.27434 - 21.09019 16.43681 15.36986 14.44886 13.62898 12.87968 - 12.19770 11.57499 11.00705 10.48846 10.01328 9.57349 - 9.15769 8.75439 8.35367 7.93804 7.47184 6.87510 - 5.99600 5.35389 4.45189 3.40089 1.75143 1.19095 - 0.57247 0.44968 0.31157 0.28840 0.27486 0.27345 - 21.08917 16.44753 15.42238 14.53210 13.73852 13.01531 - 12.35910 11.76271 11.22174 10.73091 10.28427 9.87347 - 9.48638 9.11101 8.73794 8.35033 7.91331 7.34713 - 6.49494 5.85771 4.94070 3.83652 2.00995 1.34542 - 0.62457 0.48176 0.32146 0.29368 0.27422 0.27289 - 21.04420 16.45186 15.46609 14.60287 13.82902 13.12241 - 12.48032 11.89748 11.37067 10.89563 10.46743 10.07924 - 9.72075 9.38022 9.04421 8.68706 8.26867 7.71988 - 6.89348 6.26968 5.35697 4.22458 2.24897 1.48578 - 0.67350 0.51325 0.33134 0.29845 0.27406 0.27252 - 20.98941 16.46982 15.51555 14.67754 13.92747 13.24679 - 12.63231 12.07860 11.58212 11.13863 10.74311 10.38826 - 10.06275 9.75542 9.45763 9.15260 8.80271 8.31675 - 7.52589 6.91387 6.01585 4.86254 2.67912 1.76165 - 0.76256 0.56899 0.35002 0.30938 0.27476 0.27204 - 20.91885 16.47757 15.55094 14.73381 14.00120 13.33764 - 12.73985 12.20332 11.72492 11.30067 10.92609 10.59434 - 10.29458 10.01619 9.75133 9.48413 9.17758 8.73932 - 7.99837 7.41166 6.53564 5.37627 3.05660 2.02112 - 0.84403 0.62042 0.36780 0.32001 0.27596 0.27175 - 20.76729 16.49532 15.61064 14.82488 14.11780 13.47865 - 12.90452 12.39209 11.93865 11.54135 11.19670 10.89917 - 10.63952 10.40895 10.20167 10.00418 9.78178 9.44152 - 8.81090 8.28443 7.46830 6.33113 3.83630 2.59569 - 1.02628 0.73594 0.40842 0.34503 0.28019 0.27135 - 20.52037 16.49844 15.64838 14.88431 14.19129 13.56332 - 12.99901 12.49654 12.05479 11.67132 11.34260 11.06470 - 10.83250 10.63951 10.47634 10.32010 10.13425 9.85484 - 9.33320 8.87002 8.10833 7.00928 4.46426 3.07271 - 1.18758 0.83999 0.44494 0.36822 0.28502 0.27115 - 19.95810 16.50310 15.67871 14.93477 14.25854 13.64533 - 13.09441 12.60451 12.17557 11.80683 11.49676 11.24280 - 11.03981 10.88201 10.76290 10.66411 10.55455 10.37589 - 9.99349 9.61971 8.95185 7.92916 5.39544 3.86430 - 1.47421 1.02396 0.50960 0.40889 0.29618 0.27095 - 19.48192 16.50357 15.69087 14.95557 14.28727 13.68207 - 13.13937 12.65794 12.23785 11.87871 11.57949 11.33817 - 11.15046 11.01187 10.91769 10.85244 10.78956 10.67828 - 10.39569 10.08830 9.49947 8.55351 6.08402 4.48477 - 1.72657 1.18826 0.56683 0.44553 0.30712 0.27085 - 19.13705 16.50491 15.69848 14.96685 14.30168 13.70068 - 13.16354 12.68866 12.27616 11.92506 11.63344 11.39913 - 11.21973 11.09249 11.01399 10.97060 10.93963 10.87896 - 10.66914 10.40685 9.88552 9.02368 6.63377 4.98032 - 1.95227 1.34089 0.61974 0.47800 0.31819 0.27078 - 18.89798 16.50449 15.70328 14.97518 14.31334 13.71603 - 13.18240 12.71096 12.30176 11.95432 11.66765 11.44036 - 11.26892 11.15014 11.08178 11.05262 11.04335 11.01596 - 10.86535 10.65060 10.18620 9.37300 7.05631 5.42099 - 2.18357 1.47860 0.66835 0.50963 0.32819 0.27074 - 18.59576 16.50417 15.70924 14.98608 14.32888 13.73606 - 13.20676 12.74037 12.33689 11.99564 11.71481 11.49328 - 11.32942 11.22201 11.16937 11.16094 11.18027 11.19951 - 11.12918 10.97585 10.60298 9.90369 7.74265 6.09909 - 2.63236 1.73460 0.75860 0.56550 0.34861 0.27069 - 18.40260 16.50475 15.71471 14.99457 14.33980 13.74952 - 13.22274 12.75877 12.35755 12.01919 11.74250 11.52679 - 11.36947 11.26868 11.22392 11.22709 11.26486 11.31256 - 11.29595 11.19271 10.89620 10.27665 8.22805 6.64311 - 3.02749 1.96200 0.84043 0.61816 0.36634 0.27066 - 18.11047 16.50554 15.72157 15.00560 14.35452 13.76764 - 13.24442 12.78441 12.38796 12.05448 11.78265 11.57164 - 11.42108 11.33046 11.29960 11.32033 11.38170 11.47040 - 11.53709 11.50749 11.32568 10.85851 9.09839 7.61393 - 3.82774 2.49236 1.02436 0.73412 0.40882 0.27062 - 17.97243 16.51472 15.72338 15.00498 14.35480 13.77074 - 13.25120 12.79528 12.40245 12.07214 11.80407 11.59671 - 11.44678 11.35287 11.32106 11.35717 11.45855 11.58739 - 11.67472 11.66570 11.55025 11.20695 9.67252 8.24725 - 4.46105 3.01249 1.18730 0.83729 0.44494 0.27060 - 17.79472 16.51402 15.72610 15.00998 14.36183 13.77962 - 13.26206 12.80812 12.41742 12.08952 11.82416 11.62020 - 11.47447 11.38600 11.36150 11.40769 11.52369 11.67472 - 11.80446 11.83900 11.80862 11.59949 10.37495 9.12092 - 5.41582 3.82865 1.47381 1.02120 0.51027 0.27058 - 17.70097 16.51321 15.72704 15.01204 14.36498 13.78371 - 13.26705 12.81415 12.42450 12.09785 11.83409 11.63199 - 11.48843 11.40289 11.38229 11.43375 11.55731 11.71952 - 11.87080 11.92814 11.94441 11.81539 10.80920 9.69191 - 6.12215 4.47168 1.72520 1.18569 0.56789 0.27057 - 17.61621 16.50436 15.72894 15.01886 14.37303 13.79146 - 13.27361 12.81919 12.42847 12.10151 11.83825 11.63853 - 11.50067 11.42424 11.41153 11.45885 11.56242 11.71827 - 11.90529 11.99034 12.03677 11.95205 11.10815 10.09856 - 6.66916 4.98680 1.98025 1.33659 0.62058 0.27056 - 17.57587 16.50394 15.72869 15.01894 14.37365 13.79261 - 13.27530 12.82173 12.43226 12.10638 11.84338 11.64295 - 11.50493 11.43015 11.42045 11.47086 11.57647 11.73460 - 11.93335 12.03357 12.09789 12.03110 11.30892 10.45017 - 7.11049 5.39968 2.28337 1.48542 0.66790 0.27056 - 17.52209 16.50414 15.72996 15.02087 14.37610 13.79545 - 13.27850 12.82540 12.43633 12.11108 11.84884 11.64927 - 11.51231 11.43884 11.43098 11.48406 11.59369 11.75868 - 11.97028 12.08213 12.17013 12.15217 11.60777 10.87730 - 7.79301 6.10302 2.79857 1.82310 0.75662 0.27055 - 17.48959 16.50528 15.73246 15.02402 14.37945 13.79882 - 13.28177 12.82857 12.43951 12.11427 11.85219 11.65291 - 11.51646 11.44382 11.43715 11.49205 11.60421 11.77320 - 11.99280 12.11261 12.21560 12.22752 11.79859 11.16161 - 8.30101 6.65276 3.22024 2.14005 0.83789 0.27055 - 5.03732 5.12715 5.19716 5.25011 5.28732 5.31071 - 5.32141 5.32136 5.31328 5.29821 5.27745 5.25181 - 5.22200 5.18893 5.15368 5.11890 5.08765 5.06209 - 5.04318 5.03500 5.02604 5.01760 5.00745 5.00467 - 5.00243 5.00213 5.00192 5.00190 5.00188 5.00187 - 5.72529 5.82635 5.89508 5.93663 5.95455 5.95354 - 5.93652 5.90761 5.87187 5.82941 5.77873 5.72010 - 5.65782 5.59582 5.53441 5.47352 5.41395 5.35916 - 5.30820 5.28105 5.25504 5.23718 5.22332 5.21986 - 5.21712 5.21678 5.21652 5.21647 5.21646 5.21641 - 6.21591 6.32053 6.38026 6.40354 6.39734 6.37003 - 6.32564 6.26893 6.20571 6.13655 6.06041 5.97812 - 5.89381 5.81135 5.73102 5.65243 5.57589 5.50397 - 5.43623 5.40197 5.36956 5.34702 5.32820 5.32366 - 5.32007 5.31964 5.31929 5.31921 5.31919 5.31915 - 6.90596 7.00606 7.03947 7.02140 6.96565 6.88758 - 6.79284 6.68692 6.57623 6.46247 6.34621 6.22923 - 6.11370 6.00205 5.89476 5.79179 5.69341 5.60057 - 5.51529 5.47642 5.43988 5.41293 5.38650 5.38022 - 5.37527 5.37461 5.37413 5.37406 5.37401 5.37399 - 7.39269 7.48079 7.48441 7.42527 7.32323 7.19958 - 7.06134 6.91445 6.76573 6.61737 6.47069 6.32776 - 6.18916 6.05618 5.92939 5.80896 5.69516 5.58829 - 5.49252 5.45165 5.41350 5.38445 5.35358 5.34626 - 5.34046 5.33968 5.33912 5.33905 5.33898 5.33899 - 7.76773 7.84046 7.81400 7.71620 7.57222 7.40828 - 7.23258 7.05137 6.87168 6.69576 6.52497 6.36113 - 6.20395 6.05397 5.91172 5.77734 5.65097 5.53289 - 5.42873 5.38579 5.34602 5.31551 5.28213 5.27424 - 5.26800 5.26716 5.26655 5.26647 5.26639 5.26641 - 8.07233 8.12809 8.07229 7.93853 7.75663 7.55697 - 7.34872 7.13833 6.93296 6.73449 6.54390 6.36244 - 6.18956 6.02537 5.87027 5.72408 5.58680 5.45896 - 5.34717 5.30162 5.25978 5.22799 5.19330 5.18514 - 5.17872 5.17783 5.17720 5.17713 5.17706 5.17708 - 8.54978 8.56975 8.45856 8.26036 8.01257 7.75226 - 7.48998 7.23245 6.98672 6.75348 6.53190 6.32176 - 6.12311 5.93582 5.75988 5.59412 5.43802 5.29325 - 5.16697 5.11478 5.06760 5.03332 4.99806 4.98990 - 4.98352 4.98265 4.98204 4.98195 4.98188 4.98188 - 8.91673 8.90063 8.73866 8.48436 8.18121 7.87132 - 7.56596 7.27185 6.99568 6.73640 6.49128 6.25853 - 6.03938 5.83381 5.64130 5.45961 5.28760 5.12823 - 4.98823 4.92851 4.87510 4.83809 4.80318 4.79527 - 4.78914 4.78833 4.78774 4.78767 4.78761 4.78759 - 9.85233 9.47551 9.08135 8.70091 8.33336 7.97822 - 7.63504 7.30369 6.98452 6.67660 6.38344 6.10428 - 5.84060 5.59083 5.35602 5.13744 4.93605 4.75041 - 4.58491 4.51667 4.46511 4.43440 4.37136 4.34556 - 4.35130 4.35562 4.35385 4.35252 4.35511 4.35335 - 10.27939 9.82778 9.35750 8.90747 8.47604 8.06222 - 7.66546 7.28532 6.92148 6.57370 6.24555 5.93521 - 5.64494 5.37235 5.11794 4.88243 4.66570 4.46358 - 4.27674 4.19458 4.12575 4.07928 4.00863 3.98607 - 3.99491 3.99915 3.99678 3.99540 3.99763 3.99627 - 10.62828 10.31107 9.80397 9.22012 8.62678 8.07996 - 7.58478 7.13729 6.72987 6.35744 6.01065 5.68001 - 5.37026 5.07980 4.80502 4.54110 4.28527 4.04137 - 3.80526 3.68698 3.58031 3.51281 3.46786 3.45886 - 3.45236 3.45167 3.45111 3.45100 3.45099 3.45101 - 11.02741 10.59001 9.97024 9.29557 8.63270 8.03503 - 7.50234 7.02522 6.59090 6.19392 5.82650 5.47726 - 5.14946 4.84189 4.54932 4.26724 3.99262 3.72711 - 3.46398 3.33028 3.20819 3.12874 3.07324 3.06190 - 3.05357 3.05264 3.05192 3.05177 3.05175 3.05177 - 11.48425 10.71581 9.94577 9.24216 8.59549 7.99998 - 7.45115 6.94501 6.47744 6.04833 5.65766 5.29492 - 4.95701 4.64097 4.34070 4.05403 3.77604 3.49454 - 3.20166 3.05677 2.92570 2.83766 2.76799 2.75926 - 2.74693 2.74490 2.74436 2.74423 2.74440 2.74422 - 11.67924 10.83859 10.00415 9.24919 8.56102 7.93283 - 7.35865 6.83188 6.34964 5.91129 5.51430 5.14674 - 4.80346 4.48233 4.17589 3.88134 3.59346 3.30003 - 2.99329 2.84085 2.70216 2.60732 2.52782 2.51561 - 2.50148 2.49934 2.49851 2.49836 2.49843 2.49826 - 11.95122 10.99217 10.05632 9.22238 8.47178 7.79503 - 7.18395 6.62884 6.12614 5.67732 5.27326 4.90087 - 4.55169 4.22436 3.91115 3.60740 3.30764 2.99990 - 2.67669 2.51498 2.36591 2.26039 2.16434 2.14598 - 2.12857 2.12619 2.12484 2.12465 2.12456 2.12441 - 12.14198 11.06875 10.04711 9.15328 8.36197 7.65780 - 7.02861 6.46305 5.95362 5.50163 5.09443 4.71746 - 4.36008 4.02083 3.69592 3.38109 3.07361 2.76377 - 2.44386 2.28199 2.12446 2.00569 1.89917 1.87450 - 1.85491 1.85259 1.85064 1.85040 1.85019 1.85009 - 12.53152 11.19207 9.99170 8.97975 8.11444 7.36477 - 6.70623 6.12446 5.60825 5.14841 4.73266 4.34670 - 3.97971 3.62936 3.29983 2.98435 2.67877 2.37122 - 2.05086 1.88547 1.71857 1.58574 1.45906 1.42805 - 1.40318 1.40021 1.39771 1.39739 1.39713 1.39707 - 12.82177 11.26876 9.94063 8.84691 7.92796 7.14626 - 6.47075 5.87905 5.35917 4.89639 4.47621 4.08584 - 3.71437 3.35860 3.02546 2.71324 2.41386 2.11424 - 1.80133 1.63756 1.46772 1.32800 1.19123 1.15677 - 1.12897 1.12564 1.12284 1.12247 1.12220 1.12217 - 13.31840 11.40950 9.91291 8.72476 7.74241 6.91312 - 6.21167 5.60554 5.07348 4.60010 4.16818 3.76638 - 3.38855 3.03203 2.69884 2.39097 2.09661 1.80575 - 1.50704 1.34938 1.18324 1.04237 0.89489 0.85689 - 0.82637 0.82231 0.81936 0.81901 0.81868 0.81865 - 13.77888 11.59008 9.97900 8.72224 7.69782 6.83462 - 6.11168 5.49347 4.94937 4.46286 4.01970 3.60960 - 3.22652 2.86687 2.53025 2.21791 1.92585 1.63919 - 1.34814 1.19567 1.03350 0.89328 0.74055 0.70029 - 0.66814 0.66390 0.66077 0.66039 0.66007 0.65996 - 14.20308 11.79468 10.10189 8.78738 7.72862 6.84128 - 6.10031 5.46931 4.91340 4.41406 3.95887 3.53895 - 3.14869 2.78417 2.44328 2.12506 1.82992 1.54478 - 1.25737 1.10721 0.94626 0.80527 0.64835 0.60648 - 0.57302 0.56862 0.56537 0.56496 0.56464 0.56446 - 14.57414 12.04673 10.28510 8.88791 7.77019 6.85988 - 6.11378 5.48327 4.92421 4.41770 3.95435 3.52668 - 3.12771 2.75300 2.40187 2.07547 1.77605 1.49275 - 1.20588 1.05564 0.89380 0.75078 0.58938 0.54611 - 0.51139 0.50710 0.50350 0.50309 0.50266 0.50254 - 15.23450 12.43573 10.58480 9.11107 7.94290 7.00838 - 6.24307 5.59308 5.01464 4.48994 4.01000 3.56760 - 3.15594 2.77014 2.40807 2.06859 1.75230 1.45889 - 1.16724 1.01399 0.84702 0.69730 0.52520 0.47861 - 0.44112 0.43645 0.43257 0.43212 0.43166 0.43157 - 15.76953 12.77333 10.86198 9.33879 8.13963 7.18652 - 6.40591 5.74027 5.14690 4.60908 4.11787 3.66537 - 3.24406 2.84829 2.47512 2.12201 1.78832 1.47688 - 1.17531 1.01615 0.84101 0.68208 0.49692 0.44647 - 0.40579 0.40070 0.39650 0.39600 0.39552 0.39550 - 16.76729 13.37848 11.39065 9.84726 8.66365 7.68829 - 6.86616 6.15392 5.52306 4.95694 4.44297 3.97072 - 3.53168 3.11856 2.72516 2.34392 1.97126 1.61209 - 1.26936 1.09003 0.88801 0.70097 0.48007 0.41943 - 0.37009 0.36366 0.35896 0.35837 0.35793 0.35777 - 17.36630 13.89192 11.88537 10.29938 9.08867 8.09290 - 7.26034 6.54005 5.89734 5.31603 4.78601 4.29763 - 3.84085 3.40741 2.99161 2.58644 2.18686 1.79226 - 1.40004 1.19670 0.96428 0.74636 0.48809 0.41732 - 0.35962 0.35223 0.34633 0.34562 0.34496 0.34466 - 18.13866 14.49118 12.53099 11.01044 9.82226 8.82164 - 7.96733 7.21817 6.54594 5.93590 5.37825 4.86342 - 4.38129 3.92324 3.48296 3.05216 2.62013 2.17119 - 1.68512 1.41944 1.12492 0.85005 0.52630 0.43351 - 0.35632 0.34600 0.33749 0.33644 0.33600 0.33445 - 18.63226 14.83828 12.95253 11.52822 10.38204 9.38749 - 8.51663 7.74516 7.05735 6.43713 5.86901 5.34018 - 4.84076 4.36270 3.90068 3.44775 2.99269 2.51444 - 1.96877 1.64725 1.28341 0.95008 0.56659 0.45905 - 0.36091 0.34589 0.33366 0.33242 0.33157 0.32953 - 18.91655 15.09651 13.29618 11.91901 10.78472 9.80215 - 8.94261 8.17581 7.48100 6.84619 6.26288 5.72240 - 5.21527 4.73275 4.26701 3.80701 3.33502 2.81867 - 2.21072 1.84936 1.43052 1.05301 0.61233 0.48464 - 0.36681 0.34804 0.33115 0.32933 0.32897 0.32633 - 19.13025 15.25590 13.54312 12.21854 11.11213 10.14317 - 9.28867 8.52178 7.82465 7.18628 6.59860 6.05330 - 5.54113 5.05324 4.58136 4.11338 3.62910 3.09025 - 2.43917 2.04240 1.57323 1.14840 0.65638 0.51199 - 0.37390 0.35080 0.32932 0.32701 0.32681 0.32400 - 19.31235 15.42447 13.90235 12.67602 11.62360 10.67793 - 9.82870 9.05912 8.36005 7.72200 7.13631 6.59357 - 6.08283 5.59369 5.11683 4.63813 4.13255 3.55069 - 2.82305 2.37353 1.83937 1.34333 0.74781 0.56205 - 0.38815 0.35791 0.32710 0.32346 0.32400 0.32080 - 19.48801 15.54286 14.12933 12.96250 11.95386 11.03994 - 10.21362 9.46010 8.77190 8.14079 7.55912 7.01843 - 6.50863 6.01972 5.54187 5.05980 4.54568 3.94354 - 3.17094 2.68162 2.08615 1.51434 0.83052 0.61375 - 0.40325 0.36527 0.32593 0.32116 0.32182 0.31868 - 19.70648 15.70506 14.45138 13.38978 12.45912 11.60751 - 10.83073 10.11711 9.46104 8.85599 8.29563 7.77262 - 7.27771 6.80110 6.33257 5.85525 5.33751 4.71345 - 3.87789 3.32562 2.62441 1.91333 1.01958 0.73283 - 0.43937 0.38424 0.32565 0.31804 0.31838 0.31552 - 19.80792 15.78055 14.61543 13.62107 12.74142 11.93427 - 11.19582 10.51627 9.89065 9.31314 8.77793 8.27786 - 7.80354 7.34502 6.89203 6.42728 5.91743 5.29163 - 4.43020 3.84398 3.07714 2.26701 1.18861 0.84018 - 0.47287 0.40281 0.32742 0.31705 0.31632 0.31376 - 19.90833 15.83798 14.77523 13.85863 13.04186 12.29274 - 11.60805 10.97957 10.40296 9.87277 9.38333 8.92718 - 8.49387 8.07272 7.65388 7.22018 6.73748 6.13085 - 5.26361 4.64876 3.80960 2.86913 1.48474 1.03091 - 0.53372 0.43791 0.33371 0.31823 0.31395 0.31184 - 19.94218 15.85582 14.85029 13.97686 13.19681 12.48356 - 11.83393 11.24076 10.69969 10.20553 9.75251 9.33273 - 8.93470 8.54707 8.16044 7.75816 7.30631 6.72878 - 5.87967 5.25936 4.38651 3.36635 1.75535 1.19939 - 0.58864 0.47054 0.34160 0.32142 0.31262 0.31083 - 19.93867 15.86239 14.89331 14.04748 13.29154 12.60274 - 11.97758 11.40980 10.89505 10.42834 10.00377 9.61318 - 9.24435 8.88538 8.52730 8.15404 7.73226 7.18568 - 6.36320 5.74765 4.86035 3.78899 2.00781 1.35225 - 0.63933 0.50113 0.35000 0.32546 0.31187 0.31021 - 19.92018 15.87474 14.93192 14.10493 13.36453 12.69060 - 12.08010 11.52713 11.02808 10.57838 10.17280 9.80392 - 9.46047 9.13121 8.80719 8.47143 8.08715 7.56763 - 6.75328 6.13914 5.25727 4.16735 2.24147 1.49191 - 0.68720 0.53090 0.35851 0.32957 0.31142 0.30979 - 19.84775 15.87769 14.97147 14.17251 13.45633 12.80656 - 12.22041 11.69269 11.22020 10.79890 10.42402 10.08851 - 9.78131 9.49148 9.21079 8.92290 8.59081 8.12433 - 7.35895 6.76687 5.90070 4.78639 2.66162 1.76295 - 0.77467 0.58518 0.37538 0.33857 0.31158 0.30926 - 19.78554 15.88373 15.00223 14.22214 13.52187 12.88790 - 12.31710 11.80520 11.34948 10.94620 10.59110 10.27771 - 9.99559 9.73449 9.48701 9.23769 8.95002 8.53197 - 7.81606 7.24851 6.40351 5.28382 3.02958 2.01749 - 0.85512 0.63533 0.39169 0.34782 0.31216 0.30894 - 19.65448 15.89995 15.05651 14.30492 13.62809 13.01634 - 12.46698 11.97693 11.54396 11.16531 10.83779 10.55633 - 10.31228 10.09741 9.90647 9.72652 9.52358 9.20509 - 8.60106 8.09316 7.30522 6.20639 3.78883 2.57976 - 1.03567 0.74859 0.42974 0.37041 0.31482 0.30849 - 19.43916 15.90411 15.09312 14.36108 13.69643 13.09418 - 12.55316 12.07160 11.64865 11.28208 10.96950 10.70723 - 10.48964 10.31002 10.16012 10.01911 9.85265 9.59776 - 9.10680 8.66168 7.92128 6.85412 4.40121 3.04837 - 1.19541 0.85114 0.46454 0.39165 0.31843 0.30827 - 18.96118 15.90895 15.11908 14.40504 13.75618 13.16787 - 12.63940 12.16979 11.75890 11.40588 11.10959 10.86785 - 10.67602 10.52896 10.42107 10.33538 10.24255 10.08581 - 9.73343 9.37968 8.73822 7.75057 5.30335 3.81580 - 1.48074 1.03319 0.52696 0.43026 0.32721 0.30804 - 18.55367 15.90982 15.12983 14.42343 13.78133 13.20005 - 12.67898 12.21711 11.81418 11.46999 11.18365 10.95350 - 10.77574 10.64631 10.56122 10.50611 10.45632 10.36427 - 10.11231 9.82683 9.26640 8.35512 5.96940 4.41805 - 1.73190 1.19619 0.58265 0.46535 0.33644 0.30793 - 18.25731 15.91132 15.13714 14.43373 13.79424 13.21661 - 12.70018 12.24373 11.84713 11.50976 11.23075 11.00839 - 10.83930 10.72023 10.64848 10.61201 10.59052 10.54530 - 10.36800 10.13328 9.64119 8.80123 6.48829 4.91138 - 1.95821 1.34564 0.63408 0.49742 0.34575 0.30786 - 18.05287 15.91069 15.14073 14.44056 13.80418 13.22968 - 12.71640 12.26331 11.87011 11.53665 11.26207 11.04496 - 10.88213 10.77078 10.70904 10.68640 10.68515 10.67160 - 10.54873 10.35691 9.92399 9.14690 6.90808 5.32558 - 2.18418 1.48451 0.68202 0.52738 0.35500 0.30782 - 17.79321 15.91024 15.14589 14.45009 13.81774 13.24718 - 12.73788 12.28929 11.90126 11.57338 11.30412 11.09222 - 10.93630 10.83517 10.78770 10.78379 10.80848 10.83792 - 10.79105 10.65896 10.31695 9.65461 7.57239 5.98356 - 2.61998 1.73863 0.77083 0.58193 0.37369 0.30776 - 17.62769 15.91050 15.15035 14.45719 13.82699 13.25882 - 12.75182 12.30570 11.92037 11.59554 11.32969 11.12174 - 10.97073 10.87600 10.83682 10.84403 10.88468 10.94007 - 10.94406 10.85790 10.58620 10.00704 8.05621 6.50756 - 2.99962 1.96517 0.85196 0.63272 0.39087 0.30773 - 17.40364 15.92026 15.15530 14.46130 13.83333 13.26912 - 12.76707 12.32626 11.94611 11.62628 11.36607 11.16398 - 11.01636 10.92222 10.88694 10.91554 11.00443 11.11424 - 11.17000 11.13354 10.97100 10.56046 8.89563 7.42584 - 3.78521 2.49594 1.03353 0.74687 0.42914 0.30768 - 17.26108 15.92020 15.15816 14.46616 13.83997 13.27736 - 12.77707 12.33800 11.95966 11.64183 11.38391 11.18464 - 11.04059 10.95106 10.92180 10.95882 11.06013 11.18945 - 11.28253 11.28330 11.19071 10.88453 9.43274 8.06236 - 4.39909 2.99254 1.19517 0.84871 0.46465 0.30766 - 17.10893 15.91975 15.16072 14.47074 13.84626 13.28526 - 12.78662 12.34921 11.97286 11.65700 11.40151 11.20528 - 11.06504 10.98040 10.95776 11.00389 11.11828 11.26730 - 11.39800 11.43801 11.42377 11.24532 10.10408 8.90740 - 5.32626 3.78284 1.47994 1.03054 0.52792 0.30763 - 17.00316 15.91103 15.16319 14.47835 13.85527 13.29416 - 12.79446 12.35592 11.97876 11.66285 11.40835 11.21491 - 11.08094 11.00605 10.99231 11.03606 11.13315 11.27916 - 11.45047 11.52411 11.55419 11.44285 10.51395 9.45725 - 6.01279 4.40268 1.73000 1.19331 0.58434 0.30762 - 16.95296 15.91043 15.16325 14.47888 13.85638 13.29584 - 12.79671 12.35882 11.98233 11.66731 11.41376 11.22138 - 11.08864 11.01523 11.00350 11.05002 11.15100 11.30338 - 11.48840 11.57558 11.62843 11.56204 10.79891 9.84578 - 6.53805 4.90313 1.98306 1.34347 0.63567 0.30761 - 16.91820 15.90996 15.16296 14.47887 13.85680 13.29668 - 12.79815 12.36108 11.98572 11.67167 11.41826 11.22513 - 11.09222 11.02036 11.01147 11.06074 11.16341 11.31787 - 11.51369 11.61430 11.68332 11.63300 10.98494 10.17996 - 6.96472 5.30244 2.27174 1.49146 0.68188 0.30761 - 16.87140 15.91029 15.16449 14.48103 13.85943 13.29956 - 12.80119 12.36414 11.98854 11.67466 11.42231 11.23125 - 11.10020 11.02905 11.02046 11.07126 11.17834 11.34038 - 11.54685 11.65536 11.74404 11.74836 11.27958 10.54840 - 7.61665 6.00524 2.76763 1.81108 0.77106 0.30760 - 16.84410 15.91138 15.16657 14.48373 13.86243 13.30285 - 12.80444 12.36729 11.99167 11.67779 11.42545 11.23457 - 11.10382 11.03333 11.02572 11.07809 11.18756 11.35367 - 11.56660 11.68065 11.78349 11.81496 11.45028 10.82046 - 8.10308 6.53475 3.17483 2.11508 0.85117 0.30760 - 4.76074 4.84814 4.91893 4.97513 5.01726 5.04641 - 5.06355 5.07062 5.07034 5.06369 5.05175 5.03516 - 5.01441 4.99018 4.96336 4.93632 4.91177 4.89160 - 4.87719 4.87150 4.86527 4.85901 4.85002 4.84730 - 4.84520 4.84493 4.84472 4.84469 4.84467 4.84467 - 5.45668 5.55056 5.62205 5.67350 5.70471 5.71637 - 5.71049 5.69096 5.66293 5.62776 5.58626 5.53970 - 5.49054 5.44096 5.39080 5.33934 5.28650 5.23477 - 5.18759 5.16602 5.14441 5.12783 5.11521 5.11214 - 5.10940 5.10907 5.10882 5.10879 5.10878 5.10874 - 5.95059 6.05849 6.12512 6.15802 6.16369 6.14990 - 6.12012 6.07840 6.02975 5.97446 5.91155 5.84190 - 5.77008 5.70011 5.63170 5.56314 5.49373 5.42706 - 5.36456 5.33344 5.30428 5.28407 5.26647 5.26219 - 5.25884 5.25842 5.25811 5.25805 5.25802 5.25799 - 6.65108 6.75888 6.80502 6.80311 6.76586 6.70748 - 6.63296 6.54700 6.45525 6.35934 6.26008 6.15931 - 6.05904 5.96156 5.86723 5.77592 5.68760 5.60258 - 5.52268 5.48599 5.45141 5.42590 5.40100 5.39511 - 5.39045 5.38985 5.38940 5.38934 5.38931 5.38927 - 7.14588 7.24491 7.26597 7.22825 7.14985 7.05021 - 6.93573 6.81172 6.68447 6.55629 6.42898 6.30458 - 6.18315 6.06557 5.95269 5.84549 5.74450 5.64816 - 5.55897 5.52016 5.48346 5.45526 5.42581 5.41885 - 5.41334 5.41260 5.41207 5.41199 5.41194 5.41194 - 7.54370 7.59021 7.58132 7.52855 7.43505 7.30648 - 7.15180 6.98414 6.81850 6.65877 6.50588 6.36134 - 6.22499 6.09696 5.97597 5.85824 5.74174 5.63246 - 5.53907 5.49945 5.46109 5.43056 5.39875 5.39101 - 5.38495 5.38421 5.38356 5.38351 5.38345 5.38345 - 7.85621 7.88118 7.84532 7.76283 7.63776 7.47686 - 7.29042 7.09302 6.90106 6.71855 6.54634 6.38541 - 6.23486 6.09402 5.96147 5.83315 5.70700 5.58971 - 5.49086 5.44955 5.40965 5.37779 5.34443 5.33631 - 5.32995 5.32917 5.32848 5.32842 5.32835 5.32837 - 8.32145 8.35967 8.27709 8.11249 7.89915 7.67061 - 7.43711 7.20576 6.98422 6.77376 6.57414 6.38532 - 6.20668 6.03788 5.87951 5.73171 5.59460 5.46786 - 5.35612 5.30941 5.26595 5.23290 5.19809 5.18984 - 5.18334 5.18245 5.18182 5.18175 5.18168 5.18168 - 8.69344 8.69765 8.56738 8.34972 8.08338 7.80645 - 7.53016 7.26204 7.00981 6.77309 6.54967 6.33798 - 6.13901 5.95281 5.77933 5.61706 5.46529 5.32600 - 5.20428 5.15222 5.10441 5.06955 5.03489 5.02674 - 5.02033 5.01948 5.01887 5.01877 5.01872 5.01870 - 9.35540 9.27764 9.04253 8.71525 8.34454 7.97629 - 7.62223 7.28903 6.98317 6.70007 6.43446 6.18135 - 5.94526 5.72680 5.52446 5.33364 5.15205 4.98587 - 4.83966 4.77330 4.71351 4.67346 4.63951 4.63177 - 4.62582 4.62508 4.62452 4.62443 4.62440 4.62437 - 10.07132 9.65501 9.22076 8.80412 8.40393 8.01950 - 7.65036 7.29628 6.95706 6.63263 6.32625 6.03656 - 5.76574 5.51206 5.27637 5.05988 4.86306 4.68261 - 4.52058 4.45277 4.39993 4.36597 4.29634 4.26903 - 4.27896 4.28418 4.28172 4.28009 4.28291 4.28113 - 10.42154 10.13845 9.67360 9.13109 8.57445 8.05733 - 7.58615 7.15904 6.77066 6.41602 6.08550 5.77045 - 5.47663 5.20366 4.94780 4.70319 4.46687 4.24556 - 4.03840 3.93674 3.84582 3.78892 3.75051 3.74265 - 3.73698 3.73636 3.73587 3.73577 3.73577 3.73577 - 10.82296 10.42562 9.85008 9.21555 8.58671 8.01602 - 7.50496 7.04624 6.62941 6.24886 5.89620 5.56090 - 5.24712 4.95464 4.67843 4.41340 4.15661 3.91209 - 3.67668 3.55977 3.45452 3.38767 3.34192 3.33268 - 3.32600 3.32527 3.32468 3.32456 3.32455 3.32456 - 11.28235 10.55976 9.83270 9.16506 8.54918 7.98012 - 7.45410 6.96769 6.51739 6.10322 5.72525 5.37439 - 5.04805 4.74377 4.45644 4.18446 3.92373 3.66312 - 3.39604 3.26623 3.15155 3.07769 3.02085 3.01429 - 3.00451 3.00288 3.00251 3.00239 3.00259 3.00241 - 11.48153 10.68748 9.89597 9.17634 8.51808 7.91528 - 7.36271 6.85466 6.38855 5.96385 5.57828 5.22139 - 4.88848 4.57768 4.28258 4.00097 3.72838 3.45368 - 3.17050 3.03221 2.90959 2.82953 2.76460 2.75543 - 2.74435 2.74264 2.74206 2.74193 2.74205 2.74188 - 11.75789 10.84775 9.95509 9.15572 8.43382 7.78096 - 7.18986 6.65183 6.16367 5.72640 5.33182 4.96815 - 4.62750 4.30833 4.00393 3.71032 3.42266 3.12999 - 2.82624 2.67675 2.54263 2.45211 2.37274 2.35870 - 2.34495 2.34304 2.34207 2.34192 2.34188 2.34175 - 11.93363 10.92711 9.95706 9.09985 8.33505 7.65025 - 7.03570 6.48248 5.98476 5.54316 5.14560 4.77808 - 4.42958 4.09770 3.77958 3.47233 3.17414 2.87624 - 2.57247 2.42131 2.27765 2.17341 2.08448 2.06474 - 2.04921 2.04740 2.04588 2.04569 2.04553 2.04545 - 12.31149 11.04886 9.90248 8.92796 8.08907 7.35848 - 6.71445 6.14402 5.63695 5.18454 4.77524 4.39560 - 4.03487 3.69028 3.36562 3.05536 2.75592 2.45599 - 2.14598 1.98808 1.83218 1.71226 1.60343 1.57767 - 1.55706 1.55462 1.55258 1.55231 1.55211 1.55205 - 12.58505 11.11761 9.84546 8.79041 7.89936 7.13806 - 6.47787 5.89771 5.38558 4.92805 4.51195 4.12560 - 3.75885 3.40840 3.08011 2.77227 2.47738 2.18280 - 1.87679 1.71851 1.55765 1.42924 1.30936 1.27997 - 1.25625 1.25343 1.25107 1.25074 1.25053 1.25050 - 13.04072 11.26101 9.82043 8.65800 7.69286 6.88306 - 6.20099 5.61119 5.08944 4.62230 4.19635 3.80117 - 3.42778 3.07230 2.73874 2.43241 2.14356 1.85707 - 1.56095 1.40689 1.24712 1.11494 0.98286 0.94927 - 0.92227 0.91902 0.91628 0.91593 0.91565 0.91563 - 13.45348 11.40837 9.86476 8.64762 7.64981 6.80778 - 6.10022 5.49302 4.95678 4.47594 4.03732 3.63136 - 3.25232 2.89675 2.56399 2.25470 1.96474 1.67989 - 1.39078 1.24057 1.08364 0.95120 0.81171 0.77572 - 0.74699 0.74318 0.74038 0.74005 0.73975 0.73967 - 13.84661 11.59502 9.97360 8.70388 7.67438 6.80774 - 6.08006 5.45805 4.90980 4.41754 3.96883 3.55461 - 3.16917 2.80863 2.47114 2.15596 1.86303 1.57944 - 1.29326 1.14465 0.98801 0.85387 0.70921 0.67133 - 0.64113 0.63714 0.63421 0.63385 0.63354 0.63341 - 14.20627 11.78638 10.10629 8.79198 7.73475 6.85062 - 6.10731 5.47151 4.91151 4.40874 3.95054 3.52817 - 3.13608 2.77006 2.42744 2.10617 1.80695 1.52262 - 1.23677 1.08806 0.93004 0.79327 0.64359 0.60403 - 0.57242 0.56826 0.56519 0.56481 0.56450 0.56433 - 14.79183 12.19522 10.42731 9.00815 7.87365 6.95893 - 6.20510 5.56281 4.99182 4.47503 4.00322 3.56856 - 3.16341 2.78261 2.42465 2.08913 1.77639 1.48425 - 1.19296 1.04077 0.87700 0.73279 0.57152 0.52837 - 0.49369 0.48940 0.48582 0.48541 0.48497 0.48489 - 15.28994 12.51258 10.68763 9.22271 8.05984 7.12837 - 6.36098 5.70453 5.11940 4.58954 4.10598 3.66066 - 3.24557 2.85500 2.48648 2.13799 1.80860 1.49917 - 1.19775 1.03961 0.86772 0.71427 0.53931 0.49203 - 0.45399 0.44925 0.44533 0.44486 0.44440 0.44436 - 16.22060 13.08282 11.18698 9.70534 8.55862 7.60945 - 6.80627 6.10830 5.48804 4.93000 4.42251 3.95588 - 3.52219 3.11448 2.72669 2.35133 1.98435 1.62920 - 1.28744 1.10901 0.91047 0.72917 0.51799 0.46033 - 0.41365 0.40757 0.40309 0.40252 0.40213 0.40196 - 16.77907 13.56878 11.65734 10.13675 8.96474 7.99773 - 7.18643 6.48240 5.85190 5.27978 4.75684 4.27426 - 3.82283 3.39491 2.98512 2.58671 2.19428 1.80538 - 1.41586 1.21329 0.98385 0.77146 0.52387 0.45638 - 0.40149 0.39452 0.38893 0.38826 0.38760 0.38743 - 17.49292 14.13787 12.27424 10.81574 9.66606 8.69577 - 7.86537 7.13533 6.47774 5.87892 5.33009 4.82264 - 4.34748 3.89674 3.46414 3.04134 2.61731 2.17550 - 1.69517 1.43205 1.14082 0.87155 0.55887 0.46991 - 0.39640 0.38688 0.37923 0.37824 0.37758 0.37643 - 17.76547 14.46362 12.74421 11.38387 10.25403 9.26628 - 8.39895 7.63012 6.94557 6.33193 5.77692 5.26775 - 4.79011 4.33250 3.88817 3.44813 2.99754 2.50955 - 1.95271 1.63831 1.29381 0.98088 0.60233 0.48916 - 0.39839 0.38625 0.37521 0.37371 0.37314 0.37114 - 18.05786 14.68126 13.03433 11.73586 10.63778 9.66833 - 8.80967 8.04242 7.35419 6.73320 6.16855 5.64878 - 5.16083 4.69366 4.23965 3.78809 3.32085 2.80388 - 2.19458 1.83962 1.43943 1.08076 0.64489 0.51345 - 0.40302 0.38703 0.37237 0.37056 0.36986 0.36750 - 18.26157 14.82713 13.25484 12.00556 10.93779 9.98730 - 9.13985 8.37781 7.69038 7.06696 6.49778 5.97230 - 5.47845 5.00553 4.54529 4.08577 3.60623 3.06686 - 2.41552 2.02698 1.57998 1.17641 0.68770 0.53869 - 0.40857 0.38864 0.37017 0.36800 0.36727 0.36471 - 18.52119 15.00727 13.56714 12.39292 11.37826 10.46407 - 9.64118 8.89447 8.21547 7.59529 7.02565 6.49737 - 5.99965 5.52227 5.05620 4.58770 4.09227 3.52149 - 2.80752 2.36679 1.84328 1.35634 0.77154 0.58924 - 0.42088 0.39324 0.36705 0.36408 0.36342 0.36069 - 18.67336 15.11397 13.77413 12.65710 11.68554 10.80356 - 10.00463 9.27542 8.60893 7.99739 7.43345 6.90878 - 6.41329 5.93700 5.47046 4.99885 4.49512 3.90469 - 3.14741 2.66827 2.08545 1.52517 0.85180 0.63833 - 0.43376 0.39882 0.36505 0.36119 0.36066 0.35791 - 18.85686 15.25515 14.06333 13.04678 12.15142 11.33186 - 10.58372 9.89648 9.26468 8.68201 8.14225 7.63790 - 7.15937 6.69683 6.24045 5.77399 5.26689 4.65542 - 3.83774 3.29793 2.61287 1.91730 1.03629 0.75259 - 0.46584 0.41440 0.36280 0.35657 0.35630 0.35368 - 18.93756 15.31704 14.20764 13.25458 12.40898 11.63337 - 10.92388 10.27151 9.67136 9.11767 8.60455 8.12461 - 7.66798 7.22448 6.78428 6.33076 5.83179 5.21911 - 4.37692 3.80447 3.05592 2.26409 1.20211 0.85664 - 0.49657 0.43056 0.36287 0.35422 0.35372 0.35129 - 19.01070 15.35800 14.34396 13.46510 12.68065 11.96208 - 11.30585 10.70467 10.15388 9.64821 9.18178 8.74688 - 8.33246 7.92751 7.52251 7.10090 6.62979 6.03708 - 5.19050 4.59069 3.77213 2.85346 1.49393 1.04303 - 0.55376 0.46234 0.36651 0.35322 0.35078 0.34867 - 19.02852 15.36566 14.40565 13.56855 12.82008 12.13655 - 11.51469 10.94802 10.43212 9.96188 9.53144 9.13268 - 8.75367 8.38271 8.01068 7.62146 7.18227 6.61959 - 5.79193 5.18718 4.33593 3.33958 1.76003 1.20892 - 0.60638 0.49277 0.37243 0.35477 0.34915 0.34727 - 19.02577 15.37558 14.45014 13.63847 12.91143 12.24886 - 11.64748 11.10154 10.60725 10.15993 9.75422 9.38264 - 9.03378 8.69640 8.36141 8.01199 7.61244 7.08002 - 6.26298 5.65603 4.79601 3.75952 2.00791 1.35754 - 0.65572 0.52193 0.37924 0.35774 0.34784 0.34641 - 18.99197 15.37153 14.47247 13.68113 12.97167 12.32645 - 11.74234 11.21400 10.73794 10.30984 9.92460 9.57494 - 9.24959 8.93743 8.62966 8.30959 7.94078 7.43717 - 6.64241 6.04319 5.18509 4.12371 2.23789 1.49863 - 0.70182 0.54986 0.38653 0.36082 0.34744 0.34582 - 18.91949 15.36846 14.50426 13.74008 13.05415 12.43210 - 11.87099 11.36637 10.91514 10.51355 10.15710 9.83908 - 9.54878 9.27566 9.01171 8.74087 8.42636 7.97798 - 7.23339 6.65609 5.81295 4.72757 2.64960 1.76628 - 0.78755 0.60223 0.40143 0.36807 0.34715 0.34507 - 18.86113 15.37140 14.53033 13.78388 13.11294 12.50555 - 11.95877 11.46880 11.03304 10.64812 10.31010 10.01293 - 9.74671 9.50170 9.27088 9.03914 8.77026 8.37209 - 7.67873 7.12625 6.30354 5.21249 3.01003 2.01677 - 0.86676 0.65097 0.41627 0.37597 0.34724 0.34461 - 18.72060 15.37537 14.57849 13.86349 13.21620 12.62854 - 12.09895 11.62559 11.20745 10.84268 10.52896 10.26269 - 10.03728 9.84493 9.67607 9.50816 9.30375 8.99465 - 8.43514 7.95593 7.18439 6.10663 3.76297 2.56465 - 1.04444 0.76243 0.45198 0.39587 0.34868 0.34399 - 18.55644 15.38655 14.60929 13.90814 13.27166 12.69345 - 12.17284 11.70888 11.30110 10.94836 10.64885 10.39966 - 10.19519 10.02899 9.89359 9.76954 9.62311 9.38940 - 8.92571 8.50138 7.78410 6.74262 4.35039 3.02929 - 1.20389 0.86260 0.48492 0.41542 0.35123 0.34367 - 18.14014 15.39582 14.63652 13.94881 13.32340 12.75613 - 12.24651 11.79406 11.39861 11.05966 10.77608 10.54589 - 10.36470 10.22782 10.13035 10.05677 9.97974 9.84510 - 9.52493 9.19216 8.57553 7.61615 5.23306 3.77841 - 1.48720 1.04271 0.54476 0.45199 0.35792 0.34335 - 17.78697 15.39981 14.64764 13.96466 13.34367 12.78201 - 12.27910 11.83461 11.44822 11.11905 10.84507 10.62442 - 10.45456 10.33282 10.25578 10.20999 10.17315 10.10345 - 9.88144 9.61129 9.08067 8.21488 5.89205 4.35557 - 1.73586 1.20517 0.59908 0.48525 0.36581 0.34319 - 17.52913 15.39818 14.65111 13.97330 13.35753 12.80081 - 12.30231 11.86163 11.47846 11.15253 10.88360 10.67047 - 10.50998 10.39926 10.33579 10.30781 10.29591 10.26414 - 10.11505 9.90626 9.44598 8.63767 6.38705 4.84739 - 1.96289 1.35265 0.64871 0.51645 0.37356 0.34309 - 17.34950 15.40019 14.65661 13.97980 13.36454 12.80976 - 12.31442 11.87764 11.49860 11.17732 10.91314 10.70488 - 10.54962 10.44487 10.38926 10.37308 10.38004 10.37924 - 10.28217 10.11391 9.71483 8.97335 6.79360 5.25249 - 2.18573 1.49055 0.69586 0.54525 0.38180 0.34303 - 17.12239 15.39710 14.65883 13.98765 13.37816 12.82789 - 12.33600 11.90209 11.52612 11.20820 10.94838 10.74571 - 10.59793 10.50320 10.46071 10.46133 10.49116 10.52737 - 10.50151 10.39529 10.08889 9.45749 7.43059 5.89691 - 2.61573 1.74362 0.78228 0.59931 0.39787 0.34295 - 16.97543 15.39878 14.66457 13.99445 13.38504 12.83588 - 12.34613 11.91503 11.54243 11.22832 10.97249 10.77378 - 10.63002 10.53978 10.50328 10.51361 10.55967 10.62162 - 10.63960 10.57291 10.33883 9.79999 7.89745 6.40611 - 2.98892 1.96971 0.86266 0.64826 0.41388 0.34290 - 16.75471 15.39801 14.66904 14.00291 13.39693 12.85040 - 12.36304 11.93471 11.56576 11.25592 11.00436 10.81003 - 10.67177 10.58932 10.56320 10.58709 10.65264 10.74916 - 10.83659 10.83200 10.69992 10.31034 8.71651 7.32868 - 3.74889 2.48441 1.04256 0.76040 0.45178 0.34283 - 16.63043 15.39824 14.67176 14.00730 13.40269 12.85768 - 12.37162 11.94474 11.57757 11.26953 11.02001 10.82823 - 10.69320 10.61497 10.59433 10.62559 10.70189 10.81588 - 10.93839 10.96844 10.89918 10.60470 9.23240 7.96077 - 4.34901 2.96341 1.20259 0.86189 0.48550 0.34280 - 16.52440 15.40720 14.67299 14.00551 13.40137 12.85869 - 12.37627 11.95323 11.58912 11.28374 11.03676 10.84718 - 10.71179 10.63039 10.60940 10.65558 10.76865 10.91646 - 11.04911 11.09458 11.09499 10.94570 9.88961 8.74563 - 5.25807 3.74671 1.48579 1.03994 0.54572 0.34277 - 16.42969 15.39895 14.67539 14.01277 13.40999 12.86703 - 12.38352 11.95919 11.59420 11.28870 11.04256 10.85554 - 10.72614 10.65410 10.64151 10.68486 10.78015 10.92421 - 11.09560 11.17223 11.21132 11.12289 10.27950 9.27520 - 5.92666 4.35043 1.73475 1.20137 0.60057 0.34275 - 16.38556 15.39849 14.67550 14.01321 13.41080 12.86836 - 12.38547 11.96187 11.59753 11.29263 11.04728 10.86121 - 10.73293 10.66223 10.65141 10.69721 10.79597 10.94565 - 11.12924 11.21798 11.27715 11.22939 10.54637 9.64686 - 6.43755 4.83838 1.98503 1.35053 0.65065 0.34274 - 16.35504 15.39794 14.67509 14.01305 13.41114 12.86910 - 12.38670 11.96379 11.60053 11.29662 11.05137 10.86452 - 10.73599 10.66663 10.65841 10.70678 10.80707 10.95856 - 11.15151 11.25210 11.32597 11.29260 10.71754 9.96369 - 6.85271 5.22760 2.26334 1.49772 0.69571 0.34274 - 16.31371 15.39802 14.67649 14.01514 13.41357 12.87175 - 12.38936 11.96636 11.60284 11.29897 11.05477 10.86999 - 10.74326 10.67449 10.66632 10.71587 10.82016 10.97833 - 11.18083 11.28874 11.37994 11.39468 10.98562 10.30946 - 7.48506 5.91317 2.74417 1.81139 0.78335 0.34273 - 16.29085 15.39902 14.67805 14.01719 13.41600 12.87435 - 12.39204 11.96910 11.60615 11.30279 11.05832 10.87239 - 10.74500 10.67720 10.67117 10.72291 10.82862 10.98877 - 11.19782 11.31321 11.41752 11.44783 11.12336 10.58070 - 7.96571 6.41492 3.13947 2.11490 0.85984 0.34272 - 4.50183 4.58604 4.65645 4.71437 4.75949 4.79202 - 4.81299 4.82470 4.83023 4.83033 4.82536 4.81592 - 4.80371 4.79018 4.77523 4.75863 4.74094 4.72542 - 4.71601 4.71330 4.70916 4.70376 4.69714 4.69517 - 4.69344 4.69321 4.69304 4.69302 4.69303 4.69302 - 5.20065 5.29275 5.36461 5.41830 5.45360 5.47108 - 5.47253 5.46148 5.44262 5.41718 5.38586 5.34978 - 5.31123 5.27210 5.23200 5.18980 5.14511 5.10091 - 5.06127 5.04360 5.02620 5.01289 5.00176 4.99898 - 4.99657 4.99628 4.99606 4.99603 4.99601 4.99595 - 5.70010 5.80600 5.87522 5.91415 5.92809 5.92360 - 5.90385 5.87287 5.83554 5.79209 5.74122 5.68350 - 5.62333 5.56456 5.50670 5.44790 5.38720 5.32809 - 5.27311 5.24653 5.22179 5.20446 5.18847 5.18459 - 5.18150 5.18110 5.18081 5.18077 5.18073 5.18069 - 6.40998 6.52064 6.57464 6.58409 6.56045 6.51666 - 6.45722 6.38649 6.30979 6.22863 6.14382 6.05701 - 5.97002 5.88485 5.80189 5.72115 5.64261 5.56604 - 5.49329 5.46008 5.42875 5.40542 5.38232 5.37685 - 5.37251 5.37194 5.37154 5.37148 5.37142 5.37141 - 6.92505 7.00125 7.03208 7.02526 6.98259 6.90796 - 6.80814 6.69363 6.57681 6.46104 6.34731 6.23739 - 6.13206 6.03231 5.93711 5.84331 5.74899 5.65854 - 5.57837 5.54301 5.50848 5.48120 5.45387 5.44727 - 5.44204 5.44140 5.44086 5.44081 5.44075 5.44076 - 7.31572 7.37575 7.38359 7.34938 7.27582 7.16805 - 7.03442 6.88734 6.74120 6.59976 6.46394 6.33524 - 6.21369 6.09959 5.99175 5.88663 5.78212 5.68329 - 5.59740 5.56017 5.52356 5.49411 5.46394 5.45660 - 5.45079 5.45009 5.44948 5.44942 5.44936 5.44937 - 7.63317 7.67509 7.65928 7.59830 7.49566 7.35763 - 7.19384 7.01827 6.84676 6.68332 6.52879 6.38425 - 6.24906 6.12282 6.00423 5.88943 5.77627 5.67034 - 5.57969 5.54092 5.50268 5.47161 5.43971 5.43193 - 5.42575 5.42500 5.42435 5.42430 5.42424 5.42424 - 8.10630 8.16495 8.10739 7.96940 7.78289 7.58029 - 7.37134 7.16281 6.96208 6.77079 6.58931 6.41793 - 6.25589 6.10279 5.95947 5.82645 5.70396 5.59063 - 5.48916 5.44573 5.40444 5.37230 5.33844 5.33032 - 5.32386 5.32300 5.32238 5.32230 5.32223 5.32223 - 8.48299 8.51157 8.41008 8.22205 7.98468 7.73498 - 7.48393 7.23897 7.00786 6.79068 6.58561 6.39153 - 6.20944 6.03962 5.88218 5.73582 5.59982 5.47546 - 5.36623 5.31875 5.27415 5.24057 5.20647 5.19829 - 5.19181 5.19094 5.19031 5.19023 5.19018 5.19016 - 9.15208 9.10505 8.90458 8.61120 8.27198 7.93184 - 7.60278 7.29210 7.00700 6.74336 6.49583 6.25988 - 6.04048 5.83904 5.65403 5.48064 5.31631 5.16750 - 5.03846 4.97978 4.92598 4.88858 4.85499 4.84707 - 4.84091 4.84012 4.83953 4.83944 4.83939 4.83937 - 9.88093 9.49683 9.09542 8.70924 8.33755 7.97986 - 7.63587 7.30541 6.98845 6.68502 6.39814 6.12680 - 5.87316 5.63590 5.41619 5.21554 5.03485 4.87140 - 4.72800 4.67049 4.62862 4.60269 4.53258 4.50158 - 4.51219 4.51812 4.51553 4.51371 4.51696 4.51490 - 10.22889 9.98449 9.56024 9.05415 8.52863 8.03714 - 7.58740 7.17915 6.80890 6.47144 6.15655 5.85602 - 5.57662 5.31917 5.07993 4.85234 4.63325 4.43116 - 4.24721 4.15812 4.07829 4.02783 3.99238 3.98485 - 3.97935 3.97874 3.97824 3.97815 3.97813 3.97818 - 10.63608 10.27985 9.74581 9.14697 8.54766 8.00065 - 7.50902 7.06730 6.66697 6.30212 5.96353 5.64126 - 5.34049 5.06200 4.80092 4.55155 4.31088 4.08492 - 3.87302 3.76957 3.67686 3.61823 3.57768 3.56939 - 3.56339 3.56273 3.56219 3.56208 3.56207 3.56211 - 11.10412 10.42223 9.73359 9.09841 8.51037 7.96534 - 7.46010 6.99174 6.55729 6.15688 5.79076 5.45105 - 5.13565 4.84260 4.56763 4.30958 4.06501 3.82345 - 3.57898 3.46179 3.35986 3.29601 3.24701 3.24122 - 3.23289 3.23153 3.23120 3.23109 3.23129 3.23114 - 11.31028 10.55665 9.80305 9.11483 8.48325 7.90319 - 7.37011 6.87896 6.42753 6.01536 5.64048 5.29362 - 4.97063 4.66986 4.38582 4.11674 3.85881 3.60161 - 3.33962 3.21354 3.10400 3.03505 2.97973 2.97195 - 2.96276 2.96137 2.96090 2.96078 2.96089 2.96075 - 11.59734 10.72770 9.87192 9.10219 8.40500 7.77288 - 7.19925 6.67633 6.20110 5.77436 5.38867 5.03331 - 4.70092 4.38990 4.09437 3.81090 3.53522 3.25711 - 2.97158 2.83315 2.71201 2.63379 2.56648 2.55489 - 2.54368 2.54215 2.54139 2.54125 2.54125 2.54110 - 11.79249 10.82916 9.89459 9.06331 8.31805 7.64800 - 7.04467 6.50027 6.00984 5.57398 5.18213 4.82209 - 4.48442 4.16675 3.86484 3.57313 3.28721 2.99718 - 2.69830 2.55237 2.42276 2.33620 2.25837 2.24361 - 2.23029 2.22854 2.22751 2.22737 2.22727 2.22714 - 12.14870 10.94139 9.83573 8.88968 8.07144 7.35634 - 6.72459 6.16419 5.66551 5.22019 4.81724 4.44383 - 4.08928 3.75035 3.43060 3.12550 2.83209 2.53987 - 2.24065 2.09026 1.94467 1.83610 1.74170 1.72006 - 1.70283 1.70081 1.69913 1.69890 1.69874 1.69868 - 12.41060 11.00672 9.77726 8.75099 7.88043 7.13411 - 6.48548 5.91461 5.40977 4.95822 4.54752 4.16642 - 3.80478 3.45902 3.13454 2.83033 2.53979 2.25069 - 1.95225 1.79953 1.64697 1.52846 1.42286 1.39772 - 1.37742 1.37503 1.37304 1.37276 1.37260 1.37258 - 12.83466 11.13670 9.74331 8.61151 7.66814 6.87411 - 6.20293 5.62124 5.10579 4.64372 4.22234 3.83155 - 3.46235 3.11070 2.78036 2.47651 2.19037 1.90698 - 1.61495 1.46432 1.31055 1.18638 1.06730 1.03770 - 1.01390 1.01105 1.00866 1.00834 1.00812 1.00813 - 13.21359 11.27290 9.78048 8.59393 7.61697 6.79120 - 6.09534 5.49664 4.96689 4.49117 4.05692 3.65491 - 3.27954 2.92734 2.59759 2.29075 2.00275 1.71999 - 1.43350 1.28573 1.13372 1.00823 0.88033 0.84805 - 0.82227 0.81882 0.81632 0.81603 0.81574 0.81569 - 13.57920 11.44583 9.87897 8.64285 7.63576 6.78610 - 6.07027 5.45649 4.91448 4.42733 3.98300 3.57266 - 3.19079 2.83350 2.49904 2.18657 1.89555 1.61348 - 1.32911 1.18247 1.03017 0.90234 0.76823 0.73373 - 0.70624 0.70260 0.69993 0.69961 0.69931 0.69918 - 13.91473 11.62480 10.00202 8.72425 7.69108 6.82433 - 6.09294 5.46533 4.91159 4.41400 3.96027 3.54181 - 3.15325 2.79050 2.45101 2.13271 1.83572 1.55260 - 1.26808 1.12106 0.96704 0.83614 0.69628 0.65986 - 0.63080 0.62696 0.62414 0.62380 0.62349 0.62331 - 14.46230 12.01112 10.30495 8.92838 7.82205 6.92559 - 6.18356 5.54923 4.98438 4.47276 4.00552 3.57502 - 3.17366 2.79639 2.44189 2.10991 1.80029 1.50942 - 1.21878 1.06787 0.90757 0.76871 0.61671 0.57645 - 0.54415 0.54017 0.53685 0.53646 0.53605 0.53596 - 14.93138 12.31335 10.55279 9.13286 7.99946 7.08683 - 6.33181 5.68412 5.10582 4.58160 4.10292 3.66190 - 3.25072 2.86385 2.49906 2.15460 1.82909 1.52160 - 1.22045 1.06328 0.89447 0.74609 0.58034 0.53595 - 0.50030 0.49589 0.49221 0.49178 0.49135 0.49133 - 15.78915 12.90768 11.07507 9.60367 8.45272 7.51615 - 6.73701 6.06446 5.46226 4.91560 4.41591 3.95493 - 3.52409 3.11681 2.72925 2.35709 1.99685 1.64714 - 1.30634 1.12844 0.93265 0.75619 0.55411 0.49939 - 0.45547 0.45003 0.44550 0.44494 0.44446 0.44447 - 16.35931 13.33514 11.48674 10.01026 8.86421 7.91739 - 7.12206 6.43140 5.81208 5.24935 4.73432 4.25835 - 3.81231 3.38886 2.98330 2.58989 2.20326 1.81921 - 1.43225 1.23057 1.00392 0.79647 0.55848 0.49399 - 0.44164 0.43504 0.42972 0.42910 0.42842 0.42820 - 17.05753 13.89428 12.08398 10.66040 9.53351 8.58398 - 7.77242 7.05950 6.41669 5.83053 5.29253 4.79424 - 4.32668 3.88211 3.45469 3.03665 2.61744 2.18091 - 1.70679 1.44725 1.16041 0.89652 0.59185 0.50553 - 0.43483 0.42597 0.41899 0.41802 0.41701 0.41533 - 17.47191 14.23646 12.49167 11.13368 10.03054 9.08828 - 8.27310 7.55111 6.89732 6.29942 5.74931 5.23871 - 4.75858 4.30087 3.85917 3.42449 2.98300 2.51023 - 1.97240 1.66346 1.31505 0.99670 0.63043 0.52623 - 0.43603 0.42381 0.41442 0.41325 0.41138 0.40885 - 17.58138 14.42824 12.82741 11.55297 10.47175 9.51863 - 8.67618 7.92567 7.25457 6.65080 6.10295 5.59871 - 5.12380 4.66645 4.21953 3.77301 3.30992 2.79849 - 2.19855 1.85019 1.45767 1.10489 0.67552 0.54569 - 0.43841 0.42385 0.41127 0.40953 0.40763 0.40443 - 17.77005 14.56825 13.03670 11.80858 10.75674 9.82254 - 8.99186 8.24755 7.57854 6.97385 6.42303 5.91464 - 5.43509 4.97282 4.52010 4.06569 3.59018 3.05651 - 2.41552 2.03461 1.59669 1.19971 0.71686 0.56919 - 0.44247 0.42431 0.40860 0.40658 0.40434 0.40109 - 18.00018 14.73483 13.32790 12.17262 11.17327 10.27587 - 9.47087 8.74344 8.08471 7.48530 6.93615 6.42697 - 5.94525 5.47971 5.02179 4.55856 4.06708 3.50221 - 2.80001 2.36833 1.85610 1.37756 0.79770 0.61645 - 0.45211 0.42682 0.40457 0.40192 0.39938 0.39635 - 18.12440 14.82666 13.51601 12.41780 11.46198 10.59765 - 9.81766 9.10890 8.46391 7.87438 7.33215 6.82774 - 6.34924 5.88557 5.42769 4.96161 4.46189 3.87765 - 3.13309 2.66394 2.09390 1.54390 0.87515 0.66268 - 0.46278 0.43063 0.40172 0.39835 0.39585 0.39312 - 18.24617 14.92946 13.76671 12.77147 11.89484 11.09552 - 10.36859 9.70368 9.09490 8.53548 8.01847 7.53532 - 7.07475 6.62582 6.17909 5.71915 5.21701 4.61276 - 3.80935 3.28088 2.61078 1.92836 1.05412 0.77163 - 0.49084 0.44290 0.39760 0.39229 0.39047 0.38827 - 18.27867 14.95965 13.88256 12.95424 12.13060 11.37739 - 10.69067 10.06154 9.48480 8.95437 8.46379 8.00482 - 7.56619 7.13679 6.70715 6.26133 5.76868 5.16446 - 4.33758 3.77705 3.04455 2.26773 1.21597 0.87207 - 0.51886 0.45673 0.39616 0.38880 0.38748 0.38556 - 18.29048 14.96047 13.98341 13.13395 12.37535 11.68179 - 11.04980 10.47213 9.94427 9.46078 9.01555 8.60038 - 8.20344 7.81314 7.42023 7.00863 6.54655 5.96464 - 5.13474 4.54730 3.74563 2.84413 1.50252 1.05386 - 0.57252 0.48541 0.39756 0.38609 0.38424 0.38263 - 18.27896 14.94831 14.02673 13.22062 12.49934 11.84150 - 11.24395 10.70019 10.20621 9.75687 9.34623 8.96602 - 8.60391 8.24793 7.88914 7.51178 7.08391 6.53399 - 5.72400 5.13176 4.29768 3.31977 1.76412 1.21711 - 0.62296 0.51385 0.40187 0.38636 0.38253 0.38107 - 18.26093 14.94707 14.06076 13.28101 12.58170 11.94471 - 11.36695 10.84303 10.36927 9.94128 9.55381 9.19949 - 8.86699 8.54511 8.22488 7.88964 7.50380 6.98483 - 6.18339 5.58815 4.74695 3.73244 2.00893 1.36449 - 0.67045 0.54118 0.40744 0.38862 0.38117 0.38010 - 18.22289 14.93801 14.07721 13.31749 12.63536 12.01516 - 11.45387 10.94664 10.49011 10.08021 9.71211 9.37875 - 9.06918 8.77251 8.48009 8.17540 7.82202 7.33361 - 6.55541 5.96776 5.12780 4.08852 2.23503 1.50448 - 0.71541 0.56796 0.41369 0.39084 0.38071 0.37945 - 18.15323 14.93162 14.10354 13.36920 12.70929 12.11078 - 11.57103 11.08592 10.65259 10.26755 9.92663 9.62350 - 9.34796 9.08992 8.84168 8.58742 8.29041 7.85988 - 7.13409 6.56867 5.74278 4.67936 2.63986 1.76941 - 0.79950 0.61862 0.42697 0.39670 0.38024 0.37862 - 18.10243 14.93521 14.12763 13.40917 12.76272 12.17739 - 11.65075 11.17906 10.76000 10.39053 10.06697 9.78372 - 9.53139 9.30085 9.08539 8.87034 8.61974 8.24116 - 7.56909 7.02936 6.22367 5.15429 2.99415 2.01651 - 0.87753 0.66610 0.44053 0.40349 0.38008 0.37811 - 17.98491 14.94420 14.17451 13.48297 12.85712 12.28929 - 11.77800 11.32157 10.91873 10.56797 10.26719 10.01307 - 9.79946 9.61915 9.46338 9.31081 9.12520 8.83829 - 8.30454 7.84032 7.08681 6.03075 3.73395 2.55579 - 1.05336 0.77525 0.47384 0.42135 0.38076 0.37742 - 17.84460 14.95962 14.20566 13.52425 12.90601 12.34561 - 11.84251 11.39539 11.00380 10.66591 10.37899 10.13990 - 9.94456 9.78800 9.66342 9.55224 9.42262 9.21358 - 8.77825 8.36652 7.67236 6.66264 4.31418 3.00676 - 1.21124 0.87420 0.50501 0.43987 0.38231 0.37708 - 17.47121 14.96470 14.22842 13.56118 12.95478 12.40509 - 11.91164 11.47397 11.09189 10.76489 10.49194 10.27127 - 10.09870 9.96989 9.88071 9.81689 9.75301 9.63782 - 9.34783 9.03586 8.44466 7.51142 5.17682 3.74853 - 1.49317 1.05199 0.56255 0.47364 0.38773 0.37673 - 17.15134 14.96329 14.23543 13.57477 12.97426 12.43071 - 11.94332 11.51208 11.13665 10.81671 10.55178 10.34055 - 10.17964 10.06571 9.99583 9.95765 9.93017 9.87308 - 9.68090 9.43987 8.93732 8.08721 5.81286 4.32568 - 1.74202 1.21217 0.61489 0.50547 0.39410 0.37655 - 16.91866 14.96321 14.23999 13.58186 12.98326 12.44269 - 11.95946 11.53337 11.16392 10.85027 10.59105 10.38482 - 10.22983 10.12435 10.06624 10.04424 10.04081 10.02577 - 9.90166 9.70694 9.27518 8.51425 6.32771 4.78930 - 1.96115 1.35854 0.66420 0.53500 0.40226 0.37644 - 16.75748 14.96201 14.24279 13.58731 12.99096 12.45310 - 11.97253 11.54905 11.18189 10.87083 10.61542 10.41445 - 10.26541 10.16619 10.11563 10.10458 10.11787 10.12770 - 10.05309 9.90548 9.53772 8.83194 6.70622 5.19475 - 2.18732 1.49640 0.70959 0.56296 0.40841 0.37637 - 16.55492 14.96168 14.24716 13.59497 13.00181 12.46708 - 11.98988 11.56970 11.20615 10.89907 10.64832 10.45283 - 10.31030 10.21919 10.17935 10.18320 10.21856 10.26377 - 10.25402 10.16393 9.88979 9.29827 7.32251 5.83036 - 2.60990 1.74735 0.79484 0.61498 0.42323 0.37628 - 16.45445 14.97105 14.24906 13.59447 13.00229 12.47015 - 11.99645 11.58025 11.22086 10.91780 10.67078 10.47789 - 10.33533 10.24184 10.20260 10.22165 10.29403 10.37867 - 10.39369 10.32279 10.10226 9.61132 7.80631 6.31500 - 2.97253 1.97569 0.87379 0.66312 0.43775 0.37623 - 16.26060 14.97233 14.25444 13.60273 13.01303 12.48327 - 12.01213 11.59845 11.24195 10.94216 10.69875 10.51022 - 10.37309 10.28662 10.25668 10.28853 10.37979 10.49446 - 10.56737 10.55374 10.43951 10.10369 8.59019 7.20494 - 3.72598 2.49101 1.05135 0.77254 0.47249 0.37616 - 16.14975 14.97245 14.25687 13.60673 13.01841 12.49001 - 12.01998 11.60777 11.25262 10.95442 10.71274 10.52641 - 10.39213 10.30944 10.28451 10.32330 10.42461 10.55484 - 10.65779 10.67516 10.62195 10.38375 9.09287 7.81461 - 4.31570 2.96382 1.21023 0.87146 0.50484 0.37612 - 16.00595 14.96390 14.26019 13.61574 13.02943 12.50127 - 12.03088 11.61814 11.26334 10.96604 10.72537 10.54108 - 10.41301 10.34189 10.32914 10.36933 10.45658 10.58693 - 10.74341 10.81199 10.82501 10.67435 9.69479 8.66093 - 5.20177 3.69743 1.49062 1.05374 0.56369 0.37609 - 15.94319 14.96339 14.26095 13.61711 13.03131 12.50383 - 12.03413 11.62195 11.26741 10.97060 10.73150 10.54988 - 10.42430 10.35460 10.34290 10.38579 10.47946 10.62150 - 10.79291 10.87199 10.91702 10.84594 10.08063 9.12523 - 5.85797 4.30876 1.73925 1.20945 0.61677 0.37607 - 15.90444 14.96297 14.26084 13.61729 13.03192 12.50495 - 12.03585 11.62418 11.27029 10.97412 10.73577 10.55505 - 10.43051 10.36197 10.35179 10.39686 10.49374 10.64073 - 10.82293 10.91307 10.97645 10.94104 10.32441 9.47933 - 6.35774 4.78699 1.98792 1.35762 0.66552 0.37606 - 15.87795 14.96254 14.26031 13.61708 13.03210 12.50551 - 12.03689 11.62599 11.27307 10.97781 10.73957 10.55802 - 10.43318 10.36591 10.35816 10.40554 10.50361 10.65226 - 10.84312 10.94371 11.01992 10.99663 10.48022 9.77761 - 6.76362 5.16857 2.25819 1.50406 0.70941 0.37605 - 15.84130 14.96285 14.26178 13.61903 13.03436 12.50797 - 12.03935 11.62822 11.27509 10.97983 10.74256 10.56301 - 10.43985 10.37302 10.36516 10.41356 10.51545 10.67005 - 10.86874 10.97599 11.06944 11.09107 10.72594 10.10403 - 7.38065 5.84084 2.72719 1.81384 0.79550 0.37604 - 15.81983 14.96367 14.26352 13.62136 13.03696 12.51052 - 12.04175 11.63089 11.27818 10.98339 10.74576 10.56499 - 10.44110 10.37516 10.36938 10.41983 10.52291 10.67919 - 10.88382 10.99792 11.10433 11.14412 10.86324 10.36079 - 7.84988 6.33466 3.11474 2.11006 0.87088 0.37604 - 4.26209 4.34226 4.41027 4.46729 4.51304 4.54770 - 4.57218 4.58849 4.59941 4.60561 4.60749 4.60563 - 4.60172 4.59713 4.59151 4.58411 4.57483 4.56663 - 4.56299 4.56256 4.56080 4.55743 4.55264 4.55113 - 4.54979 4.54961 4.54947 4.54945 4.54945 4.54945 - 4.95553 5.04530 5.11651 5.17104 5.20869 5.23002 - 5.23676 5.23227 5.22104 5.20419 5.18227 5.15613 - 5.12758 5.09820 5.06762 5.03489 4.99978 4.96504 - 4.93437 4.92087 4.90743 4.89679 4.88715 4.88471 - 4.88262 4.88236 4.88218 4.88215 4.88212 4.88209 - 5.46371 5.55668 5.62538 5.67254 5.69824 5.70354 - 5.69108 5.66565 5.63339 5.59593 5.55400 5.50873 - 5.46200 5.41546 5.36858 5.31993 5.26878 5.21806 - 5.17186 5.15098 5.13059 5.11497 5.10088 5.09746 - 5.09463 5.09429 5.09402 5.09400 5.09398 5.09393 - 6.18460 6.29249 6.34969 6.36666 6.35310 6.32015 - 6.27194 6.21268 6.14758 6.07828 6.00579 5.93164 - 5.85697 5.78329 5.71101 5.64051 5.57202 5.50515 - 5.44113 5.41156 5.38334 5.36207 5.34099 5.33599 - 5.33202 5.33150 5.33112 5.33107 5.33102 5.33101 - 6.70978 6.78935 6.82696 6.82947 6.79838 6.73721 - 6.65204 6.55259 6.45034 6.34851 6.24805 6.15077 - 6.05770 5.96993 5.88636 5.80360 5.71946 5.63817 - 5.56571 5.53337 5.50116 5.47531 5.45011 5.44405 - 5.43920 5.43859 5.43809 5.43805 5.43800 5.43800 - 7.10958 7.17576 7.19340 7.17148 7.11238 7.02068 - 6.90399 6.77386 6.64370 6.51717 6.39526 6.27964 - 6.17074 6.06914 5.97353 5.87990 5.78572 5.69585 - 5.61711 5.58243 5.54762 5.51918 5.49107 5.48427 - 5.47881 5.47814 5.47757 5.47751 5.47746 5.47747 - 7.43353 7.48448 7.48136 7.43536 7.34959 7.22968 - 7.08454 6.92722 6.77271 6.62490 6.48479 6.35368 - 6.23149 6.11815 6.01220 5.90929 5.80667 5.70974 - 5.62603 5.58962 5.55288 5.52258 5.49255 5.48525 - 5.47937 5.47865 5.47805 5.47799 5.47793 5.47794 - 7.91340 7.98653 7.94719 7.82911 7.66352 7.48224 - 7.29437 7.10573 6.92288 6.74760 6.58078 6.42332 - 6.27504 6.13596 6.00642 5.88583 5.77368 5.66986 - 5.57648 5.53513 5.49522 5.46394 5.43137 5.42349 - 5.41722 5.41638 5.41578 5.41571 5.41565 5.41563 - 8.29422 8.33998 8.26091 8.09734 7.88467 7.65845 - 7.42926 7.20429 6.99119 6.79045 6.60095 6.42200 - 6.25448 6.09869 5.95465 5.82085 5.69637 5.58257 - 5.48200 5.43735 5.39469 5.36197 5.32858 5.32048 - 5.31404 5.31319 5.31257 5.31249 5.31242 5.31242 - 8.96772 8.94220 8.77153 8.51040 8.20190 7.88780 - 7.58052 7.28867 7.02088 6.77406 6.54341 6.32449 - 6.12076 5.93292 5.76025 5.59952 5.44905 5.31319 - 5.19493 5.14132 5.09137 5.05540 5.02164 5.01351 - 5.00710 5.00628 5.00568 5.00560 5.00552 5.00552 - 9.47579 9.28791 9.02360 8.71935 8.38331 8.02625 - 7.66189 7.30757 6.98095 6.68431 6.41771 6.17626 - 5.95597 5.75047 5.55875 5.37856 5.20847 5.05042 - 4.90957 4.84804 4.79175 4.75220 4.71811 4.71099 - 4.70444 4.70353 4.70298 4.70294 4.70287 4.70287 - 10.11111 9.77946 9.37740 8.95370 8.51590 8.07326 - 7.63783 7.22443 6.84544 6.50409 6.19820 5.92083 - 5.66677 5.42864 5.20440 4.99171 4.78922 4.59896 - 4.42641 4.34963 4.27966 4.23184 4.19564 4.18993 - 4.18354 4.18246 4.18193 4.18195 4.18177 4.18189 - 10.46095 10.14384 9.64942 9.08485 8.51364 7.98861 - 7.51454 7.08807 6.70281 6.35287 6.02856 5.72005 - 5.43207 5.16556 4.91652 4.68027 4.45441 4.24426 - 4.05038 3.95763 3.87446 3.82121 3.78256 3.77434 - 3.76828 3.76758 3.76704 3.76694 3.76692 3.76692 - 10.93772 10.29391 9.64156 9.03708 8.47547 7.95328 - 7.46781 7.01661 6.59715 6.20977 5.85490 5.52564 - 5.22047 4.93788 4.67427 4.42890 4.19875 3.97372 - 3.74810 3.64104 3.54884 3.49195 3.44717 3.44115 - 3.43342 3.43223 3.43186 3.43173 3.43194 3.43177 - 11.14863 10.43375 9.71637 9.05828 8.45224 7.89392 - 7.37940 6.90425 6.46660 6.06616 5.70130 5.36378 - 5.05004 4.75878 4.48520 4.22796 3.98365 3.74219 - 3.49842 3.38238 3.28302 3.22206 3.17258 3.16513 - 3.15696 3.15579 3.15533 3.15520 3.15533 3.15519 - 11.44320 10.61342 9.79368 9.05299 8.37984 7.76772 - 7.21076 6.70197 6.23866 5.82154 5.44391 5.09608 - 4.77135 4.46821 4.18146 3.90812 3.64431 3.38010 - 3.11098 2.98199 2.87123 2.80223 2.74326 2.73304 - 2.72352 2.72226 2.72161 2.72148 2.72150 2.72139 - 11.64424 10.72156 9.82262 9.01932 8.29676 7.64533 - 7.05734 6.52569 6.04581 5.61812 5.23299 4.87921 - 4.54802 4.23704 3.94249 3.65941 3.38370 3.10577 - 2.82143 2.68415 2.56466 2.48779 2.41985 2.40726 - 2.39606 2.39462 2.39378 2.39365 2.39359 2.39349 - 12.00346 10.84582 9.77776 8.85808 8.05892 7.35806 - 6.73743 6.18598 5.69469 5.25559 4.85826 4.49048 - 4.14181 3.80870 3.49436 3.19479 2.90744 2.62292 - 2.33440 2.19108 2.05437 1.95502 1.87209 1.85369 - 1.83910 1.83740 1.83600 1.83581 1.83568 1.83563 - 12.27045 10.91759 9.72338 8.72108 7.86782 7.13442 - 6.49600 5.93356 5.43556 4.98978 4.58435 4.20827 - 3.85133 3.50967 3.18858 2.88782 2.60179 2.31848 - 2.02778 1.88041 1.73525 1.62518 1.53137 1.50967 - 1.49216 1.49011 1.48842 1.48816 1.48805 1.48800 - 12.68484 11.04508 9.68654 8.57763 7.65123 6.87018 - 6.20863 5.63452 5.12513 4.66797 4.25096 3.86421 - 3.49864 3.15009 2.82232 2.52065 2.23725 1.95719 - 1.66944 1.52220 1.37405 1.25711 1.14919 1.12296 - 1.10186 1.09935 1.09725 1.09696 1.09678 1.09675 - 13.02954 11.16611 9.71424 8.55328 7.59440 6.78261 - 6.09658 5.50493 4.98052 4.50901 4.07846 3.67993 - 3.30789 2.95880 2.63189 2.32732 2.04111 1.76031 - 1.47655 1.33126 1.18391 1.06477 0.94716 0.91814 - 0.89492 0.89180 0.88955 0.88930 0.88902 0.88899 - 13.34388 11.31615 9.80083 8.59579 7.60869 6.77356 - 6.06748 5.46024 4.92309 4.43995 3.99914 3.59216 - 3.21351 2.85934 2.52780 2.21778 1.92837 1.64761 - 1.36507 1.22039 1.07218 0.95014 0.82565 0.79422 - 0.76918 0.76584 0.76341 0.76313 0.76284 0.76277 - 13.61299 11.50992 9.94532 8.67635 7.64079 6.78382 - 6.06965 5.45898 4.91616 4.42515 3.97699 3.56389 - 3.17805 2.81466 2.47359 2.15632 1.86353 1.58335 - 1.29965 1.15404 1.00353 0.87793 0.74748 0.71394 - 0.68712 0.68386 0.68112 0.68080 0.68046 0.68041 - 14.13019 11.82933 10.19479 8.86453 7.78625 6.90567 - 6.17209 5.54246 4.98146 4.47367 4.01030 3.58364 - 3.18592 2.81199 2.46063 2.13157 1.82429 1.53429 - 1.24430 1.09465 0.93758 0.80371 0.66052 0.62303 - 0.59298 0.58930 0.58622 0.58586 0.58548 0.58541 - 14.58958 12.12600 10.43502 9.06097 7.95545 7.05882 - 6.31285 5.67082 5.09727 4.57757 4.10321 3.66627 - 3.25879 2.87522 2.51356 2.17228 1.84975 1.54370 - 1.24283 1.08665 0.92081 0.77726 0.62024 0.57861 - 0.54521 0.54110 0.53766 0.53726 0.53685 0.53678 - 15.43142 12.71058 10.94304 9.51530 8.38966 7.46916 - 6.70045 6.03572 5.44045 4.90023 4.40645 3.95072 - 3.52426 3.12049 2.73617 2.36773 2.01165 1.66488 - 1.32474 1.14758 0.95452 0.78278 0.58955 0.53760 - 0.49597 0.49083 0.48652 0.48599 0.48554 0.48552 - 15.94618 13.10901 11.33489 9.90644 8.78628 7.85583 - 7.07104 6.38863 5.77734 5.22272 4.71556 4.24668 - 3.80626 3.38686 2.98463 2.59511 2.21329 1.83332 - 1.44849 1.24774 1.02384 0.82105 0.59191 0.53020 - 0.48019 0.47393 0.46887 0.46827 0.46762 0.46760 - 16.36102 13.58126 11.94264 10.60317 9.50059 8.54311 - 7.70880 6.97531 6.32743 5.75078 5.23197 4.75702 - 4.31013 3.87953 3.46032 3.04640 2.62817 2.18891 - 1.71131 1.45389 1.17685 0.92539 0.62549 0.53667 - 0.47070 0.46338 0.45672 0.45552 0.45490 0.45371 - 16.69250 13.85169 12.28525 11.02152 9.95769 9.02248 - 8.19752 7.46412 6.80953 6.22149 5.68841 5.19793 - 4.73591 4.29110 3.85745 3.42679 2.98560 2.50926 - 1.96851 1.66416 1.33033 1.02764 0.66321 0.55440 - 0.47014 0.46011 0.45156 0.45017 0.44868 0.44685 - 16.90080 14.01933 12.52823 11.32841 10.30136 9.38956 - 8.57801 7.85036 7.19567 6.60332 6.06311 5.56400 - 5.09311 4.63967 4.19683 3.75486 3.29727 2.79296 - 2.20261 1.86010 1.47382 1.12582 0.70283 0.57512 - 0.47181 0.45866 0.44788 0.44631 0.44416 0.44200 - 17.04214 14.12913 12.71121 11.56201 10.56868 9.67958 - 8.88281 8.16364 7.51262 6.92028 6.37753 5.87430 - 5.39869 4.94031 4.49170 4.04198 3.57226 3.04631 - 2.41604 2.04185 1.61125 1.21952 0.74263 0.59693 - 0.47459 0.45815 0.44489 0.44313 0.44052 0.43821 - 17.21770 14.26129 12.96813 11.89564 10.95900 10.11076 - 9.34330 8.64404 8.00557 7.42009 6.87995 6.37644 - 5.89890 5.43744 4.98387 4.52565 4.04041 3.48410 - 2.79413 2.37039 1.86712 1.39520 0.82069 0.64130 - 0.48206 0.45900 0.44029 0.43809 0.43502 0.43264 - 17.31862 14.33837 13.13776 12.12203 11.22957 10.41570 - 9.67477 8.99573 8.37247 7.79812 7.26594 6.76796 - 6.29424 5.83512 5.38198 4.92127 4.42820 3.85303 - 3.12161 2.66116 2.10121 1.55927 0.89573 0.68514 - 0.49095 0.46144 0.43691 0.43419 0.43106 0.42874 - 17.44360 14.44381 13.37628 12.45490 11.63676 10.88517 - 10.19647 9.56174 8.97615 8.43399 7.92941 7.45511 - 7.00152 6.55896 6.11839 5.66488 5.17017 4.57572 - 3.78640 3.26747 2.60913 1.93714 1.07014 0.78980 - 0.51575 0.47105 0.43155 0.42726 0.42487 0.42283 - 17.50456 14.49379 13.49713 12.63223 11.85965 11.14923 - 10.49779 9.89746 9.34387 8.83170 8.35530 7.90737 - 7.47788 7.05674 6.63482 6.19663 5.71225 5.11825 - 4.30566 3.75492 3.03499 2.27022 1.22875 0.88734 - 0.54147 0.48295 0.42901 0.42295 0.42129 0.41952 - 17.56940 14.53258 13.61415 12.81169 12.09219 11.43267 - 10.82994 10.27755 9.77142 9.30653 8.87719 8.47574 - 8.09096 7.71182 7.32925 6.92756 6.47548 5.90474 - 5.08934 4.51180 3.72339 2.83588 1.51092 1.06528 - 0.59200 0.50892 0.42862 0.41882 0.41731 0.41591 - 17.60300 14.55579 13.67887 12.90796 12.21584 11.58328 - 11.00734 10.48248 10.00500 9.57043 9.17349 8.80687 - 8.45964 8.12078 7.78123 7.42448 7.01617 6.47842 - 5.67068 5.08186 4.26284 3.30580 1.76962 1.22563 - 0.64011 0.53467 0.43147 0.41906 0.41466 0.41397 - 17.59377 14.55737 13.70975 12.96152 12.28938 11.67684 - 11.12097 10.61689 10.16121 9.74976 9.37763 9.03778 - 8.71937 8.41155 8.10547 7.78448 7.41279 6.90707 - 6.11884 5.53273 4.70636 3.70982 2.01104 1.37235 - 0.68595 0.56106 0.43595 0.41949 0.41359 0.41276 - 17.53743 14.54482 13.73109 13.00637 12.35085 11.75132 - 11.20652 10.71352 10.27088 9.87528 9.52225 9.20537 - 8.91444 8.63790 8.36306 8.06519 7.70610 7.22216 - 6.47955 5.91574 5.08997 4.05774 2.23158 1.51123 - 0.72996 0.58714 0.44127 0.42047 0.41304 0.41194 - 17.52083 14.56054 13.75955 13.04814 12.40840 11.82860 - 11.30618 10.83724 10.41913 10.04856 9.72154 9.43200 - 9.17009 8.92604 8.69240 8.45369 8.17333 7.76017 - 7.05270 6.49805 5.68641 4.64055 2.63286 1.77341 - 0.81197 0.63551 0.45288 0.42546 0.41211 0.41090 - 17.47704 14.56531 13.78247 13.08507 12.45736 11.88948 - 11.37894 10.92239 10.51753 10.16151 9.85089 9.58029 - 9.34070 9.12331 8.92184 8.72207 8.48852 8.12900 - 7.47836 6.95087 6.15979 5.10778 2.98213 2.01750 - 0.88870 0.68164 0.46515 0.43114 0.41172 0.41026 - 17.36443 14.56852 13.82172 13.15024 12.54270 11.99177 - 11.49616 11.05407 10.66440 10.32564 10.03592 9.79219 - 9.58873 9.41886 9.27450 9.13550 8.96687 8.70131 - 8.19417 7.74526 7.00827 5.96999 3.71128 2.54952 - 1.06247 0.78834 0.49594 0.44696 0.41190 0.40939 - 17.22977 14.57844 13.84879 13.18787 12.58779 12.04377 - 11.55544 11.12169 10.74225 10.41535 10.13844 9.90865 - 9.72230 9.57486 9.46007 9.36030 9.24523 9.05681 - 8.65060 8.25634 7.58171 6.59252 4.28348 2.99264 - 1.21880 0.88614 0.52546 0.46362 0.41302 0.40896 - 16.89076 14.58110 13.86833 13.22118 12.63255 12.09868 - 11.61910 11.19376 10.82275 10.50561 10.24154 10.02885 - 9.86374 9.74224 9.66055 9.60504 9.55177 9.45334 - 9.19190 8.90024 8.33358 7.42448 5.13077 3.72405 - 1.49917 1.06139 0.58039 0.49529 0.41722 0.40851 - 16.60597 14.58328 13.87655 13.23337 12.64812 12.11889 - 11.64499 11.22658 10.86356 10.55489 10.29891 10.09400 - 9.93814 9.82923 9.76470 9.73276 9.71424 9.67439 - 9.50614 9.27745 8.80181 7.99620 5.77328 4.28154 - 1.74232 1.21969 0.63152 0.52544 0.42358 0.40829 - 16.39880 14.58272 13.87989 13.23975 12.65745 12.13167 - 11.66172 11.24744 10.88841 10.58384 10.33247 10.13298 - 9.98380 9.88341 9.82999 9.81294 9.81594 9.81173 - 9.70966 9.53440 9.13074 8.40091 6.26275 4.74946 - 1.96444 1.36480 0.67900 0.55379 0.42991 0.40816 - 16.25511 14.58242 13.88275 13.24461 12.66425 12.14089 - 11.67351 11.26155 10.90467 10.60240 10.35454 10.16013 - 10.01649 9.92162 9.87483 9.86784 9.88680 9.90545 - 9.84896 9.71929 9.38068 8.70936 6.63321 5.14727 - 2.18935 1.50237 0.72324 0.58054 0.43502 0.40807 - 16.07483 14.58002 13.88414 13.25081 12.67532 12.15573 - 11.69131 11.28179 10.92713 10.62751 10.38306 10.19331 - 10.05601 9.96973 9.93410 9.94110 9.97886 10.02901 - 10.03466 9.96055 9.71106 9.15413 7.24501 5.76865 - 2.60499 1.75320 0.80654 0.63135 0.44804 0.40796 - 15.95820 14.58267 13.88974 13.25649 12.68060 12.16172 - 11.69901 11.29183 10.94024 10.64394 10.40301 10.21668 - 10.08269 9.99989 9.96899 9.98414 10.03596 10.10797 - 10.14987 10.10983 9.92771 9.46362 7.69046 6.26136 - 2.96684 1.97684 0.88444 0.67796 0.46170 0.40789 - 15.80894 14.59168 13.89267 13.25788 12.68362 12.16772 - 11.70885 11.30610 10.95896 10.66716 10.43029 10.24709 - 10.11406 10.03051 10.00249 10.03535 10.12708 10.24297 - 10.32176 10.31679 10.22204 9.91850 8.47623 7.12727 - 3.70516 2.48925 1.06020 0.78523 0.49399 0.40780 - 15.70893 14.59156 13.89463 13.26143 12.68840 12.17370 - 11.71599 11.31443 10.96857 10.67822 10.44296 10.26172 - 10.13127 10.05114 10.02775 10.06698 10.16787 10.29794 - 10.40410 10.42759 10.38956 10.17935 8.96168 7.72370 - 4.28587 2.95341 1.21770 0.88274 0.52471 0.40775 - 15.57771 14.58329 13.89788 13.27009 12.69892 12.18431 - 11.72589 11.32372 10.97806 10.68850 10.45421 10.27486 - 10.15034 10.08128 10.06938 10.10937 10.19564 10.32490 - 10.48187 10.55325 10.57515 10.44526 9.53687 8.54761 - 5.15732 3.67319 1.49616 1.06347 0.58120 0.40771 - 15.52124 14.58313 13.89870 13.27139 12.70059 12.18652 - 11.72875 11.32713 10.98169 10.69253 10.45965 10.28282 - 10.16062 10.09282 10.08176 10.12410 10.21633 10.35631 - 10.52695 10.60772 10.65829 10.60204 9.90161 8.99389 - 5.80198 4.27513 1.74362 1.21748 0.63270 0.40768 - 15.48620 14.58273 13.89877 13.27162 12.70103 12.18747 - 11.73029 11.32926 10.98436 10.69572 10.46346 10.28736 - 10.16607 10.09943 10.08981 10.13418 10.22932 10.37374 - 10.55425 10.64517 10.71206 10.68758 10.12948 9.33430 - 6.29271 4.74563 1.99201 1.36469 0.68014 0.40767 - 15.46236 14.58242 13.89833 13.27138 12.70117 12.18797 - 11.73126 11.33089 10.98694 10.69919 10.46694 10.28997 - 10.16832 10.10290 10.09561 10.14213 10.23824 10.38426 - 10.57290 10.67313 10.75097 10.73679 10.27471 9.61900 - 6.69106 5.12090 2.25583 1.51041 0.72293 0.40766 - 15.42929 14.58256 13.89959 13.27318 12.70337 12.19036 - 11.73362 11.33312 10.98882 10.70097 10.46956 10.29445 - 10.17437 10.10933 10.10187 10.14933 10.24897 10.40031 - 10.59571 10.70214 10.79654 10.82377 10.50001 9.92586 - 7.29557 5.78270 2.71518 1.81837 0.80765 0.40765 - 15.41037 14.58290 13.90072 13.27509 12.70584 12.19298 - 11.73618 11.33563 10.99174 10.70433 10.47259 10.29629 - 10.17550 10.11117 10.10558 10.15485 10.25550 10.40836 - 10.60922 10.72213 10.82892 10.87309 10.62443 10.16249 - 7.75463 6.26984 3.09626 2.10859 0.88233 0.40765 - 4.03792 4.11472 4.18063 4.23669 4.28266 4.31871 - 4.34572 4.36556 4.38088 4.39233 4.40034 4.40549 - 4.40945 4.41349 4.41704 4.41875 4.41782 4.41667 - 4.41817 4.41967 4.42026 4.41924 4.41649 4.41548 - 4.41459 4.41447 4.41437 4.41437 4.41436 4.41437 - 4.73328 4.82112 4.88853 4.93853 4.97312 4.99498 - 5.00564 5.00739 5.00335 4.99451 4.98172 4.96564 - 4.94694 4.92633 4.90404 4.88075 4.85718 4.83375 - 4.81138 4.80108 4.79138 4.78402 4.77561 4.77327 - 4.77151 4.77129 4.77113 4.77110 4.77109 4.77106 - 5.24409 5.33239 5.39864 5.44532 5.47247 5.48113 - 5.47373 5.45474 5.42990 5.40074 5.36793 5.33249 - 5.29613 5.26027 5.22433 5.18662 5.14618 5.10570 - 5.06893 5.05237 5.03611 5.02331 5.01067 5.00757 - 5.00503 5.00472 5.00447 5.00445 5.00441 5.00438 - 5.97062 6.07699 6.13578 6.15668 6.14902 6.12354 - 6.08402 6.03426 5.97894 5.91964 5.85736 5.79361 - 5.72959 5.66677 5.60544 5.54569 5.48750 5.43035 - 5.37525 5.34969 5.32508 5.30624 5.28732 5.28282 - 5.27923 5.27875 5.27840 5.27835 5.27832 5.27830 - 6.50175 6.58410 6.62739 6.63752 6.61574 6.56525 - 6.49174 6.40433 6.31395 6.22365 6.13440 6.04799 - 5.96556 5.88831 5.81513 5.74260 5.66835 5.59622 - 5.53154 5.50241 5.47310 5.44938 5.42663 5.42115 - 5.41671 5.41617 5.41572 5.41567 5.41565 5.41562 - 6.90730 6.97974 7.00665 6.99576 6.94905 6.87076 - 6.76799 6.65172 6.53480 6.42076 6.31063 6.20614 - 6.10796 6.01684 5.93144 5.84776 5.76303 5.68164 - 5.60974 5.57769 5.54519 5.51856 5.49290 5.48669 - 5.48167 5.48105 5.48053 5.48046 5.48044 5.48043 - 7.23667 7.29685 7.30604 7.27382 7.20292 7.09851 - 6.96899 6.82686 6.68658 6.55198 6.42410 6.30439 - 6.19302 6.09024 5.99452 5.90140 5.80792 5.71900 - 5.64146 5.60729 5.57247 5.54369 5.51592 5.50918 - 5.50368 5.50302 5.50245 5.50238 5.50235 5.50235 - 7.72944 7.81050 7.78734 7.68940 7.54476 7.38249 - 7.21155 7.03840 6.87025 6.70901 6.55540 6.41030 - 6.27366 6.14564 6.02652 5.91563 5.81228 5.71611 - 5.62846 5.58894 5.55054 5.52042 5.48936 5.48179 - 5.47577 5.47499 5.47441 5.47432 5.47425 5.47425 - 8.11796 8.17604 8.11639 7.97494 7.78459 7.57887 - 7.36817 7.15997 6.96235 6.77611 6.60029 6.43434 - 6.27904 6.13473 6.00141 5.87758 5.76215 5.65602 - 5.56119 5.51856 5.47746 5.44558 5.41284 5.40484 - 5.39845 5.39761 5.39701 5.39693 5.39685 5.39683 - 8.80418 8.79901 8.65286 8.41600 8.13071 7.83838 - 7.55125 7.27769 7.02622 6.79433 6.57783 6.37274 - 6.18212 6.00659 5.84546 5.69559 5.55516 5.42789 - 5.31669 5.26630 5.21863 5.18323 5.14861 5.14015 - 5.13345 5.13259 5.13194 5.13184 5.13178 5.13176 - 9.54654 9.21622 8.87164 8.53849 8.21640 7.90516 - 7.60468 7.31498 7.03616 6.76842 6.51444 6.27360 - 6.04800 5.83687 5.64167 5.46418 5.30573 5.16426 - 5.04310 4.99673 4.96555 4.94637 4.87446 4.83942 - 4.84951 4.85589 4.85317 4.85121 4.85481 4.85246 - 9.96043 9.65659 9.28540 8.88912 8.47549 8.05408 - 7.63731 7.24055 6.87705 6.55017 6.25785 5.99356 - 5.75214 5.52652 5.31479 5.11461 4.92459 4.74678 - 4.58651 4.51555 4.45046 4.40503 4.36806 4.36122 - 4.35439 4.35334 4.35275 4.35273 4.35262 4.35270 - 10.31635 10.02533 9.56322 9.02753 8.48096 7.97626 - 7.51930 7.10785 6.73689 6.40055 6.08885 5.79233 - 5.51610 5.26152 5.02482 4.80102 4.58759 4.39035 - 4.21092 4.12588 4.04900 3.99870 3.96029 3.95180 - 3.94542 3.94466 3.94406 3.94397 3.94396 3.94396 - 10.79935 10.18177 9.56055 8.98290 8.44463 7.94288 - 7.47535 7.03994 6.63452 6.25951 5.91552 5.59649 - 5.30127 5.02875 4.77590 4.54226 4.32513 4.11443 - 3.90423 3.80499 3.71976 3.66728 3.62453 3.61798 - 3.61042 3.60932 3.60888 3.60873 3.60894 3.60879 - 11.01715 10.32755 9.64105 9.00912 8.42558 7.88670 - 7.38906 6.92872 6.50406 6.11491 5.75992 5.43167 - 5.12705 4.84497 4.58129 4.33498 4.10296 3.87539 - 3.64714 3.53933 3.44784 3.39249 3.34633 3.33864 - 3.33095 3.32992 3.32942 3.32929 3.32942 3.32928 - 11.32410 10.51739 9.72793 9.01202 8.35970 7.76525 - 7.22335 6.72763 6.27562 5.86797 5.49850 5.15835 - 4.84124 4.54574 4.26723 4.00315 3.75001 3.49833 - 3.24406 3.12348 3.02159 2.95991 2.90636 2.89645 - 2.88794 2.88691 2.88628 2.88615 2.88617 2.88605 - 11.53357 10.63247 9.76339 8.98383 8.28086 7.64579 - 7.07159 6.55171 6.08183 5.66224 5.28397 4.93664 - 4.61191 4.30738 4.01969 3.74444 3.47793 3.21110 - 2.94046 2.81132 2.70098 2.63229 2.57118 2.55942 - 2.54961 2.54843 2.54767 2.54753 2.54748 2.54738 - 11.89099 10.76212 9.72827 8.83268 8.05104 7.36330 - 6.75295 6.20979 5.72544 5.29224 4.90025 4.53782 - 4.19461 3.86687 3.55757 3.26315 2.98154 2.70453 - 2.42675 2.29050 2.16242 2.07132 1.99664 1.98036 - 1.96756 1.96609 1.96487 1.96470 1.96458 1.96454 - 12.15003 10.83049 9.67345 8.69601 7.86029 7.13951 - 6.51046 5.95537 5.46312 5.02211 4.62101 4.24925 - 3.89674 3.55948 3.24230 2.94521 2.66326 2.38538 - 2.10271 1.96092 1.82315 1.72082 1.63595 1.61670 - 1.60120 1.59940 1.59792 1.59769 1.59759 1.59756 - 12.54731 10.94956 9.63201 8.54914 7.64085 6.87245 - 6.21934 5.65128 5.14655 4.69317 4.27962 3.89628 - 3.53420 3.18909 2.86441 2.56511 2.28402 2.00695 - 1.72376 1.58014 1.43767 1.32749 1.22867 1.20510 - 1.18615 1.18391 1.18204 1.18177 1.18162 1.18161 - 12.88683 11.06951 9.65777 8.52101 7.57893 6.77957 - 6.10206 5.51645 4.99667 4.52893 4.10164 3.70617 - 3.33704 2.99078 2.66645 2.36403 2.07949 1.80053 - 1.51955 1.37689 1.23413 1.12092 1.01222 0.98594 - 0.96490 0.96206 0.96003 0.95982 0.95955 0.95953 - 13.20728 11.22247 9.74296 8.56008 7.58881 6.76588 - 6.06849 5.46740 4.93488 4.45543 4.01778 3.61362 - 3.23762 2.88603 2.55696 2.24912 1.96128 1.68187 - 1.40117 1.25841 1.11405 0.99738 0.88157 0.85291 - 0.83007 0.82701 0.82480 0.82455 0.82427 0.82420 - 13.48108 11.41681 9.88434 8.63705 7.61748 6.77249 - 6.06690 5.46231 4.92411 4.43682 3.99182 3.58153 - 3.19824 2.83724 2.49850 2.18355 1.89270 1.61369 - 1.33118 1.18701 1.03985 0.91926 0.79739 0.76654 - 0.74189 0.73891 0.73640 0.73610 0.73580 0.73572 - 13.97322 11.72336 10.12378 8.81777 7.75682 6.88810 - 6.16286 5.53933 4.98307 4.47919 4.01917 3.59543 - 3.20029 2.82868 2.47963 2.15312 1.84834 1.55961 - 1.27035 1.12179 0.96762 0.83834 0.70337 0.66848 - 0.64052 0.63711 0.63426 0.63393 0.63358 0.63350 - 14.37861 11.99247 10.34855 9.00619 7.92142 7.03735 - 6.29927 5.66270 5.09365 4.57789 4.10711 3.67342 - 3.26880 2.88776 2.52858 2.19008 1.87041 1.56601 - 1.26578 1.11066 0.94766 0.80857 0.65947 0.62032 - 0.58894 0.58509 0.58187 0.58149 0.58111 0.58106 - 15.12229 12.52537 10.82573 9.44268 8.34286 7.43715 - 6.67670 6.01720 5.42650 4.89068 4.40116 3.94946 - 3.52660 3.12604 2.74476 2.37950 2.02670 1.68239 - 1.34339 1.16734 0.97716 0.80984 0.62443 0.57492 - 0.53528 0.53040 0.52629 0.52579 0.52536 0.52536 - 15.61939 12.91248 11.20426 9.81994 8.72511 7.81070 - 7.03598 6.36062 5.75529 5.20607 4.70389 4.23958 - 3.80330 3.38761 2.98889 2.60286 2.22447 1.84731 - 1.46435 1.26467 1.04358 0.84526 0.62442 0.56530 - 0.51745 0.51150 0.50667 0.50609 0.50547 0.50539 - 16.08197 13.41191 11.81380 10.50196 9.41717 8.47404 - 7.65163 6.92849 6.28979 5.72140 5.21002 4.74169 - 4.30043 3.87443 3.45895 3.04813 2.63263 2.19627 - 1.72219 1.46696 1.19297 0.94587 0.65409 0.56834 - 0.50539 0.49864 0.49244 0.49127 0.49058 0.48919 - 16.45905 13.71848 12.17263 10.92060 9.86495 8.93827 - 8.12235 7.39867 6.75432 6.17683 5.65425 5.17368 - 4.72011 4.28179 3.85287 3.42550 2.98664 2.51247 - 1.97500 1.67322 1.34299 1.04497 0.68907 0.58338 - 0.50280 0.49367 0.48607 0.48473 0.48304 0.48096 - 16.69810 13.91187 12.42638 11.22659 10.20047 9.29279 - 8.48801 7.76951 7.12584 6.54579 6.01845 5.53184 - 5.07168 4.62634 4.18916 3.75076 3.29522 2.79262 - 2.20528 1.86562 1.48377 1.14069 0.72643 0.60187 - 0.50279 0.49087 0.48160 0.48013 0.47763 0.47525 - 16.85800 14.03890 12.61504 11.45803 10.46037 9.57217 - 8.78050 8.07005 7.43060 6.85187 6.32380 5.83507 - 5.37199 4.92300 4.48087 4.03506 3.56731 3.04276 - 2.41539 2.04425 1.61872 1.23240 0.76432 0.62179 - 0.50414 0.48925 0.47805 0.47646 0.47335 0.47090 - 17.04825 14.18855 12.87517 11.78532 10.83783 9.98647 - 9.22191 8.53077 7.90456 7.33439 6.81131 6.32500 - 5.86250 5.41238 4.96664 4.51306 4.02997 3.47492 - 2.78784 2.36751 1.87028 1.40497 0.83924 0.66308 - 0.50935 0.48835 0.47269 0.47080 0.46699 0.46464 - 17.14667 14.26934 13.04129 12.00412 11.09781 10.27874 - 9.53957 8.86831 8.25760 7.69940 7.18553 6.70627 - 6.24910 5.80263 5.35835 4.90302 4.41254 3.83890 - 3.11065 2.65390 2.10069 1.56650 0.91182 0.70454 - 0.51650 0.48944 0.46878 0.46650 0.46249 0.46034 - 17.23248 14.35495 13.25967 12.31695 11.48477 10.72778 - 10.04053 9.41332 8.84019 8.31429 7.82846 7.37364 - 6.93771 6.50919 6.07907 5.63265 5.14226 4.55091 - 3.76620 3.25173 2.60131 1.93872 1.08201 0.80518 - 0.53827 0.49666 0.46248 0.45896 0.45559 0.45389 - 17.24527 14.37582 13.35830 12.47694 11.69400 10.98023 - 10.33121 9.73849 9.19677 8.69986 8.24099 7.81145 - 7.39903 6.99205 6.58134 6.15162 5.67338 5.08450 - 4.27833 3.73286 3.02165 2.26730 1.23796 0.90015 - 0.56196 0.50692 0.45922 0.45421 0.45171 0.45030 - 17.23317 14.36690 13.44117 12.63267 11.91035 11.25200 - 10.65392 10.10933 9.61367 9.16146 8.74644 8.36009 - 7.98992 7.62392 7.25303 6.86162 6.41870 5.85666 - 5.05115 4.48037 3.70189 2.82596 1.51686 1.07486 - 0.60981 0.53067 0.45766 0.44932 0.44749 0.44642 - 17.21814 14.35991 13.48560 12.71644 12.02682 11.39857 - 10.82860 10.31120 9.84254 9.41802 9.03218 8.67749 - 8.34253 8.01600 7.68882 7.34441 6.94800 6.42066 - 5.62246 5.04059 4.23379 3.29154 1.77378 1.23344 - 0.65580 0.55461 0.45952 0.44900 0.44492 0.44434 - 17.18088 14.34333 13.50403 12.76236 12.09609 11.49001 - 10.94100 10.44428 9.99644 9.59338 9.23019 8.89988 - 8.59163 8.29463 8.00015 7.69161 7.33298 6.83999 - 6.06434 5.48631 4.67216 3.69022 2.01240 1.37907 - 0.70031 0.57974 0.46310 0.44882 0.44379 0.44306 - 17.14262 14.33265 13.51707 12.79410 12.14402 11.55335 - 11.01940 10.53763 10.10511 9.71814 9.37228 9.06100 - 8.77403 8.50112 8.23400 7.95646 7.63195 7.17273 - 6.42455 5.85557 5.04242 4.03543 2.23263 1.51692 - 0.74300 0.60432 0.46758 0.44968 0.44307 0.44219 - 17.07797 14.32439 13.53886 12.83993 12.21043 11.63978 - 11.12527 10.66341 10.25152 9.88657 9.56484 9.28064 - 9.02472 8.78788 8.56307 8.33522 8.06822 7.67111 - 6.98261 6.43893 5.64005 4.60847 2.62702 1.77696 - 0.82367 0.65158 0.47789 0.45316 0.44221 0.44108 - 17.01453 14.31827 13.55862 12.87898 12.26446 11.70656 - 11.20306 10.75141 10.34989 9.99639 9.68843 9.42209 - 9.19067 8.98603 8.79783 8.60297 8.36303 8.00795 - 7.39340 6.88889 6.10823 5.06616 2.97914 2.01555 - 0.89897 0.69662 0.48896 0.45802 0.44168 0.44041 - 16.93564 14.33647 13.60379 12.94373 12.34538 11.80270 - 11.31391 10.87774 10.49317 10.15885 9.87297 9.63257 - 9.43215 9.26531 9.12457 8.99087 8.83089 8.57975 - 8.09567 7.66157 6.94054 5.91836 3.69208 2.54442 - 1.07113 0.80092 0.51747 0.47190 0.44159 0.43949 - 16.82162 14.35021 13.63224 12.98243 12.39237 11.85705 - 11.37547 10.94690 10.57095 10.24669 9.97267 9.74656 - 9.56358 9.41851 9.30568 9.20875 9.09888 8.91886 - 8.53583 8.16342 7.50436 6.52252 4.25183 2.98916 - 1.22667 0.89652 0.54529 0.48677 0.44246 0.43903 - 16.51961 14.35916 13.65575 13.01694 12.43607 11.90964 - 11.43682 11.01751 10.65176 10.33890 10.07809 9.86771 - 9.70409 9.58337 9.50191 9.44646 9.39434 9.30167 - 9.05673 8.77979 8.23400 7.34793 5.09198 3.70359 - 1.50484 1.07051 0.59785 0.51647 0.44568 0.43856 - 16.26001 14.36127 13.66433 13.02985 12.45271 11.93080 - 11.46345 11.05073 10.69278 10.38817 10.13538 9.93274 - 9.77831 9.66998 9.60527 9.57255 9.55344 9.51540 - 9.35747 9.14123 8.68653 7.90703 5.72627 4.25359 - 1.74637 1.22732 0.64737 0.54492 0.45140 0.43833 - 16.06987 14.35828 13.66601 13.03652 12.46420 11.94662 - 11.48313 11.07346 10.71774 10.41557 10.16674 9.97046 - 9.82403 9.72499 9.67160 9.65344 9.65432 9.64641 - 9.55008 9.39084 9.01041 8.29665 6.18803 4.72080 - 1.97465 1.37319 0.69270 0.57209 0.45531 0.43819 - 15.93907 14.35747 13.66807 13.04110 12.47106 11.95593 - 11.49494 11.08793 10.73486 10.43556 10.18998 9.99753 - 9.85569 9.76244 9.71653 9.70861 9.72430 9.74011 - 9.68694 9.56495 9.24303 8.59930 6.57630 5.10456 - 2.19113 1.50895 0.73641 0.59804 0.46091 0.43809 - 15.77270 14.35691 13.67179 13.04794 12.48090 11.96890 - 11.51094 11.10704 10.75734 10.46170 10.22029 10.03283 - 9.89694 9.81111 9.77499 9.78068 9.81631 9.86337 - 9.86705 9.79641 9.56103 9.03073 7.17380 5.72078 - 2.60144 1.75788 0.81849 0.64702 0.47274 0.43797 - 15.66593 14.35962 13.67748 13.05370 12.48616 11.97483 - 11.51893 11.11774 10.77097 10.47863 10.24058 10.05654 - 9.92395 9.84165 9.81032 9.82400 9.87335 9.94216 - 9.98080 9.94133 9.76882 9.32807 7.61059 6.20736 - 2.95898 1.98032 0.89520 0.69252 0.48527 0.43790 - 15.50783 14.35974 13.68113 13.06068 12.49622 11.98711 - 11.53300 11.13391 10.79025 10.50165 10.26735 10.08683 - 9.95876 9.88293 9.86051 9.88566 9.95096 10.04753 - 10.14315 10.15505 10.06539 9.75527 8.36638 7.09126 - 3.68409 2.47633 1.06886 0.79948 0.51637 0.43781 - 15.41746 14.36025 13.68364 13.06449 12.50117 11.99316 - 11.54015 11.14228 10.79995 10.51295 10.28054 10.10209 - 9.97666 9.90416 9.88627 9.91759 9.99194 10.10331 - 10.22760 10.26694 10.22752 9.99955 8.83429 7.68404 - 4.25695 2.92891 1.22476 0.89688 0.54511 0.43776 - 15.32119 14.36089 13.68595 13.06761 12.50505 11.99825 - 11.54674 11.15059 10.80996 10.52456 10.29355 10.11653 - 9.99345 9.92492 9.91262 9.95122 10.03504 10.16101 - 10.31371 10.38165 10.39851 10.26811 9.39884 8.44730 - 5.11980 3.65333 1.50168 1.07316 0.59847 0.43771 - 15.26999 14.36089 13.68690 13.06902 12.50685 12.00051 - 11.54966 11.15407 10.81372 10.52874 10.29917 10.12473 - 10.00403 9.93684 9.92546 9.96654 10.05642 10.19276 - 10.35895 10.43713 10.48350 10.42407 9.74824 8.87698 - 5.75462 4.24758 1.74796 1.22553 0.64843 0.43769 - 15.23844 14.36043 13.68659 13.06907 12.50731 12.00158 - 11.55122 11.15622 10.81637 10.53193 10.30301 10.12943 - 10.00975 9.94375 9.93380 9.97691 10.06981 10.21093 - 10.38670 10.47456 10.53887 10.51259 9.96746 9.20463 - 6.23749 4.71168 1.99745 1.37175 0.69468 0.43768 - 15.21694 14.35995 13.68595 13.06875 12.50746 12.00210 - 11.55222 11.15778 10.81895 10.53540 10.30653 10.13208 - 10.01207 9.94737 9.93982 9.98514 10.07905 10.22160 - 10.40568 10.50350 10.57909 10.56262 10.10820 9.47994 - 6.62876 5.08100 2.25544 1.51684 0.73649 0.43767 - 15.18671 14.36012 13.68733 13.07066 12.50968 12.00440 - 11.55460 11.15995 10.82074 10.53717 10.30923 10.13672 - 10.01832 9.95399 9.94626 9.99255 10.09021 10.23861 - 10.42917 10.53227 10.62487 10.65050 10.32529 9.77325 - 7.22295 5.73408 2.70555 1.82289 0.81977 0.43766 - 15.16895 14.36128 13.68947 13.07318 12.51216 12.00683 - 11.55677 11.16226 10.82365 10.54060 10.31235 10.13863 - 10.01949 9.95594 9.95017 9.99828 10.09681 10.24670 - 10.44375 10.55376 10.65497 10.69184 10.44400 10.00358 - 7.67357 6.21412 3.07993 2.10679 0.89334 0.43765 - 3.83244 3.90573 3.96927 4.02404 4.06981 4.10680 - 4.13577 4.15852 4.17748 4.19332 4.20651 4.21772 - 4.22865 4.24053 4.25260 4.26283 4.26972 4.27538 - 4.28215 4.28549 4.28757 4.28775 4.28751 4.28727 - 4.28696 4.28691 4.28688 4.28687 4.28688 4.28689 - 4.52590 4.60123 4.66291 4.71252 4.74990 4.77539 - 4.79017 4.79661 4.79790 4.79490 4.78819 4.77857 - 4.76791 4.75765 4.74725 4.73521 4.72052 4.70524 - 4.69197 4.68617 4.68013 4.67476 4.66854 4.66695 - 4.66564 4.66546 4.66533 4.66534 4.66532 4.66526 - 5.03736 5.11742 5.17862 5.22325 5.25130 5.26355 - 5.26199 5.25029 5.23318 5.21199 5.18738 5.16037 - 5.13275 5.10604 5.07973 5.05226 5.02261 4.99292 - 4.96607 4.95393 4.94168 4.93160 4.92117 4.91861 - 4.91654 4.91628 4.91607 4.91605 4.91604 4.91598 - 5.76964 5.87223 5.93057 5.95371 5.95059 5.93142 - 5.89948 5.85782 5.81041 5.75903 5.70550 5.65152 - 5.59744 5.54403 5.49175 5.44132 5.39324 5.34696 - 5.30203 5.28031 5.25922 5.24309 5.22668 5.22259 - 5.21942 5.21902 5.21873 5.21868 5.21866 5.21863 - 6.29725 6.40594 6.45590 6.45989 6.43070 6.38270 - 6.32077 6.24929 6.17371 6.09621 6.01863 5.94281 - 5.86864 5.79671 5.72757 5.66188 5.60004 5.54130 - 5.48481 5.45752 5.43091 5.41048 5.38992 5.38481 - 5.38082 5.38031 5.37995 5.37990 5.37988 5.37986 - 6.70633 6.81560 6.85375 6.83712 6.78211 6.70684 - 6.61754 6.51962 6.41959 6.31986 6.22221 6.12842 - 6.03801 5.95134 5.86897 5.79135 5.71875 5.65043 - 5.58548 5.55429 5.52382 5.50037 5.47672 5.47085 - 5.46625 5.46566 5.46523 5.46516 5.46513 5.46514 - 7.03891 7.14471 7.16870 7.13072 7.05058 6.94978 - 6.83562 6.71425 6.59286 6.47395 6.35919 6.25010 - 6.14604 6.04708 5.95374 5.86624 5.78466 5.70846 - 5.63685 5.60269 5.56937 5.54368 5.51767 5.51117 - 5.50609 5.50544 5.50498 5.50492 5.50489 5.50488 - 7.55667 7.64831 7.64096 7.56080 7.43312 7.28488 - 7.12562 6.96336 6.80704 6.65833 6.51685 6.38264 - 6.25572 6.13640 6.02516 5.92180 5.82596 5.73685 - 5.65451 5.61648 5.57937 5.55040 5.52085 5.51365 - 5.50789 5.50713 5.50657 5.50651 5.50644 5.50644 - 7.95250 8.02296 7.98086 7.85880 7.68748 7.49862 - 7.30275 7.10810 6.92351 6.74997 6.58631 6.43183 - 6.28697 6.15194 6.02687 5.91062 5.80234 5.70252 - 5.61225 5.57098 5.53094 5.49984 5.46807 5.46030 - 5.45407 5.45326 5.45266 5.45259 5.45252 5.45251 - 8.65129 8.66021 8.53310 8.31707 8.05343 7.78275 - 7.51624 7.26103 7.02450 6.80514 6.60049 6.40767 - 6.22884 6.06410 5.91267 5.77122 5.63782 5.51615 - 5.40942 5.36088 5.31449 5.27943 5.24468 5.23616 - 5.22940 5.22850 5.22786 5.22776 5.22770 5.22768 - 9.39216 9.08507 8.76509 8.45511 8.15477 7.86393 - 7.58258 7.31076 7.04866 6.79648 6.55679 6.32907 - 6.11538 5.91508 5.72966 5.56095 5.41027 5.27564 - 5.16017 5.11590 5.08593 5.06690 4.99510 4.96005 - 4.96959 4.97584 4.97312 4.97118 4.97472 4.97241 - 9.99439 9.57959 9.15217 8.74313 8.35148 7.97637 - 7.61769 7.27556 6.94849 6.63878 6.34803 6.07506 - 5.82226 5.58910 5.37626 5.18520 5.01623 4.86412 - 4.72812 4.67149 4.62695 4.59471 4.51350 4.47979 - 4.49432 4.50114 4.49757 4.49538 4.49879 4.49681 - 10.18615 9.91411 9.47696 8.96571 8.44217 7.95869 - 7.52095 7.12645 6.77004 6.44609 6.14514 5.85892 - 5.59380 5.35196 5.12875 4.91683 4.71222 4.52335 - 4.35451 4.27514 4.20248 4.15354 4.11454 4.10562 - 4.09881 4.09800 4.09735 4.09724 4.09722 4.09729 - 10.49131 10.12686 9.60361 9.02075 8.44027 7.91329 - 7.44204 7.01993 6.63964 6.29410 5.97405 5.67003 - 5.38716 5.12826 4.88778 4.65930 4.43902 4.23267 - 4.04399 3.95585 3.87625 3.82359 3.78213 3.77305 - 3.76620 3.76539 3.76475 3.76464 3.76460 3.76464 - 10.89376 10.22954 9.57108 8.96330 8.40069 7.88005 - 7.39835 6.95207 6.53985 6.16161 5.81621 5.49698 - 5.20119 4.92797 4.67369 4.43755 4.21673 4.00126 - 3.78575 3.68429 3.59846 3.54668 3.50192 3.49364 - 3.48602 3.48506 3.48450 3.48435 3.48447 3.48434 - 11.20946 10.42874 9.66800 8.97591 8.34360 7.76595 - 7.23822 6.75464 6.31297 5.91387 5.55171 5.21838 - 4.90814 4.61970 4.34897 4.09376 3.85092 3.61124 - 3.37077 3.25753 3.16246 3.10549 3.05495 3.04501 - 3.03694 3.03601 3.03536 3.03522 3.03525 3.03509 - 11.42497 10.55047 9.71051 8.95442 8.27058 7.65122 - 7.08992 6.58068 6.11956 5.70680 5.33416 4.99205 - 4.67272 4.37396 4.09274 3.82518 3.56795 3.31242 - 3.05541 2.93377 2.83070 2.76748 2.71069 2.69941 - 2.69037 2.68932 2.68858 2.68845 2.68840 2.68825 - 11.77036 10.68826 9.69394 8.82388 8.05797 7.37948 - 6.77462 6.23545 5.75541 5.32710 4.94052 4.58389 - 4.24638 3.92366 3.61879 3.32927 3.05381 2.78481 - 2.51768 2.38794 2.26702 2.18223 2.11381 2.09912 - 2.08762 2.08631 2.08522 2.08506 2.08496 2.08491 - 12.02790 10.75895 9.64263 8.69047 7.86974 7.15714 - 6.53236 5.97997 5.49044 5.05275 4.65573 4.28882 - 3.94165 3.60973 3.29720 3.00370 2.72479 2.45143 - 2.17675 2.04046 1.90911 1.81294 1.73548 1.71828 - 1.70441 1.70281 1.70150 1.70129 1.70121 1.70123 - 12.41943 10.87469 9.59746 8.53903 7.64560 6.88568 - 6.23680 5.67117 5.16875 4.71797 4.30757 3.92796 - 3.56993 3.22886 2.90762 2.61043 2.33067 2.05591 - 1.77764 1.63784 1.50057 1.39617 1.30532 1.28407 - 1.26698 1.26497 1.26330 1.26305 1.26293 1.26297 - 12.75651 10.98838 9.61286 8.49922 7.57244 6.78325 - 6.11188 5.53033 5.01417 4.54986 4.12583 3.73335 - 3.36686 3.02281 2.70038 2.39960 2.11673 1.84003 - 1.56249 1.42261 1.28420 1.17632 1.07538 1.05146 - 1.03229 1.02968 1.02784 1.02765 1.02739 1.02740 - 13.07244 11.13324 9.68570 8.52472 7.56957 6.75939 - 6.07138 5.47694 4.94909 4.47302 4.03810 3.63633 - 3.26242 2.91265 2.58529 2.27922 1.99311 1.71556 - 1.43739 1.29681 1.15622 1.04445 0.93607 0.90970 - 0.88867 0.88584 0.88381 0.88359 0.88332 0.88321 - 13.34452 11.31917 9.81466 8.58952 7.58785 6.75756 - 6.06341 5.46732 4.93500 4.45170 4.00939 3.60097 - 3.21926 2.85989 2.52293 2.21001 1.92116 1.64373 - 1.36296 1.22046 1.07670 0.96078 0.84607 0.81741 - 0.79453 0.79177 0.78946 0.78918 0.78891 0.78874 - 13.82345 11.61514 10.04161 8.75851 7.71690 6.86405 - 6.15171 5.53805 4.98850 4.48889 4.03147 3.60941 - 3.21578 2.84598 2.49905 2.17494 1.87243 1.58495 - 1.29662 1.14927 0.99803 0.87304 0.74508 0.71236 - 0.68617 0.68300 0.68034 0.68002 0.67970 0.67960 - 14.20711 11.87800 10.26467 8.94750 7.88205 7.01244 - 6.28549 5.65735 5.09424 4.58256 4.11456 3.68294 - 3.28026 2.90136 2.54457 2.20866 1.89147 1.58845 - 1.28878 1.13466 0.97435 0.83940 0.69747 0.66057 - 0.63101 0.62741 0.62438 0.62402 0.62367 0.62371 - 14.88861 12.39249 10.74063 9.39009 8.30881 7.41384 - 6.65945 6.00398 5.41694 4.88476 4.39884 3.95056 - 3.53078 3.13290 2.75423 2.39190 2.04228 1.70027 - 1.36202 1.18679 0.99907 0.83587 0.65817 0.61109 - 0.57343 0.56880 0.56490 0.56443 0.56401 0.56408 - 15.33054 12.75515 11.10716 9.76152 8.68656 7.78251 - 7.01250 6.33975 5.73747 5.19211 4.69424 4.23433 - 3.80196 3.38950 2.99375 2.61103 2.23633 1.86213 - 1.48074 1.28188 1.06325 0.86908 0.65620 0.59961 - 0.55386 0.54820 0.54358 0.54303 0.54246 0.54204 - 15.74442 13.20686 11.66553 10.39410 9.33668 8.41420 - 7.60712 6.89540 6.26511 5.70289 5.19606 4.73127 - 4.29318 3.87036 3.45819 3.05083 2.63899 2.20629 - 1.73592 1.48267 1.21116 0.96757 0.68263 0.59963 - 0.53940 0.53308 0.52724 0.52619 0.52575 0.52284 - 16.06537 13.47419 11.98892 10.77949 9.75502 8.85308 - 8.05650 7.34804 6.71562 6.14745 5.63221 5.15755 - 4.70905 4.27533 3.85063 3.42717 2.99194 2.52108 - 1.98685 1.68707 1.35936 1.06464 0.71522 0.61212 - 0.53472 0.52627 0.51939 0.51829 0.51710 0.51260 - 16.26518 13.64007 12.21606 11.05987 10.06733 9.18706 - 8.40444 7.70394 7.07484 6.50657 5.98880 5.51005 - 5.05655 4.61701 4.18489 3.75088 3.29907 2.79953 - 2.21510 1.87741 1.49848 1.15856 0.75050 0.62843 - 0.53297 0.52199 0.51389 0.51278 0.51094 0.50575 - 16.39760 13.74816 12.38537 11.27224 10.30936 9.45021 - 8.68252 7.99199 7.36901 6.80390 6.28707 5.80769 - 5.35252 4.91033 4.47398 4.03302 3.56920 3.04768 - 2.42305 2.05393 1.63162 1.24864 0.78654 0.64645 - 0.53287 0.51916 0.50959 0.50846 0.50611 0.50074 - 16.55582 13.87675 12.62093 11.57460 10.66230 9.84127 - 9.10248 8.43338 7.82592 7.27165 6.76204 6.28713 - 5.83437 5.39254 4.95375 4.50589 4.02725 3.47542 - 2.79114 2.37299 1.87959 1.41835 0.85833 0.68463 - 0.53575 0.51637 0.50320 0.50195 0.49897 0.49385 - 16.64154 13.94999 12.77558 11.78002 10.90791 10.11887 - 9.40573 8.75714 8.16610 7.62492 7.12575 6.65912 - 6.21284 5.77566 5.33923 4.89032 4.40485 3.83486 - 3.10974 2.65542 2.10654 1.57731 0.92837 0.72365 - 0.54114 0.51605 0.49863 0.49713 0.49391 0.48928 - 16.73637 14.04589 12.99403 12.08599 11.28305 10.55227 - 9.88846 9.28241 8.72829 8.21950 7.74899 7.30785 - 6.88403 6.46609 6.04511 5.60641 5.12235 4.53604 - 3.75592 3.24471 2.59976 1.94366 1.09416 0.82020 - 0.55991 0.52091 0.49136 0.48888 0.48602 0.48255 - 16.77463 14.08921 13.10667 12.25332 11.49415 10.80218 - 10.17302 9.59868 9.07393 8.59270 8.14831 7.73205 - 7.33173 6.93562 6.53460 6.11340 5.64257 5.06011 - 4.26024 3.71896 3.01422 2.26749 1.24728 0.91258 - 0.58165 0.52964 0.48753 0.48373 0.48148 0.47884 - 16.80859 14.12156 13.21927 12.42925 11.72292 11.07945 - 10.49541 9.96414 9.48118 9.04117 8.63787 8.26277 - 7.90336 7.54757 7.18639 6.80428 6.37033 5.81705 - 5.02090 4.45600 3.68561 2.81891 1.52268 1.08404 - 0.62697 0.55139 0.48510 0.47823 0.47650 0.47487 - 16.82246 14.14173 13.28524 12.52978 11.85199 11.23468 - 10.67474 10.16691 9.70740 9.29171 8.91458 8.56862 - 8.24264 7.92553 7.60823 7.27416 6.88833 6.37090 - 5.58223 5.00673 4.21013 3.27983 1.77758 1.24081 - 0.67100 0.57378 0.48623 0.47740 0.47373 0.47278 - 16.80649 14.14366 13.31821 12.58702 11.92977 11.33201 - 10.79081 10.30145 9.86064 9.46442 9.10805 8.78472 - 8.48382 8.19480 7.90908 7.61024 7.26232 6.78076 - 6.01761 5.44730 4.64359 3.67349 2.01361 1.38537 - 0.71425 0.59776 0.48909 0.47678 0.47238 0.47150 - 16.78235 14.14455 13.34054 12.62634 11.98371 11.39981 - 10.87213 10.39631 9.96941 9.58789 9.24741 8.94170 - 8.66073 8.39449 8.13505 7.86644 7.55249 7.10568 - 6.37229 5.81215 5.00969 4.01451 2.23155 1.52231 - 0.75594 0.62140 0.49292 0.47719 0.47153 0.47063 - 16.73125 14.14647 13.37065 12.67912 12.05585 11.49075 - 10.98128 10.52393 10.11619 9.75509 9.43705 9.15654 - 8.90465 8.67253 8.45348 8.23299 7.97569 7.59171 - 6.92081 6.38763 5.60024 4.58078 2.62196 1.78033 - 0.83508 0.66720 0.50206 0.47981 0.47057 0.46954 - 16.66441 14.13982 13.39267 12.72158 12.11291 11.55926 - 11.05909 10.61039 10.21220 9.86250 9.55855 9.29620 - 9.06829 8.86659 8.68162 8.49201 8.26113 7.91961 - 7.32375 6.83046 6.06191 5.03269 2.97071 2.01674 - 0.90930 0.71101 0.51204 0.48397 0.47004 0.46887 - 16.57951 14.14725 13.42825 12.77853 12.18806 11.65148 - 11.16766 10.73559 10.35477 10.02391 9.74121 9.50362 - 9.30555 9.14068 9.00191 8.87089 8.71569 8.47424 - 8.00843 7.58735 6.88154 5.87467 3.67576 2.54019 - 1.07956 0.81327 0.53848 0.49613 0.46995 0.46797 - 16.46852 14.15344 13.44899 12.81027 12.22937 11.70197 - 11.22707 10.80391 10.43245 10.11175 9.84048 9.61649 - 9.43528 9.29185 9.18056 9.08498 8.97712 8.80325 - 8.43585 8.07647 7.43459 6.47067 4.22908 2.98005 - 1.23383 0.90744 0.56473 0.50962 0.47065 0.46751 - 16.19289 14.16219 13.47093 12.84259 12.27090 11.75268 - 11.28707 10.87364 10.51275 10.20356 9.94546 9.73699 - 9.57482 9.45533 9.37475 9.31947 9.26707 9.17638 - 8.94091 8.67454 8.14656 7.28203 5.05913 3.68617 - 1.51034 1.07954 0.61504 0.53721 0.47319 0.46705 - 15.96036 14.16762 13.48207 12.85822 12.29077 11.77710 - 11.31632 10.90821 10.55320 10.25059 10.00001 9.80036 - 9.64878 9.54234 9.47843 9.44543 9.42465 9.38309 - 9.23097 9.02963 8.59227 7.82078 5.66737 4.23924 - 1.75585 1.23568 0.66231 0.56412 0.47685 0.46682 - 15.79171 14.17099 13.48851 12.86739 12.30244 11.79157 - 11.33383 10.92903 10.57777 10.27935 10.03358 9.83962 - 9.69475 9.59653 9.54315 9.52444 9.52435 9.51535 - 9.42035 9.26626 8.90001 8.20917 6.14088 4.69135 - 1.97822 1.37993 0.70706 0.59004 0.48127 0.46668 - 15.67323 14.17569 13.49575 12.87429 12.30861 11.79856 - 11.34321 10.94186 10.59432 10.29986 10.05819 9.86845 - 9.72781 9.63407 9.58663 9.57756 9.59359 9.60936 - 9.55437 9.43426 9.12607 8.50590 6.51917 5.07387 - 2.19327 1.51412 0.75009 0.61475 0.48641 0.46659 - 15.52402 14.17697 13.50016 12.88145 12.31853 11.81128 - 11.35902 10.96107 10.61739 10.32710 10.08913 9.90296 - 9.76734 9.68165 9.64534 9.65000 9.68385 9.73099 - 9.73597 9.66378 9.42811 8.91357 7.12991 5.69826 - 2.58567 1.75366 0.83167 0.66362 0.49906 0.46647 - 15.42759 14.17716 13.50294 12.88626 12.32531 11.81991 - 11.36949 10.97316 10.63075 10.34210 10.10703 9.92525 - 9.79415 9.71246 9.68093 9.69382 9.74201 9.80908 - 9.84523 9.80522 9.63653 9.20991 7.54017 6.16093 - 2.95246 1.98378 0.90593 0.70691 0.50830 0.46640 - 15.30467 14.18401 13.50428 12.88687 12.32817 11.82615 - 11.37961 10.98765 10.64971 10.36550 10.13459 9.95592 - 9.82592 9.74377 9.71547 9.74633 9.83393 9.94354 - 10.01470 10.00708 9.91529 9.63207 8.28802 7.00183 - 3.67327 2.48748 1.07768 0.81024 0.53624 0.46631 - 15.21995 14.18308 13.50558 12.88984 12.33257 11.83184 - 11.38667 10.99601 10.65957 10.37694 10.14786 9.97117 - 9.84371 9.76492 9.74118 9.77836 9.87517 9.99927 - 10.09793 10.11700 10.07561 9.87526 8.74589 7.57348 - 4.23953 2.93839 1.23244 0.90503 0.56374 0.46626 - 15.10650 14.17380 13.50749 12.89752 12.34268 11.84275 - 11.39718 11.00602 10.66977 10.38794 10.15985 9.98503 - 9.86346 9.79571 9.78336 9.82116 9.90330 10.02700 - 10.17726 10.24361 10.25800 10.12677 9.28054 8.35902 - 5.08745 3.63634 1.50710 1.08274 0.61555 0.46621 - 15.05882 14.17383 13.50894 12.89952 12.34505 11.84538 - 11.40026 11.00945 10.67340 10.39208 10.16549 9.99330 - 9.87408 9.80763 9.79616 9.83643 9.92476 10.05870 - 10.22202 10.29872 10.34350 10.28263 9.61852 8.77444 - 5.71392 4.22404 1.75215 1.23344 0.66400 0.46618 - 15.02974 14.17420 13.50973 12.90046 12.34600 11.84662 - 11.40190 11.01159 10.67604 10.39529 10.16935 9.99792 - 9.87965 9.81433 9.80434 9.84670 9.93815 10.07697 - 10.24985 10.33611 10.39867 10.37057 9.83210 9.09248 - 6.19005 4.68246 2.00202 1.37874 0.70912 0.46617 - 15.01022 14.17454 13.50989 12.90063 12.34624 11.84712 - 11.40287 11.01332 10.67869 10.39874 10.17274 10.00046 - 9.88186 9.81786 9.81027 9.85481 9.94727 10.08760 - 10.26906 10.36537 10.43874 10.41941 9.96925 9.36232 - 6.57519 5.04605 2.25459 1.52326 0.75002 0.46616 - 14.98333 14.17513 13.51116 12.90223 12.34814 11.84921 - 11.40513 11.01546 10.68063 10.40061 10.17546 10.00504 - 9.88802 9.82438 9.81665 9.86223 9.95852 10.10480 - 10.29244 10.39366 10.48429 10.50814 10.18307 9.64545 - 7.16047 5.69159 2.69608 1.82588 0.83188 0.46615 - 14.96833 14.17500 13.51120 12.90284 12.34941 11.85103 - 11.40718 11.01796 10.68369 10.40414 10.17866 10.00705 - 9.88937 9.82659 9.82084 9.86820 9.96509 10.11256 - 10.30671 10.41525 10.51490 10.54937 10.29921 9.87288 - 7.60345 6.16460 3.06391 2.10360 0.90422 0.46615 - 3.64394 3.71445 3.77614 3.82995 3.87567 3.91350 - 3.94420 3.96944 3.99149 4.01106 4.02860 4.04484 - 4.06148 4.07974 4.09879 4.11635 4.13042 4.14241 - 4.15372 4.15866 4.16256 4.16465 4.16673 4.16714 - 4.16736 4.16738 4.16741 4.16741 4.16743 4.16743 - 4.33153 4.40312 4.46213 4.51010 4.54695 4.57305 - 4.58965 4.59908 4.60448 4.60673 4.60639 4.60413 - 4.60155 4.59987 4.59846 4.59559 4.59000 4.58354 - 4.57855 4.57656 4.57413 4.57122 4.56631 4.56499 - 4.56394 4.56380 4.56369 4.56369 4.56367 4.56364 - 4.84334 4.91940 4.97808 5.02155 5.04982 5.06375 - 5.06523 5.05778 5.04595 5.03103 5.01364 4.99468 - 4.97571 4.95805 4.94113 4.92324 4.90322 4.88315 - 4.86576 4.85811 4.84998 4.84247 4.83323 4.83087 - 4.82899 4.82874 4.82853 4.82853 4.82850 4.82847 - 5.58191 5.67981 5.73746 5.76290 5.76382 5.74917 - 5.72226 5.68650 5.64620 5.60286 5.55758 5.51161 - 5.46570 5.42091 5.37771 5.33666 5.29803 5.26083 - 5.22482 5.20787 5.19089 5.17701 5.16199 5.15829 - 5.15530 5.15491 5.15462 5.15458 5.15454 5.15452 - 6.11598 6.22235 6.27442 6.28350 6.26091 6.21955 - 6.16447 6.10075 6.03448 5.96699 5.89825 5.82934 - 5.76196 5.69808 5.63802 5.58139 5.52777 5.47684 - 5.42845 5.40524 5.38212 5.36374 5.34488 5.34023 - 5.33650 5.33601 5.33565 5.33560 5.33556 5.33555 - 6.53113 6.64062 6.68359 6.67466 6.62855 6.56176 - 6.48081 6.39206 6.30290 6.21452 6.12617 6.03867 - 5.95418 5.87514 5.80166 5.73265 5.66721 5.60555 - 5.54767 5.51984 5.49227 5.47060 5.44882 5.44345 - 5.43915 5.43860 5.43819 5.43812 5.43808 5.43809 - 6.86905 6.97749 7.00880 6.98085 6.91156 6.82077 - 6.71618 6.60502 6.49556 6.38892 6.28385 6.18089 - 6.08240 5.99082 5.90614 5.82682 5.75160 5.68111 - 5.61558 5.58422 5.55326 5.52910 5.50498 5.49902 - 5.49426 5.49364 5.49319 5.49312 5.49309 5.49308 - 7.39672 7.49420 7.49708 7.42962 7.31576 7.18113 - 7.03506 6.88561 6.74168 6.60436 6.47215 6.34499 - 6.22483 6.11345 6.01068 5.91461 5.82377 5.73923 - 5.66181 5.62542 5.58979 5.56211 5.53427 5.52742 - 5.52197 5.52127 5.52074 5.52066 5.52061 5.52059 - 7.79895 7.87847 7.84965 7.74299 7.58768 7.41429 - 7.23300 7.05193 6.87984 6.71762 6.56393 6.41817 - 6.28153 6.15472 6.03754 5.92801 5.82472 5.72904 - 5.64243 5.60238 5.56345 5.53330 5.50272 5.49521 - 5.48923 5.48844 5.48786 5.48778 5.48773 5.48771 - 8.50795 8.53145 8.42285 8.22650 7.98224 7.72952 - 7.47919 7.23806 7.01339 6.80481 6.61147 6.43106 - 6.26371 6.10814 5.96390 5.82872 5.70128 5.58407 - 5.47978 5.43232 5.38678 5.35205 5.31723 5.30871 - 5.30193 5.30105 5.30039 5.30030 5.30023 5.30021 - 9.25355 8.96705 8.66824 8.37826 8.09677 7.82367 - 7.55897 7.30277 7.05527 6.81672 6.58953 6.37329 - 6.16999 5.97910 5.80212 5.64083 5.49654 5.36729 - 5.25586 5.21275 5.18294 5.16325 5.09146 5.05671 - 5.06569 5.07174 5.06902 5.06711 5.07057 5.06832 - 9.63373 9.48648 9.17843 8.78367 8.35892 7.95489 - 7.58046 7.23724 6.92468 6.64044 6.37838 6.13266 - 5.90607 5.69769 5.50500 5.32279 5.14843 4.98887 - 4.84790 4.78191 4.71972 4.67528 4.63655 4.62715 - 4.61979 4.61888 4.61818 4.61806 4.61801 4.61804 - 10.05822 9.81076 9.40061 8.91409 8.41198 7.94631 - 7.52326 7.14093 6.79507 6.48133 6.19211 5.91965 - 5.66763 5.43650 5.22244 5.01960 4.82482 4.64491 - 4.48357 4.40790 4.33770 4.28906 4.24860 4.23907 - 4.23170 4.23081 4.23010 4.22998 4.22994 4.22998 - 10.36616 10.02899 9.53412 8.97600 8.41618 7.90593 - 7.44834 7.03768 6.66763 6.33206 6.02292 5.73121 - 5.46018 5.21144 4.98019 4.76104 4.55076 4.35403 - 4.17442 4.09095 4.01482 3.96324 3.92090 3.91132 - 3.90400 3.90310 3.90241 3.90231 3.90226 3.90227 - 10.77537 10.13726 9.50499 8.91996 8.37715 7.87377 - 7.40711 6.97409 6.57355 6.20555 5.86919 5.55846 - 5.27103 5.00631 4.76104 4.53466 4.32436 4.11976 - 3.91473 3.81808 3.73624 3.68661 3.64205 3.63301 - 3.62520 3.62427 3.62362 3.62346 3.62359 3.62347 - 11.09770 10.34408 9.61030 8.94088 8.32772 7.76629 - 7.25230 6.78051 6.34895 5.95827 5.60338 5.27684 - 4.97341 4.69200 4.42890 4.18224 3.94905 3.72004 - 3.49107 3.38371 3.29405 3.24072 3.19187 3.18149 - 3.17360 3.17276 3.17206 3.17191 3.17194 3.17182 - 11.31866 10.47188 9.65920 8.92549 8.26011 7.65603 - 7.10741 6.60875 6.15646 5.75073 5.38399 5.04734 - 4.73357 4.44061 4.16575 3.90554 3.65690 3.41137 - 3.16592 3.05057 2.95367 2.89506 2.84119 2.82982 - 2.82128 2.82037 2.81961 2.81947 2.81942 2.81933 - 11.67068 10.62069 9.65500 8.80658 8.05704 7.39106 - 6.79602 6.26459 5.79065 5.36720 4.98472 4.63200 - 4.29853 3.98002 3.67946 3.39490 3.12542 2.86396 - 2.60663 2.48284 2.36852 2.28937 2.22553 2.21189 - 2.20131 2.20011 2.19910 2.19896 2.19887 2.19882 - 11.93686 10.69732 9.60709 8.67484 7.86960 7.16918 - 6.55413 6.00933 5.52522 5.09128 4.69706 4.33254 - 3.98788 3.65872 3.34909 3.05899 2.78454 2.51702 - 2.25008 2.11876 1.99343 1.90302 1.83125 1.81549 - 1.80283 1.80138 1.80019 1.79999 1.79992 1.79991 - 12.32988 10.81571 9.56270 8.52252 7.64359 6.89530 - 6.25531 5.69639 5.19851 4.75062 4.34211 3.96396 - 3.60743 3.26811 2.94877 2.65353 2.37630 2.10496 - 1.83151 1.69521 1.56296 1.46412 1.37969 1.36020 - 1.34458 1.34275 1.34123 1.34100 1.34089 1.34090 - 12.64988 10.92817 9.57960 8.48226 7.56679 6.78723 - 6.12362 5.54816 5.03654 4.57543 4.15349 3.76240 - 3.39734 3.05513 2.73477 2.43583 2.15449 1.87968 - 1.60535 1.46830 1.33418 1.23129 1.13694 1.11493 - 1.09729 1.09488 1.09320 1.09303 1.09278 1.09279 - 12.95132 11.06670 9.64676 8.50194 7.55818 6.75896 - 6.07991 5.49093 4.96428 4.48796 4.05512 3.65846 - 3.28912 2.94142 2.61468 2.30939 2.02510 1.75018 - 1.47436 1.33502 1.19783 1.09114 0.98955 0.96494 - 0.94538 0.94286 0.94099 0.94073 0.94057 0.94046 - 13.21960 11.20932 9.74000 8.55917 7.59243 6.77757 - 6.08437 5.48217 4.94317 4.45562 4.01375 3.61047 - 3.23573 2.88292 2.55103 2.24016 1.95041 1.67324 - 1.39518 1.25404 1.11340 1.00202 0.89368 0.86708 - 0.84583 0.84309 0.84106 0.84078 0.84059 0.84044 - 13.66897 11.48609 9.95377 8.72150 7.71857 6.88090 - 6.16741 5.54551 4.98827 4.48447 4.02819 3.61219 - 3.22635 2.86364 2.52207 2.20014 1.89685 1.60949 - 1.32345 1.17712 1.02848 0.90755 0.78596 0.75542 - 0.73087 0.72768 0.72532 0.72500 0.72478 0.72464 - 14.02776 11.73809 10.16984 8.90506 7.87843 7.02387 - 6.29607 5.66087 5.09213 4.57801 4.11104 3.68355 - 3.28691 2.91468 2.56370 2.23058 1.91292 1.61000 - 1.31227 1.15919 1.00135 0.87022 0.73474 0.70013 - 0.67222 0.66858 0.66588 0.66551 0.66526 0.66519 - 14.66539 12.26681 10.65894 9.33956 8.27707 7.39385 - 6.64665 5.99602 5.41287 4.88405 4.40105 3.95529 - 3.53763 3.14159 2.76477 2.40476 2.05790 1.71809 - 1.38095 1.20673 1.02155 0.86219 0.69127 0.64631 - 0.61035 0.60594 0.60221 0.60176 0.60136 0.60140 - 15.10389 12.62456 11.01601 9.69946 8.64281 7.75215 - 6.99176 6.32621 5.72937 5.18812 4.69332 4.23570 - 3.80504 3.39402 2.99985 2.61947 2.24796 1.87662 - 1.49706 1.29929 1.08333 0.89314 0.68712 0.63268 - 0.58872 0.58331 0.57888 0.57833 0.57780 0.57759 - 15.52147 13.08085 11.57070 10.32062 9.27716 8.36608 - 7.56825 6.86438 6.24078 5.68437 5.18262 4.72222 - 4.28786 3.86814 3.45857 3.05356 2.64409 2.21437 - 1.74798 1.49719 1.22876 0.98889 0.71025 0.62970 - 0.57192 0.56603 0.56045 0.55941 0.55905 0.55703 - 15.85330 13.35728 11.89439 10.69817 9.68293 8.78962 - 8.00110 7.30044 6.67555 6.11466 5.60634 5.13811 - 4.69520 4.26609 3.84519 3.42494 2.99267 2.52519 - 1.99553 1.69873 1.37459 1.08372 0.74058 0.63989 - 0.56562 0.55786 0.55152 0.55042 0.54939 0.54616 - 16.06155 13.53095 12.12214 10.97307 9.98598 9.11198 - 8.33620 7.64321 7.02205 6.46201 5.95249 5.48166 - 5.03523 4.60157 4.17431 3.74434 3.29612 2.80038 - 2.22087 1.88649 1.51172 1.17575 0.77394 0.65428 - 0.56258 0.55256 0.54535 0.54428 0.54260 0.53875 - 16.19971 13.64516 12.29170 11.18147 10.22107 9.36627 - 8.60434 7.92091 7.30603 6.74972 6.24205 5.77169 - 5.32470 4.88940 4.45881 4.02267 3.56306 3.04573 - 2.42627 2.06067 1.64294 1.26417 0.80831 0.67068 - 0.56140 0.54890 0.54059 0.53955 0.53734 0.53321 - 16.36256 13.78084 12.52643 11.47773 10.56415 9.74475 - 9.01003 8.34720 7.74776 7.20282 6.70337 6.23882 - 5.79571 5.36224 4.93061 4.48888 4.01560 3.46875 - 2.79003 2.37564 1.88737 1.43103 0.87732 0.70622 - 0.56255 0.54480 0.53360 0.53254 0.52962 0.52542 - 16.44629 13.85559 12.67832 11.67822 10.80294 10.01398 - 9.30380 8.66080 8.07747 7.54565 7.05697 6.60130 - 6.16544 5.73754 5.30927 4.86755 4.38842 3.82416 - 3.10500 2.65458 2.11117 1.58756 0.94513 0.74320 - 0.56658 0.54344 0.52862 0.52743 0.52418 0.52018 - 16.52126 13.94173 12.88605 11.97323 11.16685 10.43561 - 9.77396 9.17255 8.62521 8.12501 7.66444 7.23405 - 6.82093 6.41305 6.00146 5.57156 5.09568 4.51679 - 3.74381 3.23694 2.59805 1.94862 1.10703 0.83623 - 0.58283 0.54631 0.52063 0.51873 0.51562 0.51239 - 16.53545 13.97078 12.98730 12.13187 11.37123 10.67990 - 10.05322 9.48326 8.96455 8.49089 8.05529 7.64870 - 7.25830 6.87197 6.48059 6.06893 5.60745 5.03376 - 4.24229 3.70588 3.00768 2.26833 1.25758 0.92629 - 0.60276 0.55357 0.51623 0.51325 0.51062 0.50810 - 16.53197 13.98076 13.08373 12.29677 11.59302 10.95277 - 10.37252 9.84578 9.36801 8.93393 8.53725 8.16943 - 7.81785 7.47042 7.11823 6.74580 6.32215 5.77934 - 4.99375 4.43480 3.67191 2.81354 1.52970 1.09467 - 0.64553 0.57320 0.51283 0.50713 0.50507 0.50349 - 16.52324 13.98795 13.14124 12.39269 11.72029 11.10799 - 10.55278 10.04940 9.59425 9.18298 8.81054 8.46976 - 8.14981 7.83991 7.53119 7.20711 6.83239 6.32597 - 5.54756 4.97807 4.19007 3.26988 1.78246 1.24966 - 0.68754 0.59393 0.51312 0.50571 0.50216 0.50104 - 16.49670 13.98301 13.16943 12.44701 11.79684 11.20522 - 10.66936 10.18478 9.74828 9.35606 9.00357 8.68430 - 8.38809 8.10479 7.82609 7.53580 7.19806 6.72787 - 5.97715 5.41406 4.61935 3.65935 2.01605 1.39297 - 0.72940 0.61663 0.51520 0.50458 0.50055 0.49954 - 16.46791 13.98045 13.18926 12.48483 11.85002 11.27312 - 10.75119 10.28038 9.85780 9.48001 9.14297 8.84058 - 8.56331 8.30163 8.04784 7.78638 7.48153 7.04606 - 6.32668 5.77480 4.98182 3.99685 2.23180 1.52882 - 0.76996 0.63924 0.51832 0.50451 0.49953 0.49852 - 16.39453 13.97156 13.21771 12.54175 11.92914 11.37114 - 10.86594 10.41110 10.00506 9.64542 9.32927 9.05219 - 8.80677 8.58431 8.37434 8.15417 7.88619 7.50172 - 6.86043 6.34704 5.56824 4.55518 2.62352 1.78267 - 0.84732 0.68324 0.52602 0.50659 0.49829 0.49723 - 16.35840 13.97704 13.24062 12.57854 11.97795 11.43156 - 10.93784 10.49480 10.10113 9.75490 9.45357 9.19320 - 8.96702 8.76717 8.58457 8.39849 8.17332 7.84159 - 7.26171 6.77884 6.02173 5.00420 2.96398 2.01879 - 0.92035 0.72592 0.53511 0.50965 0.49766 0.49644 - 16.29102 13.99265 13.28068 12.63732 12.05293 11.52250 - 11.04447 10.61758 10.24113 9.91380 9.63379 9.39816 - 9.20149 9.03763 8.89971 8.76995 8.61755 8.38278 - 7.93110 7.52102 6.82923 5.83691 3.66187 2.53700 - 1.08845 0.82599 0.55945 0.52009 0.49730 0.49537 - 16.19418 14.00323 13.30417 12.67043 12.09443 11.57229 - 11.10236 10.68393 10.31661 9.99944 9.73108 9.50931 - 9.32960 9.18699 9.07600 8.98071 8.87406 8.70439 - 8.34811 7.99894 7.37228 6.42528 4.20952 2.97239 - 1.24128 0.91867 0.58415 0.53222 0.49774 0.49484 - 15.93790 14.01110 13.32552 12.70223 12.13551 11.62231 - 11.16146 10.75240 10.39545 10.08970 9.83449 9.62828 - 9.46766 9.34898 9.26855 9.21302 9.16054 9.07109 - 8.84137 8.58242 8.06882 7.22344 5.03083 3.67125 - 1.51592 1.08876 0.63224 0.55774 0.49968 0.49429 - 15.71748 14.01267 13.33398 12.71652 12.15489 11.64664 - 11.19076 10.78699 10.43587 10.13656 9.88866 9.69111 - 9.54099 9.43541 9.37179 9.33860 9.31736 9.27552 - 9.12550 8.92896 8.50372 7.75145 5.63225 4.21869 - 1.76024 1.24355 0.67793 0.58314 0.50273 0.49402 - 15.55732 14.01481 13.34012 12.72468 12.16450 11.65859 - 11.20600 10.80650 10.46064 10.16705 9.92440 9.73149 - 9.58675 9.48868 9.43545 9.41653 9.41618 9.40889 - 9.31410 9.15737 8.79726 8.13488 6.12090 4.66269 - 1.97373 1.38427 0.72248 0.60791 0.50855 0.49385 - 15.44550 14.01568 13.34440 12.73085 12.17230 11.66825 - 11.21792 10.82076 10.47704 10.18587 9.94674 9.75874 - 9.61939 9.52667 9.47982 9.47065 9.48566 9.50016 - 9.44433 9.32530 9.02442 8.42096 6.47327 5.04498 - 2.19523 1.52007 0.76353 0.63161 0.51108 0.49374 - 15.30725 14.01394 13.34633 12.73764 12.18399 11.68378 - 11.23637 10.84152 10.49976 10.21094 9.97504 9.79178 - 9.65882 9.57450 9.53855 9.54334 9.57714 9.62065 - 9.62002 9.55048 9.32658 8.82679 7.05664 5.64466 - 2.59651 1.76720 0.84233 0.67790 0.52029 0.49361 - 15.21909 14.01480 13.34948 12.74246 12.19053 11.69192 - 11.24632 10.85338 10.51355 10.22696 9.99359 9.81334 - 9.68402 9.60419 9.57424 9.58757 9.63405 9.69729 - 9.73203 9.69431 9.52521 9.10480 7.48540 6.11345 - 2.94569 1.98963 0.91652 0.72147 0.53036 0.49352 - 15.08323 14.01843 13.35645 12.74994 12.19799 11.70073 - 11.25745 10.86793 10.53193 10.24947 10.02046 9.84455 - 9.71979 9.64530 9.62249 9.64675 9.71110 9.80521 - 9.89186 9.89759 9.81441 9.52896 8.19429 6.95617 - 3.66545 2.48454 1.08615 0.82250 0.55703 0.49341 - 15.00657 14.01824 13.35802 12.75314 12.20259 11.70650 - 11.26436 10.87598 10.54131 10.26044 10.03332 9.85958 - 9.73747 9.66631 9.64790 9.67827 9.75159 9.86065 - 9.97586 10.00776 9.97211 9.76671 8.64498 7.51584 - 4.22585 2.93002 1.23951 0.91584 0.58309 0.49336 - 14.92443 14.01751 13.35920 12.75585 12.20681 11.71199 - 11.27103 10.88379 10.55054 10.27131 10.04616 9.87465 - 9.75528 9.68766 9.67388 9.71048 9.79301 9.91741 - 10.06286 10.12331 10.13946 10.02633 9.18889 8.23476 - 5.06577 3.64312 1.51332 1.08611 0.63287 0.49330 - 14.88153 14.01728 13.35963 12.75701 12.20864 11.71435 - 11.27402 10.88752 10.55510 10.27683 10.05268 9.88226 - 9.76428 9.69849 9.68713 9.72696 9.81425 9.94647 - 10.10768 10.18335 10.22741 10.16573 9.50784 8.68490 - 5.67870 4.20341 1.75629 1.24131 0.67947 0.49328 - 14.85500 14.01735 13.36002 12.75763 12.20935 11.71555 - 11.27571 10.88973 10.55790 10.28026 10.05672 9.88699 - 9.76982 9.70514 9.69525 9.73711 9.82746 9.96455 - 10.13538 10.22053 10.28221 10.25321 9.71783 8.99541 - 6.14898 4.65676 2.00528 1.38566 0.72346 0.49326 - 14.83636 14.01760 13.36047 12.75809 12.20997 11.71643 - 11.27685 10.89128 10.55986 10.28263 10.05949 9.89021 - 9.77357 9.70963 9.70074 9.74401 9.83644 9.97684 - 10.15419 10.24579 10.31956 10.31315 9.86682 9.22361 - 6.52739 5.03896 2.25484 1.52095 0.76529 0.49325 - 14.81154 14.01781 13.36113 12.75907 12.21124 11.71799 - 11.27878 10.89355 10.56244 10.28553 10.06283 9.89414 - 9.77827 9.71523 9.70753 9.75250 9.84759 9.99218 - 10.17775 10.27765 10.36699 10.39002 10.06523 9.53714 - 7.10621 5.65413 2.68688 1.82770 0.84386 0.49324 - 14.79618 14.01749 13.36147 12.75997 12.21259 11.71958 - 11.28051 10.89551 10.56491 10.28842 10.06545 9.89578 - 9.77946 9.71740 9.71173 9.75851 9.85417 9.99975 - 10.19158 10.29911 10.39782 10.43090 10.17926 9.76355 - 7.54215 6.12031 3.04897 2.10021 0.91502 0.49323 - 3.47248 3.54079 3.60104 3.65411 3.69983 3.73838 - 3.77048 3.79772 3.82227 3.84482 3.86589 3.88625 - 3.90768 3.93141 3.95648 3.98017 3.99998 4.01694 - 4.03200 4.03845 4.04418 4.04820 4.05252 4.05356 - 4.05431 4.05439 4.05446 4.05447 4.05449 4.05450 - 4.15286 4.22086 4.27751 4.32428 4.36110 4.38838 - 4.40722 4.41983 4.42910 4.43588 4.44074 4.44430 - 4.44809 4.45327 4.45922 4.46420 4.46679 4.46831 - 4.47035 4.47143 4.47202 4.47146 4.46866 4.46789 - 4.46730 4.46721 4.46712 4.46713 4.46712 4.46711 - 4.66346 4.73579 4.79226 4.83490 4.86380 4.87972 - 4.88443 4.88121 4.87427 4.86481 4.85349 4.84109 - 4.82911 4.81879 4.80964 4.80011 4.78901 4.77792 - 4.76879 4.76481 4.76007 4.75496 4.74794 4.74613 - 4.74468 4.74449 4.74431 4.74432 4.74430 4.74429 - 5.40605 5.50053 5.55711 5.58354 5.58736 5.57723 - 5.55602 5.52648 5.49222 5.45484 5.41598 5.37713 - 5.33881 5.30175 5.26644 5.23344 5.20314 5.17492 - 5.14776 5.13426 5.12046 5.10903 5.09652 5.09328 - 5.09074 5.09042 5.09017 5.09013 5.09013 5.09011 - 5.94527 6.04976 6.10320 6.11610 6.09894 6.06374 - 6.01534 5.95867 5.89971 5.83960 5.77819 5.71641 - 5.65624 5.59979 5.54733 5.49827 5.45215 5.40921 - 5.36875 5.34867 5.32840 5.31219 5.29580 5.29174 - 5.28847 5.28804 5.28773 5.28769 5.28765 5.28766 - 6.36601 6.47499 6.52143 6.51875 6.48033 6.42149 - 6.34851 6.26781 6.18683 6.10659 6.02600 5.94568 - 5.86824 5.79642 5.73019 5.66819 5.60934 5.55464 - 5.50372 5.47849 5.45329 5.43358 5.41421 5.40940 - 5.40558 5.40508 5.40472 5.40467 5.40462 5.40463 - 6.70889 6.81832 6.85507 6.83550 6.77592 6.69463 - 6.59916 6.49691 6.39636 6.29841 6.20146 6.10582 - 6.01434 5.92982 5.85209 5.77927 5.70990 5.64545 - 5.58587 5.55663 5.52764 5.50519 5.48333 5.47792 - 5.47362 5.47307 5.47266 5.47259 5.47255 5.47255 - 7.24438 7.34579 7.35754 7.30192 7.20090 7.07829 - 6.94331 6.80424 6.67035 6.54260 6.41915 6.29981 - 6.18688 6.08242 5.98615 5.89590 5.81005 5.73020 - 5.65697 5.62195 5.58764 5.56122 5.53520 5.52881 - 5.52373 5.52308 5.52258 5.52251 5.52247 5.52247 - 7.65225 7.73836 7.72118 7.62891 7.48870 7.32926 - 7.16062 6.99113 6.82989 6.67779 6.53343 6.39614 - 6.26717 6.14735 6.03643 5.93241 5.83380 5.74202 - 5.65831 5.61916 5.58111 5.55183 5.52252 5.51535 - 5.50964 5.50890 5.50836 5.50828 5.50822 5.50822 - 8.37008 8.40544 8.31335 8.13546 7.90961 7.67372 - 7.43844 7.21069 6.99799 6.80033 6.61723 6.44655 - 6.28795 6.13988 6.00204 5.87254 5.75013 5.63637 - 5.53355 5.48658 5.44139 5.40678 5.37200 5.36352 - 5.35675 5.35588 5.35523 5.35513 5.35506 5.35505 - 9.11748 8.85106 8.57246 8.30155 8.03801 7.78178 - 7.53288 7.29144 7.05767 6.83186 6.61623 6.41050 - 6.21652 6.03386 5.86397 5.70858 5.56897 5.44331 - 5.33425 5.29153 5.26130 5.24075 5.16954 5.13542 - 5.14346 5.14922 5.14657 5.14472 5.14806 5.14588 - 9.74119 9.36913 8.98558 8.61746 8.26389 7.92427 - 7.59861 7.28717 6.98878 6.70555 6.43905 6.18846 - 5.95608 5.74170 5.54626 5.37133 5.21729 5.07878 - 4.95426 4.90189 4.85969 4.82692 4.74141 4.70550 - 4.71979 4.72674 4.72290 4.72062 4.72414 4.72202 - 9.93625 9.71144 9.32584 8.86235 8.38071 7.93264 - 7.52470 7.15552 6.82150 6.51859 6.23948 5.97686 - 5.73446 5.51282 5.30828 5.11479 4.92877 4.75624 - 4.60066 4.52741 4.45849 4.40944 4.36716 4.35700 - 4.34905 4.34806 4.34730 4.34718 4.34713 4.34713 - 10.24916 9.93638 9.46690 8.93173 8.39171 7.89805 - 7.45449 7.05605 6.69709 6.37175 6.07208 5.78956 - 5.52769 5.28821 5.06650 4.85687 4.65571 4.46727 - 4.29506 4.21491 4.14092 4.08956 4.04582 4.03567 - 4.02783 4.02685 4.02611 4.02599 4.02594 4.02593 - 10.66382 10.05123 9.44365 8.88012 8.35607 7.86900 - 7.41660 6.99609 6.60655 6.24819 5.92029 5.61751 - 5.33788 5.08106 4.84419 4.62684 4.42623 4.23145 - 4.03547 3.94262 3.86344 3.81467 3.76960 3.75995 - 3.75179 3.75084 3.75013 3.74995 3.75010 3.74996 - 10.99694 10.26865 9.55892 8.90996 8.31427 7.76770 - 7.26643 6.80565 6.38361 6.00100 5.65313 5.33321 - 5.03641 4.76182 4.50610 4.26763 4.04358 3.82445 - 3.60566 3.50319 3.41758 3.36648 3.31846 3.30772 - 3.29983 3.29902 3.29828 3.29812 3.29815 3.29806 - 11.22604 10.40428 9.61502 8.90080 8.25176 7.66136 - 7.12427 6.63540 6.19140 5.79250 5.43164 5.10053 - 4.79242 4.50534 4.23688 3.98392 3.74360 3.50750 - 3.27244 3.16245 3.07035 3.01492 2.96304 2.95164 - 2.94339 2.94254 2.94177 2.94162 2.94159 2.94152 - 11.52666 10.60274 9.67284 8.81089 8.03979 7.37312 - 6.79403 6.28477 5.82953 5.41772 5.03764 4.68024 - 4.34387 4.02945 3.73738 3.46107 3.19705 2.94238 - 2.69457 2.57516 2.46603 2.39178 2.33146 2.31861 - 2.30886 2.30765 2.30676 2.30663 2.30655 2.30651 - 11.84936 10.64379 9.57925 8.66528 7.87295 7.18170 - 6.57342 6.03399 5.55435 5.12440 4.73397 4.37324 - 4.03235 3.70684 3.40066 3.11422 2.84424 2.58243 - 2.32298 2.19616 2.07570 1.98960 1.92270 1.90823 - 1.89658 1.89525 1.89417 1.89399 1.89393 1.89390 - 12.23715 10.76190 9.53503 8.51269 7.64612 6.90637 - 6.27214 5.71746 5.22311 4.77827 4.37269 3.99737 - 3.64355 3.30673 2.98968 2.69667 2.42220 2.15447 - 1.88583 1.75269 1.62451 1.53001 1.45123 1.43335 - 1.41901 1.41735 1.41596 1.41576 1.41566 1.41564 - 12.54757 10.87442 9.55230 8.47071 7.56538 6.79374 - 6.13603 5.56511 5.05713 4.59900 4.17961 3.79075 - 3.42772 3.08739 2.76883 2.47167 2.19227 1.91990 - 1.64886 1.51419 1.38355 1.28480 1.19631 1.17605 - 1.15980 1.15757 1.15603 1.15588 1.15565 1.15566 - 12.84235 11.00971 9.61612 8.48747 7.55404 6.76267 - 6.08933 5.50451 4.98113 4.50752 4.07704 3.68247 - 3.31505 2.96909 2.64399 2.34031 2.05753 1.78442 - 1.51099 1.37341 1.23931 1.13669 1.04099 1.01812 - 1.00002 0.99769 0.99597 0.99573 0.99558 0.99550 - 13.10492 11.14876 9.70554 8.54154 7.58561 6.77862 - 6.09101 5.49279 4.95683 4.47182 4.03218 3.63093 - 3.25809 2.90705 2.57683 2.26751 1.97904 1.70330 - 1.42714 1.28742 1.14958 1.04211 0.93969 0.91484 - 0.89508 0.89253 0.89065 0.89039 0.89022 0.89012 - 13.54525 11.41859 9.91132 8.69716 7.70635 6.87689 - 6.16904 5.55112 4.99693 4.49563 4.04151 3.62748 - 3.24351 2.88261 2.54278 2.22242 1.92048 1.63438 - 1.34980 1.20448 1.05830 0.94108 0.82544 0.79669 - 0.77365 0.77067 0.76846 0.76815 0.76795 0.76783 - 13.89748 11.66394 10.11972 8.87404 7.86074 7.01507 - 6.29330 5.66242 5.09700 4.58556 4.12083 3.69529 - 3.30046 2.93000 2.58073 2.24931 1.93331 1.63198 - 1.33553 1.18324 1.02768 0.90017 0.77071 0.73793 - 0.71155 0.70812 0.70558 0.70523 0.70500 0.70488 - 14.52024 12.18280 10.59696 9.29584 8.24605 7.37275 - 6.63330 5.98883 5.41035 4.88504 4.40467 3.96097 - 3.54503 3.15059 2.77556 2.41782 2.07361 1.73594 - 1.39982 1.22647 1.04349 0.88759 0.72306 0.68012 - 0.64578 0.64158 0.63802 0.63760 0.63721 0.63721 - 14.94955 12.53411 10.94576 9.64615 8.60137 7.72116 - 6.96969 6.31155 5.72038 5.18334 4.69170 4.23650 - 3.80789 3.39880 3.00677 2.62906 2.26067 1.89179 - 1.51347 1.31642 1.10267 0.91613 0.71695 0.66469 - 0.62253 0.61736 0.61311 0.61258 0.61209 0.61205 - 15.48377 12.99087 11.43662 10.18117 9.15809 8.28395 - 7.52788 6.85907 6.25412 5.70171 5.19418 4.72357 - 4.28102 3.85887 3.45148 3.05103 2.64725 2.22489 - 1.76615 1.51679 1.24558 1.00323 0.73489 0.66202 - 0.60479 0.59831 0.59329 0.59254 0.59187 0.59078 - 15.66207 13.25243 11.81134 10.62770 9.62128 8.73596 - 7.95482 7.26119 6.64298 6.08848 5.58620 5.12358 - 4.68565 4.26075 3.84340 3.42614 2.99648 2.53149 - 2.00472 1.70992 1.38855 1.10132 0.76540 0.66773 - 0.59694 0.58981 0.58385 0.58277 0.58197 0.57964 - 15.86082 13.42193 12.03344 10.89542 9.91645 9.05017 - 8.28172 7.59592 6.98181 6.42862 5.92570 5.46109 - 5.02026 4.59142 4.16829 3.74186 3.29672 2.80374 - 2.22731 1.89514 1.52363 1.19141 0.79703 0.68047 - 0.59293 0.58379 0.57721 0.57617 0.57480 0.57180 - 15.99108 13.53287 12.19822 11.09811 10.14535 9.29795 - 8.54324 7.86703 7.25935 6.71016 6.20941 5.74567 - 5.30473 4.87475 4.44881 4.01674 3.56068 3.04646 - 2.43030 2.06709 1.65295 1.27820 0.82988 0.69541 - 0.59084 0.57944 0.57205 0.57108 0.56919 0.56576 - 16.14195 13.66359 12.42536 11.38591 10.47930 9.66682 - 8.93898 8.28323 7.69099 7.15331 6.66109 6.20358 - 5.76707 5.33961 4.91346 4.47671 4.00789 3.46492 - 2.78998 2.37825 1.89408 1.44240 0.89629 0.72848 - 0.59038 0.57410 0.56439 0.56349 0.56087 0.55702 - 16.21729 13.73483 12.57187 11.58051 10.71171 9.92938 - 9.22575 8.58955 8.01321 7.48855 7.00707 6.55854 - 6.12955 5.70810 5.28590 4.84988 4.37603 3.81637 - 3.10154 2.65400 2.11505 1.59671 0.96201 0.76348 - 0.59305 0.57166 0.55887 0.55794 0.55491 0.55099 - 16.27922 13.81485 12.77137 11.86679 11.06653 10.34128 - 9.68554 9.09021 8.54913 8.05540 7.60148 7.17789 - 6.77162 6.37054 5.96578 5.54266 5.07344 4.50065 - 3.73344 3.23010 2.59637 1.95313 1.12021 0.85301 - 0.60664 0.57235 0.54986 0.54845 0.54534 0.54191 - 16.28569 13.84011 12.86829 12.02059 11.26603 10.58049 - 9.95935 9.39489 8.88180 8.41389 7.98426 7.58384 - 7.19987 6.82017 6.43575 6.03132 5.57728 5.01082 - 4.22647 3.69426 3.00183 2.26930 1.26830 0.94070 - 0.62461 0.57796 0.54470 0.54240 0.53960 0.53685 - 16.27206 13.84544 12.95943 12.18036 11.48272 10.84824 - 10.27317 9.75137 9.27840 8.84903 8.45714 8.09429 - 7.74804 7.40644 7.06073 6.69554 6.27993 5.74574 - 4.96942 4.41591 3.65988 2.80919 1.53717 1.10589 - 0.66462 0.59524 0.54012 0.53542 0.53310 0.53137 - 16.23727 13.83843 13.00971 12.27447 11.61210 11.00758 - 10.45787 9.95811 9.50477 9.09429 8.72280 8.38496 - 8.07261 7.77553 7.47989 7.15891 6.77355 6.26337 - 5.50772 4.95619 4.18086 3.26356 1.78425 1.26069 - 0.70481 0.61370 0.53925 0.53367 0.52990 0.52844 - 16.20467 13.83178 13.03768 12.32904 11.68849 11.10360 - 10.57205 10.09001 9.65494 9.26368 8.91266 8.59677 - 8.30794 8.03631 7.76910 7.48072 7.13213 6.65899 - 5.93279 5.38796 4.60440 3.64828 2.01821 1.40144 - 0.74508 0.63519 0.54053 0.53206 0.52788 0.52663 - 16.17337 13.82787 13.05691 12.36653 11.74118 11.17039 - 10.65216 10.18340 9.76212 9.38557 9.05036 8.75159 - 8.48138 8.23027 7.98648 7.72579 7.40976 6.97194 - 6.27856 5.74516 4.96188 3.98147 2.23433 1.53511 - 0.78438 0.65682 0.54296 0.53153 0.52656 0.52540 - 16.12170 13.82673 13.08450 12.41725 11.81157 11.25948 - 10.75933 10.30890 9.90685 9.55083 9.23798 8.96382 - 8.72099 8.50088 8.29343 8.07673 7.81425 7.43877 - 6.81149 6.30699 5.53784 4.53466 2.62104 1.78719 - 0.85985 0.69948 0.54971 0.53237 0.52501 0.52384 - 16.08699 13.83136 13.10598 12.45262 11.85899 11.31857 - 10.83008 10.39144 10.00175 9.65906 9.36085 9.10316 - 8.87927 8.68143 8.50079 8.31712 8.09591 7.77175 - 7.20568 6.73232 5.98605 4.97944 2.95836 2.02114 - 0.93157 0.74090 0.55778 0.53467 0.52418 0.52288 - 16.02686 13.84712 13.14417 12.50857 11.93104 11.40690 - 10.93450 10.51249 10.14020 9.81630 9.53907 9.30567 - 9.11083 8.94854 8.81199 8.68352 8.53292 8.30269 - 7.86188 7.46103 6.78203 5.80348 3.64983 2.53450 - 1.09742 0.83874 0.58015 0.54352 0.52351 0.52158 - 15.93977 13.85873 13.16728 12.54060 11.97109 11.45523 - 10.99114 10.57780 10.21474 9.90092 9.63518 9.41540 - 9.23729 9.09608 8.98626 8.89183 8.78605 8.61897 - 8.27046 7.92930 7.31590 6.38459 4.19250 2.96594 - 1.24875 0.92992 0.60337 0.55438 0.52370 0.52093 - 15.70393 13.86845 13.18966 12.57285 12.01217 11.50469 - 11.04918 10.64491 10.29191 9.98946 9.73681 9.53261 - 9.37353 9.25612 9.17661 9.12167 9.06951 8.98086 - 8.75484 8.50127 7.99921 7.17044 5.00612 3.65867 - 1.52152 1.09801 0.64931 0.57797 0.52515 0.52027 - 15.49932 13.87110 13.19945 12.58819 12.03222 11.52919 - 11.07808 10.67864 10.33113 10.03501 9.78977 9.59436 - 9.44588 9.34149 9.27864 9.24591 9.22494 9.18329 - 9.03479 8.84161 8.42540 7.68882 5.60146 4.20133 - 1.76463 1.25143 0.69347 0.60192 0.52768 0.51994 - 15.35004 13.87171 13.20459 12.59692 12.04397 11.54371 - 11.09554 10.69913 10.35509 10.06299 9.82244 9.63262 - 9.49084 9.39465 9.34236 9.32395 9.32354 9.31342 - 9.21867 9.06944 8.71972 8.06114 6.06393 4.64475 - 1.98528 1.39361 0.73582 0.62552 0.53095 0.51974 - 15.24407 13.87562 13.21200 12.60375 12.04948 11.55004 - 11.10437 10.71167 10.37150 10.08329 9.84666 9.66076 - 9.52307 9.43145 9.38520 9.37627 9.39138 9.40598 - 9.35024 9.23202 8.93608 8.34529 6.43254 5.01977 - 2.19724 1.52610 0.77697 0.64828 0.53500 0.51961 - 15.11320 13.87555 13.21585 12.61077 12.05942 11.56276 - 11.11995 10.73031 10.39335 10.10873 9.87613 9.69494 - 9.56301 9.47866 9.44201 9.44635 9.48091 9.52636 - 9.52497 9.45309 9.23386 8.74608 7.00097 5.61810 - 2.59539 1.77020 0.85454 0.69282 0.54359 0.51944 - 15.03128 13.87485 13.21733 12.61458 12.06571 11.57101 - 11.12996 10.74205 10.40693 10.12446 9.89434 9.71605 - 9.58768 9.50782 9.47714 9.48979 9.53660 9.60194 - 9.63635 9.59565 9.42987 9.01913 7.42120 6.08284 - 2.94205 1.99075 0.92749 0.73534 0.55285 0.51934 - 14.90716 13.87374 13.21904 12.61982 12.07447 11.58267 - 11.14388 10.75807 10.42539 10.14583 9.91920 9.74496 - 9.62146 9.54778 9.52527 9.54946 9.61331 9.70678 - 9.79329 9.79928 9.71624 9.43357 8.12413 6.90770 - 3.65419 2.48468 1.09485 0.83469 0.57722 0.51921 - 14.83708 13.87389 13.22039 12.62235 12.07838 11.58781 - 11.15045 10.76621 10.43545 10.15779 9.93247 9.75909 - 9.63742 9.56784 9.55123 9.58161 9.65177 9.75809 - 9.88003 9.91785 9.87041 9.63757 8.57404 7.52832 - 4.18478 2.89640 1.24828 0.93407 0.60263 0.51914 - 14.76065 13.87500 13.22342 12.62629 12.08290 11.59308 - 11.15665 10.77338 10.44360 10.16732 9.94450 9.77473 - 9.65652 9.58954 9.57584 9.61217 9.69400 9.81719 - 9.96145 10.02174 10.03835 9.92584 9.09951 8.16776 - 5.04155 3.63059 1.51866 1.09517 0.64965 0.51907 - 14.72081 13.87538 13.22455 12.62782 12.08457 11.59527 - 11.15947 10.77697 10.44803 10.17267 9.95081 9.78215 - 9.66531 9.60015 9.58885 9.62833 9.71487 9.84577 - 10.00546 10.08070 10.12522 10.06420 9.41267 8.60840 - 5.64804 4.18502 1.76037 1.24912 0.69480 0.51904 - 14.69591 13.87528 13.22492 12.62831 12.08546 11.59653 - 11.16112 10.77917 10.45078 10.17599 9.95473 9.78668 - 9.67065 9.60658 9.59680 9.63828 9.72778 9.86351 - 10.03281 10.11732 10.17913 10.15087 9.61932 8.91060 - 6.11299 4.63393 2.00777 1.39252 0.73768 0.51902 - 14.67844 13.87524 13.22496 12.62875 12.08615 11.59748 - 11.16242 10.78073 10.45268 10.17824 9.95734 9.78973 - 9.67424 9.61091 9.60213 9.64498 9.73651 9.87556 - 10.05136 10.14219 10.21579 10.21016 9.76639 9.13273 - 6.48671 5.01227 2.25303 1.52705 0.77860 0.51901 - 14.65519 13.87515 13.22552 12.62972 12.08750 11.59920 - 11.16440 10.78299 10.45517 10.18102 9.96053 9.79352 - 9.67879 9.61635 9.60873 9.65325 9.74740 9.89065 - 10.07458 10.17350 10.26225 10.28595 9.96301 9.44099 - 7.05779 5.62074 2.67846 1.82920 0.85574 0.51899 - 14.64149 13.87544 13.22625 12.63071 12.08884 11.60068 - 11.16602 10.78484 10.45755 10.18384 9.96313 9.79518 - 9.68001 9.61856 9.61292 9.65923 9.75391 9.89797 - 10.08797 10.19466 10.29282 10.32557 10.07644 9.67065 - 7.48788 6.08040 3.03574 2.09756 0.92571 0.51898 - 3.31702 3.38293 3.44157 3.49374 3.53933 3.57849 - 3.61192 3.64107 3.66798 3.69331 3.71755 3.74144 - 3.76666 3.79438 3.82371 3.85205 3.87688 3.89862 - 3.91746 3.92541 3.93280 3.93844 3.94463 3.94618 - 3.94734 3.94748 3.94761 3.94762 3.94764 3.94766 - 3.98728 4.05260 4.10738 4.15304 4.18960 4.21752 - 4.23797 4.25320 4.26613 4.27756 4.28790 4.29749 - 4.30729 4.31806 4.32944 4.34044 4.35013 4.35899 - 4.36745 4.37132 4.37473 4.37638 4.37524 4.37487 - 4.37464 4.37459 4.37454 4.37457 4.37455 4.37454 - 4.49463 4.56465 4.61979 4.66198 4.69139 4.70879 - 4.71601 4.71628 4.71379 4.70967 4.70444 4.69861 - 4.69320 4.68909 4.68607 4.68328 4.68004 4.67712 - 4.67538 4.67471 4.67315 4.67039 4.66512 4.66370 - 4.66261 4.66245 4.66231 4.66231 4.66230 4.66228 - 5.23830 5.33149 5.38859 5.41693 5.42380 5.41749 - 5.40074 5.37620 5.34726 5.31551 5.28258 5.24991 - 5.21795 5.18749 5.15905 5.13334 5.11078 5.09049 - 5.07090 5.06086 5.05022 5.04099 5.03048 5.02770 - 5.02554 5.02526 5.02505 5.02502 5.02501 5.02499 - 5.78258 5.88634 5.94156 5.95833 5.94685 5.91870 - 5.87782 5.82798 5.77389 5.71758 5.66100 5.60603 - 5.55323 5.50350 5.45729 5.41480 5.37605 5.34051 - 5.30672 5.28977 5.27236 5.25820 5.24392 5.24037 - 5.23747 5.23709 5.23682 5.23677 5.23675 5.23675 - 6.20836 6.31768 6.36754 6.37076 6.34033 6.29085 - 6.22742 6.15471 6.07855 6.00131 5.92508 5.85195 - 5.78235 5.71716 5.65669 5.60062 5.54861 5.50048 - 5.45510 5.43268 5.41006 5.39217 5.37487 5.37066 - 5.36718 5.36671 5.36639 5.36635 5.36630 5.36633 - 6.55528 6.66634 6.70886 6.69789 6.64843 6.57741 - 6.49150 6.39725 6.30237 6.20879 6.11689 6.02800 - 5.94373 5.86578 5.79405 5.72691 5.66317 5.60431 - 5.54994 5.52289 5.49599 5.47525 5.45547 5.45054 - 5.44661 5.44611 5.44573 5.44567 5.44565 5.44566 - 7.09853 7.20379 7.22412 7.18007 7.09182 6.98153 - 6.85760 6.72774 6.60076 6.47856 6.36109 6.24902 - 6.14347 6.04548 5.95479 5.86950 5.78823 5.71260 - 5.64308 5.60964 5.57691 5.55186 5.52754 5.52156 - 5.51680 5.51619 5.51573 5.51565 5.51562 5.51563 - 7.51220 7.60433 7.59798 7.51930 7.39344 7.24731 - 7.09046 6.93108 6.77826 6.63357 6.49662 6.36722 - 6.24575 6.13236 6.02682 5.92738 5.83276 5.74426 - 5.66312 5.62514 5.58832 5.56012 5.53204 5.52517 - 5.51971 5.51900 5.51848 5.51840 5.51834 5.51835 - 8.23941 8.28538 8.20814 8.04676 7.83705 7.61524 - 7.39235 7.17614 6.97504 6.78885 6.61627 6.45472 - 6.30390 6.16250 6.03022 5.90531 5.78653 5.67510 - 5.57357 5.52731 5.48282 5.44867 5.41399 5.40555 - 5.39882 5.39794 5.39728 5.39719 5.39713 5.39712 - 8.73212 8.72610 8.58074 8.34642 8.06691 7.78483 - 7.51150 7.25351 7.01741 6.80158 6.60250 6.41577 - 6.24236 6.08077 5.93020 5.78782 5.65177 5.52463 - 5.40959 5.35673 5.30575 5.26683 5.22843 5.21898 - 5.21147 5.21050 5.20977 5.20967 5.20961 5.20960 - 9.38771 9.27921 9.01440 8.66140 8.27433 7.90268 - 7.55671 7.24008 6.95438 6.69638 6.45789 6.23241 - 6.02396 5.83290 5.65679 5.48999 5.32905 5.17963 - 5.04528 4.98175 4.92037 4.87452 4.83250 4.82205 - 4.81377 4.81272 4.81193 4.81179 4.81175 4.81176 - 9.82182 9.61901 9.25523 8.81106 8.34591 7.91175 - 7.51632 7.15974 6.83979 6.55121 6.28432 6.03110 - 5.79694 5.58378 5.38784 5.20235 5.02310 4.85622 - 4.70531 4.63376 4.56550 4.51579 4.47184 4.46110 - 4.45263 4.45158 4.45076 4.45063 4.45057 4.45059 - 10.13951 9.85118 9.40416 8.88786 8.36365 7.88374 - 7.45275 7.06675 6.72086 6.40838 6.11964 5.84584 - 5.59194 5.36082 5.14781 4.94655 4.75282 4.57111 - 4.40501 4.32738 4.25477 4.20318 4.15792 4.14721 - 4.13884 4.13778 4.13699 4.13688 4.13682 4.13681 - 10.56207 9.97143 9.38494 8.84021 8.33296 7.86093 - 7.42204 7.01378 6.63532 6.28696 5.96809 5.67376 - 5.40220 5.15318 4.92413 4.71474 4.52231 4.33560 - 4.14693 4.05710 3.97992 3.93163 3.88555 3.87513 - 3.86659 3.86562 3.86484 3.86464 3.86478 3.86464 - 10.90449 10.19943 9.51136 8.88103 8.30145 7.76882 - 7.27964 6.82948 6.41677 6.04220 5.70145 5.38820 - 5.09798 4.82995 4.58112 4.35011 4.13419 3.92376 - 3.71386 3.61557 3.53325 3.48371 3.43564 3.42427 - 3.41620 3.41541 3.41459 3.41443 3.41445 3.41435 - 11.14043 10.34326 9.57599 8.88021 8.24657 7.66911 - 7.14291 6.66324 6.22705 5.83455 5.47919 5.15325 - 4.85037 4.56879 4.30630 4.06012 3.82754 3.60013 - 3.37452 3.26928 3.18126 3.12825 3.07725 3.06543 - 3.05723 3.05643 3.05562 3.05546 3.05542 3.05534 - 11.50286 10.51605 9.60073 8.78985 8.06785 7.42215 - 6.84238 6.32274 5.85835 5.44291 5.06775 4.72266 - 4.39779 4.08887 3.79838 3.52441 3.26634 3.01867 - 2.77910 2.66562 2.56149 2.49003 2.43249 2.42024 - 2.41080 2.40973 2.40883 2.40870 2.40861 2.40858 - 11.76847 10.60148 9.56419 8.66916 7.88959 7.20659 - 6.60350 6.06731 5.58965 5.16104 4.77188 4.41298 - 4.07503 3.75365 3.45203 3.16978 2.90353 2.64648 - 2.39423 2.27194 2.15621 2.07401 2.01088 1.99731 - 1.98639 1.98515 1.98415 1.98397 1.98392 1.98390 - 12.15334 10.72049 9.52054 8.51608 7.66122 6.92878 - 6.29860 5.74610 5.25294 4.80887 4.40407 4.03005 - 3.67841 3.34467 3.03093 2.74041 2.46771 2.20261 - 1.93889 1.80925 1.68529 1.59492 1.52089 1.50429 - 1.49098 1.48944 1.48817 1.48798 1.48789 1.48789 - 12.46455 10.82782 9.52849 8.46419 7.57128 6.80779 - 6.15469 5.58631 5.08003 4.62333 4.20557 3.81879 - 3.45800 3.11991 2.80340 2.50778 2.22953 1.95898 - 1.69143 1.55950 1.43259 1.33787 1.25438 1.23553 - 1.22041 1.21833 1.21691 1.21677 1.21655 1.21657 - 12.74593 10.96073 9.59047 8.47606 7.55080 6.76439 - 6.09445 5.51370 4.99659 4.52940 4.10219 3.70738 - 3.33982 2.99584 2.67379 2.37236 2.09003 1.81696 - 1.54624 1.41204 1.28151 1.18199 1.09105 1.06994 - 1.05311 1.05081 1.04921 1.04905 1.04881 1.04878 - 12.99663 11.09847 9.67768 8.52404 7.57253 6.76923 - 6.08598 5.49411 4.96716 4.49085 4.05530 3.65321 - 3.27935 2.92987 2.60266 2.29579 2.00801 1.73213 - 1.45803 1.32122 1.18664 1.08221 0.98448 0.96135 - 0.94291 0.94041 0.93865 0.93846 0.93821 0.93814 - 13.41466 11.38605 9.89691 8.67329 7.66970 6.84014 - 6.14226 5.53905 4.99963 4.51051 4.06365 3.65155 - 3.26628 2.90292 2.56116 2.24188 1.94398 1.65981 - 1.37557 1.23226 1.08882 0.97464 0.86417 0.83686 - 0.81503 0.81242 0.81022 0.80995 0.80971 0.80962 - 13.75073 11.62302 10.09988 8.84722 7.82294 6.97834 - 6.26696 5.65010 5.09739 4.59593 4.13780 3.71527 - 3.32022 2.94736 2.59575 2.26523 1.95370 1.65474 - 1.35822 1.20755 1.05456 0.93020 0.80611 0.77476 - 0.74967 0.74664 0.74410 0.74379 0.74351 0.74346 - 14.35722 12.09561 10.54166 9.26282 8.22650 7.36169 - 6.62746 5.98644 5.41061 4.88751 4.40908 3.96716 - 3.55297 3.16036 2.78726 2.43161 2.08958 1.75360 - 1.41853 1.24619 1.06559 0.91317 0.75445 0.71331 - 0.68041 0.67640 0.67300 0.67260 0.67222 0.67226 - 14.76289 12.43782 10.88759 9.61311 8.58258 7.71106 - 6.96438 6.30884 5.71917 5.18312 4.69227 4.23801 - 3.81088 3.40398 3.01455 2.63947 2.27340 1.90643 - 1.52970 1.33377 1.12245 0.93947 0.74655 0.69626 - 0.65571 0.65076 0.64667 0.64616 0.64570 0.64558 - 15.26974 12.88495 11.37434 10.14468 9.13507 8.26809 - 7.51509 6.84750 6.24361 5.69249 5.18654 4.71782 - 4.27750 3.85787 3.45320 3.05546 2.65429 2.23457 - 1.77886 1.53151 1.26320 1.02450 0.76208 0.69150 - 0.63651 0.63031 0.62542 0.62470 0.62418 0.62239 - 15.45830 13.14346 11.73501 10.57183 9.57883 8.70354 - 7.92970 7.24140 6.62695 6.07503 5.57454 5.11327 - 4.67673 4.25358 3.83842 3.42391 2.99767 2.53680 - 2.01505 1.72322 1.40512 1.12119 0.79074 0.69534 - 0.62748 0.62084 0.61503 0.61399 0.61351 0.60990 - 15.65423 13.31071 11.95109 10.83045 9.86339 9.00640 - 8.24521 7.56518 6.95563 6.40609 5.90614 5.44410 - 5.00572 4.57950 4.15923 3.73605 3.29469 2.80619 - 2.23528 1.90646 1.53875 1.20989 0.82075 0.70639 - 0.62236 0.61390 0.60762 0.60663 0.60570 0.60113 - 15.78320 13.42013 12.11036 11.02504 10.08275 9.24393 - 8.49633 7.82624 7.22383 6.67926 6.18264 5.72265 - 5.28526 4.85874 4.43633 4.00797 3.55603 3.04654 - 2.43618 2.07652 1.66653 1.29530 0.85206 0.71978 - 0.61924 0.60870 0.60180 0.60090 0.59952 0.59442 - 15.93261 13.54884 12.32822 11.29974 10.40111 9.59596 - 8.87491 8.22571 7.63981 7.10834 6.62213 6.17037 - 5.73925 5.31681 4.89537 4.46320 3.99905 3.46111 - 2.79219 2.38420 1.90458 1.45689 0.91576 0.75020 - 0.61699 0.60189 0.59311 0.59234 0.59027 0.58477 - 16.00639 13.61792 12.46769 11.48446 10.62203 9.84608 - 9.14893 8.51952 7.95021 7.43279 6.95864 6.51733 - 6.09514 5.67984 5.26329 4.83253 4.36378 3.80937 - 3.10060 2.65687 2.12265 1.60881 0.97920 0.78308 - 0.61818 0.59824 0.58684 0.58610 0.58359 0.57815 - 16.06233 13.69245 12.65594 11.75615 10.96025 10.24028 - 9.59059 9.00218 8.46879 7.98334 7.53816 7.12342 - 6.72558 6.33218 5.93435 5.51755 5.05416 4.48708 - 3.72612 3.22667 2.59798 1.95999 1.13333 0.86892 - 0.62902 0.59666 0.57665 0.57562 0.57278 0.56823 - 16.06180 13.71315 12.74684 11.90307 11.15246 10.47195 - 9.85667 9.29904 8.79354 8.33392 7.91309 7.52167 - 7.14638 6.77469 6.39758 5.99988 5.55209 4.99176 - 4.21406 3.68591 2.99881 2.27207 1.27867 0.95415 - 0.64505 0.60065 0.57076 0.56904 0.56627 0.56274 - 16.03651 13.71296 12.83301 12.05860 11.36554 10.73638 - 10.16702 9.65158 9.18549 8.76349 8.37928 8.02431 - 7.68572 7.35134 7.01246 6.65387 6.24480 5.71742 - 4.94884 4.40004 3.65001 2.80596 1.54401 1.11614 - 0.68243 0.61574 0.56525 0.56142 0.55890 0.55681 - 16.00813 13.70525 12.87618 12.14224 11.48357 10.88568 - 10.34506 9.85665 9.41652 9.02002 8.66152 8.33301 - 8.02222 7.71748 7.41070 7.08726 6.71648 6.22836 - 5.48985 4.94202 4.16508 3.24987 1.78845 1.26687 - 0.72194 0.63483 0.56386 0.55746 0.55502 0.55366 - 15.96088 13.69672 12.91045 12.20839 11.57403 10.99543 - 10.47024 9.99458 9.56584 9.18077 8.83549 8.52458 - 8.23938 7.96990 7.70466 7.42056 7.08030 6.61746 - 5.90144 5.36207 4.58530 3.63726 2.02090 1.40832 - 0.75955 0.65306 0.56447 0.55717 0.55323 0.55170 - 15.92745 13.69252 12.93088 12.24819 11.62988 11.06563 - 10.55366 10.09071 9.67473 9.30293 8.97192 8.67674 - 8.40944 8.16069 7.91933 7.66240 7.35264 6.92371 - 6.24192 5.71543 4.93984 3.96771 2.23514 1.54099 - 0.79779 0.67372 0.56637 0.55637 0.55174 0.55037 - 15.87516 13.69169 12.96043 12.30203 11.70406 11.15862 - 10.66433 10.21881 9.82071 9.46783 9.15746 8.88541 - 8.64477 8.42722 8.22264 8.00883 7.74972 7.38077 - 6.76628 6.27049 5.51063 4.51643 2.61868 1.79117 - 0.87167 0.71490 0.57218 0.55667 0.54999 0.54869 - 15.84226 13.69704 12.98288 12.33841 11.75223 11.21821 - 10.73507 10.30085 9.91461 9.57457 9.27838 9.02248 - 8.80060 8.60533 8.42752 8.24618 8.02694 7.70778 - 7.15401 6.68983 5.95393 4.95739 2.95329 2.02322 - 0.94220 0.75519 0.57943 0.55842 0.54905 0.54766 - 15.78899 13.71450 13.02120 12.39314 11.82198 11.30317 - 10.83521 10.41718 10.04828 9.72735 9.45275 9.22173 - 9.02918 8.86919 8.73477 8.60787 8.45853 8.23149 - 7.79953 7.40665 6.73918 5.77340 3.63916 2.53234 - 1.10599 0.85105 0.60010 0.56600 0.54821 0.54627 - 15.71025 13.72689 13.04343 12.42322 11.85921 11.34797 - 10.88812 10.47857 10.11916 9.80885 9.54641 9.32963 - 9.15407 9.01484 8.90651 8.81337 8.70910 8.54450 - 8.20173 7.86677 7.26469 6.34774 4.17737 2.96025 - 1.25594 0.94084 0.62201 0.57579 0.54826 0.54557 - 15.51398 13.74573 13.06456 12.44795 11.88992 11.38722 - 10.93772 10.54014 10.19364 9.89708 9.64901 9.44701 - 9.28611 9.16291 9.07845 9.03009 9.00099 8.92833 - 8.68660 8.42135 7.92865 7.12577 4.98313 3.64716 - 1.52627 1.10752 0.66639 0.59723 0.54947 0.54486 - 15.29719 13.74035 13.07558 12.46805 11.91496 11.41581 - 10.96944 10.57501 10.23240 9.94086 9.69940 9.50670 - 9.35971 9.25573 9.19270 9.16043 9.14159 9.10329 - 8.95671 8.76419 8.35527 7.63333 5.57319 4.18598 - 1.76814 1.25938 0.70913 0.61993 0.55161 0.54450 - 15.15838 13.73751 13.07703 12.47538 11.92806 11.43300 - 10.98952 10.59731 10.25686 9.96790 9.72997 9.54224 - 9.40211 9.30717 9.25591 9.23856 9.23943 9.23055 - 9.13721 8.98987 8.64538 7.99811 6.03142 4.62552 - 1.98858 1.40031 0.74994 0.64281 0.55437 0.54429 - 15.06161 13.73725 13.07998 12.48078 11.93570 11.44271 - 11.00139 10.61149 10.27339 9.98701 9.75205 9.56787 - 9.43215 9.34278 9.29881 9.29142 9.30666 9.32028 - 9.26639 9.15195 8.85850 8.27508 6.39986 4.99418 - 2.19911 1.53273 0.78983 0.66501 0.55771 0.54414 - 14.93918 13.73723 13.08384 12.48774 11.94541 11.45524 - 11.01682 10.62990 10.29490 10.01189 9.78079 9.60116 - 9.47115 9.38891 9.35434 9.35998 9.39432 9.43821 - 9.43855 9.37076 9.15237 8.66912 6.96284 5.58476 - 2.59323 1.77639 0.86603 0.70814 0.56530 0.54396 - 14.86146 13.73957 13.08838 12.49246 11.95006 11.46072 - 11.02412 10.63967 10.30757 10.02770 9.79989 9.62350 - 9.49673 9.41794 9.38786 9.40075 9.44767 9.51341 - 9.54926 9.50993 9.34621 8.94094 7.37045 6.05019 - 2.93778 1.99414 0.93815 0.74924 0.57424 0.54385 - 14.74509 13.74011 13.09181 12.49837 11.95824 11.47124 - 11.03675 10.65475 10.32537 10.04860 9.82424 9.65180 - 9.52967 9.45691 9.43484 9.45900 9.52251 9.61574 - 9.70328 9.71067 9.62938 9.35010 8.06167 6.86493 - 3.64433 2.48508 1.10348 0.84668 0.59698 0.54371 - 14.67895 13.74089 13.09403 12.50153 11.96225 11.47626 - 11.04297 10.66220 10.33425 10.05910 9.83659 9.66629 - 9.54662 9.47703 9.45913 9.48921 9.56144 9.66910 - 9.78423 9.81739 9.78354 9.58223 8.49573 7.40873 - 4.19514 2.92115 1.25403 0.93741 0.62038 0.54364 - 14.60827 13.74173 13.09633 12.50470 11.96618 11.48110 - 11.04893 10.66953 10.34303 10.06947 9.84883 9.68077 - 9.56374 9.49749 9.48400 9.52010 9.60135 9.72380 - 9.86758 9.92817 9.94636 9.83651 9.02009 8.10478 - 5.01983 3.61966 1.52401 1.10410 0.66620 0.54357 - 14.57129 13.74163 13.09704 12.50599 11.96810 11.48354 - 11.05198 10.67324 10.34741 10.07463 9.85488 9.68791 - 9.57228 9.50776 9.49659 9.53578 9.62170 9.75178 - 9.91051 9.98560 10.03137 9.97277 9.32839 8.53831 - 5.62063 4.16861 1.76440 1.25682 0.70995 0.54353 - 14.54817 13.74134 13.09700 12.50647 11.96915 11.48516 - 11.05398 10.67560 10.35019 10.07786 9.85862 9.69226 - 9.57743 9.51400 9.50429 9.54541 9.63426 9.76907 - 9.93717 10.02135 10.08402 10.05778 9.53237 8.83610 - 6.08098 4.61332 2.00978 1.39931 0.75173 0.54351 - 14.53196 13.74100 13.09694 12.50679 11.96983 11.48619 - 11.05535 10.67718 10.35205 10.08002 9.86113 9.69516 - 9.58088 9.51816 9.50946 9.55192 9.64273 9.78076 - 9.95528 10.04570 10.11978 10.11572 9.67768 9.05538 - 6.45074 4.98803 2.25128 1.53310 0.79176 0.54350 - 14.51015 13.74113 13.09759 12.50764 11.97095 11.48747 - 11.05689 10.67907 10.35433 10.08273 9.86430 9.69888 - 9.58523 9.52339 9.51585 9.55997 9.65325 9.79531 - 9.97787 10.07623 10.16494 10.18987 9.87301 9.35958 - 7.01495 5.59049 2.67100 1.83090 0.86748 0.54348 - 14.49617 13.74222 13.09942 12.50912 11.97178 11.48804 - 11.05748 10.67996 10.35553 10.08425 9.86620 9.70115 - 9.58792 9.52652 9.51958 9.56459 9.65929 9.80372 - 9.99096 10.09413 10.19219 10.23588 10.00002 9.56413 - 7.43135 6.05960 3.02642 2.08848 0.93870 0.54347 - 3.17376 3.23763 3.29490 3.34633 3.39181 3.43152 - 3.46609 3.49689 3.52580 3.55348 3.58039 3.60726 - 3.63565 3.66671 3.69955 3.73169 3.76056 3.78615 - 3.80814 3.81745 3.82650 3.83388 3.84223 3.84439 - 3.84606 3.84626 3.84643 3.84646 3.84648 3.84650 - 3.84608 3.89675 3.94281 3.98555 4.02459 4.05950 - 4.08990 4.11548 4.13600 4.15156 4.16281 4.17090 - 4.17848 4.18797 4.19989 4.21461 4.23229 4.25206 - 4.27178 4.27985 4.28367 4.28270 4.28417 4.28597 - 4.28551 4.28527 4.28533 4.28528 4.28553 4.28536 - 4.34009 4.40716 4.46131 4.50427 4.53606 4.55715 - 4.56883 4.57357 4.57463 4.57311 4.56986 4.56614 - 4.56422 4.56589 4.57039 4.57509 4.57776 4.58025 - 4.58471 4.58733 4.58877 4.58797 4.58437 4.58336 - 4.58258 4.58246 4.58236 4.58237 4.58236 4.58232 - 5.08832 5.16691 5.22349 5.26081 5.27919 5.27997 - 5.26598 5.24212 5.21459 5.18527 5.15512 5.12564 - 5.09891 5.07665 5.05822 5.04102 5.02306 5.00653 - 4.99406 4.98877 4.98143 4.97321 4.96462 4.96241 - 4.96048 4.96023 4.96005 4.96004 4.96004 4.96001 - 5.63381 5.73136 5.78781 5.81060 5.80625 5.78278 - 5.74476 5.69795 5.64931 5.60029 5.55074 5.50136 - 5.45369 5.40952 5.36925 5.33278 5.30004 5.27110 - 5.24427 5.23024 5.21550 5.20327 5.19079 5.18761 - 5.18502 5.18469 5.18444 5.18440 5.18438 5.18438 - 6.06289 6.16796 6.22085 6.23138 6.20841 6.16287 - 6.10133 6.03188 5.96389 5.89790 5.83111 5.76304 - 5.69718 5.63697 5.58250 5.53237 5.48560 5.44347 - 5.40485 5.38485 5.36447 5.34841 5.33296 5.32903 - 5.32588 5.32549 5.32519 5.32514 5.32511 5.32513 - 6.41358 6.52249 6.56889 6.56525 6.52318 6.45673 - 6.37397 6.28457 6.19935 6.11822 6.03656 5.95313 - 5.87256 5.79921 5.73286 5.67124 5.61269 5.55930 - 5.51052 5.48572 5.46090 5.44174 5.42365 5.41910 - 5.41544 5.41498 5.41464 5.41458 5.41457 5.41456 - 6.97492 7.04929 7.07226 7.05255 6.99291 6.89886 - 6.77945 6.64817 6.52063 6.40077 6.28922 6.18648 - 6.09171 6.00410 5.92235 5.84264 5.76254 5.68672 - 5.62134 5.59242 5.56180 5.53589 5.51354 5.50812 - 5.50346 5.50290 5.50246 5.50238 5.50237 5.50236 - 7.37937 7.47838 7.48063 7.41089 7.29352 7.15494 - 7.00578 6.85601 6.71627 6.58593 6.45995 6.33616 - 6.21845 6.10990 6.00993 5.91545 5.82421 5.73861 - 5.66054 5.62368 5.58790 5.56056 5.53348 5.52687 - 5.52161 5.52091 5.52040 5.52034 5.52030 5.52029 - 8.11349 8.17386 8.10873 7.95763 7.75847 7.54941 - 7.34071 7.13863 6.94995 6.77423 6.61015 6.45557 - 6.31104 6.17593 6.04958 5.92941 5.81354 5.70390 - 5.60369 5.55783 5.51360 5.47957 5.44507 5.43668 - 5.43002 5.42914 5.42849 5.42841 5.42834 5.42832 - 8.61134 8.62350 8.49248 8.27000 8.00338 7.73800 - 7.48296 7.24096 7.01483 6.80484 6.61187 6.43390 - 6.26955 6.11550 5.97097 5.83346 5.70126 5.57666 - 5.46260 5.40977 5.35857 5.31928 5.28044 5.27091 - 5.26332 5.26234 5.26160 5.26150 5.26143 5.26143 - 9.51065 9.17651 8.83077 8.49795 8.17736 7.86850 - 7.57152 7.28668 7.01310 6.75274 6.50709 6.27556 - 6.06041 5.86154 5.68004 5.51750 5.37422 5.24473 - 5.12670 5.07589 5.03327 4.99830 4.91035 4.87402 - 4.88765 4.89445 4.89048 4.88820 4.89165 4.88960 - 9.77433 9.47533 9.11896 8.74167 8.35019 7.95352 - 7.56321 7.19384 6.85855 6.56013 6.29654 6.06096 - 5.84742 5.64917 5.46292 5.28405 5.10983 4.94520 - 4.79735 4.73005 4.66249 4.60949 4.56480 4.55402 - 4.54496 4.54389 4.54302 4.54288 4.54284 4.54285 - 10.10249 9.71166 9.27253 8.82558 8.37639 7.93283 - 7.50466 7.10385 6.74193 6.42018 6.13600 5.88111 - 5.64830 5.43133 5.22668 5.03122 4.84311 4.66556 - 4.50416 4.43067 4.35926 4.30539 4.25925 4.24829 - 4.23931 4.23826 4.23740 4.23726 4.23721 4.23721 - 10.46557 9.89806 9.33327 8.80746 8.31668 7.85898 - 7.43250 7.03505 6.66602 6.32583 6.01409 5.72642 - 5.46144 5.21924 4.99749 4.79598 4.61187 4.43312 - 4.25080 4.16315 4.08714 4.03873 3.99157 3.98055 - 3.97155 3.97054 3.96968 3.96947 3.96964 3.96949 - 10.82186 10.13669 9.46752 8.85376 8.28880 7.76910 - 7.29137 6.85153 6.44810 6.08175 5.74843 5.44219 - 5.15873 4.89728 4.65507 4.43091 4.22215 4.01895 - 3.81595 3.72085 3.64128 3.59324 3.54455 3.53216 - 3.52382 3.52306 3.52216 3.52196 3.52198 3.52188 - 11.06809 10.28800 9.53741 8.85628 8.23572 7.67004 - 7.15449 6.68462 6.25743 5.87302 5.52509 5.20617 - 4.90996 4.63454 4.37790 4.13759 3.91109 3.69016 - 3.47161 3.37013 3.28584 3.23541 3.18443 3.17152 - 3.16325 3.16254 3.16162 3.16145 3.16139 3.16132 - 11.42916 10.46934 9.57447 8.77788 8.06577 7.42716 - 6.85321 6.33937 5.88183 5.47416 5.10717 4.76997 - 4.45146 4.14665 3.85880 3.58802 3.33499 3.09380 - 2.86176 2.75251 2.65274 2.58444 2.52818 2.51604 - 2.50675 2.50569 2.50479 2.50467 2.50457 2.50454 - 11.69655 10.55789 9.54089 8.65979 7.88971 7.21332 - 6.61535 6.08398 5.61163 5.18883 4.80574 4.45266 - 4.11942 3.80122 3.50186 3.22242 2.96072 2.70956 - 2.46425 2.34588 2.23422 2.15526 2.09479 2.08181 - 2.07136 2.07017 2.06921 2.06905 2.06900 2.06899 - 12.07520 10.67706 9.49973 8.51063 7.66628 6.94095 - 6.31547 5.76646 5.27639 4.83522 4.43333 4.06221 - 3.71336 3.38216 3.07073 2.78235 2.51217 2.25052 - 1.99167 1.86513 1.74472 1.65773 1.58764 1.57211 - 1.55964 1.55820 1.55702 1.55684 1.55676 1.55677 - 12.37855 10.79867 9.52019 8.46081 7.56936 6.81158 - 6.16643 5.60532 5.10341 4.64944 4.23509 3.85258 - 3.49411 3.15518 2.83667 2.54111 2.26636 1.99949 - 1.73427 1.60423 1.48042 1.38948 1.31071 1.29271 - 1.27847 1.27680 1.27540 1.27522 1.27508 1.27507 - 12.64917 10.93258 9.58439 8.47303 7.54709 6.76592 - 6.10456 5.53188 5.01943 4.55472 4.13006 3.73827 - 3.37194 3.02655 2.70233 2.40096 2.12184 1.85186 - 1.58268 1.44990 1.32215 1.22631 1.14021 1.12010 - 1.10419 1.10232 1.10074 1.10053 1.10037 1.10030 - 12.89248 11.06899 9.67058 8.51930 7.56627 6.76800 - 6.09363 5.51021 4.98802 4.51400 4.08063 3.68100 - 3.30784 2.95660 2.62713 2.32045 2.03609 1.76306 - 1.49006 1.35449 1.22243 1.12144 1.02869 1.00665 - 0.98914 0.98707 0.98533 0.98510 0.98493 0.98482 - 13.30284 11.32802 9.86575 8.66124 7.67024 6.84845 - 6.15499 5.55402 5.01555 4.52665 4.07976 3.66778 - 3.28332 2.92154 2.58182 2.26442 1.96785 1.68465 - 1.40183 1.25986 1.11882 1.00778 0.90207 0.87618 - 0.85552 0.85306 0.85099 0.85073 0.85051 0.85041 - 13.63261 11.56033 10.06270 8.82823 7.81579 6.97846 - 6.27141 5.65718 5.10628 4.60618 4.14918 3.72776 - 3.33401 2.96272 2.61288 2.28420 1.97438 1.67667 - 1.38128 1.23171 1.08099 0.95976 0.84061 0.81078 - 0.78692 0.78405 0.78165 0.78135 0.78108 0.78105 - 14.23155 12.02431 10.49167 9.22892 8.20328 7.34632 - 6.61798 5.98167 5.40980 4.89006 4.41446 3.97490 - 3.56254 3.17132 2.79950 2.44551 2.10556 1.77133 - 1.43728 1.26586 1.08742 0.93818 0.78480 0.74534 - 0.71376 0.70991 0.70666 0.70627 0.70591 0.70596 - 14.63542 12.36027 10.82735 9.56807 8.54921 7.68838 - 6.95096 6.30295 5.71858 5.18591 4.69705 4.24389 - 3.81747 3.41134 3.02304 2.64977 2.28617 1.92144 - 1.54618 1.35118 1.14202 0.96224 0.77487 0.72628 - 0.68720 0.68244 0.67849 0.67799 0.67756 0.67739 - 15.14461 12.78286 11.28678 10.08353 9.09972 8.25127 - 7.51000 6.84941 6.24923 5.69906 5.19152 4.71939 - 4.27537 3.85301 3.44725 3.05110 2.65533 2.24582 - 1.79803 1.54947 1.27949 1.04145 0.78610 0.71959 - 0.66649 0.65960 0.65505 0.65458 0.65377 0.65207 - 15.43908 13.06460 11.61278 10.44592 9.47732 8.64324 - 7.91462 7.26231 6.66330 6.10853 5.59309 5.11195 - 4.65953 4.22991 3.81639 3.40904 2.99332 2.54503 - 2.03409 1.74343 1.41981 1.13011 0.81013 0.72372 - 0.65595 0.64849 0.64333 0.64265 0.64186 0.63829 - 15.61679 13.22939 11.83144 10.70836 9.76559 8.94859 - 8.23093 7.58516 6.98939 6.43530 5.91866 5.43509 - 4.97965 4.54661 4.12854 3.71394 3.28530 2.81215 - 2.25432 1.92663 1.55161 1.21481 0.83726 0.73328 - 0.64972 0.64048 0.63502 0.63444 0.63320 0.62867 - 15.55289 13.30567 12.04136 10.98525 10.06204 9.23527 - 8.49405 7.82591 7.22199 6.67339 6.17122 5.70537 - 5.26344 4.83488 4.41301 3.98787 3.54172 3.04017 - 2.43924 2.08454 1.67900 1.31053 0.87060 0.74022 - 0.64471 0.63527 0.62872 0.62776 0.62694 0.62137 - 15.68680 13.42764 12.25366 11.25607 10.37775 9.58541 - 8.87087 8.22325 7.63503 7.09834 6.60516 6.14610 - 5.70933 5.28428 4.86345 4.43517 3.97803 3.44948 - 2.79133 2.38885 1.91416 1.46945 0.93129 0.76781 - 0.64087 0.62723 0.61918 0.61837 0.61692 0.61093 - 15.75215 13.49258 12.38802 11.43597 10.59427 9.83144 - 9.14102 8.51321 7.94139 7.41843 6.93683 6.48769 - 6.05941 5.64141 5.22565 4.79927 4.33831 3.79409 - 3.09673 2.65875 2.12966 1.61910 0.99242 0.79859 - 0.64084 0.62264 0.61236 0.61164 0.60971 0.60381 - 15.80097 13.56073 12.56573 11.69527 10.91928 10.21246 - 9.56991 8.98372 8.44851 7.95820 7.50618 7.08414 - 6.68072 6.28508 5.88862 5.47692 5.02217 4.46605 - 3.71700 3.22344 2.60004 1.96574 1.14279 0.88115 - 0.64952 0.61933 0.60141 0.60058 0.59809 0.59317 - 15.80068 13.57858 12.64885 11.83141 11.09930 10.43122 - 9.82324 9.26853 8.76235 8.29923 7.87306 7.47578 - 7.09609 6.72302 6.34784 5.95553 5.51648 4.96709 - 4.20125 3.67900 2.99723 2.27453 1.28593 0.96449 - 0.66406 0.62209 0.59512 0.59376 0.59111 0.58730 - 15.78314 13.57850 12.72622 11.97212 11.29401 10.67548 - 10.11323 9.60172 9.13689 8.71401 8.32749 7.96967 - 7.62918 7.29502 6.95879 6.60550 6.20448 5.68723 - 4.93003 4.38713 3.64280 2.80358 1.54882 1.12433 - 0.69941 0.63544 0.58902 0.58586 0.58319 0.58096 - 15.76501 13.57413 12.76560 12.04708 11.40014 10.81121 - 10.27715 9.79313 9.35556 8.96014 8.60163 8.27265 - 7.96191 7.65852 7.35470 7.03607 6.67224 6.19312 - 5.46544 4.92367 4.15312 3.24380 1.79162 1.27392 - 0.73750 0.65328 0.58715 0.58166 0.57901 0.57760 - 15.74509 13.57186 12.79089 12.09512 11.46833 10.89885 - 10.38375 9.91864 9.50026 9.12458 8.78671 8.47953 - 8.19184 7.91301 7.63590 7.34698 7.01667 6.57470 - 5.88264 5.35124 4.57264 3.61980 2.01753 1.41390 - 0.77578 0.67272 0.58741 0.57937 0.57650 0.57552 - 15.70274 13.56819 12.81753 12.14368 11.53280 10.97517 - 10.46893 10.01089 9.59905 9.23069 8.90252 8.60977 - 8.34474 8.09834 7.85966 7.60608 7.30097 6.87920 - 6.20840 5.68874 4.92037 3.95544 2.23589 1.54681 - 0.81108 0.69027 0.58885 0.58003 0.57562 0.57411 - 15.65804 13.57021 12.84677 12.19454 11.60193 11.06143 - 10.57186 10.13096 9.73750 9.38929 9.08340 8.81553 - 8.57831 8.36325 8.16048 7.94845 7.69211 7.32862 - 6.72460 6.23646 5.48581 4.50038 2.61658 1.79585 - 0.88346 0.73001 0.59386 0.57993 0.57370 0.57232 - 15.62861 13.57631 12.86888 12.22965 11.64820 11.11872 - 10.63985 10.21006 9.82845 9.49318 9.20176 8.95031 - 8.73206 8.53930 8.36308 8.18302 7.96569 7.65086 - 7.10644 6.64985 5.92416 4.93788 2.94885 2.02612 - 0.95280 0.76923 0.60039 0.58123 0.57266 0.57122 - 15.57744 13.59289 12.90637 12.28398 11.71769 11.20357 - 10.73997 10.32605 9.96116 9.64409 9.37315 9.14552 - 8.95591 8.79829 8.66574 8.54039 8.39267 8.16843 - 7.74281 7.35619 6.69918 5.74624 3.63016 2.53020 - 1.11439 0.86318 0.61956 0.58774 0.57166 0.56974 - 15.50057 13.60318 12.92722 12.31340 11.75494 11.24891 - 10.79353 10.38838 10.03307 9.72665 9.46771 9.25389 - 9.08037 8.94206 8.83390 8.74103 8.63776 8.47444 - 8.13531 7.80738 7.22256 6.32747 4.16407 2.94338 - 1.26306 0.95459 0.64096 0.59493 0.57182 0.56900 - 15.31627 13.62093 12.94777 12.33815 11.78593 11.28841 - 10.84348 10.44974 10.10644 9.81255 9.56667 9.36648 - 9.20719 9.08550 9.00258 8.95584 8.92845 8.85768 - 8.61901 8.35742 7.87284 7.08236 4.96277 3.63662 - 1.53130 1.11656 0.68291 0.61634 0.57257 0.56825 - 15.11339 13.61272 12.95507 12.35618 11.81125 11.31830 - 10.87634 10.48492 10.14425 9.85419 9.61406 9.42291 - 9.27787 9.17631 9.11593 9.08579 9.06790 9.02947 - 8.88538 8.69738 8.29361 7.58056 5.54923 4.17187 - 1.77283 1.26679 0.72379 0.63827 0.57430 0.56787 - 14.98210 13.61463 12.96085 12.36375 11.82015 11.32924 - 10.89023 10.50283 10.16725 9.88272 9.64769 9.46093 - 9.32104 9.22663 9.17617 9.15977 9.16222 9.15792 - 9.06717 8.91598 8.57276 7.94662 6.02451 4.60320 - 1.98302 1.40532 0.76523 0.65916 0.57955 0.56765 - 14.89069 13.61491 12.96444 12.36944 11.82765 11.33846 - 10.90128 10.51582 10.18220 9.90010 9.66855 9.48651 - 9.35178 9.26251 9.21813 9.21083 9.22778 9.24492 - 9.19335 9.07866 8.79007 8.21624 6.36199 4.97851 - 2.20106 1.53784 0.80337 0.68070 0.58014 0.56749 - 14.77664 13.61563 12.96863 12.37637 11.83708 11.35036 - 10.91593 10.53332 10.20287 9.92419 9.69653 9.51898 - 9.38982 9.30754 9.27236 9.27780 9.31346 9.36051 - 9.36264 9.29420 9.08055 8.60545 6.91504 5.56593 - 2.59275 1.77917 0.87804 0.72253 0.58718 0.56730 - 14.70511 13.61650 12.97153 12.38082 11.84302 11.35800 - 10.92526 10.54443 10.21580 9.93902 9.71367 9.53894 - 9.41329 9.33534 9.30584 9.31919 9.36654 9.43272 - 9.47012 9.43280 9.27195 8.87127 7.32275 6.02057 - 2.93411 1.99753 0.94873 0.76293 0.59500 0.56718 - 14.59655 13.61799 12.97562 12.38702 11.85125 11.36843 - 10.93805 10.55966 10.23335 9.95910 9.73684 9.56611 - 9.44525 9.37331 9.35162 9.37587 9.43944 9.53259 - 9.62082 9.62973 9.55115 9.27573 8.00338 6.82438 - 3.63535 2.48559 1.11203 0.85850 0.61630 0.56703 - 14.53556 13.61620 12.97521 12.38952 11.85679 11.37606 - 10.94657 10.56864 10.24260 9.96876 9.74741 9.57843 - 9.46025 9.39224 9.37592 9.40698 9.47893 9.58348 - 9.69812 9.73596 9.70304 9.50280 8.44168 7.34903 - 4.17754 2.92410 1.26222 0.94724 0.63785 0.56695 - 14.46880 13.61617 12.97679 12.39234 11.86064 11.38091 - 10.95261 10.57578 10.25107 9.97880 9.75927 9.59245 - 9.47680 9.41201 9.39996 9.43706 9.51813 9.63707 - 9.77916 9.84404 9.86316 9.75431 8.95903 8.03578 - 4.99337 3.61864 1.53155 1.11115 0.68198 0.56688 - 14.43304 13.61838 12.97978 12.39401 11.86082 11.38059 - 10.95290 10.57755 10.25468 9.98437 9.76660 9.60110 - 9.48649 9.42258 9.41161 9.45060 9.53607 9.66550 - 9.82348 9.89850 9.94552 9.88996 9.25452 8.47606 - 5.59587 4.15382 1.76847 1.26448 0.72489 0.56684 - 14.41148 13.61820 12.97983 12.39437 11.86165 11.38188 - 10.95455 10.57954 10.25716 9.98740 9.77019 9.60528 - 9.49144 9.42860 9.41907 9.45998 9.54821 9.68225 - 9.84949 9.93336 9.99680 9.97330 9.45658 8.77019 - 6.05215 4.59473 2.01180 1.40602 0.76560 0.56682 - 14.39621 13.61807 12.97987 12.39468 11.86231 11.38279 - 10.95571 10.58098 10.25887 9.98943 9.77258 9.60807 - 9.49477 9.43265 9.42409 9.46628 9.55637 9.69356 - 9.86713 9.95710 10.03157 10.02997 9.60063 8.98666 - 6.41824 4.96615 2.24987 1.53903 0.80475 0.56680 - 14.37584 13.61791 12.98012 12.39542 11.86341 11.38425 - 10.95751 10.58314 10.26127 9.99205 9.77556 9.61162 - 9.49904 9.43778 9.43034 9.47408 9.56657 9.70762 - 9.88904 9.98686 10.07554 10.10216 9.79294 9.28696 - 6.97585 5.56289 2.66446 1.83277 0.87909 0.56678 - 14.36317 13.61561 12.97874 12.39609 11.86613 11.38800 - 10.96139 10.58636 10.26349 9.99327 9.77612 9.61217 - 9.50019 9.44016 9.43450 9.48034 9.57445 9.71488 - 9.89907 10.00520 10.10370 10.14607 9.91986 9.48531 - 7.37836 6.03405 3.02025 2.08362 0.94950 0.56677 - 3.03813 3.10233 3.16008 3.21210 3.25826 3.29877 - 3.33428 3.36623 3.39659 3.42600 3.45492 3.48403 - 3.51482 3.54836 3.58390 3.61916 3.65165 3.68069 - 3.70512 3.71533 3.72564 3.73457 3.74507 3.74786 - 3.75006 3.75032 3.75056 3.75059 3.75062 3.75063 - 3.70187 3.75191 3.79779 3.84074 3.88041 3.91642 - 3.94841 3.97609 3.99926 4.01801 4.03293 4.04509 - 4.05699 4.07087 4.08725 4.10651 4.12879 4.15325 - 4.17771 4.18810 4.19416 4.19486 4.19808 4.20031 - 4.20024 4.20005 4.20015 4.20011 4.20035 4.20018 - 4.20987 4.25852 4.30122 4.33963 4.37330 4.40178 - 4.42467 4.44162 4.45248 4.45739 4.45728 4.45366 - 4.44977 4.44858 4.45092 4.45751 4.46889 4.48445 - 4.50214 4.50947 4.51097 4.50646 4.50527 4.50705 - 4.50582 4.50540 4.50545 4.50540 4.50568 4.50548 - 4.94821 5.02205 5.07603 5.11278 5.13257 5.13651 - 5.12705 5.10845 5.08619 5.06195 5.03675 5.01208 - 4.99018 4.97290 4.95972 4.94821 4.93647 4.92646 - 4.92037 4.91806 4.91338 4.90695 4.90031 4.89860 - 4.89702 4.89681 4.89666 4.89665 4.89665 4.89662 - 5.49633 5.59070 5.64603 5.66959 5.66778 5.64846 - 5.61571 5.57462 5.53139 5.48750 5.44316 5.39922 - 5.35711 5.31842 5.28360 5.25253 5.22528 5.20241 - 5.18194 5.17061 5.15837 5.14808 5.13771 5.13502 - 5.13284 5.13256 5.13235 5.13231 5.13229 5.13228 - 5.93348 6.02086 6.07284 6.09410 6.08582 6.05106 - 5.99535 5.92762 5.85860 5.79125 5.72644 5.66546 - 5.60909 5.55819 5.51207 5.46812 5.42452 5.38418 - 5.35074 5.33594 5.31855 5.30244 5.28964 5.28652 - 5.28365 5.28331 5.28306 5.28299 5.28301 5.28299 - 6.28858 6.37642 6.42288 6.43380 6.41083 6.35788 - 6.28181 6.19331 6.10510 6.02055 5.94042 5.86575 - 5.79662 5.73330 5.67497 5.61870 5.56258 5.51013 - 5.46580 5.44616 5.42418 5.40473 5.38928 5.38556 - 5.38221 5.38180 5.38149 5.38143 5.38144 5.38142 - 6.84522 6.92391 6.95249 6.93912 6.88644 6.79981 - 6.68806 6.56446 6.44440 6.33178 6.22711 6.13080 - 6.04185 5.95937 5.88210 5.80643 5.73014 5.65795 - 5.59613 5.56893 5.54007 5.51567 5.49524 5.49034 - 5.48608 5.48556 5.48516 5.48509 5.48508 5.48508 - 7.27031 7.33134 7.33658 7.29657 7.21482 7.09776 - 6.95559 6.80317 6.65747 6.52247 6.39860 6.28560 - 6.18165 6.08480 5.99339 5.90310 5.81125 5.72380 - 5.64858 5.61572 5.58181 5.55374 5.52883 5.52282 - 5.51778 5.51717 5.51668 5.51661 5.51658 5.51656 - 7.99376 8.05812 8.00452 7.86906 7.68600 7.49029 - 7.29244 7.09989 6.92066 6.75425 6.59861 6.45123 - 6.31285 6.18306 6.06119 5.94461 5.83134 5.72326 - 5.62381 5.57832 5.53462 5.50116 5.46733 5.45912 - 5.45262 5.45176 5.45114 5.45105 5.45099 5.45099 - 8.49960 8.51213 8.39427 8.19198 7.94607 7.69646 - 7.45289 7.22021 7.00357 6.80332 6.61944 6.44943 - 6.29191 6.14370 6.00406 5.87055 5.74142 5.61842 - 5.50448 5.45159 5.40033 5.36097 5.32205 5.31251 - 5.30491 5.30393 5.30320 5.30310 5.30304 5.30302 - 9.21719 9.03930 8.79826 8.52325 8.22118 7.90146 - 7.57667 7.26299 6.97594 6.71942 6.49212 6.28942 - 6.10687 5.93807 5.77980 5.62572 5.47180 5.32469 - 5.19311 5.13304 5.07125 5.02108 4.97761 4.96697 - 4.95796 4.95689 4.95605 4.95590 4.95587 4.95586 - 9.67142 9.39089 9.05332 8.69363 8.31851 7.93677 - 7.55988 7.20238 6.87753 6.58828 6.33282 6.10481 - 5.89868 5.70794 5.52917 5.35711 5.18836 5.02771 - 4.88187 4.81461 4.74644 4.69237 4.64633 4.63516 - 4.62574 4.62463 4.62374 4.62358 4.62355 4.62354 - 10.00280 9.63358 9.21514 8.78656 8.35355 7.92413 - 7.50823 7.11812 6.76572 6.45253 6.17613 5.92867 - 5.70331 5.49393 5.29695 5.10870 4.92680 4.75426 - 4.59622 4.52349 4.45197 4.39719 4.34965 4.33824 - 4.32887 4.32777 4.32687 4.32673 4.32667 4.32665 - 10.25890 9.81219 9.32477 8.83880 8.35862 7.89124 - 7.44503 7.02975 6.65615 6.32486 6.03211 5.76909 - 5.52756 5.30194 5.08867 4.88575 4.69195 4.50868 - 4.33993 4.26280 4.18958 4.13562 4.08707 4.07557 - 4.06645 4.06538 4.06446 4.06435 4.06427 4.06425 - 10.73052 10.06972 9.42267 8.82772 8.27874 7.77256 - 7.30623 6.87605 6.48079 6.12119 5.79360 5.49267 - 5.21455 4.95870 4.72267 4.50539 4.30415 4.10855 - 3.91230 3.81986 3.74185 3.69393 3.64456 3.63177 - 3.62311 3.62232 3.62136 3.62116 3.62120 3.62109 - 10.98142 10.22668 9.49846 8.83596 8.23089 7.67802 - 7.17302 6.71185 6.29179 5.91305 5.56983 5.25525 - 4.96353 4.69302 4.44191 4.20797 3.98871 3.77551 - 3.56458 3.46652 3.38471 3.33523 3.28413 3.27082 - 3.26237 3.26165 3.26068 3.26051 3.26046 3.26039 - 11.36960 10.43490 9.55964 8.77742 8.07548 7.44376 - 6.87415 6.36264 5.90588 5.49830 5.13202 4.79774 - 4.48646 4.19374 3.92039 3.66224 3.41639 3.17645 - 2.94081 2.83072 2.73630 2.67643 2.61973 2.60739 - 2.59801 2.59695 2.59611 2.59600 2.59584 2.59584 - 11.62700 10.51948 9.52483 8.65914 7.89952 7.23013 - 6.63699 6.10939 5.64052 5.22117 4.84167 4.49228 - 4.16274 3.84801 3.55185 3.27566 3.01777 2.77160 - 2.53307 2.41869 2.31087 2.23461 2.17585 2.16313 - 2.15289 2.15172 2.15079 2.15063 2.15057 2.15056 - 12.02239 10.64852 9.48719 8.50963 7.67393 6.95514 - 6.33451 5.78933 5.30242 4.86394 4.46453 4.09583 - 3.74935 3.42047 3.11119 2.82474 2.55673 2.29826 - 2.04432 1.92099 1.80419 1.72031 1.65283 1.63788 - 1.62591 1.62453 1.62340 1.62323 1.62315 1.62315 - 12.32391 10.76886 9.50521 8.45683 7.57390 6.82285 - 6.18270 5.62535 5.12633 4.67465 4.26225 3.88151 - 3.52480 3.18764 2.87081 2.57674 2.30341 2.03870 - 1.77704 1.64950 1.52887 1.44109 1.36545 1.34825 - 1.33470 1.33312 1.33179 1.33162 1.33149 1.33147 - 12.58097 10.89521 9.56415 8.46541 7.54880 6.77470 - 6.11835 5.54919 5.03936 4.57664 4.15364 3.76333 - 3.39847 3.05461 2.73191 2.43191 2.15398 1.88562 - 1.61908 1.48825 1.36322 1.27036 1.18779 1.16867 - 1.15359 1.15182 1.15033 1.15013 1.14999 1.14992 - 12.80781 11.02286 9.64495 8.50843 7.56576 6.77475 - 6.10523 5.52502 5.00517 4.53296 4.10111 3.70284 - 3.33106 2.98126 2.65325 2.34794 2.06477 1.79306 - 1.52210 1.38810 1.25841 1.16024 1.07133 1.05041 - 1.03383 1.03188 1.03023 1.03001 1.02985 1.02976 - 13.19227 11.26894 9.83255 8.64603 7.66672 6.85211 - 6.16290 5.56452 5.02798 4.54074 4.09535 3.68481 - 3.30177 2.94145 2.60318 2.28718 1.99191 1.70979 - 1.42843 1.28768 1.14873 1.04040 0.93890 0.91430 - 0.89467 0.89233 0.89037 0.89012 0.88992 0.88983 - 13.50836 11.49517 10.02593 8.81071 7.81015 6.97956 - 6.27614 5.66402 5.11485 4.61645 4.16112 3.74135 - 3.34921 2.97944 2.63108 2.30382 1.99535 1.69877 - 1.40464 1.25624 1.10761 0.98919 0.87448 0.84600 - 0.82323 0.82050 0.81821 0.81792 0.81768 0.81763 - 14.09953 11.95464 10.44923 9.20476 8.18977 7.33920 - 6.61459 5.98080 5.41123 4.89379 4.42046 3.98301 - 3.57249 3.18281 2.81241 2.45995 2.12172 1.78899 - 1.45606 1.28564 1.10935 0.96316 0.81477 0.77685 - 0.74651 0.74282 0.73971 0.73934 0.73898 0.73902 - 14.50692 12.28835 10.77734 9.53368 8.52456 7.67107 - 6.93923 6.29572 5.71512 5.18566 4.69951 4.24857 - 3.82387 3.41906 3.03203 2.66057 2.29934 1.93651 - 1.56218 1.36780 1.16059 0.98396 0.80226 0.75549 - 0.71786 0.71330 0.70949 0.70900 0.70861 0.70846 - 15.03040 12.68604 11.19930 10.01612 9.05396 8.22337 - 7.49454 6.84031 6.24022 5.68788 5.18146 4.71523 - 4.27768 3.85936 3.45456 3.05560 2.65654 2.25474 - 1.81632 1.56367 1.29148 1.05598 0.80969 0.74655 - 0.69444 0.68792 0.68349 0.68276 0.68252 0.68084 - 15.08274 12.93538 11.59093 10.46902 9.50392 8.64915 - 7.89003 7.21208 6.60449 6.05679 5.55866 5.09875 - 4.66354 4.24243 3.83019 3.41965 2.99864 2.54443 - 2.03106 1.74418 1.43149 1.15335 0.83393 0.74351 - 0.68183 0.67606 0.67023 0.66914 0.66934 0.66577 - 15.24076 13.08243 11.79261 10.71698 9.78102 8.94646 - 8.20084 7.53113 6.92770 6.38110 5.88192 5.41960 - 4.98134 4.55662 4.13943 3.72105 3.28628 2.80609 - 2.24528 1.92234 1.56100 1.23806 0.86005 0.75083 - 0.67437 0.66713 0.66090 0.65984 0.65985 0.65529 - 15.34323 13.17800 11.94072 10.90284 9.99363 9.17854 - 8.44709 7.78730 7.19050 6.64800 6.15105 5.68967 - 5.25155 4.82623 4.40711 3.98427 3.54007 3.04022 - 2.44128 2.08816 1.68523 1.32024 0.88821 0.76121 - 0.66941 0.66042 0.65375 0.65278 0.65252 0.64737 - 15.46063 13.28995 12.14256 11.16393 10.30035 9.52030 - 8.81603 8.17711 7.59625 7.06583 6.57798 6.12353 - 5.69077 5.26930 4.85167 4.42621 3.97161 3.44532 - 2.78966 2.38908 1.91743 1.47681 0.94701 0.78703 - 0.66435 0.65134 0.64335 0.64255 0.64174 0.63611 - 15.51848 13.35053 12.27163 11.33856 10.51153 9.76104 - 9.08091 8.46176 7.89725 7.38048 6.90416 6.45957 - 6.03539 5.62115 5.20888 4.78578 4.32788 3.78653 - 3.09229 2.65650 2.13080 1.62485 1.00679 0.81651 - 0.66338 0.64598 0.63604 0.63536 0.63408 0.62846 - 15.56642 13.41982 12.44702 11.59346 10.83089 10.13536 - 9.50227 8.92407 8.39559 7.91097 7.46383 7.04606 - 6.64663 6.25491 5.86236 5.45460 5.00390 4.45196 - 3.70760 3.21702 2.59769 1.96867 1.15477 0.89664 - 0.67024 0.64124 0.62452 0.62386 0.62182 0.61707 - 15.57268 13.44363 12.53277 11.72990 11.00942 10.35134 - 9.75178 9.20422 8.70412 8.24619 7.82449 7.43121 - 7.05532 6.68609 6.31487 5.92678 5.49232 4.94807 - 4.18828 3.66973 2.99261 2.27550 1.29617 0.97813 - 0.68337 0.64292 0.61797 0.61693 0.61448 0.61079 - 15.56650 13.45353 12.61560 11.87278 11.20370 10.59320 - 10.03777 9.53217 9.07245 8.65403 8.27143 7.91718 - 7.58014 7.24953 6.91707 6.56800 6.17194 5.66082 - 4.91149 4.37336 3.63460 2.80139 1.55636 1.13515 - 0.71662 0.65469 0.61154 0.60894 0.60615 0.60404 - 15.55425 13.45410 12.65758 11.94850 11.30947 10.72742 - 10.19932 9.72057 9.28761 8.89624 8.54135 8.21568 - 7.90812 7.60798 7.30762 6.99294 6.63391 6.16109 - 5.44204 4.90570 4.14145 3.23860 1.79665 1.28260 - 0.75316 0.67133 0.60933 0.60461 0.60171 0.60046 - 15.52866 13.45337 12.68905 12.00533 11.38728 10.82375 - 10.31179 9.84737 9.42731 9.04861 8.70802 8.40086 - 8.11976 7.85558 7.59649 7.31857 6.98573 6.53911 - 5.84832 5.32000 4.55431 3.61932 2.02678 1.41775 - 0.78806 0.69032 0.60963 0.60217 0.59952 0.59825 - 15.49750 13.45154 12.71074 12.04480 11.44054 10.88886 - 10.38783 9.93458 9.52708 9.16266 8.83807 8.54855 - 8.28640 8.04258 7.80634 7.55534 7.25365 6.83782 - 6.17720 5.66416 4.90275 3.94466 2.23689 1.55235 - 0.82424 0.70656 0.61045 0.60255 0.59824 0.59676 - 15.45238 13.45381 12.74091 12.09648 11.50991 10.97443 - 10.48895 10.05172 9.66194 9.31742 9.01520 8.75078 - 8.51664 8.30416 8.10374 7.89433 7.64147 7.28277 - 6.68619 6.20394 5.46210 4.48637 2.61478 1.79893 - 0.89503 0.74497 0.61480 0.60215 0.59614 0.59486 - 15.42470 13.45995 12.76242 12.13058 11.55497 11.03018 - 10.55527 10.12900 9.75092 9.41921 9.13128 8.88317 - 8.66793 8.47770 8.30378 8.12630 7.91229 7.60150 - 7.06300 6.61185 5.89571 4.92059 2.94492 2.02758 - 0.96321 0.78314 0.62069 0.60311 0.59499 0.59369 - 15.37968 13.47624 12.79705 12.18108 11.62038 11.11126 - 10.65230 10.24245 9.88132 9.56761 9.29970 9.07481 - 8.88768 8.73235 8.60199 8.47894 8.33378 8.11257 - 7.69176 7.31002 6.66229 5.72120 3.62219 2.52928 - 1.12284 0.87517 0.63851 0.60873 0.59384 0.59212 - 15.30942 13.48631 12.81624 12.20801 11.65494 11.15408 - 10.70380 10.30322 9.95185 9.64878 9.39265 9.18120 - 9.00978 8.87347 8.76721 8.67625 8.57505 8.41436 - 8.07980 7.75639 7.17998 6.29675 4.15300 2.93932 - 1.27031 0.96572 0.65891 0.61478 0.59391 0.59134 - 15.11433 13.49417 12.83545 12.23642 11.69175 11.19922 - 10.75741 10.36566 10.02389 9.73165 9.48792 9.29113 - 9.13760 9.02377 8.94668 8.89475 8.84756 8.76460 - 8.54722 8.30540 7.83196 7.05124 4.95402 3.61517 - 1.53571 1.12796 0.69961 0.63372 0.59524 0.59054 - 14.94476 13.49622 12.84434 12.25073 11.71075 11.22246 - 10.78475 10.39719 10.05982 9.77261 9.53487 9.34570 - 9.20239 9.10237 9.04339 9.01455 8.99802 8.96170 - 8.82160 8.63682 8.23791 7.53321 5.52601 4.15955 - 1.77685 1.27438 0.73866 0.65591 0.59599 0.59014 - 14.81889 13.49867 12.85145 12.25946 11.72035 11.23357 - 10.79837 10.41433 10.08123 9.79889 9.56649 9.38300 - 9.24576 9.15253 9.10223 9.08618 9.09003 9.08689 - 9.00007 8.85539 8.51987 7.89087 5.97184 4.59424 - 1.99426 1.41351 0.77833 0.67593 0.59853 0.58990 - 14.73244 13.49918 12.85530 12.26515 11.72741 11.24214 - 10.80884 10.42696 10.09642 9.81698 9.58769 9.40756 - 9.27438 9.18637 9.14300 9.13662 9.15463 9.17359 - 9.12536 9.01311 8.72798 8.16096 6.33023 4.95858 - 2.20274 1.54375 0.81642 0.69650 0.60135 0.58974 - 14.62466 13.49975 12.85944 12.27197 11.73658 11.25374 - 10.82294 10.44392 10.11650 9.84040 9.61492 9.43919 - 9.31140 9.23018 9.19576 9.20189 9.23838 9.28682 - 9.29157 9.22526 9.01487 8.54577 6.87705 5.54134 - 2.59157 1.78371 0.88968 0.73703 0.60783 0.58953 - 14.55767 13.50014 12.86150 12.27574 11.74223 11.26115 - 10.83211 10.45479 10.12910 9.85486 9.63161 9.45862 - 9.33422 9.25725 9.22839 9.24221 9.29017 9.35730 - 9.39670 9.36139 9.20384 8.80873 7.28002 5.99260 - 2.93071 2.00099 0.95926 0.77641 0.61510 0.58941 - 14.45656 13.50038 12.86385 12.28065 11.74994 11.27152 - 10.84481 10.46967 10.14620 9.87437 9.65414 9.48502 - 9.36531 9.29414 9.27290 9.29736 9.36114 9.45452 - 9.54369 9.55427 9.47907 9.20862 7.95229 6.78934 - 3.62731 2.48617 1.12052 0.87014 0.63516 0.58925 - 14.39893 13.50041 12.86481 12.28292 11.75341 11.27617 - 10.85073 10.47709 10.15541 9.88536 9.66628 9.49781 - 9.37978 9.31258 9.29705 9.32716 9.39624 9.50163 - 9.62578 9.66719 9.62494 9.40047 8.38526 7.39416 - 4.14230 2.88191 1.27004 0.96709 0.65714 0.58916 - 14.33606 13.50060 12.86658 12.28559 11.75709 11.28083 - 10.85647 10.48390 10.16355 9.89505 9.67774 9.51136 - 9.39584 9.33182 9.32050 9.35645 9.43415 9.55322 - 9.70453 9.77343 9.78352 9.64495 8.88385 8.08573 - 4.95603 3.55853 1.53605 1.13385 0.69777 0.58908 - 14.30266 13.50084 12.86776 12.28733 11.75904 11.28317 - 10.85910 10.48682 10.16669 9.89871 9.68286 9.51884 - 9.40528 9.34200 9.33122 9.37001 9.45496 9.58373 - 9.74121 9.81632 9.86475 9.81257 9.18700 8.41900 - 5.57342 4.14037 1.77248 1.27202 0.73962 0.58904 - 14.28249 13.50096 12.86810 12.28788 11.75995 11.28424 - 10.86053 10.48873 10.16911 9.90173 9.68642 9.52293 - 9.41006 9.34781 9.33845 9.37911 9.46670 9.59993 - 9.76645 9.85032 9.91474 9.89398 9.38679 8.71056 - 6.02597 4.57775 2.01378 1.41268 0.77928 0.58902 - 14.26833 13.50104 12.86833 12.28838 11.76050 11.28513 - 10.86166 10.49012 10.17084 9.90378 9.68881 9.52567 - 9.41329 9.35171 9.34331 9.38521 9.47461 9.61083 - 9.78356 9.87344 9.94860 9.94927 9.52934 8.92533 - 6.38868 4.94600 2.24880 1.54495 0.81756 0.58900 - 14.24905 13.50129 12.86907 12.28930 11.76168 11.28657 - 10.86344 10.49218 10.17315 9.90634 9.69173 9.52913 - 9.41742 9.35665 9.34931 9.39275 9.48447 9.62446 - 9.80481 9.90232 9.99124 10.01948 9.71891 9.22206 - 6.94022 5.53748 2.65879 1.83494 0.89054 0.58898 - 14.23719 13.49899 12.86769 12.28997 11.76448 11.29040 - 10.86730 10.49539 10.17526 9.90733 9.69203 9.52953 - 9.41852 9.35897 9.35334 9.39881 9.49225 9.63161 - 9.81445 9.91996 10.01837 10.06207 9.84271 9.41508 - 7.33668 6.00438 3.01149 2.08264 0.95994 0.58897 - 2.91598 2.97910 3.03627 3.08817 3.13469 3.17596 - 3.21261 3.24593 3.27776 3.30873 3.33925 3.37003 - 3.40254 3.43789 3.47539 3.51293 3.54809 3.57985 - 3.60671 3.61808 3.62985 3.64028 3.65243 3.65566 - 3.65824 3.65856 3.65884 3.65887 3.65890 3.65890 - 3.56650 3.61635 3.66243 3.70589 3.74643 3.78368 - 3.81731 3.84703 3.87266 3.89428 3.91243 3.92812 - 3.94365 3.96117 3.98117 4.00401 4.02991 4.05822 - 4.08700 4.09975 4.10823 4.11086 4.11568 4.11810 - 4.11839 4.11826 4.11838 4.11835 4.11857 4.11842 - 4.07012 4.11874 4.16187 4.20109 4.23598 4.26614 - 4.29115 4.31071 4.32467 4.33316 4.33703 4.33772 - 4.33826 4.34151 4.34825 4.35922 4.37502 4.39526 - 4.41814 4.42825 4.43256 4.43021 4.43062 4.43252 - 4.43164 4.43128 4.43135 4.43130 4.43156 4.43136 - 4.80928 4.88229 4.93651 4.97443 4.99626 5.00309 - 4.99719 4.98267 4.96468 4.94489 4.92424 4.90417 - 4.88682 4.87403 4.86540 4.85887 4.85277 4.84870 - 4.84843 4.84894 4.84708 4.84278 4.83772 4.83632 - 4.83502 4.83485 4.83471 4.83469 4.83469 4.83468 - 5.35644 5.45575 5.51376 5.53847 5.53785 5.52123 - 5.49266 5.45663 5.41860 5.37984 5.34050 5.30138 - 5.26401 5.23009 5.20012 5.17417 5.15238 5.13512 - 5.12031 5.11182 5.10229 5.09390 5.08513 5.08278 - 5.08087 5.08062 5.08043 5.08040 5.08038 5.08038 - 5.78592 5.90417 5.96327 5.97551 5.95464 5.91628 - 5.86629 5.81031 5.75483 5.70007 5.64384 5.58614 - 5.53062 5.48078 5.43665 5.39663 5.35975 5.32817 - 5.30073 5.28577 5.27016 5.25772 5.24601 5.24296 - 5.24051 5.24020 5.23996 5.23991 5.23990 5.23991 - 6.15445 6.24763 6.29952 6.31557 6.29745 6.24912 - 6.17757 6.09376 6.01069 5.93175 5.85754 5.78884 - 5.72534 5.66702 5.61315 5.56121 5.50965 5.46196 - 5.42250 5.40525 5.38541 5.36744 5.35351 5.35014 - 5.34703 5.34666 5.34638 5.34632 5.34634 5.34632 - 6.71471 6.80095 6.83721 6.83115 6.78537 6.70519 - 6.59957 6.48202 6.36816 6.26189 6.16362 6.07351 - 5.99021 5.91259 5.83947 5.76761 5.69509 5.62674 - 5.56878 5.54343 5.51618 5.49287 5.47370 5.46909 - 5.46506 5.46457 5.46421 5.46414 5.46415 5.46413 - 7.14279 7.21253 7.22698 7.19602 7.12305 7.01440 - 6.88025 6.73548 6.59715 6.46924 6.35211 6.24535 - 6.14693 6.05478 5.96731 5.88045 5.79182 5.70744 - 5.63519 5.60368 5.57092 5.54359 5.51965 5.51390 - 5.50903 5.50844 5.50797 5.50791 5.50788 5.50786 - 7.87560 7.94432 7.90151 7.78041 7.61228 7.42941 - 7.24234 7.05926 6.88905 6.73119 6.58318 6.44228 - 6.30938 6.18431 6.06636 5.95295 5.84219 5.73613 - 5.63822 5.59314 5.54973 5.51647 5.48291 5.47479 - 5.46834 5.46750 5.46687 5.46678 5.46673 5.46670 - 8.39039 8.40234 8.29585 8.11190 7.88552 7.65156 - 7.41992 7.19702 6.98965 6.79834 6.62262 6.45979 - 6.30840 6.16538 6.02998 5.89989 5.77346 5.65232 - 5.53923 5.48633 5.43486 5.39525 5.35609 5.34649 - 5.33885 5.33786 5.33712 5.33701 5.33694 5.33694 - 9.11242 8.94705 8.72054 8.46070 8.17409 7.86961 - 7.55926 7.25865 6.98281 6.73569 6.51624 6.32033 - 6.14403 5.98132 5.82888 5.67984 5.52969 5.38504 - 5.25443 5.19414 5.13175 5.08084 5.03652 5.02565 - 5.01644 5.01534 5.01446 5.01432 5.01428 5.01428 - 9.57534 9.30913 8.98725 8.64322 8.28346 7.91646 - 7.55328 7.20804 6.89381 6.61361 6.36590 6.14487 - 5.94542 5.76144 5.58932 5.42324 5.25921 5.10198 - 4.95799 4.89087 4.82223 4.76726 4.72011 4.70861 - 4.69888 4.69773 4.69681 4.69666 4.69661 4.69661 - 9.91383 9.56070 9.15886 8.74603 8.32788 7.91222 - 7.50885 7.12991 6.78727 6.48256 6.21361 5.97311 - 5.75457 5.55214 5.36211 5.18028 5.00378 4.83553 - 4.68047 4.60844 4.53685 4.48124 4.43249 4.42071 - 4.41098 4.40982 4.40887 4.40873 4.40867 4.40867 - 10.17580 9.74683 9.27676 8.80651 8.34053 7.88587 - 7.45094 7.04566 6.68091 6.35749 6.07183 5.81559 - 5.58078 5.36201 5.15564 4.95925 4.77126 4.59303 - 4.42835 4.35257 4.27975 4.22515 4.17540 4.16350 - 4.15402 4.15289 4.15193 4.15182 4.15173 4.15172 - 10.65804 10.01589 9.38614 8.80616 8.27023 7.77547 - 7.31913 6.89780 6.51034 6.15756 5.83609 5.54088 - 5.26840 5.01824 4.78812 4.57712 4.38252 4.19349 - 4.00300 3.91275 3.83592 3.78789 3.73763 3.72439 - 3.71542 3.71460 3.71359 3.71338 3.71342 3.71331 - 10.91749 10.18132 9.46996 8.82165 8.22871 7.68625 - 7.19022 6.73681 6.32349 5.95050 5.61238 5.30265 - 5.01583 4.75038 4.50467 4.27665 4.06390 3.85749 - 3.65311 3.55788 3.47796 3.42896 3.37738 3.36363 - 3.35497 3.35424 3.35323 3.35304 3.35299 3.35292 - 11.31776 10.40192 9.54248 8.77308 8.08163 7.45859 - 6.89625 6.39074 5.93884 5.53524 5.17240 4.84141 - 4.53363 4.24470 3.97546 3.72200 3.48159 3.24778 - 3.01879 2.91202 2.82039 2.76210 2.70602 2.69344 - 2.68410 2.68308 2.68220 2.68208 2.68192 2.68193 - 11.56764 10.49100 9.51739 8.66551 7.91456 7.25031 - 6.66030 6.13514 5.66896 5.25282 4.87697 4.53155 - 4.20592 3.89472 3.60172 3.32860 3.07422 2.83259 - 2.60016 2.48927 2.38459 2.31034 2.25296 2.24047 - 2.23038 2.22924 2.22832 2.22815 2.22810 2.22809 - 11.95948 10.62006 9.47999 8.51585 7.68842 6.97440 - 6.35627 5.81280 5.32782 4.89168 4.49498 4.12922 - 3.78556 3.45914 3.15194 2.86717 2.60095 2.34522 - 2.09573 1.97534 1.86179 1.78069 1.71553 1.70110 - 1.68956 1.68824 1.68715 1.68698 1.68689 1.68691 - 12.25416 10.73496 9.49229 8.45759 7.58352 6.83812 - 6.20125 5.64601 5.14895 4.69927 4.28899 3.91043 - 3.55581 3.22054 2.90534 2.61244 2.34006 2.07706 - 1.81868 1.69357 1.57607 1.49134 1.41848 1.40199 - 1.38904 1.38753 1.38626 1.38609 1.38596 1.38596 - 12.50358 10.85400 9.54340 8.45891 7.55221 6.78508 - 6.13330 5.56717 5.05962 4.59880 4.17745 3.78869 - 3.42538 3.08307 2.76180 2.46284 2.18559 1.91842 - 1.65441 1.52561 1.40343 1.31359 1.23414 1.21586 - 1.20149 1.19981 1.19838 1.19820 1.19806 1.19799 - 12.72349 10.97509 9.61720 8.49551 7.56372 6.78075 - 6.11687 5.54055 5.02334 4.55297 4.12245 3.72530 - 3.35469 3.00625 2.67959 2.37535 2.09285 1.82207 - 1.55315 1.42088 1.29378 1.19851 1.11297 1.09301 - 1.07722 1.07536 1.07379 1.07359 1.07344 1.07333 - 13.09917 11.21448 9.79777 8.62656 7.65879 6.85274 - 6.16980 5.57583 5.04219 4.55676 4.11250 3.70277 - 3.32064 2.96149 2.62453 2.30973 2.01540 1.73416 - 1.45430 1.31489 1.17814 1.07254 0.97481 0.95132 - 0.93261 0.93039 0.92852 0.92828 0.92810 0.92800 - 13.41179 11.44058 9.99100 8.79070 7.80095 6.97801 - 6.28003 5.67180 5.12534 4.62875 4.17470 3.75592 - 3.36477 2.99616 2.64908 2.32314 2.01597 1.72051 - 1.42763 1.28034 1.13369 1.01789 0.90727 0.88004 - 0.85828 0.85568 0.85350 0.85322 0.85299 0.85295 - 14.00316 11.90396 10.41661 9.18492 8.17792 7.33284 - 6.61206 5.98126 5.41422 4.89900 4.42762 3.99188 - 3.58279 3.19431 2.82512 2.47419 2.13787 1.80690 - 1.47520 1.30567 1.13113 0.98750 0.84374 0.80728 - 0.77808 0.77454 0.77157 0.77121 0.77087 0.77093 - 14.41422 12.23860 10.74193 9.50846 8.50569 7.65737 - 6.92983 6.29009 5.71282 5.18630 4.70271 4.25390 - 3.83084 3.42722 3.04132 2.67142 2.31242 1.95174 - 1.57900 1.38552 1.18009 1.00608 0.82930 0.78409 - 0.74774 0.74334 0.73965 0.73917 0.73882 0.73863 - 14.94455 12.63199 11.15095 9.97382 9.01799 8.19515 - 7.47424 6.82685 6.23138 5.68214 5.17854 4.71524 - 4.27991 3.86272 3.45863 3.06099 2.66443 2.26579 - 1.83002 1.57833 1.30811 1.07563 0.83430 0.77279 - 0.72252 0.71622 0.71174 0.71097 0.71096 0.70889 - 14.97497 12.87548 11.54153 10.42561 9.46465 8.61415 - 7.85952 7.18631 6.58367 6.04098 5.54774 5.09233 - 4.66089 4.24262 3.83243 3.42338 3.00370 2.55140 - 2.04128 1.75665 1.44666 1.17133 0.85644 0.76799 - 0.70880 0.70331 0.69728 0.69617 0.69674 0.69244 - 15.12240 13.01556 11.73592 10.66578 9.73407 8.90407 - 8.16330 7.49881 6.90087 6.35988 5.86618 5.40895 - 4.97493 4.55338 4.13844 3.72164 3.28824 2.81014 - 2.25304 1.93274 1.57463 1.25462 0.88101 0.77373 - 0.70039 0.69356 0.68707 0.68597 0.68651 0.68104 - 15.21477 13.10455 11.87727 10.84522 9.94055 9.13039 - 8.40414 7.74992 7.15894 6.62236 6.13123 5.67525 - 5.24168 4.81979 4.40310 3.98201 3.53932 3.04176 - 2.44692 2.09676 1.69741 1.33554 0.90778 0.78272 - 0.69460 0.68615 0.67922 0.67819 0.67858 0.67246 - 15.31474 13.20535 12.06827 11.09623 10.23816 9.46377 - 8.76529 8.13237 7.55767 7.03343 6.55164 6.10284 - 5.67490 5.25716 4.84230 4.41893 3.96621 3.44268 - 2.79179 2.39459 1.92704 1.48993 0.96422 0.80625 - 0.68817 0.67594 0.66781 0.66694 0.66690 0.66030 - 15.35914 13.25736 12.18916 11.26360 10.44293 9.69873 - 9.02479 8.41192 7.85367 7.34310 6.87281 6.43386 - 6.01455 5.60420 5.19495 4.77426 4.31864 3.78048 - 3.09152 2.65940 2.13812 1.63606 1.02209 0.83393 - 0.68609 0.66966 0.65981 0.65908 0.65859 0.65209 - 15.38676 13.31346 12.35245 11.50784 10.75288 10.06453 - 9.43817 8.86644 8.34416 7.86550 7.42400 7.01149 - 6.61669 6.22891 5.83972 5.43494 4.98725 4.43937 - 3.70119 3.21476 2.60037 1.97582 1.16666 0.91092 - 0.69079 0.66317 0.64732 0.64670 0.64526 0.63990 - 15.38290 13.33073 12.43231 11.63900 10.92661 10.27605 - 9.68336 9.14222 8.64808 8.19576 7.77927 7.39080 - 7.01923 6.65383 6.28606 5.90122 5.47026 4.93062 - 4.17760 3.66351 2.99164 2.27943 1.30571 0.99032 - 0.70235 0.66358 0.64026 0.63939 0.63726 0.63322 - 15.36875 13.33620 12.51060 11.77749 11.11671 10.51356 - 9.96480 9.46525 9.01102 8.59759 8.21956 7.86947 - 7.53623 7.20915 6.88008 6.53444 6.14227 5.63631 - 4.89443 4.36114 3.62806 2.80036 1.56279 1.14461 - 0.73341 0.67355 0.63324 0.63106 0.62819 0.62606 - 15.35599 13.33707 12.55202 11.85217 11.22082 10.64578 - 10.12396 9.65085 9.22296 8.83616 8.48541 8.16352 - 7.85942 7.56258 7.26544 6.95411 6.59900 6.13147 - 5.42015 4.88887 4.13070 3.23390 1.80084 1.29036 - 0.76845 0.68896 0.63065 0.62655 0.62337 0.62227 - 15.33662 13.33857 12.58252 11.90633 11.29542 10.73898 - 10.23385 9.77580 9.36141 8.98766 8.65128 8.34758 - 8.06917 7.80698 7.54962 7.27402 6.94511 6.50470 - 5.82298 5.30021 4.54073 3.61175 2.02905 1.42427 - 0.80212 0.70703 0.63064 0.62394 0.62101 0.61993 - 15.30590 13.33756 12.60537 11.94676 11.34943 10.80444 - 10.30966 9.86205 9.45942 9.09915 8.77807 8.49161 - 8.23226 7.99117 7.75762 7.50927 7.21065 6.79985 - 6.14799 5.64090 4.88620 3.93486 2.23804 1.55781 - 0.83722 0.72250 0.63124 0.62406 0.61976 0.61834 - 15.26157 13.34186 12.63819 12.00111 11.42061 10.89038 - 10.40936 9.97627 9.59036 9.24955 8.95086 8.68983 - 8.45890 8.24947 8.05185 7.84494 7.59457 7.23992 - 6.65110 6.17481 5.44065 4.47296 2.61356 1.80288 - 0.90652 0.75960 0.63502 0.62344 0.61749 0.61633 - 15.23557 13.34893 12.66053 12.03575 11.46570 10.94546 - 10.47442 10.05164 9.67699 9.34876 9.06431 8.81962 - 8.60762 8.42040 8.24922 8.07415 7.86252 7.55526 - 7.02357 6.57808 5.87013 4.90411 2.94174 2.03010 - 0.97357 0.79676 0.64037 0.62413 0.61624 0.61510 - 15.19501 13.36582 12.69463 12.08488 11.52929 11.02433 - 10.56889 10.16232 9.80440 9.49394 9.22923 9.00744 - 8.82314 8.67031 8.54226 8.42155 8.27909 8.06110 - 7.64527 7.26818 6.62882 5.69832 3.61506 2.52869 - 1.13119 0.88698 0.65698 0.62904 0.61496 0.61345 - 15.13041 13.37557 12.71230 12.10975 11.56169 11.06520 - 10.61878 10.22167 9.87356 9.57350 9.32021 9.11138 - 8.94242 8.80839 8.70436 8.61564 8.51684 8.35894 - 8.02872 7.70953 7.14115 6.26905 4.14250 2.93509 - 1.27742 0.97670 0.67646 0.63407 0.61494 0.61262 - 14.94615 13.38241 12.72959 12.13596 11.59617 11.10813 - 10.67042 10.28236 9.94384 9.65446 9.41322 9.21862 - 9.06705 8.95507 8.87978 8.82976 8.78475 8.70437 - 8.49079 8.25245 7.78555 7.01499 4.93766 3.60637 - 1.54091 1.13725 0.71561 0.65167 0.61623 0.61178 - 14.78513 13.38371 12.73758 12.14916 11.61408 11.13034 - 10.69668 10.31287 9.97869 9.69424 9.45886 9.27167 - 9.13004 9.03149 8.97388 8.94658 8.93205 8.89841 - 8.76233 8.58058 8.18638 7.48955 5.50453 4.14827 - 1.78080 1.28188 0.75329 0.67318 0.61676 0.61135 - 14.66683 13.38500 12.74304 12.15676 11.62309 11.14104 - 10.70996 10.32957 10.00002 9.72080 9.49034 9.30750 - 9.17087 9.07918 9.03109 9.01708 9.02251 9.02277 - 8.93907 8.79280 8.45816 7.84848 5.97191 4.56907 - 1.98884 1.41969 0.79292 0.69142 0.62211 0.61110 - 14.58414 13.38563 12.74714 12.16257 11.63014 11.14957 - 10.72015 10.34173 10.01405 9.73705 9.50986 9.33157 - 9.19998 9.11333 9.07110 9.06576 9.08484 9.10573 - 9.06154 8.95234 8.67060 8.10927 6.30097 4.94118 - 2.20447 1.54958 0.82929 0.71199 0.62175 0.61093 - 14.48211 13.38634 12.75133 12.16919 11.63888 11.16059 - 10.73384 10.35810 10.03351 9.75979 9.53634 9.36232 - 9.23597 9.15596 9.12252 9.12933 9.16644 9.21617 - 9.22438 9.16098 8.95401 8.49018 6.84194 5.51917 - 2.59060 1.78820 0.90117 0.75126 0.62779 0.61071 - 14.41888 13.38697 12.75366 12.17320 11.64444 11.16780 - 10.74257 10.36853 10.04571 9.77385 9.55259 9.38128 - 9.25817 9.18226 9.15418 9.16852 9.21684 9.28483 - 9.32698 9.29433 9.14054 8.75086 7.24046 5.96647 - 2.92759 2.00444 0.96966 0.78965 0.63461 0.61058 - 14.32351 13.38784 12.75656 12.17833 11.65203 11.17771 - 10.75469 10.38288 10.06226 9.79281 9.57455 9.40698 - 9.28843 9.21812 9.19741 9.22206 9.28586 9.37944 - 9.46998 9.48250 9.41155 9.14717 7.90502 6.75549 - 3.61983 2.48690 1.12895 0.88159 0.65357 0.61041 - 14.26913 13.38809 12.75781 12.18064 11.65554 11.18238 - 10.76051 10.39010 10.07120 9.80347 9.58629 9.41931 - 9.30241 9.23599 9.22085 9.25098 9.31983 9.42497 - 9.55002 9.59321 9.55443 9.33479 8.33347 7.35674 - 4.13044 2.87800 1.27720 0.97774 0.67462 0.61033 - 14.20973 13.38820 12.75945 12.18338 11.65926 11.18697 - 10.76606 10.39672 10.07903 9.81278 9.59729 9.43234 - 9.31787 9.25454 9.24355 9.27942 9.35668 9.47516 - 9.62651 9.69644 9.70908 9.57438 8.82532 8.04150 - 4.93872 3.54887 1.54142 1.14303 0.71351 0.61024 - 14.17804 13.38844 12.76072 12.18519 11.66138 11.18927 - 10.76875 10.39957 10.08207 9.81633 9.60227 9.43963 - 9.32705 9.26439 9.25384 9.29244 9.37688 9.50506 - 9.66205 9.73730 9.78747 9.73932 9.12474 8.36752 - 5.55305 4.12801 1.77647 1.27948 0.75410 0.61020 - 14.15912 13.38878 12.76126 12.18583 11.66217 11.19042 - 10.77015 10.40142 10.08447 9.81931 9.60582 9.44367 - 9.33172 9.26999 9.26077 9.30119 9.38825 9.52069 - 9.68657 9.77051 9.83566 9.81751 9.32201 8.65639 - 6.00206 4.56211 2.01578 1.41921 0.79275 0.61018 - 14.14577 13.38897 12.76159 12.18622 11.66271 11.19119 - 10.77115 10.40273 10.08612 9.82134 9.60819 9.44640 - 9.33490 9.27377 9.26541 9.30705 9.39591 9.53121 - 9.70312 9.79308 9.86838 9.87067 9.46250 8.86901 - 6.36152 4.92746 2.24805 1.55074 0.83019 0.61016 - 14.12774 13.38902 12.76193 12.18683 11.66357 11.19231 - 10.77281 10.40472 10.08839 9.82382 9.61100 9.44974 - 9.33889 9.27854 9.27119 9.31431 9.40545 9.54441 - 9.72375 9.82115 9.90980 9.93892 9.64883 9.16182 - 6.90728 5.51398 2.65391 1.83750 0.90185 0.61014 - 14.11632 13.38623 12.75984 12.18689 11.66587 11.19583 - 10.77646 10.40777 10.09039 9.82474 9.61123 9.45001 - 9.33983 9.28071 9.27510 9.32026 9.41308 9.55148 - 9.73300 9.83801 9.93678 9.98223 9.76990 9.35017 - 7.29826 5.97697 3.00401 2.08254 0.97026 0.61012 - 2.80243 2.86462 2.92134 2.97325 3.02017 3.06224 - 3.10001 3.13465 3.16785 3.20018 3.23207 3.26420 - 3.29810 3.33488 3.37393 3.41325 3.45050 3.48444 - 3.51326 3.52555 3.53837 3.54990 3.56366 3.56738 - 3.57033 3.57069 3.57102 3.57105 3.57109 3.57109 - 3.44284 3.49229 3.53834 3.58208 3.62320 3.66138 - 3.69630 3.72769 3.75539 3.77946 3.80040 3.81914 - 3.83785 3.85855 3.88171 3.90769 3.93672 3.96832 - 4.00066 4.01522 4.02542 4.02934 4.03587 4.03887 - 4.03956 4.03947 4.03964 4.03961 4.03983 4.03970 - 3.94173 3.99004 4.03333 4.07308 4.10889 4.14038 - 4.16717 4.18896 4.20561 4.21726 4.22467 4.22922 - 4.23374 4.24098 4.25167 4.26656 4.28629 4.31062 - 4.33785 4.35016 4.35648 4.35555 4.35779 4.36031 - 4.35984 4.35953 4.35964 4.35960 4.35984 4.35969 - 4.67898 4.75076 4.80494 4.84380 4.86752 4.87710 - 4.87467 4.86405 4.85015 4.83452 4.81810 4.80223 - 4.78899 4.78023 4.77571 4.77370 4.77279 4.77416 - 4.77895 4.78169 4.78182 4.77899 4.77605 4.77524 - 4.77437 4.77425 4.77417 4.77415 4.77417 4.77416 - 5.22633 5.32467 5.38361 5.41064 5.41335 5.40065 - 5.37640 5.34485 5.31123 5.27685 5.24200 5.20749 - 5.17472 5.14531 5.11980 5.09847 5.08164 5.06975 - 5.06009 5.05361 5.04603 5.03932 5.03265 5.03085 - 5.02937 5.02919 5.02905 5.02902 5.02901 5.02902 - 5.65681 5.77541 5.83663 5.85222 5.83558 5.80198 - 5.75709 5.70628 5.65578 5.60583 5.55433 5.50135 - 5.45051 5.40530 5.36577 5.33033 5.29808 5.27143 - 5.24881 5.23578 5.22205 5.21124 5.20156 5.19905 - 5.19704 5.19679 5.19660 5.19656 5.19655 5.19656 - 6.02678 6.12194 6.17715 6.19737 6.18413 6.14124 - 6.07546 5.99747 5.92002 5.84643 5.77731 5.71342 - 5.65455 5.60075 5.55131 5.50381 5.45672 5.41344 - 5.37816 5.36283 5.34483 5.32832 5.31634 5.31351 - 5.31081 5.31048 5.31026 5.31021 5.31024 5.31021 - 6.59068 6.68093 6.72260 6.72265 6.68348 6.61024 - 6.51165 6.40094 6.29352 6.19325 6.10051 6.01549 - 5.93693 5.86374 5.79478 5.72685 5.65807 5.59323 - 5.53850 5.51467 5.48895 5.46696 5.44949 5.44536 - 5.44170 5.44127 5.44093 5.44087 5.44087 5.44086 - 7.02235 7.09778 7.11937 7.09614 7.03124 6.93081 - 6.80474 6.66772 6.53658 6.41526 6.30411 6.20273 - 6.10915 6.02135 5.93775 5.85436 5.76886 5.68725 - 5.61738 5.58698 5.55542 5.52925 5.50672 5.50137 - 5.49682 5.49627 5.49583 5.49576 5.49575 5.49575 - 7.76382 7.83945 7.80677 7.69699 7.54029 7.36803 - 7.19071 7.01667 6.85489 6.70485 6.56372 6.42872 - 6.30088 6.18021 6.06600 5.95562 5.84715 5.74266 - 5.64568 5.60097 5.55807 5.52542 5.49267 5.48477 - 5.47853 5.47771 5.47710 5.47702 5.47696 5.47696 - 8.28566 8.30507 8.21040 8.03981 7.82683 7.60503 - 7.38425 7.17114 6.97275 6.78965 6.62127 6.46491 - 6.31913 6.18094 6.04957 5.92269 5.79855 5.67866 - 5.56579 5.51278 5.46125 5.42173 5.38294 5.37346 - 5.36593 5.36495 5.36423 5.36413 5.36405 5.36404 - 9.01644 8.86267 8.65006 8.40410 8.13108 7.83964 - 7.54150 7.25195 6.98590 6.74733 6.53532 6.34604 - 6.17584 6.01892 5.87181 5.72723 5.58022 5.43731 - 5.30689 5.24606 5.18297 5.13151 5.08694 5.07603 - 5.06678 5.06568 5.06481 5.06466 5.06462 5.06458 - 9.48705 9.23341 8.92649 8.59701 8.25122 7.89738 - 7.54633 7.21197 6.90728 6.63538 6.39492 6.18051 - 5.98744 5.80980 5.64385 5.48319 5.32326 5.16864 - 5.02558 4.95814 4.88877 4.83301 4.78520 4.77352 - 4.76365 4.76248 4.76154 4.76138 4.76134 4.76129 - 9.83168 9.49212 9.10610 8.70815 8.30389 7.90101 - 7.50923 7.14055 6.80688 6.51001 6.24797 6.01390 - 5.80173 5.60580 5.42229 5.24640 5.07471 4.90999 - 4.75685 4.68501 4.61307 4.55673 4.50701 4.49493 - 4.48495 4.48376 4.48280 4.48266 4.48259 4.48255 - 10.09871 9.68440 9.23093 8.77572 8.32333 7.88082 - 7.45667 7.06085 6.70441 6.38828 6.10913 5.85908 - 5.63048 5.41809 5.21821 5.02796 4.84530 4.67140 - 4.50969 4.43468 4.36206 4.30698 4.25603 4.24373 - 4.23392 4.23275 4.23176 4.23164 4.23154 4.23153 - 10.58910 9.96275 9.35030 8.78515 8.26214 7.77858 - 7.33199 6.91917 6.53917 6.19283 5.87703 5.58711 - 5.31985 5.07494 4.85031 4.64517 4.45673 4.27364 - 4.08809 3.99963 3.92379 3.87569 3.82434 3.81050 - 3.80116 3.80030 3.79924 3.79901 3.79906 3.79899 - 10.85526 10.13499 9.44090 8.80710 8.22651 7.69453 - 7.20745 6.76166 6.35487 5.98736 5.65401 5.34874 - 5.06641 4.80566 4.56498 4.34252 4.13585 3.93572 - 3.73720 3.64448 3.56630 3.51779 3.46540 3.45097 - 3.44200 3.44126 3.44018 3.43997 3.43992 3.43991 - 11.26379 10.36395 9.52201 8.76661 8.08658 7.47286 - 6.91819 6.41888 5.97193 5.57224 5.21265 4.88470 - 4.58009 4.29466 4.02926 3.78024 3.54498 3.31695 - 3.09419 2.99054 2.90152 2.84469 2.78885 2.77584 - 2.76642 2.76542 2.76451 2.76438 2.76421 2.76424 - 11.50905 10.45546 9.50287 8.66573 7.92511 7.26806 - 6.68312 6.16185 5.69902 5.28599 4.91320 4.57089 - 4.24840 3.94032 3.65037 3.38047 3.12983 2.89271 - 2.66577 2.55795 2.45616 2.38384 2.32752 2.31516 - 2.30518 2.30405 2.30313 2.30297 2.30292 2.30287 - 11.89825 10.58457 9.46639 8.51673 7.69918 6.99172 - 6.37779 5.83725 5.35474 4.92085 4.52637 4.16281 - 3.82136 3.49706 3.19187 2.90904 2.64503 2.39225 - 2.14690 2.02907 1.91828 1.83953 1.77657 1.76266 - 1.75155 1.75028 1.74924 1.74907 1.74899 1.74895 - 12.18999 10.69891 9.47848 8.45799 7.59329 6.85388 - 6.22051 5.66747 5.17231 4.72448 4.31604 3.93933 - 3.58652 3.25292 2.93923 2.64772 2.37683 2.11595 - 1.86074 1.73774 1.62276 1.54049 1.47029 1.45451 - 1.44215 1.44071 1.43950 1.43934 1.43922 1.43920 - 12.43723 10.81787 9.52962 8.45907 7.56113 6.79925 - 6.15023 5.58567 5.07958 4.62034 4.20071 3.81371 - 3.45203 3.11115 2.79114 2.49339 2.21739 1.95194 - 1.69052 1.56349 1.44356 1.35609 1.27953 1.26206 - 1.24836 1.24676 1.24540 1.24523 1.24510 1.24508 - 12.65462 10.93850 9.60299 8.49509 7.57163 6.79329 - 6.13161 5.55640 5.04035 4.57143 4.14258 3.74717 - 3.37813 3.03098 2.70546 2.40236 2.12110 1.85183 - 1.58513 1.45440 1.32933 1.23633 1.15384 1.13476 - 1.11969 1.11793 1.11643 1.11623 1.11609 1.11607 - 13.02361 11.17444 9.78023 8.62302 7.66354 6.86173 - 6.18064 5.58756 5.05496 4.57093 4.12827 3.72021 - 3.33954 2.98157 2.64563 2.33193 2.03889 1.75901 - 1.48091 1.34278 1.20790 1.10456 1.01017 0.98768 - 0.96977 0.96765 0.96587 0.96563 0.96547 0.96541 - 13.32744 11.39437 9.96787 8.78230 7.80143 6.98320 - 6.28750 5.68054 5.13534 4.64021 4.18771 3.77050 - 3.38069 3.01317 2.66708 2.34226 2.03640 1.74226 - 1.45087 1.30475 1.16000 1.04662 0.93963 0.91349 - 0.89261 0.89013 0.88804 0.88778 0.88756 0.88745 - 13.89611 11.84210 10.38040 9.16560 8.16868 7.32958 - 6.61225 5.98367 5.41856 4.90519 4.43557 4.00145 - 3.59376 3.20644 2.83834 2.48864 2.15378 1.82421 - 1.49380 1.32531 1.15273 1.01172 0.87210 0.83691 - 0.80871 0.80530 0.80244 0.80210 0.80177 0.80174 - 14.28783 12.16512 10.69689 9.48191 8.48968 7.64768 - 6.92381 6.28653 5.71159 5.18742 4.70614 4.25950 - 3.83826 3.43608 3.05147 2.68300 2.32568 1.96664 - 1.59532 1.40274 1.19908 1.02757 0.85521 0.81140 - 0.77618 0.77192 0.76834 0.76787 0.76754 0.76761 - 14.78435 12.55363 11.10530 9.94122 8.98961 8.17091 - 7.45470 6.81218 6.22120 5.67595 5.17577 4.71529 - 4.28223 3.86680 3.46423 3.06818 2.67360 2.27761 - 1.84403 1.59271 1.32356 1.09333 0.85670 0.79678 - 0.74832 0.74225 0.73770 0.73688 0.73704 0.73658 - 14.83062 12.78464 11.47431 10.37460 9.42536 8.58398 - 7.83642 7.16876 6.57045 6.03114 5.54058 5.08742 - 4.65806 4.24187 3.83385 3.42710 3.00982 2.56001 - 2.05241 1.76911 1.46054 1.18688 0.87594 0.78955 - 0.73312 0.72796 0.72167 0.72043 0.72138 0.71973 - 14.97274 12.92203 11.66458 10.60963 9.68931 8.86833 - 8.13469 7.47590 6.88251 6.34518 5.85450 5.39984 - 4.96825 4.54915 4.13673 3.72256 3.29190 2.81654 - 2.26215 1.94328 1.58674 1.26833 0.89867 0.79357 - 0.72377 0.71741 0.71055 0.70928 0.71036 0.70788 - 15.06189 13.00980 11.80306 10.78532 9.89161 9.09027 - 8.37111 7.72263 7.13634 6.60360 6.11570 5.66254 - 5.23164 4.81247 4.39859 3.98040 3.54073 3.04616 - 2.45422 2.10559 1.70797 1.34778 0.92403 0.80127 - 0.71734 0.70949 0.70215 0.70093 0.70198 0.69881 - 15.15882 13.11035 11.99062 11.03135 10.18327 9.41721 - 8.72555 8.09834 7.52838 7.00816 6.52986 6.08419 - 5.65929 5.24463 4.83297 4.41291 3.96365 3.44351 - 2.79592 2.40048 1.93495 1.49988 0.97838 0.82294 - 0.71004 0.69864 0.69016 0.68909 0.68983 0.68578 - 15.20256 13.16330 12.10997 11.19582 10.38416 9.64770 - 8.98025 8.37290 7.81937 7.31285 6.84615 6.41051 - 5.99442 5.58737 5.18158 4.76449 4.31262 3.77821 - 3.09292 2.66280 2.14384 1.64425 1.03475 0.84930 - 0.70733 0.69191 0.68190 0.68098 0.68129 0.67685 - 15.23216 13.22259 12.27260 11.43670 10.68893 10.00691 - 9.38614 8.81937 8.30149 7.82675 7.38885 6.97973 - 6.58830 6.20401 5.81849 5.41763 4.97416 4.43064 - 3.69704 3.21318 2.60183 1.98062 1.17689 0.92415 - 0.71073 0.68445 0.66914 0.66845 0.66761 0.66350 - 15.23109 13.24318 12.35346 11.56708 10.86040 10.21513 - 9.62724 9.09051 8.60038 8.15174 7.73868 7.35352 - 6.98524 6.62327 6.25915 5.87828 5.45169 4.91681 - 4.16914 3.65813 2.98993 2.28174 1.31438 1.00215 - 0.72120 0.68401 0.66195 0.66115 0.65937 0.65612 - 15.22121 13.25392 12.43417 11.70577 11.04904 10.44981 - 9.90472 9.40865 8.95772 8.54741 8.17239 7.82526 - 7.49503 7.17109 6.84541 6.50355 6.11572 5.61493 - 4.87944 4.35005 3.62162 2.79891 1.56933 1.15449 - 0.75053 0.69259 0.65470 0.65283 0.64991 0.64816 - 15.21131 13.25808 12.47745 11.78128 11.15313 10.58117 - 10.06226 9.59197 9.16684 8.78272 8.43457 8.11528 - 7.81386 7.51981 7.22575 6.91791 6.56695 6.10466 - 5.40030 4.87344 4.12064 3.22951 1.80558 1.29882 - 0.78421 0.70686 0.65181 0.64822 0.64476 0.64393 - 15.19297 13.26137 12.50973 11.83681 11.22856 10.67453 - 10.17173 9.71584 9.30362 8.93210 8.59800 8.29672 - 8.02087 7.76147 7.50701 7.23420 6.90822 6.47259 - 5.79917 5.28182 4.52828 3.60500 2.03193 1.43157 - 0.81670 0.72402 0.65150 0.64545 0.64218 0.64131 - 15.16492 13.26212 12.53345 11.87765 11.28261 10.73984 - 10.24719 9.80162 9.40101 9.04274 8.72368 8.43927 - 8.18208 7.94332 7.71227 7.46655 7.17097 6.76480 - 6.12075 5.61908 4.87095 3.92627 2.23980 1.56394 - 0.85068 0.73871 0.65187 0.64525 0.64091 0.63954 - 15.15232 13.27801 12.56527 11.92399 11.34371 10.81706 - 10.34159 9.91456 9.53371 9.19643 8.89949 8.63797 - 8.40373 8.18893 7.98817 7.78915 7.56078 7.22181 - 6.62411 6.14204 5.41792 4.46412 2.60765 1.80875 - 0.91871 0.77471 0.65520 0.64399 0.63826 0.63728 - 15.12927 13.28560 12.58722 11.95784 11.38826 10.87194 - 10.40696 9.99070 9.62125 9.29630 9.01305 8.76714 - 8.55105 8.35773 8.18284 8.01546 7.82616 7.53453 - 6.99242 6.54054 5.84406 4.89326 2.93231 2.03481 - 0.98453 0.81089 0.66006 0.64428 0.63685 0.63590 - 15.06084 13.29274 12.62456 12.01719 11.46386 10.96090 - 10.50748 10.10263 9.74616 9.43685 9.17306 8.95200 - 8.76837 8.61619 8.48892 8.36929 8.22847 8.01317 - 7.60223 7.22955 6.59750 5.67641 3.60840 2.52817 - 1.13975 0.89890 0.67521 0.64892 0.63536 0.63404 - 14.99905 13.30244 12.64252 12.04267 11.49693 11.00239 - 10.55795 10.16247 9.81572 9.51678 9.26435 9.05618 - 8.88770 8.75401 8.65028 8.56198 8.46395 8.30769 - 7.98127 7.66602 7.10479 6.24261 4.13233 2.93112 - 1.28469 0.98771 0.69378 0.65298 0.63519 0.63310 - 14.82437 13.30954 12.66019 12.06940 11.53216 11.04620 - 10.61039 10.22395 9.88676 9.59841 9.35801 9.16397 - 9.01269 8.90069 8.82519 8.77487 8.72970 8.64977 - 8.43848 8.20311 7.74227 6.98116 4.92223 3.59806 - 1.54620 1.14657 0.73141 0.66928 0.63642 0.63216 - 14.67200 13.31129 12.66857 12.08310 11.55051 11.06880 - 10.63714 10.25492 9.92209 9.63870 9.40417 9.21751 - 9.07610 8.97740 8.91933 8.89132 8.87601 8.84218 - 8.70772 8.52830 8.13866 7.44958 5.48461 4.13782 - 1.78481 1.28942 0.76775 0.69014 0.63675 0.63168 - 14.56006 13.31286 12.67429 12.09086 11.55962 11.07983 - 10.65064 10.27201 9.94385 9.66571 9.43609 9.25374 - 9.11722 9.02531 8.97667 8.96183 8.96635 8.96597 - 8.88274 8.73795 8.40732 7.80569 5.94896 4.55389 - 1.99183 1.42697 0.80651 0.70706 0.64222 0.63140 - 14.48175 13.31356 12.67843 12.09690 11.56703 11.08864 - 10.66122 10.28442 9.95817 9.68235 9.45602 9.27813 - 9.14655 9.05970 9.01698 9.01080 9.02876 9.04846 - 9.00423 8.89640 8.61778 8.06263 6.27410 4.92521 - 2.20622 1.55542 0.84204 0.72724 0.64146 0.63121 - 14.38513 13.31445 12.68287 12.10377 11.57602 11.10004 - 10.67521 10.30117 9.97804 9.70554 9.48295 9.30939 - 9.18307 9.10292 9.06898 9.07496 9.11085 9.15902 - 9.16607 9.10314 8.89825 8.43947 6.80965 5.49881 - 2.58981 1.79273 0.91259 0.76529 0.64713 0.63096 - 14.32517 13.31522 12.68523 12.10771 11.58172 11.10738 - 10.68421 10.31186 9.99050 9.71986 9.49950 9.32868 - 9.20573 9.12970 9.10116 9.11468 9.16182 9.22809 - 9.26838 9.23551 9.08298 8.69742 7.20393 5.94244 - 2.92474 2.00790 0.98000 0.80270 0.65356 0.63082 - 14.23473 13.31607 12.68826 12.11308 11.58955 11.11756 - 10.69671 10.32657 10.00743 9.73921 9.52188 9.35500 - 9.23677 9.16642 9.14525 9.16910 9.23186 9.32371 - 9.41168 9.42301 9.35189 9.08977 7.86108 6.72447 - 3.61294 2.48769 1.13733 0.89289 0.67154 0.63062 - 14.18325 13.31635 12.68953 12.11542 11.59310 11.12227 - 10.70257 10.33393 10.01654 9.75010 9.53391 9.36762 - 9.25109 9.18468 9.16921 9.19855 9.26633 9.36982 - 9.49251 9.53431 9.49413 9.27468 8.28540 7.32242 - 4.11960 2.87459 1.28433 0.98822 0.69171 0.63052 - 14.12696 13.31651 12.69120 12.11826 11.59684 11.12699 - 10.70825 10.34073 10.02462 9.75968 9.54521 9.38097 - 9.26693 9.20366 9.19237 9.22752 9.30380 9.42084 - 9.57012 9.63862 9.64915 9.51267 8.77137 8.00106 - 4.92291 3.54009 1.54672 1.15203 0.72895 0.63043 - 14.09700 13.31677 12.69237 12.11999 11.59887 11.12940 - 10.71097 10.34362 10.02773 9.76334 9.55034 9.38843 - 9.27627 9.21372 9.20294 9.24098 9.32449 9.45131 - 9.60626 9.68000 9.72824 9.67847 9.06738 8.31971 - 5.53421 4.11679 1.78046 1.28686 0.76834 0.63038 - 14.07891 13.31702 12.69292 12.12063 11.59977 11.13046 - 10.71247 10.34554 10.03020 9.76636 9.55391 9.39255 - 9.28109 9.21951 9.21012 9.25003 9.33620 9.46732 - 9.63121 9.71371 9.77695 9.75689 9.26287 8.60519 - 5.97966 4.54782 2.01834 1.42570 0.80601 0.63035 - 14.06628 13.31721 12.69325 12.12103 11.60030 11.13133 - 10.71348 10.34691 10.03190 9.76842 9.55634 9.39535 - 9.28437 9.22344 9.21497 9.25613 9.34412 9.47812 - 9.64810 9.73667 9.81006 9.81026 9.40220 8.81543 - 6.33596 4.91042 2.24802 1.55645 0.84264 0.63033 - 14.04930 13.31727 12.69369 12.12164 11.60128 11.13255 - 10.71515 10.34899 10.03425 9.77099 9.55923 9.39878 - 9.28847 9.22838 9.22096 9.26364 9.35395 9.49167 - 9.66917 9.76528 9.85229 9.87943 9.58725 9.10455 - 6.87614 5.49228 2.65001 1.84054 0.91301 0.63031 - 14.03854 13.31469 12.69171 12.12181 11.60358 11.13598 - 10.71881 10.35203 10.03629 9.77196 9.55951 9.39906 - 9.28939 9.23051 9.22484 9.26963 9.36168 9.49893 - 9.67877 9.78266 9.87994 9.92342 9.70769 9.29094 - 7.26223 5.95134 2.99742 2.08298 0.98044 0.63030 - 2.69700 2.75826 2.81450 2.86628 2.91350 2.95620 - 2.99491 3.03068 3.06508 3.09866 3.13179 3.16515 - 3.20018 3.23800 3.27813 3.31887 3.35807 3.39410 - 3.42462 3.43767 3.45148 3.46414 3.47948 3.48364 - 3.48697 3.48738 3.48773 3.48777 3.48782 3.48783 - 3.32632 3.37572 3.42201 3.46622 3.50807 3.54724 - 3.58342 3.61636 3.64591 3.67209 3.69541 3.71673 - 3.73811 3.76147 3.78728 3.81590 3.84760 3.88209 - 3.91777 3.93417 3.94625 3.95159 3.95920 3.96228 - 3.96320 3.96314 3.96332 3.96331 3.96351 3.96337 - 3.81988 3.86834 3.91217 3.95273 3.98967 4.02260 - 4.05117 4.07508 4.09421 4.10865 4.11918 4.12704 - 4.13499 4.14561 4.15967 4.17791 4.20101 4.22895 - 4.26026 4.27479 4.28340 4.28418 4.28748 4.28992 - 4.28969 4.28943 4.28953 4.28950 4.28973 4.28957 - 4.55463 4.62553 4.67993 4.71995 4.74573 4.75813 - 4.75914 4.75232 4.74222 4.73033 4.71758 4.70535 - 4.69581 4.69085 4.69023 4.69227 4.69554 4.70135 - 4.71095 4.71621 4.71885 4.71783 4.71605 4.71545 - 4.71478 4.71467 4.71460 4.71459 4.71460 4.71459 - 5.10195 5.19906 5.25898 5.28860 5.29487 5.28605 - 5.26584 5.23844 5.20905 5.17888 5.14815 5.11765 - 5.08899 5.06387 5.04278 5.02575 5.01300 5.00529 - 5.00042 4.99658 4.99154 4.98660 4.98132 4.97983 - 4.97859 4.97845 4.97832 4.97828 4.97828 4.97828 - 5.54396 5.63666 5.69678 5.72799 5.73128 5.70943 - 5.66768 5.61455 5.56038 5.50801 5.45818 5.41194 - 5.36990 5.33277 5.30002 5.26950 5.23977 5.21370 - 5.19470 5.18700 5.17641 5.16535 5.15769 5.15584 - 5.15394 5.15371 5.15355 5.15351 5.15354 5.15352 - 5.90398 6.00097 6.05927 6.08340 6.07478 6.03704 - 5.97676 5.90433 5.83221 5.76367 5.69933 5.63999 - 5.58554 5.53605 5.49082 5.44735 5.40410 5.36467 - 5.33349 5.32034 5.30457 5.28983 5.27942 5.27695 - 5.27455 5.27426 5.27405 5.27400 5.27404 5.27402 - 6.47085 6.56488 6.61158 6.61729 6.58429 6.51753 - 6.42550 6.32120 6.21984 6.12523 6.03773 5.95757 - 5.88353 5.81460 5.74960 5.68533 5.61990 5.55830 - 5.50692 5.48484 5.46096 5.44049 5.42448 5.42071 - 5.41733 5.41692 5.41661 5.41655 5.41656 5.41655 - 6.90539 6.98637 7.01470 6.99870 6.94131 6.84847 - 6.72991 6.60006 6.47560 6.36044 6.25492 6.15863 - 6.06966 5.98601 5.90612 5.82602 5.74346 5.66457 - 5.59737 5.56832 5.53823 5.51331 5.49198 5.48690 - 5.48260 5.48207 5.48165 5.48159 5.48158 5.48156 - 7.65371 7.73737 7.71469 7.61542 7.46904 7.30650 - 7.13818 6.97245 6.81840 6.67548 6.54073 6.41135 - 6.28831 6.17172 6.06090 5.95341 5.84743 5.74481 - 5.64914 5.60512 5.56296 5.53091 5.49859 5.49080 - 5.48463 5.48382 5.48322 5.48314 5.48308 5.48307 - 8.18126 8.21040 8.12785 7.96984 7.76895 7.55807 - 7.34706 7.14283 6.95271 6.77728 6.61581 6.46554 - 6.32492 6.19100 6.06313 5.93926 5.81775 5.69948 - 5.58714 5.53436 5.48310 5.44369 5.40474 5.39520 - 5.38761 5.38662 5.38589 5.38578 5.38570 5.38572 - 8.91989 8.78016 8.58236 8.35027 8.09010 7.81041 - 7.52291 7.24294 6.98561 6.75494 6.55005 6.36723 - 6.20284 6.05112 5.90859 5.76791 5.62396 5.48301 - 5.35304 5.29187 5.22841 5.17662 5.13117 5.11997 - 5.11049 5.10935 5.10846 5.10831 5.10826 5.10828 - 9.39758 9.15956 8.86882 8.55404 8.22148 7.87947 - 7.53891 7.21390 6.91773 6.65359 6.42019 6.21235 - 6.02539 5.85346 5.69281 5.53685 5.38072 5.22872 - 5.08657 5.01889 4.94910 4.89278 4.84373 4.83166 - 4.82147 4.82024 4.81927 4.81913 4.81908 4.81909 - 9.74832 9.42539 9.05633 8.67340 8.28232 7.89097 - 7.50921 7.14940 6.82381 6.53435 6.27911 6.05150 - 5.84551 5.65550 5.47764 5.30697 5.13971 4.97830 - 4.82686 4.75515 4.68295 4.62601 4.57493 4.56241 - 4.55206 4.55083 4.54982 4.54967 4.54960 4.54961 - 10.02083 9.62381 9.18778 8.74760 8.30814 7.87668 - 7.46197 7.07446 6.72555 6.41638 6.14367 5.89981 - 5.67730 5.47084 5.27676 5.09200 4.91418 4.74422 - 4.58506 4.51066 4.43812 4.38252 4.33018 4.31741 - 4.30722 4.30599 4.30496 4.30485 4.30474 4.30472 - 10.52216 9.91178 9.31578 8.76482 8.25419 7.78139 - 7.34415 6.93950 6.56665 6.22647 5.91611 5.63123 - 5.36891 5.12899 4.90958 4.70994 4.52723 4.34956 - 4.16824 4.08116 4.00589 3.95741 3.90497 3.89064 - 3.88094 3.88005 3.87893 3.87869 3.87875 3.87861 - 10.79638 10.09142 9.41341 8.79322 8.22423 7.70222 - 7.22364 6.78521 6.38476 6.02261 5.69398 5.39313 - 5.11524 4.85908 4.62327 4.40612 4.20517 4.01075 - 3.81726 3.72650 3.64949 3.60104 3.54783 3.53292 - 3.52365 3.52289 3.52175 3.52153 3.52149 3.52140 - 11.21840 10.33250 9.50534 8.76197 8.09189 7.48648 - 6.93881 6.44537 6.00323 5.60755 5.25144 4.92681 - 4.62561 4.34381 4.08230 3.83761 3.60723 3.38450 - 3.16719 3.06610 2.97909 2.92318 2.86729 2.85391 - 2.84439 2.84340 2.84244 2.84231 2.84215 2.84215 - 11.46861 10.43083 9.49333 8.66735 7.93524 7.28467 - 6.70484 6.18772 5.72840 5.31847 4.94866 4.60937 - 4.29006 3.98530 3.69864 3.43199 3.18475 2.95167 - 2.72988 2.62489 2.52548 2.45446 2.39863 2.38626 - 2.37625 2.37511 2.37419 2.37403 2.37397 2.37398 - 11.86436 10.56523 9.46024 8.52008 7.70984 7.00804 - 6.39839 5.86123 5.38146 4.94988 4.55750 4.19603 - 3.85674 3.53468 3.23168 2.95078 2.68871 2.43861 - 2.19727 2.08196 1.97377 1.89699 1.83531 1.82164 - 1.81072 1.80947 1.80845 1.80829 1.80820 1.80824 - 12.15566 10.67966 9.47191 8.46039 7.60252 6.86844 - 6.23897 5.68887 5.19601 4.75009 4.34335 3.96827 - 3.61711 3.28521 2.97315 2.68300 2.41330 2.15424 - 1.90215 1.78132 1.66891 1.58893 1.52050 1.50511 - 1.49310 1.49171 1.49053 1.49038 1.49025 1.49025 - 12.39868 10.79643 9.52106 8.45961 7.56845 6.81173 - 6.16640 5.60448 5.10042 4.64286 4.22470 3.83911 - 3.47884 3.13941 2.82078 2.52413 2.24898 1.98487 - 1.72598 1.60082 1.48330 1.39819 1.32376 1.30682 - 1.29359 1.29204 1.29073 1.29056 1.29043 1.29035 - 12.61041 10.91375 9.59182 8.49353 7.57703 6.80374 - 6.14560 5.57286 5.05870 4.59132 4.16381 3.76967 - 3.40191 3.05610 2.73184 2.42975 2.14923 1.88103 - 1.61646 1.48737 1.36455 1.27389 1.19380 1.17537 - 1.16084 1.15914 1.15769 1.15750 1.15737 1.15725 - 12.96627 11.14202 9.76324 8.61699 7.66519 6.86855 - 6.19092 5.60021 5.06939 4.58676 4.14532 3.73839 - 3.35888 3.00213 2.66739 2.35473 2.06251 1.78352 - 1.50705 1.37026 1.23741 1.13637 1.04476 1.02307 - 1.00581 1.00378 1.00206 1.00183 1.00167 1.00157 - 13.25814 11.35470 9.94537 8.77207 7.79960 6.98682 - 6.29473 5.69022 5.14684 4.65311 4.20178 3.78562 - 3.39692 3.03056 2.68567 2.36198 2.05716 1.76401 - 1.47396 1.32900 1.18617 1.07510 0.97117 0.94593 - 0.92579 0.92339 0.92138 0.92112 0.92092 0.92091 - 13.81208 11.79266 10.34901 9.14724 8.15883 7.32561 - 6.61239 5.98682 5.42402 4.91249 4.44436 4.01152 - 3.60503 3.21890 2.85200 2.50360 2.17014 1.84187 - 1.51264 1.34514 1.17447 1.03596 0.89999 0.86589 - 0.83856 0.83526 0.83251 0.83218 0.83185 0.83193 - 14.20491 12.11542 10.66216 9.45822 8.47318 7.63673 - 6.91722 6.28353 5.71159 5.18997 4.71086 4.26607 - 3.84639 3.44555 3.06215 2.69498 2.33910 1.98149 - 1.61162 1.42012 1.21856 1.04977 0.88146 0.83887 - 0.80468 0.80055 0.79706 0.79659 0.79629 0.79602 - 14.70758 12.51765 11.07649 9.91216 8.95984 8.14573 - 7.43701 6.80136 6.21374 5.66985 5.17192 4.71536 - 4.28583 3.87237 3.47071 3.07556 2.68243 2.28809 - 1.85671 1.60711 1.34049 1.11323 0.88080 0.82213 - 0.77534 0.76942 0.76473 0.76391 0.76426 0.76185 - 15.00011 12.75154 11.33986 10.22181 9.30461 8.51835 - 7.82807 7.19922 6.60513 6.04868 5.54274 5.08579 - 4.65551 4.23539 3.82141 3.40904 2.99482 2.57644 - 2.09576 1.79692 1.46913 1.18715 0.89437 0.81982 - 0.76019 0.75292 0.74720 0.74606 0.74709 0.74263 - 15.14653 12.92317 11.55860 10.46405 9.55238 8.77071 - 8.08910 7.47660 6.90746 6.37356 5.87195 5.39959 - 4.95318 4.52826 4.11806 3.71205 3.29321 2.83070 - 2.28482 1.96463 1.59910 1.27227 0.91496 0.82073 - 0.74947 0.74152 0.73497 0.73423 0.73492 0.72939 - 15.00418 12.98008 11.77065 10.74981 9.85432 9.05304 - 8.33539 7.68978 7.10739 6.57933 6.09653 5.64851 - 5.22215 4.80655 4.39538 3.97925 3.54136 3.04908 - 2.46078 2.11471 1.72024 1.36281 0.94276 0.82174 - 0.74115 0.73366 0.72582 0.72456 0.72625 0.71952 - 15.09518 13.07853 11.95460 10.99142 10.14083 9.37434 - 8.68385 8.05924 7.49302 6.97741 6.50429 6.06392 - 5.64386 5.23316 4.82469 4.40721 3.96025 3.44288 - 2.79935 2.40670 1.94459 1.51247 0.99452 0.84091 - 0.73227 0.72143 0.71244 0.71129 0.71282 0.70566 - 15.13163 13.12794 12.07011 11.15218 10.33805 9.60111 - 8.93470 8.32976 7.77978 7.27768 6.81598 6.38555 - 5.97431 5.57140 5.16909 4.75498 4.30589 3.77467 - 3.09378 2.66656 2.15114 1.65476 1.04885 0.86537 - 0.72830 0.71362 0.70322 0.70222 0.70335 0.69637 - 15.14495 13.17833 12.22538 11.38686 10.63739 9.95527 - 9.33556 8.77097 8.25616 7.78524 7.35170 6.94719 - 6.56023 6.18002 5.79822 5.40088 4.96092 4.42138 - 3.69282 3.21211 2.60456 1.98699 1.18757 0.93713 - 0.72948 0.70428 0.68920 0.68847 0.68829 0.68267 - 15.13204 13.19214 12.30114 11.51352 10.80609 10.16117 - 9.57451 9.03980 8.55240 8.10702 7.69768 7.31648 - 6.95218 6.59396 6.23350 5.85632 5.43359 4.90317 - 4.16103 3.65341 2.98926 2.28508 1.32293 1.01324 - 0.73847 0.70261 0.68147 0.68071 0.67933 0.67519 - 15.10751 13.19449 12.37610 11.64833 10.99225 10.39416 - 9.85058 9.35636 8.90763 8.49982 8.12753 7.78332 - 7.45612 7.13528 6.81283 6.47452 6.09072 5.59479 - 4.86550 4.33991 3.61602 2.79792 1.57522 1.16324 - 0.76583 0.70959 0.67377 0.67215 0.66919 0.66720 - 15.09076 13.19493 12.41679 11.72223 11.09549 10.52510 - 10.00785 9.53930 9.11603 8.73390 8.38786 8.07081 - 7.77175 7.48024 7.18895 6.88431 6.53721 6.07981 - 5.38198 4.85928 4.11147 3.22547 1.80958 1.30611 - 0.79820 0.72282 0.67068 0.66752 0.66377 0.66298 - 15.06924 13.19640 12.44764 11.77697 11.17055 10.61841 - 10.11735 9.66321 9.25269 8.88285 8.55047 8.25096 - 7.97704 7.71979 7.46767 7.19739 6.87434 6.44313 - 5.77709 5.26477 4.51688 3.59882 2.03411 1.43777 - 0.82968 0.73923 0.67025 0.66475 0.66111 0.66038 - 15.03972 13.19614 12.47077 11.81749 11.22463 10.68389 - 10.19306 9.74917 9.35008 8.99324 8.67555 8.39252 - 8.13687 7.89988 7.67085 7.42744 7.13466 6.73271 - 6.09563 5.59892 4.85693 3.91844 2.24094 1.56910 - 0.86271 0.75336 0.67058 0.66440 0.65997 0.65863 - 15.02652 13.21139 12.50241 11.86398 11.28614 10.76146 - 10.28784 9.86239 9.48291 9.14682 8.85091 8.59038 - 8.35711 8.14342 7.94401 7.74672 7.52082 7.18562 - 6.59422 6.11702 5.39972 4.45316 2.60660 1.81230 - 0.92952 0.78827 0.67357 0.66322 0.65728 0.65640 - 15.00427 13.21905 12.52449 11.89806 11.33088 10.81667 - 10.35351 9.93879 9.57060 9.24669 8.96431 8.71910 - 8.50370 8.31114 8.13721 7.97112 7.78375 7.49529 - 6.95887 6.51172 5.82233 4.87942 2.92934 2.03688 - 0.99432 0.82364 0.67812 0.66341 0.65586 0.65504 - 14.93912 13.22715 12.56255 11.95796 11.40697 10.90602 - 10.45437 10.05100 9.69572 9.38737 9.12427 8.90369 - 8.72038 8.56849 8.44151 8.32240 8.18265 7.96944 - 7.56281 7.19406 6.56849 5.65602 3.60196 2.52689 - 1.14765 0.91011 0.69244 0.66764 0.65439 0.65321 - 14.88184 13.23759 12.58092 11.98374 11.44020 10.94772 - 10.50506 10.11111 9.76559 9.46758 9.21581 9.00805 - 8.83979 8.70617 8.60245 8.51417 8.41648 8.26127 - 7.93789 7.62605 7.07122 6.21801 4.12233 2.92679 - 1.29147 0.99815 0.71028 0.67095 0.65420 0.65229 - 14.71624 13.24516 12.59891 12.01074 11.47577 10.99177 - 10.55786 10.17300 9.83710 9.54972 9.31005 9.11645 - 8.96535 8.85328 8.77747 8.72671 8.68108 8.60101 - 8.39102 8.15797 7.70243 6.94999 4.90786 3.59012 - 1.55121 1.15550 0.74660 0.68617 0.65553 0.65136 - 14.57119 13.24689 12.60730 12.02451 11.49429 11.01477 - 10.58496 10.20428 9.87277 9.59037 9.35664 9.17050 - 9.02932 8.93054 8.87209 8.84338 8.82716 8.79255 - 8.65854 8.48067 8.09497 7.41309 5.46663 4.12862 - 1.78862 1.29667 0.78174 0.70649 0.65576 0.65089 - 14.46441 13.24852 12.61312 12.03235 11.50358 11.02579 - 10.59855 10.22149 9.89470 9.61763 9.38890 9.20712 - 9.07086 8.97887 8.92977 8.91420 8.91776 8.91624 - 8.83237 8.68832 8.36108 7.76701 5.92864 4.54044 - 1.99478 1.43405 0.81970 0.72217 0.66139 0.65061 - 14.38966 13.24916 12.61727 12.03838 11.51097 11.03469 - 10.60912 10.23397 9.90916 9.63447 9.40906 9.23179 - 9.10046 9.01353 8.97040 8.96348 8.98039 8.99870 - 8.95338 8.84599 8.57006 8.02067 6.24987 4.91181 - 2.20805 1.56109 0.85445 0.74203 0.66029 0.65043 - 14.29772 13.25011 12.62171 12.04534 11.52004 11.04616 - 10.62318 10.25081 9.92915 9.65788 9.43625 9.26329 - 9.13721 9.05704 9.02277 9.02811 9.06298 9.10963 - 9.11496 9.05173 8.84833 8.39391 6.78032 5.48125 - 2.58925 1.79714 0.92374 0.77894 0.66569 0.65019 - 14.24090 13.25092 12.62417 12.04927 11.52563 11.05339 - 10.63216 10.26156 9.94171 9.67231 9.45290 9.28270 - 9.15999 9.08403 9.05524 9.06814 9.11429 9.17908 - 9.21743 9.18379 9.03178 8.64932 7.17049 5.92104 - 2.92228 2.01134 0.99015 0.81544 0.67182 0.65005 - 14.15507 13.25201 12.62722 12.05464 11.53335 11.06364 - 10.64474 10.27640 9.95879 9.69183 9.47543 9.30917 - 9.19127 9.12103 9.09970 9.12301 9.18493 9.27544 - 9.36144 9.37154 9.29934 9.03787 7.82055 6.69560 - 3.60669 2.48868 1.14563 0.90396 0.68895 0.64986 - 14.10571 13.25242 12.62889 12.05746 11.53738 11.06864 - 10.65079 10.28364 9.96721 9.70162 9.48690 9.32272 - 9.20732 9.14007 9.12270 9.15151 9.22168 9.32592 - 9.43774 9.47168 9.44438 9.25729 8.22868 7.20971 - 4.14045 2.90716 1.28950 0.98868 0.70729 0.64976 - 14.05220 13.25271 12.63066 12.06031 11.54121 11.07345 - 10.65656 10.29046 9.97536 9.71136 9.49842 9.33628 - 9.22337 9.15929 9.14614 9.18069 9.25929 9.37781 - 9.51694 9.57617 9.59711 9.49664 8.72302 7.86623 - 4.93813 3.57883 1.55036 1.14717 0.74486 0.64967 - 14.02442 13.25288 12.63154 12.06163 11.54294 11.07556 - 10.65916 10.29371 9.97937 9.71621 9.50418 9.34298 - 9.23128 9.16889 9.15801 9.19564 9.27851 9.40430 - 9.55773 9.63046 9.67686 9.62491 9.01559 8.27585 - 5.51703 4.10668 1.78443 1.29409 0.78228 0.64962 - 14.00725 13.25314 12.63208 12.06237 11.54383 11.07670 - 10.66066 10.29563 9.98182 9.71923 9.50775 9.34707 - 9.23607 9.17471 9.16529 9.20487 9.29039 9.42054 - 9.58287 9.66427 9.72650 9.70523 9.21008 8.55877 - 5.95922 4.53476 2.02090 1.43204 0.81902 0.64960 - 13.99538 13.25334 12.63242 12.06276 11.54447 11.07758 - 10.66177 10.29703 9.98354 9.72127 9.51013 9.34982 - 9.23930 9.17865 9.17018 9.21107 9.29842 9.43151 - 9.59988 9.68728 9.76024 9.76005 9.34890 8.76678 - 6.31253 4.89480 2.24819 1.56208 0.85489 0.64958 - 13.97904 13.25331 12.63275 12.06338 11.54544 11.07890 - 10.66354 10.29911 9.98586 9.72381 9.51300 9.35324 - 9.24340 9.18360 9.17624 9.21869 9.30836 9.44520 - 9.62124 9.71625 9.80282 9.82956 9.53336 9.05322 - 6.84751 5.47215 2.64640 1.84348 0.92403 0.64956 - 13.96868 13.25053 12.63068 12.06354 11.54774 11.08242 - 10.66719 10.30219 9.98792 9.72482 9.51336 9.35364 - 9.24449 9.18585 9.18017 9.22462 9.31603 9.45243 - 9.63125 9.73427 9.82979 9.87116 9.65310 9.23767 - 7.22918 5.92767 2.99117 2.08329 0.99049 0.64954 - 2.59622 2.65665 2.71261 2.76460 2.81248 2.85626 - 2.89633 2.93360 2.96937 3.00416 3.03830 3.07250 - 3.10828 3.14684 3.18776 3.22950 3.26999 3.30733 - 3.33892 3.35254 3.36734 3.38131 3.39839 3.40308 - 3.40685 3.40732 3.40772 3.40776 3.40781 3.40782 - 3.22709 3.27613 3.32222 3.36632 3.40814 3.44739 - 3.48378 3.51707 3.54711 3.57398 3.59819 3.62063 - 3.64344 3.66859 3.69658 3.72782 3.76252 3.79999 - 3.83817 3.85567 3.86904 3.87573 3.88495 3.88846 - 3.88968 3.88967 3.88988 3.88987 3.89009 3.88995 - 3.70847 3.76674 3.81683 3.86009 3.89639 3.92594 - 3.94935 3.96800 3.98377 3.99741 4.00979 4.02210 - 4.03675 4.05568 4.07856 4.10351 4.12875 4.15503 - 4.18287 4.19666 4.20882 4.21602 4.22017 4.22102 - 4.22168 4.22174 4.22179 4.22181 4.22181 4.22180 - 4.44069 4.51281 4.56856 4.60993 4.63709 4.65095 - 4.65356 4.64856 4.64070 4.63145 4.62173 4.61285 - 4.60686 4.60556 4.60870 4.61454 4.62167 4.63149 - 4.64529 4.65265 4.65718 4.65746 4.65714 4.65689 - 4.65647 4.65641 4.65636 4.65634 4.65638 4.65636 - 4.98214 5.07880 5.13986 5.17181 5.18124 5.17601 - 5.15966 5.13628 5.11094 5.08485 5.05827 5.03192 - 5.00724 4.98585 4.96838 4.95521 4.94679 4.94353 - 4.94279 4.94093 4.93780 4.93429 4.93044 4.92929 - 4.92833 4.92822 4.92812 4.92809 4.92809 4.92810 - 5.40861 5.52766 5.59235 5.61377 5.60504 5.58103 - 5.54693 5.50740 5.46785 5.42814 5.38592 5.34118 - 5.29831 5.26132 5.23020 5.20314 5.17903 5.16052 - 5.14642 5.13779 5.12834 5.12069 5.11399 5.11218 - 5.11073 5.11056 5.11042 5.11038 5.11038 5.11038 - 5.76149 5.89594 5.96073 5.97089 5.94500 5.90360 - 5.85318 5.79884 5.74620 5.69417 5.63849 5.57858 - 5.52075 5.47057 5.42750 5.38821 5.35047 5.31839 - 5.29203 5.27756 5.26277 5.25158 5.24206 5.23963 - 5.23770 5.23747 5.23729 5.23725 5.23725 5.23726 - 6.32366 6.46963 6.52546 6.51210 6.45540 6.38336 - 6.30409 6.22324 6.14678 6.07273 5.99518 5.91277 - 5.83295 5.76201 5.69893 5.63910 5.57939 5.52483 - 5.47739 5.45365 5.43053 5.41352 5.39829 5.39459 - 5.39166 5.39130 5.39102 5.39097 5.39095 5.39096 - 6.76108 6.90153 6.94053 6.90321 6.81941 6.72086 - 6.61651 6.51229 6.41441 6.32085 6.22587 6.12767 - 6.03272 5.94623 5.86712 5.79093 5.71458 5.64258 - 5.57810 5.54733 5.51786 5.49609 5.47542 5.47045 - 5.46654 5.46605 5.46568 5.46562 5.46558 5.46560 - 7.54679 7.64433 7.62892 7.53276 7.38980 7.23504 - 7.07788 6.92430 6.78058 6.64570 6.51682 6.39164 - 6.27213 6.15924 6.05211 5.94776 5.84400 5.74330 - 5.64936 5.60582 5.56420 5.53280 5.50141 5.49386 - 5.48788 5.48711 5.48654 5.48645 5.48640 5.48640 - 8.11587 8.09592 8.01667 7.89441 7.73431 7.54437 - 7.33607 7.12526 6.92931 6.75171 6.59260 6.44937 - 6.31876 6.19590 6.07802 5.95881 5.83431 5.71215 - 5.60217 5.55209 5.50123 5.46008 5.42232 5.41311 - 5.40553 5.40461 5.40387 5.40377 5.40372 5.40371 - 9.02028 8.75979 8.48894 8.22615 7.97111 7.72355 - 7.48369 7.25187 7.02752 6.81226 6.60738 6.41259 - 6.22982 6.05908 5.90142 5.75815 5.62934 5.50972 - 5.39590 5.34364 5.29592 5.25482 5.16842 5.13542 - 5.14593 5.15154 5.14779 5.14578 5.14867 5.14698 - 9.32030 9.10206 8.82869 8.52814 8.20694 7.87377 - 7.54010 7.22071 6.92973 6.67055 6.44202 6.23923 - 6.05770 5.89165 5.73690 5.58577 5.43257 5.28223 - 5.14104 5.07329 5.00265 4.94517 4.89596 4.88393 - 4.87367 4.87246 4.87150 4.87133 4.87127 4.87127 - 9.67172 9.37038 9.02008 8.65234 8.27330 7.89126 - 7.51670 7.16269 6.84234 6.55783 6.30738 6.08476 - 5.88426 5.70027 5.52861 5.36322 5.19947 5.04036 - 4.89043 4.81887 4.74601 4.68792 4.63645 4.62387 - 4.61341 4.61217 4.61117 4.61101 4.61093 4.61093 - 9.94407 9.56863 9.15152 8.72688 8.29996 7.87847 - 7.47169 7.09069 6.74757 6.44368 6.17595 5.93715 - 5.72006 5.51947 5.33144 5.15207 4.97831 4.81137 - 4.65436 4.58040 4.50750 4.45098 4.39810 4.38522 - 4.37487 4.37363 4.37259 4.37247 4.37237 4.37235 - 10.28204 9.89940 9.38412 8.81985 8.26310 7.76125 - 7.31608 6.92032 6.56804 6.25228 5.95988 5.68251 - 5.42433 5.19005 4.97604 4.77730 4.58927 4.40832 - 4.23698 4.15954 4.08719 4.03343 3.97869 3.96588 - 3.95584 3.95449 3.95352 3.95340 3.95329 3.95325 - 10.71760 10.03228 9.37198 8.76709 8.21142 7.70099 - 7.23254 6.80294 6.41023 6.05473 5.73192 5.43636 - 5.16343 4.91193 4.68064 4.46802 4.27168 4.08185 - 3.89261 3.80358 3.72752 3.67906 3.62537 3.61024 - 3.60079 3.60001 3.59884 3.59863 3.59858 3.59852 - 11.02909 10.32386 9.54386 8.77298 8.06099 7.44331 - 6.91007 6.44636 6.03776 5.66953 5.32342 4.99010 - 4.67685 4.39009 4.12894 3.88561 3.65579 3.43948 - 3.23796 3.14425 3.05784 2.99683 2.94147 2.92893 - 2.91925 2.91800 2.91708 2.91695 2.91687 2.91682 - 11.41018 10.38885 9.46549 8.65174 7.93040 7.28938 - 6.71802 6.20829 5.75511 5.35030 4.98479 4.64917 - 4.33295 4.03073 3.74634 3.48234 3.23866 3.00977 - 2.79249 2.68979 2.59236 2.52249 2.46717 2.45482 - 2.44481 2.44366 2.44274 2.44258 2.44252 2.44251 - 11.82060 10.54213 9.45129 8.52140 7.71891 7.02304 - 6.41791 5.88439 5.40776 4.97896 4.58912 4.23001 - 3.89285 3.57266 3.27134 2.99213 2.73215 2.48483 - 2.24723 2.13410 2.02800 1.95274 1.89223 1.87879 - 1.86805 1.86682 1.86581 1.86566 1.86557 1.86558 - 12.11766 10.66662 9.47346 8.47127 7.61933 6.88889 - 6.26142 5.71254 5.22085 4.77621 4.37090 3.99741 - 3.64791 3.31762 3.00710 2.71830 2.44989 2.19270 - 1.94354 1.82459 1.71421 1.63597 1.56910 1.55410 - 1.54240 1.54104 1.53990 1.53975 1.53962 1.53962 - 12.36039 10.78682 9.52672 8.47447 7.58838 6.83410 - 6.18939 5.62735 5.12333 4.66616 4.24879 3.86431 - 3.50544 3.16755 2.85046 2.55508 2.28089 2.01812 - 1.76152 1.63794 1.52230 1.43898 1.36643 1.35000 - 1.33718 1.33569 1.33441 1.33425 1.33412 1.33407 - 12.56865 10.90368 9.59757 8.50870 7.59704 6.82569 - 6.16759 5.59413 5.07948 4.61209 4.18503 3.79177 - 3.42526 3.08095 2.75823 2.45743 2.17778 1.91060 - 1.64788 1.52013 1.39905 1.31022 1.23228 1.21444 - 1.20042 1.19878 1.19738 1.19719 1.19707 1.19698 - 12.91413 11.12452 9.76219 8.62608 7.67968 6.88526 - 6.20799 5.61687 5.08578 4.60326 4.16228 3.75618 - 3.37783 3.02247 2.68919 2.37777 2.08647 1.80834 - 1.53324 1.39754 1.26633 1.16723 1.07820 1.05725 - 1.04062 1.03866 1.03700 1.03678 1.03663 1.03655 - 13.19413 11.32631 9.93339 8.77100 7.80499 6.99566 - 6.30527 5.70163 5.15902 4.66616 4.21579 3.80070 - 3.41315 3.04802 2.70436 2.38183 2.07806 1.78590 - 1.49706 1.35312 1.21196 1.10297 1.00195 0.97757 - 0.95812 0.95582 0.95389 0.95363 0.95344 0.95341 - 13.71799 11.73838 10.31304 9.12479 8.14542 7.31873 - 6.61026 5.98837 5.42854 4.91945 4.45331 4.02206 - 3.61678 3.23157 2.86552 2.51819 2.18612 1.85939 - 1.53162 1.36515 1.19620 1.05984 0.92712 0.89401 - 0.86745 0.86425 0.86159 0.86126 0.86094 0.86099 - 14.08506 12.04348 10.61279 9.42530 8.45121 7.62286 - 6.90935 6.28027 5.71192 5.19309 4.71614 4.27298 - 3.85451 3.45459 3.07206 2.70607 2.35187 1.99622 - 1.62838 1.43801 1.23803 1.07116 0.90612 0.86456 - 0.83120 0.82717 0.82375 0.82330 0.82302 0.82283 - 14.55520 12.44671 11.03605 9.88307 8.93272 8.11950 - 7.41335 6.78412 6.20774 5.67483 5.18030 4.71888 - 4.28470 3.87223 3.47630 3.08951 2.70161 2.29636 - 1.85609 1.61765 1.36105 1.13698 0.90158 0.84256 - 0.79859 0.79347 0.78835 0.78761 0.78799 0.78616 - 14.86687 12.64664 11.26656 10.18753 9.30016 8.52395 - 7.83006 7.19333 6.59514 6.03886 5.53552 5.08197 - 4.65434 4.23538 3.82181 3.41044 2.99879 2.58450 - 2.10787 1.81007 1.48305 1.20217 0.91269 0.83959 - 0.78212 0.77501 0.76897 0.76777 0.76911 0.76567 - 14.76493 12.80947 11.58127 10.54463 9.63704 8.82589 - 8.09974 7.44679 6.85795 6.32424 5.83654 5.38454 - 4.95566 4.53961 4.13075 3.72083 3.29533 2.82630 - 2.27967 1.96523 1.61333 1.29870 0.93525 0.83339 - 0.76939 0.76364 0.75586 0.75445 0.75658 0.75162 - 14.85563 12.90220 11.72227 10.72096 9.83858 9.04596 - 8.33329 7.68974 7.10715 6.57727 6.09166 5.64065 - 5.21218 4.79608 4.38606 3.97266 3.53891 3.05150 - 2.46810 2.12429 1.73166 1.37536 0.95766 0.83827 - 0.76133 0.75430 0.74589 0.74446 0.74681 0.74118 - 14.95316 13.00866 11.91179 10.96668 10.12804 9.36912 - 8.68257 8.05896 7.49147 6.97292 6.49588 6.05153 - 5.62858 5.21699 4.80964 4.39528 3.95316 3.44151 - 2.80365 2.41358 1.95360 1.52286 1.00736 0.85560 - 0.75156 0.74137 0.73179 0.73045 0.73277 0.72657 - 14.99543 13.06375 12.03056 11.12910 10.32580 9.59554 - 8.93231 8.32780 7.77596 7.27041 6.80431 6.36943 - 5.95498 5.55099 5.14982 4.73903 4.29520 3.77022 - 3.09553 2.67115 2.15813 1.66348 1.06024 0.87880 - 0.74699 0.73312 0.72224 0.72105 0.72300 0.71680 - 15.01675 13.11947 12.18610 11.36100 10.62019 9.94338 - 9.32607 8.76148 8.24476 7.77050 7.33277 6.92405 - 6.53405 6.15284 5.77226 5.37839 4.94400 4.41118 - 3.68950 3.21209 2.60754 1.99243 1.19666 0.94859 - 0.74705 0.72296 0.70797 0.70711 0.70760 0.70245 - 15.00614 13.13268 12.25782 11.48111 10.78110 10.14074 - 9.55631 9.02190 8.53321 8.08534 7.67279 7.28832 - 6.92169 6.56292 6.20383 5.83002 5.41266 4.88884 - 4.15380 3.64977 2.98914 2.28808 1.33056 1.02348 - 0.75515 0.72063 0.70021 0.69943 0.69846 0.69463 - 14.98013 13.12971 12.32260 11.60294 10.95240 10.35827 - 9.81713 9.32415 8.87560 8.46718 8.09376 7.74833 - 7.42045 7.10001 6.77926 6.44404 6.06484 5.57478 - 4.85243 4.33076 3.61111 2.79713 1.58092 1.17185 - 0.78115 0.72655 0.69252 0.69108 0.68812 0.68630 - 14.95979 13.12403 12.35444 11.66621 11.04429 10.47760 - 9.96318 9.49670 9.07481 8.69354 8.34803 8.03136 - 7.73295 7.44265 7.15330 6.85145 6.50821 6.05586 - 5.36457 4.84591 4.10285 3.22170 1.81366 1.31356 - 0.81243 0.73891 0.68937 0.68656 0.68253 0.68190 - 14.93058 13.11900 12.37923 11.71491 11.11321 10.56463 - 10.06612 9.61389 9.20488 8.83632 8.50511 8.20689 - 7.93470 7.67985 7.43088 7.16442 6.84519 6.41559 - 5.75376 5.24823 4.50584 3.59186 2.03689 1.44732 - 0.84243 0.75231 0.68889 0.68448 0.68092 0.67920 - 14.90115 13.11545 12.39670 11.74852 11.15972 10.62258 - 10.13484 9.69380 9.29746 8.94326 8.62817 8.34767 - 8.09448 7.85987 7.63311 7.39182 7.10123 6.70262 - 6.07156 5.57931 4.84314 3.91079 2.24242 1.57450 - 0.87509 0.76820 0.68910 0.68326 0.67873 0.67737 - 14.88514 13.12500 12.42131 11.78726 11.21357 10.69291 - 10.22309 9.80137 9.42547 9.09284 8.80024 8.54280 - 8.31236 8.10113 7.90388 7.70856 7.48467 7.15226 - 6.56577 6.09270 5.38176 4.44239 2.60587 1.81623 - 0.94065 0.80199 0.69170 0.68208 0.67588 0.67506 - 14.86020 13.12947 12.44036 11.81849 11.25569 10.74563 - 10.28648 9.87561 9.51112 9.19075 8.91173 8.66968 - 8.45709 8.26696 8.09512 7.93086 7.74530 7.45925 - 6.92726 6.48410 5.80117 4.86591 2.92683 2.03944 - 1.00443 0.83650 0.69589 0.68212 0.67439 0.67364 - 14.79358 13.13502 12.47629 11.87697 11.33096 10.83462 - 10.38726 9.98775 9.63592 9.33056 9.07005 8.85170 - 8.67034 8.52016 8.39483 8.27757 8.14010 7.92953 - 7.52647 7.16092 6.54126 5.63689 3.59614 2.52656 - 1.15583 0.92137 0.70934 0.68591 0.67281 0.67174 - 14.73687 13.14531 12.49587 11.90467 11.36634 10.87801 - 10.43896 10.04810 9.70527 9.40963 9.15992 8.95403 - 8.78748 8.65556 8.55354 8.46704 8.37125 8.21824 - 7.89814 7.58934 7.04025 6.19517 4.11333 2.92345 - 1.29850 1.00859 0.72646 0.68850 0.67253 0.67078 - 14.58061 13.15443 12.51518 11.93276 11.40250 10.92228 - 10.49147 10.10921 9.77556 9.49012 9.25217 9.06011 - 8.91047 8.79984 8.72550 8.67626 8.63233 8.55427 - 8.34723 8.11677 7.66602 6.92099 4.89413 3.58277 - 1.55636 1.16444 0.76152 0.70266 0.67391 0.66982 - 14.44537 13.15770 12.52400 11.94605 11.42008 10.94402 - 10.51731 10.13930 9.81007 9.52959 9.29755 9.11288 - 8.97303 8.87553 8.81831 8.79080 8.77590 8.74317 - 8.61240 8.43703 8.05495 7.37874 5.44887 4.11938 - 1.79246 1.30395 0.79551 0.72250 0.67406 0.66933 - 14.34623 13.16046 12.52986 11.95339 11.42843 10.95419 - 10.52995 10.15555 9.83109 9.55601 9.32901 9.14874 - 9.01376 8.92284 8.87473 8.86014 8.86486 8.86515 - 8.78415 8.64217 8.31833 7.73041 5.90823 4.52668 - 1.99770 1.44117 0.83271 0.73695 0.67987 0.66904 - 14.27758 13.15942 12.53158 11.95836 11.43663 10.96487 - 10.54242 10.16921 9.84551 9.57143 9.34686 9.17097 - 9.04146 8.95659 8.91547 8.90985 8.92685 8.94488 - 8.90296 8.79987 8.52545 7.97839 6.22970 4.89501 - 2.21058 1.56690 0.86584 0.75748 0.67804 0.66884 - 14.19126 13.16079 12.53578 11.96504 11.44549 10.97610 - 10.55609 10.18555 9.86481 9.59403 9.37318 9.20169 - 9.07744 8.99927 8.96681 8.97311 9.00764 9.05361 - 9.06223 9.00322 8.80048 8.34788 6.75861 5.45764 - 2.58863 1.80301 0.93413 0.79311 0.68301 0.66859 - 14.13688 13.16182 12.53852 11.96923 11.45121 10.98324 - 10.56483 10.19595 9.87704 9.60822 9.38956 9.22070 - 9.09964 9.02556 8.99851 9.01233 9.05799 9.12160 - 9.16271 9.13340 8.98178 8.60099 7.14742 5.89191 - 2.91889 2.01742 0.99983 0.82849 0.68874 0.66844 - 14.05363 13.16283 12.54214 11.97492 11.45894 10.99307 - 10.57686 10.21032 9.89382 9.62763 9.41195 9.24661 - 9.12994 9.06135 9.04172 9.06609 9.12756 9.21585 - 9.30310 9.31783 9.24626 8.98646 7.79421 6.65682 - 3.59749 2.49495 1.15429 0.91469 0.70498 0.66825 - 14.00535 13.16276 12.54369 11.97762 11.46272 10.99801 - 10.58284 10.21741 9.90213 9.63733 9.42323 9.25978 - 9.14544 9.07968 9.06395 9.09392 9.16389 9.26528 - 9.37709 9.41581 9.38960 9.20439 8.19947 7.16523 - 4.12656 2.91252 1.29768 0.99758 0.72255 0.66815 - 13.95386 13.16396 12.54603 11.97982 11.46461 11.00026 - 10.58634 10.22286 9.91030 9.64830 9.43622 9.27380 - 9.16104 9.09846 9.08729 9.12191 9.19719 9.31285 - 9.46092 9.52908 9.53917 9.40289 8.67637 7.92897 - 4.89439 3.52458 1.55733 1.16962 0.75879 0.66805 - 13.92660 13.16424 12.54721 11.98133 11.46641 11.00224 - 10.58870 10.22557 9.91332 9.65194 9.44132 9.28116 - 9.17019 9.10827 9.09760 9.13513 9.21770 9.34315 - 9.49629 9.56915 9.61708 9.56838 8.96727 8.23560 - 5.50024 4.09663 1.78840 1.30129 0.79595 0.66801 - 13.91037 13.16501 12.54805 11.98206 11.46689 11.00297 - 10.58978 10.22731 9.91567 9.65487 9.44482 9.28519 - 9.17491 9.11397 9.10466 9.14408 9.22925 9.35889 - 9.52085 9.60236 9.66505 9.64560 9.15963 8.51605 - 5.93932 4.52190 2.02326 1.43839 0.83182 0.66798 - 13.89909 13.16561 12.54868 11.98254 11.46731 11.00353 - 10.59068 10.22857 9.91730 9.65686 9.44713 9.28791 - 9.17811 9.11783 9.10939 9.15008 9.23705 9.36952 - 9.53744 9.62494 9.69764 9.69825 9.29691 8.72237 - 6.28988 4.87944 2.24835 1.56773 0.86694 0.66796 - 13.88382 13.16578 12.54932 11.98345 11.46857 11.00513 - 10.59262 10.23071 9.91959 9.65930 9.44990 9.29126 - 9.18217 9.12270 9.11527 9.15743 9.24667 9.38280 - 9.55818 9.65314 9.73934 9.76660 9.47876 9.00574 - 6.82029 5.45261 2.64306 1.84652 0.93489 0.66794 - 13.87372 13.16261 12.54724 11.98411 11.47176 11.00955 - 10.59696 10.23417 9.92185 9.66040 9.45022 9.29151 - 9.18302 9.12473 9.11910 9.16333 9.25425 9.38982 - 9.56763 9.67044 9.76688 9.81020 9.59653 9.18677 - 7.19791 5.90496 2.98553 2.08408 1.00042 0.66792 - 2.50288 2.56304 2.61902 2.67130 2.71969 2.76418 - 2.80512 2.84331 2.87998 2.91556 2.95041 2.98521 - 3.02151 3.06054 3.10196 3.14443 3.18601 3.22467 - 3.25758 3.27191 3.28760 3.30253 3.32097 3.32604 - 3.33013 3.33063 3.33107 3.33112 3.33118 3.33117 - 3.12373 3.17302 3.21957 3.26430 3.30693 3.34718 - 3.38476 3.41944 3.45105 3.47968 3.50578 3.53020 - 3.55497 3.58198 3.61173 3.64462 3.68094 3.72039 - 3.76127 3.78031 3.79503 3.80252 3.81264 3.81643 - 3.81786 3.81787 3.81811 3.81810 3.81830 3.81819 - 3.60085 3.65831 3.70830 3.75211 3.78960 3.82089 - 3.84654 3.86771 3.88607 3.90230 3.91719 3.93193 - 3.94883 3.96984 3.99474 4.02192 4.04990 4.07941 - 4.11082 4.12636 4.13996 4.14797 4.15313 4.15422 - 4.15505 4.15513 4.15519 4.15521 4.15521 4.15521 - 4.32780 4.39949 4.45566 4.49822 4.52730 4.54374 - 4.54944 4.54785 4.54340 4.53753 4.53115 4.52549 - 4.52263 4.52435 4.53048 4.53939 4.54984 4.56337 - 4.58135 4.59085 4.59722 4.59864 4.59945 4.59946 - 4.59923 4.59919 4.59917 4.59916 4.59918 4.59918 - 4.86743 4.96383 5.02600 5.06020 5.07270 5.07101 - 5.05850 5.03902 5.01737 4.99485 4.97192 4.94939 - 4.92854 4.91083 4.89687 4.88707 4.88204 4.88255 - 4.88614 4.88642 4.88530 4.88323 4.88064 4.87978 - 4.87905 4.87896 4.87889 4.87887 4.87887 4.87888 - 5.29323 5.41299 5.47973 5.50419 5.49925 5.47947 - 5.44982 5.41473 5.37934 5.34357 5.30529 5.26461 - 5.22578 5.19274 5.16542 5.14194 5.12121 5.10627 - 5.09627 5.08979 5.08245 5.07635 5.07100 5.06952 - 5.06831 5.06817 5.06806 5.06803 5.06802 5.06803 - 5.64622 5.78241 5.85018 5.86417 5.84270 5.80613 - 5.76072 5.71130 5.66326 5.61551 5.56403 5.50829 - 5.45460 5.40848 5.36933 5.33368 5.29924 5.27045 - 5.24788 5.23550 5.22282 5.21321 5.20509 5.20300 - 5.20133 5.20112 5.20097 5.20092 5.20092 5.20093 - 6.20968 6.35941 6.41993 6.41180 6.36073 6.29456 - 6.22124 6.14621 6.07514 6.00605 5.93309 5.85497 - 5.77927 5.71239 5.65322 5.59692 5.54022 5.48841 - 5.44404 5.42216 5.40097 5.38546 5.37156 5.36817 - 5.36551 5.36518 5.36493 5.36488 5.36485 5.36488 - 6.64910 6.79500 6.84019 6.80933 6.73216 6.64038 - 6.54280 6.44512 6.35332 6.26532 6.17527 6.08143 - 5.99052 5.90798 5.83262 5.75975 5.68608 5.61637 - 5.55433 5.52509 5.49728 5.47684 5.45734 5.45266 - 5.44897 5.44850 5.44815 5.44809 5.44806 5.44807 - 7.44055 7.54662 7.54018 7.45284 7.31848 7.17214 - 7.02320 6.87741 6.74092 6.61257 6.48926 6.36871 - 6.25324 6.14410 6.04037 5.93890 5.83733 5.73807 - 5.64531 5.60262 5.56201 5.53145 5.50076 5.49337 - 5.48755 5.48678 5.48621 5.48614 5.48609 5.48608 - 8.01544 8.00565 7.93705 7.82530 7.67535 7.49507 - 7.29576 7.09321 6.90475 6.73388 6.58074 6.44280 - 6.31677 6.19785 6.08324 5.96667 5.84412 5.72320 - 5.61376 5.56381 5.51337 5.47285 5.43540 5.42626 - 5.41873 5.41783 5.41709 5.41699 5.41692 5.41692 - 8.92929 8.68151 8.42316 8.17212 7.92809 7.69089 - 7.46067 7.23783 7.02179 6.81415 6.61612 6.42744 - 6.24999 6.08374 5.92973 5.78919 5.66214 5.54347 - 5.42973 5.37702 5.32841 5.28655 5.20158 5.16965 - 5.17931 5.18460 5.18096 5.17904 5.18179 5.18016 - 9.23646 9.03283 8.77368 8.48617 8.17678 7.85423 - 7.53000 7.21903 6.93562 6.68332 6.46100 6.26396 - 6.08784 5.92689 5.77681 5.62954 5.47901 5.33012 - 5.18914 5.12107 5.05014 4.99249 4.94288 4.93069 - 4.92032 4.91910 4.91813 4.91796 4.91791 4.91788 - 9.59395 9.30834 8.97298 8.61863 8.25146 7.87988 - 7.51446 7.16854 6.85545 6.57752 6.33306 6.11612 - 5.92107 5.74238 5.57577 5.41470 5.25415 5.09708 - 4.94795 4.87630 4.80322 4.74487 4.69275 4.67997 - 4.66933 4.66808 4.66706 4.66689 4.66682 4.66680 - 9.87146 9.51247 9.11070 8.69952 8.28436 7.87305 - 7.47507 7.10179 6.76556 6.46789 6.20588 5.97254 - 5.76081 5.56551 5.38265 5.20790 5.03782 4.87358 - 4.71808 4.64439 4.57150 4.51471 4.46100 4.44784 - 4.43727 4.43600 4.43493 4.43481 4.43470 4.43469 - 10.21802 9.85180 9.35220 8.80158 8.25636 7.76404 - 7.32681 6.93795 6.59184 6.28168 5.99447 5.72207 - 5.46883 5.23949 5.03045 4.83657 4.65294 4.47560 - 4.30696 4.23060 4.15883 4.10488 4.04912 4.03597 - 4.02564 4.02426 4.02325 4.02312 4.02301 4.02300 - 10.65983 9.99120 9.34594 8.75380 8.20910 7.70809 - 7.24770 6.82507 6.43833 6.08791 5.76952 5.47803 - 5.20911 4.96169 4.73466 4.52661 4.33509 4.14996 - 3.96467 3.87708 3.80183 3.75331 3.69878 3.68317 - 3.67345 3.67264 3.67143 3.67122 3.67117 3.67113 - 10.97736 10.29310 9.52954 8.77099 8.06818 7.45756 - 6.93004 6.47131 6.06736 5.70339 5.36093 5.03073 - 4.72063 4.43746 4.18014 3.94077 3.71490 3.50269 - 3.30571 3.21433 3.12963 3.06912 3.01308 3.00024 - 2.99027 2.98898 2.98803 2.98790 2.98781 2.98778 - 11.36100 10.36243 9.45590 8.65437 7.94190 7.30729 - 6.74065 6.23464 5.78464 5.38276 5.02007 4.68730 - 4.37399 4.07470 3.79316 3.53198 3.29131 3.06604 - 2.85330 2.75305 2.65761 2.58861 2.53308 2.52051 - 2.51030 2.50913 2.50818 2.50802 2.50796 2.50792 - 11.77098 10.51909 9.44578 8.52771 7.73315 7.04247 - 6.44062 5.90943 5.43487 5.00805 4.62024 4.26325 - 3.92821 3.61007 3.31063 3.03300 2.77462 2.52964 - 2.29579 2.18502 2.08120 2.00745 1.94745 1.93399 - 1.92325 1.92201 1.92101 1.92085 1.92076 1.92074 - 12.06485 10.64347 9.46819 8.47771 7.63322 6.90742 - 6.28252 5.73521 5.24497 4.80186 4.39817 4.02641 - 3.67863 3.34996 3.04086 2.75310 2.48551 2.22987 - 1.98373 1.86690 1.75884 1.68245 1.61662 1.60178 - 1.59025 1.58891 1.58777 1.58763 1.58750 1.58749 - 12.30378 10.76198 9.52005 8.47955 7.60074 6.85078 - 6.20834 5.64753 5.14462 4.68870 4.27269 3.88969 - 3.53232 3.19586 2.88001 2.58547 2.31178 2.05013 - 1.79608 1.67437 1.56091 1.47952 1.40844 1.39235 - 1.37983 1.37837 1.37712 1.37696 1.37683 1.37681 - 12.50821 10.87665 9.58890 8.51193 7.60750 6.84032 - 6.18433 5.61195 5.09828 4.63198 4.20615 3.81421 - 3.44909 3.10610 2.78454 2.48450 2.20528 1.93900 - 1.67851 1.55244 1.43338 1.34644 1.27033 1.25296 - 1.23933 1.23773 1.23637 1.23619 1.23607 1.23603 - 12.84720 11.09342 9.74932 8.62534 7.68629 6.89596 - 6.22077 5.63078 5.10067 4.61919 4.17937 3.77448 - 3.39736 3.04319 2.71096 2.40032 2.10958 1.83227 - 1.55898 1.42465 1.29521 1.19796 1.11121 1.09091 - 1.07480 1.07290 1.07129 1.07108 1.07094 1.07087 - 13.12223 11.29141 9.91658 8.76638 7.80783 7.00278 - 6.31469 5.71244 5.17103 4.67936 4.23019 3.81630 - 3.42990 3.06581 2.72312 2.40145 2.09849 1.80729 - 1.51996 1.37717 1.23764 1.13051 1.03207 1.00844 - 0.98961 0.98738 0.98551 0.98526 0.98508 0.98500 - 13.63732 11.69485 10.28636 9.11020 8.13858 7.31713 - 6.61228 5.99304 5.43535 4.92802 4.46334 4.03331 - 3.62905 3.24471 2.87953 2.53325 2.20251 1.87705 - 1.55038 1.38474 1.21733 1.08305 0.95357 0.92145 - 0.89567 0.89257 0.89000 0.88969 0.88938 0.88938 - 13.99843 11.99201 10.57637 9.40049 8.43460 7.61293 - 6.90478 6.27998 5.71484 5.19837 4.72309 4.28114 - 3.86360 3.46452 3.08294 2.71819 2.36554 2.01126 - 1.64438 1.45470 1.25637 1.09188 0.93073 0.89039 - 0.85803 0.85413 0.85080 0.85035 0.85009 0.85008 - 14.49293 12.34678 10.94373 9.82792 8.91553 8.12238 - 7.42088 6.78707 6.20272 5.66385 5.17112 4.71898 - 4.29279 3.88163 3.48186 3.08913 2.69957 2.30970 - 1.88264 1.63490 1.37124 1.14840 0.92404 0.86819 - 0.82454 0.81892 0.81403 0.81317 0.81376 0.81277 - 14.78651 12.55866 11.18437 10.12695 9.26260 8.50057 - 7.81349 7.17990 6.58440 6.03097 5.53057 5.07984 - 4.65456 4.23729 3.82501 3.41491 3.00463 2.59148 - 2.11616 1.81971 1.49504 1.21725 0.93312 0.86201 - 0.80712 0.80023 0.79388 0.79261 0.79416 0.79193 - 14.64183 12.73142 11.51862 10.49272 9.59353 8.78983 - 8.07027 7.42326 6.83977 6.31086 5.82742 5.37909 - 4.95312 4.53920 4.13176 3.72274 3.29792 2.82995 - 2.28553 1.97295 1.62372 1.31207 0.95396 0.85456 - 0.79381 0.78839 0.78013 0.77857 0.78111 0.77738 - 14.72842 12.82148 11.65612 10.66505 9.79097 9.00576 - 8.29972 7.66223 7.08515 6.56027 6.07916 5.63202 - 5.20669 4.79288 4.38442 3.97202 3.53902 3.05279 - 2.47186 2.13014 1.74051 1.38741 0.97516 0.85829 - 0.78520 0.77860 0.76961 0.76801 0.77086 0.76636 - 14.82148 12.92555 11.84180 10.90619 10.07541 9.32363 - 8.64357 8.02594 7.46397 6.95051 6.47806 6.03773 - 5.61809 5.20901 4.80346 4.39035 3.94924 3.43907 - 2.80417 2.41652 1.96000 1.53289 1.02293 0.87377 - 0.77446 0.76487 0.75466 0.75310 0.75605 0.75068 - 14.86156 12.97981 11.95857 11.06614 10.27026 9.54682 - 8.88985 8.29111 7.74464 7.24406 6.78247 6.35160 - 5.94049 5.53913 5.13993 4.73062 4.28809 3.76493 - 3.09358 2.67188 2.16262 1.67195 1.07431 0.89553 - 0.76903 0.75591 0.74446 0.74304 0.74566 0.74003 - 14.88042 13.03485 12.11185 11.29478 10.56073 9.89012 - 9.27848 8.71919 8.20740 7.73771 7.30417 6.89924 - 6.51250 6.13400 5.75564 5.36365 4.93110 4.40074 - 3.68315 3.20883 2.60848 1.99787 1.20813 0.96283 - 0.76728 0.74422 0.72915 0.72812 0.72916 0.72421 - 14.86844 13.04767 12.18228 11.41320 10.71944 10.08492 - 9.50579 8.97632 8.49220 8.04855 7.63990 7.25897 - 6.89548 6.53941 6.18265 5.81096 5.39579 4.87487 - 4.14438 3.64368 2.98748 2.29122 1.34025 1.03603 - 0.77397 0.74067 0.72076 0.71990 0.71929 0.71554 - 14.84079 13.04417 12.24565 11.53273 10.88816 10.29934 - 9.76305 9.27453 8.83009 8.42544 8.05550 7.71327 - 7.38831 7.07052 6.75218 6.41932 6.04266 5.55596 - 4.83866 4.32055 3.60559 2.79674 1.58813 1.18212 - 0.79790 0.74481 0.71229 0.71096 0.70801 0.70623 - 14.81931 13.03777 12.27617 11.59443 10.97806 10.41646 - 9.90665 9.44439 9.02637 8.64865 8.30639 7.99275 - 7.69710 7.40937 7.12246 6.82305 6.48249 6.03363 - 5.34755 4.83256 4.09432 3.21852 1.81893 1.32227 - 0.82772 0.75591 0.70865 0.70613 0.70186 0.70130 - 14.78983 13.03203 12.29952 11.64141 11.04517 10.50159 - 10.00774 9.55972 9.15454 8.78944 8.46137 8.16603 - 7.89651 7.64419 7.39758 7.13324 6.81610 6.38968 - 5.73368 5.23243 4.49548 3.58703 2.04037 1.45455 - 0.85650 0.76850 0.70790 0.70360 0.70004 0.69825 - 14.75984 13.02788 12.31645 11.67425 11.09083 10.55845 - 10.07506 9.63799 9.24527 8.89437 8.58232 8.30467 - 8.05414 7.82209 7.59778 7.35872 7.07036 6.67483 - 6.04912 5.56099 4.83043 3.90409 2.24458 1.58074 - 0.88819 0.78358 0.70781 0.70222 0.69761 0.69619 - 14.74432 13.03674 12.33984 11.71168 11.14298 10.62689 - 10.16123 9.74327 9.37083 9.04134 8.75163 8.49684 - 8.26888 8.06003 7.86512 7.67218 7.45088 7.12162 - 6.53975 6.07038 5.36519 4.43248 2.60572 1.82077 - 0.95231 0.81607 0.70984 0.70085 0.69440 0.69357 - 14.72009 13.04102 12.35828 11.74197 11.18400 10.67845 - 10.22320 9.81594 9.45472 9.13734 8.86102 8.62149 - 8.41128 8.22347 8.05394 7.89208 7.70912 7.42612 - 6.89844 6.45879 5.78158 4.85326 2.92478 2.04249 - 1.01496 0.84962 0.71358 0.70064 0.69268 0.69197 - 14.65580 13.04652 12.39360 11.79928 11.25769 10.76544 - 10.32163 9.92541 9.57653 9.27390 9.01586 8.79980 - 8.62056 8.47246 8.34923 8.23431 8.09960 7.89213 - 7.49289 7.13033 6.51582 5.61864 3.59077 2.52648 - 1.16428 0.93280 0.72610 0.70387 0.69082 0.68981 - 14.60259 13.05694 12.41271 11.82621 11.29204 10.80753 - 10.37201 9.98433 9.64432 9.35120 9.10373 8.89988 - 8.73527 8.60530 8.50526 8.42092 8.32754 8.17733 - 7.86103 7.55528 7.01135 6.17347 4.10473 2.92048 - 1.30574 1.01912 0.74245 0.70575 0.69035 0.68873 - 14.45373 13.06602 12.43157 11.85351 11.32722 10.85066 - 10.42313 10.04389 9.71288 9.42973 9.19381 9.00354 - 8.85555 8.74649 8.67376 8.62630 8.58445 8.50899 - 8.30567 8.07815 7.63209 6.89393 4.88126 3.57600 - 1.56167 1.17341 0.77625 0.71887 0.69176 0.68764 - 14.32438 13.06912 12.44010 11.86646 11.34429 10.87187 - 10.44828 10.07312 9.74643 9.46813 9.23803 9.05505 - 8.91666 8.82047 8.76449 8.73833 8.72518 8.69495 - 8.56814 8.39567 8.01765 7.34717 5.43249 4.11098 - 1.79640 1.31129 0.80912 0.73821 0.69185 0.68708 - 14.22952 13.07169 12.44583 11.87360 11.35251 10.88169 - 10.46050 10.08887 9.76686 9.49386 9.26871 9.09001 - 8.95639 8.86663 8.81958 8.80612 8.81233 8.81486 - 8.73743 8.59810 8.27845 7.69708 5.88962 4.51396 - 2.00070 1.44831 0.84557 0.75148 0.69780 0.68675 - 14.16386 13.07067 12.44742 11.87841 11.36042 10.89207 - 10.47266 10.10216 9.78084 9.50881 9.28601 9.11163 - 8.98340 8.89964 8.85949 8.85478 8.87284 8.89272 - 8.85442 8.75421 8.48377 7.94195 6.20780 4.88223 - 2.21245 1.57249 0.87789 0.77184 0.69560 0.68653 - 14.08148 13.07196 12.45158 11.88481 11.36908 10.90296 - 10.48593 10.11800 9.79959 9.53077 9.31162 9.14155 - 9.01849 8.94125 8.90958 8.91652 8.95173 8.99906 - 9.01073 8.95436 8.75554 8.30812 6.73258 5.44098 - 2.58816 1.80735 0.94501 0.80640 0.70023 0.68625 - 14.02959 13.07291 12.45430 11.88896 11.37454 10.90982 - 10.49438 10.12809 9.81145 9.54457 9.32756 9.16005 - 9.04010 8.96685 8.94043 8.95474 9.00086 9.06544 - 9.10903 9.08207 8.93431 8.55875 7.11816 5.87197 - 2.91662 2.02083 1.00978 0.84089 0.70561 0.68608 - 13.95024 13.07404 12.45777 11.89449 11.38208 10.91945 - 10.50611 10.14206 9.82776 9.56345 9.34932 9.18524 - 9.06954 9.00163 8.98246 9.00707 9.06869 9.15738 - 9.24601 9.26246 9.19438 8.93977 7.75943 6.63098 - 3.59175 2.49599 1.16249 0.92548 0.72115 0.68586 - 13.90411 13.07398 12.45921 11.89716 11.38582 10.92423 - 10.51191 10.14897 9.83585 9.57285 9.36027 9.19803 - 9.08460 9.01946 9.00409 9.03417 9.10407 9.20552 - 9.31809 9.35811 9.33490 9.15454 8.16114 7.13568 - 4.11833 2.91088 1.30465 1.00726 0.73820 0.68575 - 13.85492 13.07510 12.46145 11.89924 11.38767 10.92643 - 10.51523 10.15421 9.84372 9.58350 9.37288 9.21163 - 9.09972 9.03771 9.02680 9.06136 9.13633 9.25168 - 9.40003 9.46905 9.48103 9.34801 8.63346 7.89728 - 4.88148 3.51743 1.56256 1.17829 0.77351 0.68563 - 13.82887 13.07519 12.46251 11.90083 11.38944 10.92847 - 10.51758 10.15682 9.84662 9.58698 9.37781 9.21876 - 9.10860 9.04719 9.03670 9.07413 9.15630 9.28133 - 9.43433 9.50752 9.55682 9.51139 8.92134 8.19852 - 5.48488 4.08733 1.79230 1.30842 0.80963 0.68558 - 13.81340 13.07596 12.46335 11.90135 11.38991 10.92919 - 10.51872 10.15855 9.84891 9.58983 9.38119 9.22267 - 9.11318 9.05270 9.04348 9.08272 9.16751 9.29664 - 9.45821 9.53986 9.60347 9.58675 9.11151 8.47636 - 5.92091 4.50988 2.02563 1.44463 0.84442 0.68555 - 13.80265 13.07647 12.46397 11.90182 11.39033 10.92964 - 10.51955 10.15977 9.85051 9.59176 9.38345 9.22532 - 9.11627 9.05637 9.04800 9.08848 9.17506 9.30697 - 9.47434 9.56185 9.63514 9.63800 9.24681 8.68033 - 6.26873 4.86508 2.24864 1.57321 0.87860 0.68553 - 13.78808 13.07685 12.46461 11.90272 11.39148 10.93113 - 10.52131 10.16179 9.85270 9.59413 9.38613 9.22855 - 9.12018 9.06107 9.05367 9.09558 9.18441 9.31986 - 9.49449 9.58928 9.67573 9.70463 9.42539 8.95990 - 6.79470 5.43439 2.64028 1.84968 0.94527 0.68550 - 13.77850 13.07397 12.46273 11.90338 11.39456 10.93534 - 10.52552 10.16515 9.85489 9.59517 9.38641 9.22875 - 9.12099 9.06308 9.05747 9.10143 9.19183 9.32663 - 9.50357 9.60609 9.70272 9.74733 9.54038 9.13787 - 7.16895 5.88385 2.98043 2.08519 1.01033 0.68548 - 2.41518 2.47514 2.53118 2.58374 2.63263 2.67780 - 2.71956 2.75862 2.79615 2.83255 2.86812 2.90355 - 2.94031 2.97965 3.02131 3.06414 3.10643 3.14593 - 3.17966 3.19449 3.21099 3.22692 3.24654 3.25194 - 3.25630 3.25684 3.25731 3.25736 3.25741 3.25742 - 3.02583 3.07547 3.12255 3.16795 3.21141 3.25265 - 3.29138 3.32736 3.36045 3.39069 3.41851 3.44473 - 3.47128 3.49998 3.53130 3.56563 3.60331 3.64417 - 3.68679 3.70687 3.72277 3.73136 3.74297 3.74724 - 3.74901 3.74905 3.74933 3.74933 3.74952 3.74942 - 3.50473 3.55380 3.59895 3.64139 3.68078 3.71680 - 3.74911 3.77745 3.80168 3.82193 3.83889 3.85371 - 3.86896 3.88710 3.90887 3.93505 3.96634 4.00282 - 4.04305 4.06217 4.07544 4.08004 4.08733 4.09071 - 4.09133 4.09118 4.09136 4.09133 4.09155 4.09143 - 4.22028 4.29134 4.34780 4.39148 4.42246 4.44148 - 4.45027 4.45202 4.45086 4.44815 4.44479 4.44205 - 4.44207 4.44670 4.45577 4.46771 4.48126 4.49790 - 4.51892 4.53001 4.53825 4.54139 4.54374 4.54415 - 4.54425 4.54423 4.54424 4.54425 4.54427 4.54425 - 4.75842 4.85368 4.91666 4.95312 4.96877 4.97053 - 4.96160 4.94579 4.92788 4.90903 4.88958 4.87031 - 4.85273 4.83852 4.82820 4.82194 4.82012 4.82367 - 4.83063 4.83295 4.83399 4.83360 4.83247 4.83199 - 4.83154 4.83148 4.83144 4.83143 4.83142 4.83143 - 5.18405 5.30303 5.37116 5.39864 5.39763 5.38198 - 5.35652 5.32559 5.29426 5.26243 5.22797 5.19095 - 5.15577 5.12644 5.10284 5.08294 5.06551 5.05372 - 5.04721 5.04287 5.03774 5.03333 5.02934 5.02819 - 5.02725 5.02714 5.02705 5.02703 5.02701 5.02702 - 5.53756 5.67350 5.74333 5.76105 5.74420 5.71237 - 5.67164 5.62679 5.58310 5.53954 5.49210 5.44032 - 5.39050 5.34818 5.31274 5.28058 5.24940 5.22378 - 5.20475 5.19448 5.18397 5.17598 5.16914 5.16735 - 5.16592 5.16575 5.16562 5.16558 5.16557 5.16558 - 6.10318 6.25383 6.31770 6.31453 6.26921 6.20883 - 6.14109 6.07133 6.00516 5.94065 5.87211 5.79828 - 5.72665 5.66355 5.60785 5.55476 5.50109 5.45237 - 5.41148 5.39149 5.37218 5.35806 5.34530 5.34217 - 5.33972 5.33942 5.33919 5.33915 5.33912 5.33914 - 6.54530 6.69324 6.74291 6.71807 6.64761 6.56245 - 6.47118 6.37938 6.29295 6.20987 6.12452 6.03518 - 5.94842 5.86953 5.79737 5.72737 5.65647 5.58972 - 5.53098 5.50332 5.47702 5.45767 5.43917 5.43473 - 5.43125 5.43079 5.43046 5.43041 5.43037 5.43040 - 7.34381 7.45399 7.45415 7.37484 7.24900 7.11081 - 6.96945 6.83060 6.70035 6.57762 6.45948 6.34369 - 6.23239 6.12674 6.02584 5.92676 5.82743 5.73072 - 5.64065 5.59883 5.55890 5.52883 5.49883 5.49161 - 5.48591 5.48517 5.48463 5.48455 5.48449 5.48449 - 7.89660 7.95593 7.90188 7.76997 7.59464 7.41057 - 7.22681 7.04855 6.88134 6.72575 6.58141 6.44622 - 6.31874 6.19642 6.07845 5.96266 5.84737 5.73404 - 5.62520 5.57318 5.52254 5.48386 5.44624 5.43701 - 5.42968 5.42873 5.42802 5.42793 5.42785 5.42785 - 8.84549 8.60886 8.36153 8.12086 7.88660 7.65858 - 7.43700 7.22219 7.01365 6.81290 6.62113 6.43807 - 6.26560 6.10362 5.95316 5.81539 5.69032 5.57291 - 5.45975 5.40689 5.35771 5.31527 5.23116 5.19989 - 5.20886 5.21391 5.21035 5.20849 5.21114 5.20955 - 9.16337 8.96963 8.72120 8.44442 8.14556 7.83315 - 7.51844 7.21602 6.94013 6.69429 6.47753 6.28544 - 6.11392 5.95739 5.81152 5.66795 5.52029 5.37334 - 5.23315 5.16493 5.09364 5.03554 4.98540 4.97303 - 4.96251 4.96126 4.96028 4.96011 4.96006 4.95999 - 9.52697 9.25222 8.92826 8.58501 8.22850 7.86696 - 7.51081 7.17318 6.86734 6.59564 6.35660 6.14455 - 5.95420 5.78013 5.61807 5.46115 5.30396 5.14926 - 5.00113 4.92941 4.85604 4.79729 4.74446 4.73144 - 4.72062 4.71934 4.71829 4.71813 4.71805 4.71801 - 9.80936 9.46220 9.07240 8.67250 8.26790 7.86635 - 7.47720 7.11178 6.78243 6.49072 6.23393 6.00540 - 5.79836 5.60775 5.42956 5.25923 5.09297 4.93158 - 4.77750 4.70390 4.63090 4.57382 4.51935 4.50593 - 4.49516 4.49388 4.49279 4.49265 4.49255 4.49253 - 10.16504 9.80905 9.32191 8.78389 8.25006 7.76700 - 7.33729 6.95479 6.61443 6.30954 6.02729 5.75972 - 5.51112 5.28623 5.08161 4.89229 4.71327 4.53958 - 4.37298 4.29734 4.22592 4.17180 4.11534 4.10197 - 4.09146 4.09005 4.08901 4.08888 4.08878 4.08879 - 10.60998 9.95592 9.32375 8.74285 8.20788 7.71531 - 7.26229 6.84610 6.46499 6.11943 5.80538 5.51794 - 5.25302 5.00962 4.78673 4.58304 4.39605 4.21518 - 4.03322 3.94674 3.87198 3.82327 3.76829 3.75252 - 3.74263 3.74180 3.74056 3.74034 3.74031 3.74030 - 10.93490 10.26767 9.51805 8.77033 8.07588 7.47194 - 6.94993 6.49593 6.09622 5.73616 5.39738 5.07069 - 4.76397 4.48400 4.22994 3.99427 3.77272 3.56487 - 3.37163 3.28171 3.19803 3.13783 3.08160 3.06865 - 3.05857 3.05726 3.05630 3.05617 3.05608 3.05606 - 11.32090 10.34130 9.44898 8.65800 7.95341 7.32471 - 6.76266 6.26041 5.81371 5.41483 5.05504 4.72509 - 4.41455 4.11794 3.83904 3.58074 3.34346 3.12196 - 2.91314 2.81468 2.72038 2.65168 2.59631 2.58371 - 2.57343 2.57225 2.57130 2.57114 2.57108 2.57100 - 11.72967 10.50008 9.44162 8.53386 7.74656 7.06096 - 6.46263 5.93412 5.46185 5.03715 4.65142 4.29645 - 3.96337 3.64707 3.34939 3.07351 2.81715 2.57480 - 2.34434 2.23541 2.13302 2.06000 2.00061 1.98726 - 1.97656 1.97533 1.97434 1.97419 1.97410 1.97402 - 12.01802 10.62265 9.46333 8.48352 7.64614 6.92502 - 6.30304 5.75771 5.26918 4.82771 4.42567 4.05553 - 3.70932 3.38210 3.07433 2.78778 2.52145 2.26764 - 2.02429 1.90913 1.80266 1.72743 1.66258 1.64796 - 1.63660 1.63529 1.63417 1.63403 1.63390 1.63389 - 12.24969 10.73783 9.51321 8.48407 7.61243 6.86692 - 6.22697 5.66764 5.16607 4.71152 4.29695 3.91539 - 3.55941 3.22418 2.90944 2.61588 2.34315 2.08290 - 1.83113 1.71091 1.59905 1.51905 1.44931 1.43355 - 1.42131 1.41989 1.41866 1.41851 1.41839 1.41842 - 12.44680 10.84874 9.57962 8.51476 7.61774 6.85482 - 6.20104 5.62986 5.11729 4.65218 4.22767 3.83707 - 3.47323 3.13138 2.81084 2.51172 2.23336 1.96825 - 1.70966 1.58489 1.46740 1.38199 1.30752 1.29058 - 1.27732 1.27577 1.27444 1.27427 1.27415 1.27419 - 12.77372 11.05866 9.73520 8.62456 7.69343 6.90733 - 6.23411 5.64506 5.11583 4.63538 4.19670 3.79303 - 3.41709 3.06401 2.73279 2.42311 2.13330 1.85699 - 1.58512 1.45184 1.32388 1.22829 1.14365 1.12395 - 1.10833 1.10650 1.10494 1.10473 1.10460 1.10456 - 13.04079 11.25152 9.89826 8.76210 7.81184 7.01119 - 6.32514 5.72386 5.18333 4.69262 4.24451 3.83175 - 3.44648 3.08350 2.74189 2.42129 2.11940 1.82923 - 1.54307 1.40118 1.26306 1.15768 1.06167 1.03876 - 1.02052 1.01836 1.01656 1.01632 1.01614 1.01599 - 13.54969 11.64941 10.26129 9.09873 8.13515 7.31843 - 6.61621 5.99859 5.44224 4.93618 4.47272 4.04389 - 3.64076 3.25751 2.89343 2.54837 2.21896 1.89480 - 1.56933 1.40451 1.23847 1.10597 0.97930 0.94801 - 0.92290 0.91989 0.91741 0.91710 0.91680 0.91673 - 13.91528 11.94713 10.54806 9.38365 8.42463 7.60762 - 6.90269 6.28033 5.71734 5.20282 4.72932 4.28890 - 3.87260 3.47447 3.09374 2.73004 2.37883 2.02620 - 1.66105 1.47235 1.27545 1.11269 0.95432 0.91484 - 0.88318 0.87936 0.87610 0.87565 0.87539 0.87566 - 14.41890 12.31112 10.91693 9.80359 8.89244 8.10361 - 7.40819 6.78014 6.19942 5.66281 5.17248 4.72320 - 4.29896 3.88817 3.48804 3.09553 2.70759 2.32033 - 1.89637 1.65020 1.38824 1.16700 0.94499 0.89012 - 0.84755 0.84202 0.83704 0.83614 0.83668 0.83708 - 14.72322 12.52864 11.15697 10.09684 9.23112 8.47324 - 7.79359 7.16742 6.57640 6.02560 5.52819 5.08127 - 4.65847 4.24119 3.82766 3.41710 3.00851 2.59853 - 2.12751 1.83347 1.51087 1.23445 0.95222 0.88233 - 0.82912 0.82233 0.81571 0.81435 0.81578 0.81578 - 14.90379 12.66109 11.32420 10.31168 9.48565 8.75432 - 8.08903 7.46707 6.87249 6.31574 5.81706 5.37509 - 4.95653 4.53778 4.11745 3.69609 3.27356 2.84590 - 2.33712 2.00512 1.63037 1.30571 0.96666 0.88152 - 0.81684 0.80883 0.80103 0.79933 0.80142 0.80073 - 15.01215 12.74548 11.44865 10.47642 9.68408 8.97507 - 8.32238 7.70582 7.11192 6.55449 6.05800 5.62205 - 5.20890 4.79153 4.36856 3.94108 3.50901 3.06691 - 2.52702 2.16454 1.74636 1.37762 0.98509 0.88482 - 0.80804 0.79876 0.79004 0.78808 0.79062 0.78920 - 14.76831 12.89787 11.81105 10.87246 10.03996 9.28823 - 8.60968 7.99488 7.43677 6.92788 6.46038 6.02495 - 5.60944 5.20331 4.79966 4.38766 3.94746 3.43920 - 2.80836 2.42363 1.97044 1.54583 1.03800 0.89004 - 0.79445 0.78549 0.77471 0.77278 0.77578 0.77260 - 14.80647 12.95111 11.92538 11.02920 10.23110 9.50733 - 8.85165 8.25563 7.71304 7.21716 6.76078 6.33509 - 5.92843 5.53029 5.13320 4.72517 4.28360 3.76240 - 3.09524 2.67661 2.17094 1.68317 1.08796 0.91057 - 0.78844 0.77609 0.76415 0.76234 0.76500 0.76122 - 14.86408 13.02927 12.08678 11.25478 10.51021 9.83364 - 9.21986 8.66175 8.15388 7.69024 7.26412 6.86688 - 6.48664 6.11252 5.73709 5.34799 4.92125 4.40577 - 3.70869 3.23461 2.61335 1.98263 1.21280 0.97986 - 0.78681 0.76386 0.74840 0.74623 0.74780 0.74425 - 14.82774 13.02691 12.14777 11.36778 10.66638 10.02739 - 9.44667 8.91814 8.43710 7.99832 7.59575 7.22147 - 6.86412 6.51306 6.16060 5.79337 5.38465 4.87597 - 4.16077 3.66037 2.98933 2.27910 1.34461 1.04993 - 0.79177 0.75943 0.73980 0.73785 0.73819 0.73490 - 14.73818 12.98208 12.18459 11.47268 10.82951 10.24288 - 9.70939 9.22426 8.78370 8.38333 8.01791 7.68016 - 7.35929 7.04489 6.72930 6.39864 6.02400 5.53987 - 4.82690 4.31202 3.60137 2.79714 1.59503 1.19167 - 0.81353 0.76189 0.73074 0.72941 0.72623 0.72484 - 14.70081 12.96425 12.20642 11.52797 10.91487 10.35664 - 9.85037 9.39181 8.97765 8.60385 8.26557 7.95579 - 7.66372 7.37912 7.09492 6.79793 6.45972 6.01380 - 5.33223 4.82051 4.08669 3.21581 1.82395 1.33047 - 0.84218 0.77198 0.72679 0.72447 0.71986 0.71950 - 14.66124 12.95031 12.22305 11.56976 10.97801 10.43905 - 9.94968 9.50599 9.10481 8.74339 8.41875 8.12661 - 7.86014 7.61070 7.36672 7.10455 6.78927 6.36564 - 5.71498 5.21780 4.48600 3.58274 2.04361 1.46135 - 0.86994 0.78393 0.72586 0.72162 0.71801 0.71619 - 14.62348 12.94095 12.23646 11.60035 11.02216 10.49470 - 10.01576 9.58278 9.19379 8.84633 8.53742 8.26271 - 8.01502 7.78571 7.56403 7.32750 7.04158 6.64912 - 6.02820 5.54378 4.81851 3.89793 2.24664 1.58661 - 0.90078 0.79831 0.72554 0.72015 0.71546 0.71394 - 14.60155 12.94452 12.25586 11.63460 11.07185 10.56110 - 10.10006 9.68617 9.31727 8.99087 8.70389 8.45159 - 8.22600 8.01954 7.82711 7.63687 7.41857 7.09277 - 6.51550 6.04958 5.34970 4.42317 2.60558 1.82514 - 0.96363 0.82963 0.72710 0.71867 0.71204 0.71110 - 14.57736 12.94801 12.27341 11.66389 11.11180 10.61133 - 10.16062 9.75726 9.39940 9.08492 8.81113 8.57387 - 8.36587 8.18036 8.01329 7.85413 7.67423 7.39475 - 6.87156 6.43527 5.76334 4.84137 2.92288 2.04553 - 1.02523 0.86231 0.73046 0.71828 0.71014 0.70935 - 14.51992 12.95695 12.31054 11.72165 11.18475 10.69657 - 10.25644 9.86351 9.51758 9.21764 8.96211 8.74838 - 8.57140 8.42559 8.30476 8.19247 8.06068 7.85649 - 7.46138 7.10185 6.49217 5.60158 3.58583 2.52672 - 1.17258 0.94390 0.74217 0.72104 0.70799 0.70700 - 14.47445 12.97061 12.33101 11.74874 11.21850 10.73749 - 10.30534 9.92074 9.58355 9.29302 9.04800 8.84642 - 8.68400 8.55617 8.45830 8.37623 8.28539 8.13817 - 7.82601 7.52343 6.98448 6.15327 4.09682 2.91800 - 1.31289 1.02935 0.75784 0.72232 0.70729 0.70583 - 14.33487 12.98113 12.35041 11.77579 11.25273 10.77943 - 10.35496 9.97860 9.65024 9.36949 9.13579 8.94754 - 8.80142 8.69413 8.62311 8.57744 8.53770 8.46499 - 8.26589 8.04160 7.60043 6.86885 4.86929 3.56978 - 1.56693 1.18218 0.79053 0.73451 0.70872 0.70463 - 14.21017 12.98356 12.35828 11.78809 11.26921 10.79991 - 10.37937 10.00702 9.68287 9.40683 9.17876 8.99758 - 8.86079 8.76600 8.71134 8.68655 8.67508 8.64752 - 8.52524 8.35614 7.98257 7.31779 5.41715 4.10304 - 1.80028 1.31851 0.82237 0.75343 0.70878 0.70403 - 14.11759 12.98336 12.36177 11.79456 11.27831 10.81150 - 10.39341 10.02373 9.70269 9.43025 9.20642 9.03020 - 8.89922 8.81152 8.76590 8.75345 8.76012 8.76165 - 8.69043 8.56238 8.24861 7.65344 5.84464 4.52101 - 2.01272 1.45197 0.85610 0.76937 0.71050 0.70367 - 14.05356 12.98295 12.36403 11.79881 11.28444 10.81938 - 10.40303 10.03528 9.71639 9.44642 9.22543 9.05256 - 8.92553 8.84274 8.80344 8.79965 8.81904 8.84115 - 8.80682 8.70977 8.44386 7.90781 6.18730 4.86995 - 2.21438 1.57812 0.88971 0.78584 0.71245 0.70343 - 13.97287 12.98287 12.36705 11.80454 11.29251 10.82986 - 10.41587 10.05068 9.73463 9.46782 9.25033 9.08161 - 8.95962 8.88316 8.85215 8.85978 8.89599 8.94499 - 8.95990 8.90637 8.71202 8.27049 6.70831 5.42530 - 2.58795 1.81180 0.95573 0.81939 0.71689 0.70312 - 13.92027 12.98602 12.37245 11.80914 11.29592 10.83345 - 10.42122 10.05869 9.74580 9.48228 9.26771 9.10144 - 8.98180 8.90814 8.88118 8.89564 8.94352 9.01107 - 9.05613 9.02956 8.88877 8.52155 7.08224 5.86151 - 2.91550 2.02189 1.02012 0.85238 0.72286 0.70294 - 13.84588 12.98548 12.37380 11.81373 11.30388 10.84398 - 10.43348 10.07247 9.76128 9.49992 9.28823 9.12577 - 9.01075 8.94254 8.92251 8.94659 9.00905 9.10069 - 9.19038 9.20538 9.14358 8.89758 7.71562 6.61923 - 3.58970 2.49188 1.17030 0.93620 0.73790 0.70270 - 13.80292 12.98453 12.37423 11.81627 11.30858 10.85041 - 10.44106 10.08070 9.76980 9.50865 9.29754 9.13644 - 9.02388 8.95935 8.94438 8.97467 9.04455 9.14609 - 9.25945 9.30079 9.28073 9.10566 8.12509 7.10855 - 4.11076 2.90956 1.31159 1.01676 0.75336 0.70257 - 13.75752 12.98726 12.37774 11.81911 11.31069 10.85246 - 10.44415 10.08568 9.77736 9.51891 9.30975 9.14960 - 9.03851 8.97706 8.96641 9.00099 9.07570 9.19082 - 9.33949 9.40932 9.42327 9.29398 8.59253 7.86728 - 4.86944 3.51103 1.56780 1.18671 0.78756 0.70245 - 13.73277 12.98806 12.37931 11.82079 11.31235 10.85428 - 10.44632 10.08821 9.78019 9.52232 9.31452 9.15656 - 9.04718 8.98622 8.97590 9.01324 9.09510 9.21979 - 9.37269 9.44623 9.49693 9.45499 8.87704 8.16313 - 5.47042 4.07880 1.79623 1.31536 0.82275 0.70239 - 13.71779 12.98823 12.37964 11.82120 11.31290 10.85508 - 10.44749 10.08984 9.78236 9.52504 9.31779 9.16036 - 9.05161 8.99151 8.98239 9.02150 9.10596 9.23464 - 9.39584 9.47766 9.54216 9.52822 9.06456 8.43815 - 5.90362 4.49879 2.02815 1.45077 0.85674 0.70236 - 13.70734 12.98824 12.37976 11.82137 11.31331 10.85582 - 10.44841 10.09103 9.78387 9.52688 9.31999 9.16295 - 9.05462 8.99510 8.98676 9.02705 9.11326 9.24460 - 9.41143 9.49898 9.57291 9.57811 9.19780 8.63980 - 6.24899 4.85175 2.24922 1.57868 0.89024 0.70233 - 13.69311 12.98793 12.37979 11.82207 11.31445 10.85729 - 10.45019 10.09300 9.78597 9.52915 9.32259 9.16608 - 9.05843 8.99968 8.99232 9.03398 9.12230 9.25704 - 9.43091 9.52558 9.61241 9.64300 9.37275 8.91558 - 6.77087 5.41735 2.63787 1.85311 0.95583 0.70230 - 13.68421 12.98566 12.37851 11.82282 11.31743 10.86129 - 10.45423 10.09631 9.78815 9.53018 9.32282 9.16623 - 9.05921 9.00172 8.99619 9.03983 9.12957 9.26349 - 9.43967 9.54202 9.63893 9.68479 9.48504 9.09075 - 7.14191 5.86422 2.97603 2.08670 1.02009 0.70228 - 2.33528 2.39426 2.44966 2.50186 2.55067 2.59605 - 2.63825 2.67795 2.71619 2.75335 2.78967 2.82575 - 2.86297 2.90248 2.94414 2.98713 3.03001 3.07023 - 3.10450 3.11975 3.13728 3.15458 3.17517 3.18079 - 3.18541 3.18598 3.18647 3.18652 3.18657 3.18658 - 2.92173 2.97432 3.02432 3.07254 3.11869 3.16245 - 3.20347 3.24152 3.27638 3.30809 3.33711 3.36426 - 3.39166 3.42124 3.45350 3.48890 3.52786 3.57048 - 3.61552 3.63690 3.65365 3.66250 3.67518 3.68009 - 3.68202 3.68204 3.68237 3.68238 3.68259 3.68247 - 3.38713 3.44748 3.50086 3.54842 3.59002 3.62575 - 3.65613 3.68232 3.70595 3.72755 3.74770 3.76719 - 3.78778 3.81112 3.83766 3.86768 3.90116 3.93720 - 3.97398 3.99160 4.00722 4.01708 4.02518 4.02711 - 4.02860 4.02876 4.02889 4.02890 4.02891 4.02892 - 4.10847 4.18169 4.24076 4.28738 4.32157 4.34400 - 4.35627 4.36143 4.36347 4.36369 4.36301 4.36273 - 4.36511 4.37212 4.38369 4.39844 4.41519 4.43514 - 4.45916 4.47153 4.48092 4.48496 4.48875 4.48956 - 4.48996 4.48998 4.49004 4.49004 4.49007 4.49004 - 4.65180 4.74812 4.81262 4.85104 4.86921 4.87409 - 4.86874 4.85667 4.84227 4.82676 4.81066 4.79480 - 4.78050 4.76927 4.76177 4.75852 4.76019 4.76733 - 4.77740 4.78107 4.78349 4.78430 4.78460 4.78449 - 4.78437 4.78435 4.78434 4.78433 4.78434 4.78433 - 5.07977 5.20493 5.27467 5.30092 5.29895 5.28553 - 5.26496 5.23977 5.21299 5.18455 5.15332 5.11997 - 5.08850 5.06256 5.04213 5.02547 5.01155 5.00318 - 4.99973 4.99690 4.99334 4.99022 4.98763 4.98687 - 4.98622 4.98615 4.98609 4.98608 4.98607 4.98609 - 5.45830 5.55686 5.62190 5.65717 5.66366 5.64435 - 5.60477 5.55391 5.50269 5.45395 5.40823 5.36612 - 5.32753 5.29257 5.26095 5.23117 5.20248 5.17778 - 5.16064 5.15442 5.14621 5.13786 5.13275 5.13158 - 5.13031 5.13014 5.13005 5.13003 5.13007 5.13004 - 6.03537 6.13442 6.19188 6.21307 6.19968 6.15579 - 6.08871 6.00980 5.93258 5.86038 5.79345 5.73183 - 5.67424 5.61972 5.56759 5.51597 5.46403 5.41587 - 5.37689 5.36086 5.34382 5.32937 5.31820 5.31559 - 5.31325 5.31297 5.31276 5.31272 5.31273 5.31272 - 6.48040 6.57140 6.61551 6.61964 6.58609 6.51985 - 6.42934 6.32743 6.22913 6.13797 6.05408 5.97697 - 5.90454 5.83494 5.76712 5.69858 5.62821 5.56129 - 5.50483 5.48090 5.45664 5.43693 5.41988 5.41583 - 5.41241 5.41199 5.41166 5.41161 5.41161 5.41161 - 7.24627 7.36236 7.36948 7.29763 7.17945 7.04886 - 6.91490 6.78305 6.65919 6.54217 6.42895 6.31734 - 6.20968 6.10737 6.00947 5.91304 5.81600 5.72131 - 5.63325 5.59255 5.55375 5.52452 5.49517 5.48807 - 5.48247 5.48173 5.48119 5.48111 5.48107 5.48107 - 7.80022 7.86015 7.81543 7.69793 7.53719 7.36373 - 7.18709 7.01437 6.85316 6.70395 6.56538 6.43475 - 6.31100 6.19192 6.07673 5.96331 5.85007 5.73855 - 5.63135 5.58004 5.53010 5.49195 5.45481 5.44567 - 5.43841 5.43747 5.43677 5.43668 5.43662 5.43660 - 8.56603 8.47826 8.33185 8.14792 7.93225 7.69307 - 7.44189 7.19414 6.96546 6.76011 6.57755 6.41483 - 6.26898 6.13476 6.00817 5.88055 5.74560 5.61027 - 5.48303 5.42182 5.35742 5.30451 5.25931 5.24820 - 5.23869 5.23756 5.23667 5.23652 5.23649 5.23643 - 9.06850 8.89179 8.65930 8.39707 8.11132 7.81048 - 7.50580 7.21198 6.94338 6.70367 6.49203 6.30439 - 6.13698 5.98448 5.84243 5.70208 5.55669 5.41133 - 5.27222 5.20422 5.13275 5.07429 5.02438 5.01210 - 5.00161 5.00036 4.99940 4.99923 4.99918 4.99913 - 9.44206 9.18476 8.87669 8.54761 8.20360 7.85297 - 7.50619 7.17659 6.87766 6.61192 6.37803 6.17060 - 5.98462 5.81483 5.65683 5.50344 5.34891 5.19615 - 5.04929 4.97778 4.90416 4.84489 4.79203 4.77902 - 4.76816 4.76687 4.76584 4.76567 4.76559 4.76555 - 9.73589 9.40562 9.03081 8.64405 8.25087 7.85917 - 7.47848 7.12038 6.79747 6.51149 6.25983 6.03604 - 5.83356 5.64732 5.47332 5.30673 5.14351 4.98447 - 4.83197 4.75868 4.68548 4.62784 4.57300 4.55949 - 4.54862 4.54731 4.54623 4.54609 4.54598 4.54595 - 10.20173 9.71045 9.20657 8.72260 8.25854 7.81643 - 7.39884 7.00855 6.65007 6.32559 6.03330 5.77039 - 5.53553 5.32765 5.13914 4.95687 4.77223 4.59481 - 4.43435 4.36000 4.28836 4.23332 4.17666 4.16248 - 4.15189 4.15051 4.14944 4.14931 4.14922 4.14918 - 10.57543 9.93258 9.30977 8.73707 8.20943 7.72350 - 7.27651 6.86587 6.48989 6.14900 5.83928 5.55604 - 5.29523 5.05583 4.83691 4.63726 4.45429 4.27703 - 4.09769 4.01198 3.93755 3.88861 3.83266 3.81640 - 3.80625 3.80541 3.80412 3.80388 3.80385 3.80383 - 10.89707 10.27220 9.53445 8.78250 8.08185 7.47973 - 6.96538 6.52023 6.12638 5.76950 5.43313 5.10923 - 4.80574 4.52938 4.27908 4.04709 3.82885 3.62418 - 3.43425 3.34599 3.26342 3.20334 3.14618 3.13286 - 3.12248 3.12112 3.12012 3.11998 3.11989 3.11986 - 11.29665 10.33387 9.45215 8.66861 7.96923 7.34425 - 6.78506 6.28538 5.84136 5.44540 5.08873 4.76208 - 4.45474 4.16105 3.88479 3.62899 3.39441 3.17593 - 2.97061 2.87397 2.78112 2.71298 2.65713 2.64425 - 2.63373 2.63253 2.63155 2.63138 2.63131 2.63126 - 11.68925 10.48428 9.44043 8.54257 7.76191 7.08069 - 6.48519 5.95876 5.48846 5.06575 4.68209 4.32927 - 3.99836 3.68412 3.38830 3.11399 2.85912 2.61880 - 2.39147 2.28448 2.18396 2.11213 2.05292 2.03948 - 2.02871 2.02747 2.02647 2.02631 2.02621 2.02618 - 11.96432 10.59901 9.45700 8.48883 7.65915 6.94304 - 6.32409 5.78070 5.29377 4.85379 4.45320 4.08456 - 3.73993 3.41432 3.10802 2.82258 2.55706 2.30461 - 2.06390 1.95057 1.84606 1.77231 1.70803 1.69345 - 1.68216 1.68085 1.67973 1.67960 1.67946 1.67946 - 12.18780 10.70918 9.50304 8.48641 7.62301 6.88283 - 6.24606 5.68865 5.18849 4.73513 4.32164 3.94120 - 3.58645 3.25259 2.93913 2.64649 2.37426 2.11501 - 1.86550 1.74692 1.63691 1.55843 1.48954 1.47394 - 1.46185 1.46044 1.45922 1.45908 1.45895 1.45895 - 12.38070 10.81732 9.56685 8.51477 7.62615 6.86866 - 6.21812 5.64888 5.13762 4.67355 4.24991 3.86021 - 3.49741 3.15677 2.83741 2.53912 2.26119 1.99688 - 1.74028 1.61699 1.50121 1.41728 1.34388 1.32718 - 1.31414 1.31261 1.31129 1.31112 1.31101 1.31100 - 12.70649 11.02602 9.71983 8.62139 7.69833 6.91746 - 6.24749 5.66045 5.13257 4.65308 4.21516 3.81220 - 3.43710 3.08503 2.75485 2.44596 2.15667 1.88110 - 1.61090 1.47888 1.35248 1.25838 1.17508 1.15571 - 1.14039 1.13859 1.13705 1.13685 1.13673 1.13666 - 12.97663 11.22035 9.88222 8.75699 7.81407 7.01824 - 6.33533 5.73615 5.19708 4.70744 4.26015 3.84812 - 3.46362 3.10151 2.76080 2.44100 2.13984 1.85056 - 1.56590 1.42515 1.28858 1.18478 1.09032 1.06782 - 1.04992 1.04781 1.04603 1.04580 1.04563 1.04551 - 13.48764 11.61931 10.24388 9.09029 8.13228 7.31938 - 6.61983 6.00428 5.44972 4.94525 4.48321 4.05559 - 3.65345 3.27096 2.90755 2.56323 2.23481 1.91190 - 1.58795 1.42421 1.25975 1.12903 1.00460 0.97395 - 0.94933 0.94639 0.94397 0.94367 0.94336 0.94335 - 13.84349 11.91188 10.52696 9.37171 8.41775 7.60398 - 6.90120 6.28068 5.71967 5.20729 4.73593 4.29745 - 3.88261 3.48538 3.10519 2.74208 2.39178 2.04051 - 1.67719 1.48964 1.29430 1.13335 0.97796 0.93944 - 0.90853 0.90479 0.90160 0.90117 0.90096 0.90104 - 14.30264 12.26551 10.89348 9.78492 8.87311 8.08679 - 7.39629 6.77333 6.19601 5.66163 5.17369 4.72728 - 4.30542 3.89593 3.49623 3.10365 2.71591 2.33058 - 1.90960 1.66427 1.40358 1.18421 0.96584 0.91279 - 0.87185 0.86633 0.86121 0.86044 0.86159 0.86060 - 14.57880 12.45861 11.11548 10.06732 9.20648 8.45280 - 7.77728 7.15492 6.56714 6.01935 5.52522 5.08186 - 4.66198 4.24642 3.83345 3.42248 3.01344 2.60551 - 2.13833 1.84525 1.52388 1.24902 0.97051 0.90331 - 0.85263 0.84577 0.83875 0.83764 0.84036 0.83783 - 14.43715 12.60789 11.42244 10.41464 9.52938 8.73753 - 8.02816 7.39008 6.81447 6.29253 5.81519 5.37208 - 4.95039 4.53974 4.13480 3.72785 3.30529 2.84093 - 2.30248 1.99382 1.64895 1.34102 0.98879 0.89254 - 0.83759 0.83266 0.82337 0.82189 0.82642 0.82177 - 14.50627 12.68557 11.54835 10.57639 9.71734 8.94497 - 8.24996 7.62213 7.05353 6.53610 6.06146 5.61985 - 5.19900 4.78865 4.38283 3.97263 3.54201 3.05962 - 2.48517 2.14775 1.76292 1.41378 1.00738 0.89384 - 0.82777 0.82183 0.81158 0.81004 0.81536 0.80953 - 14.57216 12.77030 11.71562 10.80127 9.98722 9.24984 - 8.58209 7.97517 7.42249 6.91706 6.45150 6.01699 - 5.60208 5.19672 4.79407 4.38340 3.94497 3.43908 - 2.81141 2.42861 1.97757 1.55500 1.05103 0.90552 - 0.81507 0.80644 0.79480 0.79330 0.79928 0.79198 - 14.59354 12.81091 11.81936 10.94942 10.17153 9.46348 - 8.81966 8.23226 7.69558 7.20334 6.74888 6.32397 - 5.91775 5.52027 5.12420 4.71760 4.27802 3.75950 - 3.09589 2.67941 2.17610 1.69060 1.09932 0.92448 - 0.80807 0.79617 0.78339 0.78203 0.78787 0.78000 - 14.63939 12.87875 11.96977 11.16411 10.44049 9.78043 - 9.17939 8.63076 8.12957 7.67024 7.24648 6.85025 - 6.47037 6.09658 5.72159 5.33336 4.90848 4.39690 - 3.70611 3.23517 2.61566 1.98612 1.22092 0.99131 - 0.80496 0.78263 0.76645 0.76458 0.76891 0.76218 - 14.60769 12.87848 12.02979 11.27417 10.59237 9.96909 - 9.40065 8.88143 8.40712 7.97285 7.57299 7.20007 - 6.84345 6.49304 6.14126 5.77510 5.36833 4.86356 - 4.15481 3.65784 2.98916 2.28076 1.35132 1.05990 - 0.80859 0.77714 0.75733 0.75556 0.75807 0.75239 - 14.52663 12.84174 12.07246 11.38275 10.75683 10.18346 - 9.65975 9.18140 8.74513 8.34711 7.98281 7.64598 - 7.32725 7.01732 6.70851 6.38639 6.02045 5.54077 - 4.82163 4.29763 3.57434 2.76828 1.60027 1.21043 - 0.83578 0.78128 0.74399 0.74208 0.74164 0.74187 - 14.51859 12.84111 12.10141 11.43800 10.83733 10.28969 - 9.79219 9.34085 8.93249 8.56330 8.22859 7.92160 - 7.63192 7.34959 7.06762 6.77293 6.43731 5.99466 - 5.31771 4.80912 4.07931 3.21282 1.82820 1.33789 - 0.85579 0.78704 0.74360 0.74155 0.73713 0.73629 - 14.49214 12.83716 12.12488 11.48357 10.90184 10.37096 - 9.88836 9.45040 9.05418 8.69715 8.37638 8.08780 - 7.82473 7.57865 7.33780 7.07812 6.76462 6.34334 - 5.69737 5.20386 4.47692 3.57860 2.04650 1.46763 - 0.88262 0.79843 0.74259 0.73839 0.73483 0.73284 - 14.47117 12.83432 12.13946 11.51329 10.94456 10.42513 - 9.95273 9.52485 9.13959 8.79537 8.49052 8.22113 - 7.97898 7.75378 7.53294 7.29646 7.01336 6.62529 - 6.00899 5.52829 4.81019 3.89183 2.24712 1.58928 - 0.91333 0.81480 0.74201 0.73624 0.73056 0.73050 - 14.45917 12.84748 12.16600 11.55091 10.99390 10.48846 - 10.03242 9.62327 9.25885 8.93673 8.65380 8.40536 - 8.18346 7.98050 7.79142 7.60438 7.38923 7.06655 - 6.49296 6.02998 5.33512 4.41465 2.60565 1.82934 - 0.97436 0.84249 0.74337 0.73536 0.72831 0.72753 - 14.43995 12.85353 12.18467 11.58018 11.03285 10.53693 - 10.09055 9.69143 9.33771 9.02728 8.75745 8.52405 - 8.31980 8.13791 7.97437 7.81871 7.64225 7.36614 - 6.84669 6.41324 5.74618 4.83028 2.92111 2.04839 - 1.03504 0.87441 0.74645 0.73488 0.72643 0.72572 - 14.38301 12.86102 12.21948 11.63519 11.10274 10.61880 - 10.18278 9.79379 9.45167 9.15539 8.90337 8.69305 - 8.51939 8.37684 8.25934 8.15068 8.02298 7.82308 - 7.43242 7.07572 6.47037 5.58525 3.58010 2.52670 - 1.18064 0.95459 0.75748 0.73736 0.72456 0.72327 - 14.33566 12.87138 12.23732 11.66003 11.13436 10.65782 - 10.22967 9.84887 9.51522 9.22800 8.98611 8.78753 - 8.62812 8.50336 8.40874 8.33017 8.24324 8.10048 - 7.79363 7.49436 6.95970 6.13365 4.08802 2.91521 - 1.31992 1.03923 0.77255 0.73822 0.72389 0.72205 - 14.19749 12.87830 12.25370 11.68461 11.16651 10.69758 - 10.27717 9.90443 9.57936 9.30156 9.07055 8.88483 - 8.74114 8.63636 8.56800 8.52536 8.48923 8.42107 - 8.22798 8.00757 7.57123 6.84537 4.85744 3.56374 - 1.57215 1.19071 0.80429 0.74961 0.72518 0.72080 - 14.07637 12.87953 12.26047 11.69583 11.18193 10.71706 - 10.30045 9.93163 9.61064 9.33737 9.11178 8.93285 - 8.79814 8.70541 8.65286 8.63047 8.62207 8.59887 - 8.48325 8.31853 7.94999 7.29099 5.40358 4.09581 - 1.80411 1.32560 0.83526 0.76813 0.72493 0.72018 - 13.98755 12.88054 12.26479 11.70178 11.18906 10.72584 - 10.31154 9.94607 9.62959 9.36140 9.14053 8.96555 - 8.83514 8.74824 8.70389 8.69356 8.70409 8.71320 - 8.64612 8.51417 8.20512 7.63807 5.85732 4.49079 - 2.00665 1.46239 0.87042 0.77923 0.73103 0.71980 - 13.92441 12.88143 12.26871 11.70686 11.19479 10.73270 - 10.32011 9.95660 9.64210 9.37617 9.15833 8.98738 - 8.86138 8.77901 8.74009 8.73761 8.76019 8.78721 - 8.75849 8.66482 8.40627 7.87887 6.16688 4.86122 - 2.21495 1.58392 0.90243 0.79818 0.72870 0.71955 - 13.84741 12.88246 12.27269 11.71269 11.20233 10.74221 - 10.33197 9.97109 9.65946 9.39669 9.18223 9.01516 - 8.89386 8.81752 8.78660 8.79521 8.83422 8.88745 - 8.90660 8.85606 8.67045 8.23839 6.68023 5.41632 - 2.58744 1.81514 0.96716 0.83101 0.73330 0.71923 - 13.80029 12.88302 12.27475 11.71624 11.20746 10.74880 - 10.33997 9.98048 9.67030 9.40917 9.19668 9.03217 - 8.91396 8.84143 8.81543 8.83086 8.88005 8.94973 - 8.99926 8.97695 8.84279 8.48325 7.05659 5.84412 - 2.91358 2.02541 1.02984 0.86419 0.73856 0.71904 - 13.72938 12.88379 12.27716 11.72105 11.21472 10.75839 - 10.35139 9.99359 9.68510 9.42595 9.21611 9.05517 - 8.94140 8.87416 8.85488 8.87959 8.94272 9.03551 - 9.12802 9.14624 9.09080 8.85289 7.68350 6.59692 - 3.58495 2.49307 1.17831 0.94658 0.75335 0.71878 - 13.68892 12.88395 12.27816 11.72305 11.21797 10.76266 - 10.35674 10.00019 9.69324 9.43561 9.22666 9.06611 - 8.95387 8.89036 8.87639 8.90592 8.97296 9.07593 - 9.20145 9.24869 9.21998 9.01967 8.09227 7.18243 - 4.07541 2.86281 1.31938 1.03782 0.77067 0.71865 - 13.64424 12.88428 12.27966 11.72546 11.22112 10.76664 - 10.36162 10.00612 9.70037 9.44408 9.23664 9.07784 - 8.96774 8.90694 8.89664 8.93137 9.00612 9.12140 - 9.27096 9.34232 9.36009 9.23794 8.55516 7.84044 - 4.85818 3.50499 1.57301 1.19502 0.80139 0.71853 - 13.62031 12.88459 12.28091 11.72692 11.22265 10.76843 - 10.36372 10.00852 9.70301 9.44720 9.24110 9.08443 - 8.97598 8.91563 8.90555 8.94289 9.02459 9.14918 - 9.30255 9.37703 9.43018 9.39424 8.83557 8.13088 - 5.45682 4.07076 1.80020 1.32225 0.83553 0.71847 - 13.60617 12.88506 12.28144 11.72742 11.22310 10.76911 - 10.36475 10.01005 9.70505 9.44976 9.24416 9.08799 - 8.98012 8.92059 8.91170 8.95072 9.03490 9.16322 - 9.32450 9.40702 9.47345 9.46398 9.01712 8.40242 - 5.88749 4.48831 2.03076 1.45686 0.86858 0.71843 - 13.59625 12.88538 12.28176 11.72768 11.22349 10.76963 - 10.36559 10.01117 9.70646 9.45150 9.24621 9.09040 - 8.98296 8.92397 8.91584 8.95601 9.04184 9.17265 - 9.33925 9.42734 9.50294 9.51141 9.14505 8.60078 - 6.23062 4.83922 2.25014 1.58414 0.90135 0.71841 - 13.58271 12.88516 12.28198 11.72846 11.22471 10.77119 - 10.36736 10.01305 9.70847 9.45366 9.24868 9.09338 - 8.98658 8.92834 8.92115 8.96260 9.05039 9.18438 - 9.35776 9.45267 9.54060 9.57349 9.31556 8.87208 - 6.74879 5.40145 2.63607 1.85685 0.96605 0.71838 - 13.57376 12.88240 12.28029 11.72921 11.22788 10.77538 - 10.37148 10.01635 9.71058 9.45464 9.24891 9.09357 - 8.98739 8.93035 8.92487 8.96822 9.05735 9.19052 - 9.36597 9.46821 9.56579 9.61501 9.43014 9.04459 - 7.11670 5.84602 2.97229 2.08882 1.03015 0.71836 - 2.25712 2.31584 2.37123 2.42366 2.47293 2.51894 - 2.56190 2.60241 2.64142 2.67924 2.71611 2.75262 - 2.79015 2.82985 2.87158 2.91456 2.95742 2.99781 - 3.03274 3.04854 3.06674 3.08465 3.10592 3.11174 - 3.11651 3.11710 3.11760 3.11765 3.11771 3.11772 - 2.83388 2.88682 2.93736 2.98626 3.03321 3.07791 - 3.12002 3.15927 3.19546 3.22860 3.25909 3.28773 - 3.31651 3.34731 3.38058 3.41674 3.45628 3.49962 - 3.54595 3.56826 3.58612 3.59596 3.60943 3.61440 - 3.61651 3.61655 3.61688 3.61691 3.61711 3.61700 - 3.29445 3.35447 3.40807 3.45635 3.49913 3.53647 - 3.56880 3.59713 3.62289 3.64656 3.66871 3.69009 - 3.71241 3.73734 3.76534 3.79671 3.83156 3.86917 - 3.90790 3.92672 3.94365 3.95459 3.96352 3.96557 - 3.96718 3.96736 3.96750 3.96753 3.96754 3.96754 - 4.01027 4.08311 4.14261 4.19033 4.22629 4.25106 - 4.26612 4.27431 4.27938 4.28255 4.28470 4.28712 - 4.29207 4.30152 4.31538 4.33228 4.35110 4.37331 - 4.40008 4.41404 4.42511 4.43040 4.43496 4.43592 - 4.43644 4.43649 4.43655 4.43655 4.43659 4.43657 - 4.55167 4.64706 4.71227 4.75264 4.77357 4.78158 - 4.77956 4.77092 4.75998 4.74788 4.73510 4.72239 - 4.71116 4.70296 4.69836 4.69784 4.70199 4.71160 - 4.72471 4.73026 4.73451 4.73656 4.73767 4.73774 - 4.73775 4.73775 4.73775 4.73774 4.73774 4.73775 - 4.97900 5.10348 5.17433 5.20306 5.20442 5.19471 - 5.17800 5.15677 5.13386 5.10919 5.08159 5.05171 - 5.02361 5.00096 4.98371 4.97004 4.95890 4.95322 - 4.95291 4.95199 4.95029 4.94841 4.94667 4.94609 - 4.94561 4.94555 4.94550 4.94548 4.94549 4.94549 - 5.35733 5.45646 5.52317 5.56100 5.57084 5.55553 - 5.52040 5.47412 5.42732 5.38276 5.34096 5.30253 - 5.26741 5.23579 5.20733 5.18060 5.15489 5.13320 - 5.11926 5.11472 5.10828 5.10128 5.09701 5.09604 - 5.09495 5.09481 5.09473 5.09470 5.09474 5.09473 - 5.93574 6.03628 6.09644 6.12119 6.11210 6.07310 - 6.01124 5.93758 5.86529 5.79769 5.73499 5.67725 - 5.62325 5.57211 5.52318 5.47465 5.42579 5.38070 - 5.34475 5.33023 5.31476 5.30153 5.29128 5.28891 - 5.28677 5.28652 5.28632 5.28627 5.28630 5.28629 - 6.38270 6.47614 6.52392 6.53254 6.50416 6.44357 - 6.35891 6.26275 6.16982 6.08354 6.00405 5.93090 - 5.86205 5.79576 5.73102 5.66550 5.59821 5.53427 - 5.48057 5.45792 5.43497 5.41632 5.40026 5.39648 - 5.39328 5.39289 5.39258 5.39254 5.39253 5.39252 - 7.15402 7.27392 7.28683 7.22178 7.11085 6.98743 - 6.86038 6.73503 6.61712 6.50543 6.39681 6.28910 - 6.18488 6.08580 5.99095 5.89736 5.80299 5.71087 - 5.62498 5.58497 5.54687 5.51837 5.49008 5.48326 - 5.47788 5.47717 5.47666 5.47658 5.47653 5.47653 - 7.71283 7.77787 7.74056 7.63148 7.47938 7.31406 - 7.14495 6.97911 6.82420 6.68061 6.54686 6.42028 - 6.30004 6.18418 6.07196 5.96125 5.85048 5.74123 - 5.63558 5.58450 5.53482 5.49716 5.46101 5.45214 - 5.44508 5.44418 5.44351 5.44340 5.44334 5.44332 - 8.48552 8.40673 8.27020 8.09603 7.88981 7.65963 - 7.41680 7.17660 6.95462 6.75508 6.57753 6.41917 - 6.27716 6.14638 6.02293 5.89815 5.76573 5.63221 - 5.50562 5.44427 5.37970 5.32684 5.28234 5.27145 - 5.26210 5.26100 5.26015 5.25998 5.25994 5.25989 - 8.99398 8.82819 8.60717 8.35575 8.08010 7.78854 - 7.49226 7.20589 6.94389 6.70997 6.50339 6.32023 - 6.15692 6.00822 5.86969 5.73248 5.58969 5.44606 - 5.30741 5.23914 5.16733 5.10876 5.05924 5.04710 - 5.03670 5.03548 5.03452 5.03434 5.03431 5.03424 - 9.37271 9.12778 8.83224 8.51457 8.18087 7.83943 - 7.50079 7.17835 6.88576 6.62565 6.39674 6.19388 - 6.01217 5.84642 5.69226 5.54228 5.39050 5.23960 - 5.09337 5.02166 4.94773 4.88825 4.83552 4.82256 - 4.81174 4.81045 4.80942 4.80926 4.80919 4.80915 - 9.67111 9.35431 8.99276 8.61774 8.23484 7.85206 - 7.47908 7.12775 6.81086 6.53028 6.28349 6.06428 - 5.86617 5.68412 5.51414 5.35116 5.19087 5.03391 - 4.88237 4.80908 4.73570 4.67784 4.62290 4.60938 - 4.59848 4.59718 4.59608 4.59593 4.59583 4.59582 - 10.05264 9.73217 9.27235 8.75430 8.23668 7.76911 - 7.35419 6.98510 6.65605 6.36081 6.08776 5.82960 - 5.59017 5.37372 5.17705 4.99527 4.82321 4.65528 - 4.49248 4.41784 4.34670 4.29202 4.23425 4.22050 - 4.20966 4.20819 4.20713 4.20700 4.20690 4.20689 - 10.52669 9.89717 9.28732 8.72574 8.20770 7.73005 - 7.29023 6.88578 6.51516 6.17882 5.87308 5.59349 - 5.33620 5.10031 4.88497 4.68904 4.50984 4.33598 - 4.15904 4.07404 3.99992 3.95089 3.89451 3.87804 - 3.86774 3.86689 3.86558 3.86533 3.86531 3.86530 - 10.85537 10.24837 9.52520 8.78346 8.09025 7.49417 - 6.98496 6.54424 6.15425 5.80087 5.46793 5.14754 - 4.84749 4.57440 4.32722 4.09830 3.88313 3.68157 - 3.49478 3.40795 3.32637 3.26650 3.20883 3.19531 - 3.18474 3.18335 3.18233 3.18221 3.18211 3.18208 - 11.26106 10.31499 9.44722 8.67386 7.98194 7.36241 - 6.80733 6.31095 5.86987 5.47666 5.12271 4.79880 - 4.49422 4.20324 3.92955 3.67622 3.44412 3.22848 - 3.02655 2.93164 2.83999 2.77215 2.71606 2.70301 - 2.69233 2.69110 2.69010 2.68993 2.68986 2.68980 - 11.65830 10.46994 9.43904 8.55032 7.77627 7.09981 - 6.50771 5.98385 5.51572 5.09491 4.71303 4.36198 - 4.03281 3.72032 3.42618 3.15347 2.90034 2.66227 - 2.43800 2.33274 2.23365 2.16254 2.10347 2.08996 - 2.07912 2.07788 2.07687 2.07671 2.07661 2.07656 - 11.93406 10.58540 9.45560 8.49600 7.67251 6.96089 - 6.34505 5.80390 5.31875 4.88023 4.48095 4.11355 - 3.77012 3.44573 3.14067 2.85642 2.59218 2.34151 - 2.10337 1.99159 1.88860 1.81588 1.75203 1.73749 - 1.72623 1.72492 1.72380 1.72367 1.72353 1.72353 - 12.15642 10.69464 9.50024 8.49192 7.63449 6.89867 - 6.26493 5.70962 5.21104 4.75894 4.34651 3.96703 - 3.61322 3.28032 2.96786 2.67621 2.40503 2.14722 - 1.89991 1.78271 1.67418 1.59687 1.52869 1.51321 - 1.50124 1.49984 1.49863 1.49849 1.49836 1.49838 - 12.34799 10.80168 9.56237 8.51840 7.63564 6.88239 - 6.23484 5.66767 5.15793 4.69502 4.27232 3.88344 - 3.52144 3.18163 2.86316 2.56575 2.28875 2.02568 - 1.77100 1.64896 1.53462 1.45194 1.37948 1.36300 - 1.35014 1.34863 1.34733 1.34717 1.34706 1.34707 - 12.67235 11.00869 9.71245 8.62156 7.70411 6.92731 - 6.26031 5.67545 5.14916 4.67084 4.23381 3.83159 - 3.45719 3.10581 2.77638 2.46830 2.17989 1.90540 - 1.63676 1.50583 1.38083 1.28814 1.20624 1.18725 - 1.17224 1.17047 1.16897 1.16877 1.16865 1.16859 - 12.94251 11.20215 9.87273 8.75434 7.81666 7.02475 - 6.34487 5.74803 5.21072 4.72239 4.27609 3.86482 - 3.48098 3.11952 2.77947 2.46047 2.16026 1.87207 - 1.58878 1.44902 1.31387 1.21163 1.11898 1.09698 - 1.07951 1.07745 1.07571 1.07549 1.07532 1.07518 - 13.44846 11.59659 10.22859 9.08131 8.12810 7.31920 - 6.62302 6.01025 5.45784 4.95498 4.49416 4.06747 - 3.66610 3.28432 2.92167 2.57830 2.25106 1.92938 - 1.60658 1.44368 1.28067 1.15175 1.02971 0.99975 - 0.97569 0.97283 0.97047 0.97017 0.96987 0.96985 - 13.79209 11.88074 10.50467 9.35658 8.40790 7.59865 - 6.89967 6.28227 5.72366 5.21306 4.74302 4.30560 - 3.89174 3.49552 3.11642 2.75455 2.40561 2.05558 - 1.69335 1.50654 1.31265 1.15357 1.00077 0.96304 - 0.93279 0.92913 0.92598 0.92556 0.92537 0.92553 - 14.23057 12.21161 10.85229 9.75790 8.85718 8.07688 - 7.38891 6.76752 6.19269 5.66118 5.17516 4.72954 - 4.30859 3.90089 3.50345 3.11295 2.72664 2.34226 - 1.92230 1.67791 1.41879 1.20132 0.98554 0.93350 - 0.89368 0.88823 0.88302 0.88226 0.88347 0.88284 - 14.22107 12.42152 11.20138 10.16259 9.25753 8.45214 - 7.73405 7.09109 6.51357 5.99191 5.51642 5.07614 - 4.65775 4.25097 3.85129 3.45256 3.04415 2.60597 - 2.11462 1.84151 1.54446 1.28244 0.99165 0.91507 - 0.87166 0.86757 0.85934 0.85796 0.86150 0.85885 - 14.32815 12.53831 11.36958 10.37362 9.49751 8.71290 - 8.00926 7.37571 6.80363 6.28446 5.80930 5.36798 - 4.94789 4.53885 4.13555 3.73034 3.30968 2.84740 - 2.31138 2.00411 1.66084 1.35438 1.00478 0.90994 - 0.85727 0.85255 0.84283 0.84125 0.84616 0.84196 - 14.39088 12.61156 11.49088 10.53094 9.68120 8.91633 - 8.22734 7.60427 7.03944 6.52496 6.05265 5.61297 - 5.19386 4.78523 4.38120 3.97288 3.54432 3.06421 - 2.49239 2.15653 1.77348 1.42592 1.02219 0.91011 - 0.84684 0.84119 0.83042 0.82876 0.83455 0.82910 - 14.45093 12.69215 11.65289 10.75000 9.94507 9.21522 - 8.55358 7.95164 7.40297 6.90078 6.43784 6.00552 - 5.59261 5.18922 4.78857 4.38001 3.94385 3.44051 - 2.81580 2.43481 1.98588 1.56522 1.06405 0.92014 - 0.83329 0.82511 0.81285 0.81120 0.81778 0.81069 - 14.45355 12.72288 11.75143 10.89634 10.12962 9.42999 - 8.79221 8.20899 7.67495 7.18434 6.73095 6.30723 - 5.90324 5.50959 5.11860 4.71765 4.28269 3.76412 - 3.09362 2.67267 2.16769 1.68867 1.12197 0.95131 - 0.81893 0.80746 0.80517 0.80455 0.79875 0.79814 - 14.51712 12.79976 11.90197 11.10536 10.38904 9.73533 - 9.13971 8.59576 8.09861 7.64274 7.22199 6.82845 - 6.45111 6.07979 5.70731 5.32163 4.89937 4.39050 - 3.70294 3.23437 2.61830 1.99213 1.23027 1.00260 - 0.82160 0.80002 0.78341 0.78143 0.78615 0.77949 - 14.48813 12.80130 11.96187 11.21364 10.53796 9.92028 - 9.35674 8.84188 8.37146 7.94068 7.54396 7.17390 - 6.81998 6.47214 6.12291 5.75926 5.35509 4.85306 - 4.14779 3.65351 2.98891 2.28464 1.35923 1.06986 - 0.82432 0.79385 0.77401 0.77213 0.77498 0.76926 - 14.41087 12.76745 12.00509 11.32101 10.69993 10.13108 - 9.61145 9.13688 8.70409 8.30931 7.94803 7.61403 - 7.29802 6.99074 6.68449 6.36497 6.00176 5.52509 - 4.80977 4.28843 3.56889 2.76745 1.60706 1.21982 - 0.84967 0.79641 0.76063 0.75879 0.75776 0.75829 - 14.40522 12.76859 12.03458 11.37584 10.77921 10.23541 - 9.74148 9.29350 8.88832 8.52214 8.19030 7.88605 - 7.59900 7.31919 7.03971 6.74757 6.41469 5.97537 - 5.30294 4.79746 4.07183 3.20999 1.83267 1.34538 - 0.86906 0.80168 0.75980 0.75792 0.75341 0.75246 - 14.37908 12.76516 12.05816 11.42140 10.84346 10.31612 - 9.83673 9.40171 9.00820 8.65368 8.33536 8.04921 - 7.78876 7.54554 7.30768 7.05079 6.73974 6.32121 - 5.67952 5.18948 4.46778 3.57489 2.04940 1.47385 - 0.89508 0.81259 0.75870 0.75452 0.75100 0.74886 - 14.35898 12.76281 12.07289 11.45078 10.88569 10.36958 - 9.90020 9.47512 9.09245 8.75065 8.44808 8.18090 - 7.94102 7.71831 7.50020 7.26669 6.98659 6.60152 - 5.98952 5.51259 4.79950 3.88584 2.24873 1.59505 - 0.92513 0.82827 0.75793 0.75250 0.74651 0.74642 - 14.34814 12.77620 12.09928 11.48811 10.93449 10.43216 - 9.97892 9.57232 9.21023 8.89024 8.60934 8.36285 - 8.14293 7.94208 7.75531 7.57091 7.35885 7.03991 - 6.47122 6.01161 5.32137 4.40610 2.60549 1.83349 - 0.98502 0.85511 0.75905 0.75143 0.74419 0.74333 - 14.32973 12.78242 12.11791 11.51706 10.97311 10.48012 - 10.03638 9.63966 9.28809 8.97962 8.71161 8.47995 - 8.27744 8.09744 7.93599 7.78276 7.60925 7.33689 - 6.82252 6.39252 5.73009 4.81944 2.91935 2.05134 - 1.04480 0.88629 0.76187 0.75086 0.74221 0.74143 - 14.27484 12.79004 12.15237 11.57146 11.04202 10.56085 - 10.12743 9.74077 9.40076 9.10633 8.85596 8.64710 - 8.47472 8.33336 8.21717 8.11032 7.98533 7.78907 - 7.40330 7.04992 6.44910 5.56978 3.57571 2.52703 - 1.18865 0.96513 0.77234 0.75305 0.74021 0.73888 - 14.22952 12.80028 12.16988 11.59584 11.07324 10.59944 - 10.17381 9.79526 9.46360 9.17810 8.93767 8.74038 - 8.58209 8.45841 8.36487 8.28765 8.20257 8.06255 - 7.76024 7.46453 6.93508 6.11541 4.08086 2.91316 - 1.32689 1.04896 0.78687 0.75354 0.73940 0.73761 - 14.09688 12.80719 12.18614 11.62015 11.10499 10.63878 - 10.22073 9.85018 9.52700 9.25084 9.02120 8.83662 - 8.69388 8.58988 8.52221 8.48028 8.44518 8.37880 - 8.18933 7.97220 7.54120 6.82236 4.84659 3.55820 - 1.57734 1.19913 0.81771 0.76422 0.74074 0.73631 - 13.98062 12.80837 12.19269 11.63122 11.12025 10.65799 - 10.24377 9.87707 9.55795 9.28624 9.06194 8.88407 - 8.75023 8.65820 8.60618 8.58419 8.57620 8.55409 - 8.44150 8.27977 7.91617 7.26372 5.38964 4.08867 - 1.80793 1.33263 0.84784 0.78241 0.74050 0.73566 - 13.89535 12.80950 12.19711 11.63714 11.12725 10.66664 - 10.25471 9.89134 9.57670 9.31004 9.09041 8.91646 - 8.78683 8.70051 8.65658 8.64657 8.65739 8.66708 - 8.60199 8.47262 8.16846 7.60873 5.84136 4.47967 - 2.00961 1.46927 0.88241 0.79255 0.74673 0.73527 - 13.83469 12.81042 12.20103 11.64220 11.13295 10.67347 - 10.26322 9.90177 9.58906 9.32463 9.10802 8.93806 - 8.81281 8.73095 8.69237 8.69012 8.71293 8.74009 - 8.71282 8.62176 8.36764 7.84631 6.14822 4.85008 - 2.21673 1.58953 0.91386 0.81137 0.74419 0.73501 - 13.76072 12.81138 12.20490 11.64802 11.14046 10.68294 - 10.27501 9.91614 9.60623 9.34492 9.13166 8.96554 - 8.84493 8.76904 8.73837 8.74709 8.78610 8.83931 - 8.85935 8.81052 8.62849 8.20216 6.65797 5.40207 - 2.58716 1.81959 0.97760 0.84333 0.74865 0.73467 - 13.71552 12.81206 12.20696 11.65156 11.14557 10.68950 - 10.28295 9.92543 9.61696 9.35729 9.14597 8.98237 - 8.86483 8.79270 8.76690 8.78234 8.83140 8.90109 - 8.95120 8.92983 8.79848 8.44428 7.03154 5.82731 - 2.91180 2.02897 1.03946 0.87579 0.75374 0.73447 - 13.64764 12.81275 12.20936 11.65635 11.15301 10.69917 - 10.29432 9.93841 9.63157 9.37386 9.16517 9.00513 - 8.89197 8.82509 8.80596 8.83054 8.89337 8.98617 - 9.07879 9.09699 9.04310 8.80947 7.65319 6.57532 - 3.58017 2.49435 1.18635 0.95681 0.76805 0.73421 - 13.60874 12.81293 12.21026 11.65834 11.15614 10.70342 - 10.29965 9.94498 9.63967 9.38341 9.17561 9.01594 - 8.90430 8.84112 8.82720 8.85660 8.92338 9.02604 - 9.15123 9.19849 9.17068 8.97336 8.05856 7.15798 - 4.06793 2.86143 1.32633 1.04719 0.78500 0.73408 - 13.56583 12.81308 12.21176 11.66064 11.15918 10.70728 - 10.30445 9.95085 9.64672 9.39180 9.18549 9.02755 - 8.91802 8.85755 8.84729 8.88182 8.95612 9.07083 - 9.21985 9.29111 9.30911 9.18845 8.51628 7.81186 - 4.84717 3.49958 1.57828 1.20319 0.81473 0.73394 - 13.54282 12.81349 12.21291 11.66210 11.16071 10.70896 - 10.30647 9.95317 9.64930 9.39490 9.18992 9.03410 - 8.92623 8.86617 8.85609 8.89320 8.97446 9.09832 - 9.25084 9.32519 9.37852 9.34358 8.79269 8.09729 - 5.44359 4.06323 1.80416 1.32905 0.84809 0.73388 - 13.52917 12.81387 12.21344 11.66249 11.16104 10.70953 - 10.30749 9.95468 9.65134 9.39745 9.19295 9.03763 - 8.93035 8.87108 8.86217 8.90095 8.98466 9.11226 - 9.27263 9.35485 9.42123 9.41233 8.97170 8.36554 - 5.87161 4.47838 2.03354 1.46284 0.88048 0.73384 - 13.51967 12.81419 12.21375 11.66285 11.16144 10.71016 - 10.30831 9.95582 9.65277 9.39916 9.19499 9.04001 - 8.93312 8.87441 8.86627 8.90616 8.99153 9.12163 - 9.28733 9.37499 9.45029 9.45907 9.09792 8.56147 - 6.21236 4.82717 2.25109 1.58945 0.91264 0.73382 - 13.50676 12.81408 12.21408 11.66363 11.16276 10.71171 - 10.31007 9.95771 9.65475 9.40131 9.19742 9.04294 - 8.93671 8.87875 8.87154 8.91272 8.99997 9.13327 - 9.30573 9.40005 9.48753 9.52056 9.26608 8.82907 - 6.72676 5.38599 2.63417 1.86035 0.97631 0.73379 - 13.49804 12.81162 12.21269 11.66458 11.16582 10.71590 - 10.31419 9.96100 9.65691 9.40232 9.19767 9.04311 - 8.93746 8.88071 8.87522 8.91831 9.00692 9.13930 - 9.31378 9.41548 9.51268 9.56190 9.37960 8.99962 - 7.09167 5.82823 2.96859 2.09052 1.03948 0.73377 - 2.18202 2.24033 2.29570 2.34845 2.39833 2.44523 - 2.48924 2.53082 2.57070 2.60917 2.64641 2.68306 - 2.72052 2.76006 2.80163 2.84469 2.88802 2.92893 - 2.96396 2.97977 2.99830 3.01695 3.03948 3.04568 - 3.05078 3.05141 3.05195 3.05201 3.05207 3.05208 - 2.76089 2.81201 2.86100 2.90864 2.95467 2.99880 - 3.04074 3.08023 3.11710 3.15135 3.18331 3.21366 - 3.24417 3.27645 3.31091 3.34792 3.38800 3.43181 - 3.47893 3.50178 3.52025 3.53068 3.54529 3.55076 - 3.55318 3.55325 3.55363 3.55367 3.55385 3.55375 - 3.22177 3.27313 3.32117 3.36691 3.41006 3.45026 - 3.48718 3.52056 3.55022 3.57623 3.59916 3.62002 - 3.64117 3.66481 3.69164 3.72240 3.75798 3.79924 - 3.84569 3.86831 3.88475 3.89148 3.90182 3.90634 - 3.90762 3.90751 3.90779 3.90781 3.90800 3.90788 - 3.92104 3.99294 4.05213 4.10015 4.13698 4.16319 - 4.18017 4.19068 4.19827 4.20412 4.20905 4.21422 - 4.22170 4.23332 4.24911 4.26801 4.28922 4.31399 - 4.34325 4.35834 4.37037 4.37638 4.38209 4.38338 - 4.38414 4.38421 4.38430 4.38431 4.38434 4.38433 - 4.45187 4.54751 4.61448 4.65770 4.68198 4.69326 - 4.69439 4.68880 4.68091 4.67186 4.66209 4.65236 - 4.64404 4.63860 4.63668 4.63880 4.64563 4.65798 - 4.67385 4.68077 4.68639 4.68947 4.69157 4.69189 - 4.69209 4.69212 4.69214 4.69213 4.69214 4.69215 - 4.87479 4.99502 5.06865 5.10473 5.11427 5.10997 - 5.09616 5.07686 5.05677 5.03583 5.01210 4.98564 - 4.96066 4.94102 4.92669 4.91596 4.90782 4.90495 - 4.90736 4.90807 4.90801 4.90730 4.90645 4.90609 - 4.90577 4.90573 4.90570 4.90569 4.90569 4.90569 - 5.22814 5.36656 5.44349 5.47154 5.46695 5.44801 - 5.42032 5.38831 5.35691 5.32514 5.28917 5.24857 - 5.20947 5.17732 5.15159 5.12903 5.10739 5.09063 - 5.08032 5.07527 5.07003 5.06587 5.06207 5.06103 - 5.06020 5.06011 5.06002 5.06000 5.06000 5.06001 - 5.79706 5.95324 6.02749 6.03785 6.00774 5.96282 - 5.91042 5.85550 5.80341 5.75217 5.69611 5.63394 - 5.57329 5.52058 5.47482 5.43144 5.38719 5.34697 - 5.31433 5.29937 5.28517 5.27476 5.26488 5.26246 - 5.26055 5.26032 5.26013 5.26010 5.26009 5.26010 - 6.24461 6.40127 6.46442 6.45593 6.40312 6.33556 - 6.26142 6.18609 6.11521 6.04661 5.97440 5.89680 - 5.82079 5.75213 5.68970 5.62907 5.56710 5.50843 - 5.45744 5.43429 5.41255 5.39658 5.38083 5.37704 - 5.37406 5.37367 5.37339 5.37335 5.37332 5.37332 - 7.05898 7.18457 7.20462 7.14728 7.04382 6.92717 - 6.80621 6.68657 6.57426 6.46794 6.36397 6.26003 - 6.15906 6.06304 5.97108 5.88026 5.78853 5.69891 - 5.61539 5.57658 5.53961 5.51192 5.48437 5.47769 - 5.47243 5.47174 5.47123 5.47115 5.47110 5.47110 - 7.62707 7.70655 7.67703 7.57116 7.42163 7.26175 - 7.10038 6.94281 6.79475 6.65645 6.52697 6.40415 - 6.28726 6.17451 6.06511 5.95690 5.84834 5.74129 - 5.63783 5.58761 5.53866 5.50154 5.46605 5.45732 - 5.45037 5.44948 5.44882 5.44872 5.44867 5.44865 - 8.59887 8.39332 8.17675 7.96505 7.75808 7.55576 - 7.35826 7.16590 6.97826 6.79667 6.62221 6.45461 - 6.29558 6.14494 6.00364 5.87267 5.75202 5.63735 - 5.52576 5.47303 5.42353 5.38129 5.30244 5.27390 - 5.28085 5.28518 5.28200 5.28036 5.28271 5.28130 - 9.09683 8.81697 8.52732 8.24738 7.97680 7.71536 - 7.46315 7.22057 6.98723 6.76466 6.55431 6.35563 - 6.17057 5.99972 5.84390 5.70428 5.58027 5.46415 - 5.34876 5.29224 5.23618 5.18445 5.08658 5.05241 - 5.06639 5.07257 5.06794 5.06566 5.06858 5.06695 - 9.31772 9.08203 8.79568 8.48654 8.16071 7.82650 - 7.49451 7.17822 6.89144 6.63683 6.41305 6.21497 - 6.03760 5.87560 5.72466 5.57741 5.42788 5.27875 - 5.13377 5.06241 4.98860 4.92908 4.87643 4.86350 - 4.85267 4.85139 4.85036 4.85019 4.85014 4.85009 - 9.61394 9.30899 8.95875 8.59378 8.21984 7.84493 - 7.47894 7.13381 6.82259 6.54721 6.30519 6.09046 - 5.89657 5.71842 5.55203 5.39218 5.23441 5.07937 - 4.92907 4.85612 4.78289 4.72502 4.66999 4.65645 - 4.64553 4.64421 4.64310 4.64297 4.64288 4.64286 - 9.99385 9.68172 9.23622 8.73423 8.23065 7.77249 - 7.36348 6.99886 6.67469 6.38458 6.11622 5.86206 - 5.62638 5.41382 5.22109 5.04302 4.87406 4.70830 - 4.54678 4.47271 4.40192 4.34725 4.28919 4.27535 - 4.26443 4.26294 4.26187 4.26175 4.26164 4.26162 - 10.45938 9.84899 9.25605 8.70873 8.20268 7.73507 - 7.30356 6.90594 6.54084 6.20887 5.90663 5.63001 - 5.37560 5.14272 4.93063 4.73822 4.56272 4.39219 - 4.21751 4.13308 4.05914 4.00992 3.95327 3.93673 - 3.92627 3.92540 3.92407 3.92382 3.92382 3.92378 - 10.80747 10.19497 9.48805 8.77166 8.10051 7.51498 - 7.00828 6.56759 6.18003 5.83113 5.50255 5.18534 - 4.88810 4.61804 4.37411 4.14858 3.93673 3.73789 - 3.55321 3.46750 3.38669 3.32695 3.26876 3.25504 - 3.24428 3.24286 3.24183 3.24170 3.24160 3.24157 - 11.21181 10.28546 9.43341 8.67235 7.99005 7.37802 - 6.82877 6.33692 5.89929 5.50876 5.15706 4.83526 - 4.53297 4.24461 3.97372 3.72311 3.49365 3.28066 - 3.08141 2.98774 2.89690 2.82921 2.77265 2.75938 - 2.74850 2.74725 2.74623 2.74606 2.74599 2.74593 - 11.63654 10.46055 9.43865 8.55699 7.78872 7.11706 - 6.52888 6.00828 5.54282 5.12424 4.74431 4.39505 - 4.06759 3.75674 3.46419 3.19306 2.94169 2.70578 - 2.48418 2.38030 2.28220 2.21141 2.15223 2.13861 - 2.12766 2.12641 2.12538 2.12522 2.12512 2.12508 - 11.92741 10.58660 9.46162 8.50594 7.68594 6.97756 - 6.36455 5.82590 5.34296 4.90641 4.50891 4.14310 - 3.80105 3.47779 3.17371 2.89047 2.62748 2.37854 - 2.14269 2.03219 1.93023 1.85806 1.79454 1.78004 - 1.76880 1.76749 1.76638 1.76625 1.76611 1.76610 - 12.15469 10.69942 9.50794 8.50228 7.64733 6.91399 - 6.28252 5.72930 5.23263 4.78229 4.37148 3.99344 - 3.64078 3.30873 2.99697 2.70612 2.43599 2.17964 - 1.93422 1.81809 1.71053 1.63393 1.56650 1.55122 - 1.53940 1.53802 1.53683 1.53669 1.53656 1.53656 - 12.34393 10.80525 9.56899 8.52766 7.64723 6.89620 - 6.25064 5.68531 5.17728 4.71597 4.29474 3.90716 - 3.54617 3.20708 2.88918 2.59250 2.31651 2.05472 - 1.80162 1.68049 1.56706 1.48520 1.41384 1.39767 - 1.38506 1.38358 1.38231 1.38216 1.38204 1.38204 - 12.65103 11.00228 9.71276 8.62680 7.71284 6.93851 - 6.27336 5.69000 5.16508 4.68806 4.25224 3.85111 - 3.47757 3.12686 2.79800 2.49065 2.20321 1.92982 - 1.66251 1.53239 1.40834 1.31666 1.23624 1.21769 - 1.20303 1.20130 1.19984 1.19965 1.19952 1.19947 - 12.89670 11.18148 9.86461 8.75486 7.82260 7.03394 - 6.35598 5.76041 5.22419 4.73689 4.29158 3.88124 - 3.49823 3.13749 2.79814 2.47990 2.18061 1.89348 - 1.61152 1.47264 1.33857 1.23751 1.14653 1.12502 - 1.10793 1.10592 1.10423 1.10400 1.10384 1.10373 - 13.35387 11.54732 10.20369 9.07227 8.12823 7.32427 - 6.63033 6.01851 5.46681 4.96468 4.50462 4.07878 - 3.67831 3.29750 2.93584 2.59345 2.26718 1.94663 - 1.62518 1.46315 1.30130 1.17374 1.05388 1.02457 - 1.00102 0.99823 0.99592 0.99562 0.99534 0.99532 - 13.67466 11.81787 10.47116 9.34196 8.40386 7.60018 - 6.90358 6.28707 5.72914 5.21934 4.75021 4.31378 - 3.90097 3.50584 3.12790 2.76724 2.41961 2.07085 - 1.70974 1.52352 1.33056 1.17282 1.02281 0.98599 - 0.95645 0.95287 0.94982 0.94943 0.94921 0.94930 - 14.08536 12.17229 10.84464 9.74843 8.83599 8.05139 - 7.36702 6.75520 6.19331 5.67265 5.18851 4.73589 - 4.30912 3.90296 3.51265 3.13136 2.74943 2.35134 - 1.92020 1.68747 1.43827 1.22302 1.00368 0.95192 - 0.91492 0.91039 0.90501 0.90429 0.90526 0.90439 - 14.31316 12.38398 11.09282 10.03612 9.15015 8.38611 - 7.71683 7.11471 6.55675 6.03512 5.54643 5.08706 - 4.65293 4.23951 3.84119 3.44943 3.05103 2.62267 - 2.13603 1.86054 1.55517 1.28570 1.00506 0.93782 - 0.89256 0.88717 0.87997 0.87907 0.88136 0.87896 - 14.43944 12.51234 11.26464 10.24513 9.38471 8.64014 - 7.98553 7.39388 6.84233 6.32374 5.83547 5.37482 - 4.93869 4.52295 4.12134 3.72399 3.31486 2.86452 - 2.33476 2.02443 1.66978 1.35277 1.01527 0.93234 - 0.87742 0.87111 0.86271 0.86172 0.86496 0.86113 - 14.50944 12.59293 11.39037 10.40364 9.56687 8.84001 - 8.19887 7.61733 7.07319 6.55972 6.07477 5.61612 - 5.18120 4.76608 4.36398 3.96390 3.54760 3.08089 - 2.51698 2.17780 1.78122 1.42084 1.03048 0.93204 - 0.86642 0.85904 0.84978 0.84877 0.85261 0.84762 - 14.37000 12.64574 11.61550 10.71874 9.91847 9.19253 - 8.53418 7.93505 7.38882 6.88877 6.42773 5.99719 - 5.58601 5.18436 4.78552 4.37882 3.94458 3.44310 - 2.82026 2.44035 1.99284 1.57377 1.07585 0.93376 - 0.85061 0.84335 0.83177 0.83003 0.83567 0.82837 - 14.37570 12.67830 11.71321 10.86271 10.09949 9.40302 - 8.76812 8.18756 7.65603 7.16780 6.71668 6.29515 - 5.89326 5.50160 5.11259 4.71360 4.28060 3.76398 - 3.09560 2.67599 2.17285 1.69591 1.13276 0.96396 - 0.83529 0.82493 0.82368 0.82293 0.81620 0.81529 - 14.43631 12.75162 11.85801 11.06430 10.35066 9.69955 - 9.10658 8.56537 8.07099 7.61797 7.20008 6.80935 - 6.43466 6.06581 5.69563 5.31215 4.89207 4.38556 - 3.70083 3.23400 2.62012 1.99638 1.23868 1.01332 - 0.83724 0.81643 0.80093 0.79959 0.80219 0.79590 - 14.39932 12.74625 11.91077 11.16572 10.49293 9.87805 - 9.31744 8.80560 8.33826 7.91060 7.51702 7.15005 - 6.79903 6.45387 6.10709 5.74576 5.34387 4.84437 - 4.14232 3.65018 2.98838 2.28718 1.36636 1.07934 - 0.83917 0.80966 0.79095 0.78954 0.79075 0.78527 - 14.30733 12.70064 11.94318 11.26329 10.64597 10.08069 - 9.56454 9.09338 8.66393 8.27246 7.91443 7.58360 - 7.27065 6.96627 6.66282 6.34602 5.98551 5.51168 - 4.79962 4.28043 3.56400 2.76654 1.61322 1.22857 - 0.86304 0.81112 0.77696 0.77514 0.77327 0.77389 - 14.29411 12.69530 11.96642 11.31220 10.71963 10.17972 - 9.68954 9.24523 8.84358 8.48085 8.15236 7.85137 - 7.56743 7.29059 7.01392 6.72453 6.39447 5.95831 - 5.28987 4.78706 4.06497 3.20725 1.83686 1.35252 - 0.88184 0.81583 0.77553 0.77378 0.76893 0.76786 - 14.26168 12.68728 11.98658 11.35481 10.78116 10.25765 - 9.78181 9.35019 8.96009 8.60903 8.29416 8.01145 - 7.75428 7.51415 7.27918 7.02504 6.71666 6.30110 - 5.66343 5.17640 4.45923 3.57113 2.05213 1.47986 - 0.90719 0.82625 0.77415 0.77002 0.76640 0.76413 - 14.25743 12.69304 12.00216 11.37914 10.81450 10.30096 - 9.83627 9.41743 9.04204 8.70726 8.40956 8.14367 - 7.90097 7.67314 7.45408 7.23085 6.97248 6.60128 - 5.97794 5.49178 4.78155 3.88273 2.24923 1.60366 - 0.93660 0.83885 0.77303 0.76851 0.76309 0.76161 - 14.22569 12.69235 12.02144 11.41543 10.86650 10.36840 - 9.91915 9.51623 9.15756 8.84079 8.56291 8.31933 - 8.10223 7.90421 7.72031 7.53890 7.33003 7.01462 - 6.45026 5.99369 5.30803 4.39803 2.60541 1.83753 - 0.99549 0.86738 0.77394 0.76659 0.75940 0.75841 - 14.20582 12.69680 12.03834 11.44286 10.90355 10.41491 - 9.97514 9.58199 9.23371 8.92828 8.66309 8.43410 - 8.23421 8.05685 7.89814 7.74782 7.57754 7.30887 - 6.79909 6.37228 5.71447 4.80919 2.91777 2.05428 - 1.05441 0.89787 0.77657 0.76599 0.75732 0.75646 - 14.15078 12.70297 12.07121 11.49545 10.97077 10.49384 - 10.06421 9.68096 9.34394 9.05217 8.80415 8.59743 - 8.42716 8.28798 8.17419 8.07013 7.94849 7.75623 - 7.37541 7.02527 6.42884 5.55513 3.57158 2.52748 - 1.19653 0.97541 0.78669 0.76817 0.75519 0.75382 - 14.10701 12.71304 12.08861 11.51967 11.00168 10.53179 - 10.10966 9.73422 9.40528 9.12218 8.88390 8.68856 - 8.53214 8.41041 8.31897 8.24414 8.16199 8.02574 - 7.72860 7.43647 6.91189 6.09807 4.07405 2.91132 - 1.33373 1.05847 0.80083 0.76843 0.75422 0.75251 - 13.98047 12.72059 12.10509 11.54389 11.03289 10.57033 - 10.15547 9.78771 9.46699 9.19300 8.96524 8.78236 - 8.64118 8.53873 8.47265 8.43255 8.39980 8.33672 - 8.15231 7.93892 7.51313 6.80062 4.83619 3.55295 - 1.58247 1.20742 0.83085 0.77846 0.75563 0.75117 - 13.86981 12.72250 12.11189 11.55487 11.04772 10.58897 - 10.17776 9.81374 9.49699 9.22736 9.00484 8.82854 - 8.69608 8.60534 8.55458 8.53394 8.52768 8.50837 - 8.40074 8.24285 7.88440 7.23801 5.37627 4.08182 - 1.81174 1.33957 0.86012 0.79628 0.75539 0.75050 - 13.78853 12.72425 12.11648 11.56064 11.05443 10.59712 - 10.18818 9.82747 9.51516 9.25051 9.03257 8.86011 - 8.73176 8.64654 8.60362 8.59467 8.60692 8.61895 - 8.55814 8.43232 8.13364 7.58111 5.82606 4.46899 - 2.01265 1.47610 0.89408 0.80544 0.76177 0.75009 - 13.73047 12.72548 12.12058 11.56566 11.05978 10.60358 - 10.19628 9.83749 9.52709 9.26465 9.04967 8.88111 - 8.75705 8.67619 8.63847 8.63712 8.66107 8.69003 - 8.66665 8.57927 8.33053 7.81565 6.13039 4.83932 - 2.21855 1.59511 0.92497 0.82410 0.75904 0.74982 - 13.65969 12.72696 12.12473 11.57133 11.06703 10.61267 - 10.20759 9.85139 9.54379 9.28437 9.07267 8.90786 - 8.78832 8.71324 8.68325 8.69259 8.73237 8.78687 - 8.80991 8.76421 8.58733 8.16772 6.63688 5.38840 - 2.58702 1.82405 0.98779 0.85528 0.76340 0.74948 - 13.61606 12.72765 12.12677 11.57485 11.07190 10.61889 - 10.21524 9.86041 9.55419 9.29637 9.08657 8.92420 - 8.80766 8.73627 8.71104 8.72694 8.77651 8.84712 - 8.89954 8.88077 8.75421 8.40682 7.00786 5.81128 - 2.91016 2.03253 1.04890 0.88710 0.76834 0.74927 - 13.55068 12.72837 12.12926 11.57959 11.07909 10.62818 - 10.22629 9.87302 9.56841 9.31246 9.10520 8.94631 - 8.83403 8.76775 8.74901 8.77381 8.83681 8.93003 - 9.02387 9.04368 8.99362 8.76650 7.62466 6.55487 - 3.57558 2.49565 1.19433 0.96690 0.78222 0.74900 - 13.51281 12.72865 12.13056 11.58207 11.08269 10.63270 - 10.23161 9.87919 9.57547 9.32059 9.11471 8.95752 - 8.84740 8.78380 8.76847 8.79795 8.86792 8.97304 - 9.08926 9.12990 9.12122 8.96624 8.01253 7.04859 - 4.09527 2.89860 1.33097 1.04543 0.79721 0.74886 - 13.47243 12.72661 12.12984 11.58385 11.08721 10.63883 - 10.23853 9.88631 9.58276 9.32822 9.12303 8.96718 - 8.85927 8.79901 8.78835 8.82404 8.90168 9.01569 - 9.15392 9.22129 9.25399 9.17721 8.49120 7.66264 - 4.86263 3.55776 1.58424 1.19266 0.82769 0.74873 - 13.44998 12.72903 12.13269 11.58530 11.08692 10.63799 - 10.23819 9.88731 9.58551 9.33282 9.12919 8.97440 - 8.86722 8.80759 8.79768 8.83466 8.91556 9.03896 - 9.19130 9.26602 9.32059 9.28885 8.75106 8.06564 - 5.43090 4.05591 1.80801 1.33570 0.86035 0.74866 - 13.43667 12.72932 12.13311 11.58568 11.08735 10.63865 - 10.23922 9.88879 9.58748 9.33526 9.13212 8.97781 - 8.87121 8.81236 8.80356 8.84218 8.92549 9.05251 - 9.21246 9.29483 9.36207 9.35575 8.92695 8.33080 - 5.85653 4.46879 2.03613 1.46876 0.89214 0.74862 - 13.42735 12.72924 12.13323 11.58584 11.08774 10.63927 - 10.24006 9.88988 9.58883 9.33691 9.13407 8.98010 - 8.87391 8.81559 8.80753 8.84724 8.93216 9.06160 - 9.22672 9.31436 9.39021 9.40100 9.05044 8.52380 - 6.19509 4.81559 2.25202 1.59480 0.92374 0.74859 - 13.41474 12.72873 12.13305 11.58642 11.08895 10.64081 - 10.24180 9.89167 9.59072 9.33895 9.13643 8.98295 - 8.87739 8.81979 8.81265 8.85358 8.94035 9.07290 - 9.24454 9.33869 9.42646 9.46092 9.21492 8.78724 - 6.70601 5.37127 2.63253 1.86393 0.98643 0.74856 - 13.40601 12.72577 12.13126 11.58696 11.09181 10.64489 - 10.24584 9.89495 9.59283 9.33990 9.13660 8.98304 - 8.87807 8.82170 8.81624 8.85905 8.94707 9.07866 - 9.25232 9.35375 9.45110 9.50145 9.32617 8.95461 - 7.06819 5.81148 2.96503 2.09223 1.04878 0.74854 - 2.11406 2.17165 2.22656 2.27904 2.32888 2.37595 - 2.42030 2.46235 2.50278 2.54182 2.57962 2.61672 - 2.65444 2.69391 2.73514 2.77776 2.82078 2.86170 - 2.89736 2.91379 2.93314 2.95252 2.97540 2.98166 - 2.98682 2.98746 2.98800 2.98806 2.98810 2.98813 - 2.66969 2.72372 2.77559 2.82601 2.87467 2.92125 - 2.96541 3.00684 3.04533 3.08086 3.11374 3.14471 - 3.17565 3.20831 3.24309 3.28042 3.32089 3.36549 - 3.41415 3.43800 3.45726 3.46810 3.48338 3.48913 - 3.49163 3.49169 3.49210 3.49213 3.49230 3.49221 - 3.11869 3.17946 3.23454 3.28488 3.33031 3.37078 - 3.40664 3.43869 3.46815 3.49542 3.52098 3.54554 - 3.57080 3.59837 3.62877 3.66248 3.69984 3.74033 - 3.78246 3.80307 3.82158 3.83364 3.84457 3.84739 - 3.84947 3.84968 3.84987 3.84990 3.84989 3.84992 - 3.82113 3.89535 3.95721 4.00814 4.04807 4.07749 - 4.09771 4.11133 4.12181 4.13032 4.13763 4.14494 - 4.15443 4.16800 4.18569 4.20646 4.22955 4.25629 - 4.28770 4.30391 4.31707 4.32400 4.33086 4.33246 - 4.33346 4.33356 4.33367 4.33368 4.33371 4.33371 - 4.35724 4.45349 4.52167 4.56663 4.59320 4.60734 - 4.61172 4.60957 4.60500 4.59912 4.59243 4.58565 - 4.58007 4.57713 4.57750 4.58186 4.59104 4.60587 - 4.62427 4.63238 4.63923 4.64338 4.64677 4.64744 - 4.64794 4.64800 4.64805 4.64805 4.64806 4.64807 - 4.78271 4.90812 4.98263 5.01697 5.02517 5.02271 - 5.01347 4.99964 4.98392 4.96619 4.94535 4.92204 - 4.90021 4.88347 4.87182 4.86366 4.85809 4.85794 - 4.86311 4.86508 4.86633 4.86678 4.86727 4.86729 - 4.86729 4.86729 4.86730 4.86730 4.86730 4.86731 - 5.16026 5.26226 5.33353 5.37722 5.39407 5.38664 - 5.35996 5.32225 5.28367 5.24689 5.21241 5.18082 - 5.15216 5.12669 5.10412 5.08320 5.06337 5.04753 - 5.03927 5.03758 5.03421 5.02979 5.02771 5.02729 - 5.02669 5.02661 5.02657 5.02656 5.02659 5.02658 - 5.74119 5.84601 5.91229 5.94450 5.94399 5.91440 - 5.86237 5.79848 5.73545 5.67643 5.62166 5.57122 - 5.52399 5.47921 5.43633 5.39376 5.35095 5.31183 - 5.28161 5.26993 5.25754 5.24691 5.23878 5.23693 - 5.23526 5.23505 5.23490 5.23487 5.23488 5.23488 - 6.19214 6.29139 6.34685 6.36443 6.34600 6.29603 - 6.22228 6.13679 6.05378 5.97664 5.90547 5.83982 - 5.77780 5.71780 5.65895 5.59921 5.53785 5.47982 - 5.43173 5.41182 5.39177 5.37551 5.36148 5.35819 - 5.35542 5.35508 5.35481 5.35478 5.35477 5.35477 - 6.97472 7.10303 7.12712 7.07467 6.97691 6.86656 - 6.75216 6.63877 6.53183 6.43006 6.33015 6.23006 - 6.13253 6.03949 5.95015 5.86178 5.77260 5.68577 - 5.60505 5.56736 5.53148 5.50470 5.47822 5.47180 - 5.46675 5.46610 5.46561 5.46553 5.46549 5.46549 - 7.54341 7.61950 7.59612 7.50222 7.36551 7.21491 - 7.05961 6.90654 6.76320 6.63001 6.50534 6.38663 - 6.27315 6.16322 6.05617 5.95015 5.84395 5.73942 - 5.63838 5.58912 5.54108 5.50470 5.47002 5.46146 - 5.45465 5.45378 5.45313 5.45303 5.45298 5.45295 - 8.33059 8.26901 8.15065 7.99435 7.80544 7.59169 - 7.36415 7.13785 6.92823 6.73957 6.57145 6.42125 - 6.28634 6.16176 6.04366 5.92353 5.79513 5.66525 - 5.54202 5.48208 5.41854 5.36620 5.32257 5.31187 - 5.30262 5.30152 5.30068 5.30052 5.30050 5.30042 - 8.85100 8.70592 8.50587 8.27435 8.01732 7.74294 - 7.46224 7.18980 6.94013 6.71701 6.51984 6.34499 - 6.18913 6.04716 5.91464 5.78250 5.64370 5.50332 - 5.36748 5.30028 5.22913 5.17072 5.12159 5.10952 - 5.09913 5.09790 5.09694 5.09676 5.09674 5.09665 - 9.23978 9.01830 8.74571 8.44915 8.13464 7.81042 - 7.48710 7.17816 6.89751 6.64790 6.42823 6.23370 - 6.05970 5.90114 5.75359 5.60925 5.46181 5.31425 - 5.17062 5.09980 5.02634 4.96689 4.91416 4.90118 - 4.89030 4.88901 4.88797 4.88780 4.88775 4.88768 - 9.54698 9.25583 8.91868 8.56541 8.20180 7.83593 - 7.47768 7.13921 6.83370 6.56318 6.32535 6.11442 - 5.92419 5.74965 5.58678 5.42998 5.27451 5.12123 - 4.97231 4.89981 4.82687 4.76901 4.71379 4.70016 - 4.68916 4.68784 4.68673 4.68659 4.68649 4.68647 - 9.94416 9.65100 9.21719 8.72172 8.22311 7.77128 - 7.36952 7.01184 6.69308 6.40712 6.14257 5.89241 - 5.66074 5.45194 5.26274 5.08788 4.92167 4.75807 - 4.59805 4.52449 4.45395 4.39921 4.34080 4.32686 - 4.31584 4.31435 4.31327 4.31313 4.31302 4.31303 - 10.43194 9.82973 9.24454 8.70413 8.20435 7.74246 - 7.31622 6.92347 6.56291 6.23511 5.93677 5.66393 - 5.41316 5.18378 4.97510 4.78606 4.61381 4.44600 - 4.27296 4.18889 4.11514 4.06593 4.00894 3.99218 - 3.98165 3.98077 3.97943 3.97917 3.97917 3.97915 - 10.92842 10.14408 9.40428 8.73371 8.12494 7.57172 - 7.06884 6.61364 6.20383 5.83565 5.50377 5.20172 - 4.92277 4.66340 4.42459 4.20396 3.99928 3.80272 - 3.61001 3.51949 3.43966 3.38572 3.32717 3.31153 - 3.30093 3.29989 3.29870 3.29854 3.29835 3.29839 - 11.19707 10.28264 9.43936 8.68447 8.00656 7.39769 - 6.85091 6.36138 5.92627 5.53852 5.18980 4.87107 - 4.57166 4.28577 4.01705 3.76866 3.54174 3.33145 - 3.13476 3.04213 2.95183 2.88400 2.82692 2.81344 - 2.80236 2.80108 2.80004 2.79986 2.79979 2.79972 - 11.60858 10.44983 9.43988 8.56659 7.80429 7.13683 - 6.55160 6.03330 5.56984 5.15316 4.77508 4.42765 - 4.10193 3.79269 3.50165 3.23198 2.98224 2.74833 - 2.52922 2.42666 2.32951 2.25898 2.19935 2.18550 - 2.17436 2.17308 2.17203 2.17187 2.17177 2.17170 - 11.89042 10.56969 9.45802 8.51190 7.69882 6.99539 - 6.38581 5.84958 5.36844 4.93332 4.53700 4.17230 - 3.83140 3.50934 3.20647 2.92427 2.66223 2.41466 - 2.18107 2.07197 1.97127 1.89978 1.83595 1.82126 - 1.80988 1.80855 1.80742 1.80729 1.80714 1.80713 - 12.11446 10.67969 9.50139 8.50539 7.65757 6.92949 - 6.30172 5.75103 5.25608 4.80689 4.39692 4.01959 - 3.66777 3.33678 3.02611 2.73609 2.46650 2.21111 - 1.96775 1.85303 1.74688 1.67117 1.60365 1.58824 - 1.57633 1.57494 1.57373 1.57359 1.57345 1.57349 - 12.30385 10.78491 9.56081 8.52876 7.65529 6.90950 - 6.26775 5.70502 5.19867 4.73836 4.31778 3.93071 - 3.57043 3.23232 2.91549 2.61954 2.34390 2.08283 - 1.83164 1.71188 1.59990 1.51908 1.44785 1.43162 - 1.41898 1.41749 1.41621 1.41605 1.41593 1.41597 - 12.61384 10.98300 9.70345 8.62553 7.71780 6.94828 - 6.28674 5.70597 5.18271 4.70666 4.27143 3.87074 - 3.49784 3.14805 2.82019 2.51354 2.22645 1.95367 - 1.68798 1.55910 1.43653 1.34608 1.26623 1.24775 - 1.23318 1.23146 1.23000 1.22981 1.22968 1.22964 - 12.86127 11.16346 9.85520 8.75246 7.82563 7.04112 - 6.36637 5.77318 5.23860 4.75238 4.30779 3.89804 - 3.51573 3.15585 2.81743 2.49996 2.20122 1.91484 - 1.63428 1.49648 1.36388 1.26421 1.17416 1.15285 - 1.13596 1.13397 1.13229 1.13207 1.13191 1.13176 - 13.30377 11.52250 10.19051 9.06719 8.12811 7.32735 - 6.63547 6.02517 5.47487 4.97407 4.51527 4.09059 - 3.69115 3.31119 2.95031 2.60876 2.28350 1.96411 - 1.64402 1.48293 1.32247 1.19638 1.07798 1.04905 - 1.02581 1.02306 1.02079 1.02049 1.02022 1.02017 - 13.59135 11.77558 10.44940 9.33285 8.40133 7.60079 - 6.90533 6.28931 5.73232 5.22396 4.75657 4.32192 - 3.91058 3.51645 3.13924 2.77934 2.43272 2.08537 - 1.72609 1.54094 1.34931 1.19289 1.04451 1.00816 - 0.97900 0.97547 0.97245 0.97206 0.97184 0.97204 - 13.93199 12.09042 10.80155 9.72844 8.82798 8.04831 - 7.36466 6.75208 6.19025 5.67071 5.18840 4.73794 - 4.31317 3.90852 3.51937 3.13904 2.75815 2.36165 - 1.93294 1.70166 1.45388 1.23984 1.02215 0.97113 - 0.93492 0.93044 0.92496 0.92422 0.92525 0.92481 - 14.10564 12.27047 11.03169 10.00637 9.13691 8.37956 - 7.71096 7.10732 6.54889 6.02827 5.54160 5.08476 - 4.65304 4.24147 3.84452 3.45381 3.05645 2.62981 - 2.14608 1.87235 1.56862 1.30036 1.02148 0.95520 - 0.91123 0.90594 0.89852 0.89755 0.89998 0.89819 - 14.19660 12.37715 11.19008 10.20725 9.36652 8.63007 - 7.97641 7.38293 6.83070 6.31307 5.82697 5.36908 - 4.93563 4.52199 4.12195 3.72577 3.31770 2.86921 - 2.34268 2.03432 1.68153 1.36577 1.03019 0.94843 - 0.89530 0.88914 0.88040 0.87932 0.88275 0.87957 - 14.08117 12.41311 11.34968 10.43171 9.61333 8.87180 - 8.19942 7.58750 7.02929 6.51792 6.04620 5.60577 - 5.18607 4.77807 4.37596 3.97088 3.54681 3.07206 - 2.50611 2.17333 1.79335 1.44832 1.04958 0.94037 - 0.88250 0.87784 0.86715 0.86529 0.87058 0.86548 - 14.12832 12.48335 11.49939 10.63813 9.86472 9.15874 - 8.51442 7.92434 7.38301 6.88452 6.42264 5.98992 - 5.57669 5.17417 4.77571 4.37072 3.93944 3.44194 - 2.82377 2.44632 2.00113 1.58370 1.08801 0.94723 - 0.86722 0.86036 0.84824 0.84633 0.85233 0.84543 - 14.12888 12.51116 11.59163 10.77641 10.04028 9.36415 - 8.74372 8.17264 7.64640 7.16006 6.70831 6.28474 - 5.88090 5.48845 5.09991 4.70272 4.27280 3.76025 - 3.09661 2.67957 2.17905 1.70430 1.14417 0.97681 - 0.85082 0.84107 0.84011 0.83925 0.83227 0.83183 - 14.20528 12.59404 11.73917 10.97615 10.28618 9.65328 - 9.07358 8.54138 8.05238 7.60174 7.18396 6.79202 - 6.41612 6.04704 5.67776 5.29644 4.87987 4.37810 - 3.69897 3.23480 2.62289 2.00081 1.24725 1.02428 - 0.85264 0.83235 0.81650 0.81511 0.81777 0.81171 - 14.19605 12.60687 11.80164 11.08066 10.42693 9.82706 - 9.27771 8.77392 8.31188 7.88720 7.49477 7.12787 - 6.77678 6.43221 6.08679 5.72773 5.32915 4.83403 - 4.13729 3.64789 2.98853 2.28968 1.37364 1.08909 - 0.85384 0.82506 0.80628 0.80480 0.80609 0.80070 - 14.14631 12.58972 11.85040 11.18512 10.57992 10.02455 - 9.51639 9.05153 8.62690 8.23898 7.88348 7.55453 - 7.24328 6.94084 6.63964 6.32545 5.96800 5.49758 - 4.78948 4.27275 3.55955 2.76606 1.61972 1.23751 - 0.87606 0.82521 0.79228 0.79048 0.78804 0.78893 - 14.15563 12.59978 11.88262 11.23805 10.65372 10.12089 - 9.63677 9.19763 8.80037 8.44134 8.11598 7.81771 - 7.53630 7.26197 6.98789 6.70121 6.37412 5.94137 - 5.27718 4.77709 4.05854 3.20483 1.84122 1.35975 - 0.89442 0.82957 0.79043 0.78877 0.78387 0.78270 - 14.13531 12.59988 11.90729 11.28255 10.71508 10.19733 - 9.72657 9.29947 8.91332 8.56569 8.25390 7.97405 - 7.71980 7.48281 7.25107 6.99999 6.69435 6.28168 - 5.64798 5.16396 4.45112 3.56768 2.05502 1.48594 - 0.91910 0.83959 0.78896 0.78480 0.78124 0.77885 - 14.12139 12.59876 11.92031 11.30896 10.75404 10.24734 - 9.78669 9.36945 8.99376 8.65831 8.36189 8.10093 - 7.86725 7.65058 7.43854 7.21112 6.93708 6.55810 - 5.95414 5.48377 4.77969 3.87470 2.25196 1.60636 - 0.94795 0.85401 0.78775 0.78285 0.77642 0.77623 - 14.11061 12.61230 11.94642 11.34485 10.79997 10.30571 - 9.86009 9.46061 9.10525 8.79165 8.51685 8.27625 - 8.06207 7.86699 7.68604 7.50768 7.30206 6.99018 - 6.43011 5.97657 5.29543 4.39055 2.60551 1.84157 - 1.00579 0.87938 0.78839 0.78130 0.77402 0.77292 - 14.09114 12.61667 11.96300 11.37179 10.83638 10.35133 - 9.91494 9.52501 9.17976 8.87720 8.61479 8.38851 - 8.19132 8.01669 7.86083 7.71355 7.54662 7.28168 - 6.77653 6.35285 5.69957 4.79948 2.91633 2.05720 - 1.06390 0.90921 0.79082 0.78065 0.77185 0.77090 - 14.03144 12.61959 11.99420 11.42358 10.90296 10.42938 - 10.00247 9.62171 9.28713 8.99783 8.75229 8.54799 - 8.38004 8.24310 8.13161 8.03022 7.91194 7.72389 - 7.34840 7.00154 6.40915 5.54051 3.56756 2.52800 - 1.20436 0.98553 0.80053 0.78264 0.76959 0.76817 - 14.00887 12.63629 12.00982 11.44144 10.92587 10.46009 - 10.04288 9.67258 9.34811 9.06848 8.83233 8.63724 - 8.47837 8.35206 8.25817 8.19212 8.13397 8.01615 - 7.70888 7.40528 6.87965 6.06842 4.06131 2.92959 - 1.33857 1.06232 0.81375 0.78557 0.76872 0.76681 - 13.86653 12.63569 12.02610 11.46980 10.96286 10.50347 - 10.09136 9.72594 9.40738 9.13540 8.90950 8.72837 - 8.58884 8.48793 8.42345 8.38516 8.35473 8.29500 - 8.11584 7.90625 7.48557 6.77917 4.82610 3.54802 - 1.58760 1.21554 0.84355 0.79216 0.76989 0.76543 - 13.76445 12.63963 12.03326 11.48000 10.97638 10.52076 - 10.11248 9.75109 9.43667 9.16910 8.94835 8.77363 - 8.64255 8.55307 8.50350 8.48412 8.47954 8.46298 - 8.36036 8.20638 7.85335 7.21329 5.36356 4.07527 - 1.81548 1.34641 0.87212 0.80974 0.76969 0.76475 - 13.69012 12.64190 12.03703 11.48502 10.98272 10.52881 - 10.12269 9.76443 9.45429 9.19162 8.97541 8.80446 - 8.67742 8.59330 8.55135 8.54340 8.55696 8.57117 - 8.51455 8.39246 8.09979 7.55499 5.81161 4.45865 - 2.01560 1.48285 0.90558 0.81805 0.77620 0.76434 - 13.63569 12.64314 12.04062 11.48951 10.98803 10.53521 - 10.13068 9.77418 9.46580 9.20524 8.99197 8.82496 - 8.70219 8.62230 8.58535 8.58472 8.60971 8.64046 - 8.62075 8.53696 8.29435 7.78694 6.11349 4.82897 - 2.22030 1.60062 0.93596 0.83664 0.77329 0.76406 - 13.56610 12.64393 12.04434 11.49514 10.99501 10.54403 - 10.14169 9.78762 9.48198 9.22438 9.01432 8.85098 - 8.73260 8.65834 8.62891 8.63874 8.67922 8.73497 - 8.76080 8.71803 8.54704 8.13527 6.61680 5.37523 - 2.58687 1.82845 0.99789 0.86707 0.77756 0.76370 - 13.52152 12.64394 12.04657 11.49872 10.99985 10.55011 - 10.14906 9.79637 9.49211 9.23608 9.02787 8.86683 - 8.75133 8.68064 8.65590 8.67217 8.72220 8.79373 - 8.84827 8.83192 8.71067 8.37096 6.98522 5.79587 - 2.90855 2.03604 1.05825 0.89823 0.78239 0.76348 - 13.45464 12.64377 12.04925 11.50374 11.00689 10.55894 - 10.15961 9.80856 9.50593 9.25175 9.04600 8.88824 - 8.77682 8.71113 8.69277 8.71777 8.78090 8.87445 - 8.96953 8.99092 8.94431 8.72331 7.59700 6.53532 - 3.57128 2.49710 1.20222 0.97676 0.79595 0.76319 - 13.41828 12.64406 12.05053 11.50609 11.01027 10.56333 - 10.16477 9.81452 9.51279 9.25967 9.05524 8.89915 - 8.78986 8.72677 8.71171 8.74125 8.81116 8.91625 - 9.03331 9.07518 9.06838 8.91771 7.98094 7.02614 - 4.08893 2.89782 1.33775 1.05435 0.81057 0.76305 - 13.38151 12.64483 12.05142 11.50756 11.01266 10.56672 - 10.16922 9.82027 9.52017 9.26864 9.06511 8.90933 - 8.80137 8.74186 8.73191 8.76623 8.83994 8.95426 - 9.10379 9.17606 9.19645 9.08258 8.44149 7.75879 - 4.82667 3.48961 1.58864 1.21903 0.84038 0.76292 - 13.36076 12.64526 12.05235 11.50880 11.01406 10.56827 - 10.17114 9.82246 9.52256 9.27150 9.06924 8.91553 - 8.80913 8.74991 8.74011 8.77690 8.85743 8.98033 - 9.13257 9.20771 9.26290 9.23346 8.70972 8.03478 - 5.41871 4.04899 1.81193 1.34232 0.87236 0.76285 - 13.34714 12.64535 12.05288 11.50918 11.01438 10.56882 - 10.17202 9.82383 9.52446 9.27391 9.07210 8.91880 - 8.81290 8.75444 8.74573 8.78418 8.86709 8.99363 - 9.15299 9.23532 9.30403 9.30107 8.88254 8.29623 - 5.84192 4.45963 2.03878 1.47463 0.90356 0.76281 - 13.33738 12.64537 12.05319 11.50963 11.01476 10.56933 - 10.17274 9.82488 9.52582 9.27555 9.07401 8.92100 - 8.81546 8.75749 8.74952 8.78905 8.87359 9.00255 - 9.16673 9.25400 9.33195 9.34693 9.00375 8.48620 - 6.17831 4.80447 2.25305 1.60007 0.93463 0.76278 - 13.32523 12.64527 12.05351 11.51031 11.01587 10.57077 - 10.17438 9.82666 9.52768 9.27755 9.07628 8.92373 - 8.81880 8.76154 8.75444 8.79517 8.88153 9.01351 - 9.18410 9.27772 9.36690 9.40441 9.16442 8.74554 - 6.68588 5.35712 2.63104 1.86750 0.99639 0.76275 - 13.31967 12.64371 12.05212 11.51094 11.01873 10.57464 - 10.17830 9.82984 9.52977 9.27853 9.07652 8.92391 - 8.81958 8.76354 8.75810 8.80053 8.88784 9.01881 - 9.19218 9.29312 9.38880 9.43815 9.27249 8.91053 - 7.04551 5.79535 2.96188 2.09416 1.05787 0.76273 - 2.05115 2.10668 2.16010 2.21167 2.26116 2.30841 - 2.35344 2.39647 2.43799 2.47812 2.51689 2.55473 - 2.59272 2.63183 2.67212 2.71357 2.75570 2.79670 - 2.83406 2.85153 2.87075 2.88908 2.91310 2.92016 - 2.92532 2.92585 2.92643 2.92655 2.92655 2.92660 - 2.59148 2.64646 2.69938 2.75089 2.80066 2.84837 - 2.89366 2.93621 2.97580 3.01235 3.04619 3.07803 - 3.10974 3.14307 3.17841 3.21615 3.25693 3.30196 - 3.35140 3.37576 3.39549 3.40668 3.42275 3.42886 - 3.43153 3.43159 3.43203 3.43207 3.43226 3.43215 - 3.03201 3.09502 3.15225 3.20461 3.25188 3.29406 - 3.33146 3.36499 3.39593 3.42470 3.45175 3.47775 - 3.50434 3.53310 3.56454 3.59923 3.63754 3.67900 - 3.72220 3.74338 3.76253 3.77521 3.78707 3.79018 - 3.79245 3.79268 3.79290 3.79295 3.79293 3.79296 - 3.72595 3.80366 3.86880 3.92271 3.96528 3.99704 - 4.01935 4.03502 4.04768 4.05851 4.06826 4.07800 - 4.08973 4.10525 4.12463 4.14706 4.17191 4.20040 - 4.23332 4.25027 4.26441 4.27235 4.28024 4.28211 - 4.28334 4.28347 4.28361 4.28362 4.28366 4.28365 - 4.25804 4.36044 4.43256 4.47978 4.50806 4.52456 - 4.53197 4.53321 4.53203 4.52937 4.52557 4.52133 - 4.51812 4.51753 4.52027 4.52702 4.53856 4.55535 - 4.57538 4.58461 4.59274 4.59800 4.60245 4.60340 - 4.60413 4.60423 4.60430 4.60431 4.60431 4.60432 - 4.69842 4.79782 4.87188 4.92295 4.95144 4.95926 - 4.95030 4.93128 4.91055 4.89044 4.87151 4.85451 - 4.84013 4.82910 4.82128 4.81563 4.81160 4.81149 - 4.81797 4.82306 4.82620 4.82652 4.82839 4.82889 - 4.82902 4.82903 4.82907 4.82906 4.82909 4.82908 - 5.06337 5.16835 5.24298 5.29017 5.31065 5.30691 - 5.28390 5.24987 5.21493 5.18175 5.15082 5.12265 - 5.09725 5.07482 5.05511 5.03694 5.01978 5.00645 - 5.00041 4.99981 4.99787 4.99483 4.99377 4.99360 - 4.99323 4.99318 4.99317 4.99316 4.99319 4.99318 - 5.64750 5.75483 5.82431 5.86020 5.86376 5.83851 - 5.79093 5.73148 5.67268 5.61767 5.56668 5.51978 - 5.47591 5.43433 5.39450 5.35489 5.31499 5.27859 - 5.25078 5.24026 5.22932 5.22001 5.21284 5.21122 - 5.20973 5.20955 5.20943 5.20941 5.20940 5.20942 - 6.10188 6.20343 6.26215 6.28365 6.26974 6.22466 - 6.15599 6.07548 5.99715 5.92426 5.85696 5.79485 - 5.73615 5.67932 5.62352 5.56680 5.50841 5.45320 - 5.40763 5.38890 5.37021 5.35512 5.34199 5.33890 - 5.33631 5.33599 5.33574 5.33572 5.33569 5.33570 - 6.89365 7.02143 7.04891 7.00248 6.91170 6.80783 - 6.69920 6.59101 6.48883 6.39144 6.29551 6.19900 - 6.10479 6.01488 5.92853 5.84301 5.75657 5.67241 - 5.59424 5.55770 5.52293 5.49701 5.47127 5.46503 - 5.46008 5.45944 5.45898 5.45892 5.45885 5.45886 - 7.46873 7.54408 7.52477 7.43798 7.30947 7.16627 - 7.01734 6.86983 6.73153 6.60288 6.48226 6.36718 - 6.25698 6.15011 6.04588 5.94247 5.83868 5.73658 - 5.63789 5.58958 5.54244 5.50678 5.47282 5.46440 - 5.45769 5.45684 5.45621 5.45611 5.45605 5.45603 - 8.26216 8.20536 8.09315 7.94380 7.76236 7.55634 - 7.33641 7.11714 6.91362 6.73002 6.56608 6.41938 - 6.28753 6.16579 6.05035 5.93265 5.80639 5.67838 - 5.55677 5.49754 5.43470 5.38295 5.34002 5.32947 - 5.32032 5.31923 5.31840 5.31824 5.31823 5.31818 - 8.78746 8.64930 8.45711 8.23374 7.98495 7.71867 - 7.44567 7.18021 6.93661 6.71859 6.52569 6.35450 - 6.20187 6.06292 5.93314 5.80340 5.66653 5.52770 - 5.39311 5.32644 5.25585 5.19796 5.14945 5.13751 - 5.12721 5.12600 5.12505 5.12488 5.12485 5.12480 - 9.17926 8.96700 8.70395 8.41654 8.11074 7.79468 - 7.47880 7.17652 6.90166 6.65709 6.44171 6.25095 - 6.08039 5.92499 5.78032 5.63846 5.49293 5.34685 - 5.20436 5.13399 5.06098 5.00193 4.94968 4.93680 - 4.92600 4.92473 4.92371 4.92353 4.92348 4.92344 - 9.48832 9.20872 8.88266 8.53943 8.18481 7.82693 - 7.47571 7.14341 6.84336 6.57769 6.34415 6.13711 - 5.95048 5.77923 5.61936 5.46513 5.31169 5.15997 - 5.01222 4.94016 4.86757 4.80998 4.75506 4.74150 - 4.73057 4.72925 4.72814 4.72802 4.72793 4.72790 - 9.97974 9.54647 9.09563 8.65682 8.23112 7.82136 - 7.43105 7.06409 6.72593 6.41920 6.14281 5.89503 - 5.67558 5.48376 5.31142 5.14349 4.96956 4.80005 - 4.64565 4.57341 4.50290 4.44770 4.38997 4.37545 - 4.36460 4.36318 4.36207 4.36193 4.36184 4.36180 - 10.38245 9.79437 9.22191 8.69240 8.20195 7.74808 - 7.32866 6.94172 6.58607 6.26234 5.96743 5.69759 - 5.44967 5.22312 5.01725 4.83112 4.66180 4.49661 - 4.32541 4.24183 4.16824 4.11889 4.06172 4.04494 - 4.03433 4.03344 4.03209 4.03182 4.03184 4.03178 - 10.88905 10.11924 9.39184 8.73153 8.13131 7.58521 - 7.08826 6.63796 6.23211 5.86714 5.53794 5.23831 - 4.96171 4.70477 4.46850 4.25058 4.04880 3.85501 - 3.66456 3.57481 3.49534 3.44125 3.38227 3.36644 - 3.35569 3.35463 3.35342 3.35326 3.35308 3.35310 - 11.16303 10.26564 9.43541 8.69017 8.01932 7.41562 - 6.87274 6.38633 5.95399 5.56891 5.22277 4.90662 - 4.60976 4.32631 4.05989 3.81368 3.58895 3.38092 - 3.18659 3.09504 3.00534 2.93746 2.87990 2.86620 - 2.85492 2.85362 2.85256 2.85238 2.85230 2.85226 - 11.58828 10.44205 9.44121 8.57495 7.81824 7.15529 - 6.57363 6.05821 5.59712 5.18238 4.80601 4.46018 - 4.13607 3.82848 3.53908 3.27098 3.02283 2.79073 - 2.57376 2.47234 2.37610 2.30594 2.24601 2.23197 - 2.22068 2.21938 2.21832 2.21815 2.21805 2.21802 - 11.87569 10.56512 9.46055 8.52012 7.71182 7.01253 - 6.40633 5.87280 5.39372 4.96015 4.56509 4.20150 - 3.86169 3.54083 3.23919 2.95819 2.69731 2.45114 - 2.21938 2.11136 2.01171 1.94088 1.87705 1.86228 - 1.85085 1.84951 1.84837 1.84824 1.84809 1.84809 - 12.09957 10.67509 9.50325 8.51255 7.66919 6.94496 - 6.32033 5.77211 5.27898 4.83115 4.42220 4.04573 - 3.69477 3.36471 3.05502 2.76597 2.49730 2.24308 - 2.00134 1.88762 1.78249 1.70755 1.64037 1.62500 - 1.61315 1.61176 1.61055 1.61041 1.61027 1.61027 - 12.28579 10.77856 9.56121 8.53458 7.66550 6.92335 - 6.28450 5.72403 5.21932 4.76024 4.34058 3.95428 - 3.59473 3.25740 2.94139 2.64627 2.37146 2.11141 - 1.86169 1.74285 1.63184 1.55182 1.48126 1.46519 - 1.45268 1.45121 1.44994 1.44979 1.44967 1.44965 - 12.58564 10.97105 9.70007 8.62861 7.72559 6.95949 - 6.30046 5.72155 5.19969 4.72474 4.29036 3.89041 - 3.51815 3.16900 2.84181 2.53588 2.24962 1.97779 - 1.71335 1.58525 1.46355 1.37398 1.29533 1.27720 - 1.26291 1.26122 1.25979 1.25960 1.25948 1.25943 - 12.82137 11.14505 9.84780 8.75295 7.83138 7.05029 - 6.37777 5.78615 5.25280 4.76760 4.32391 3.91493 - 3.53328 3.17402 2.83620 2.51946 2.22162 1.93623 - 1.65676 1.51964 1.38789 1.28921 1.20074 1.17992 - 1.16340 1.16146 1.15982 1.15961 1.15945 1.15938 - 13.23661 11.48856 10.17387 9.06185 8.12928 7.33212 - 6.64202 6.03277 5.48349 4.98382 4.52621 4.10267 - 3.70419 3.32498 2.96476 2.62392 2.29959 1.98131 - 1.66244 1.50209 1.34261 1.21766 1.10111 1.07273 - 1.04992 1.04722 1.04501 1.04471 1.04445 1.04444 - 13.50308 11.72938 10.42509 9.32223 8.39815 7.60139 - 6.90747 6.29221 5.73625 5.22932 4.76359 4.33061 - 3.92068 3.52755 3.15105 2.79173 2.44581 2.09966 - 1.74221 1.55814 1.36768 1.21235 1.06555 1.02968 - 1.00090 0.99740 0.99441 0.99404 0.99382 0.99379 - 13.81893 12.02796 10.76518 9.70815 8.81653 8.04134 - 7.35954 6.74793 6.18754 5.67003 5.19006 4.74192 - 4.31901 3.91553 3.52705 3.14717 2.76696 2.37197 - 1.94597 1.71627 1.46990 1.25681 1.04002 0.98943 - 0.95381 0.94937 0.94381 0.94306 0.94413 0.94283 - 13.98395 12.20053 10.98782 9.97845 9.11818 8.36575 - 7.69955 7.09747 6.54116 6.02330 5.53968 5.08575 - 4.65620 4.24577 3.84925 3.45868 3.06181 2.63691 - 2.15667 1.88500 1.58285 1.31532 1.03699 0.97121 - 0.92826 0.92305 0.91539 0.91440 0.91690 0.91390 - 14.07643 12.30555 11.14171 10.17322 9.34133 8.61017 - 7.95964 7.36859 6.81924 6.30498 5.82241 5.36776 - 4.93663 4.52411 4.12434 3.72807 3.32037 2.87377 - 2.35126 2.04528 1.69426 1.37913 1.04399 0.96284 - 0.91119 0.90515 0.89606 0.89492 0.89848 0.89403 - 13.97758 12.34440 11.29541 10.38812 9.57823 8.84392 - 8.17755 7.57068 7.01668 6.50880 6.03994 5.60177 - 5.18382 4.77713 4.37600 3.97175 3.54869 3.07580 - 2.51305 2.18226 1.80422 1.46034 1.06229 0.95357 - 0.89759 0.89316 0.88203 0.88007 0.88555 0.87926 - 14.03077 12.41789 11.44427 10.59092 9.82429 9.12441 - 8.48563 7.90062 7.36388 6.86955 6.41137 5.98181 - 5.57112 5.17040 4.77318 4.36903 3.93859 3.44275 - 2.82778 2.45248 2.00952 1.59360 1.09889 0.95881 - 0.88138 0.87487 0.86223 0.86017 0.86642 0.85861 - 14.03567 12.44814 11.53606 10.72694 9.99619 9.32531 - 8.70996 8.14382 7.62235 7.14054 6.69303 6.27322 - 5.87245 5.48227 5.09526 4.69904 4.26992 3.75884 - 3.09818 2.68325 2.18512 1.71237 1.15422 0.98777 - 0.86390 0.85470 0.85402 0.85301 0.84555 0.84482 - 14.11617 12.53199 11.68060 10.92090 10.23460 9.60593 - 9.03092 8.50381 8.02015 7.57497 7.16252 6.77543 - 6.40336 6.03676 5.66872 5.28767 4.87114 4.37092 - 3.69631 3.23524 2.62618 2.00601 1.25456 1.03309 - 0.86569 0.84590 0.82960 0.82819 0.83076 0.82461 - 14.10236 12.54144 11.73951 11.02186 10.37167 9.77583 - 9.23094 8.73199 8.27503 7.85557 7.46831 7.10622 - 6.75913 6.41740 6.07374 5.71557 5.31756 4.82415 - 4.13165 3.64528 2.98910 2.29282 1.37976 1.09694 - 0.86643 0.83833 0.81934 0.81781 0.81908 0.81365 - 14.04125 12.51684 11.78255 11.12185 10.52098 9.96986 - 9.46599 9.00542 8.58510 8.20144 7.85014 7.52521 - 7.21766 6.91848 6.62011 6.30837 5.95312 5.48500 - 4.77991 4.26529 3.55510 2.76534 1.62520 1.24515 - 0.88743 0.83758 0.80572 0.80391 0.80086 0.80200 - 14.04443 12.52242 11.81099 11.17144 10.59176 10.06342 - 9.58361 9.14863 8.75538 8.40026 8.07866 7.78403 - 7.50601 7.23483 6.96363 6.67966 6.35528 5.92549 - 5.26509 4.76750 4.05225 3.20226 1.84479 1.36594 - 0.90566 0.84187 0.80369 0.80208 0.79716 0.79586 - 14.02003 12.51923 11.83296 11.21375 10.65127 10.13818 - 9.67179 9.24873 8.86634 8.52221 8.21370 7.93701 - 7.68588 7.45200 7.22340 6.97536 6.67264 6.26305 - 5.63323 5.15199 4.44324 3.56411 2.05727 1.49115 - 0.92990 0.85170 0.80231 0.79809 0.79460 0.79208 - 14.00263 12.51653 11.84536 11.23976 10.68957 10.18724 - 9.73047 9.31689 8.94468 8.61257 8.31932 8.06134 - 7.83057 7.61694 7.40812 7.18402 6.91331 6.53754 - 5.93755 5.47022 4.77024 3.86923 2.25317 1.61135 - 0.95831 0.86565 0.80107 0.79637 0.78977 0.78953 - 13.99194 12.52859 11.86940 11.27359 10.73366 10.24390 - 9.80228 9.40635 9.05418 8.74347 8.47131 8.23323 - 8.02162 7.82924 7.65127 7.47620 7.27425 6.96635 - 6.41079 5.96017 5.28317 4.38299 2.60529 1.84519 - 1.01537 0.89053 0.80172 0.79483 0.78749 0.78630 - 13.97434 12.53369 11.88607 11.30005 10.76924 10.28833 - 9.85565 9.46905 9.12681 8.82699 8.56710 8.34321 - 8.14844 7.97640 7.82333 7.67919 7.51583 7.25498 - 6.75468 6.33417 5.68520 4.78996 2.91478 2.05987 - 1.07281 0.91985 0.80409 0.79425 0.78535 0.78433 - 13.92277 12.53995 11.91782 11.35066 10.83360 10.36378 - 9.94051 9.56321 9.23169 8.94505 8.70184 8.49964 - 8.33365 8.19870 8.08937 7.99061 7.87575 7.69194 - 7.32182 6.97838 6.39040 5.52702 3.56375 2.52845 - 1.21185 0.99518 0.81360 0.79623 0.78312 0.78167 - 13.88267 12.54929 11.93385 11.37306 10.86253 10.39959 - 9.98372 9.61406 9.29036 9.01198 8.77798 8.58658 - 8.43388 8.31585 8.22832 8.15805 8.08166 7.95318 - 7.66713 7.38248 6.86744 6.06458 4.06098 2.90819 - 1.34722 1.07676 0.82699 0.79620 0.78187 0.78035 - 13.76430 12.55583 11.94886 11.39547 10.89173 10.43574 - 10.02695 9.66470 9.34891 9.07926 8.85529 8.67581 - 8.53766 8.43807 8.37488 8.33816 8.30988 8.25341 - 8.07960 7.87405 7.45893 6.75897 4.81649 3.54330 - 1.59264 1.22342 0.85574 0.80529 0.78342 0.77900 - 13.66089 12.55719 11.95509 11.40560 10.90553 10.45320 - 10.04783 9.68911 9.37706 9.11156 8.89258 8.71941 - 8.58968 8.50138 8.45291 8.43473 8.43176 8.41787 - 8.32022 8.17022 7.82281 7.18928 5.35133 4.06891 - 1.81918 1.35310 0.88372 0.82270 0.78328 0.77832 - 13.58490 12.55837 11.95904 11.41087 10.91171 10.46076 - 10.05756 9.70195 9.39409 9.13337 8.91877 8.74924 - 8.62341 8.54035 8.49938 8.49247 8.50740 8.52376 - 8.47126 8.35282 8.06605 7.52895 5.79754 4.44873 - 2.01853 1.48946 0.91673 0.83023 0.78994 0.77791 - 13.53057 12.55923 11.96261 11.41533 10.91667 10.46690 - 10.06525 9.71142 9.40528 9.14650 8.93471 8.76908 - 8.64748 8.56857 8.53248 8.53275 8.55884 8.59129 - 8.57518 8.49498 8.25808 7.75778 6.09716 4.81912 - 2.22204 1.60602 0.94666 0.84881 0.78688 0.77764 - 13.46458 12.56024 11.96611 11.42062 10.92351 10.47546 - 10.07596 9.72450 9.42101 9.16515 8.95653 8.79441 - 8.67707 8.60363 8.57493 8.58541 8.62662 8.68352 - 8.71205 8.67227 8.50658 8.10198 6.59741 5.36297 - 2.58686 1.83284 1.00778 0.87853 0.79112 0.77730 - 13.42423 12.56075 11.96803 11.42388 10.92822 10.48149 - 10.08321 9.73303 9.43090 9.17659 8.96981 8.80995 - 8.69540 8.62543 8.60125 8.61798 8.66850 8.74081 - 8.79745 8.78355 8.66702 8.33433 6.96337 5.78164 - 2.90711 2.03955 1.06743 0.90909 0.79588 0.77709 - 13.36396 12.56150 11.97019 11.42826 10.93502 10.49027 - 10.09365 9.74496 9.44436 9.19193 8.98757 8.83089 - 8.72029 8.65518 8.63720 8.66242 8.72564 8.81947 - 8.91567 8.93857 8.89547 8.68077 7.57016 6.51680 - 3.56724 2.49861 1.21000 0.98641 0.80918 0.77681 - 13.32982 12.56180 11.97107 11.43011 10.93797 10.49423 - 10.09857 9.75097 9.45175 9.20064 8.99704 8.84067 - 8.73146 8.66988 8.65678 8.68642 8.75308 8.85593 - 8.98302 9.03340 9.01346 8.83210 7.96431 7.09042 - 4.04773 2.85867 1.34685 1.07423 0.82540 0.77668 - 13.29166 12.56219 11.97254 11.43236 10.94094 10.49789 - 10.10298 9.75625 9.45804 9.20811 9.00589 8.85115 - 8.74396 8.68491 8.67518 8.70947 8.78294 8.89698 - 9.04653 9.11930 9.14141 9.03146 8.40443 7.73178 - 4.81689 3.48524 1.59386 1.22678 0.85272 0.77654 - 13.27004 12.56242 11.97378 11.43388 10.94232 10.49943 - 10.10478 9.75832 9.46033 9.21086 9.00989 8.85721 - 8.75156 8.69279 8.68311 8.71977 8.79993 8.92238 - 9.07441 9.14982 9.20607 9.17963 8.66863 8.00348 - 5.40689 4.04250 1.81585 1.34886 0.88412 0.77648 - 13.25639 12.56251 11.97440 11.43436 10.94264 10.49987 - 10.10558 9.75966 9.46227 9.21335 9.01285 8.86053 - 8.75531 8.69724 8.68863 8.72685 8.80931 8.93526 - 9.09424 9.17667 9.24609 9.24536 8.83845 8.26294 - 5.82800 4.45093 2.04156 1.48046 0.91478 0.77644 - 13.24706 12.56253 11.97482 11.43482 10.94302 10.50027 - 10.10625 9.76068 9.46361 9.21505 9.01485 8.86278 - 8.75788 8.70025 8.69234 8.73161 8.81563 8.94393 - 9.10756 9.19482 9.27327 9.28992 8.95743 8.45135 - 6.16253 4.79390 2.25425 1.60529 0.94537 0.77641 - 13.23633 12.56253 11.97483 11.43528 10.94402 10.50170 - 10.10787 9.76241 9.46545 9.21702 9.01709 8.86551 - 8.76117 8.70425 8.69715 8.73758 8.82334 8.95454 - 9.12443 9.21787 9.30729 9.34589 9.11428 8.70602 - 6.66682 5.34361 2.62986 1.87120 1.00616 0.77638 - 13.23203 12.56108 11.97324 11.43552 10.94647 10.50537 - 10.11168 9.76554 9.46746 9.21784 9.01710 8.86543 - 8.76172 8.70601 8.70060 8.74274 8.82952 8.95971 - 9.13227 9.23289 9.32863 9.37904 9.21935 8.86451 - 7.02329 5.78010 2.95913 2.09631 1.06677 0.77636 - 1.98824 2.04254 2.09520 2.14645 2.19608 2.24388 - 2.28975 2.33377 2.37618 2.41703 2.45633 2.49447 - 2.53254 2.57150 2.61144 2.65239 2.69401 2.73460 - 2.77188 2.78952 2.80915 2.82803 2.85266 2.85986 - 2.86515 2.86571 2.86631 2.86642 2.86642 2.86647 - 2.51586 2.57739 2.63481 2.68866 2.73874 2.78497 - 2.82760 2.86730 2.90512 2.94136 2.97625 3.01027 - 3.04467 3.08064 3.11849 3.15857 3.20105 3.24525 - 3.28968 3.31132 3.33221 3.34799 3.36438 3.36879 - 3.37211 3.37247 3.37280 3.37286 3.37287 3.37290 - 2.94975 3.01863 3.08038 3.13579 3.18468 3.22721 - 3.26404 3.29668 3.32723 3.35628 3.38426 3.41168 - 3.43988 3.47015 3.50293 3.53865 3.57764 3.61965 - 3.66358 3.68525 3.70505 3.71834 3.73059 3.73375 - 3.73613 3.73638 3.73659 3.73663 3.73664 3.73666 - 3.63865 3.72014 3.78852 3.84504 3.88958 3.92274 - 3.94611 3.96275 3.97672 3.98926 4.00106 4.01310 - 4.02715 4.04479 4.06603 4.08999 4.11604 4.14577 - 4.18041 4.19838 4.21347 4.22205 4.23062 4.23266 - 4.23401 4.23414 4.23429 4.23431 4.23436 4.23435 - 4.17034 4.27241 4.34534 4.39433 4.42513 4.44457 - 4.45521 4.45969 4.46148 4.46157 4.46048 4.45901 - 4.45845 4.46023 4.46507 4.47382 4.48737 4.50602 - 4.52791 4.53828 4.54763 4.55386 4.55919 4.56038 - 4.56129 4.56140 4.56150 4.56150 4.56151 4.56151 - 4.61147 4.70767 4.78047 4.83219 4.86314 4.87494 - 4.87101 4.85734 4.84146 4.82545 4.80995 4.79577 - 4.78382 4.77508 4.76949 4.76617 4.76470 4.76707 - 4.77560 4.78166 4.78611 4.78778 4.79067 4.79144 - 4.79183 4.79185 4.79191 4.79192 4.79195 4.79194 - 4.97770 5.07705 5.14890 5.19615 5.21934 5.22054 - 5.20401 5.17688 5.14799 5.11971 5.09261 5.06736 - 5.04434 5.02416 5.00671 4.99109 4.97693 4.96645 - 4.96252 4.96285 4.96229 4.96077 4.96084 4.96098 - 4.96089 4.96087 4.96089 4.96088 4.96091 4.96091 - 5.56394 5.66363 5.72925 5.76498 5.77187 5.75279 - 5.71333 5.66241 5.61091 5.56161 5.51486 5.47098 - 5.42946 5.39008 5.35253 5.31570 5.27921 5.24611 - 5.22052 5.21087 5.20127 5.19354 5.18765 5.18637 - 5.18523 5.18509 5.18498 5.18497 5.18498 5.18498 - 6.01962 6.11419 6.16974 6.19178 6.18182 6.14350 - 6.08337 6.01174 5.94093 5.87390 5.81092 5.75188 - 5.69554 5.64093 5.58743 5.53354 5.47872 5.42695 - 5.38369 5.36582 5.34837 5.33470 5.32290 5.32018 - 5.31792 5.31765 5.31742 5.31740 5.31739 5.31740 - 6.80754 6.94255 6.97260 6.92643 6.83749 6.74026 - 6.64164 6.54350 6.44786 6.35392 6.26049 6.16701 - 6.07603 5.98924 5.90584 5.82314 5.73948 5.65819 - 5.58276 5.54720 5.51337 5.48833 5.46390 5.45800 - 5.45334 5.45274 5.45229 5.45222 5.45218 5.45218 - 7.38860 7.46890 7.45609 7.37654 7.25517 7.11827 - 6.97491 6.83246 6.69905 6.57501 6.45834 6.34649 - 6.23914 6.13509 6.03362 5.93281 5.83149 5.73212 - 5.63617 5.58873 5.54237 5.50742 5.47453 5.46636 - 5.45988 5.45906 5.45843 5.45834 5.45829 5.45828 - 8.18251 8.14338 8.04558 7.90715 7.73347 7.53247 - 7.31561 7.09853 6.89754 6.71703 6.55660 6.41370 - 6.28555 6.16723 6.05475 5.93940 5.81485 5.68854 - 5.56924 5.51125 5.44922 5.39775 5.35554 5.34516 - 5.33609 5.33503 5.33422 5.33405 5.33405 5.33396 - 8.71139 8.59613 8.42180 8.21119 7.97064 7.70891 - 7.43790 7.17345 6.93155 6.71620 6.52672 6.35950 - 6.21092 6.07567 5.94911 5.82172 5.68619 5.54858 - 5.41605 5.35057 5.28072 5.22301 5.17499 5.16315 - 5.15288 5.15167 5.15074 5.15055 5.15053 5.15044 - 9.10909 8.91992 8.67476 8.40019 8.10279 7.79156 - 7.47805 7.17719 6.90435 6.66258 6.45069 6.26392 - 6.09742 5.94577 5.80441 5.66499 5.52090 5.37601 - 5.23530 5.16590 5.09353 5.03466 4.98274 4.96994 - 4.95915 4.95787 4.95685 4.95668 4.95663 4.95656 - 9.39758 9.20020 8.89597 8.53711 8.15844 7.79275 - 7.44928 7.13377 6.85236 6.60259 6.37724 6.16929 - 5.97826 5.80383 5.64311 5.49173 5.34484 5.19832 - 5.05029 4.97734 4.90517 4.84901 4.79390 4.78034 - 4.76952 4.76811 4.76708 4.76693 4.76683 4.76681 - 9.93099 9.50897 9.06837 8.63880 8.22143 7.81915 - 7.43551 7.07445 6.74151 6.43929 6.16683 5.92261 - 5.70643 5.51770 5.34833 5.18324 5.01186 4.84429 - 4.69101 4.61914 4.54894 4.49396 4.43643 4.42197 - 4.41118 4.40976 4.40865 4.40852 4.40843 4.40843 - 10.33742 9.75989 9.19690 8.67596 8.19337 7.74670 - 7.33396 6.95320 6.60330 6.28479 5.99468 5.72926 - 5.48529 5.26213 5.05917 4.87550 4.70823 4.54476 - 4.37492 4.29184 4.21856 4.16931 4.11229 4.09558 - 4.08503 4.08414 4.08280 4.08254 4.08255 4.08255 - 10.71913 10.12438 9.45512 8.77995 8.13721 7.55805 - 7.04721 6.60814 6.24135 5.92268 5.61386 5.29914 - 5.00288 4.74149 4.50727 4.29037 4.08680 3.89539 - 3.71642 3.63282 3.55369 3.49292 3.43408 3.41994 - 3.40899 3.40748 3.40639 3.40628 3.40614 3.40615 - 11.14529 10.24622 9.41776 8.67758 8.01414 7.41922 - 6.88543 6.40723 5.98110 5.60029 5.25703 4.94281 - 4.64750 4.36563 4.10093 3.85688 3.63486 3.42944 - 3.23687 3.14583 3.05645 2.98864 2.93090 2.91711 - 2.90576 2.90444 2.90338 2.90319 2.90312 2.90304 - 11.56630 10.43138 9.43854 8.57910 7.82838 7.17069 - 6.59357 6.08193 5.62381 5.21135 4.83681 4.49251 - 4.16980 3.86359 3.57556 3.30880 3.06216 2.83181 - 2.61691 2.51655 2.42109 2.35118 2.29099 2.27680 - 2.26538 2.26407 2.26298 2.26282 2.26271 2.26262 - 11.84650 10.55875 9.46727 8.53510 7.73167 7.03498 - 6.42991 5.89690 5.41850 4.98591 4.59206 4.22986 - 3.89149 3.57199 3.27153 2.99144 2.73127 2.48623 - 2.25649 2.14974 2.05116 1.98086 1.91685 1.90195 - 1.89041 1.88906 1.88790 1.88777 1.88762 1.88761 - 12.06395 10.67015 9.51489 8.53344 7.69419 6.97080 - 6.34514 5.79542 5.30158 4.85391 4.44584 4.07072 - 3.72123 3.39251 3.08393 2.79559 2.52731 2.27389 - 2.03401 1.92156 1.81759 1.74333 1.67616 1.66071 - 1.64880 1.64740 1.64618 1.64604 1.64590 1.64595 - 12.24545 10.77322 9.57416 8.55727 7.69195 6.94978 - 6.30883 5.74588 5.23981 4.78053 4.36158 3.97657 - 3.61847 3.28246 2.96750 2.67303 2.39850 2.13912 - 1.89112 1.77350 1.66366 1.58440 1.51403 1.49794 - 1.48542 1.48395 1.48267 1.48252 1.48239 1.48246 - 12.54209 10.96158 9.70757 8.64554 7.74648 6.98079 - 6.32030 5.73953 5.21668 4.74165 4.30791 3.90904 - 3.53800 3.18995 2.86368 2.55840 2.27255 2.00144 - 1.73859 1.61159 1.49106 1.40239 1.32421 1.30615 - 1.29192 1.29024 1.28881 1.28863 1.28850 1.28848 - 12.77954 11.12937 9.84481 8.75814 7.84131 7.06260 - 6.39109 5.79992 5.26704 4.78246 4.33950 3.93135 - 3.55054 3.19207 2.85502 2.53895 2.24181 1.95739 - 1.67945 1.54337 1.41280 1.31513 1.22735 1.20666 - 1.19027 1.18834 1.18671 1.18650 1.18634 1.18618 - 13.19479 11.46201 10.15364 9.04797 8.12112 7.32931 - 6.64404 6.03879 5.49239 4.99463 4.53819 4.11533 - 3.71732 3.33856 2.97886 2.63879 2.31552 1.99853 - 1.68112 1.52169 1.36340 1.23968 1.12435 1.09629 - 1.07374 1.07108 1.06889 1.06859 1.06834 1.06826 - 13.45135 11.69876 10.40325 9.30751 8.38871 7.59650 - 6.90643 6.29438 5.74098 5.23606 4.77186 4.34005 - 3.93100 3.53856 3.16265 2.80404 2.45910 2.11409 - 1.75795 1.57472 1.38553 1.23162 1.08659 1.05126 - 1.02290 1.01946 1.01651 1.01614 1.01592 1.01620 - 13.74068 11.99482 10.75279 9.70681 8.81944 8.04462 - 7.36112 6.74756 6.18650 5.66965 5.19130 4.74529 - 4.32448 3.92273 3.53554 3.15648 2.77671 2.38226 - 1.95736 1.72863 1.48378 1.27248 1.05827 1.00866 - 0.97397 0.96962 0.96400 0.96320 0.96430 0.96441 - 13.77976 12.15070 11.01712 10.03981 9.17901 8.40614 - 7.71099 7.08336 6.51509 5.99805 5.52394 5.08334 - 4.66483 4.25943 3.86280 3.46888 3.06710 2.63727 - 2.15573 1.88791 1.59613 1.33887 1.05646 0.98421 - 0.94671 0.94337 0.93480 0.93320 0.93656 0.93524 - 13.85879 12.24837 11.16796 10.23505 9.40502 8.65452 - 7.97503 7.35760 6.79520 6.28068 5.80662 5.36455 - 4.94396 4.53612 4.13592 3.73583 3.32239 2.86930 - 2.34418 2.04295 1.70585 1.40447 1.06361 0.97347 - 0.92879 0.92522 0.91491 0.91297 0.91770 0.91494 - 13.90523 12.30991 11.27672 10.37974 9.57669 8.84661 - 8.18240 7.57604 7.02129 6.51173 6.04064 5.60018 - 5.18054 4.77318 4.37240 3.96949 3.54861 3.07828 - 2.51822 2.18900 1.81291 1.47099 1.07643 0.96939 - 0.91591 0.91176 0.90023 0.89810 0.90373 0.89964 - 13.93507 12.37039 11.41891 10.58068 9.82386 9.12986 - 8.49365 7.90855 7.36969 6.87185 6.40949 5.97607 - 5.56312 5.16263 4.76780 4.36749 3.94086 3.44530 - 2.82530 2.44722 2.00466 1.59576 1.12300 0.98595 - 0.89004 0.88453 0.88514 0.88401 0.87729 0.87798 - 13.94800 12.40326 11.50838 10.71117 9.98855 9.32287 - 8.71024 8.14480 7.62239 7.13843 6.68801 6.26515 - 5.86203 5.47085 5.08419 4.68967 4.26341 3.75572 - 3.09859 2.68573 2.19024 1.72023 1.16622 1.00159 - 0.88062 0.87201 0.87149 0.87032 0.86265 0.86335 - 14.01280 12.47447 11.64112 10.89452 10.21721 9.59445 - 9.02262 8.49646 8.01199 7.56459 7.14916 6.75904 - 6.38504 6.01839 5.65217 5.27463 4.86259 4.36602 - 3.69325 3.23351 2.62769 2.01151 1.26433 1.04481 - 0.88207 0.86281 0.84605 0.84460 0.84706 0.84176 - 13.99196 12.47540 11.68994 10.98440 10.34301 9.75335 - 9.21230 8.71523 8.25853 7.83808 7.44908 7.08511 - 6.73697 6.39575 6.05418 5.69954 5.30600 4.81640 - 4.12618 3.64135 2.98857 2.29648 1.38817 1.10744 - 0.88196 0.85455 0.83530 0.83371 0.83494 0.82998 - 13.92393 12.43979 11.71818 11.06742 10.47435 9.92947 - 9.43032 8.97318 8.55519 8.17295 7.82247 7.49805 - 7.19121 6.89339 6.59708 6.28819 5.93646 5.47211 - 4.77081 4.25842 3.55132 2.76552 1.63246 1.25488 - 0.90104 0.85217 0.82133 0.81948 0.81588 0.81740 - 13.91491 12.43567 11.73810 11.10925 10.53767 10.01535 - 9.53968 9.10734 8.71554 8.36102 8.03975 7.74590 - 7.47035 7.20420 6.94066 6.66650 6.35249 5.92895 - 5.26310 4.75518 4.02368 3.16788 1.84538 1.38303 - 0.92988 0.86181 0.81292 0.81005 0.81016 0.81075 - 13.90851 12.42254 11.74171 11.13708 10.59063 10.08850 - 9.62737 9.20429 8.81749 8.46898 8.16289 7.89699 - 7.65699 7.42806 7.19838 6.94892 6.64963 6.24486 - 5.61970 5.14293 4.43954 3.55698 2.05810 1.49861 - 0.94297 0.86630 0.81640 0.81329 0.80755 0.80664 - 13.87591 12.42541 11.76291 11.16492 10.62101 10.12366 - 9.67108 9.26121 8.89275 8.56446 8.27512 8.02108 - 7.79408 7.58398 7.37864 7.15803 6.89069 6.51810 - 5.92184 5.45741 4.76140 3.86437 2.25540 1.61763 - 0.96996 0.87849 0.81543 0.81089 0.80415 0.80386 - 13.86588 12.43513 11.78238 11.19248 10.65794 10.17332 - 9.73652 9.34524 8.99748 8.69098 8.42290 8.18874 - 7.98090 7.79217 7.61772 7.44617 7.24778 6.94367 - 6.39246 5.94466 5.27161 4.37600 2.60587 1.84973 - 1.02593 0.90257 0.81573 0.80900 0.80164 0.80034 - 13.84850 12.43932 11.79768 11.21719 10.69132 10.21532 - 9.78727 9.40511 9.06715 8.77144 8.51556 8.29555 - 8.10451 7.93606 7.78651 7.64589 7.48617 7.22935 - 6.73393 6.31651 5.67164 4.78102 2.91383 2.06324 - 1.08250 0.93116 0.81783 0.80826 0.79928 0.79819 - 13.80029 12.44628 11.82879 11.26641 10.75421 10.28925 - 9.87069 9.49780 9.17020 8.88699 8.64683 8.44737 - 8.28401 8.15178 8.04542 7.95020 7.83966 7.66093 - 7.29657 6.95650 6.37263 5.51413 3.56035 2.52935 - 1.21982 1.00524 0.82688 0.80996 0.79677 0.79529 - 13.75983 12.45622 11.84680 11.29118 10.78519 10.32633 - 9.91400 9.54761 9.22688 8.95130 8.71993 8.53104 - 8.38087 8.26540 8.18067 8.11356 8.04102 7.91734 - 7.63767 7.35706 6.84691 6.04926 4.05502 2.90707 - 1.35420 1.08597 0.83982 0.80974 0.79523 0.79384 - 13.64482 12.46277 11.86219 11.31387 10.81451 10.36211 - 9.95626 9.59662 9.28328 9.01598 8.79427 8.61694 - 8.48091 8.38342 8.32244 8.28821 8.26310 8.21099 - 8.04375 7.84276 7.43347 6.73980 4.80734 3.53895 - 1.59790 1.23146 0.86793 0.81834 0.79672 0.79237 - 13.54534 12.46375 11.86736 11.32270 10.82677 10.37798 - 9.97569 9.61967 9.31013 9.04699 8.83013 8.65894 - 8.53105 8.44446 8.39770 8.38142 8.38088 8.37082 - 8.27971 8.13456 7.79338 7.16653 5.33966 4.06293 - 1.82305 1.35993 0.89529 0.83554 0.79658 0.79163 - 13.47260 12.46464 11.87038 11.32671 10.83155 10.38428 - 9.98430 9.63159 9.32638 9.06803 8.85548 8.68777 - 8.56355 8.48189 8.44229 8.43691 8.45391 8.47358 - 8.42695 8.31321 8.03325 7.50421 5.78413 4.43921 - 2.02162 1.49618 0.92784 0.84229 0.80333 0.79119 - 13.42002 12.46560 11.87372 11.33053 10.83556 10.38940 - 9.99126 9.64060 9.33715 9.08064 8.87077 8.70681 - 8.58668 8.50904 8.47412 8.47568 8.50347 8.53866 - 8.52795 8.45248 8.22247 7.72993 6.08163 4.80964 - 2.22391 1.61152 0.95733 0.86084 0.80012 0.79089 - 13.35607 12.46652 11.87710 11.33537 10.84172 10.39723 - 10.00131 9.65312 9.35226 9.09852 8.89165 8.73108 - 8.61507 8.54272 8.51492 8.52632 8.56873 8.62767 - 8.66055 8.62494 8.46599 8.06981 6.57900 5.35103 - 2.58692 1.83729 1.01762 0.88987 0.80430 0.79051 - 13.31713 12.46694 11.87880 11.33860 10.84638 10.40321 - 10.00835 9.66126 9.36166 9.10942 8.90435 8.74598 - 8.63264 8.56361 8.54019 8.55760 8.60902 8.68288 - 8.74300 8.73265 8.62248 8.29844 6.94258 5.76772 - 2.90584 2.04315 1.07657 0.91982 0.80898 0.79028 - 13.25913 12.46750 11.88094 11.34324 10.85372 10.41232 - 10.01870 9.67267 9.37444 9.12402 8.92136 8.76603 - 8.65648 8.59213 8.57467 8.60028 8.66391 8.75854 - 8.85679 8.88213 8.84416 8.63782 7.54459 6.49905 - 3.56333 2.50012 1.21774 0.99597 0.82203 0.78999 - 13.22622 12.46771 11.88170 11.34506 10.85675 10.41633 - 10.02354 9.67848 9.38151 9.13236 8.93041 8.77535 - 8.66713 8.60620 8.59347 8.62332 8.69015 8.79337 - 8.92164 8.97380 8.95811 8.78441 7.93490 7.06962 - 4.04159 2.85810 1.35358 1.08293 0.83811 0.78983 - 13.18946 12.46810 11.88307 11.34709 10.85928 10.41966 - 10.02767 9.68351 9.38757 9.13954 8.93889 8.78538 - 8.67907 8.62057 8.61107 8.64535 8.71871 8.83269 - 8.98274 9.05654 9.08133 8.97721 8.36862 7.70676 - 4.80754 3.48101 1.59901 1.23440 0.86477 0.78969 - 13.16853 12.46833 11.88430 11.34831 10.86035 10.42077 - 10.02921 9.68547 9.38975 9.14215 8.94269 8.79118 - 8.68634 8.62809 8.61859 8.65517 8.73504 8.85715 - 9.00930 9.08537 9.14346 9.12151 8.62761 7.97392 - 5.39555 4.03623 1.81979 1.35535 0.89561 0.78962 - 13.17901 12.47502 11.88242 11.34308 10.85486 10.41651 - 10.02693 9.68542 9.39166 9.14554 8.94690 8.79493 - 8.68700 8.62307 8.60968 8.65382 8.75707 8.89484 - 9.03531 9.10524 9.17209 9.18248 8.79992 8.22637 - 5.81093 4.44519 2.04463 1.48683 0.92518 0.78957 - 13.14618 12.46855 11.88513 11.34882 10.86043 10.42120 - 10.03039 9.68770 9.39298 9.14621 8.94742 8.79649 - 8.69238 8.63523 8.62741 8.66648 8.75005 8.87775 - 9.04098 9.12837 9.20788 9.22759 8.90922 8.41541 - 6.14721 4.78382 2.25562 1.61051 0.95587 0.78954 - 13.13585 12.46846 11.88524 11.34949 10.86182 10.42282 - 10.03209 9.68937 9.39467 9.14805 8.94955 8.79908 - 8.69553 8.63902 8.63200 8.67218 8.75741 8.88789 - 9.05707 9.15041 9.24049 9.28131 9.06119 8.66499 - 6.64841 5.33082 2.62903 1.87507 1.01581 0.78951 - 13.13289 12.46800 11.88425 11.35002 10.86397 10.42558 - 10.03454 9.69132 9.39653 9.15001 8.95120 8.79988 - 8.69605 8.64054 8.63532 8.67672 8.76160 8.89194 - 9.06701 9.16752 9.26292 9.30348 9.14007 8.86035 - 7.02018 5.72855 2.94787 2.11658 1.07154 0.78948 - 1.92450 1.97990 2.03355 2.08565 2.13596 2.18427 - 2.23052 2.27483 2.31752 2.35866 2.39823 2.43660 - 2.47479 2.51374 2.55352 2.59420 2.63548 2.67577 - 2.71291 2.73064 2.75059 2.76988 2.79464 2.80179 - 2.80709 2.80766 2.80825 2.80836 2.80836 2.80841 - 2.45870 2.51239 2.56439 2.61529 2.66481 2.71263 - 2.75844 2.80192 2.84285 2.88116 2.91706 2.95116 - 2.98506 3.02027 3.05706 3.09574 3.13692 3.18202 - 3.23160 3.25619 3.27653 3.28862 3.30570 3.31206 - 3.31501 3.31512 3.31558 3.31563 3.31579 3.31571 - 2.89367 2.94935 3.00220 3.05306 3.10160 3.14745 - 3.19023 3.22962 3.26538 3.29751 3.32646 3.35314 - 3.37978 3.40845 3.43976 3.47436 3.51319 3.55776 - 3.60831 3.63330 3.65213 3.66085 3.67415 3.67974 - 3.68164 3.68157 3.68194 3.68198 3.68217 3.68207 - 3.56646 3.64292 3.70809 3.76321 3.80812 3.84324 - 3.86976 3.89008 3.90747 3.92294 3.93720 3.95124 - 3.96700 3.98619 4.00891 4.03443 4.06224 4.09360 - 4.12936 4.14770 4.16320 4.17228 4.18171 4.18400 - 4.18558 4.18575 4.18592 4.18593 4.18598 4.18597 - 4.08520 4.18631 4.26046 4.31217 4.34626 4.36865 - 4.38186 4.38882 4.39329 4.39624 4.39794 4.39900 - 4.40079 4.40484 4.41182 4.42253 4.43784 4.45826 - 4.48198 4.49313 4.50328 4.51019 4.51628 4.51769 - 4.51878 4.51892 4.51902 4.51902 4.51904 4.51905 - 4.50484 4.62916 4.71056 4.75706 4.77885 4.78780 - 4.78787 4.78267 4.77648 4.76910 4.75842 4.74432 - 4.73087 4.72186 4.71744 4.71644 4.71816 4.72447 - 4.73549 4.74111 4.74631 4.74991 4.75321 4.75397 - 4.75459 4.75466 4.75472 4.75473 4.75474 4.75475 - 4.85871 5.00021 5.08552 5.12569 5.13547 5.13164 - 5.11935 5.10271 5.08636 5.06921 5.04732 5.02002 - 4.99330 4.97254 4.95745 4.94539 4.93447 4.92759 - 4.92647 4.92676 4.92719 4.92760 4.92805 4.92818 - 4.92830 4.92832 4.92833 4.92833 4.92833 4.92834 - 5.43356 5.59230 5.67651 5.70195 5.68963 5.66287 - 5.62838 5.59085 5.55537 5.51992 5.47878 5.43062 - 5.38305 5.34263 5.30850 5.27652 5.24364 5.21409 - 5.19160 5.18221 5.17381 5.16803 5.16253 5.16129 - 5.16033 5.16020 5.16011 5.16009 5.16008 5.16010 - 5.88958 6.04951 6.12451 6.13361 6.10130 6.05433 - 6.00016 5.94378 5.89049 5.83815 5.78096 5.71732 - 5.65447 5.59848 5.54829 5.49941 5.44873 5.40102 - 5.36089 5.34315 5.32687 5.31527 5.30392 5.30125 - 5.29918 5.29892 5.29872 5.29868 5.29866 5.29868 - 6.72711 6.85920 6.89570 6.86113 6.78326 6.69162 - 6.59419 6.49612 6.40293 6.31348 6.22435 6.13386 - 6.04564 5.96230 5.88272 5.80337 5.72196 5.64310 - 5.57087 5.53666 5.50405 5.47991 5.45651 5.45081 - 5.44633 5.44576 5.44531 5.44524 5.44521 5.44521 - 7.31662 7.40567 7.39655 7.31763 7.19743 7.06549 - 6.92977 6.79527 6.66744 6.54676 6.43260 6.32344 - 6.21909 6.11840 6.02043 5.92264 5.82355 5.72657 - 5.63353 5.58719 5.54183 5.50769 5.47589 5.46799 - 5.46170 5.46090 5.46030 5.46021 5.46016 5.46014 - 8.30858 8.13517 7.95069 7.76941 7.59131 7.41629 - 7.24456 7.07639 6.91140 6.75074 6.59532 6.44493 - 6.30098 6.16330 6.03268 5.90999 5.79532 5.68535 - 5.57822 5.52769 5.48057 5.44120 5.36988 5.34411 - 5.34862 5.35218 5.34949 5.34811 5.35017 5.34885 - 8.83382 8.59016 8.33626 8.08975 7.85042 7.61820 - 7.39324 7.17591 6.96593 6.76468 6.57348 6.39193 - 6.22180 6.06361 5.91820 5.78664 5.66842 5.55673 - 5.44518 5.39028 5.33576 5.28592 5.19428 5.16260 - 5.17437 5.17983 5.17560 5.17355 5.17619 5.17468 - 9.08042 8.88128 8.63226 8.35861 8.06620 7.76304 - 7.45944 7.16873 6.90471 6.67015 6.46383 6.28111 - 6.11712 5.96663 5.82574 5.68749 5.54619 5.40417 - 5.26463 5.19531 5.12337 5.06522 5.01378 5.00108 - 4.99042 4.98916 4.98815 4.98799 4.98793 4.98786 - 9.39162 9.12848 8.81913 8.49160 8.15168 7.80742 - 7.46871 7.14786 6.85821 6.60195 6.37686 6.17739 - 5.99740 5.83173 5.67667 5.52686 5.37765 5.22962 - 5.08453 5.01340 4.94172 4.88485 4.83048 4.81705 - 4.80622 4.80492 4.80383 4.80370 4.80358 4.80357 - 9.79620 9.53170 9.13207 8.67043 8.20144 7.77257 - 7.38842 7.04522 6.73978 6.46631 6.21347 5.97438 - 5.75330 5.55458 5.37486 5.20836 5.04885 4.89049 - 4.73435 4.66215 4.59263 4.53836 4.48017 4.46630 - 4.45534 4.45385 4.45278 4.45265 4.45253 4.45256 - 10.11637 9.77309 9.28966 8.74904 8.21263 7.73133 - 7.30742 6.93426 6.60494 6.31039 6.03441 5.76894 - 5.52226 5.30177 5.10425 4.92227 4.74897 4.57930 - 4.41606 4.34246 4.27260 4.21836 4.15863 4.14460 - 4.13357 4.13204 4.13094 4.13083 4.13069 4.13075 - 10.79851 10.06039 9.36004 8.72206 8.14023 7.60927 - 7.12473 6.68445 6.28653 5.92779 5.60358 5.30828 - 5.03597 4.78362 4.55227 4.33972 4.14363 3.95504 - 3.76815 3.67933 3.60003 3.54549 3.48627 3.47053 - 3.45961 3.45851 3.45729 3.45711 3.45696 3.45699 - 11.01654 10.27499 9.48573 8.71859 8.01559 7.40734 - 6.88276 6.42500 6.01932 5.65211 5.30873 4.98198 - 4.67664 4.39655 4.14080 3.90328 3.68019 3.47601 - 3.28808 3.19512 3.10516 3.03885 2.98047 2.96622 - 2.95494 2.95354 2.95249 2.95232 2.95224 2.95214 - 11.53760 10.42211 9.44329 8.59291 7.84786 7.19348 - 6.61816 6.10782 5.65119 5.24054 4.86799 4.52571 - 4.20472 3.89975 3.61265 3.34688 3.10159 2.87291 - 2.65984 2.56032 2.46527 2.39527 2.33479 2.32048 - 2.30894 2.30760 2.30651 2.30634 2.30625 2.30613 - 11.83776 10.55568 9.46960 8.54210 7.74300 7.05034 - 6.44881 5.91882 5.44288 5.01225 4.62003 4.25918 - 3.92196 3.60346 3.30394 3.02477 2.76565 2.52192 - 2.29378 2.18791 2.09004 2.02004 1.95574 1.94069 - 1.92904 1.92768 1.92650 1.92637 1.92622 1.92620 - 12.06383 10.66783 9.51312 8.53420 7.69890 6.98032 - 6.35949 5.81403 5.32334 4.87784 4.47120 4.09705 - 3.74836 3.42043 3.11267 2.82513 2.55768 2.30531 - 2.06692 1.95538 1.85233 1.77862 1.71119 1.69559 - 1.68357 1.68216 1.68092 1.68079 1.68064 1.68071 - 12.24595 10.76901 9.56871 8.55380 7.69253 6.95559 - 6.32013 5.76205 5.25947 4.80245 4.38487 4.00065 - 3.64314 3.30772 2.99340 2.69960 2.42577 2.16730 - 1.92072 1.80403 1.69522 1.61669 1.54616 1.52992 - 1.51733 1.51584 1.51454 1.51440 1.51425 1.51436 - 12.53011 10.95111 9.69900 8.64063 7.74617 6.98543 - 6.32977 5.75316 5.23330 4.76025 4.32773 3.92959 - 3.55905 3.21147 2.88569 2.58090 2.29563 2.02530 - 1.76371 1.63763 1.51823 1.43052 1.35252 1.33443 - 1.32022 1.31854 1.31710 1.31692 1.31678 1.31678 - 12.74736 11.11236 9.83681 8.75709 7.84540 7.07046 - 6.40177 5.81273 5.28153 4.79824 4.35630 3.94895 - 3.56882 3.21095 2.87443 2.55888 2.26230 1.97859 - 1.70178 1.56656 1.43713 1.34054 1.25339 1.23281 - 1.21655 1.21464 1.21302 1.21281 1.21264 1.21248 - 13.12662 11.43039 10.14268 9.04954 8.12903 7.33968 - 6.65461 6.04878 5.50219 5.00479 4.54913 4.12731 - 3.73040 3.35267 2.99391 2.65463 2.33210 2.01591 - 1.69949 1.54074 1.38345 1.26083 1.14689 1.11920 - 1.09696 1.09434 1.09219 1.09190 1.09167 1.09153 - 13.37342 11.65690 10.38137 9.29856 8.38698 7.59856 - 6.91014 6.29882 5.74618 5.24223 4.77915 4.34855 - 3.94069 3.54935 3.17449 2.81694 2.47309 2.12918 - 1.77408 1.59138 1.40296 1.25002 1.10670 1.07191 - 1.04398 1.04058 1.03767 1.03731 1.03706 1.03741 - 13.67704 11.94441 10.70868 9.66977 8.78981 8.02283 - 7.34700 6.74026 6.18453 5.67158 5.19594 4.75167 - 4.33189 3.93067 3.54384 3.16536 2.78662 2.39355 - 1.97023 1.74226 1.49811 1.28754 1.07500 1.02627 - 0.99242 0.98818 0.98250 0.98158 0.98230 0.98332 - 13.84280 12.11560 10.92599 9.93138 9.08101 8.33595 - 7.67564 7.07900 6.52846 6.01663 5.53894 5.09033 - 4.66485 4.25690 3.86166 3.47183 3.07580 2.65247 - 2.17519 1.90573 1.60640 1.34180 1.06822 1.00471 - 0.96453 0.95968 0.95167 0.95028 0.95207 0.95298 - 13.80152 12.20011 11.11859 10.18568 9.35755 8.61083 - 7.93663 7.32569 6.77063 6.26390 5.79765 5.36276 - 4.94784 4.54361 4.14510 3.74505 3.33056 2.87658 - 2.35188 2.05152 1.71577 1.41582 1.07709 0.98795 - 0.94491 0.94166 0.93111 0.92873 0.93232 0.93191 - 13.85664 12.26577 11.22680 10.32660 9.52316 8.79558 - 8.13619 7.53649 6.98979 6.48915 6.02722 5.59537 - 5.18261 4.77963 4.38089 3.97797 3.55565 3.08398 - 2.52414 2.19584 1.82136 1.48114 1.08892 0.98295 - 0.93148 0.92775 0.91590 0.91322 0.91745 0.91606 - 13.89946 12.33370 11.36999 10.52373 9.76329 9.06966 - 8.43712 7.85850 7.32826 6.84051 6.38893 5.96588 - 5.56141 5.16646 4.77430 4.37412 3.94575 3.44841 - 2.82843 2.45140 2.01079 1.60403 1.13409 0.99835 - 0.90494 0.89999 0.90021 0.89832 0.88987 0.89364 - 13.91929 12.37098 11.46042 10.65275 9.92452 9.25780 - 8.64796 8.08855 7.57473 7.10120 6.66220 6.25057 - 5.85679 5.47183 5.08839 4.69429 4.26634 3.75675 - 3.09953 2.68778 2.19452 1.72710 1.17637 1.01321 - 0.89506 0.88711 0.88625 0.88426 0.87465 0.87851 - 13.98718 12.44401 11.59212 10.83279 10.14832 9.52333 - 8.95358 8.43316 7.95736 7.52085 7.11754 6.73944 - 6.37532 6.01495 5.65143 5.27335 4.85863 4.36019 - 3.68938 3.23223 2.62972 2.01655 1.27263 1.05472 - 0.89597 0.87731 0.86026 0.85845 0.85859 0.85618 - 13.95467 12.43911 11.63853 10.92258 10.27522 9.68374 - 9.14448 8.65230 8.20308 7.79208 7.41369 7.06041 - 6.72132 6.38619 6.04776 5.69351 5.29841 4.80778 - 4.11976 3.63756 2.98836 2.29977 1.39536 1.11639 - 0.89534 0.86866 0.84926 0.84733 0.84674 0.84399 - 13.86107 12.39055 11.66215 11.00690 10.41160 9.86659 - 9.36925 8.91567 8.50269 8.12667 7.78317 7.46601 - 7.16583 6.87335 6.58102 6.27473 5.92442 5.46113 - 4.76162 4.25095 3.54685 2.76508 1.63867 1.26336 - 0.91325 0.86532 0.83515 0.83298 0.82815 0.83098 - 13.83646 12.37805 11.67877 11.04902 10.47765 9.95660 - 9.48318 9.05396 8.66602 8.31600 7.99969 7.71097 - 7.44029 7.17839 6.91844 6.64723 6.33565 5.91439 - 5.25134 4.74543 4.01702 3.16535 1.85036 1.39066 - 0.94146 0.87438 0.82649 0.82352 0.82280 0.82410 - 13.82418 12.37811 11.69663 11.08203 10.52454 10.01720 - 9.55750 9.14239 8.76929 8.43525 8.13652 7.86755 - 7.61949 7.38365 7.15354 6.91589 6.63999 6.25053 - 5.61329 5.12491 4.42231 3.55802 2.06333 1.50382 - 0.95418 0.87747 0.82975 0.82639 0.82213 0.81986 - 13.78056 12.35975 11.70080 11.10498 10.56319 10.06855 - 9.61921 9.21287 8.84779 8.52255 8.23556 7.98326 - 7.75815 7.55057 7.34813 7.13071 6.86690 6.49810 - 5.90630 5.44490 4.75279 3.85953 2.25724 1.62329 - 0.98072 0.89032 0.82857 0.82419 0.81744 0.81699 - 13.76446 12.36456 11.71794 11.13294 10.60267 10.12157 - 9.68777 9.29892 8.95315 8.64828 8.38155 8.14865 - 7.94222 7.75526 7.58307 7.41439 7.21961 6.91987 - 6.37396 5.92941 5.26041 4.36909 2.60617 1.85386 - 1.03582 0.91380 0.82870 0.82213 0.81503 0.81335 - 13.72136 12.35981 11.73503 11.16539 10.64536 10.17151 - 9.74298 9.35922 9.02001 8.72397 8.46900 8.25175 - 8.06619 7.90560 7.76270 7.61996 7.44683 7.18432 - 6.70875 6.30381 5.65767 4.76717 2.92289 2.06308 - 1.09053 0.94197 0.83090 0.82127 0.81285 0.81113 - 13.70183 12.37726 11.76531 11.20711 10.69835 10.23591 - 9.81938 9.44816 9.12207 8.84028 8.60146 8.40328 - 8.24122 8.11032 8.00544 7.91201 7.80390 7.62874 - 7.27002 6.93381 6.35472 5.50153 3.55697 2.53017 - 1.22747 1.01486 0.83946 0.82290 0.80960 0.80813 - 13.68801 12.39757 11.78361 11.22634 10.72107 10.26495 - 9.85650 9.49439 9.17751 8.90488 8.67523 8.48623 - 8.33319 8.21255 8.12448 8.06481 8.01449 7.90787 - 7.61802 7.32657 6.81625 6.02155 4.04352 2.92670 - 1.35854 1.08905 0.85163 0.82558 0.80820 0.80663 - 13.58008 12.40578 11.79918 11.24828 10.74903 10.29898 - 9.89690 9.54163 9.23229 8.96820 8.74847 8.57129 - 8.43253 8.32976 8.26497 8.23725 8.23322 8.19777 - 8.02071 7.80828 7.39660 6.70346 4.78967 3.55880 - 1.60199 1.23290 0.87892 0.83463 0.80813 0.80511 - 13.46168 12.39688 11.80285 11.26078 10.76745 10.32112 - 9.92126 9.56750 9.25990 8.99838 8.78285 8.61271 - 8.48561 8.39959 8.35320 8.33728 8.33736 8.32858 - 8.24054 8.09845 7.76266 7.14285 5.32822 4.05712 - 1.82682 1.36659 0.90652 0.84789 0.80899 0.80434 - 13.38922 12.39710 11.80606 11.26528 10.77282 10.32791 - 9.93018 9.57951 9.27605 9.01918 8.80785 8.64114 - 8.51767 8.43659 8.39737 8.39229 8.40963 8.42996 - 8.38535 8.27416 7.99945 7.47826 5.77078 4.42994 - 2.02466 1.50278 0.93865 0.85392 0.81594 0.80388 - 13.33809 12.39708 11.80880 11.26919 10.77760 10.33385 - 9.93759 9.58849 9.28656 9.03153 8.82292 8.65994 - 8.54054 8.46346 8.42892 8.43064 8.45851 8.49406 - 8.48494 8.41164 8.18624 7.70074 6.06618 4.80037 - 2.22575 1.61694 0.96772 0.87249 0.81268 0.80358 - 13.27642 12.39761 11.81168 11.27392 10.78385 10.34196 - 9.94769 9.60083 9.30139 9.04909 8.84349 8.68388 - 8.56856 8.49670 8.46917 8.48065 8.52298 8.58197 - 8.61571 8.58156 8.42623 8.03644 6.56035 5.33932 - 2.58707 1.84169 1.02724 0.90090 0.81699 0.80319 - 13.23881 12.39845 11.81368 11.27704 10.78820 10.34749 - 9.95447 9.60887 9.31074 9.05991 8.85603 8.69854 - 8.58585 8.51728 8.49408 8.51153 8.56279 8.63656 - 8.69712 8.68773 8.58033 8.26192 6.92129 5.75399 - 2.90466 2.04671 1.08550 0.93030 0.82174 0.80295 - 13.18283 12.39973 11.81631 11.28146 10.79452 10.35565 - 9.96426 9.62017 9.32354 9.07443 8.87282 8.71833 - 8.60940 8.54542 8.52807 8.55360 8.61701 8.71140 - 8.80957 8.83522 8.79867 8.59627 7.51798 6.48118 - 3.55964 2.50170 1.22532 1.00533 0.83475 0.80264 - 13.15116 12.40015 11.81708 11.28318 10.79734 10.35937 - 9.96887 9.62585 9.33058 9.08278 8.88189 8.72763 - 8.61994 8.55929 8.54663 8.57636 8.64292 8.74578 - 8.87371 8.92585 8.91094 8.74035 7.90454 7.04813 - 4.03568 2.85767 1.36019 1.09150 0.85072 0.80249 - 13.11542 12.40025 11.81824 11.28520 10.80006 10.36283 - 9.97308 9.63086 9.33654 9.08987 8.89029 8.73761 - 8.63183 8.57362 8.56411 8.59815 8.67108 8.78453 - 8.93411 9.00777 9.03274 8.93016 8.33241 7.68045 - 4.79839 3.47710 1.60412 1.24195 0.87674 0.80233 - 13.09543 12.40039 11.81947 11.28652 10.80143 10.36429 - 9.97476 9.63278 9.33864 9.09240 8.89404 8.74333 - 8.63904 8.58103 8.57151 8.60783 8.68726 8.80874 - 8.96022 9.03613 9.09434 9.07326 8.58706 7.94299 - 5.38432 4.03032 1.82374 1.36178 0.90698 0.80226 - 13.10602 12.40749 11.81809 11.28159 10.79603 10.36001 - 9.97250 9.63279 9.34059 9.09574 8.89813 8.74693 - 8.63951 8.57588 8.56250 8.60638 8.70909 8.84621 - 8.98611 9.05577 9.12233 9.13319 8.75738 8.19197 - 5.79740 4.43730 2.04762 1.49260 0.93600 0.80222 - 13.07397 12.40071 11.82050 11.28743 10.80201 10.36502 - 9.97610 9.63495 9.34168 9.09624 8.89856 8.74840 - 8.64480 8.58790 8.58011 8.61896 8.70213 8.82916 - 8.99153 9.07859 9.15792 9.17794 8.86444 8.37877 - 6.13182 4.77412 2.25715 1.61628 0.96618 0.80219 - 13.06381 12.40072 11.82062 11.28789 10.80299 10.36641 - 9.97767 9.63663 9.34341 9.09808 8.90063 8.75092 - 8.64788 8.59163 8.58463 8.62460 8.70944 8.83918 - 9.00739 9.10028 9.19008 9.23102 9.01418 8.62492 - 6.62981 5.31827 2.62827 1.87878 1.02510 0.80215 - 13.05927 12.39897 11.81892 11.28813 10.80544 10.37004 - 9.98142 9.63971 9.34540 9.09893 8.90071 8.75092 - 8.64850 8.59343 8.58806 8.62965 8.71531 8.84394 - 9.01472 9.11463 9.21038 9.26245 9.11482 8.77661 - 6.98107 5.75121 2.95449 2.10088 1.08392 0.80212 - 1.86618 1.91943 1.97191 2.02384 2.07493 2.12485 - 2.17322 2.21970 2.26399 2.30593 2.34550 2.38317 - 2.42025 2.45791 2.49613 2.53477 2.57383 2.61401 - 2.65560 2.67631 2.69632 2.71263 2.73740 2.74644 - 2.75124 2.75155 2.75228 2.75234 2.75258 2.75247 - 2.39206 2.44722 2.50063 2.55284 2.60353 2.65236 - 2.69898 2.74305 2.78431 2.82271 2.85848 2.89229 - 2.92594 2.96108 2.99803 3.03714 3.07897 3.12474 - 3.17471 3.19940 3.21992 3.23228 3.24993 3.25651 - 3.25953 3.25964 3.26012 3.26017 3.26036 3.26027 - 2.81442 2.88036 2.94039 2.99526 3.04474 3.08885 - 3.12800 3.16329 3.19625 3.22740 3.25726 3.28655 - 3.31707 3.35032 3.38635 3.42451 3.46431 3.50659 - 3.55165 3.57412 3.59437 3.60799 3.62219 3.62575 - 3.62838 3.62868 3.62897 3.62899 3.62905 3.62904 - 3.48481 3.56515 3.63362 3.69134 3.73818 3.77461 - 3.80201 3.82314 3.84166 3.85868 3.87484 3.89100 - 3.90888 3.92996 3.95428 3.98107 4.00985 4.04214 - 4.07912 4.09819 4.11444 4.12414 4.13434 4.13684 - 4.13856 4.13875 4.13894 4.13895 4.13901 4.13900 - 4.00234 4.10409 4.17931 4.23254 4.26867 4.29371 - 4.30999 4.32012 4.32755 4.33317 4.33744 4.34097 - 4.34511 4.35127 4.36018 4.37273 4.38987 4.41185 - 4.43690 4.44891 4.46003 4.46778 4.47467 4.47631 - 4.47757 4.47773 4.47785 4.47787 4.47788 4.47789 - 4.41936 4.54630 4.62741 4.67235 4.69397 4.70659 - 4.71319 4.71491 4.71324 4.70819 4.69952 4.68823 - 4.67777 4.67135 4.66917 4.67035 4.67437 4.68261 - 4.69514 4.70174 4.70804 4.71256 4.71671 4.71773 - 4.71853 4.71864 4.71872 4.71873 4.71872 4.71874 - 4.77171 4.91749 5.00154 5.03786 5.04583 5.04652 - 5.04342 5.03654 5.02588 5.01077 4.99045 4.96616 - 4.94289 4.92504 4.91240 4.90276 4.89448 4.88985 - 4.89040 4.89173 4.89333 4.89469 4.89604 4.89643 - 4.89675 4.89680 4.89683 4.89682 4.89682 4.89685 - 5.34567 5.51069 5.59308 5.61274 5.59734 5.57617 - 5.55359 5.52864 5.50002 5.46645 5.42655 5.38166 - 5.33796 5.30073 5.26925 5.23993 5.21014 5.18332 - 5.16282 5.15451 5.14727 5.14243 5.13786 5.13686 - 5.13613 5.13603 5.13595 5.13594 5.13592 5.13595 - 5.80247 5.96938 6.04318 6.04713 6.01232 5.97142 - 5.92949 5.88589 5.83966 5.78941 5.73363 5.67336 - 5.61442 5.56164 5.51410 5.46800 5.42064 5.37603 - 5.33816 5.32145 5.30623 5.29551 5.28507 5.28266 - 5.28081 5.28056 5.28038 5.28036 5.28032 5.28035 - 6.64468 6.78280 6.82158 6.78744 6.71144 6.62598 - 6.53768 6.44870 6.36144 6.27514 6.18868 6.10167 - 6.01696 5.93650 5.85942 5.78276 5.70472 5.62937 - 5.55988 5.52652 5.49467 5.47122 5.44870 5.44323 - 5.43894 5.43839 5.43797 5.43790 5.43787 5.43788 - 7.23983 7.33266 7.32966 7.25789 7.14466 7.01845 - 6.88742 6.75709 6.63350 6.51712 6.40703 6.30147 - 6.20019 6.10206 6.00636 5.91104 5.81503 5.72152 - 5.63135 5.58573 5.54093 5.50732 5.47643 5.46873 - 5.46260 5.46184 5.46126 5.46116 5.46111 5.46109 - 8.06435 8.03263 7.94432 7.81620 7.65337 7.46358 - 7.25792 7.05170 6.86098 6.68997 6.53814 6.40278 - 6.28071 6.16687 6.05789 5.94635 5.82688 5.70593 - 5.59098 5.53461 5.47380 5.42322 5.38289 5.37302 - 5.36429 5.36327 5.36250 5.36233 5.36234 5.36222 - 8.60835 8.50232 8.33908 8.13994 7.91105 7.66097 - 7.40141 7.14802 6.91668 6.71125 6.53080 6.37151 - 6.22914 6.09810 5.97444 5.85018 5.71915 5.58628 - 5.45729 5.39302 5.32419 5.26732 5.22085 5.20945 - 5.19948 5.19831 5.19743 5.19724 5.19723 5.19710 - 9.01310 8.83590 8.60420 8.34281 8.05824 7.75933 - 7.45755 7.16775 6.90533 6.67326 6.47018 6.29120 - 6.13101 5.98393 5.84595 5.70989 5.56991 5.42909 - 5.29135 5.22298 5.15154 5.09348 5.04277 5.03030 - 5.01976 5.01851 5.01752 5.01735 5.01730 5.01722 - 9.33152 9.08705 8.79297 8.47678 8.14478 7.80563 - 7.47011 7.15157 6.86450 6.61127 6.38953 6.19368 - 6.01729 5.85493 5.70277 5.55520 5.40743 5.26057 - 5.11692 5.04654 4.97539 4.91879 4.86499 4.85172 - 4.84099 4.83970 4.83862 4.83848 4.83839 4.83837 - 9.74841 9.49671 9.10716 8.65301 8.19059 7.76867 - 7.39158 7.05477 6.75431 6.48460 6.23501 5.99912 - 5.78117 5.58544 5.40852 5.24449 5.08689 4.92972 - 4.77440 4.70285 4.63402 4.58022 4.52225 4.50843 - 4.49752 4.49603 4.49495 4.49483 4.49471 4.49476 - 10.07087 9.74744 9.27085 8.73002 8.19463 7.72160 - 7.31039 6.94931 6.62671 6.33461 6.06026 5.79760 - 5.55422 5.33690 5.14233 4.96295 4.79165 4.62304 - 4.46044 4.38761 4.31856 4.26478 4.20502 4.19096 - 4.17990 4.17837 4.17727 4.17715 4.17702 4.17710 - 10.76461 10.03368 9.34109 8.71031 8.13527 7.61075 - 7.13240 6.69799 6.30564 5.95213 5.63281 5.34201 - 5.07358 4.82431 4.59526 4.38435 4.18937 4.00176 - 3.81611 3.72804 3.64955 3.59557 3.53596 3.51974 - 3.50875 3.50767 3.50642 3.50625 3.50607 3.50613 - 11.06930 10.20356 9.40253 8.68324 8.03558 7.45250 - 6.92767 6.45654 6.03630 5.66062 5.32200 5.01218 - 4.72117 4.44352 4.18281 3.94254 3.72416 3.52234 - 3.33329 3.24376 3.15515 3.08712 3.02838 3.01419 - 3.00248 3.00112 3.00002 2.99983 2.99975 2.99964 - 11.51677 10.41107 9.44089 8.59762 7.85859 7.20935 - 6.63830 6.13146 5.67762 5.26914 4.89837 4.55757 - 4.23793 3.93423 3.64838 3.38391 3.14011 2.91314 - 2.70194 2.60330 2.50880 2.43876 2.37760 2.36301 - 2.35123 2.34987 2.34875 2.34858 2.34848 2.34834 - 11.81113 10.54945 9.47681 8.55777 7.76359 7.07343 - 6.47287 5.94323 5.46784 5.03808 4.64699 4.28745 - 3.95155 3.63426 3.33582 3.05762 2.79944 2.55696 - 2.33062 2.22571 2.12845 2.05849 1.99376 1.97853 - 1.96672 1.96534 1.96415 1.96402 1.96386 1.96384 - 12.03274 10.66392 9.52559 8.55583 7.72464 7.00685 - 6.38490 5.83787 5.34637 4.90097 4.49512 4.12219 - 3.77482 3.44809 3.14134 2.85459 2.58775 2.33632 - 2.09953 1.98892 1.88649 1.81295 1.74543 1.72975 - 1.71767 1.71624 1.71500 1.71486 1.71471 1.71481 - 12.21241 10.76567 9.58288 8.57731 7.71965 6.98267 - 6.34514 5.78461 5.28061 4.82334 4.40634 4.02326 - 3.66703 3.33279 3.01945 2.72634 2.45296 2.19521 - 1.95006 1.83424 1.72608 1.64785 1.57749 1.56128 - 1.54869 1.54721 1.54591 1.54576 1.54562 1.54577 - 12.49798 10.94573 9.70850 8.65844 7.76752 7.00721 - 6.35027 5.77201 5.25120 4.77800 4.34595 3.94868 - 3.57919 3.23261 2.90769 2.60356 2.31873 2.04901 - 1.78862 1.66332 1.54466 1.45749 1.38002 1.36206 - 1.34794 1.34627 1.34484 1.34466 1.34452 1.34454 - 12.72120 11.10284 9.83657 8.76322 7.85557 7.08300 - 6.41563 5.82738 5.29677 4.81401 4.37260 3.96582 - 3.58635 3.22921 2.89345 2.57859 2.28260 1.99962 - 1.72392 1.58945 1.46088 1.36506 1.27860 1.25820 - 1.24207 1.24018 1.23857 1.23837 1.23820 1.23799 - 13.10767 11.41383 10.12670 9.03677 8.12068 7.33646 - 6.65656 6.05521 5.51171 5.01616 4.56147 4.14011 - 3.74358 3.36639 3.00829 2.66974 2.34798 2.03279 - 1.71768 1.55983 1.40371 1.28222 1.16921 1.14174 - 1.11968 1.11709 1.11496 1.11467 1.11444 1.11428 - 13.34861 11.63848 10.36483 9.28506 8.37691 7.59245 - 6.90807 6.30040 5.75060 5.24871 4.78716 4.35770 - 3.95083 3.56043 3.18641 2.82950 2.48620 2.14329 - 1.79001 1.60852 1.42152 1.26983 1.12762 1.09313 - 1.06545 1.06208 1.05919 1.05883 1.05858 1.05910 - 13.62978 11.92626 10.70263 9.66955 8.79097 8.02307 - 7.34531 6.73698 6.18112 5.66942 5.19599 4.75437 - 4.33704 3.93771 3.55216 3.17450 2.79638 2.40445 - 1.98333 1.75682 1.51429 1.30513 1.09411 1.04594 - 1.01272 1.00854 1.00281 1.00186 1.00266 1.00416 - 13.68008 12.08437 10.96099 9.99120 9.13684 8.37043 - 7.68175 7.06061 6.49880 5.98810 5.52002 5.08495 - 4.67109 4.26923 3.87520 3.48318 3.08303 2.65536 - 2.17722 1.91161 1.62234 1.36748 1.08886 1.01843 - 0.98331 0.98030 0.97142 0.96948 0.97219 0.97324 - 13.76301 12.18343 11.10891 10.18019 9.35457 8.60936 - 7.93589 7.32512 6.76979 6.26254 5.79568 5.36035 - 4.94540 4.54181 4.14459 3.74649 3.33456 2.88349 - 2.36184 2.06305 1.72886 1.43015 1.09343 1.00533 - 0.96395 0.96088 0.95007 0.94763 0.95142 0.95153 - 13.81187 12.24601 11.21540 10.32026 9.51993 8.79418 - 8.13552 7.53578 6.98841 6.48671 6.02359 5.59069 - 5.17749 4.77497 4.37757 3.97687 3.55754 3.08920 - 2.53268 2.20605 1.83320 1.49428 1.10419 0.99939 - 0.95002 0.94652 0.93433 0.93156 0.93605 0.93504 - 13.84308 12.30706 11.35372 10.51418 9.75802 9.06690 - 8.43542 7.85665 7.32536 6.83594 6.38241 5.95756 - 5.55206 5.15729 4.76653 4.36894 3.94415 3.45072 - 2.83445 2.45922 2.02050 1.61534 1.14794 1.01346 - 0.92216 0.91764 0.91800 0.91606 0.90758 0.91153 - 13.85348 12.33789 11.43903 10.63937 9.91623 9.25263 - 8.64417 8.08474 7.56981 7.09437 6.65306 6.23923 - 5.84411 5.45924 5.07728 4.68605 4.26211 3.75682 - 3.10350 2.69362 2.20234 1.73678 1.18899 1.02723 - 0.91148 0.90406 0.90343 0.90138 0.89165 0.89555 - 13.90445 12.39879 11.56090 10.81135 10.13332 9.51225 - 8.94423 8.42369 7.94637 7.50732 7.10099 6.72010 - 6.35456 5.99489 5.63422 5.26090 4.85206 4.35850 - 3.69001 3.23374 2.63319 2.02268 1.28259 1.06654 - 0.91172 0.89349 0.87600 0.87419 0.87436 0.87190 - 13.86600 12.38753 11.59987 10.89326 10.25238 9.66501 - 9.12785 8.63610 8.18597 7.77309 7.39232 7.03682 - 6.69671 6.36255 6.02709 5.67763 5.28848 4.80289 - 4.11747 3.63629 2.98925 2.30369 1.40378 1.12684 - 0.91011 0.88399 0.86431 0.86233 0.86178 0.85897 - 13.77039 12.33327 11.61425 10.96616 10.37601 9.83496 - 9.34026 8.88822 8.47588 8.09982 7.75585 7.43820 - 7.13808 6.84673 6.55667 6.25385 5.90803 5.44946 - 4.75423 4.24572 3.54428 2.76587 1.64576 1.27269 - 0.92606 0.87898 0.84965 0.84745 0.84213 0.84514 - 13.74622 12.31866 11.62645 11.00225 10.43517 9.91745 - 9.44658 9.01917 8.63246 8.28320 7.96736 7.67909 - 7.40927 7.14897 6.89146 6.62361 6.31620 5.89941 - 5.24070 4.73709 4.01159 3.16366 1.85594 1.39888 - 0.95347 0.88731 0.84044 0.83748 0.83627 0.83781 - 13.72864 12.30139 11.62822 11.02812 10.48507 9.98694 - 9.53043 9.11262 8.73167 8.38899 8.08792 7.82600 - 7.58997 7.36590 7.14225 6.89962 6.60741 6.20961 - 5.59254 5.12161 4.42576 3.55038 2.06417 1.51180 - 0.96592 0.89114 0.84314 0.84011 0.83418 0.83328 - 13.69280 12.29948 11.64495 11.05277 10.51380 10.02143 - 9.57377 9.16891 8.80544 8.48195 8.19684 7.94649 - 7.72335 7.51783 7.31778 7.10333 6.84313 6.47830 - 5.89106 5.43268 4.74439 3.85490 2.25946 1.62935 - 0.99180 0.90242 0.84182 0.83754 0.83069 0.83021 - 13.67879 12.30396 11.65983 11.07721 10.54901 10.07012 - 9.63846 9.25173 8.90808 8.60531 8.34068 8.10984 - 7.90544 7.72049 7.55036 7.38393 7.19185 6.89577 - 6.35518 5.91416 5.24945 4.36255 2.60681 1.85828 - 1.04596 0.92523 0.84167 0.83518 0.82810 0.82632 - 13.64415 12.29855 11.67159 11.10258 10.58569 10.11636 - 9.69307 9.31402 8.97784 8.68318 8.42844 8.21104 - 8.02617 7.86786 7.72820 7.58787 7.41573 7.15683 - 6.68701 6.28408 5.64560 4.76519 2.92280 2.05692 - 1.10093 0.95748 0.84371 0.83291 0.82380 0.82395 - 13.61452 12.31338 11.70412 11.14868 10.64273 10.18323 - 9.76952 9.40093 9.07704 8.79700 8.55954 8.36245 - 8.20125 8.07118 7.96725 7.87508 7.76896 7.59701 - 7.24356 6.91116 6.33700 5.48930 3.55380 2.53115 - 1.23529 1.02455 0.85187 0.83563 0.82233 0.82074 - 13.57814 12.32413 11.72219 11.17324 10.67308 10.21954 - 9.81188 9.44963 9.13250 8.85996 8.63116 8.44443 - 8.29608 8.18232 8.09929 8.03434 7.96499 7.84673 - 7.57684 7.30394 6.80458 6.01903 4.04370 2.90516 - 1.36784 1.10375 0.86415 0.83525 0.82009 0.81914 - 13.47243 12.33189 11.73814 11.19601 10.70205 10.25466 - 9.85324 9.49758 9.18767 8.92328 8.70394 8.52858 - 8.39412 8.29789 8.23796 8.20486 8.18144 8.13266 - 7.97268 7.77849 7.38035 6.70061 4.78967 3.53082 - 1.60825 1.24708 0.89125 0.84307 0.82131 0.81752 - 13.37891 12.33273 11.74299 11.20438 10.71373 10.26981 - 9.87194 9.52007 9.21445 8.95490 8.74115 8.57227 - 8.44540 8.35836 8.31039 8.29398 8.29557 8.28723 - 8.19679 8.05625 7.73272 7.13996 5.33094 4.02463 - 1.82776 1.38166 0.92013 0.85385 0.82348 0.81670 - 13.31268 12.33466 11.74660 11.20887 10.71906 10.27659 - 9.88082 9.53180 9.22978 8.97415 8.76383 8.59794 - 8.47509 8.39439 8.35538 8.35042 8.36791 8.38859 - 8.34527 8.23606 7.96604 7.45236 5.75771 4.42101 - 2.02775 1.50935 0.94930 0.86534 0.82819 0.81621 - 13.26338 12.33605 11.75034 11.21276 10.72293 10.28148 - 9.88762 9.54068 9.24036 8.98645 8.77870 8.61656 - 8.49781 8.42107 8.38661 8.38835 8.41631 8.45204 - 8.44380 8.37206 8.15054 7.67163 6.05107 4.79141 - 2.22766 1.62238 0.97798 0.88393 0.82484 0.81588 - 13.20368 12.33731 11.75391 11.21757 10.72895 10.28915 - 9.89740 9.55292 9.25516 9.00394 8.79914 8.64032 - 8.52564 8.45410 8.42662 8.43802 8.48029 8.53919 - 8.57320 8.53994 8.38746 8.00339 6.54199 5.32791 - 2.58731 1.84614 1.03677 0.91175 0.82923 0.81547 - 13.16740 12.33786 11.75571 11.22088 10.73359 10.29496 - 9.90427 9.56084 9.26433 9.01462 8.81161 8.65488 - 8.54279 8.47453 8.45142 8.46876 8.51981 8.59333 - 8.65388 8.64501 8.53961 8.22597 6.90025 5.74056 - 2.90361 2.05033 1.09439 0.94063 0.83405 0.81522 - 13.11340 12.33845 11.75784 11.22549 10.74079 10.30396 - 9.91441 9.57199 9.27683 9.02896 8.82834 8.67458 - 8.56617 8.50251 8.48527 8.51066 8.57368 8.66759 - 8.76548 8.79120 8.75536 8.55592 7.49155 6.46352 - 3.55610 2.50343 1.23294 1.01461 0.84700 0.81489 - 13.08230 12.33718 11.75750 11.22740 10.74520 10.30989 - 9.92110 9.57887 9.28366 9.03580 8.83557 8.68296 - 8.57659 8.51606 8.50305 8.53374 8.60302 8.70452 - 8.82187 8.87077 8.86997 8.73383 7.87106 6.92655 - 4.06127 2.90363 1.36537 1.08813 0.85933 0.81472 - 13.04850 12.33739 11.75836 11.22892 10.74751 10.31314 - 9.92532 9.58405 9.28974 9.04279 8.84363 8.69253 - 8.58844 8.53115 8.52178 8.55525 8.62719 8.73981 - 8.88907 8.96258 8.98736 8.88554 8.29672 7.65394 - 4.78934 3.47356 1.60934 1.24936 0.88814 0.81456 - 13.05141 12.34613 11.75919 11.22503 10.74158 10.30737 - 9.92146 9.58314 9.29205 9.04807 8.85101 8.70008 - 8.59259 8.52845 8.51407 8.55626 8.65631 8.78941 - 8.92215 8.98507 9.03859 9.02466 8.55591 7.90804 - 5.36845 4.02777 1.82800 1.36866 0.91724 0.81448 - 13.03928 12.34554 11.75900 11.22510 10.74187 10.30803 - 9.92243 9.58440 9.29365 9.05004 8.85343 8.70298 - 8.59610 8.53274 8.51937 8.56297 8.66511 8.80151 - 8.94073 9.01005 9.07621 9.08715 8.71629 8.15809 - 5.78412 4.42962 2.05044 1.49822 0.94657 0.81443 - 13.00730 12.33887 11.76142 11.23074 10.74754 10.31276 - 9.92594 9.58670 9.29493 9.05065 8.85387 8.70442 - 8.60132 8.54468 8.53689 8.57548 8.65813 8.78448 - 8.94608 9.03267 9.11164 9.13170 8.82157 8.34291 - 6.11679 4.76459 2.25844 1.62177 0.97648 0.81440 - 12.99749 12.33838 11.76113 11.23120 10.74883 10.31448 - 9.92770 9.58835 9.29659 9.05246 8.85598 8.70694 - 8.60437 8.54838 8.54137 8.58108 8.66538 8.79447 - 8.96187 9.05420 9.14358 9.18444 8.96959 8.58584 - 6.61164 5.30595 2.62729 1.88223 1.03460 0.81436 - 12.99275 12.33702 11.76014 11.23223 10.75198 10.31859 - 9.93176 9.59159 9.29862 9.05327 8.85597 8.70689 - 8.60493 8.55012 8.54473 8.58606 8.67125 8.79916 - 8.96901 9.06846 9.16387 9.21572 9.06915 8.73554 - 6.96021 5.73701 2.95207 2.10280 1.09231 0.81433 - 1.81033 1.86340 1.91581 1.96774 2.01890 2.06895 - 2.11754 2.16430 2.20892 2.25124 2.29121 2.32924 - 2.36662 2.40445 2.44265 2.48106 2.51967 2.55926 - 2.60031 2.62084 2.64086 2.65737 2.68241 2.69152 - 2.69640 2.69673 2.69746 2.69753 2.69775 2.69765 - 2.32745 2.38286 2.43668 2.48939 2.54067 2.59018 - 2.63758 2.68251 2.72469 2.76406 2.80079 2.83553 - 2.86997 2.90569 2.94296 2.98208 3.02363 3.06902 - 3.11882 3.14354 3.16415 3.17664 3.19454 3.20122 - 3.20432 3.20443 3.20491 3.20496 3.20514 3.20506 - 2.74509 2.81099 2.87122 2.92651 2.97667 3.02173 - 3.06213 3.09897 3.13383 3.16714 3.19921 3.23046 - 3.26213 3.29539 3.33060 3.36828 3.40886 3.45225 - 3.49757 3.51998 3.54059 3.55477 3.56872 3.57250 - 3.57528 3.57556 3.57582 3.57588 3.57586 3.57591 - 3.40866 3.48901 3.55806 3.61689 3.66531 3.70375 - 3.73347 3.75708 3.77803 3.79736 3.81567 3.83378 - 3.85334 3.87583 3.90125 3.92891 3.95842 3.99152 - 4.02966 4.04942 4.06634 4.07649 4.08701 4.08958 - 4.09136 4.09155 4.09174 4.09175 4.09180 4.09180 - 3.92347 4.02404 4.09997 4.15531 4.19424 4.22203 - 4.24091 4.25362 4.26367 4.27200 4.27897 4.28510 - 4.29158 4.29970 4.31017 4.32404 4.34240 4.36567 - 4.39236 4.40543 4.41758 4.42600 4.43326 4.43497 - 4.43629 4.43646 4.43659 4.43659 4.43660 4.43662 - 4.33866 4.46464 4.54679 4.59419 4.61901 4.63478 - 4.64440 4.64907 4.65035 4.64828 4.64263 4.63431 - 4.62657 4.62245 4.62218 4.62506 4.63074 4.64067 - 4.65518 4.66306 4.67064 4.67601 4.68058 4.68169 - 4.68256 4.68267 4.68276 4.68276 4.68277 4.68278 - 4.69005 4.83523 4.92066 4.95975 4.97122 4.97537 - 4.97562 4.97199 4.96453 4.95260 4.93550 4.91442 - 4.89411 4.87878 4.86830 4.86066 4.85442 4.85180 - 4.85457 4.85732 4.86034 4.86267 4.86451 4.86501 - 4.86543 4.86547 4.86551 4.86550 4.86551 4.86552 - 5.29209 5.40024 5.47643 5.52416 5.54408 5.53871 - 5.51307 5.47554 5.43638 5.39827 5.36160 5.32689 - 5.29403 5.26314 5.23392 5.20524 5.17670 5.15133 - 5.13331 5.12745 5.12192 5.11745 5.11376 5.11298 - 5.11232 5.11223 5.11215 5.11215 5.11216 5.11217 - 5.72092 5.88898 5.96550 5.97316 5.94259 5.90606 - 5.86847 5.82901 5.78658 5.73985 5.68744 5.63046 - 5.57462 5.52470 5.47984 5.43647 5.39202 5.35023 - 5.31506 5.29984 5.28609 5.27641 5.26680 5.26459 - 5.26290 5.26266 5.26249 5.26246 5.26244 5.26247 - 6.56619 6.70745 6.75030 6.72075 6.64972 6.56939 - 6.48620 6.40204 6.31895 6.23624 6.15296 6.06893 - 5.98706 5.90941 5.83517 5.76149 5.68664 5.61442 - 5.54776 5.51576 5.48520 5.46272 5.44133 5.43614 - 5.43205 5.43152 5.43112 5.43105 5.43103 5.43104 - 7.16506 7.26241 7.26455 7.19817 7.09050 6.97001 - 6.84463 6.71950 6.60030 6.48754 6.38051 6.27770 - 6.17906 6.08361 5.99067 5.89826 5.80532 5.71483 - 5.62743 5.58309 5.53953 5.50692 5.47727 5.46988 - 5.46397 5.46325 5.46269 5.46258 5.46255 5.46254 - 7.99705 7.97128 7.88958 7.76818 7.61202 7.42865 - 7.22898 7.02816 6.84206 6.67497 6.52637 6.39375 - 6.27412 6.16266 6.05607 5.94698 5.83009 5.71172 - 5.59925 5.54410 5.48460 5.43515 5.39602 5.38645 - 5.37794 5.37694 5.37620 5.37604 5.37606 5.37595 - 8.54698 8.44826 8.29277 8.10120 7.87954 7.63620 - 7.38282 7.13487 6.90819 6.70666 6.52948 6.37297 - 6.23310 6.10445 5.98311 5.86107 5.73215 5.60137 - 5.47459 5.41151 5.34397 5.28821 5.24275 5.23158 - 5.22179 5.22064 5.21977 5.21959 5.21959 5.21948 - 8.95658 8.78785 8.56478 8.31156 8.03451 7.74245 - 7.44678 7.16233 6.90449 6.67633 6.47654 6.30044 - 6.14286 5.99827 5.86264 5.72871 5.59061 5.45159 - 5.31580 5.24851 5.17826 5.12115 5.07121 5.05888 - 5.04848 5.04724 5.04626 5.04609 5.04607 5.04599 - 9.27913 9.04410 8.75938 8.45172 8.12738 7.79499 - 7.46540 7.15201 6.86941 6.62002 6.40163 6.20877 - 6.03516 5.87539 5.72567 5.58025 5.43427 5.28905 - 5.14715 5.07770 5.00757 4.95175 4.89841 4.88523 - 4.87457 4.87329 4.87221 4.87209 4.87200 4.87196 - 9.70292 9.46161 9.08232 8.63724 8.18257 7.76720 - 7.39561 7.06349 6.76708 6.50098 6.25478 6.02224 - 5.80738 5.61435 5.43980 5.27792 5.12227 4.96668 - 4.81270 4.74195 4.67382 4.62037 4.56240 4.54857 - 4.53765 4.53615 4.53507 4.53495 4.53484 4.53484 - 10.03020 9.71835 9.25268 8.72101 8.19313 7.72621 - 7.32004 6.96326 6.64449 6.35588 6.08489 5.82558 - 5.58528 5.37064 5.17843 5.00125 4.83199 4.66499 - 4.50357 4.43138 4.36278 4.30909 4.24903 4.23488 - 4.22375 4.22220 4.22108 4.22097 4.22083 4.22088 - 10.73389 10.01410 9.33161 8.70938 8.14155 7.62311 - 7.14991 6.71983 6.33108 5.98056 5.66379 5.37525 - 5.10899 4.86189 4.63500 4.42630 4.23357 4.04796 - 3.86367 3.77594 3.69747 3.64320 3.58310 3.56670 - 3.55556 3.55447 3.55320 3.55302 3.55284 3.55288 - 11.04000 10.18900 9.39985 8.68938 8.04821 7.46987 - 6.94859 6.48030 6.06260 5.68935 5.35311 5.04562 - 4.75689 4.48138 4.22264 3.98423 3.76766 3.56753 - 3.37987 3.29078 3.20222 3.13384 3.07461 3.06024 - 3.04837 3.04699 3.04586 3.04568 3.04560 3.04552 - 11.49072 10.40090 9.44250 8.60757 7.87440 7.22922 - 6.66092 6.15613 5.70406 5.29726 4.92810 4.58894 - 4.27092 3.96880 3.68444 3.42130 3.17876 2.95307 - 2.74321 2.64519 2.55103 2.48095 2.41940 2.40466 - 2.39274 2.39136 2.39022 2.39005 2.38995 2.38985 - 11.78520 10.54018 9.47932 8.56831 7.77960 7.09308 - 6.49479 5.96670 5.49263 5.06409 4.67420 4.31590 - 3.98128 3.66528 3.36806 3.09086 2.83346 2.59188 - 2.36680 2.26262 2.16596 2.09623 2.03122 2.01584 - 2.00393 2.00254 2.00133 2.00120 2.00104 2.00102 - 12.00527 10.65414 9.52750 8.56569 7.73974 7.02527 - 6.40530 5.85950 5.36905 4.92464 4.51980 4.14791 - 3.80164 3.47603 3.17034 2.88439 2.61808 2.36733 - 2.13178 2.02196 1.92021 1.84700 1.77928 1.76350 - 1.75134 1.74990 1.74864 1.74851 1.74835 1.74841 - 12.18289 10.75472 9.58365 8.58602 7.73348 6.99960 - 6.36382 5.80435 5.30124 4.84484 4.42876 4.04664 - 3.69142 3.35819 3.04577 2.75333 2.48039 2.22325 - 1.97935 1.86434 1.75688 1.67901 1.60855 1.59227 - 1.57962 1.57812 1.57682 1.57667 1.57652 1.57660 - 12.46344 10.93144 9.70631 8.66437 7.77854 7.02116 - 6.36579 5.78843 5.26841 4.79602 4.36484 3.96844 - 3.59984 3.25410 2.92994 2.62638 2.34197 2.07291 - 1.81383 1.68937 1.57146 1.48475 1.40735 1.38935 - 1.37521 1.37354 1.37210 1.37193 1.37178 1.37178 - 12.68156 11.08508 9.83122 8.76628 7.86384 7.09424 - 6.42846 5.84112 5.31133 4.82942 4.38887 3.98295 - 3.60429 3.24788 2.91275 2.59842 2.30298 2.02081 - 1.74646 1.61285 1.48512 1.38988 1.30365 1.28326 - 1.26716 1.26526 1.26365 1.26345 1.26329 1.26316 - 13.05582 11.38735 10.11408 9.03340 8.12279 7.34173 - 6.66354 6.06327 5.52085 5.02643 4.57290 4.15264 - 3.75699 3.38044 3.02284 2.68490 2.36399 2.04994 - 1.73622 1.57914 1.42383 1.30304 1.19079 1.16352 - 1.14162 1.13904 1.13693 1.13664 1.13642 1.13631 - 13.28580 11.60462 10.34614 9.27634 8.37388 7.59263 - 6.90998 6.30348 5.75504 5.25474 4.79487 4.36699 - 3.96134 3.57170 3.19821 2.84198 2.49972 2.15809 - 1.80612 1.62523 1.43882 1.28774 1.14683 1.11275 - 1.08538 1.08204 1.07919 1.07883 1.07859 1.07885 - 13.55295 11.88193 10.67501 9.65234 8.77987 8.01547 - 7.33964 6.73273 6.17858 5.66896 5.19781 4.75846 - 4.34310 3.94528 3.56091 3.18420 2.80699 2.41603 - 1.99599 1.77002 1.52800 1.31941 1.10974 1.06230 - 1.02974 1.02559 1.01980 1.01887 1.01968 1.02033 - 13.60784 12.03629 10.92419 9.96271 9.11487 8.35385 - 7.66962 7.05219 6.49346 5.98533 5.51941 5.08620 - 4.67397 4.27359 3.88093 3.49017 3.09122 2.66471 - 2.18766 1.92257 1.63377 1.37942 1.10213 1.03249 - 0.99836 0.99540 0.98636 0.98441 0.98717 0.98708 - 13.68927 12.13361 11.06915 10.14787 9.32826 8.58824 - 7.91922 7.31230 6.76032 6.25600 5.79172 5.35863 - 4.94570 4.54388 4.14825 3.75157 3.34092 2.89103 - 2.37047 2.07223 1.73862 1.44045 1.10511 1.01786 - 0.97779 0.97481 0.96373 0.96126 0.96515 0.96413 - 13.73836 12.19599 11.17415 10.28547 9.49061 8.76967 - 8.11530 7.51941 6.97552 6.47696 6.01668 5.58637 - 5.17546 4.77495 4.37936 3.98023 3.56229 3.09520 - 2.53982 2.21378 1.84161 1.50333 1.11474 1.01086 - 0.96308 0.95971 0.94718 0.94435 0.94898 0.94698 - 13.77135 12.25784 11.31091 10.47647 9.72463 9.03762 - 8.41000 7.83492 7.30715 6.82109 6.37073 5.94885 - 5.54605 5.15368 4.76503 4.36928 3.94609 3.45406 - 2.83907 2.46458 2.02684 1.62272 1.15718 1.02369 - 0.93397 0.92973 0.93014 0.92814 0.91952 0.92289 - 13.78327 12.28962 11.39562 10.59987 9.88029 9.22019 - 8.61517 8.05919 7.54768 7.07562 6.63761 6.22697 - 5.83479 5.45255 5.07297 4.68383 4.26173 3.75802 - 3.10614 2.69710 2.20703 1.74284 1.19730 1.03666 - 0.92276 0.91570 0.91517 0.91302 0.90310 0.90674 - 13.83439 12.35063 11.51594 10.76912 10.09362 9.47517 - 8.90986 8.39218 7.91779 7.48180 7.07858 6.70087 - 6.33848 5.98192 5.62426 5.25382 4.84759 4.35602 - 3.68890 3.23357 2.63484 2.02650 1.28906 1.07443 - 0.92302 0.90508 0.88710 0.88530 0.88538 0.88301 - 13.79416 12.33797 11.55318 10.84896 10.21023 9.62519 - 9.09045 8.60124 8.15376 7.74363 7.36574 7.01322 - 6.67616 6.34508 6.01274 5.66639 5.28020 4.79712 - 4.11366 3.63376 2.98891 2.30594 1.40934 1.13402 - 0.92116 0.89548 0.87541 0.87340 0.87282 0.87011 - 13.69307 12.27977 11.56399 10.91843 10.33074 9.79201 - 9.29962 8.84991 8.43991 8.06620 7.72464 7.40949 - 7.11196 6.82331 6.53612 6.23634 5.89373 5.43836 - 4.74633 4.23966 3.54069 2.76540 1.65085 1.27974 - 0.93619 0.88986 0.86121 0.85894 0.85314 0.85638 - 13.66405 12.26173 11.57324 10.95228 10.38796 9.87282 - 9.40432 8.97914 8.59452 8.24731 7.93347 7.64726 - 7.37961 7.12172 6.86690 6.60205 6.29799 5.88477 - 5.22981 4.72838 4.00571 3.16129 1.86009 1.40536 - 0.96337 0.89803 0.85204 0.84907 0.84738 0.84915 - 13.65008 12.25890 11.58692 10.98009 10.42917 9.92734 - 9.47239 9.06134 8.69174 8.36074 8.06480 7.79865 - 7.55382 7.32203 7.09694 6.86545 6.59692 6.21568 - 5.58742 5.10435 4.40854 3.55176 2.06927 1.51544 - 0.97583 0.90105 0.85471 0.85123 0.84708 0.84470 - 13.60580 12.23882 11.58879 11.00034 10.46446 9.97481 - 9.52956 9.12681 8.76529 8.44359 8.16010 7.91127 - 7.68970 7.48598 7.28812 7.07639 6.81952 6.45857 - 5.87605 5.42068 4.73613 3.85019 2.26092 1.63431 - 1.00139 0.91294 0.85334 0.84913 0.84219 0.84169 - 13.59075 12.24195 11.60240 11.02353 10.49868 10.02267 - 9.59348 9.20893 8.86711 8.56594 8.30268 8.07312 - 7.86999 7.68649 7.51804 7.35367 7.16430 6.87198 - 6.33678 5.89926 5.23872 4.35601 2.60700 1.86197 - 1.05494 0.93540 0.85324 0.84679 0.83971 0.83788 - 13.55834 12.23757 11.61440 11.04880 10.53484 10.06828 - 9.64743 9.27053 8.93621 8.64314 8.38974 8.17349 - 7.98968 7.83246 7.69402 7.55537 7.38576 7.13052 - 6.66601 6.26662 5.63256 4.75669 2.92174 2.05989 - 1.10937 0.96720 0.85526 0.84471 0.83535 0.83554 - 13.53386 12.25557 11.64896 11.09596 10.59221 10.13496 - 9.72326 9.35654 9.03434 8.75582 8.51970 8.32374 - 8.16349 8.03418 7.93094 7.83970 7.73509 7.56586 - 7.21730 6.88862 6.31943 5.47728 3.55063 2.53193 - 1.24247 1.03350 0.86338 0.84740 0.83403 0.83239 - 13.52132 12.27665 11.66910 11.11753 10.61737 10.16574 - 9.76133 9.40286 9.08916 8.81932 8.59205 8.40506 - 8.25372 8.13456 8.04784 7.98962 7.94139 7.83890 - 7.55774 7.27367 6.77414 5.99176 4.03269 2.92525 - 1.37164 1.10611 0.87501 0.85006 0.83244 0.83081 - 13.39842 12.27575 11.68410 11.14393 10.65183 10.20621 - 9.80642 9.45231 9.14386 8.88082 8.66268 8.48838 - 8.35475 8.25906 8.19947 8.16659 8.14351 8.09569 - 7.93843 7.74713 7.35410 6.68115 4.78111 3.52705 - 1.61326 1.25449 0.90221 0.85471 0.83292 0.82921 - 13.30588 12.27511 11.68784 11.15156 10.66305 10.22102 - 9.82492 9.47469 9.17050 8.91225 8.69955 8.53161 - 8.40545 8.31889 8.27123 8.25498 8.25672 8.24881 - 8.16004 8.02169 7.70277 7.11690 5.31987 4.01860 - 1.83165 1.38837 0.93074 0.86523 0.83513 0.82841 - 13.24004 12.27586 11.69074 11.15542 10.66785 10.22746 - 9.83363 9.48634 9.18580 8.93141 8.72206 8.55696 - 8.43470 8.35445 8.31573 8.31096 8.32860 8.34947 - 8.30695 8.19931 7.93331 7.42663 5.74479 4.41243 - 2.03081 1.51571 0.95954 0.87631 0.83994 0.82794 - 13.19178 12.27607 11.69327 11.15880 10.67179 10.23260 - 9.84056 9.49516 9.19626 8.94360 8.73683 8.57537 - 8.45712 8.38082 8.34671 8.34863 8.37658 8.41230 - 8.40463 8.33407 8.11577 7.64284 6.03617 4.78264 - 2.22955 1.62767 0.98789 0.89495 0.83650 0.82762 - 13.13381 12.27674 11.69623 11.16329 10.67779 10.24036 - 9.85037 9.50728 9.21086 8.96088 8.75708 8.59893 - 8.48473 8.41358 8.38637 8.39787 8.44004 8.49877 - 8.53293 8.50033 8.35009 7.97095 6.52381 5.31671 - 2.58756 1.85046 1.04601 0.92225 0.84093 0.82723 - 13.09869 12.27760 11.69833 11.16659 10.68241 10.24608 - 9.85716 9.51518 9.21999 8.97148 8.76948 8.61345 - 8.50185 8.43393 8.41096 8.42831 8.47921 8.55251 - 8.61302 8.60453 8.50063 8.19098 6.87933 5.72727 - 2.90253 2.05383 1.10304 0.95065 0.84577 0.82700 - 13.04646 12.27881 11.70105 11.17159 10.68949 10.25480 - 9.86708 9.52619 9.23238 8.98568 8.78604 8.63305 - 8.52516 8.46178 8.44457 8.46982 8.53259 8.62621 - 8.72386 8.74962 8.71430 8.51724 7.46543 6.44601 - 3.55257 2.50510 1.24037 1.02363 0.85870 0.82668 - 13.01676 12.27914 11.70191 11.17338 10.69238 10.25863 - 9.87175 9.53185 9.23931 8.99388 8.79492 8.64216 - 8.53550 8.47542 8.46286 8.49223 8.55809 8.66011 - 8.78708 8.83877 8.82430 8.65783 7.84493 7.00494 - 4.02430 2.85747 1.37343 1.10820 0.87453 0.82651 - 12.98323 12.27926 11.70297 11.17519 10.69489 10.26186 - 9.87581 9.53679 9.24524 9.00088 8.80316 8.65190 - 8.54709 8.48942 8.47998 8.51363 8.58570 8.69807 - 8.84657 8.91973 8.94438 8.84332 8.26208 7.62785 - 4.78048 3.47009 1.61443 1.25664 0.89939 0.82633 - 12.98671 12.28671 11.70269 11.17110 10.69004 10.25794 - 9.87392 9.53722 9.24753 9.00469 8.80857 8.65829 - 8.55127 8.48741 8.47304 8.51499 8.61456 8.74710 - 8.87936 8.94202 8.99523 8.98152 8.51823 7.87748 - 5.35734 4.02228 1.83199 1.37496 0.92798 0.82624 - 12.97542 12.28641 11.70261 11.17126 10.69044 10.25861 - 9.87484 9.53844 9.24907 9.00663 8.81094 8.66121 - 8.55481 8.49170 8.47835 8.52169 8.62331 8.75907 - 8.89774 8.96676 9.03260 9.04358 8.67662 8.12484 - 5.77082 4.42209 2.05331 1.50387 0.95687 0.82620 - 12.94409 12.28015 11.70532 11.17701 10.69590 10.26324 - 9.87833 9.54076 9.25040 9.00725 8.81139 8.66268 - 8.56008 8.50365 8.49579 8.53413 8.61637 8.74211 - 8.90292 8.98914 9.06789 9.08798 8.78037 8.30781 - 6.10176 4.75528 2.25994 1.62721 0.98635 0.82617 - 12.93481 12.28006 11.70544 11.17766 10.69729 10.26487 - 9.88000 9.54239 9.25204 9.00904 8.81347 8.66519 - 8.56312 8.50732 8.50024 8.53966 8.62354 8.75200 - 8.91856 9.01048 9.09953 9.14029 8.92706 8.54819 - 6.59355 5.29376 2.62648 1.88566 1.04372 0.82613 - 12.93047 12.27841 11.70404 11.17859 10.70053 10.26918 - 9.88418 9.54561 9.25402 9.00981 8.81343 8.66502 - 8.56350 8.50889 8.50349 8.54459 8.62934 8.75661 - 8.92558 9.02456 9.11969 9.17149 9.02590 8.69619 - 6.93958 5.72290 2.94969 2.10473 1.10083 0.82611 - 1.75615 1.80917 1.86161 1.91363 1.96496 2.01524 - 2.06411 2.11120 2.15619 2.19889 2.23922 2.27758 - 2.31517 2.35306 2.39113 2.42917 2.46722 2.50625 - 2.54702 2.56755 2.58762 2.60423 2.62942 2.63859 - 2.64353 2.64387 2.64461 2.64468 2.64489 2.64480 - 2.26346 2.32228 2.37834 2.43206 2.48320 2.53161 - 2.57729 2.62059 2.66204 2.70181 2.74000 2.77703 - 2.81405 2.85218 2.89163 2.93275 2.97572 3.01996 - 3.06420 3.08579 3.10706 3.12377 3.14201 3.14703 - 3.15076 3.15115 3.15154 3.15161 3.15161 3.15165 - 2.67720 2.74311 2.80387 2.86014 2.91165 2.95833 - 3.00045 3.03884 3.07475 3.10861 3.14088 3.17233 - 3.20482 3.23993 3.27757 3.31688 3.35722 3.39964 - 3.44477 3.46733 3.48792 3.50210 3.51712 3.52088 - 3.52368 3.52401 3.52430 3.52432 3.52437 3.52437 - 3.33473 3.41525 3.48499 3.54500 3.59506 3.63549 - 3.66747 3.69338 3.71648 3.73774 3.75781 3.77752 - 3.79869 3.82285 3.84996 3.87906 3.90958 3.94323 - 3.98150 4.00130 4.01867 4.02958 4.04074 4.04348 - 4.04541 4.04563 4.04584 4.04586 4.04591 4.04591 - 3.84651 3.94658 4.02335 4.08055 4.12200 4.15254 - 4.17424 4.18969 4.20228 4.21295 4.22214 4.23044 - 4.23905 4.24926 4.26176 4.27751 4.29746 4.32165 - 4.34882 4.36243 4.37535 4.38453 4.39260 4.39454 - 4.39607 4.39627 4.39641 4.39643 4.39644 4.39645 - 4.26009 4.38535 4.46856 4.51834 4.54620 4.56508 - 4.57778 4.58551 4.58989 4.59082 4.58789 4.58190 - 4.57637 4.57454 4.57660 4.58174 4.58938 4.60065 - 4.61612 4.62476 4.63330 4.63955 4.64504 4.64642 - 4.64753 4.64766 4.64777 4.64780 4.64781 4.64781 - 4.61070 4.75512 4.84186 4.88372 4.89865 4.90620 - 4.90976 4.90944 4.90543 4.89692 4.88286 4.86426 - 4.84625 4.83338 4.82545 4.82031 4.81629 4.81538 - 4.81956 4.82324 4.82735 4.83063 4.83346 4.83427 - 4.83492 4.83500 4.83507 4.83507 4.83507 4.83510 - 5.21176 5.32101 5.39917 5.44955 5.47274 5.47112 - 5.44952 5.41605 5.38074 5.34616 5.31274 5.28099 - 5.25089 5.22264 5.19597 5.16985 5.14394 5.12109 - 5.10523 5.10039 5.09604 5.09268 5.09007 5.08958 - 5.08918 5.08912 5.08909 5.08910 5.08911 5.08911 - 5.64192 5.81028 5.88914 5.90056 5.87442 5.84219 - 5.80872 5.77315 5.73439 5.69112 5.64201 5.58820 - 5.53538 5.48836 5.44630 5.40565 5.36393 5.32489 - 5.29244 5.27846 5.26595 5.25730 5.24884 5.24695 - 5.24548 5.24529 5.24515 5.24513 5.24512 5.24513 - 6.49038 6.63352 6.67992 6.65497 6.58903 6.51372 - 6.43532 6.35543 6.27592 6.19633 6.11626 6.03575 - 5.95729 5.88264 5.81103 5.73990 5.66783 5.59893 - 5.53577 5.50505 5.47566 5.45415 5.43394 5.42902 - 5.42514 5.42464 5.42428 5.42422 5.42419 5.42420 - 7.09318 7.19343 7.20012 7.13913 7.03716 6.92209 - 6.80174 6.68118 6.56606 6.45696 6.35330 6.25367 - 6.15793 6.06514 5.97464 5.88459 5.79420 5.70707 - 5.62341 5.58029 5.53777 5.50601 5.47754 5.47039 - 5.46470 5.46400 5.46346 5.46337 5.46333 5.46331 - 7.93212 7.91152 7.83569 7.72041 7.57049 7.39327 - 7.19951 7.00417 6.82300 6.66018 6.51523 6.38562 - 6.26831 6.15855 6.05333 5.94592 5.83154 5.71617 - 5.60672 5.55293 5.49439 5.44547 5.40743 5.39814 - 5.38981 5.38884 5.38812 5.38795 5.38799 5.38784 - 8.48821 8.39565 8.24699 8.06232 7.84751 7.61083 - 7.36371 7.12151 6.89996 6.70288 6.52944 6.37593 - 6.23825 6.11100 5.99063 5.86989 5.74319 5.61508 - 5.49081 5.42882 5.36209 5.30684 5.26237 5.25145 - 5.24184 5.24072 5.23986 5.23967 5.23970 5.23955 - 8.90277 8.74126 8.52584 8.28005 8.01019 7.72486 - 7.43545 7.15663 6.90380 6.67998 6.48386 6.31079 - 6.15552 6.01253 5.87809 5.74551 5.60935 5.47254 - 5.33882 5.27243 5.20292 5.14633 5.09725 5.08517 - 5.07494 5.07373 5.07277 5.07260 5.07258 5.07248 - 9.22922 9.00255 8.72624 8.42647 8.10939 7.78364 - 7.45999 7.15190 6.87397 6.62867 6.41381 6.22400 - 6.05296 5.89530 5.74734 5.60357 5.45927 5.31577 - 5.17558 5.10696 5.03753 4.98221 4.92965 4.91668 - 4.90620 4.90494 4.90388 4.90375 4.90367 4.90364 - 9.65939 9.42788 9.05803 8.62128 8.17396 7.76517 - 7.39927 7.07176 6.77870 6.51523 6.27203 6.04325 - 5.83213 5.64218 5.47008 5.31010 5.15591 5.00154 - 4.84881 4.77871 4.71125 4.65835 4.60095 4.58729 - 4.57650 4.57503 4.57396 4.57383 4.57371 4.57378 - 9.99103 9.69091 9.23524 8.71166 8.19073 7.73036 - 7.32999 6.97748 6.66087 6.37343 6.10491 5.85008 - 5.61451 5.40343 5.21374 5.03843 4.87069 4.70477 - 4.54425 4.47267 4.40473 4.35154 4.29187 4.27784 - 4.26680 4.26526 4.26416 4.26404 4.26392 4.26400 - 10.70487 9.99572 9.32279 8.70865 8.14765 7.63501 - 7.16674 6.74079 6.35547 6.00781 5.69350 5.40717 - 5.14306 4.89815 4.67345 4.46699 4.27645 4.09257 - 3.90911 3.82152 3.74331 3.68941 3.62942 3.61291 - 3.60176 3.60069 3.59941 3.59922 3.59905 3.59910 - 10.92496 10.24045 9.47884 8.72217 8.02762 7.43628 - 6.93369 6.49640 6.10363 5.74327 5.40475 5.08334 - 4.78376 4.50963 4.25985 4.02805 3.81020 3.61058 - 3.42663 3.33543 3.24641 3.17982 3.11996 3.10515 - 3.09335 3.09189 3.09078 3.09061 3.09053 3.09039 - 11.46863 10.39254 9.44436 8.61711 7.88972 7.24885 - 6.68380 6.18157 5.73169 5.32677 4.95929 4.62160 - 4.30476 4.00352 3.71994 3.45776 3.21657 2.99231 - 2.78360 2.68600 2.59205 2.52187 2.45992 2.44502 - 2.43296 2.43157 2.43042 2.43025 2.43014 2.42998 - 11.76382 10.53359 9.48287 8.57909 7.79542 7.11240 - 6.51648 5.99010 5.51750 5.09030 4.70168 4.34455 - 4.01101 3.69596 3.39963 3.12331 2.86691 2.62643 - 2.40252 2.29886 2.20246 2.13267 2.06742 2.05196 - 2.03996 2.03855 2.03734 2.03720 2.03705 2.03702 - 11.98354 10.64770 9.53101 8.57608 7.75474 7.04334 - 6.42532 5.88084 5.39151 4.94816 4.54435 4.17345 - 3.82811 3.50337 3.19849 2.91332 2.64783 2.39804 - 2.16367 2.05442 1.95296 1.87975 1.81206 1.79628 - 1.78409 1.78266 1.78140 1.78127 1.78111 1.78122 - 12.16039 10.74776 9.58620 8.59521 7.74710 7.01611 - 6.38213 5.82385 5.32176 4.86631 4.45114 4.06987 - 3.71544 3.38290 3.07114 2.77939 2.50720 2.25098 - 2.00825 1.89382 1.78669 1.70889 1.63871 1.62251 - 1.60991 1.60841 1.60711 1.60697 1.60682 1.60699 - 12.43898 10.92241 9.70609 8.67051 7.78901 7.03447 - 6.38097 5.80491 5.28593 4.81446 4.38407 3.98837 - 3.62034 3.27507 2.95137 2.64838 2.36474 2.09661 - 1.83863 1.71474 1.59726 1.51083 1.43405 1.41625 - 1.40224 1.40058 1.39916 1.39899 1.39884 1.39887 - 12.65474 11.07353 9.82806 8.76935 7.87129 7.10465 - 6.44092 5.85507 5.32646 4.84551 4.40575 4.00046 - 3.62230 3.26629 2.93159 2.61785 2.32323 2.04201 - 1.76866 1.63558 1.50840 1.41370 1.32829 1.30813 - 1.29222 1.29035 1.28876 1.28856 1.28839 1.28816 - 13.02221 11.36997 10.10486 9.03036 8.12405 7.34614 - 6.67026 6.07176 5.53075 5.03751 4.58491 4.16544 - 3.77046 3.39452 3.03758 2.70041 2.38051 2.06750 - 1.75470 1.59813 1.44353 1.32355 1.21230 1.18530 - 1.16362 1.16107 1.15899 1.15870 1.15848 1.15831 - 13.24590 11.58232 10.33232 9.26863 8.37035 7.59225 - 6.91196 6.30737 5.76051 5.26159 4.80290 4.37609 - 3.97138 3.58261 3.21002 2.85483 2.51382 2.17343 - 1.82252 1.64215 1.45647 1.30620 1.16633 1.13258 - 1.10546 1.10215 1.09931 1.09896 1.09872 1.09930 - 13.50584 11.85179 10.65201 9.63509 8.76709 8.00668 - 7.33429 6.73029 6.17846 5.67065 5.20092 4.76272 - 4.34838 3.95156 3.56824 3.19283 2.81717 2.42792 - 2.00960 1.78445 1.54321 1.33532 1.12692 1.08013 - 1.04817 1.04408 1.03824 1.03728 1.03812 1.03983 - 13.55015 11.99881 10.89512 9.93971 9.09653 8.33945 - 7.65855 7.04399 6.48776 5.98180 5.51780 5.08631 - 4.67565 4.27675 3.88549 3.49613 3.09870 2.67393 - 2.19893 1.93495 1.64723 1.39381 1.11806 1.04924 - 1.01622 1.01338 1.00421 1.00220 1.00503 1.00634 - 13.62507 12.09036 11.03393 10.11844 9.30358 8.56772 - 7.90237 7.29876 6.74975 6.24812 5.78627 5.35539 - 4.94444 4.54438 4.15036 3.75522 3.34616 2.89813 - 2.37989 2.08293 1.75066 1.45359 1.12006 1.03378 - 0.99526 0.99246 0.98116 0.97861 0.98262 0.98295 - 13.66915 12.14784 11.13344 10.25031 9.46015 8.74351 - 8.09310 7.50089 6.96042 6.46507 6.00775 5.58014 - 5.17164 4.77323 4.37946 3.98199 3.56571 3.10055 - 2.54763 2.22303 1.85240 1.51542 1.12886 1.02606 - 0.98021 0.97708 0.96426 0.96133 0.96612 0.96527 - 13.69520 12.20265 11.26185 10.43225 9.68493 9.00230 - 8.37896 7.80813 7.28450 6.80247 6.35596 5.93767 - 5.53804 5.14831 4.76188 4.36799 3.94650 3.45643 - 2.84406 2.47125 2.03548 1.63316 1.17019 1.03790 - 0.95016 0.94634 0.94686 0.94475 0.93600 0.94018 - 13.70250 12.22974 11.34084 10.54945 9.83411 9.17836 - 8.57779 8.02635 7.51941 7.05191 6.61835 6.21188 - 5.82343 5.44429 5.06721 4.68013 4.25979 3.75803 - 3.10881 2.70156 2.21376 1.75179 1.20934 1.05004 - 0.93837 0.93180 0.93145 0.92920 0.91906 0.92320 - 13.74955 12.28594 11.45460 10.71116 10.03922 9.42484 - 8.86394 8.35103 7.88163 7.45077 7.05269 6.67990 - 6.32184 5.96877 5.61381 5.24537 4.84073 4.35105 - 3.68701 3.23387 2.63789 2.03232 1.29877 1.08595 - 0.93814 0.92055 0.90218 0.90040 0.90036 0.89814 - 13.70776 12.27226 11.49048 10.78932 10.15393 9.57265 - 9.04202 8.55726 8.11446 7.70919 7.33619 6.98842 - 6.65564 6.32811 5.99861 5.65446 5.27002 4.78875 - 4.10811 3.63049 2.98904 2.30977 1.41773 1.14426 - 0.93539 0.91020 0.88983 0.88780 0.88716 0.88449 - 13.60665 12.21558 11.50300 10.86054 10.27597 9.74054 - 9.25163 8.80555 8.39929 8.02942 7.69175 7.38036 - 7.08637 6.80087 6.51644 6.21906 5.87863 5.42549 - 4.73638 4.23195 3.53649 2.76560 1.65796 1.28902 - 0.94860 0.90302 0.87507 0.87274 0.86645 0.86990 - 13.57909 12.20017 11.51528 10.89743 10.33617 9.82397 - 9.35841 8.93618 8.55451 8.21019 7.89925 7.61588 - 7.35100 7.09572 6.84340 6.58102 6.27945 5.86894 - 5.21735 4.71832 3.99919 3.15929 1.86576 1.41356 - 0.97500 0.91047 0.86535 0.86236 0.86018 0.86219 - 13.56723 12.19988 11.53156 10.92798 10.37987 9.88079 - 9.42840 9.01979 8.65250 8.32376 8.02997 7.76594 - 7.52321 7.29353 7.07064 6.84151 6.57561 6.19750 - 5.57337 5.09318 4.40138 3.54904 2.07293 1.52186 - 0.98719 0.91331 0.86751 0.86395 0.85987 0.85743 - 13.51770 12.18153 11.53776 10.95221 10.41771 9.92919 - 9.48549 9.08514 8.72721 8.40954 8.12914 7.88163 - 7.65958 7.45452 7.25691 7.04651 6.79134 6.43645 - 5.86463 5.41260 4.72850 3.84657 2.25838 1.64169 - 1.01432 0.92348 0.86552 0.86218 0.85436 0.85420 - 13.48699 12.17799 11.55248 10.98244 10.46204 9.98727 - 9.55715 9.17070 8.82735 8.52551 8.26283 8.03572 - 7.83788 7.66209 7.50012 7.33318 7.12959 6.83073 - 6.31465 5.88973 5.22928 4.34651 2.61581 1.86359 - 1.06358 0.94685 0.86606 0.85861 0.85238 0.85012 - 13.47657 12.18184 11.56393 11.00212 10.49097 10.02627 - 9.60668 9.23065 8.89704 8.60465 8.35196 8.13657 - 7.95396 7.79839 7.66190 7.52497 7.35682 7.10458 - 6.64626 6.25087 5.62077 4.74845 2.92100 2.06349 - 1.11855 0.97760 0.86732 0.85698 0.84740 0.84762 - 13.44928 12.20408 11.60200 11.04781 10.54165 10.08447 - 9.67518 9.31216 8.99380 8.71844 8.48392 8.28785 - 8.12726 7.99840 7.89597 7.80480 7.69987 7.53555 - 7.19596 6.86809 6.29944 5.46361 3.55480 2.52791 - 1.24849 1.04527 0.87555 0.85919 0.84501 0.84425 - 13.44270 12.21890 11.61419 11.06520 10.56740 10.11805 - 9.71564 9.35902 9.04701 8.77866 8.55270 8.36685 - 8.21646 8.09807 8.01196 7.95429 7.90681 7.80591 - 7.52844 7.24774 6.75338 5.97712 4.02755 2.92481 - 1.37837 1.11470 0.88646 0.86198 0.84418 0.84257 - 13.34490 12.22694 11.62946 11.08671 10.59476 10.15137 - 9.75521 9.40526 9.10059 8.84052 8.62415 8.44977 - 8.31325 8.21219 8.14867 8.12191 8.11906 8.08654 - 7.91760 7.71382 7.31751 6.64465 4.76428 3.54884 - 1.61712 1.25524 0.91242 0.87039 0.84371 0.84087 - 13.25667 12.22742 11.63388 11.09460 10.60612 10.16619 - 9.77365 9.42754 9.12709 8.87175 8.66076 8.49269 - 8.36364 8.27177 8.22019 8.20999 8.23179 8.23892 - 8.13765 7.98576 7.66212 7.07621 5.29910 4.03711 - 1.83601 1.38860 0.94035 0.88097 0.84466 0.84001 - 13.16929 12.21718 11.63527 11.10363 10.61968 10.18209 - 9.79022 9.44392 9.14343 8.88875 8.67982 8.51631 - 8.39597 8.31723 8.27933 8.27435 8.29026 8.30774 - 8.26981 8.17249 7.90935 7.38119 5.70082 4.44036 - 2.04133 1.51202 0.96714 0.89514 0.84577 0.83949 - 13.12269 12.21900 11.63939 11.10760 10.62310 10.18579 - 9.79531 9.45128 9.15370 8.90229 8.69661 8.53602 - 8.41841 8.34253 8.30862 8.31061 8.33859 8.37437 - 8.36701 8.29724 8.08179 7.61456 6.02151 4.77409 - 2.23156 1.63303 0.99776 0.90588 0.84795 0.83915 - 13.06653 12.21948 11.64234 11.11246 10.62956 10.19397 - 9.80528 9.46328 9.16807 8.91937 8.71669 8.55939 - 8.44576 8.37498 8.34791 8.35940 8.40145 8.46008 - 8.49448 8.46246 8.31405 7.93927 6.50583 5.30565 - 2.58793 1.85487 1.05523 0.93265 0.85238 0.83871 - 13.03241 12.22025 11.64423 11.11565 10.63396 10.19954 - 9.81197 9.47112 9.17714 8.92988 8.72894 8.57369 - 8.46263 8.39505 8.37219 8.38949 8.44020 8.51332 - 8.57410 8.56611 8.46339 8.15696 6.85862 5.71414 - 2.90167 2.05747 1.11168 0.96057 0.85723 0.83845 - 12.98174 12.22157 11.64685 11.11993 10.64022 10.20753 - 9.82150 9.48209 9.18960 8.94403 8.74533 8.59302 - 8.48560 8.42250 8.40534 8.43049 8.49299 8.58634 - 8.68421 8.71039 8.67544 8.47987 7.43945 6.42858 - 3.54928 2.50695 1.24782 1.03258 0.87010 0.83810 - 12.95288 12.22202 11.64770 11.12162 10.64280 10.21106 - 9.82599 9.48770 9.19652 8.95220 8.75413 8.60204 - 8.49586 8.43602 8.42348 8.45269 8.51824 8.62002 - 8.74690 8.79861 8.78430 8.61924 7.81582 6.98348 - 4.01886 2.85759 1.37997 1.11635 0.88596 0.83792 - 12.92056 12.22234 11.64896 11.12342 10.64529 10.21424 - 9.82998 9.49256 9.20238 8.95916 8.76236 8.61177 - 8.50744 8.45000 8.44057 8.47401 8.54571 8.65759 - 8.80566 8.87874 8.90335 8.80287 8.22820 7.60201 - 4.77180 3.46682 1.61954 1.26385 0.91044 0.83775 - 12.92486 12.22969 11.64848 11.11932 10.64054 10.21050 - 9.82823 9.49308 9.20470 8.96295 8.76769 8.61808 - 8.51149 8.44787 8.43353 8.47528 8.57441 8.70637 - 8.83811 8.90053 8.95361 8.94036 8.48189 7.84769 - 5.34658 4.01699 1.83595 1.38120 0.93851 0.83767 - 12.91391 12.22950 11.64850 11.11968 10.64103 10.21128 - 9.82928 9.49438 9.20632 8.96492 8.77005 8.62092 - 8.51492 8.45205 8.43871 8.48184 8.58305 8.71825 - 8.85630 8.92505 8.99073 9.00196 8.63849 8.09264 - 5.75800 4.41486 2.05609 1.50943 0.96697 0.83762 - 12.88261 12.22294 11.65111 11.12562 10.64699 10.21617 - 9.83276 9.49648 9.20736 8.96537 8.77044 8.62234 - 8.52012 8.46391 8.45608 8.49423 8.57609 8.70131 - 8.86140 8.94720 9.02580 9.04618 8.74114 8.27399 - 6.08717 4.74626 2.26132 1.63242 0.99605 0.83759 - 12.87343 12.22285 11.65112 11.12608 10.64797 10.21748 - 9.83427 9.49809 9.20904 8.96718 8.77248 8.62482 - 8.52312 8.46755 8.46050 8.49972 8.58318 8.71109 - 8.87697 8.96844 9.05717 9.09803 8.88669 8.51206 - 6.57589 5.28196 2.62580 1.88904 1.05272 0.83755 - 12.86948 12.22100 11.64923 11.12620 10.65042 10.22118 - 9.83807 9.50116 9.21100 8.96797 8.77249 8.62477 - 8.52369 8.46930 8.46389 8.50473 8.58902 8.71561 - 8.88377 8.98237 9.07724 9.12907 8.98466 8.65850 - 6.91937 5.70911 2.94755 2.10674 1.10925 0.83752 - 1.70745 1.76029 1.81232 1.86367 1.91411 1.96335 - 2.01119 2.05746 2.10213 2.14506 2.18614 2.22563 - 2.26440 2.30327 2.34226 2.38156 2.42108 2.45956 - 2.49546 2.51304 2.53343 2.55360 2.57897 2.58614 - 2.59156 2.59216 2.59277 2.59288 2.59290 2.59294 - 2.19385 2.25491 2.31321 2.36911 2.42233 2.47266 - 2.52008 2.56487 2.60755 2.64824 2.68706 2.72445 - 2.76172 2.80006 2.83969 2.88091 2.92384 2.96790 - 3.01181 3.03325 3.05452 3.07140 3.08988 3.09495 - 3.09875 3.09915 3.09954 3.09962 3.09961 3.09966 - 2.61423 2.66251 2.71944 2.78240 2.84553 2.90221 - 2.95040 2.98921 3.01882 3.04426 3.07539 3.11647 - 3.15829 3.19364 3.22657 3.26221 3.30376 3.34927 - 3.39459 3.41581 3.43598 3.45160 3.46684 3.47055 - 3.47350 3.47391 3.47420 3.47423 3.47428 3.47428 - 3.25599 3.33833 3.41027 3.47270 3.52537 3.56854 - 3.60325 3.63179 3.65725 3.68058 3.70242 3.72368 - 3.74627 3.77186 3.80027 3.83034 3.86132 3.89529 - 3.93420 3.95449 3.97240 3.98380 3.99562 3.99855 - 4.00065 4.00088 4.00111 4.00113 4.00118 4.00118 - 3.77153 3.87228 3.95000 4.00845 4.05158 4.08433 - 4.10867 4.12692 4.14218 4.15536 4.16705 4.17784 - 4.18872 4.20081 4.21479 4.23172 4.25269 4.27780 - 4.30603 4.32037 4.33416 4.34411 4.35289 4.35504 - 4.35672 4.35693 4.35709 4.35712 4.35713 4.35714 - 4.20183 4.30132 4.38088 4.44228 4.48557 4.51190 - 4.52408 4.52716 4.52767 4.52735 4.52671 4.52633 - 4.52707 4.52979 4.53452 4.54083 4.54869 4.55998 - 4.57698 4.58743 4.59723 4.60380 4.61022 4.61186 - 4.61309 4.61322 4.61335 4.61337 4.61338 4.61339 - 4.56370 4.66764 4.74776 4.80627 4.84343 4.86081 - 4.86197 4.85310 4.84205 4.83084 4.81989 4.80964 - 4.80042 4.79271 4.78658 4.78176 4.77841 4.77846 - 4.78448 4.78988 4.79536 4.79924 4.80299 4.80401 - 4.80480 4.80489 4.80497 4.80499 4.80499 4.80500 - 5.14945 5.25635 5.33310 5.38298 5.40657 5.40628 - 5.38683 5.35622 5.32426 5.29345 5.26401 5.23620 - 5.20953 5.18382 5.15904 5.13476 5.11119 5.09084 - 5.07732 5.07364 5.07065 5.06851 5.06671 5.06640 - 5.06617 5.06614 5.06611 5.06612 5.06611 5.06612 - 5.61013 5.71442 5.78374 5.82245 5.83155 5.81405 - 5.77566 5.72564 5.67524 5.62718 5.58173 5.53883 - 5.49754 5.45717 5.41735 5.37715 5.33648 5.29882 - 5.26900 5.25760 5.24675 5.23835 5.23105 5.22941 - 5.22806 5.22790 5.22778 5.22776 5.22774 5.22776 - 6.41867 6.56691 6.61631 6.59301 6.52898 6.45739 - 6.38407 6.30953 6.23437 6.15816 6.08102 6.00341 - 5.92777 5.85586 5.78693 5.71850 5.64922 5.58340 - 5.52354 5.49436 5.46636 5.44579 5.42653 5.42182 - 5.41812 5.41765 5.41729 5.41722 5.41719 5.41721 - 7.02066 7.11886 7.13018 7.07791 6.98524 6.87690 - 6.76091 6.64356 6.53189 6.42654 6.32630 6.22952 - 6.13636 6.04614 5.95823 5.87078 5.78301 5.69893 - 5.61878 5.57730 5.53619 5.50535 5.47777 5.47079 - 5.46524 5.46455 5.46404 5.46395 5.46391 5.46389 - 7.85040 7.83903 7.77279 7.66687 7.52583 7.35679 - 7.17027 6.98099 6.80453 6.64516 6.50262 6.37481 - 6.25932 6.15190 6.04938 5.94456 5.83234 5.71931 - 5.61306 5.56111 5.50418 5.45616 5.41882 5.40963 - 5.40134 5.40037 5.39966 5.39949 5.39951 5.39941 - 8.40955 8.32809 8.19062 8.01662 7.81166 7.58384 - 7.34440 7.10846 6.89169 6.69803 6.52691 6.37511 - 6.23918 6.11423 5.99649 5.87812 5.75315 5.62687 - 5.50541 5.44514 5.38001 5.32570 5.28174 5.27088 - 5.26130 5.26017 5.25933 5.25914 5.25913 5.25903 - 8.83295 8.68256 8.47824 8.24289 7.98255 7.70573 - 7.42363 7.15086 6.90270 6.68236 6.48874 6.31759 - 6.16426 6.02358 5.89168 5.76129 5.62667 5.49141 - 5.36005 5.29515 5.22706 5.17140 5.12275 5.11070 - 5.10049 5.09929 5.09833 5.09817 5.09813 5.09806 - 9.14914 8.98485 8.72356 8.40945 8.07239 7.74145 - 7.42671 7.13603 6.87757 6.64890 6.44207 6.25005 - 6.07292 5.91069 5.76091 5.61942 5.48156 5.34329 - 5.20312 5.13416 5.06585 5.01255 4.95996 4.94700 - 4.93664 4.93530 4.93431 4.93417 4.93407 4.93405 - 9.62475 9.40274 9.03985 8.60804 8.16519 7.76167 - 7.40149 7.07929 6.79033 6.53000 6.28975 6.06410 - 5.85595 5.66846 5.49842 5.34031 5.18787 5.03487 - 4.88329 4.81398 4.74731 4.69497 4.63797 4.62441 - 4.61369 4.61223 4.61118 4.61106 4.61094 4.61097 - 10.15076 9.62277 9.10709 8.62746 8.18102 7.76594 - 7.38078 7.02408 6.69513 6.39459 6.12013 5.86882 - 5.63814 5.42778 5.23730 5.06596 4.91045 4.75654 - 4.59209 4.51029 4.43871 4.39138 4.33520 4.31811 - 4.30767 4.30686 4.30546 4.30517 4.30524 4.30524 - 10.71425 10.00451 9.33221 8.71911 8.15961 7.64888 - 7.18288 6.75955 6.37709 6.03247 5.72134 5.43825 - 5.17720 4.93498 4.71259 4.50812 4.31919 4.13646 - 3.95349 3.86597 3.78795 3.73431 3.67428 3.65762 - 3.64652 3.64546 3.64417 3.64398 3.64380 3.64385 - 11.01962 10.18418 9.40828 8.70840 8.07579 7.50451 - 6.98933 6.52665 6.11433 5.74636 5.41530 5.11279 - 4.82849 4.55660 4.30085 4.06528 3.85178 3.65459 - 3.46925 3.38095 3.29268 3.22402 3.16412 3.14951 - 3.13740 3.13599 3.13485 3.13465 3.13457 3.13447 - 11.45682 10.39054 9.44995 8.62843 7.90543 7.26794 - 6.70555 6.20555 5.75768 5.35464 4.98898 4.65304 - 4.33785 4.03813 3.75582 3.49466 3.25433 3.03112 - 2.82393 2.72709 2.63348 2.56303 2.50029 2.48510 - 2.47280 2.47137 2.47019 2.47001 2.46991 2.46978 - 11.73739 10.52262 9.48295 8.58730 7.80957 7.13085 - 6.53792 6.01367 5.54268 5.11680 4.72930 4.37326 - 4.04085 3.72704 3.43187 3.15638 2.90037 2.66055 - 2.43809 2.33534 2.23953 2.16970 2.10355 2.08774 - 2.07547 2.07403 2.07278 2.07265 2.07248 2.07246 - 11.94909 10.63174 9.52787 8.58221 7.76742 7.06059 - 6.44556 5.90304 5.41506 4.97268 4.56962 4.19946 - 3.85500 3.53132 3.22748 2.94302 2.67774 2.42842 - 2.19536 2.08699 1.98620 1.91310 1.84456 1.82845 - 1.81601 1.81454 1.81325 1.81312 1.81295 1.81304 - 12.12239 10.72963 9.58144 8.60002 7.75854 7.03201 - 6.40089 5.84440 5.34346 4.88881 4.47421 4.09352 - 3.73981 3.40822 3.09741 2.80629 2.53430 2.27850 - 2.03696 1.92336 1.81690 1.73930 1.66842 1.65193 - 1.63910 1.63758 1.63626 1.63611 1.63595 1.63608 - 12.40180 10.90480 9.70084 8.67404 7.79848 7.04778 - 6.39666 5.82206 5.30407 4.83329 4.40345 4.00828 - 3.64087 3.29638 2.97349 2.67111 2.38783 2.12023 - 1.86338 1.74023 1.62342 1.53732 1.46020 1.44224 - 1.42811 1.42644 1.42500 1.42482 1.42467 1.42470 - 12.62273 11.05907 9.82370 8.77223 7.87902 7.11547 - 6.45370 5.86914 5.34148 4.86131 4.42222 4.01756 - 3.64006 3.28474 2.95073 2.63762 2.34360 2.06316 - 1.79097 1.65862 1.53211 1.43783 1.35246 1.33228 - 1.31634 1.31446 1.31287 1.31267 1.31250 1.31234 - 12.99418 11.35671 10.09878 9.02951 8.12663 7.35108 - 6.67690 6.07974 5.53995 5.04783 4.59631 4.17781 - 3.78365 3.40840 3.05206 2.71558 2.39652 2.08460 - 1.77308 1.61724 1.46338 1.34403 1.23343 1.20658 - 1.18503 1.18250 1.18042 1.18014 1.17993 1.17977 - 13.20724 11.56081 10.31902 9.26139 8.36711 7.59195 - 6.91387 6.31106 5.76579 5.26830 4.81095 4.38532 - 3.98166 3.59375 3.22189 2.86735 2.52702 2.18757 - 1.83795 1.65834 1.47353 1.32406 1.18509 1.15158 - 1.12465 1.12138 1.11858 1.11822 1.11796 1.11833 - 13.43169 11.80605 10.62160 9.61511 8.75414 7.99859 - 7.32956 6.72806 6.17835 5.67246 5.20442 4.76773 - 4.35468 3.95894 3.57650 3.20171 2.82652 2.43790 - 2.02067 1.79627 1.55602 1.34914 1.14188 1.09545 - 1.06390 1.05995 1.05430 1.05328 1.05378 1.05513 - 13.45144 11.93219 10.84689 9.90532 9.07276 8.32394 - 7.64930 7.03938 6.48641 5.98264 5.51999 5.08927 - 4.67915 4.28076 3.89004 3.50130 3.10461 2.68082 - 2.20714 1.94397 1.65718 1.40466 1.13028 1.06205 - 1.02970 1.02716 1.01833 1.01618 1.01832 1.01935 - 13.50354 12.00762 10.97409 10.07595 9.27437 8.54870 - 7.89091 7.29267 6.74721 6.24767 5.78679 5.35618 - 4.94533 4.54552 4.15196 3.75751 3.34940 2.90259 - 2.38587 2.08985 1.75866 1.46257 1.13054 1.04493 - 1.00744 1.00509 0.99425 0.99147 0.99450 0.99473 - 13.53077 12.05352 11.06534 10.20224 9.42741 8.72238 - 8.08043 7.49404 6.95719 6.46365 6.00685 5.57898 - 5.17009 4.77168 4.37833 3.98172 3.56669 3.10306 - 2.55194 2.22839 1.85897 1.52306 1.13815 1.03611 - 0.99162 0.98907 0.97677 0.97356 0.97717 0.97641 - 13.53617 12.09443 11.18387 10.37753 9.64805 8.97879 - 8.36495 7.80036 7.28022 6.79946 6.35261 5.93307 - 5.53226 5.14212 4.75607 4.36336 3.94376 3.45595 - 2.84599 2.47448 2.04015 1.63906 1.17787 1.04654 - 0.96093 0.95779 0.95872 0.95626 0.94624 0.95075 - 13.53409 12.11525 11.25818 10.49159 9.79521 9.15355 - 8.56286 8.01770 7.51398 7.04728 6.61272 6.20432 - 5.81414 5.43432 5.05768 4.67210 4.25423 3.75535 - 3.10900 2.70323 2.21702 1.75650 1.21615 1.05796 - 0.94876 0.94298 0.94311 0.94047 0.92894 0.93360 - 13.57953 12.17166 11.37225 10.65345 10.00016 9.39929 - 8.84745 8.33976 7.87235 7.44092 7.04048 6.66458 - 6.30421 5.95072 5.59728 5.23212 4.83200 4.34645 - 3.68480 3.23258 2.63812 2.03460 1.30447 1.09312 - 0.94812 0.93159 0.91367 0.91121 0.91035 0.90847 - 13.55281 12.16809 11.41352 10.73338 10.11404 9.54442 - 9.02161 8.54135 8.10023 7.69439 7.31924 6.96868 - 6.63385 6.30613 5.97831 5.63766 5.25807 4.78145 - 4.10390 3.62750 2.98777 2.31076 1.42274 1.15095 - 0.94538 0.92118 0.90113 0.89852 0.89728 0.89485 - 13.48291 12.13134 11.43630 10.80772 10.23384 9.70649 - 9.22328 8.78082 8.37641 8.00691 7.66851 7.35592 - 7.06106 6.77578 6.49274 6.19803 5.86143 5.41273 - 4.72811 4.22601 3.53317 2.76518 1.66260 1.29552 - 0.95826 0.91351 0.88627 0.88375 0.87657 0.88039 - 13.47533 12.12899 11.45555 10.84689 10.29280 9.78623 - 9.32482 8.90544 8.52547 8.18197 7.87116 7.58761 - 7.32279 7.06833 6.81767 6.55790 6.25988 5.85353 - 5.20646 4.70994 3.99376 3.15723 1.86975 1.41974 - 0.98445 0.92073 0.87639 0.87332 0.87048 0.87278 - 13.47198 12.12074 11.46254 10.87540 10.34352 9.85451 - 9.40557 8.99413 8.61883 8.28138 7.98532 7.72836 - 7.49720 7.27819 7.06068 6.82623 6.54442 6.15776 - 5.55272 5.08999 4.40531 3.54073 2.07217 1.52946 - 0.99669 0.92424 0.87819 0.87516 0.86911 0.86809 - 13.43720 12.12491 11.48558 10.90373 10.37234 9.88644 - 9.44502 9.04666 8.69047 8.37434 8.09536 7.84917 - 7.62845 7.42485 7.22894 7.02063 6.76816 6.41690 - 5.85004 5.40110 4.72056 3.84214 2.26006 1.64656 - 1.02355 0.93349 0.87625 0.87295 0.86509 0.86493 - 13.42399 12.12722 11.49902 10.92903 10.41089 9.93985 - 9.51418 9.13177 8.79108 8.49048 8.22809 8.00098 - 7.80392 7.63031 7.47119 7.30593 7.10237 6.80627 - 6.29695 5.87536 5.22093 4.34275 2.61417 1.86300 - 1.07353 0.95949 0.87635 0.86945 0.86088 0.86092 - 13.41075 12.13239 11.51383 10.95222 10.44212 9.97923 - 9.56193 9.18845 8.85735 8.56730 8.31673 8.10308 - 7.92160 7.76647 7.63012 7.49396 7.32803 7.07933 - 6.62595 6.23396 5.60822 4.74038 2.92013 2.06655 - 1.12677 0.98689 0.87807 0.86794 0.85821 0.85847 - 13.38299 12.14669 11.54534 10.99708 10.49774 10.04456 - 9.63662 9.27334 8.95420 8.67838 8.44462 8.25070 - 8.09223 7.96448 7.86270 7.77305 7.67075 7.50611 - 7.16681 6.84531 6.28545 5.45382 3.54478 2.53396 - 1.25723 1.05161 0.88606 0.87040 0.85689 0.85516 - 13.34761 12.15563 11.56209 11.02070 10.52741 10.08012 - 9.67809 9.32096 9.00839 8.73985 8.51448 8.33063 - 8.18464 8.07275 7.99132 7.92807 7.86138 7.74826 - 7.48926 7.22618 6.74219 5.97498 4.02788 2.90302 - 1.38745 1.12881 0.89771 0.87028 0.85410 0.85350 - 13.24901 12.16191 11.57683 11.04233 10.55537 10.11424 - 9.71835 9.36763 9.06210 8.80150 8.58535 8.41261 - 8.28025 8.18559 8.12681 8.09463 8.07234 8.02596 - 7.87255 7.68591 7.30230 6.64270 4.76458 3.52015 - 1.62350 1.26934 0.92373 0.87742 0.85528 0.85182 - 13.16323 12.16231 11.58134 11.05029 10.56657 10.12883 - 9.73644 9.38944 9.08807 8.83220 8.62148 8.45510 - 8.33021 8.24465 8.19768 8.18193 8.18403 8.17665 - 8.08999 7.95508 7.64431 7.07146 5.29833 4.00724 - 1.83961 1.40172 0.95149 0.88735 0.85751 0.85098 - 13.10259 12.16429 11.58481 11.05460 10.57161 10.13521 - 9.74490 9.40073 9.10292 8.85091 8.64358 8.48007 - 8.35905 8.27967 8.24148 8.23707 8.25505 8.27619 - 8.23457 8.12913 7.87000 7.37612 5.71955 4.39609 - 2.03711 1.52832 0.97950 0.89761 0.86248 0.85048 - 13.05756 12.16541 11.58813 11.05825 10.57541 10.14008 - 9.75159 9.40936 9.11316 8.86279 8.65797 8.49815 - 8.38118 8.30573 8.27204 8.27412 8.30213 8.33803 - 8.33119 8.26222 8.04906 7.58664 6.00704 4.76580 - 2.23351 1.63814 1.00719 0.91635 0.85887 0.85014 - 13.00313 12.16632 11.59137 11.06280 10.58124 10.14755 - 9.76113 9.42125 9.12753 8.87980 8.67787 8.52129 - 8.40827 8.33788 8.31097 8.32248 8.36447 8.42309 - 8.45772 8.42620 8.27934 7.90833 6.48804 5.29484 - 2.58829 1.85909 1.06410 0.94269 0.86335 0.84973 - 12.96993 12.16689 11.59306 11.06587 10.58573 10.15321 - 9.76781 9.42900 9.13652 8.89025 8.69006 8.53551 - 8.42499 8.35776 8.33502 8.35231 8.40290 8.47589 - 8.53675 8.52915 8.42746 8.12396 6.83809 5.70119 - 2.90077 2.06096 1.12008 0.97021 0.86823 0.84948 - 12.92043 12.16723 11.59496 11.07034 10.59266 10.16189 - 9.77766 9.43985 9.14871 8.90425 8.70640 8.55473 - 8.44775 8.38491 8.36785 8.39293 8.45522 8.54826 - 8.64603 8.67241 8.63791 8.44402 7.41389 6.41128 - 3.54595 2.50878 1.25521 1.04138 0.88113 0.84915 - 12.89256 12.16748 11.59572 11.07202 10.59543 10.16562 - 9.78223 9.44541 9.15550 8.91227 8.71509 8.56366 - 8.45794 8.39834 8.38583 8.41491 8.48022 8.58168 - 8.70830 8.75991 8.74580 8.58221 7.78737 6.96210 - 4.01347 2.85783 1.38654 1.12440 0.89703 0.84897 - 12.86118 12.16781 11.59697 11.07391 10.59791 10.16878 - 9.78617 9.45019 9.16124 8.91909 8.72314 8.57324 - 8.46938 8.41219 8.40280 8.43606 8.50742 8.61886 - 8.76652 8.83946 8.86405 8.76414 8.19543 7.57658 - 4.76317 3.46371 1.62468 1.27098 0.92115 0.84879 - 12.86588 12.17527 11.59649 11.06971 10.59295 10.16486 - 9.78430 9.45063 9.16353 8.92288 8.72848 8.57953 - 8.47342 8.41005 8.39575 8.43729 8.53598 8.66737 - 8.79861 8.86085 8.91386 8.90098 8.44658 7.81846 - 5.33594 4.01181 1.83991 1.38737 0.94878 0.84870 - 12.85504 12.17488 11.59641 11.06997 10.59344 10.16554 - 9.78523 9.45184 9.16506 8.92476 8.73078 8.58233 - 8.47682 8.41419 8.40090 8.44381 8.54452 8.67910 - 8.81659 8.88513 8.95074 8.96225 8.60182 8.06139 - 5.74535 4.40776 2.05891 1.51498 0.97687 0.84865 - 12.82426 12.16831 11.59892 11.07551 10.59911 10.17028 - 9.78877 9.45415 9.16636 8.92540 8.73124 8.58375 - 8.48194 8.42598 8.41817 8.45614 8.53756 8.66216 - 8.82159 8.90710 8.98553 9.00617 8.70346 8.24097 - 6.07277 4.73747 2.26283 1.63762 1.00560 0.84862 - 12.81547 12.16833 11.59913 11.07626 10.60028 10.17180 - 9.79036 9.45573 9.16800 8.92719 8.73330 8.58619 - 8.48489 8.42955 8.42253 8.46157 8.54457 8.67185 - 8.83703 8.92815 9.01662 9.05763 8.84800 8.47693 - 6.55856 5.27041 2.62517 1.89236 1.06162 0.84859 - 12.81149 12.16698 11.59804 11.07729 10.60362 10.17609 - 9.79445 9.45884 9.16980 8.92776 8.73312 8.58605 - 8.48544 8.43128 8.42585 8.46651 8.55044 8.67644 - 8.84374 8.94190 9.03655 9.08851 8.94519 8.62214 - 6.89935 5.69546 2.94541 2.10861 1.11760 0.84856 - 1.65570 1.70916 1.76174 1.81358 1.86440 1.91393 - 1.96197 2.00838 2.05317 2.09622 2.13741 2.17699 - 2.21587 2.25485 2.29391 2.33317 2.37240 2.41032 - 2.44539 2.46260 2.48299 2.50353 2.52898 2.53602 - 2.54143 2.54204 2.54266 2.54275 2.54279 2.54326 - 2.13915 2.19587 2.25137 2.30604 2.35957 2.41160 - 2.46174 2.50963 2.55495 2.59754 2.63746 2.67522 - 2.71229 2.75002 2.78852 2.82789 2.86866 2.91265 - 2.96106 2.98529 3.00587 3.01883 3.03718 3.04390 - 3.04713 3.04730 3.04781 3.04782 3.04799 3.05101 - 2.54074 2.60717 2.66896 2.72676 2.78032 2.82957 - 2.87478 2.91677 2.95677 2.99503 3.03175 3.06722 - 3.10248 3.13854 3.17572 3.21456 3.25561 3.29892 - 3.34374 3.36586 3.38652 3.40121 3.41613 3.42019 - 3.42320 3.42353 3.42383 3.42384 3.42384 3.42637 - 3.19068 3.27077 3.34123 3.40304 3.45591 3.50013 - 3.53664 3.56759 3.59587 3.62229 3.64730 3.67152 - 3.69638 3.72314 3.75191 3.78236 3.81447 3.84959 - 3.88873 3.90879 3.92661 3.93818 3.95026 3.95327 - 3.95544 3.95569 3.95592 3.95595 3.95601 3.95531 - 3.70280 3.80051 3.87761 3.93727 3.98258 4.01754 - 4.04408 4.06474 4.08292 4.09926 4.11370 4.12656 - 4.13919 4.15309 4.16887 4.18742 4.20969 4.23586 - 4.26487 4.27944 4.29346 4.30371 4.31298 4.31528 - 4.31710 4.31730 4.31746 4.31754 4.31755 4.31423 - 4.12930 4.22840 4.30859 4.37152 4.41713 4.44644 - 4.46198 4.46843 4.47187 4.47394 4.47524 4.47654 - 4.47905 4.48390 4.49101 4.49956 4.50918 4.52186 - 4.53997 4.55089 4.56121 4.56831 4.57535 4.57718 - 4.57859 4.57872 4.57884 4.57890 4.57894 4.57396 - 4.48904 4.59363 4.67539 4.73640 4.77677 4.79786 - 4.80291 4.79765 4.78941 4.78020 4.77061 4.76146 - 4.75375 4.74848 4.74545 4.74354 4.74220 4.74373 - 4.75119 4.75731 4.76355 4.76808 4.77258 4.77381 - 4.77482 4.77488 4.77495 4.77503 4.77507 4.76936 - 5.07268 5.18179 5.26171 5.31547 5.34350 5.34786 - 5.33294 5.30618 5.27692 5.24762 5.21887 5.19146 - 5.16599 5.14308 5.12220 5.10166 5.08051 5.06193 - 5.05035 5.04771 5.04578 5.04445 5.04350 5.04344 - 5.04341 5.04336 5.04333 5.04339 5.04340 5.03844 - 5.53300 5.64052 5.71395 5.75735 5.77151 5.75915 - 5.72556 5.67953 5.63181 5.58517 5.54021 5.49757 - 5.45744 5.41997 5.38433 5.34819 5.31026 5.27471 - 5.24720 5.23701 5.22734 5.21982 5.21342 5.21201 - 5.21085 5.21069 5.21056 5.21057 5.21057 5.20789 - 6.37455 6.46366 6.51005 6.52053 6.49693 6.44335 - 6.36689 6.27869 6.19194 6.10970 6.03273 5.96086 - 5.89336 5.82912 5.76660 5.70214 5.63363 5.56692 - 5.50953 5.48441 5.45825 5.43666 5.41887 5.41463 - 5.41094 5.41051 5.41018 5.41010 5.41010 5.41426 - 6.95047 7.05209 7.06837 7.02191 6.93530 6.83265 - 6.72168 6.60836 6.49945 6.39610 6.29810 6.20431 - 6.11417 6.02656 5.94103 5.85632 5.77204 5.69147 - 5.61410 5.57377 5.53381 5.50395 5.47746 5.47074 - 5.46537 5.46480 5.46434 5.46411 5.46408 5.47408 - 7.78752 7.78096 7.71973 7.61863 7.48222 7.31766 - 7.13554 6.95072 6.77898 6.62449 6.48674 6.36331 - 6.25117 6.14577 6.04443 5.94126 5.83211 5.72256 - 5.61897 5.56797 5.51196 5.46482 5.42896 5.42017 - 5.41214 5.41130 5.41070 5.41038 5.41039 5.42590 - 8.35390 8.27724 8.14463 7.97519 7.77458 7.55103 - 7.31591 7.08466 6.87320 6.68534 6.52009 6.37369 - 6.24166 6.11851 6.00121 5.88370 5.76139 5.63836 - 5.51922 5.45972 5.39535 5.34187 5.29949 5.28907 - 5.27977 5.27877 5.27803 5.27771 5.27770 5.29154 - 8.78362 8.63816 8.43892 8.20831 7.95250 7.68011 - 7.40250 7.13452 6.89176 6.67724 6.48951 6.32375 - 6.17432 6.03547 5.90399 5.77433 5.64201 5.50954 - 5.38019 5.31596 5.24855 5.19364 5.14641 5.13477 - 5.12485 5.12372 5.12284 5.12260 5.12257 5.13036 - 9.10370 8.94750 8.69270 8.38327 8.04965 7.72167 - 7.41037 7.12476 6.87397 6.65383 6.45301 6.26317 - 6.08693 5.92634 5.77881 5.63948 5.50322 5.36669 - 5.22846 5.16010 5.09244 5.03985 4.98837 4.97572 - 4.96561 4.96431 4.96334 4.96319 4.96311 4.96308 - 9.59100 9.37244 9.01603 8.59182 8.15624 7.75853 - 7.40303 7.08494 6.80005 6.54365 6.30691 6.08420 - 5.87860 5.69336 5.52532 5.36895 5.21802 5.06639 - 4.91610 4.84744 4.78144 4.72962 4.67310 4.65968 - 4.64914 4.64757 4.64647 4.64652 4.64639 4.63442 - 10.11840 9.60036 9.09381 8.62206 8.18237 7.77305 - 7.39274 7.04010 6.71448 6.41664 6.14436 5.89491 - 5.66594 5.45731 5.26860 5.09910 4.94547 4.79326 - 4.63001 4.54863 4.47747 4.43049 4.37444 4.35731 - 4.34695 4.34600 4.34452 4.34446 4.34450 4.32826 - 10.68629 9.99126 9.33134 8.72818 8.17646 7.67165 - 7.21002 6.78971 6.40909 6.06539 5.75452 5.47143 - 5.21059 4.96911 4.74802 4.54542 4.35882 4.17827 - 3.99662 3.90936 3.83134 3.77751 3.71718 3.70042 - 3.68917 3.68804 3.68671 3.68658 3.68642 3.68148 - 11.01131 10.18685 9.42045 8.72815 8.10131 7.53396 - 7.02075 6.55783 6.14293 5.77095 5.43588 5.13133 - 4.84972 4.58644 4.34260 4.11706 3.90715 3.70617 - 3.51017 3.41705 3.33121 3.26950 3.20664 3.19177 - 3.17951 3.17809 3.17704 3.17679 3.17656 3.18613 - 11.43325 10.38307 9.45469 8.64216 7.92571 7.29278 - 6.73336 6.23512 5.78813 5.38538 5.01974 4.68390 - 4.36937 4.07102 3.79049 3.53087 3.29153 3.06912 - 2.86277 2.76630 2.67275 2.60208 2.53902 2.52371 - 2.51127 2.50986 2.50870 2.50846 2.50835 2.51436 - 11.71269 10.51424 9.48564 8.59740 7.82449 7.14881 - 6.55776 6.03496 5.56560 5.14153 4.75594 4.40171 - 4.07073 3.75782 3.46325 3.18842 2.93338 2.69457 - 2.47285 2.37035 2.27462 2.20471 2.13841 2.12255 - 2.11024 2.10878 2.10752 2.10740 2.10725 2.10485 - 11.92295 10.62202 9.52827 8.58898 7.77796 7.07327 - 6.45956 5.91836 5.43248 4.99285 4.59280 4.22540 - 3.88278 3.55972 3.25586 2.97160 2.70730 2.45911 - 2.22678 2.11861 2.01787 1.94471 1.87620 1.86010 - 1.84768 1.84619 1.84489 1.84478 1.84462 1.84161 - 12.09508 10.71868 9.58011 8.60456 7.76634 7.04155 - 6.41150 5.85628 5.35762 4.90603 4.49483 4.11720 - 3.76542 3.43432 3.12325 2.83217 2.56115 2.30650 - 2.06572 1.95232 1.84591 1.76830 1.69756 1.68112 - 1.66833 1.66681 1.66548 1.66534 1.66519 1.66398 - 12.37285 10.89243 9.69779 8.67701 7.80504 7.05634 - 6.40648 5.83316 5.31704 4.84860 4.42129 4.02839 - 3.66245 3.31845 2.99550 2.69329 2.41083 2.14420 - 1.88819 1.76541 1.64889 1.56299 1.48608 1.46815 - 1.45405 1.45239 1.45096 1.45078 1.45063 1.45152 - 12.59287 11.04609 9.82038 8.77580 7.88720 7.12662 - 6.46670 5.88339 5.35670 4.87736 4.43899 4.03501 - 3.65814 3.30346 2.97005 2.65749 2.36401 2.08423 - 1.81299 1.68125 1.55540 1.46163 1.37641 1.35622 - 1.34028 1.33841 1.33682 1.33661 1.33644 1.33700 - 12.96431 11.34261 10.09375 9.03181 8.13445 7.36305 - 6.69166 6.09596 5.55624 5.06320 4.61031 4.19060 - 3.79616 3.42181 3.06694 2.73154 2.41278 2.10127 - 1.79099 1.63605 1.48316 1.36453 1.25421 1.22738 - 1.20585 1.20332 1.20124 1.20096 1.20075 1.20040 - 13.17798 11.54491 10.30956 9.25727 8.36698 7.59513 - 6.91965 6.31870 5.77449 5.27749 4.82027 4.39478 - 3.99157 3.60459 3.23386 2.88023 2.54051 2.20192 - 1.85377 1.67494 1.49074 1.34168 1.20345 1.17019 - 1.14342 1.14016 1.13738 1.13702 1.13677 1.13734 - 13.40292 11.78458 10.60048 9.59448 8.73412 7.97992 - 7.31299 6.71434 6.16827 5.66652 5.20279 4.77013 - 4.36027 3.96656 3.58531 3.21136 2.83705 2.44951 - 2.03351 1.80962 1.56954 1.36279 1.15676 1.11120 - 1.08044 1.07657 1.07090 1.06985 1.07037 1.07319 - 13.42732 11.90675 10.81477 9.86892 9.03453 8.28626 - 7.61418 7.00842 6.46087 5.96337 5.50743 5.08335 - 4.67904 4.28510 3.89754 3.51078 3.11502 2.69151 - 2.21777 1.95452 1.66774 1.41560 1.14316 1.07613 - 1.04512 1.04275 1.03387 1.03166 1.03384 1.03707 - 13.47647 11.97617 10.93287 10.02827 9.22367 8.49815 - 7.84315 7.24988 6.71110 6.21943 5.76710 5.34498 - 4.94156 4.54745 4.15790 3.76584 3.35871 2.91194 - 2.39478 2.09851 1.76730 1.47169 1.14210 1.05796 - 1.02224 1.02012 1.00919 1.00633 1.00943 1.01203 - 13.49882 12.01618 11.01687 10.14636 9.36802 8.66304 - 8.02410 7.44321 6.91382 6.42916 5.98202 5.56379 - 5.16340 4.77151 4.38274 3.98885 3.57487 3.11118 - 2.55941 2.23554 1.86616 1.53091 1.14883 1.04842 - 1.00603 1.00376 0.99134 0.98802 0.99172 0.99324 - 13.49372 12.04737 11.12512 10.31118 9.57806 8.90896 - 8.29852 7.74001 7.22812 6.75722 6.32115 5.91242 - 5.52117 5.13841 4.75755 4.36792 3.94950 3.46157 - 2.85096 2.47930 2.04543 1.64551 1.18750 1.05788 - 0.97465 0.97194 0.97294 0.97037 0.96035 0.96671 - 13.48242 12.06132 11.19327 10.41971 9.72012 9.07897 - 8.49187 7.95297 7.45768 7.00099 6.57743 6.18009 - 5.79976 5.42763 5.05650 4.67428 4.25777 3.75889 - 3.11202 2.70622 2.22075 1.76182 1.22512 1.06875 - 0.96211 0.95682 0.95711 0.95435 0.94273 0.94886 - 13.51590 12.11003 11.30165 10.57743 9.92213 9.32238 - 8.77439 8.27289 7.81364 7.39183 7.00192 6.63663 - 6.28565 5.93942 5.59105 5.22888 4.82996 4.34499 - 3.68436 3.23280 2.63922 2.03735 1.31204 1.10303 - 0.96129 0.94512 0.92700 0.92454 0.92356 0.92258 - 13.48149 12.10385 11.34351 10.66023 10.04011 9.47212 - 8.95301 8.47825 8.04417 7.64654 7.28032 6.93878 - 6.61206 6.29072 5.96756 5.62988 5.25187 4.77643 - 4.10067 3.62546 2.98722 2.31241 1.42955 1.16006 - 0.95809 0.93436 0.91414 0.91148 0.91017 0.90827 - 13.40443 12.06774 11.37185 10.74341 10.17072 9.64564 - 9.16562 8.72723 8.32760 7.96348 7.63085 7.32413 - 7.03478 6.75424 6.47518 6.18365 5.84953 5.40292 - 4.72052 4.22000 3.52974 2.76529 1.66893 1.30396 - 0.96972 0.92568 0.89906 0.89647 0.88882 0.89303 - 13.39724 12.06923 11.39706 10.78987 10.23770 9.73348 - 9.27478 8.85850 8.48197 8.14216 7.83522 7.55559 - 7.29454 7.04350 6.79595 6.53897 6.24355 5.83983 - 5.19588 4.70144 3.98828 3.15567 1.87511 1.42745 - 0.99536 0.93239 0.88881 0.88570 0.88238 0.88498 - 13.37119 12.07061 11.42437 10.83544 10.29622 9.80184 - 9.35133 8.94352 8.57771 8.25158 7.96179 7.70339 - 7.46837 7.24767 7.03139 6.79932 6.51990 6.13979 - 5.54480 5.08383 4.39788 3.53857 2.07250 1.53654 - 1.00925 0.93492 0.88982 0.88743 0.88073 0.88001 - 13.36355 12.07181 11.43516 10.85578 10.32655 9.84298 - 9.40375 9.00749 8.65332 8.33915 8.06203 7.81760 - 7.59849 7.39638 7.20195 6.99537 6.74528 6.39742 - 5.83556 5.38984 4.71295 3.83817 2.26257 1.65244 - 1.03388 0.94459 0.88804 0.88476 0.87685 0.87665 - 13.35402 12.07736 11.45173 10.88425 10.36844 9.89973 - 9.47621 9.09567 8.75648 8.45700 8.19545 7.96900 - 7.77256 7.59971 7.44158 7.27779 7.07641 6.78354 - 6.27912 5.86095 5.21076 4.33676 2.61500 1.86770 - 1.08309 0.96995 0.88788 0.88108 0.87238 0.87240 - 13.34034 12.08236 11.46679 10.90795 10.40036 9.93983 - 9.52461 9.15281 8.82295 8.53371 8.28361 8.07025 - 7.88912 7.73461 7.59919 7.46432 7.30019 7.05421 - 6.60546 6.21699 5.59580 4.73258 2.91968 2.07021 - 1.13567 0.99686 0.88942 0.87946 0.86953 0.86980 - 13.30817 12.09300 11.49554 10.95068 10.45413 10.00335 - 9.59734 9.23561 8.91763 8.64263 8.40945 8.21599 - 8.05807 7.93114 7.83035 7.74164 7.64023 7.47721 - 7.14164 6.82341 6.26837 5.44240 3.54208 2.53524 - 1.26479 1.06069 0.89718 0.88165 0.86807 0.86630 - 13.29161 12.10808 11.51056 10.96783 10.47551 10.03081 - 9.63242 9.27923 8.97005 8.70399 8.47985 8.29541 - 8.14618 8.02887 7.94380 7.88729 7.84140 7.74334 - 7.47190 7.19696 6.71234 5.94823 4.01756 2.92395 - 1.39123 1.13110 0.90815 0.88438 0.86616 0.86454 - 13.17445 12.10569 11.52496 10.99389 10.50938 10.07004 - 9.67553 9.32602 9.02173 8.76247 8.54767 8.37622 - 8.24495 8.15108 8.09278 8.06089 8.03881 7.99292 - 7.84118 7.65665 7.27718 6.62364 4.75647 3.51705 - 1.62876 1.27672 0.93419 0.88842 0.86610 0.86277 - 13.09437 12.10791 11.53015 11.00191 10.52043 10.08457 - 9.69376 9.34817 9.04812 8.79350 8.58392 8.41854 - 8.29448 8.20951 8.16295 8.14740 8.14967 8.14253 - 8.05689 7.92349 7.61617 7.04903 5.28773 4.00191 - 1.84373 1.40839 0.96162 0.89809 0.86830 0.86187 - 13.03808 12.11130 11.53442 11.00650 10.52564 10.09107 - 9.70249 9.35985 9.06342 8.81260 8.60625 8.44350 - 8.32307 8.24407 8.20610 8.20189 8.22014 8.24157 - 8.20051 8.09601 7.83964 7.35132 5.70710 4.38829 - 2.04039 1.53463 0.98928 0.90799 0.87331 0.86134 - 12.99645 12.11264 11.53723 11.00994 10.52972 10.09655 - 9.70985 9.36902 9.07391 8.82438 8.62037 8.46133 - 8.34501 8.26997 8.23645 8.23862 8.26675 8.30289 - 8.29658 8.22838 8.01719 7.55916 5.99272 4.75766 - 2.23570 1.64350 1.01668 0.92677 0.86963 0.86098 - 12.94434 12.11365 11.54027 11.01437 10.53553 10.10421 - 9.71961 9.38107 9.08828 8.84124 8.64001 8.48422 - 8.37187 8.30186 8.27504 8.28655 8.32855 8.38721 - 8.42215 8.39112 8.24562 7.87805 6.47039 5.28412 - 2.58891 1.86354 1.07302 0.95266 0.87412 0.86053 - 12.91141 12.11403 11.54205 11.01743 10.53990 10.10960 - 9.72600 9.38855 9.09709 8.85160 8.65214 8.49833 - 8.38841 8.32152 8.29887 8.31612 8.36662 8.43954 - 8.50059 8.49337 8.39266 8.09185 6.81770 5.68831 - 2.90014 2.06465 1.12848 0.97977 0.87901 0.86026 - 12.86158 12.11438 11.54435 11.02188 10.54631 10.11748 - 9.73493 9.39863 9.10881 8.86548 8.66852 8.51747 - 8.41092 8.34836 8.33141 8.35642 8.41847 8.51120 - 8.60893 8.63557 8.60162 8.40932 7.38856 6.39404 - 3.54281 2.51071 1.26254 1.05006 0.89187 0.85989 - 12.83355 12.11463 11.54550 11.02406 10.54947 10.12131 - 9.73934 9.40361 9.11460 8.87231 8.67661 8.52708 - 8.42236 8.36209 8.34808 8.37709 8.44512 8.54816 - 8.66544 8.71043 8.71246 8.58415 7.74181 6.85725 - 4.04503 2.89607 1.39040 1.12133 0.90500 0.85971 - 12.80426 12.11508 11.54635 11.02544 10.55144 10.12415 - 9.74323 9.40878 9.12115 8.88011 8.68507 8.53579 - 8.43236 8.37540 8.36603 8.39912 8.47016 8.58114 - 8.72843 8.80129 8.82594 8.72664 8.16331 7.55140 - 4.75476 3.46079 1.62981 1.27802 0.93166 0.85954 - 12.78773 12.11544 11.54727 11.02654 10.55258 10.12559 - 9.74505 9.41088 9.12335 8.88258 8.68863 8.54128 - 8.43928 8.38246 8.37301 8.40838 8.48593 8.60460 - 8.75269 8.82730 8.88572 8.86709 8.40220 7.79504 - 5.33063 4.00338 1.84356 1.39290 0.95960 0.85945 - 12.79908 12.12275 11.54648 11.02209 10.54756 10.12137 - 9.74263 9.41064 9.12507 8.88579 8.69264 8.54484 - 8.43977 8.37742 8.36413 8.40681 8.50705 8.64104 - 8.77800 8.84638 8.91192 8.92369 8.56616 8.03089 - 5.73278 4.40078 2.06170 1.52045 0.98660 0.85940 - 12.76962 12.11569 11.54810 11.02703 10.55302 10.12637 - 9.74661 9.41337 9.12662 8.88643 8.69296 8.54612 - 8.44482 8.38908 8.38123 8.41896 8.50005 8.62416 - 8.78294 8.86815 8.94647 8.96738 8.66683 8.20896 - 6.05845 4.72872 2.26430 1.64268 1.01501 0.85936 - 12.75900 12.11541 11.54850 11.02798 10.55419 10.12761 - 9.74785 9.41465 9.12806 8.88819 8.69507 8.54860 - 8.44774 8.39259 8.38555 8.42439 8.50702 8.63376 - 8.79823 8.88900 8.97724 9.01836 8.81047 8.44297 - 6.54119 5.25884 2.62464 1.89572 1.07038 0.85931 - 12.75208 12.11456 11.54881 11.02941 10.55623 10.12960 - 9.74923 9.41537 9.12857 8.88887 8.69614 8.55012 - 8.44973 8.39504 8.38846 8.42771 8.51093 8.63910 - 8.80741 8.90173 8.99564 9.04941 8.90230 8.59281 - 6.89119 5.66993 2.93700 2.11665 1.12551 0.85928 - 1.60753 1.66118 1.71392 1.76585 1.81669 1.86619 - 1.91415 1.96052 2.00534 2.04852 2.08991 2.12974 - 2.16884 2.20797 2.24704 2.28611 2.32494 2.36236 - 2.39705 2.41417 2.43465 2.45529 2.48024 2.48701 - 2.49228 2.49290 2.49349 2.49357 2.49363 2.49409 - 2.08378 2.13951 2.19426 2.24845 2.30179 2.35395 - 2.40455 2.45325 2.49975 2.54382 2.58547 2.62504 - 2.66373 2.70259 2.74159 2.78073 2.82054 2.86333 - 2.91094 2.93499 2.95551 2.96849 2.98691 2.99367 - 2.99701 2.99719 2.99771 2.99773 2.99786 3.00108 - 2.48461 2.54384 2.60116 2.65722 2.71171 2.76421 - 2.81432 2.86165 2.90589 2.94685 2.98473 3.02007 - 3.05453 3.08965 3.12561 3.16272 3.20184 3.24550 - 3.29546 3.32058 3.34027 3.35048 3.36585 3.37206 - 3.37457 3.37459 3.37505 3.37507 3.37521 3.37778 - 3.12487 3.20288 3.27227 3.33400 3.38783 3.43389 - 3.47299 3.50694 3.53821 3.56746 3.59506 3.62148 - 3.64801 3.67581 3.70512 3.73606 3.76896 3.80480 - 3.84404 3.86391 3.88161 3.89328 3.90591 3.90911 - 3.91143 3.91170 3.91195 3.91198 3.91203 3.91133 - 3.63136 3.72996 3.80790 3.86854 3.91530 3.95247 - 3.98182 4.00551 4.02642 4.04516 4.06184 4.07682 - 4.09146 4.10719 4.12456 4.14442 4.16767 4.19465 - 4.22436 4.23916 4.25351 4.26412 4.27386 4.27630 - 4.27825 4.27847 4.27864 4.27871 4.27871 4.27525 - 4.05485 4.15623 4.23887 4.30430 4.35244 4.38426 - 4.40224 4.41105 4.41678 4.42106 4.42452 4.42795 - 4.43264 4.43975 4.44908 4.45952 4.47048 4.48419 - 4.50341 4.51494 4.52597 4.53366 4.54110 4.54303 - 4.54454 4.54467 4.54480 4.54487 4.54491 4.53969 - 4.41235 4.52101 4.60666 4.67122 4.71470 4.73849 - 4.74582 4.74258 4.73624 4.72891 4.72122 4.71408 - 4.70867 4.70606 4.70584 4.70632 4.70652 4.70925 - 4.71822 4.72525 4.73248 4.73778 4.74265 4.74397 - 4.74505 4.74513 4.74520 4.74528 4.74530 4.73933 - 4.99402 5.10950 5.19516 5.25378 5.28573 5.29307 - 5.28033 5.25524 5.22747 5.19968 5.17251 5.14696 - 5.12389 5.10406 5.08667 5.06915 5.04995 5.03295 - 5.02347 5.02211 5.02150 5.02114 5.02065 5.02068 - 5.02074 5.02070 5.02068 5.02074 5.02075 5.01555 - 5.45458 5.56935 5.64926 5.69811 5.71661 5.70750 - 5.67623 5.63192 5.58568 5.54051 5.49708 5.45626 - 5.41853 5.38425 5.35227 5.31945 5.28386 5.25030 - 5.22528 5.21653 5.20830 5.20179 5.19608 5.19482 - 5.19377 5.19362 5.19351 5.19353 5.19353 5.19074 - 6.30054 6.39618 6.44872 6.46469 6.44578 6.39610 - 6.32283 6.23724 6.15279 6.07264 5.99761 5.92776 - 5.86261 5.80127 5.74207 5.68091 5.61533 5.55146 - 5.49708 5.47350 5.44875 5.42818 5.41154 5.40756 - 5.40407 5.40366 5.40337 5.40328 5.40326 5.40765 - 6.88489 6.98644 7.00682 6.96690 6.88705 6.78944 - 6.68192 6.57131 6.46531 6.36513 6.27019 6.17916 - 6.09154 6.00633 5.92323 5.84123 5.76013 5.68291 - 5.60870 5.56983 5.53122 5.50239 5.47726 5.47086 - 5.46571 5.46518 5.46474 5.46451 5.46449 5.47485 - 7.73056 7.72404 7.66469 7.56695 7.43516 7.27619 - 7.10019 6.92146 6.75521 6.60547 6.47173 6.35155 - 6.24183 6.13813 6.03814 5.93678 5.83054 5.72437 - 5.62390 5.57431 5.51961 5.47350 5.43894 5.43050 - 5.42270 5.42189 5.42133 5.42101 5.42102 5.43694 - 8.30465 8.22626 8.09457 7.92816 7.73240 7.51507 - 7.28697 7.06281 6.85773 6.67537 6.51470 6.37188 - 6.24235 6.12062 6.00414 5.88790 5.76812 5.64815 - 5.53181 5.47360 5.41051 5.35808 5.31686 5.30674 - 5.29766 5.29670 5.29600 5.29568 5.29568 5.30983 - 8.73901 8.59263 8.39502 8.16803 7.91750 7.65161 - 7.38112 7.12024 6.88383 6.67474 6.49152 6.32930 - 6.18239 6.04501 5.91440 5.78589 5.65572 5.52583 - 5.39885 5.33576 5.26959 5.21576 5.16955 5.15818 - 5.14847 5.14738 5.14652 5.14629 5.14625 5.15422 - 9.05368 8.91225 8.66282 8.35332 8.01996 7.69717 - 7.39470 7.11862 6.87508 6.65963 6.46169 6.27368 - 6.09911 5.94062 5.79541 5.65808 5.52310 5.38803 - 5.25201 5.18478 5.11829 5.06670 5.01619 5.00377 - 4.99387 4.99260 4.99165 4.99152 4.99143 4.99141 - 9.55023 9.34043 8.99238 8.57556 8.14652 7.75475 - 7.40454 7.09114 6.81021 6.55709 6.32303 6.10264 - 5.89927 5.71634 5.55059 5.39617 5.24656 5.09588 - 4.94679 4.87910 4.81422 4.76334 4.70760 4.69441 - 4.68403 4.68248 4.68138 4.68145 4.68131 4.66912 - 10.08087 9.57477 9.07881 8.61603 8.18384 7.78069 - 7.40539 7.05672 6.73415 6.43852 6.16783 5.91962 - 5.69187 5.48467 5.29766 5.13014 4.97865 4.82830 - 4.66613 4.58508 4.51450 4.46831 4.41308 4.39610 - 4.38586 4.38494 4.38346 4.38339 4.38347 4.36688 - 10.65519 9.97633 9.32987 8.73736 8.19384 7.69514 - 7.23785 6.82030 6.44113 6.09783 5.78668 5.50307 - 5.24206 5.00120 4.78154 4.58117 4.39734 4.21913 - 4.03839 3.95106 3.87306 3.81947 3.75964 3.74306 - 3.73179 3.73066 3.72933 3.72919 3.72908 3.72399 - 10.98489 10.17744 9.42472 8.74295 8.12398 7.56226 - 7.05281 6.59206 6.17802 5.80590 5.47010 5.16465 - 4.88258 4.61970 4.37711 4.15361 3.94633 3.74762 - 3.55258 3.45941 3.37337 3.31150 3.24878 3.23405 - 3.22169 3.22026 3.21920 3.21893 3.21874 3.22851 - 11.40715 10.37707 9.46264 8.65932 7.94854 7.31874 - 6.76069 6.26296 5.81637 5.41412 5.04916 4.71430 - 4.40110 4.10439 3.82555 3.56724 3.32863 3.10685 - 2.90140 2.80538 2.71198 2.64110 2.57768 2.56225 - 2.54968 2.54826 2.54709 2.54685 2.54674 2.55288 - 11.69474 10.50769 9.48733 8.60527 7.83711 7.16513 - 6.57694 6.05649 5.58921 5.16704 4.78317 4.43047 - 4.10072 3.78873 3.49485 3.22066 2.96635 2.72840 - 2.50767 2.40564 2.31017 2.24017 2.17330 2.15724 - 2.14477 2.14329 2.14200 2.14189 2.14173 2.13925 - 11.90884 10.61406 9.52497 8.59014 7.78340 7.08282 - 6.47291 5.93517 5.45237 5.01543 4.61765 4.25204 - 3.91055 3.58796 3.28422 3.00023 2.73667 2.48947 - 2.25818 2.15052 2.05017 1.97707 1.90790 1.89156 - 1.87895 1.87743 1.87611 1.87600 1.87584 1.87274 - 12.08125 10.70903 9.57367 8.60193 7.76784 7.04734 - 6.42144 5.87013 5.37491 4.92628 4.51750 4.14169 - 3.79094 3.46009 3.14887 2.85794 2.58767 2.33406 - 2.09434 1.98148 1.87554 1.79809 1.72673 1.71004 - 1.69707 1.69552 1.69417 1.69403 1.69387 1.69264 - 12.35340 10.88040 9.69025 8.67393 7.80616 7.06137 - 6.41510 5.84504 5.33178 4.86579 4.44047 4.04906 - 3.68396 3.34018 3.01718 2.71519 2.43349 2.16787 - 1.91287 1.79062 1.67458 1.58894 1.51173 1.49366 - 1.47946 1.47779 1.47634 1.47616 1.47600 1.47694 - 12.56441 11.03240 9.81516 8.77683 7.89268 7.13521 - 6.47752 5.89594 5.37078 4.89277 4.45557 4.05256 - 3.67638 3.32213 2.98906 2.67701 2.38432 2.10545 - 1.83512 1.70385 1.57842 1.48492 1.39983 1.37966 - 1.36375 1.36188 1.36029 1.36008 1.35991 1.36049 - 12.92161 11.32495 10.08984 9.03658 8.14391 7.37465 - 6.70381 6.10793 5.56802 5.07495 4.62222 4.20287 - 3.80905 3.43552 3.08161 2.74715 2.42928 2.11868 - 1.80937 1.65494 1.50257 1.38440 1.27469 1.24803 - 1.22663 1.22411 1.22205 1.22177 1.22157 1.22120 - 13.13372 11.52239 10.29848 9.25378 8.36807 7.59898 - 6.92505 6.32504 5.78159 5.28530 4.82880 4.40403 - 4.00156 3.61538 3.24551 2.89281 2.55411 2.21671 - 1.86992 1.69188 1.50863 1.36038 1.22254 1.18934 - 1.16264 1.15939 1.15661 1.15625 1.15600 1.15658 - 13.36441 11.75240 10.57015 9.56731 8.71118 7.96213 - 7.30066 6.70718 6.16541 5.66704 5.20590 4.77512 - 4.36650 3.97351 3.59270 3.21925 2.84590 2.46010 - 2.04685 1.82460 1.58616 1.38045 1.17442 1.12859 - 1.09774 1.09388 1.08814 1.08707 1.08760 1.09055 - 13.37977 11.86751 10.77684 9.83259 9.00051 8.25549 - 7.58742 6.98628 6.44375 5.95147 5.50070 5.08140 - 4.68096 4.28974 3.90384 3.51792 3.12268 2.70030 - 2.22913 1.96768 1.68289 1.43215 1.15983 1.09246 - 1.06126 1.05887 1.04988 1.04763 1.04981 1.05328 - 13.42674 11.93190 10.88714 9.98222 9.17895 8.45640 - 7.80573 7.21787 6.68527 6.20025 5.75467 5.33887 - 4.94061 4.55006 4.16257 3.77140 3.36457 2.91877 - 2.40438 2.11019 1.78135 1.48733 1.15780 1.07329 - 1.03759 1.03548 1.02438 1.02145 1.02456 1.02742 - 13.44744 11.96853 10.96570 10.09353 9.31576 8.61346 - 7.97898 7.40394 6.88147 6.40443 5.96512 5.55429 - 5.16001 4.77233 4.38599 3.99307 3.57926 3.11642 - 2.56748 2.24584 1.87906 1.54558 1.16362 1.06289 - 1.02081 1.01859 1.00593 1.00253 1.00626 1.00801 - 13.43943 11.99538 11.06715 10.25004 9.51653 8.84966 - 8.24362 7.69133 7.18709 6.72480 6.29776 5.89771 - 5.51373 5.13608 4.75824 4.36988 3.95162 3.46440 - 2.85659 2.48719 2.05602 1.65808 1.20084 1.07121 - 0.98844 0.98591 0.98693 0.98422 0.97381 0.98062 - 13.42593 12.00693 11.13193 10.35448 9.65395 9.01467 - 8.43181 7.89913 7.41166 6.96391 6.54985 6.16175 - 5.78925 5.42271 5.05498 4.67424 4.25794 3.75968 - 3.11549 2.71198 2.22937 1.77272 1.23726 1.08110 - 0.97528 0.97025 0.97061 0.96769 0.95563 0.96219 - 13.45832 12.05443 11.23792 10.50895 9.85214 9.25384 - 8.70988 8.21458 7.76329 7.35071 6.97069 6.61500 - 6.27202 5.93114 5.58553 5.22383 4.82406 4.33940 - 3.68274 3.23466 2.64499 2.04585 1.32162 1.11308 - 0.97394 0.95804 0.93948 0.93700 0.93580 0.93505 - 13.42064 12.04823 11.28146 10.59443 9.97324 9.40664 - 8.89103 8.42164 7.99442 7.60477 7.24716 6.91410 - 6.59453 6.27819 5.95785 5.62106 5.24278 4.76811 - 4.09644 3.62458 2.99010 2.31821 1.43758 1.16903 - 0.97014 0.94678 0.92619 0.92348 0.92202 0.92028 - 13.33665 12.01244 11.31465 10.68532 10.11311 9.58966 - 9.11236 8.67762 8.28246 7.92343 7.59633 7.29520 - 7.01094 6.73457 6.45872 6.16951 5.83703 5.39219 - 4.71272 4.21449 3.52748 2.76672 1.67560 1.31220 - 0.98044 0.93703 0.91092 0.90823 0.90005 0.90455 - 13.32696 12.01515 11.34353 10.73717 10.18636 9.68403 - 9.22774 8.81429 8.44097 8.10466 7.80145 7.52559 - 7.26808 7.02013 6.77523 6.52053 6.22718 5.82577 - 5.18515 4.69310 3.98328 3.15463 1.88039 1.43478 - 1.00556 0.94328 0.90036 0.89719 0.89337 0.89623 - 13.32122 12.01986 11.36375 10.77139 10.23385 9.74508 - 9.30267 8.90371 8.54565 8.22560 7.93981 7.68276 - 7.44541 7.21926 6.99861 6.77181 6.51160 6.15018 - 5.55269 5.07589 4.36179 3.49048 2.07171 1.55191 - 1.03348 0.95354 0.89386 0.88984 0.88995 0.89111 - 13.29291 12.01989 11.38547 10.80843 10.28160 9.80052 - 9.36380 8.96997 8.61794 8.30566 8.03019 7.78721 - 7.56941 7.36856 7.17544 6.97052 6.72272 6.37820 - 5.82125 5.37869 4.70543 3.83420 2.26486 1.65793 - 1.04360 0.95503 0.89908 0.89581 0.88786 0.88764 - 13.28004 12.02576 11.40497 10.84117 10.32818 9.86166 - 9.43972 9.06039 8.72212 8.42339 8.16250 7.93674 - 7.74123 7.56969 7.41318 7.25104 7.05136 6.76114 - 6.26149 5.84671 5.20064 4.33071 2.61569 1.87213 - 1.09214 0.97987 0.89876 0.89204 0.88322 0.88325 - 13.26600 12.03089 11.42048 10.86558 10.36089 9.90240 - 9.48857 9.11768 8.78843 8.49962 8.24989 8.03697 - 7.85664 7.70342 7.56964 7.43628 7.27339 7.02951 - 6.58522 6.20019 5.58345 4.72477 2.91915 2.07366 - 1.14418 1.00636 0.90021 0.89038 0.88027 0.88056 - 13.23587 12.04127 11.44776 10.90598 10.41190 9.96295 - 9.55842 9.19787 8.88096 8.60691 8.37460 8.18198 - 8.02490 7.89886 7.79900 7.71115 7.61063 7.44916 - 7.11694 6.80172 6.25139 5.43111 3.53943 2.53640 - 1.27209 1.06947 0.90783 0.89239 0.87875 0.87695 - 13.22187 12.05597 11.46104 10.92065 10.43050 9.98779 - 9.59118 9.23965 8.93198 8.66726 8.44430 8.26090 - 8.11257 7.99601 7.91154 7.85557 7.81029 7.71330 - 7.44438 7.17206 6.69215 5.93408 4.01278 2.92371 - 1.39772 1.13919 0.91860 0.89515 0.87674 0.87514 - 13.13159 12.06282 11.47471 10.94015 10.45557 10.01878 - 9.62837 9.28346 8.98316 8.72677 8.51346 8.34151 - 8.20699 8.10756 8.04532 8.01959 8.01781 7.98722 - 7.82354 7.62601 7.24221 6.58741 4.74006 3.54028 - 1.63216 1.27674 0.94354 0.90322 0.87603 0.87331 - 13.05377 12.06566 11.48079 10.94913 10.46738 10.03362 - 9.64652 9.30518 9.00888 8.75705 8.54900 8.38325 - 8.25610 8.16571 8.11521 8.10573 8.12806 8.13618 - 8.03831 7.89111 7.57772 7.00842 5.26729 4.02265 - 1.84773 1.40777 0.97043 0.91325 0.87684 0.87238 - 12.97413 12.05956 11.48545 10.95961 10.48055 10.04785 - 9.66106 9.31984 9.02422 8.77397 8.56876 8.40788 - 8.28902 8.21049 8.17210 8.16722 8.18483 8.20426 - 8.16776 8.07288 7.81824 7.30655 5.66342 4.41932 - 2.04782 1.53128 0.99802 0.92490 0.87805 0.87183 - 12.93443 12.06050 11.48775 10.96283 10.48481 10.05365 - 9.66865 9.32926 9.03533 8.78681 8.58364 8.42532 - 8.30959 8.23493 8.20161 8.20389 8.23216 8.26854 - 8.26288 8.19543 7.98608 7.53215 5.97861 4.74966 - 2.23783 1.64872 1.02594 0.93692 0.88004 0.87146 - 12.88397 12.06142 11.49058 10.96724 10.49090 10.06153 - 9.67849 9.34122 9.04953 8.80343 8.60303 8.44796 - 8.33618 8.26650 8.23983 8.25139 8.29341 8.35219 - 8.38750 8.35702 8.21279 7.84843 6.45293 5.27354 - 2.58948 1.86787 1.08174 0.96240 0.88455 0.87099 - 12.85175 12.06192 11.49246 10.97029 10.49495 10.06664 - 9.68462 9.34851 9.05818 8.81366 8.61506 8.46195 - 8.35256 8.28599 8.26344 8.28068 8.33114 8.40403 - 8.46529 8.45850 8.35879 8.06054 6.79755 5.67555 - 2.89949 2.06825 1.13673 0.98913 0.88946 0.87071 - 12.80312 12.06237 11.49485 10.97453 10.50084 10.07385 - 9.69301 9.35823 9.06970 8.82742 8.63130 8.48091 - 8.37482 8.31253 8.29565 8.32062 8.38252 8.47501 - 8.57269 8.59962 8.56634 8.37567 7.36362 6.37692 - 3.53976 2.51267 1.26980 1.05862 0.90233 0.87033 - 12.77577 12.06274 11.49610 10.97660 10.50379 10.07744 - 9.69720 9.36310 9.07545 8.83425 8.63937 8.49045 - 8.38614 8.32612 8.31219 8.34112 8.40894 8.51159 - 8.62864 8.67377 8.67631 8.54921 7.71379 6.83689 - 4.04013 2.89630 1.39682 1.12922 0.91541 0.87015 - 12.74692 12.06328 11.49725 10.97847 10.50635 10.08077 - 9.70130 9.36798 9.08118 8.84094 8.64724 8.49983 - 8.39737 8.33966 8.32873 8.36177 8.43571 8.54869 - 8.68591 8.75024 8.78979 8.73374 8.12971 7.41463 - 4.78531 3.51414 1.63244 1.26705 0.94223 0.86996 - 12.73143 12.06345 11.49777 10.97926 10.50738 10.08221 - 9.70325 9.37047 9.08415 8.84437 8.65122 8.50447 - 8.40287 8.34627 8.33686 8.37207 8.44928 8.56748 - 8.71503 8.78943 8.84802 8.83002 8.36860 7.76727 - 5.32042 3.99851 1.84762 1.39900 0.96952 0.86987 - 12.72177 12.06346 11.49798 10.97952 10.50777 10.08267 - 9.70396 9.37168 9.08613 8.84721 8.65453 8.50779 - 8.40636 8.35044 8.34183 8.37693 8.45355 8.57689 - 8.74510 8.83042 8.87330 8.82633 8.54391 8.15636 - 5.65946 4.29963 2.07284 1.55756 0.99105 0.86982 - 12.71400 12.06350 11.49839 10.98005 10.50822 10.08344 - 9.70510 9.37301 9.08730 8.84807 8.65543 8.50924 - 8.40838 8.35285 8.34498 8.38251 8.46323 8.58684 - 8.74503 8.82996 8.90823 8.92945 8.63124 8.17774 - 6.04445 4.72026 2.26591 1.64777 1.02429 0.86978 - 12.70344 12.06312 11.49890 10.98080 10.50919 10.08439 - 9.70613 9.37418 9.08872 8.84982 8.65753 8.51171 - 8.41128 8.35633 8.34926 8.38785 8.47012 8.59634 - 8.76019 8.85061 8.93864 8.97993 8.77391 8.40991 - 6.52415 5.24759 2.62432 1.89915 1.07907 0.86973 - 12.69617 12.06258 11.49930 10.98173 10.51033 10.08541 - 9.70687 9.37470 9.08926 8.85063 8.65869 8.51324 - 8.41322 8.35874 8.35218 8.39122 8.47402 8.60166 - 8.76929 8.86315 8.95678 9.01065 8.86500 8.55847 - 6.87171 5.65648 2.93522 2.11890 1.13369 0.86970 - 1.56259 1.61438 1.66591 1.71732 1.76831 1.81856 - 1.86771 1.91537 1.96120 2.00498 2.04653 2.08615 - 2.12482 2.16339 2.20160 2.23908 2.27569 2.31246 - 2.35044 2.36981 2.38985 2.40740 2.43185 2.43997 - 2.44484 2.44526 2.44591 2.44596 2.44616 2.44607 - 2.03029 2.08610 2.14103 2.19550 2.24920 2.30180 - 2.35295 2.40227 2.44945 2.49426 2.53667 2.57698 - 2.61633 2.65569 2.69497 2.73412 2.77363 2.81582 - 2.86265 2.88631 2.90664 2.91972 2.93824 2.94500 - 2.94839 2.94856 2.94907 2.94914 2.94927 2.94921 - 2.42425 2.48428 2.54250 2.59954 2.65505 2.70862 - 2.75984 2.80830 2.85367 2.89574 2.93468 2.97099 - 3.00632 3.04214 3.07862 3.11598 3.15506 3.19839 - 3.24784 3.27269 3.29230 3.30268 3.31828 3.32455 - 3.32712 3.32713 3.32759 3.32765 3.32779 3.32771 - 3.05712 3.13543 3.20578 3.26901 3.32484 3.37330 - 3.41499 3.45145 3.48485 3.51576 3.54459 3.57198 - 3.59950 3.62857 3.65926 3.69138 3.72490 3.76086 - 3.79990 3.81968 3.83763 3.84982 3.86271 3.86596 - 3.86836 3.86864 3.86891 3.86893 3.86898 3.86897 - 3.55818 3.65782 3.73778 3.80109 3.85071 3.89057 - 3.92234 3.94826 3.97132 3.99217 4.01098 4.02812 - 4.04477 4.06223 4.08106 4.10226 4.12673 4.15432 - 4.18415 4.19938 4.21431 4.22541 4.23548 4.23800 - 4.24002 4.24027 4.24047 4.24049 4.24050 4.24052 - 3.96774 4.09421 4.18278 4.24092 4.27882 4.30808 - 4.33114 4.34894 4.36288 4.37324 4.38035 4.38511 - 4.38982 4.39665 4.40595 4.41767 4.43173 4.44820 - 4.46775 4.47913 4.49079 4.49965 4.50728 4.50926 - 4.51084 4.51104 4.51120 4.51121 4.51122 4.51124 - 4.33391 4.44651 4.53582 4.60358 4.64980 4.67589 - 4.68532 4.68422 4.68046 4.67616 4.67184 4.66814 - 4.66583 4.66563 4.66720 4.66925 4.67113 4.67549 - 4.68584 4.69353 4.70159 4.70765 4.71291 4.71430 - 4.71546 4.71558 4.71569 4.71571 4.71572 4.71575 - 4.91619 5.03626 5.12603 5.18801 5.22263 5.23207 - 5.22115 5.19804 5.17298 5.14863 5.12550 5.10413 - 5.08475 5.06759 5.05204 5.03623 5.01920 5.00456 - 4.99725 4.99690 4.99731 4.99770 4.99772 4.99784 - 4.99797 4.99797 4.99799 4.99800 4.99800 4.99802 - 5.37980 5.49897 5.58282 5.63488 5.65592 5.64882 - 5.61933 5.57704 5.53364 5.49212 5.45295 5.41655 - 5.38267 5.35111 5.32101 5.29002 5.25697 5.22630 - 5.20403 5.19655 5.18944 5.18367 5.17854 5.17739 - 5.17644 5.17631 5.17621 5.17622 5.17622 5.17624 - 6.23537 6.33376 6.38914 6.40773 6.39127 6.34392 - 6.27303 6.19009 6.10883 6.03241 5.96145 5.89564 - 5.83399 5.77520 5.71790 5.65882 5.59620 5.53584 - 5.48508 5.46318 5.43976 5.41987 5.40394 5.40012 - 5.39673 5.39631 5.39600 5.39594 5.39595 5.39596 - 6.84208 6.90813 6.92700 6.90761 6.85255 6.76702 - 6.65939 6.54218 6.42991 6.32594 6.23074 6.14333 - 6.06213 5.98478 5.90955 5.83233 5.75075 5.67092 - 5.60020 5.56746 5.53130 5.50028 5.47655 5.47078 - 5.46551 5.46489 5.46443 5.46432 5.46434 5.46430 - 7.68110 7.67421 7.61663 7.52211 7.39472 7.24096 - 7.07050 6.89699 6.73502 6.58852 6.45714 6.33871 - 6.23064 6.12882 6.03096 5.93187 5.82802 5.72475 - 5.62803 5.58055 5.52763 5.48248 5.44861 5.44026 - 5.43258 5.43169 5.43105 5.43087 5.43091 5.43079 - 8.25836 8.18020 8.05134 7.88938 7.69937 7.48856 - 7.26712 7.04894 6.84837 6.66901 6.51015 6.36843 - 6.24004 6.12007 6.00583 5.89183 5.77395 5.65621 - 5.54315 5.48692 5.42565 5.37431 5.33370 5.32364 - 5.31467 5.31363 5.31285 5.31266 5.31268 5.31254 - 8.69331 8.54922 8.35627 8.13511 7.89126 7.63241 - 7.36880 7.11390 6.88192 6.67576 6.49426 6.33310 - 6.18736 6.05178 5.92345 5.79708 5.66848 5.54034 - 5.41611 5.35477 5.29027 5.23752 5.19188 5.18058 - 5.17096 5.16982 5.16892 5.16876 5.16873 5.16864 - 9.03927 8.83472 8.58418 8.31081 8.02020 7.72030 - 7.42110 7.13535 6.87691 6.64821 6.44730 6.26922 - 6.10795 5.95829 5.81712 5.67972 5.54216 5.40583 - 5.27344 5.20905 5.14411 5.09243 5.04286 5.03057 - 5.02065 5.01946 5.01846 5.01833 5.01825 5.01822 - 9.50565 9.30216 8.96416 8.55806 8.13832 7.75299 - 7.40702 7.09675 6.81894 6.56904 6.33803 6.12041 - 5.91948 5.73866 5.57474 5.42196 5.27384 5.12432 - 4.97644 4.90974 4.84587 4.79569 4.74045 4.72734 - 4.71698 4.71556 4.71453 4.71441 4.71428 4.71436 - 10.03959 9.54363 9.05781 8.60376 8.17912 7.78247 - 7.41264 7.06858 6.74984 6.45730 6.18913 5.94300 - 5.71715 5.51179 5.32658 5.16085 5.01112 4.86229 - 4.70113 4.62044 4.55027 4.50452 4.44974 4.43281 - 4.42256 4.42180 4.42041 4.42009 4.42021 4.42021 - 10.63034 9.95958 9.32151 8.73614 8.19876 7.70536 - 7.25261 6.83897 6.46310 6.12262 5.81388 5.53243 - 5.27345 5.03455 4.81675 4.61820 4.43608 4.25918 - 4.07897 3.99161 3.91353 3.85990 3.79998 3.78335 - 3.77202 3.77093 3.76962 3.76940 3.76931 3.76932 - 10.97491 10.17257 9.42581 8.74911 8.13462 7.57684 - 7.07091 6.61331 6.20205 5.83242 5.49891 5.19561 - 4.91556 4.65455 4.41368 4.19175 3.98592 3.78835 - 3.59390 3.50074 3.41453 3.35232 3.28905 3.27415 - 3.26168 3.26015 3.25903 3.25889 3.25869 3.25861 - 11.40054 10.37816 9.47054 8.67198 7.96466 7.33736 - 6.78125 6.28533 5.84074 5.44069 5.07801 4.74531 - 4.43380 4.13817 3.86000 3.60238 3.36483 3.14420 - 2.93968 2.84394 2.75051 2.67924 2.61503 2.59933 - 2.58656 2.58507 2.58385 2.58366 2.58356 2.58338 - 11.69080 10.50706 9.49155 8.61408 7.85038 7.18258 - 6.59805 6.08053 5.61532 5.19446 4.81141 4.45927 - 4.13013 3.81892 3.52593 3.25253 2.99886 2.76161 - 2.54178 2.44023 2.34504 2.27497 2.20743 2.19113 - 2.17846 2.17696 2.17567 2.17553 2.17536 2.17533 - 11.90608 10.61227 9.52694 8.59655 7.79472 7.09907 - 6.49355 5.95918 5.47826 5.04201 4.64419 4.27827 - 3.93684 3.61495 3.31227 3.02915 2.76596 2.51914 - 2.28867 2.18157 2.08171 2.00881 1.93927 1.92276 - 1.91002 1.90851 1.90718 1.90705 1.90687 1.90699 - 12.07889 10.70698 9.57471 8.60723 7.77805 7.06251 - 6.44107 5.89306 5.39952 4.95123 4.54200 4.16553 - 3.81463 3.48448 3.17440 2.88434 2.61433 2.36093 - 2.12198 2.00972 1.90440 1.82733 1.75583 1.73906 - 1.72602 1.72447 1.72311 1.72296 1.72280 1.72298 - 12.34740 10.87696 9.69057 8.67849 7.81512 7.07447 - 6.43177 5.86430 5.35232 4.88660 4.46092 4.06905 - 3.70396 3.36088 3.03894 2.73776 2.45635 2.19097 - 1.93675 1.81511 1.69978 1.61466 1.53749 1.51939 - 1.50517 1.50349 1.50204 1.50186 1.50170 1.50175 - 12.55081 11.02625 9.81482 8.78117 7.90080 7.14627 - 6.49087 5.91093 5.38678 4.90937 4.47248 4.06972 - 3.69398 3.34042 3.00818 2.69681 2.40459 2.12623 - 1.85676 1.72609 1.60134 1.50836 1.42330 1.40307 - 1.38714 1.38526 1.38366 1.38346 1.38329 1.38307 - 12.88543 11.30739 10.08345 9.03711 8.14818 7.38067 - 6.71049 6.11505 5.57600 5.08422 4.63301 4.21517 - 3.82255 3.44977 3.09637 2.76249 2.44545 2.13585 - 1.82755 1.67366 1.52186 1.40415 1.29461 1.26796 - 1.24657 1.24406 1.24200 1.24172 1.24151 1.24131 - 13.07857 11.49169 10.28250 9.24718 8.36666 7.60025 - 6.92752 6.32823 5.78586 5.29103 4.83617 4.41303 - 4.01189 3.62659 3.25736 2.90538 2.56765 2.23135 - 1.88558 1.70800 1.52522 1.37743 1.24031 1.20733 - 1.18079 1.17756 1.17480 1.17445 1.17419 1.17475 - 13.28962 11.70425 10.53849 9.54732 8.69907 7.95537 - 7.29748 6.70643 6.16645 5.66945 5.20938 4.77953 - 4.37184 3.97989 3.60020 3.22793 2.85573 2.47095 - 2.05851 1.83660 1.59855 1.39345 1.18915 1.14421 - 1.11402 1.11018 1.10446 1.10341 1.10391 1.10613 - 13.29646 11.81036 10.73593 9.80391 8.98109 8.24312 - 7.58026 6.98284 6.44283 5.95212 5.50223 5.08340 - 4.68342 4.29285 3.90782 3.52297 3.12894 2.70776 - 2.23765 1.97670 1.69246 1.44250 1.17253 1.10645 - 1.07645 1.07414 1.06512 1.06289 1.06503 1.06734 - 13.33951 11.87168 10.84290 9.95007 9.15613 8.44075 - 7.79543 7.21141 6.68145 6.19810 5.75346 5.33819 - 4.94042 4.55059 4.16404 3.77402 3.36848 2.92394 - 2.41064 2.11701 1.78886 1.49582 1.16915 1.08616 - 1.05202 1.05004 1.03885 1.03593 1.03901 1.04056 - 13.35981 11.90785 10.92008 10.05945 9.29062 8.59529 - 7.96605 7.39485 6.87504 6.39971 5.96142 5.55123 - 5.15753 4.77067 4.38536 3.99370 3.58129 3.11977 - 2.57201 2.25100 1.88507 1.55275 1.17399 1.07491 - 1.03465 1.03260 1.01982 1.01640 1.02011 1.02055 - 13.35574 11.93708 11.02138 10.21411 9.48840 8.82773 - 8.22649 7.67781 7.17622 6.71576 6.28994 5.89077 - 5.50761 5.13094 4.75427 4.36725 3.95048 3.46475 - 2.85845 2.48997 2.06015 1.66387 1.21000 1.08197 - 1.00117 0.99895 1.00006 0.99734 0.98689 0.99243 - 13.34710 11.95182 11.08712 10.31793 9.62408 8.99018 - 8.41159 7.88222 7.39726 6.95136 6.53862 6.15159 - 5.78011 5.41474 5.04837 4.66916 4.25454 3.75795 - 3.11548 2.71307 2.23205 1.77737 1.24560 1.09109 - 0.98737 0.98270 0.98320 0.98025 0.96808 0.97358 - 13.38873 12.00569 11.19591 10.47238 9.82000 9.22547 - 8.68463 8.19187 7.74265 7.33176 6.95314 6.59873 - 6.25707 5.91771 5.57386 5.21422 4.81678 4.33464 - 3.68053 3.23361 2.64504 2.04757 1.32832 1.12206 - 0.98554 0.96982 0.95104 0.94861 0.94719 0.94594 - 13.35661 12.00330 11.24106 10.55772 9.93966 9.37584 - 8.86267 8.39536 7.96997 7.58193 7.22577 6.89410 - 6.57599 6.26128 5.94279 5.60814 5.23233 4.76054 - 4.09204 3.62178 2.98883 2.31897 1.44345 1.17711 - 0.98121 0.95812 0.93729 0.93459 0.93298 0.93095 - 13.27623 11.97024 11.27511 10.64823 10.07799 9.55643 - 9.08083 8.64765 8.25394 7.89626 7.57046 7.27066 - 6.98786 6.71312 6.43918 6.15220 5.82234 5.38041 - 4.70436 4.20827 3.52406 2.76665 1.68106 1.31949 - 0.99032 0.94749 0.92185 0.91907 0.91048 0.91501 - 13.26655 11.97299 11.30357 10.69929 10.15018 9.64944 - 9.19458 8.78247 8.41038 8.07524 7.77315 7.49845 - 7.24222 6.99580 6.75271 6.50019 6.20948 5.81121 - 5.17438 4.68473 3.97802 3.15303 1.88500 1.44145 - 1.01504 0.95339 0.91106 0.90783 0.90358 0.90661 - 13.25982 11.97697 11.32317 10.73275 10.19693 9.70970 - 9.26866 8.87092 8.51397 8.19492 7.91011 7.65400 - 7.41778 7.19299 6.97402 6.74927 6.49162 6.13339 - 5.53989 5.06567 4.35489 3.48750 2.07549 1.55807 - 1.04268 0.96341 0.90441 0.90037 0.90005 0.90143 - 13.23163 11.97659 11.34428 10.76904 10.24385 9.76432 - 9.32903 8.93648 8.58559 8.27430 7.99973 7.75761 - 7.54073 7.34095 7.14917 6.94597 6.70052 6.35931 - 5.80711 5.36760 4.69793 3.83025 2.26697 1.66310 - 1.05281 0.96489 0.90942 0.90614 0.89816 0.89793 - 13.21601 11.98160 11.36402 10.80266 10.29137 9.82609 - 9.40501 9.02633 8.68870 8.39066 8.13051 7.90557 - 7.71104 7.54069 7.38551 7.22473 7.02660 6.73897 - 6.24407 5.83270 5.19078 4.32487 2.61633 1.87638 - 1.10082 0.98933 0.90905 0.90238 0.89346 0.89350 - 13.20298 11.98731 11.38003 10.82735 10.32418 9.86686 - 9.45379 9.08348 8.75481 8.46662 8.21756 8.00539 - 7.82591 7.67367 7.54093 7.40862 7.24686 7.00512 - 6.56528 6.18368 5.57136 4.71718 2.91865 2.07699 - 1.15237 1.01548 0.91045 0.90075 0.89046 0.89079 - 13.17875 12.00052 11.40841 10.86788 10.37484 9.92699 - 9.52342 9.16379 8.84774 8.57453 8.34292 8.15089 - 7.99426 7.86848 7.76879 7.68125 7.58148 7.42158 - 7.09268 6.78039 6.23465 5.41998 3.53687 2.53759 - 1.27920 1.07795 0.91804 0.90267 0.88899 0.88714 - 13.14855 12.00989 11.42375 10.88821 10.40004 9.95719 - 9.55921 9.20612 8.89775 8.63319 8.41095 8.22913 - 8.08469 7.97430 7.89432 7.83227 7.76774 7.66329 - 7.41802 7.15682 6.66952 5.90896 4.02731 2.91526 - 1.40129 1.14909 0.92898 0.90575 0.88625 0.88532 - 13.05831 12.01400 11.43517 10.90667 10.42531 9.98962 - 9.59879 9.25274 8.95130 8.69423 8.48102 8.31060 - 8.17999 8.08652 8.02842 7.99660 7.97475 7.92963 - 7.78071 7.59985 7.22812 6.58622 4.74066 3.51119 - 1.63905 1.29099 0.95415 0.90935 0.88658 0.88347 - 12.97894 12.01498 11.44057 10.91569 10.43775 10.00526 - 9.61773 9.27511 8.97755 8.72491 8.51682 8.35248 - 8.22913 8.14458 8.09815 8.08254 8.08462 8.07753 - 7.99327 7.86244 7.56146 7.00517 5.26697 3.99171 - 1.85186 1.42133 0.98105 0.91865 0.88878 0.88254 - 12.92255 12.01750 11.44535 10.92138 10.44404 10.01274 - 9.62712 9.28710 8.99287 8.74387 8.53894 8.37724 - 8.25752 8.17889 8.14097 8.13662 8.15466 8.17591 - 8.13524 8.03221 7.78084 7.30289 5.68265 4.37323 - 2.04688 1.54691 1.00813 0.92792 0.89391 0.88199 - 12.88143 12.01836 11.44846 10.92541 10.44872 10.01870 - 9.63469 9.29624 9.00325 8.75558 8.55305 8.39502 - 8.27941 8.20472 8.17120 8.17309 8.20077 8.23648 - 8.23050 8.16343 7.95561 7.50560 5.96459 4.74171 - 2.23998 1.65392 1.03503 0.94683 0.89013 0.88161 - 12.83153 12.01931 11.45151 10.93004 10.45482 10.02654 - 9.64452 9.30826 9.01756 8.77237 8.57264 8.41790 - 8.30624 8.23655 8.20966 8.22083 8.26220 8.32015 - 8.35477 8.32428 8.18081 7.81929 6.43565 5.26302 - 2.59010 1.87224 1.09036 0.97196 0.89467 0.88114 - 12.80088 12.01991 11.45329 10.93290 10.45889 10.03168 - 9.65078 9.31571 9.02638 8.78274 8.58475 8.43201 - 8.32278 8.25618 8.23344 8.25031 8.30014 8.37213 - 8.43247 8.42542 8.32600 8.02979 6.77763 5.66286 - 2.89888 2.07190 1.14491 0.99834 0.89960 0.88086 - 12.75516 12.02069 11.45530 10.93675 10.46460 10.03900 - 9.65948 9.32585 9.03824 8.79668 8.60109 8.45113 - 8.34529 8.28304 8.26598 8.29056 8.35185 8.44346 - 8.54005 8.56643 8.53273 8.34274 7.33892 6.36001 - 3.53672 2.51459 1.27700 1.06708 0.91250 0.88048 - 12.72896 12.02106 11.45655 10.93882 10.46746 10.04263 - 9.66377 9.33085 9.04407 8.80353 8.60919 8.46072 - 8.35672 8.29678 8.28270 8.31126 8.37850 8.48032 - 8.59627 8.64074 8.64255 8.51542 7.68613 6.81679 - 4.03522 2.89651 1.40323 1.13705 0.92555 0.88029 - 12.70071 12.02142 11.45750 10.94040 10.46972 10.04565 - 9.66772 9.33593 9.05055 8.81134 8.61769 8.46947 - 8.36671 8.31006 8.30064 8.33329 8.40348 8.51329 - 8.65919 8.73127 8.75506 8.65580 8.10141 7.50229 - 4.73834 3.45534 1.64004 1.29184 0.95196 0.88011 - 12.70694 12.02869 11.45693 10.93640 10.46546 10.04239 - 9.66636 9.33665 9.05294 8.81510 8.62296 8.47569 - 8.37071 8.30794 8.29364 8.33448 8.43181 8.56147 - 8.69091 8.75221 8.80421 8.79128 8.34640 7.73448 - 5.30479 3.99722 1.85198 1.40560 0.97846 0.88002 - 12.69694 12.02841 11.45704 10.93695 10.46614 10.04342 - 9.66764 9.33819 9.05475 8.81719 8.62538 8.47852 - 8.37406 8.31199 8.29866 8.34089 8.44026 8.57308 - 8.70866 8.77623 8.84082 8.85190 8.49777 7.97172 - 5.70825 4.38739 2.06744 1.53136 1.00555 0.87996 - 12.68995 12.02825 11.45715 10.93729 10.46670 10.04414 - 9.66853 9.33925 9.05599 8.81863 8.62704 8.48045 - 8.37635 8.31474 8.30204 8.34518 8.44593 8.58092 - 8.72074 8.79249 8.86545 8.89284 8.60422 8.14283 - 6.02721 4.71451 2.26782 1.65344 1.03272 0.87993 - 12.65873 12.02157 11.45936 10.94304 10.47307 10.04972 - 9.67269 9.34186 9.05739 8.81934 8.62768 8.48224 - 8.38205 8.32724 8.32018 8.35855 8.44038 8.56596 - 8.72890 8.81871 8.90601 8.94641 8.73899 8.37732 - 6.50731 5.23660 2.62411 1.90257 1.08758 0.87988 - 12.65521 12.02133 11.45897 10.94347 10.47431 10.05117 - 9.67389 9.34264 9.05799 8.82002 8.62867 8.48371 - 8.38405 8.32972 8.32308 8.36192 8.44434 8.57138 - 8.73815 8.83151 8.92438 8.97729 8.83023 8.52513 - 6.85233 5.64318 2.93359 2.12124 1.14171 0.87985 - 1.51706 1.56847 1.61973 1.67095 1.72186 1.77214 - 1.82142 1.86934 1.91554 1.95978 2.00186 2.04202 - 2.08116 2.12006 2.15839 2.19572 2.23187 2.26791 - 2.30500 2.32395 2.34373 2.36122 2.38535 2.39326 - 2.39808 2.39851 2.39915 2.39920 2.39939 2.39978 - 1.97893 2.03545 2.09110 2.14623 2.20054 2.25368 - 2.30526 2.35491 2.40228 2.44718 2.48955 2.52977 - 2.56909 2.60860 2.64821 2.68786 2.72788 2.77015 - 2.81603 2.83888 2.85862 2.87152 2.88986 2.89651 - 2.89981 2.90000 2.90051 2.90052 2.90068 2.90431 - 2.36472 2.43104 2.49354 2.55276 2.60843 2.66042 - 2.70889 2.75445 2.79809 2.83996 2.88016 2.91888 - 2.95703 2.99547 3.03438 3.07423 3.11546 3.15798 - 3.20102 3.22197 3.24185 3.25649 3.27193 3.27620 - 3.27934 3.27969 3.28000 3.28000 3.28002 3.28309 - 2.99296 3.07426 3.14706 3.21213 3.26917 3.31830 - 3.36032 3.39707 3.43114 3.46320 3.49360 3.52286 - 3.55232 3.58314 3.61526 3.64821 3.68185 3.71756 - 3.75649 3.77629 3.79431 3.80657 3.81954 3.82280 - 3.82523 3.82551 3.82577 3.82580 3.82585 3.82518 - 3.49412 3.59103 3.67124 3.73684 3.78944 3.83145 - 3.86465 3.89180 3.91659 3.93972 3.96103 3.98060 - 3.99944 4.01871 4.03896 4.06124 4.08652 4.11454 - 4.14466 4.16020 4.17552 4.18697 4.19734 4.19997 - 4.20208 4.20230 4.20249 4.20258 4.20258 4.19880 - 3.90121 4.02594 4.11362 4.17188 4.21126 4.24355 - 4.27063 4.29247 4.30934 4.32180 4.33123 4.33905 - 4.34667 4.35549 4.36598 4.37869 4.39410 4.41196 - 4.43240 4.44397 4.45613 4.46579 4.47407 4.47603 - 4.47777 4.47794 4.47811 4.47826 4.47823 4.47249 - 4.26823 4.37631 4.46327 4.53077 4.57877 4.60840 - 4.62257 4.62663 4.62750 4.62700 4.62570 4.62437 - 4.62405 4.62571 4.62905 4.63282 4.63639 4.64227 - 4.65385 4.66211 4.67100 4.67795 4.68388 4.68546 - 4.68682 4.68692 4.68701 4.68711 4.68713 4.68053 - 4.85128 4.96459 5.05063 5.11189 5.14862 5.16261 - 5.15789 5.14147 5.12220 5.10241 5.08267 5.06376 - 5.04632 5.03104 5.01738 5.00368 4.98904 4.97673 - 4.97128 4.97176 4.97328 4.97482 4.97578 4.97616 - 4.97656 4.97656 4.97657 4.97664 4.97664 4.97094 - 5.31558 5.42767 5.50777 5.55928 5.58276 5.58067 - 5.55790 5.52274 5.48546 5.44870 5.41303 5.37910 - 5.34718 5.31753 5.28944 5.26083 5.23064 5.20285 - 5.18291 5.17645 5.17063 5.16614 5.16214 5.16131 - 5.16064 5.16052 5.16044 5.16047 5.16046 5.15747 - 6.17201 6.26641 6.32051 6.34024 6.32712 6.28491 - 6.22027 6.14374 6.06794 5.99585 5.92814 5.86477 - 5.80513 5.74832 5.69319 5.63680 5.57758 5.52077 - 5.47303 5.45245 5.43045 5.41187 5.39744 5.39401 - 5.39091 5.39057 5.39031 5.39021 5.39021 5.39509 - 6.77880 6.84579 6.86703 6.85101 6.80019 6.71949 - 6.61694 6.50465 6.39662 6.29618 6.20384 6.11875 - 6.03955 5.96416 5.89104 5.81647 5.73830 5.66213 - 5.59468 5.56338 5.52864 5.49884 5.47682 5.47149 - 5.46652 5.46601 5.46566 5.46543 5.46545 5.47662 - 7.61808 7.62107 7.57230 7.48495 7.36314 7.21353 - 7.04609 6.87493 6.71517 6.57089 6.44169 6.32540 - 6.21928 6.11929 6.02328 5.92643 5.82546 5.72543 - 5.63195 5.58597 5.53432 5.49013 5.45814 5.45031 - 5.44295 5.44219 5.44167 5.44134 5.44137 5.45806 - 8.19751 8.13424 8.01770 7.86493 7.68114 7.47409 - 7.25460 7.03750 6.83823 6.66052 6.50359 6.36399 - 6.23764 6.11950 6.00698 5.89487 5.77928 5.66421 - 5.55411 5.49935 5.43923 5.38868 5.34982 5.34026 - 5.33159 5.33067 5.33000 5.32969 5.32970 5.34435 - 8.63678 8.50884 8.32905 8.11750 7.88002 7.62488 - 7.36306 7.10910 6.87834 6.67386 6.49439 6.33553 - 6.19201 6.05842 5.93187 5.80721 5.68042 5.55439 - 5.43280 5.37284 5.30944 5.25737 5.21319 5.20231 - 5.19293 5.19188 5.19106 5.19081 5.19079 5.19900 - 8.96636 8.82813 8.59550 8.30844 7.99559 7.68540 - 7.38905 7.11619 6.87656 6.66617 6.47384 6.29142 - 6.12179 5.96716 5.82504 5.69057 5.55881 5.42746 - 5.29587 5.23115 5.16716 5.11740 5.06844 5.05639 - 5.04677 5.04552 5.04460 5.04447 5.04438 5.04436 - 9.46908 9.27089 8.94059 8.54245 8.12989 7.75011 - 7.40822 7.10086 6.82521 6.57741 6.34952 6.13620 - 5.93915 5.76065 5.59787 5.44602 5.29936 5.15139 - 5.00505 4.93943 4.87664 4.82716 4.77228 4.75927 - 4.74903 4.74749 4.74640 4.74646 4.74632 4.73381 - 10.00845 9.51767 9.03780 8.58937 8.17004 7.77840 - 7.41340 7.07392 6.75953 6.47108 6.20671 5.96409 - 5.74133 5.53852 5.35535 5.19119 5.04259 4.89466 - 4.73444 4.65438 4.58521 4.54047 4.48578 4.46846 - 4.45837 4.45749 4.45598 4.45590 4.45599 4.43891 - 10.60600 9.93896 9.30596 8.72563 8.19331 7.70497 - 7.25731 6.84871 6.47781 6.14212 5.83797 5.56074 - 5.30535 5.06913 4.85312 4.65554 4.47374 4.29698 - 4.11733 4.03053 3.95329 3.90041 3.84024 3.82310 - 3.81181 3.81072 3.80935 3.80920 3.80907 3.80375 - 10.95195 10.15492 9.41445 8.74364 8.13473 7.58228 - 7.08143 6.62867 6.22195 5.85657 5.52699 5.22721 - 4.95004 4.69109 4.45146 4.23007 4.02430 3.82685 - 3.63312 3.54055 3.45485 3.39290 3.32940 3.31423 - 3.30170 3.30027 3.29918 3.29891 3.29869 3.30870 - 11.38297 10.36733 9.46721 8.67532 7.97410 7.35229 - 6.80093 6.30894 5.86732 5.46942 5.10826 4.77667 - 4.46607 4.17125 3.89390 3.63711 3.40049 3.18074 - 2.97688 2.88136 2.78801 2.71667 2.65234 2.63658 - 2.62373 2.62228 2.62108 2.62083 2.62072 2.62704 - 11.66064 10.50047 9.50093 8.63288 7.87396 7.20778 - 6.62297 6.10466 5.63927 5.21903 4.83717 4.48658 - 4.15902 3.84916 3.55724 3.28455 3.03128 2.79448 - 2.57541 2.47426 2.37921 2.30896 2.24117 2.22479 - 2.21204 2.21052 2.20920 2.20909 2.20892 2.20635 - 11.86775 10.60695 9.54222 8.62270 7.82491 7.12883 - 6.52043 5.98284 5.50016 5.06370 4.66683 4.30257 - 3.96292 3.64250 3.34089 3.05836 2.79531 2.54879 - 2.31923 2.21267 2.11299 2.03984 1.96986 1.95321 - 1.94034 1.93880 1.93744 1.93733 1.93716 1.93395 - 12.03658 10.70113 9.59103 8.63487 7.80949 7.09284 - 6.46772 5.91574 5.41990 4.97108 4.56263 4.18771 - 3.83850 3.50972 3.20062 2.91103 2.64108 2.38797 - 2.15005 2.03841 1.93332 1.85599 1.78395 1.76698 - 1.75378 1.75219 1.75081 1.75068 1.75051 1.74925 - 12.30704 10.86827 9.70097 8.69909 7.83967 7.09887 - 6.45382 5.88366 5.37017 4.90418 4.47918 4.08849 - 3.72465 3.38256 3.06131 2.76047 2.47919 2.21422 - 1.96113 1.84018 1.72522 1.64002 1.56239 1.54411 - 1.52974 1.52804 1.52657 1.52639 1.52622 1.52720 - 12.51842 11.01402 9.81519 8.78943 7.91345 7.16089 - 6.50603 5.92613 5.40224 4.92535 4.48921 4.08731 - 3.71236 3.35943 3.02766 2.71663 2.42469 2.14690 - 1.87855 1.74858 1.62438 1.53162 1.44635 1.42603 - 1.41000 1.40812 1.40650 1.40630 1.40612 1.40673 - 12.86617 11.29082 10.06945 9.02689 8.14230 7.37939 - 6.71368 6.12208 5.58585 5.09594 4.64586 4.22870 - 3.83655 3.46420 3.11123 2.77777 2.46126 2.15247 - 1.84539 1.69225 1.54121 1.42405 1.31471 1.28806 - 1.26668 1.26417 1.26211 1.26183 1.26162 1.26126 - 13.05874 11.47633 10.26944 9.23706 8.35971 7.59672 - 6.92739 6.33115 5.79119 5.29817 4.84469 4.42261 - 4.02240 3.63795 3.26945 2.91805 2.58085 2.24543 - 1.90116 1.72444 1.54244 1.39511 1.25821 1.22527 - 1.19875 1.19552 1.19276 1.19241 1.19215 1.19277 - 13.25889 11.69240 10.53548 9.54878 8.70201 7.95815 - 7.29927 6.70725 6.16709 5.67070 5.21180 4.78343 - 4.37725 3.98662 3.60809 3.23680 2.86559 2.48207 - 2.07135 1.85035 1.61307 1.40840 1.20431 1.15946 - 1.12945 1.12564 1.11991 1.11884 1.11934 1.12215 - 13.27337 11.80105 10.73213 9.80356 8.98283 8.24612 - 7.58384 6.98650 6.44620 5.95498 5.50453 5.08523 - 4.68516 4.29502 3.91096 3.52761 3.13555 2.71664 - 2.24880 1.98887 1.70538 1.45578 1.18608 1.12017 - 1.09061 1.08838 1.07932 1.07704 1.07919 1.08225 - 13.31188 11.86039 10.83829 9.94966 9.15823 8.44421 - 7.79932 7.21504 6.68428 6.19979 5.75389 5.33753 - 4.93918 4.54954 4.16400 3.77574 3.37263 2.93087 - 2.42030 2.12786 1.80057 1.50789 1.18156 1.09884 - 1.06543 1.06357 1.05230 1.04932 1.05241 1.05472 - 13.32692 11.89349 10.91321 10.05732 9.29145 8.59773 - 7.96899 7.39742 6.87658 6.39980 5.95989 5.54824 - 5.15369 4.76693 4.38271 3.99305 3.58344 3.12512 - 2.58042 2.26073 1.89575 1.56384 1.18554 1.08684 - 1.04758 1.04568 1.03277 1.02929 1.03302 1.03414 - 13.31316 11.91578 11.00850 10.20697 9.48494 8.82642 - 8.22601 7.67711 7.17445 6.71236 6.28467 5.88375 - 5.49954 5.12294 4.74753 4.36287 3.94945 3.46749 - 2.86473 2.49779 2.06915 1.67350 1.22046 1.09294 - 1.01326 1.01130 1.01251 1.00972 0.99919 1.00524 - 13.29669 11.92435 11.06862 10.30571 9.61609 8.98476 - 8.40732 7.87796 7.39208 6.94464 6.53003 6.14123 - 5.76871 5.40352 5.03856 4.66201 4.25111 3.75870 - 3.12010 2.71935 2.23968 1.78585 1.25522 1.10136 - 0.99901 0.99468 0.99531 0.99229 0.97998 0.98588 - 13.32752 11.96904 11.16830 10.45137 9.80359 9.21200 - 8.67265 8.18023 7.73035 7.31811 6.93775 6.58170 - 6.23919 5.90034 5.55843 5.20219 4.80951 4.33280 - 3.68365 3.23835 2.65005 2.05259 1.33598 1.13134 - 0.99697 0.98144 0.96246 0.96004 0.95846 0.95750 - 13.29199 11.96238 11.20824 10.53088 9.91710 9.35617 - 8.84469 8.37805 7.95248 7.56362 7.20629 6.87347 - 6.55487 6.24078 5.92421 5.59287 5.22181 4.75584 - 4.09321 3.62494 2.99225 2.32226 1.45003 1.18557 - 0.99224 0.96944 0.94842 0.94568 0.94395 0.94212 - 13.21053 11.92654 11.23772 10.61549 10.04883 9.52979 - 9.05587 8.62363 8.23024 7.87241 7.54620 7.24600 - 6.96331 6.68957 6.41763 6.13372 5.80802 5.37092 - 4.69983 4.20612 3.52417 2.76888 1.68713 1.32697 - 1.00025 0.95803 0.93288 0.93001 0.92098 0.92578 - 13.20388 11.93055 11.26561 10.66463 10.11819 9.61943 - 9.16596 8.75477 8.38320 8.04827 7.74619 7.47156 - 7.21576 6.97040 6.72916 6.47933 6.19221 5.79825 - 5.16620 4.67911 3.97511 3.15295 1.89001 1.44829 - 1.02461 0.96361 0.92187 0.91857 0.91385 0.91717 - 13.18455 11.93543 11.29385 10.70989 10.17614 9.68752 - 9.24288 8.84065 8.47985 8.15811 7.87221 7.61736 - 7.38582 7.16883 6.95687 6.73036 6.45865 6.08944 - 5.50965 5.05774 4.38109 3.53063 2.08170 1.55429 - 1.03851 0.96600 0.92184 0.91931 0.91261 0.91186 - 13.17678 11.93863 11.30799 10.73429 10.21049 9.73213 - 9.29768 8.90552 8.55448 8.24262 7.96744 7.72514 - 7.50938 7.31250 7.12512 6.92677 6.68518 6.34472 - 5.78951 5.34962 4.68555 3.83140 2.27805 1.66519 - 1.05908 0.97524 0.92099 0.91482 0.91094 0.90828 - 13.17968 11.95212 11.32897 10.76404 10.25118 9.78603 - 9.36648 8.99043 8.65617 8.36169 8.10442 7.88045 - 7.68290 7.50542 7.34395 7.18826 7.01081 6.73660 - 6.23015 5.81273 5.17742 4.32083 2.61190 1.88678 - 1.10960 0.99581 0.91928 0.91276 0.90578 0.90373 - 13.15055 11.94939 11.34241 10.79035 10.28804 9.83188 - 9.42006 9.05103 8.72351 8.43632 8.18806 7.97650 - 7.79736 7.64527 7.51269 7.38103 7.22081 6.98107 - 6.54408 6.16532 5.55806 4.70965 2.91836 2.08047 - 1.16064 1.02463 0.92065 0.91103 0.90053 0.90096 - 13.12179 11.95948 11.36923 10.83030 10.33878 9.89247 - 9.49026 9.13184 8.81677 8.54429 8.31324 8.12155 - 7.96509 7.83939 7.73975 7.65246 7.55331 7.39453 - 7.06794 6.75822 6.21740 5.40901 3.53440 2.53893 - 1.28638 1.08644 0.92815 0.91283 0.89903 0.89723 - 13.10844 11.97380 11.38269 10.84556 10.35832 9.91817 - 9.52383 9.17427 8.86832 8.60504 8.38319 8.20061 - 8.05278 7.93642 7.85196 7.79586 7.75067 7.65504 - 7.39086 7.12366 6.65263 5.90601 4.00340 2.92347 - 1.41045 1.15489 0.93861 0.91571 0.89691 0.89536 - 13.02290 11.98087 11.39663 10.86563 10.38411 9.94993 - 9.56185 9.21896 8.92036 8.66534 8.45304 8.28174 - 8.14757 8.04812 7.98554 7.95917 7.95669 7.92613 - 7.76504 7.57111 7.19444 6.55025 4.72435 3.53522 - 1.64222 1.29064 0.96306 0.92368 0.89608 0.89347 - 12.94956 11.98417 11.40315 10.87495 10.39625 9.96518 - 9.58043 9.24110 8.94650 8.69602 8.48895 8.32382 - 8.19699 8.10660 8.05570 8.04544 8.06673 8.07409 - 7.97715 7.83225 7.52438 6.96469 5.24660 4.01365 - 1.85565 1.42027 0.98945 0.93350 0.89684 0.89251 - 12.87295 11.97852 11.40843 10.88585 10.40965 9.97957 - 9.59513 9.25597 8.96207 8.71320 8.50900 8.34872 - 8.23017 8.15163 8.11287 8.10722 8.12366 8.14187 - 8.10529 8.01176 7.76078 7.25735 5.63938 4.40657 - 2.05385 1.54270 1.01656 0.94488 0.89800 0.89194 - 12.83534 11.97959 11.41095 10.88949 10.41433 9.98567 - 9.60277 9.26528 8.97314 8.72619 8.52417 8.36647 - 8.25101 8.17632 8.14265 8.14417 8.17124 8.20614 - 8.19956 8.13269 7.92599 7.47937 5.95071 4.73394 - 2.24224 1.65915 1.04400 0.95658 0.90000 0.89156 - 12.78743 11.98065 11.41400 10.89431 10.42084 9.99388 - 9.61286 9.27742 8.98752 8.74307 8.54391 8.38950 - 8.27800 8.20833 8.18128 8.19212 8.23292 8.29001 - 8.32353 8.29261 8.14962 7.79077 6.41850 5.25265 - 2.59082 1.87660 1.09886 0.98136 0.90456 0.89108 - 12.75700 11.98096 11.41579 10.89727 10.42501 9.99919 - 9.61923 9.28493 8.99637 8.75348 8.55610 8.40372 - 8.29465 8.22811 8.20520 8.22175 8.27104 8.34218 - 8.40123 8.39350 8.29408 7.99982 6.75784 5.65028 - 2.89839 2.07555 1.15298 1.00741 0.90952 0.89079 - 12.71093 11.98136 11.41790 10.90133 10.43092 10.00655 - 9.62798 9.29513 9.00829 8.76746 8.57248 8.42294 - 8.31734 8.25515 8.23797 8.26226 8.32305 8.41385 - 8.50913 8.53465 8.50037 8.31099 7.31458 6.34321 - 3.53381 2.51662 1.28417 1.07543 0.92242 0.89040 - 12.68514 11.98164 11.41896 10.90331 10.43368 10.01015 - 9.63229 9.30019 9.01423 8.77442 8.58069 8.43263 - 8.32887 8.26900 8.25483 8.28311 8.34988 8.45095 - 8.56567 8.60929 8.61032 8.48307 7.65896 6.79682 - 4.03043 2.89686 1.40963 1.14480 0.93546 0.89021 - 12.65784 11.98210 11.42011 10.90499 10.43604 10.01332 - 9.63629 9.30509 9.02004 8.78127 8.58875 8.44221 - 8.34030 8.28280 8.27169 8.30416 8.37714 8.48867 - 8.62380 8.68676 8.72455 8.66698 8.06831 7.36587 - 4.76975 3.50916 1.64264 1.28065 0.96195 0.89002 - 12.64357 11.98238 11.42054 10.90558 10.43678 10.01427 - 9.63768 9.30715 9.02309 8.78541 8.59365 8.44748 - 8.34614 8.28977 8.28000 8.31311 8.38670 8.50591 - 8.66677 8.74414 8.77042 8.69652 8.33690 7.87130 - 5.22370 3.89704 1.86538 1.44251 0.98483 0.88993 - 12.65532 11.98970 11.41995 10.90134 10.43196 10.01045 - 9.63581 9.30739 9.02485 8.78806 8.59689 8.45052 - 8.34642 8.28452 8.27116 8.31315 8.41204 8.54422 - 8.67904 8.74606 8.80980 8.81975 8.46530 7.94286 - 5.69609 4.38092 2.07047 1.53680 1.01480 0.88987 - 12.64841 11.98944 11.41996 10.90157 10.43242 10.01111 - 9.63665 9.30840 9.02604 8.78946 8.59853 8.45245 - 8.34869 8.28727 8.27457 8.31749 8.41778 8.55215 - 8.69120 8.76245 8.83462 8.86089 8.57126 8.11289 - 6.01335 4.70635 2.26964 1.65854 1.04169 0.88983 - 12.61652 11.98227 11.42187 10.90722 10.43869 10.01668 - 9.64094 9.31122 9.02767 8.79033 8.59925 8.45428 - 8.35439 8.29972 8.29261 8.33081 8.41231 8.53735 - 8.69946 8.78871 8.87532 8.91487 8.70585 8.34590 - 6.49054 5.22565 2.62398 1.90601 1.09602 0.88978 - 12.60963 11.98163 11.42208 10.90815 10.43984 10.01796 - 9.64209 9.31217 9.02849 8.79116 8.60031 8.45576 - 8.35638 8.30220 8.29555 8.33420 8.41625 8.54276 - 8.70870 8.80147 8.89376 8.94606 8.79719 8.49286 - 6.83302 5.62999 2.93205 2.12354 1.14962 0.88975 - 1.47356 1.52446 1.57531 1.62621 1.67691 1.72709 - 1.77641 1.82447 1.87095 1.91557 1.95812 1.99881 - 2.03844 2.07769 2.11619 2.15346 2.18924 2.22460 - 2.26078 2.27931 2.29900 2.31666 2.34016 2.34753 - 2.35225 2.35270 2.35330 2.35334 2.35352 2.35391 - 1.93566 1.99056 2.04479 2.09870 2.15204 2.20448 - 2.25567 2.30528 2.35297 2.39853 2.44188 2.48330 - 2.52380 2.56426 2.60452 2.64437 2.68407 2.72545 - 2.76994 2.79205 2.81141 2.82443 2.84265 2.84913 - 2.85247 2.85269 2.85321 2.85321 2.85334 2.85723 - 2.31868 2.38179 2.44212 2.50019 2.55571 2.60837 - 2.65809 2.70497 2.74935 2.79136 2.83124 2.86966 - 2.90832 2.94862 2.99014 3.03155 3.07194 3.11315 - 3.15579 3.17615 3.19532 3.20959 3.22546 3.22975 - 3.23290 3.23333 3.23365 3.23363 3.23368 3.23696 - 2.93700 3.01733 3.08955 3.15444 3.21169 3.26143 - 3.30445 3.34254 3.37822 3.41213 3.44451 3.47577 - 3.50698 3.53910 3.57206 3.60560 3.63969 3.67562 - 3.71432 3.73385 3.75164 3.76388 3.77714 3.78053 - 3.78305 3.78334 3.78362 3.78365 3.78370 3.78306 - 3.42836 3.52756 3.60856 3.67413 3.72709 3.77105 - 3.80738 3.83780 3.86479 3.88925 3.91208 3.93391 - 3.95513 3.97627 3.99788 4.02113 4.04717 4.07581 - 4.10634 4.12196 4.13740 4.14909 4.15984 4.16249 - 4.16466 4.16490 4.16511 4.16522 4.16521 4.16127 - 3.83096 3.95397 4.04311 4.10504 4.14876 4.18449 - 4.21409 4.23796 4.25695 4.27172 4.28360 4.29392 - 4.30387 4.31471 4.32689 4.34103 4.35766 4.37651 - 4.39775 4.40973 4.42241 4.43253 4.44110 4.44310 - 4.44491 4.44509 4.44526 4.44541 4.44539 4.43935 - 4.19074 4.30146 4.39151 4.46242 4.51402 4.54736 - 4.56520 4.57273 4.57670 4.57892 4.58000 4.58077 - 4.58249 4.58628 4.59176 4.59749 4.60262 4.60980 - 4.62259 4.63149 4.64118 4.64882 4.65499 4.65661 - 4.65802 4.65814 4.65823 4.65834 4.65834 4.65141 - 4.76833 4.88556 4.97598 5.04192 5.08344 5.10220 - 5.10202 5.08975 5.07401 5.05716 5.03982 5.02295 - 5.00758 4.99464 4.98352 4.97228 4.95977 4.94937 - 4.94579 4.94724 4.94987 4.95232 4.95361 4.95403 - 4.95449 4.95450 4.95450 4.95458 4.95458 4.94857 - 5.23200 5.34853 5.43353 5.49021 5.51897 5.52206 - 5.50420 5.47345 5.43989 5.40615 5.37291 5.34102 - 5.31116 5.28392 5.25851 5.23265 5.20503 5.17967 - 5.16208 5.15678 5.15220 5.14867 5.14518 5.14443 - 5.14385 5.14374 5.14366 5.14369 5.14369 5.14052 - 6.07247 6.22103 6.28574 6.28729 6.25110 6.20414 - 6.15139 6.09383 6.03285 5.96931 5.90524 5.84201 - 5.78046 5.72125 5.66451 5.60986 5.55724 5.50789 - 5.46252 5.44087 5.41982 5.40406 5.38984 5.38644 - 5.38365 5.38335 5.38306 5.38290 5.38293 5.38809 - 6.69489 6.80885 6.83839 6.80540 6.73337 6.64730 - 6.55411 6.45833 6.36512 6.27519 6.18822 6.10360 - 6.02207 5.94374 5.86830 5.79451 5.72213 5.65517 - 5.59215 5.55790 5.52339 5.49761 5.47602 5.47040 - 5.46587 5.46545 5.46509 5.46484 5.46484 5.47652 - 7.57501 7.57793 7.53028 7.44488 7.32574 7.17941 - 7.01563 6.84822 6.69207 6.55112 6.42495 6.31132 - 6.20740 6.10912 6.01466 5.91979 5.82176 5.72518 - 5.63509 5.59067 5.54038 5.49713 5.46632 5.45881 - 5.45165 5.45093 5.45043 5.45009 5.45014 5.46737 - 8.32985 8.14290 7.94689 7.75513 7.56753 7.38403 - 7.20481 7.03018 6.86000 6.69536 6.53733 6.38565 - 6.24183 6.10625 5.97977 5.86348 5.75751 5.65779 - 5.56156 5.51660 5.47472 5.43820 5.36397 5.33603 - 5.34437 5.34916 5.34597 5.34397 5.34658 5.36023 - 8.61087 8.48266 8.30382 8.09403 7.85901 7.60686 - 7.34845 7.09806 6.87082 6.66970 6.49339 6.33733 - 6.19609 6.06409 5.93875 5.81549 5.69080 5.56733 - 5.44839 5.38976 5.32755 5.27637 5.23336 5.22278 - 5.21363 5.21260 5.21181 5.21158 5.21155 5.21995 - 8.96111 8.77314 8.53757 8.27640 7.99549 7.70316 - 7.40997 7.12944 6.87623 6.65290 6.45736 6.28450 - 6.12794 5.98220 5.84433 5.71001 5.57571 5.44313 - 5.31525 5.25327 5.19045 5.14024 5.09288 5.08121 - 5.07173 5.07060 5.06965 5.06952 5.06944 5.06941 - 9.43254 9.24188 8.91888 8.52719 8.12034 7.74573 - 7.40847 7.10521 6.83308 6.58823 6.36292 6.15189 - 5.95695 5.78042 5.61948 5.46929 5.32413 5.17764 - 5.03273 4.96770 4.90561 4.85688 4.80299 4.79026 - 4.78026 4.77876 4.77769 4.77776 4.77762 4.76475 - 9.79598 9.53575 9.13094 8.65812 8.18217 7.75739 - 7.38413 7.05172 6.74987 6.47526 6.22298 5.98928 - 5.77384 5.57734 5.39740 5.22919 5.06830 4.91191 - 4.76048 4.68963 4.62358 4.57446 4.51915 4.50408 - 4.49363 4.49216 4.49108 4.49128 4.49115 4.47359 - 10.55172 9.90207 9.28409 8.71621 8.19408 7.71397 - 7.27280 6.86919 6.50191 6.16874 5.86625 5.59015 - 5.33576 5.10073 4.88610 4.69011 4.51006 4.33490 - 4.15617 4.06943 3.99189 3.93857 3.87866 3.86193 - 3.85062 3.84949 3.84815 3.84800 3.84790 3.84244 - 10.90395 10.12437 9.39864 8.73984 8.14057 7.59578 - 7.10086 6.65257 6.24902 5.88580 5.55762 5.25875 - 4.98245 4.72454 4.48614 4.26618 4.06201 3.86603 - 3.67319 3.58064 3.49441 3.43162 3.36789 3.35297 - 3.34031 3.33883 3.33775 3.33747 3.33728 3.34768 - 11.36314 10.35867 9.46765 8.68298 7.98750 7.37028 - 6.82250 6.33329 5.89382 5.49755 5.13770 4.80719 - 4.49762 4.20387 3.92760 3.67196 3.43655 3.21782 - 3.01442 2.91883 2.82505 2.75308 2.68816 2.67224 - 2.65924 2.65777 2.65656 2.65630 2.65619 2.66297 - 11.66346 10.50769 9.51173 8.64670 7.89045 7.22667 - 6.64400 6.12755 5.66382 5.24504 4.86451 4.51508 - 4.18849 3.87938 3.58811 3.31614 3.06376 2.82779 - 2.60924 2.50815 2.41286 2.34215 2.27376 2.25720 - 2.24430 2.24276 2.24143 2.24131 2.24114 2.23853 - 11.87936 10.62038 9.55670 8.63837 7.84187 7.14717 - 6.54017 6.00393 5.52260 5.08744 4.69179 4.32864 - 3.98988 3.67010 3.36895 3.08693 2.82453 2.57868 - 2.34969 2.24329 2.14353 2.07008 1.99966 1.98288 - 1.96989 1.96832 1.96695 1.96685 1.96668 1.96292 - 12.04801 10.71447 9.60519 8.64997 7.82559 7.11003 - 6.48600 5.93513 5.44041 4.99273 4.58540 4.21150 - 3.86313 3.53490 3.22622 2.93706 2.66764 2.41510 - 2.17780 2.06640 1.96134 1.88384 1.81154 1.79449 - 1.78120 1.77960 1.77821 1.77808 1.77792 1.77590 - 12.30431 10.87250 9.70895 8.70993 7.85259 7.11330 - 6.46940 5.90020 5.38762 4.92252 4.49838 4.10851 - 3.74539 3.40388 3.08312 2.78277 2.50201 2.23761 - 1.98519 1.86458 1.74981 1.66465 1.58700 1.56871 - 1.55431 1.55260 1.55113 1.55095 1.55079 1.55153 - 12.49587 11.00541 9.81490 8.79495 7.92280 7.17264 - 6.51928 5.94037 5.41730 4.94117 4.50572 4.10448 - 3.73017 3.37788 3.04674 2.73636 2.44509 2.16799 - 1.90035 1.77075 1.64685 1.55428 1.46914 1.44883 - 1.43281 1.43093 1.42933 1.42911 1.42894 1.43020 - 12.80961 11.26100 10.05548 9.02349 8.14528 7.38594 - 6.72202 6.13133 5.59581 5.10664 4.65732 4.24093 - 3.84957 3.47802 3.12586 2.79327 2.47767 2.16979 - 1.86350 1.71076 1.56018 1.44344 1.33448 1.30790 - 1.28660 1.28411 1.28206 1.28177 1.28157 1.28185 - 12.99288 11.44100 10.25182 9.23069 8.35959 7.59972 - 6.93158 6.33580 5.79651 5.30451 4.85228 4.43152 - 4.03248 3.64897 3.28127 2.93066 2.59436 2.25986 - 1.91649 1.74022 1.55876 1.41197 1.27570 1.24294 - 1.21657 1.21334 1.21059 1.21025 1.20999 1.20982 - 13.20091 11.66202 10.51944 9.54112 8.69844 7.95606 - 7.29721 6.70502 6.16543 5.67041 5.21339 4.78712 - 4.38284 3.99367 3.61619 3.24565 2.87501 2.49217 - 2.08245 1.86209 1.62558 1.42169 1.21864 1.17418 - 1.14445 1.14064 1.13488 1.13381 1.13432 1.13682 - 13.24432 11.78263 10.71678 9.79048 8.97157 8.23662 - 7.57606 6.98045 6.44187 5.95235 5.50357 5.08586 - 4.68722 4.29833 3.91537 3.53299 3.14186 2.72391 - 2.25722 1.99799 1.71533 1.46659 1.19836 1.13310 - 1.10400 1.10177 1.09262 1.09031 1.09248 1.09690 - 13.29803 11.85222 10.82862 9.93851 9.14625 8.43216 - 7.78781 7.20462 6.67542 6.19283 5.74904 5.33483 - 4.93846 4.55047 4.16624 3.77905 3.37686 2.93603 - 2.42662 2.13496 1.80870 1.51708 1.19256 1.11063 - 1.07791 1.07608 1.06465 1.06160 1.06475 1.06909 - 13.32565 11.89397 10.90836 10.04810 9.27921 8.58383 - 7.95460 7.38354 6.86406 6.38926 5.95179 5.54274 - 5.15061 4.76582 4.38316 3.99470 3.58604 3.12864 - 2.58513 2.26629 1.90251 1.57186 1.19566 1.09785 - 1.05951 1.05768 1.04455 1.04098 1.04479 1.04803 - 13.32904 11.92827 11.01048 10.20046 9.47230 8.80984 - 8.20738 7.65809 7.15639 6.69638 6.27153 5.87383 - 5.49267 5.11855 4.74504 4.36180 3.94942 3.46845 - 2.86706 2.50117 2.07408 1.68008 1.22946 1.10297 - 1.02450 1.02269 1.02374 1.02086 1.01041 1.01816 - 13.32119 11.94299 11.07390 10.30038 9.60289 8.96631 - 8.38589 7.85552 7.37031 6.92487 6.51326 6.12799 - 5.75886 5.39647 5.03370 4.65878 4.24909 3.75778 - 3.12070 2.72112 2.24321 1.79134 1.26355 1.11083 - 1.00991 1.00578 1.00631 1.00319 0.99088 0.99803 - 13.35196 11.98730 11.17202 10.44346 9.78697 9.18945 - 8.64657 8.15273 7.70327 7.29295 6.91566 6.56334 - 6.22450 5.88872 5.54930 5.19497 4.80376 4.32844 - 3.68112 3.23724 2.65107 2.05604 1.34304 1.13990 - 1.00782 0.99241 0.97306 0.97067 0.96893 0.96870 - 13.30382 11.97165 11.20511 10.51803 9.89689 9.33093 - 8.81643 8.34862 7.92344 7.53630 7.18170 6.85222 - 6.53696 6.22572 5.91155 5.58218 5.21282 4.74872 - 4.08868 3.62218 2.99180 2.32441 1.45632 1.19352 - 1.00290 0.98032 0.95893 0.95618 0.95434 0.95298 - 13.19412 11.91605 11.22094 10.59369 10.02316 9.50154 - 9.02613 8.59342 8.20043 7.84380 7.51940 7.22145 - 6.94111 6.66964 6.39988 6.11812 5.79460 5.35995 - 4.69193 4.20030 3.52123 2.76936 1.69293 1.33446 - 1.01008 0.96837 0.94357 0.94059 0.93117 0.93638 - 13.16780 11.90580 11.23875 10.63608 10.08845 9.58899 - 9.13533 8.72435 8.35342 8.01946 7.71869 7.44559 - 7.19143 6.94780 6.70836 6.46051 6.17562 5.78434 - 5.15579 4.67104 3.97022 3.15180 1.89495 1.45520 - 1.03413 0.97370 0.93244 0.92906 0.92389 0.92760 - 13.15098 11.90171 11.25184 10.66444 10.13113 9.64607 - 9.20690 8.81077 8.45525 8.13750 7.85394 7.59924 - 7.36475 7.14230 6.92638 6.70563 6.45310 6.10130 - 5.51598 5.04693 4.34264 3.48275 2.08364 1.57079 - 1.06122 0.98324 0.92549 0.92135 0.92013 0.92217 - 13.11911 11.89793 11.26983 10.69807 10.17598 9.69908 - 9.26591 8.87489 8.52489 8.21401 7.93971 7.69825 - 7.48326 7.28719 7.10070 6.90361 6.66390 6.32634 - 5.77559 5.33877 4.67840 3.82799 2.28047 1.67038 - 1.06834 0.98518 0.93122 0.92492 0.92104 0.91848 - 13.09282 11.89736 11.28704 10.73053 10.22225 9.75883 - 9.33892 8.96144 8.62571 8.33019 8.07282 7.85038 - 7.65718 7.48663 7.33097 7.17216 6.97988 6.69783 - 6.20836 5.80279 5.16800 4.31240 2.62125 1.88778 - 1.11687 1.00592 0.93011 0.92209 0.91615 0.91380 - 13.08448 11.90235 11.29974 10.75118 10.25165 9.79770 - 9.38764 9.01995 8.69347 8.40708 8.15943 7.94835 - 7.76970 7.61819 7.48629 7.35535 7.19601 6.95799 - 6.52477 6.14916 5.54616 4.70228 2.91809 2.08397 - 1.16883 1.03367 0.93067 0.92112 0.91041 0.91094 - 13.06535 11.91798 11.32932 10.79203 10.30216 9.85750 - 9.45690 9.09993 8.78615 8.51474 8.28454 8.09350 - 7.93747 7.81203 7.71254 7.62538 7.52660 7.36883 - 7.04478 6.73759 6.20107 5.39815 3.53203 2.54024 - 1.29350 1.09483 0.93807 0.92277 0.90888 0.90709 - 13.05800 11.93632 11.34585 10.80933 10.32283 9.88358 - 9.49020 9.14164 8.83676 8.57454 8.35375 8.17212 - 8.02507 7.90924 7.82498 7.76883 7.72345 7.62793 - 7.36524 7.10012 6.63325 5.89230 3.99885 2.92341 - 1.41681 1.16266 0.94836 0.92568 0.90667 0.90517 - 12.97524 11.94392 11.36017 10.82965 10.34886 9.91555 - 9.52836 9.18640 8.88879 8.63477 8.42343 8.25301 - 8.11954 8.02056 7.95814 7.93164 7.92878 7.89787 - 7.73722 7.54457 7.17111 6.53210 4.71671 3.53282 - 1.64729 1.29753 0.97257 0.93360 0.90577 0.90323 - 12.90034 11.94484 11.36517 10.83825 10.36087 9.93094 - 9.54731 9.20902 8.91537 8.66578 8.45948 8.29498 - 8.16866 8.07858 8.02779 8.01743 8.03842 8.04539 - 7.94849 7.80433 7.49875 6.94344 5.23647 4.00933 - 1.85968 1.42647 0.99873 0.94332 0.90650 0.90226 - 12.82311 11.93709 11.36865 10.84783 10.37344 9.94497 - 9.56202 9.22436 8.93205 8.68447 8.48059 8.31958 - 8.20032 8.12190 8.08392 8.07920 8.09658 8.11695 - 8.07565 7.97322 7.72533 7.25599 5.65859 4.35890 - 2.05356 1.55904 1.02635 0.94709 0.91347 0.90167 - 12.78387 11.93727 11.37117 10.85175 10.37840 9.95139 - 9.56996 9.23369 8.94247 8.69616 8.49461 8.33729 - 8.22217 8.14778 8.11428 8.11581 8.14261 8.17722 - 8.17045 8.10363 7.89773 7.45406 5.93705 4.72629 - 2.24448 1.66431 1.05282 0.96614 0.90964 0.90128 - 12.73659 11.93784 11.37401 10.85647 10.38489 9.95958 - 9.57994 9.24564 8.95666 8.71292 8.51430 8.36029 - 8.24911 8.17969 8.15278 8.16359 8.20416 8.26090 - 8.29411 8.26310 8.12037 7.76345 6.40165 5.24242 - 2.59159 1.88095 1.10725 0.99060 0.91422 0.90078 - 12.70754 11.93867 11.37589 10.85952 10.38905 9.96477 - 9.58615 9.25297 8.96534 8.72322 8.52646 8.37454 - 8.26582 8.19948 8.17664 8.19312 8.24216 8.31293 - 8.37162 8.36375 8.26435 7.97135 6.73849 5.63787 - 2.89789 2.07917 1.16096 1.01635 0.91921 0.90048 - 12.66445 11.93997 11.37850 10.86366 10.39485 9.97194 - 9.59463 9.26291 8.97707 8.73711 8.54287 8.39384 - 8.28857 8.22653 8.20932 8.23347 8.29404 8.38446 - 8.47927 8.50465 8.47019 8.28113 7.29095 6.32663 - 3.53094 2.51861 1.29125 1.08367 0.93215 0.90009 - 12.63953 11.94045 11.37975 10.86563 10.39770 9.97550 - 9.59890 9.26792 8.98296 8.74405 8.55102 8.40346 - 8.30001 8.24029 8.22609 8.25426 8.32079 8.42143 - 8.53566 8.57910 8.57991 8.45267 7.63281 6.77722 - 4.02571 2.89720 1.41595 1.15244 0.94516 0.89989 - 12.61205 11.94062 11.38081 10.86751 10.40015 9.97878 - 9.60304 9.27295 8.98889 8.75094 8.55905 8.41292 - 8.31131 8.25398 8.24292 8.27527 8.34799 8.45906 - 8.59365 8.65631 8.69390 8.63622 8.03955 7.34238 - 4.76210 3.50677 1.64769 1.28734 0.97154 0.89970 - 12.61935 11.94800 11.38003 10.86310 10.39529 9.97506 - 9.60153 9.27398 8.99212 8.75580 8.56485 8.41846 - 8.31407 8.25158 8.23724 8.27766 8.37418 8.50276 - 8.63095 8.69141 8.74212 8.72781 8.28503 7.68149 - 5.28465 3.98811 1.86017 1.41763 0.99730 0.89960 - 12.61004 11.94782 11.38034 10.86365 10.39607 9.97607 - 9.60276 9.27547 8.99389 8.75788 8.56729 8.42135 - 8.31750 8.25573 8.24235 8.28415 8.38268 8.51440 - 8.64874 8.71554 8.77902 8.78867 8.43468 7.91554 - 5.68413 4.37446 2.07340 1.54221 1.02389 0.89955 - 12.60359 11.94787 11.38046 10.86399 10.39652 9.97671 - 9.60358 9.27647 8.99506 8.75926 8.56893 8.42330 - 8.31982 8.25853 8.24579 8.28850 8.38839 8.52228 - 8.66086 8.73188 8.80383 8.82978 8.54003 8.08450 - 5.99974 4.69826 2.27137 1.66348 1.05054 0.89951 - 12.57302 11.94140 11.38276 10.86964 10.40249 9.98197 - 9.60758 9.27907 8.99651 8.75997 8.56955 8.42514 - 8.32562 8.27106 8.26384 8.30180 8.38295 8.50756 - 8.66908 8.75800 8.84432 8.88369 8.67457 8.31626 - 6.47410 5.21483 2.62389 1.90946 1.10440 0.89945 - 12.56947 11.94086 11.38207 10.86976 10.40353 9.98321 - 9.60855 9.27967 8.99703 8.76070 8.57059 8.42653 - 8.32743 8.27338 8.26673 8.30520 8.38692 8.51299 - 8.67831 8.77065 8.86261 8.91486 8.76597 8.46254 - 6.81419 5.61696 2.93056 2.12589 1.15757 0.89941 - 1.43365 1.48368 1.53373 1.58396 1.63409 1.68386 - 1.73290 1.78088 1.82744 1.87232 1.91530 1.95652 - 1.99670 2.03642 2.07525 2.11264 2.14826 2.18311 - 2.21836 2.23638 2.25587 2.27362 2.29645 2.30331 - 2.30791 2.30838 2.30894 2.30897 2.30914 2.30958 - 1.87938 1.93564 1.99126 2.04658 2.10129 2.15504 - 2.20748 2.25820 2.30687 2.35323 2.39720 2.43905 - 2.47986 2.52056 2.56094 2.60079 2.64029 2.68130 - 2.72521 2.74698 2.76607 2.77890 2.79666 2.80291 - 2.80611 2.80633 2.80682 2.80681 2.80696 2.81089 - 2.25480 2.32106 2.38398 2.44406 2.50101 2.55466 - 2.60513 2.65290 2.69882 2.74299 2.78541 2.82624 - 2.86627 2.90626 2.94627 2.98665 3.02770 3.06936 - 3.11088 3.13094 3.15021 3.16473 3.17997 3.18410 - 3.18720 3.18756 3.18787 3.18786 3.18788 3.19120 - 2.87005 2.95203 3.02614 3.09308 3.15249 3.20446 - 3.24971 3.28994 3.32757 3.36323 3.39718 3.42983 - 3.46239 3.49583 3.52997 3.56417 3.59818 3.63369 - 3.67223 3.69186 3.70993 3.72244 3.73547 3.73875 - 3.74120 3.74149 3.74174 3.74177 3.74182 3.74110 - 3.36431 3.46216 3.54420 3.61240 3.66819 3.71391 - 3.75118 3.78266 3.81186 3.83945 3.86525 3.88920 - 3.91205 3.93466 3.95755 3.98186 4.00861 4.03732 - 4.06780 4.08395 4.10003 4.11206 4.12271 4.12540 - 4.12756 4.12780 4.12798 4.12806 4.12807 4.12398 - 3.76780 3.89342 3.98329 4.04472 4.08797 4.12456 - 4.15629 4.18308 4.20506 4.22271 4.23728 4.25000 - 4.26212 4.27488 4.28869 4.30414 4.32174 4.34125 - 4.36312 4.37565 4.38903 4.39974 4.40854 4.41053 - 4.41238 4.41255 4.41272 4.41288 4.41286 4.40663 - 4.13266 4.24229 4.33177 4.40262 4.45471 4.48907 - 4.50848 4.51809 4.52459 4.52973 4.53401 4.53800 - 4.54258 4.54856 4.55560 4.56264 4.56915 4.57764 - 4.59154 4.60100 4.61150 4.61994 4.62647 4.62815 - 4.62967 4.62979 4.62987 4.62998 4.62999 4.62285 - 4.71469 4.82994 4.91905 4.98433 5.02589 5.04541 - 5.04671 5.03656 5.02352 5.00983 4.99601 4.98270 - 4.97047 4.95991 4.95057 4.94105 4.93066 4.92243 - 4.92061 4.92284 4.92642 4.92978 4.93182 4.93244 - 4.93309 4.93311 4.93312 4.93321 4.93321 4.92704 - 5.17987 5.29432 5.37802 5.43415 5.46313 5.46722 - 5.45107 5.42268 5.39194 5.36143 5.33166 5.30326 - 5.27649 5.25166 5.22821 5.20443 5.17949 5.15692 - 5.14161 5.13726 5.13368 5.13108 5.12868 5.12823 - 5.12790 5.12784 5.12777 5.12780 5.12781 5.12458 - 6.04188 6.13949 6.19837 6.22403 6.21778 6.18311 - 6.12629 6.05738 5.98850 5.92253 5.86022 5.80167 - 5.74655 5.69433 5.64407 5.59328 5.54064 5.49066 - 5.44903 5.43110 5.41150 5.39476 5.38281 5.38004 - 5.37742 5.37714 5.37693 5.37684 5.37685 5.38218 - 6.65579 6.72657 6.75349 6.74446 6.70166 6.62965 - 6.53593 6.43196 6.33109 6.23659 6.14907 6.06805 - 5.99266 5.92140 5.85295 5.78401 5.71260 5.64365 - 5.58298 5.55467 5.52247 5.49448 5.47531 5.47075 - 5.46631 5.46587 5.46557 5.46535 5.46537 5.47735 - 7.50884 7.51662 7.47496 7.39624 7.28416 7.14487 - 6.98766 6.82579 6.67360 6.53504 6.41002 6.29687 - 6.19364 6.09702 6.00505 5.91309 5.81796 5.72446 - 5.63783 5.59518 5.54641 5.50420 5.47497 5.46787 - 5.46099 5.46031 5.45987 5.45954 5.45958 5.47715 - 8.09941 8.04245 7.93447 7.79154 7.61848 7.42247 - 7.21368 7.00612 6.81449 6.64251 6.48966 6.35308 - 6.22945 6.11443 6.00555 5.89760 5.78673 5.67707 - 5.57320 5.52173 5.46458 5.41612 5.37978 5.37086 - 5.36264 5.36178 5.36117 5.36085 5.36087 5.37622 - 8.53927 8.44602 8.27896 8.06535 7.82174 7.56643 - 7.31198 7.07283 6.86323 6.68027 6.51276 6.35251 - 6.20290 6.06582 5.93916 5.81791 5.69802 5.58141 - 5.46569 5.40477 5.34334 5.29617 5.25370 5.24290 - 5.23422 5.23323 5.23245 5.23219 5.23216 5.24078 - 8.88451 8.75472 8.53362 8.25924 7.95891 7.65998 - 7.37337 7.10866 6.87557 6.67050 6.48285 6.30493 - 6.13952 5.98870 5.85004 5.71868 5.58989 5.46215 - 5.33520 5.27289 5.21146 5.16387 5.11709 5.10558 - 5.09639 5.09519 5.09433 5.09420 5.09412 5.09419 - 9.39865 9.21150 8.89533 8.51160 8.11182 7.74194 - 7.40765 7.10674 6.83744 6.59596 6.37421 6.16661 - 5.97453 5.79997 5.64034 5.49130 5.34742 5.20198 - 5.05825 4.99443 4.93372 4.88610 4.83312 4.82064 - 4.81083 4.80934 4.80830 4.80838 4.80824 4.79530 - 9.94767 9.47145 9.00549 8.56950 8.16129 7.77961 - 7.42347 7.09189 6.78450 6.50218 6.24321 6.00542 - 5.78703 5.58817 5.40857 5.24765 5.10190 4.95626 - 4.79762 4.71831 4.65047 4.60745 4.55447 4.53746 - 4.52775 4.52695 4.52547 4.52540 4.52548 4.50774 - 10.56265 9.91138 9.29300 8.72533 8.20399 7.72519 - 7.28586 6.88447 6.51976 6.18940 5.88988 5.61680 - 5.36523 5.13255 4.91980 4.72524 4.54613 4.37132 - 4.19240 4.10563 4.02869 3.97643 3.91691 3.89989 - 3.88872 3.88764 3.88628 3.88615 3.88604 3.88031 - 10.91787 10.13828 9.41305 8.75506 8.15694 7.61356 - 7.12033 6.67393 6.27244 5.91137 5.58542 5.28882 - 5.01459 4.75844 4.52146 4.30261 4.09924 3.90372 - 3.71099 3.61847 3.53254 3.47019 3.40636 3.39116 - 3.37850 3.37704 3.37595 3.37567 3.37546 3.38568 - 11.36179 10.36292 9.47666 8.69608 8.00419 7.39010 - 6.84500 6.35805 5.92042 5.52564 5.16706 4.83766 - 4.52912 4.23637 3.96103 3.70625 3.47161 3.25356 - 3.05069 2.95529 2.86163 2.78959 2.72410 2.70796 - 2.69481 2.69332 2.69208 2.69183 2.69172 2.69828 - 11.64259 10.50035 9.51410 8.65622 7.90519 7.24518 - 6.66514 6.15059 5.68835 5.27081 4.89135 4.54292 - 4.21732 3.90920 3.61887 3.34768 3.09583 2.86035 - 2.64235 2.54155 2.44647 2.37575 2.30674 2.28996 - 2.27689 2.27533 2.27398 2.27385 2.27368 2.27104 - 11.84913 10.60708 9.55526 8.64541 7.85486 7.16424 - 6.55988 6.02539 5.54534 5.11118 4.71637 4.35401 - 4.01608 3.69721 3.39697 3.11566 2.85370 2.60823 - 2.37978 2.27373 2.17429 2.10095 2.03002 2.01305 - 1.99992 1.99833 1.99694 1.99684 1.99666 1.99334 - 12.01523 10.69929 9.60208 8.65552 7.83722 7.12580 - 6.50444 5.95529 5.46174 5.01487 4.60814 4.23479 - 3.88705 3.55965 3.25181 2.96334 2.69433 2.44215 - 2.20539 2.09438 1.98971 1.91242 1.83974 1.82253 - 1.80913 1.80752 1.80612 1.80599 1.80581 1.80450 - 12.27605 10.85955 9.70597 8.71434 7.86229 7.12667 - 6.48527 5.91769 5.40617 4.94174 4.51803 4.12853 - 3.76587 3.42502 3.10501 2.80529 2.52497 2.26099 - 2.00921 1.88903 1.77473 1.68987 1.61204 1.59364 - 1.57917 1.57746 1.57598 1.57579 1.57563 1.57665 - 12.47576 10.99725 9.81374 8.79919 7.93103 7.18373 - 6.53242 5.95502 5.43301 4.95763 4.52275 4.12199 - 3.74821 3.39653 3.06603 2.75622 2.46545 2.18890 - 1.92204 1.79293 1.66952 1.57727 1.49202 1.47164 - 1.45558 1.45369 1.45207 1.45187 1.45169 1.45234 - 12.79683 11.25596 10.05391 9.02481 8.14877 7.39125 - 6.72892 6.13965 5.60543 5.11742 4.66915 4.25372 - 3.86319 3.49234 3.14079 2.80878 2.49381 2.18680 - 1.88171 1.72962 1.57961 1.46316 1.35414 1.32751 - 1.30615 1.30365 1.30159 1.30131 1.30111 1.30072 - 12.97008 11.42780 10.24293 9.22546 8.35711 7.59964 - 6.93359 6.33968 5.80201 5.31142 4.86041 4.44075 - 4.04268 3.66006 3.29314 2.94326 2.60772 2.27436 - 1.93258 1.75716 1.57638 1.42990 1.29353 1.26070 - 1.23425 1.23101 1.22825 1.22791 1.22764 1.22826 - 13.14861 11.62607 10.49255 9.52171 8.68513 7.94794 - 7.29339 6.70453 6.16726 5.67369 5.21752 4.79173 - 4.38791 3.99936 3.62273 3.25334 2.88418 2.50324 - 2.09577 1.87654 1.64087 1.43737 1.23425 1.18973 - 1.15999 1.15619 1.15040 1.14932 1.14982 1.15289 - 13.15971 11.72543 10.67619 9.76229 8.95271 8.22479 - 7.56934 6.97728 6.44098 5.95275 5.50455 5.08704 - 4.68862 4.30026 3.91819 3.53710 3.14774 2.73213 - 2.26826 2.01047 1.72898 1.48082 1.21258 1.14724 - 1.11830 1.11610 1.10689 1.10459 1.10675 1.11034 - 13.19227 11.77977 10.77680 9.90220 9.12173 8.41644 - 7.77840 7.19946 6.67279 6.19142 5.74788 5.33343 - 4.93688 4.54919 4.16581 3.78008 3.37999 2.94195 - 2.43592 2.14596 1.82110 1.53012 1.20565 1.12370 - 1.09138 1.08961 1.07809 1.07504 1.07818 1.08112 - 13.20471 11.81046 10.84806 10.00552 9.25012 8.56485 - 7.94279 7.37649 6.85976 6.38615 5.94872 5.53910 - 5.14651 4.76189 4.38008 3.99321 3.58695 3.13271 - 2.59299 2.27605 1.91381 1.58387 1.20783 1.11010 - 1.07239 1.07063 1.05738 1.05380 1.05760 1.05940 - 13.19019 11.83125 10.93940 10.14953 9.43676 8.78586 - 8.19162 7.64773 7.14907 6.69022 6.26514 5.86651 - 5.48456 5.11046 4.73784 4.35643 3.94687 3.46958 - 2.87249 2.50875 2.08344 1.69040 1.24039 1.11412 - 1.03632 1.03468 1.03586 1.03295 1.02233 1.02905 - 13.17479 11.83998 10.99753 10.24481 9.56335 8.93885 - 8.36705 7.84236 7.36031 6.91604 6.50413 6.11777 - 5.74773 5.38530 5.02351 4.65060 4.24400 3.75669 - 3.12418 2.72690 2.25096 1.80030 1.27347 1.12114 - 1.02114 1.01724 1.01790 1.01473 1.00224 1.00880 - 13.20893 11.88579 11.09486 10.38556 9.74400 9.15780 - 8.62303 8.13456 7.68812 7.27889 6.90125 6.54781 - 6.20802 5.87221 5.53380 5.18169 4.79407 4.32373 - 3.68230 3.24090 2.65582 2.06116 1.35074 1.14901 - 1.01861 1.00329 0.98373 0.98137 0.97944 0.97920 - 13.17532 11.87993 11.13359 10.46250 9.85386 9.29744 - 8.78990 8.32678 7.90433 7.51830 7.16359 6.83336 - 6.51749 6.20646 5.89344 5.56634 5.20055 4.74136 - 4.08717 3.62322 2.99420 2.32766 1.46291 1.20171 - 1.01323 0.99083 0.96922 0.96645 0.96446 0.96320 - 13.09279 11.84324 11.16115 10.54427 9.98207 9.46693 - 8.99638 8.56709 8.17631 7.82085 7.49685 7.19887 - 6.91865 6.64787 6.37947 6.09989 5.77938 5.34852 - 4.68499 4.19597 3.51981 2.77085 1.69877 1.34167 - 1.01939 0.97817 0.95372 0.95065 0.94083 0.94623 - 13.08461 11.84602 11.18746 10.59159 10.04942 9.55436 - 9.10410 8.69565 8.32648 7.99364 7.69350 7.42078 - 7.16711 6.92437 6.68628 6.44037 6.15811 5.77018 - 5.14587 4.66375 3.96610 3.15113 1.89976 1.46178 - 1.04311 0.98322 0.94241 0.93896 0.93336 0.93729 - 13.06639 11.85055 11.21428 10.63485 10.10512 9.62029 - 9.17906 8.77988 8.42169 8.10215 7.81813 7.56496 - 7.33509 7.11996 6.91026 6.68679 6.41941 6.05657 - 5.48604 5.03995 4.36975 3.52564 2.08798 1.56593 - 1.05714 0.98565 0.94183 0.93915 0.93240 0.93178 - 13.05663 11.85279 11.22802 10.65900 10.13928 9.66446 - 9.23311 8.84366 8.49502 8.18531 7.91203 7.67144 - 7.45727 7.26202 7.07646 6.88058 6.64266 6.30793 - 5.76172 5.32796 4.67131 3.82458 2.28273 1.67532 - 1.07717 0.99463 0.94090 0.93448 0.93058 0.92806 - 13.05973 11.86564 11.24806 10.68786 10.17897 9.71739 - 9.30098 8.92766 8.59575 8.30327 8.04772 7.82519 - 7.62897 7.45277 7.29268 7.13871 6.96383 6.69419 - 6.19608 5.78493 5.15786 4.30999 2.61399 1.89493 - 1.12667 1.01440 0.93902 0.93235 0.92530 0.92335 - 13.03156 11.86345 11.26181 10.71434 10.21574 9.76289 - 9.35397 8.98743 8.66214 8.37689 8.13033 7.92024 - 7.74241 7.59148 7.46001 7.32954 7.17104 6.93480 - 6.50533 6.13285 5.53424 4.69495 2.91776 2.08739 - 1.17680 1.04241 0.94026 0.93076 0.91987 0.92048 - 13.00913 11.87621 11.28933 10.75368 10.26537 9.82215 - 9.42294 9.06721 8.75457 8.48415 8.25480 8.06448 - 7.90907 7.78413 7.68506 7.59832 7.50006 7.34327 - 7.02159 6.71686 6.18467 5.38734 3.52965 2.54160 - 1.30053 1.10304 0.94765 0.93234 0.91837 0.91663 - 12.99864 11.89188 11.30403 10.76982 10.28531 9.84787 - 9.45607 9.10882 8.80507 8.54379 8.32374 8.14272 - 7.99614 7.88071 7.79681 7.74097 7.69595 7.60105 - 7.33996 7.07682 6.61395 5.87853 3.99437 2.92348 - 1.42314 1.17031 0.95783 0.93534 0.91614 0.91470 - 12.91674 11.89850 11.31762 10.78968 10.31101 9.87958 - 9.49402 9.15342 8.85694 8.60382 8.39319 8.22329 - 8.09021 7.99155 7.92938 7.90307 7.90035 7.86964 - 7.70976 7.51837 7.14795 6.51391 4.70910 3.53057 - 1.65236 1.30434 0.98185 0.94326 0.91521 0.91274 - 12.82327 11.89083 11.32201 10.80235 10.32918 9.90124 - 9.51779 9.17876 8.88425 8.63409 8.42795 8.26495 - 8.14257 8.05854 8.01220 7.99625 7.99769 7.98993 - 7.90631 7.77796 7.48407 6.94142 5.23654 3.97750 - 1.86429 1.44038 1.00886 0.94790 0.91761 0.91175 - 12.77108 11.89360 11.32708 10.80841 10.33593 9.90907 - 9.52746 9.19094 8.89966 8.65300 8.44995 8.28956 - 8.17077 8.09261 8.05473 8.05004 8.06745 8.08788 - 8.04659 7.94446 7.69817 7.23288 5.64672 4.35200 - 2.05692 1.56501 1.03521 0.95639 0.92290 0.91115 - 12.73305 11.89448 11.33029 10.81263 10.34087 9.91528 - 9.53523 9.20021 8.91003 8.66462 8.46388 8.30723 - 8.19262 8.11845 8.08495 8.08638 8.11315 8.14778 - 8.14117 8.07459 7.86956 7.42877 5.92344 4.71878 - 2.24678 1.66946 1.06150 0.97551 0.91905 0.91076 - 12.68703 11.89546 11.33343 10.81743 10.34724 9.92335 - 9.54508 9.21205 8.92413 8.68127 8.48342 8.33008 - 8.21936 8.15016 8.12323 8.13393 8.17439 8.23104 - 8.26427 8.23340 8.09114 7.73621 6.38485 5.23228 - 2.59239 1.88529 1.11551 0.99968 0.92365 0.91026 - 12.65872 11.89599 11.33511 10.82037 10.35139 9.92852 - 9.55126 9.21933 8.93278 8.69154 8.49550 8.34417 - 8.23588 8.16974 8.14692 8.16331 8.21221 8.28282 - 8.34144 8.33369 8.23457 7.94293 6.71914 5.62554 - 2.89753 2.08283 1.16884 1.02514 0.92866 0.90996 - 12.61636 11.89680 11.33721 10.82420 10.35707 9.93572 - 9.55974 9.22919 8.94439 8.70532 8.51176 8.36323 - 8.25830 8.19649 8.17936 8.20347 8.26385 8.35392 - 8.44853 8.47400 8.43973 8.25128 7.26722 6.31000 - 3.52811 2.52064 1.29829 1.09180 0.94163 0.90957 - 12.59208 11.89719 11.33837 10.82617 10.35991 9.93925 - 9.56399 9.23419 8.95025 8.71221 8.51987 8.37282 - 8.26972 8.21021 8.19607 8.22414 8.29043 8.39071 - 8.50462 8.54808 8.54901 8.42213 7.60663 6.75763 - 4.02104 2.89761 1.42228 1.16002 0.95464 0.90937 - 12.56537 11.89767 11.33971 10.82804 10.36236 9.94245 - 9.56807 9.23920 8.95616 8.71903 8.52782 8.38229 - 8.28105 8.22388 8.21277 8.24497 8.31744 8.42815 - 8.56228 8.62476 8.66242 8.60500 8.01084 7.31894 - 4.75455 3.50452 1.65282 1.29404 0.98092 0.90917 - 12.57293 11.90495 11.33894 10.82382 10.35748 9.93878 - 9.56655 9.24017 8.95932 8.72384 8.53359 8.38774 - 8.28373 8.22145 8.20712 8.24736 8.34349 8.47158 - 8.59937 8.65968 8.71033 8.69614 8.25521 7.65573 - 5.27470 3.98367 1.86432 1.42364 1.00653 0.90907 - 12.56355 11.90467 11.33905 10.82417 10.35826 9.93976 - 9.56777 9.24165 8.96105 8.72588 8.53596 8.39052 - 8.28704 8.22548 8.21212 8.25375 8.35193 8.48318 - 8.61705 8.68364 8.74706 8.75676 8.40396 7.88841 - 5.67228 4.36813 2.07638 1.54764 1.03289 0.90901 - 12.55706 11.90452 11.33916 10.82451 10.35872 9.94043 - 9.56863 9.24268 8.96227 8.72730 8.53762 8.39247 - 8.28934 8.22825 8.21553 8.25807 8.35761 8.49099 - 8.62904 8.69987 8.77173 8.79774 8.50879 8.05636 - 5.98619 4.69031 2.27326 1.66849 1.05928 0.90897 - 12.52719 11.89765 11.34097 10.82996 10.36479 9.94588 - 9.57276 9.24530 8.96369 8.72800 8.53825 8.39428 - 8.29505 8.24068 8.23351 8.27134 8.35217 8.47630 - 8.63723 8.72582 8.81191 8.85134 8.64305 8.28661 - 6.45761 5.20411 2.62397 1.91296 1.11269 0.90892 - 12.52376 11.89741 11.34048 10.83018 10.36582 9.94711 - 9.57372 9.24591 8.96422 8.72873 8.53934 8.39579 - 8.29703 8.24312 8.23641 8.27468 8.35611 8.48172 - 8.64640 8.73834 8.83001 8.88229 8.73427 8.43218 - 6.79524 5.60399 2.92930 2.12836 1.16540 0.90889 - 1.39498 1.44394 1.49305 1.54245 1.59189 1.64110 - 1.68978 1.73759 1.78419 1.82933 1.87280 1.91467 - 1.95562 1.99610 2.03566 2.07365 2.10960 2.14417 - 2.17809 2.19493 2.21300 2.22965 2.25249 2.25993 - 2.26475 2.26504 2.26536 2.26542 2.26522 2.26593 - 1.82960 1.88617 1.94219 1.99796 2.05318 2.10751 - 2.16055 2.21192 2.26125 2.30829 2.35293 2.39542 - 2.43684 2.47808 2.51890 2.55902 2.59852 2.63908 - 2.68190 2.70293 2.72141 2.73387 2.75080 2.75704 - 2.76209 2.76266 2.76162 2.76059 2.76144 2.76519 - 2.20028 2.26602 2.32918 2.39020 2.44868 2.50432 - 2.55692 2.60652 2.65339 2.69759 2.73936 2.77940 - 2.81957 2.86135 2.90416 2.94635 2.98663 3.02679 - 3.06776 3.08735 3.10587 3.11964 3.13462 3.13885 - 3.14328 3.14378 3.14302 3.14252 3.14264 3.14598 - 2.81094 2.89328 2.96803 3.03585 3.09640 3.14972 - 3.19650 3.23839 3.27773 3.31510 3.35073 3.38498 - 3.41895 3.45358 3.48864 3.52356 3.55812 3.59379 - 3.63184 3.65099 3.66860 3.68087 3.69385 3.69719 - 3.69931 3.69947 3.70001 3.70029 3.70016 3.69949 - 3.30261 3.40245 3.48528 3.55356 3.60961 3.65659 - 3.69603 3.73008 3.76164 3.79130 3.81911 3.84511 - 3.86983 3.89397 3.91806 3.94341 3.97111 4.00036 - 4.03075 4.04677 4.06280 4.07481 4.08558 4.08871 - 4.08888 4.08850 4.09036 4.09159 4.09077 4.08689 - 3.71710 3.82051 3.90785 3.98028 4.03757 4.08040 - 4.11089 4.13308 4.15242 4.17024 4.18695 4.20292 - 4.21898 4.23586 4.25330 4.27060 4.28750 4.30611 - 4.32909 4.34239 4.35615 4.36664 4.37575 4.37854 - 4.37737 4.37653 4.37909 4.38136 4.37989 4.37397 - 4.07106 4.18066 4.27059 4.34233 4.39574 4.43184 - 4.45337 4.46538 4.47451 4.48241 4.48953 4.49630 - 4.50336 4.51137 4.52004 4.52851 4.53649 4.54630 - 4.56113 4.57095 4.58194 4.59081 4.59793 4.60030 - 4.59835 4.59730 4.60017 4.60278 4.60108 4.59427 - 4.65210 4.76757 4.85744 4.92398 4.96729 4.98899 - 4.99283 4.98547 4.97535 4.96468 4.95386 4.94346 - 4.93387 4.92555 4.91814 4.91048 4.90212 4.89584 - 4.89568 4.89865 4.90313 4.90726 4.91008 4.91135 - 4.90905 4.90806 4.91048 4.91274 4.91127 4.90536 - 5.11592 5.23110 5.31615 5.37413 5.40545 5.41227 - 5.39913 5.37388 5.34628 5.31881 5.29199 5.26637 - 5.24216 5.21965 5.19835 5.17681 5.15435 5.13425 - 5.12112 5.11779 5.11539 5.11381 5.11226 5.11225 - 5.11047 5.10989 5.11110 5.11227 5.11150 5.10841 - 5.97550 6.07533 6.13709 6.16609 6.16358 6.13289 - 6.08009 6.01502 5.94957 5.88657 5.82683 5.77053 - 5.71756 5.66755 5.61969 5.57165 5.52219 5.47549 - 5.43687 5.42036 5.40232 5.38696 5.37587 5.37288 - 5.37310 5.37372 5.37149 5.36954 5.37080 5.37586 - 6.57303 6.68559 6.72071 6.69785 6.63729 6.56097 - 6.47565 6.38658 6.29966 6.21547 6.13313 6.05200 - 5.97400 5.90018 5.83018 5.76227 5.69599 5.63596 - 5.58032 5.54905 5.51729 5.49397 5.47520 5.46917 - 5.47111 5.47258 5.46741 5.46384 5.46622 5.47761 - 7.44819 7.46042 7.42373 7.35024 7.24356 7.10961 - 6.95744 6.80005 6.65154 6.51586 6.39303 6.28160 - 6.17995 6.08507 5.99513 5.90559 5.81337 5.72316 - 5.64005 5.59921 5.55220 5.51155 5.48293 5.47459 - 5.47660 5.47882 5.47162 5.46519 5.46940 5.48600 - 8.04608 7.99402 7.89133 7.75384 7.58625 7.39555 - 7.19175 6.98862 6.80064 6.63157 6.48099 6.34620 - 6.22416 6.11078 6.00365 5.89771 5.78923 5.68240 - 5.58186 5.53218 5.47670 5.42962 5.39380 5.38379 - 5.38332 5.38500 5.37849 5.37284 5.37650 5.39096 - 8.50110 8.38668 8.22237 8.02706 7.80605 7.56709 - 7.32049 7.08002 6.86035 6.66464 6.49193 6.33842 - 6.19970 6.07098 5.94954 5.83028 5.70931 5.59008 - 5.47680 5.42148 5.36248 5.31367 5.27233 5.26144 - 5.25689 5.25732 5.25324 5.24999 5.25202 5.26014 - 8.84669 8.71909 8.50290 8.23490 7.94096 7.64715 - 7.36454 7.10318 6.87325 6.67117 6.48617 6.31046 - 6.14696 5.99784 5.86077 5.73101 5.60393 5.47820 - 5.35384 5.29304 5.23298 5.18625 5.14003 5.12858 - 5.11955 5.11840 5.11745 5.11727 5.11723 5.11735 - 9.36814 9.18876 8.87809 8.49831 8.10209 7.73627 - 7.40637 7.10971 6.84399 6.60538 6.38601 6.18049 - 5.99032 5.81761 5.65975 5.51233 5.36992 5.22584 - 5.08386 5.02129 4.96181 4.91468 4.86193 4.85066 - 4.83452 4.83110 4.83525 4.83887 4.83618 4.82405 - 9.92514 9.45475 8.99409 8.56287 8.15905 7.78139 - 7.42893 7.10073 6.79645 6.51692 6.26050 6.02503 - 5.80873 5.61173 5.43377 5.27433 5.12995 4.98570 - 4.82849 4.74977 4.68227 4.63961 4.58860 4.57095 - 4.55272 4.55036 4.55557 4.56006 4.55699 4.54016 - 10.54465 9.90115 9.28925 8.72719 8.21072 7.73621 - 7.30061 6.90249 6.54059 6.21266 5.91529 5.64413 - 5.39429 5.16324 4.95195 4.75877 4.58094 4.40725 - 4.22914 4.14260 4.06579 4.01362 3.95445 3.93705 - 3.92304 3.92146 3.92226 3.92359 3.92245 3.91701 - 10.89688 10.12763 9.41078 8.75976 8.16745 7.62889 - 7.13963 6.69649 6.29758 5.93856 5.61429 5.31909 - 5.04615 4.79125 4.55548 4.33781 4.13560 3.94106 - 3.74895 3.65665 3.57096 3.50855 3.44318 3.42802 - 3.42017 3.41960 3.41462 3.41172 3.41333 3.42305 - 11.33790 10.35455 9.47902 8.70623 8.01990 7.40969 - 6.86723 6.38224 5.94628 5.55303 5.19587 4.86784 - 4.56057 4.26897 3.99461 3.74057 3.50646 3.28894 - 3.08672 2.99158 2.89781 2.82541 2.75911 2.74222 - 2.73213 2.73169 2.72792 2.72538 2.72682 2.73313 - 11.62093 10.49473 9.51893 8.66828 7.92210 7.26525 - 6.68716 6.17396 5.71296 5.29666 4.91844 4.57121 - 4.24671 3.93950 3.64988 3.37918 3.12769 2.89264 - 2.67528 2.57476 2.47961 2.40838 2.33876 2.32198 - 2.30737 2.30534 2.30502 2.30583 2.30502 2.30252 - 11.82606 10.60112 9.55989 8.65717 7.87122 7.18341 - 6.58067 6.04723 5.56814 5.13503 4.74130 4.37999 - 4.04298 3.72483 3.42517 3.14431 2.88278 2.63780 - 2.40995 2.30414 2.20462 2.13083 2.05936 2.04248 - 2.02747 2.02529 2.02522 2.02631 2.02531 2.02192 - 11.98940 10.69166 9.60525 8.66601 7.85230 7.14359 - 6.52372 5.97545 5.48274 5.03678 4.63099 4.25856 - 3.91163 3.58484 3.27751 2.98954 2.72106 2.46944 - 2.23326 2.12245 2.01774 1.94011 1.86692 1.84967 - 1.83541 1.83354 1.83267 1.83304 1.83253 1.83090 - 12.24623 10.84866 9.70612 8.72186 7.87441 7.14144 - 6.50146 5.93472 5.42396 4.96035 4.53747 4.14876 - 3.78680 3.44651 3.12700 2.82782 2.54812 2.28476 - 2.03358 1.91366 1.79947 1.71455 1.63627 1.61763 - 1.60360 1.60205 1.60013 1.59956 1.59965 1.60046 - 12.44439 10.98455 9.81154 8.80409 7.94036 7.19569 - 6.54585 5.96933 5.44812 4.97357 4.53951 4.13954 - 3.76650 3.41545 3.08553 2.77625 2.48600 2.21002 - 1.94387 1.81516 1.69208 1.59996 1.51438 1.49377 - 1.47811 1.47637 1.47435 1.47379 1.47385 1.47478 - 12.76203 11.23927 10.04665 9.02405 8.15209 7.39715 - 6.73640 6.14825 5.61506 5.12807 4.68082 4.26638 - 3.87677 3.50676 3.15594 2.82451 2.51003 2.20362 - 1.89939 1.74783 1.59833 1.48221 1.37313 1.34645 - 1.32489 1.32234 1.32039 1.32021 1.31993 1.31995 - 12.92862 11.40549 10.23050 9.21966 8.35545 7.60063 - 6.93631 6.34365 5.80721 5.31789 4.86816 4.44972 - 4.05275 3.67104 3.30494 2.95583 2.62112 2.28860 - 1.94763 1.77257 1.59217 1.44600 1.30989 1.27713 - 1.25081 1.24761 1.24480 1.24441 1.24417 1.24458 - 13.09034 11.59084 10.46939 9.50675 8.67536 7.94154 - 7.28915 6.70185 6.16602 5.67388 5.21913 4.79477 - 4.39232 4.00511 3.62980 3.26170 2.89380 2.51393 - 2.10718 1.88814 1.65261 1.44926 1.24693 1.20336 - 1.17600 1.17228 1.16508 1.16339 1.16385 1.16807 - 13.09249 11.68007 10.64249 9.73732 8.93435 8.21157 - 7.56007 6.97096 6.43683 5.95019 5.50315 5.08660 - 4.68916 4.30200 3.92132 3.54181 3.15408 2.73996 - 2.27717 2.01968 1.73830 1.49021 1.22309 1.15938 - 1.13500 1.13301 1.12107 1.11759 1.11975 1.12620 - 13.11744 11.72836 10.73784 9.87254 9.09918 8.39942 - 7.76561 7.18982 6.66546 6.18571 5.74334 5.32982 - 4.93430 4.54791 4.16613 3.78221 3.38407 2.94780 - 2.44303 2.15345 1.82876 1.53790 1.21493 1.13501 - 1.10834 1.10683 1.09199 1.08752 1.09067 1.09705 - 13.12573 11.75562 10.80586 9.97277 9.22468 8.54507 - 7.92734 7.36428 6.84988 6.37790 5.94162 5.53294 - 5.14141 4.75818 4.37810 3.99327 3.58920 3.13699 - 2.59873 2.28225 1.92028 1.59059 1.21636 1.12086 - 1.08928 1.08784 1.07107 1.06599 1.06982 1.07501 - 13.10735 11.77328 10.89373 10.11330 9.40783 8.76260 - 8.17267 7.63195 7.13554 6.67822 6.25420 5.85643 - 5.47553 5.10296 4.73236 4.35337 3.94644 3.47151 - 2.87598 2.51274 2.08793 1.69568 1.24887 1.12493 - 1.05158 1.05049 1.05003 1.04590 1.03337 1.04373 - 13.09172 11.78144 10.95049 10.20679 9.53226 8.91322 - 8.34555 7.82390 7.34401 6.90122 6.49032 6.10480 - 5.73585 5.37503 5.01536 4.64508 4.24140 3.75678 - 3.12620 2.72963 2.25441 1.80483 1.28150 1.13150 - 1.03580 1.03246 1.03174 1.02748 1.01324 1.02262 - 13.12916 11.82910 11.04778 10.34602 9.71033 9.12875 - 8.59753 8.11170 7.66715 7.25923 6.88252 6.52988 - 6.19116 5.85699 5.52084 5.17166 4.78758 4.32113 - 3.68324 3.24296 2.65808 2.06372 1.35701 1.15800 - 1.03296 1.01828 0.99617 0.99229 0.99127 0.99171 - 13.09938 11.82553 11.08714 10.42242 9.81878 9.26641 - 8.76202 8.30129 7.88063 7.49591 7.14220 6.81283 - 6.49804 6.18858 5.87768 5.55340 5.19118 4.73634 - 4.08665 3.62425 2.99543 2.32912 1.46871 1.21023 - 1.02635 1.00447 0.98113 0.97736 0.97592 0.97505 - 13.02095 11.79153 11.11589 10.50406 9.94593 9.43411 - 8.96618 8.53897 8.14974 7.79545 7.47237 7.17527 - 6.89615 6.62695 6.36069 6.08384 5.76668 5.33950 - 4.67972 4.19259 3.51856 2.77207 1.70488 1.34966 - 1.03021 0.98955 0.96526 0.96193 0.95145 0.95739 - 13.01592 11.79614 11.14281 10.55112 10.01239 9.52020 - 9.07229 8.66574 8.29808 7.96647 7.66736 7.39558 - 7.14301 6.90167 6.66542 6.42182 6.14241 5.75784 - 5.13741 4.65754 3.96258 3.15075 1.90507 1.46909 - 1.05316 0.99385 0.95344 0.94985 0.94374 0.94806 - 13.00081 11.80224 11.16989 10.59379 10.06691 9.58464 - 9.14568 8.74850 8.39203 8.07398 7.79125 7.53920 - 7.31030 7.09613 6.88753 6.66556 6.40052 6.04118 - 5.47560 5.03235 4.36481 3.52328 2.09155 1.57232 - 1.06704 0.99604 0.95235 0.94958 0.94282 0.94230 - 12.99195 11.80487 11.18372 10.61780 10.10066 9.62820 - 9.19894 8.81140 8.46447 8.15630 7.88441 7.64503 - 7.43191 7.23754 7.05286 6.85807 6.62184 6.28991 - 5.74828 5.31764 4.66456 3.82141 2.28555 1.68091 - 1.08666 1.00473 0.95126 0.94473 0.94081 0.93840 - 12.99623 11.81811 11.20361 10.64607 10.13960 9.68025 - 9.26583 8.89437 8.56413 8.27317 8.01898 7.79765 - 7.60247 7.42717 7.26783 7.11461 6.94068 6.67278 - 6.17830 5.77025 5.14779 4.30500 2.61556 1.89936 - 1.13549 1.02396 0.94913 0.94240 0.93530 0.93345 - 12.96831 11.81591 11.21716 10.67221 10.17598 9.72525 - 9.31828 8.95350 8.62978 8.34595 8.10067 7.89175 - 7.71498 7.56504 7.43444 7.30470 7.14674 6.91113 - 6.48445 6.11562 5.52219 4.68806 2.91783 2.09117 - 1.18510 1.05149 0.95020 0.94076 0.92969 0.93042 - 12.94616 11.82827 11.24406 10.71086 10.22483 9.78366 - 9.38630 9.03224 8.72109 8.45199 8.22382 8.03460 - 7.88016 7.75615 7.65791 7.57177 7.47394 7.31784 - 6.99823 6.69590 6.16823 5.37678 3.52751 2.54312 - 1.30775 1.11145 0.95740 0.94208 0.92804 0.92634 - 12.93608 11.84364 11.25841 10.72669 10.24438 9.80894 - 9.41893 9.07330 8.77100 8.51101 8.29210 8.11206 - 7.96636 7.85173 7.76853 7.71335 7.66896 7.57488 - 7.31544 7.05415 6.59497 5.86483 3.98992 2.92366 - 1.42962 1.17809 0.96737 0.94506 0.92568 0.92430 - 12.85594 11.84997 11.27175 10.74615 10.26970 9.84017 - 9.45635 9.11727 8.82213 8.57019 8.36057 8.19154 - 8.05925 7.96132 7.89983 7.87414 7.87206 7.84211 - 7.68354 7.49342 7.12557 6.49579 4.70142 3.52845 - 1.65757 1.31124 0.99113 0.95289 0.92463 0.92223 - 12.76451 11.84241 11.27610 10.75867 10.28767 9.86153 - 9.47977 9.14221 8.84902 8.59998 8.39481 8.23263 - 8.11095 8.02755 7.98177 7.96641 7.96849 7.96144 - 7.87879 7.75136 7.45937 6.92052 5.22652 3.97307 - 1.86859 1.44674 1.01792 0.95739 0.92693 0.92119 - 12.71338 11.84518 11.28116 10.76470 10.29418 9.86919 - 9.48919 9.15414 8.86416 8.61864 8.41654 8.25697 - 8.13881 8.06113 8.02365 8.01937 8.03739 8.05866 - 8.01831 7.91665 7.67180 7.21012 5.63491 4.34531 - 2.06045 1.57106 1.04404 0.96563 0.93224 0.92057 - 12.67623 11.84607 11.28436 10.76889 10.29909 9.87528 - 9.49684 9.16326 8.87433 8.63002 8.43021 8.27432 - 8.16031 8.08665 8.05355 8.05530 8.08243 8.11771 - 8.11218 8.04616 7.84212 7.40403 5.90995 4.71139 - 2.24921 1.67468 1.07014 0.98481 0.92836 0.92015 - 12.63131 11.84705 11.28738 10.77357 10.30532 9.88321 - 9.50654 9.17493 8.88823 8.64642 8.44943 8.29680 - 8.18666 8.11789 8.09127 8.10221 8.14295 8.19992 - 8.23389 8.20381 8.06255 7.70968 6.36818 5.22222 - 2.59333 1.88969 1.12376 1.00871 0.93297 0.91963 - 12.60371 11.84758 11.28905 10.77650 10.30935 9.88828 - 9.51260 9.18205 8.89671 8.65650 8.46132 8.31070 - 8.20292 8.13719 8.11462 8.13121 8.18027 8.25094 - 8.31010 8.30327 8.20528 7.91536 6.69995 5.61327 - 2.89724 2.08654 1.17672 1.03390 0.93798 0.91931 - 12.56251 11.84830 11.29114 10.78020 10.31500 9.89535 - 9.52093 9.19175 8.90815 8.67008 8.47734 8.32945 - 8.22499 8.16349 8.14655 8.17075 8.23117 8.32103 - 8.41583 8.44221 8.40917 8.22213 7.24391 6.29355 - 3.52542 2.52277 1.30538 1.09994 0.95096 0.91889 - 12.53874 11.84869 11.29219 10.78216 10.31773 9.89880 - 9.52509 9.19665 8.91391 8.67685 8.48530 8.33887 - 8.23621 8.17699 8.16298 8.19108 8.25733 8.35734 - 8.47128 8.51538 8.51745 8.39189 7.58106 6.73831 - 4.01645 2.89808 1.42865 1.16761 0.96397 0.91868 - 12.51258 11.84907 11.29343 10.78392 10.32006 9.90192 - 9.52908 9.20155 8.91967 8.68354 8.49313 8.34816 - 8.24735 8.19042 8.17941 8.21155 8.28384 8.39431 - 8.52831 8.59099 8.62938 8.57329 7.98293 7.29602 - 4.74708 3.50235 1.65798 1.30071 0.99015 0.91848 - 12.52038 11.85616 11.29255 10.77960 10.31528 9.89824 - 9.52754 9.20250 8.92279 8.68828 8.49879 8.35354 - 8.24992 8.18791 8.17366 8.21379 8.30963 8.43736 - 8.56494 8.62538 8.67659 8.66346 8.22588 7.63071 - 5.26487 3.97929 1.86845 1.42957 1.01557 0.91838 - 12.51121 11.85588 11.29266 10.77995 10.31596 9.89920 - 9.52875 9.20396 8.92451 8.69028 8.50113 8.35629 - 8.25320 8.19189 8.17858 8.22007 8.31792 8.44876 - 8.58231 8.64897 8.71287 8.72352 8.37360 7.86197 - 5.66059 4.36193 2.07935 1.55299 1.04172 0.91832 - 12.50498 11.85573 11.29277 10.78028 10.31641 9.89985 - 9.52957 9.20495 8.92568 8.69166 8.50274 8.35816 - 8.25543 8.19457 8.18191 8.22430 8.32348 8.45641 - 8.59412 8.66493 8.73721 8.76404 8.47774 8.02894 - 5.97279 4.68245 2.27513 1.67335 1.06790 0.91827 - 12.47540 11.84916 11.29468 10.78572 10.32247 9.90526 - 9.53366 9.20752 8.92706 8.69233 8.50334 8.35993 - 8.26108 8.20691 8.19975 8.23743 8.31795 8.44165 - 8.60214 8.69057 8.77670 8.81677 8.61142 8.25750 - 6.44130 5.19357 2.62411 1.91642 1.12085 0.91822 - 12.47219 11.84902 11.29449 10.78625 10.32371 9.90657 - 9.53463 9.20812 8.92755 8.69302 8.50440 8.36144 - 8.26306 8.20934 8.20263 8.24074 8.32185 8.44696 - 8.61105 8.70280 8.79438 8.84714 8.70195 8.40227 - 6.77658 5.59115 2.92811 2.13087 1.17312 0.91818 - 1.35561 1.40381 1.45227 1.50112 1.55015 1.59910 - 1.64767 1.69553 1.74238 1.78795 1.83199 1.87456 - 1.91618 1.95725 1.99721 2.03538 2.07119 2.10529 - 2.13832 2.15454 2.17193 2.18803 2.21048 2.21784 - 2.22221 2.22244 2.22292 2.22305 2.22284 2.22357 - 1.78284 1.84289 1.90134 1.95837 2.01367 2.06699 - 2.11816 2.16729 2.21464 2.26027 2.30427 2.34717 - 2.39039 2.43497 2.48005 2.52355 2.56359 2.60146 - 2.63876 2.65709 2.67554 2.69061 2.70772 2.71228 - 2.71573 2.71624 2.71658 2.71654 2.71660 2.72089 - 2.14761 2.21882 2.28557 2.34822 2.40646 2.46031 - 2.51019 2.55726 2.60322 2.64837 2.69266 2.73602 - 2.77878 2.82121 2.86314 2.90460 2.94559 2.98602 - 3.02517 3.04376 3.06198 3.07616 3.09092 3.09483 - 3.09785 3.09822 3.09852 3.09850 3.09854 3.10210 - 2.75354 2.83864 2.91549 2.98469 3.04594 3.09940 - 3.14599 3.18783 3.22781 3.26659 3.30425 3.34080 - 3.37673 3.41245 3.44797 3.48344 3.51911 3.55527 - 3.59179 3.60978 3.62739 3.64070 3.65332 3.65649 - 3.65908 3.65937 3.65962 3.65968 3.65970 3.65894 - 3.24277 3.34172 3.42494 3.49458 3.55253 3.60148 - 3.64286 3.67876 3.71213 3.74360 3.77333 3.80138 - 3.82811 3.85403 3.87958 3.90601 3.93433 3.96368 - 3.99385 4.00986 4.02598 4.03826 4.04929 4.05213 - 4.05443 4.05466 4.05486 4.05495 4.05497 4.05056 - 3.65585 3.75643 3.84250 3.91526 3.97436 4.02029 - 4.05474 4.08113 4.10406 4.12474 4.14355 4.16110 - 4.17858 4.19701 4.21612 4.23499 4.25314 4.27256 - 4.29579 4.30909 4.32314 4.33425 4.34360 4.34599 - 4.34805 4.34824 4.34839 4.34851 4.34852 4.34181 - 4.01499 4.11175 4.19488 4.26580 4.32385 4.36887 - 4.40149 4.42348 4.43764 4.44522 4.44797 4.44897 - 4.45377 4.46647 4.48457 4.50040 4.50802 4.51478 - 4.53001 4.54104 4.55292 4.56212 4.56965 4.57153 - 4.57327 4.57339 4.57356 4.57374 4.57368 4.56597 - 4.59746 4.69598 4.77684 4.84214 4.89127 4.92426 - 4.94211 4.94725 4.94327 4.93191 4.91531 4.89739 - 4.88461 4.88168 4.88554 4.88680 4.87832 4.86905 - 4.87001 4.87457 4.88025 4.88488 4.88825 4.88913 - 4.89007 4.89010 4.89020 4.89035 4.89030 4.88362 - 5.06287 5.15942 5.23477 5.29174 5.32985 5.34936 - 5.35171 5.33999 5.31858 5.28959 5.25558 5.22104 - 5.19310 5.17684 5.16853 5.15712 5.13437 5.11121 - 5.10000 5.09834 5.09736 5.09652 5.09547 5.09540 - 5.09541 5.09536 5.09537 5.09546 5.09542 5.09195 - 5.91389 6.01230 6.07442 6.10543 6.10638 6.08027 - 6.03270 5.97281 5.91168 5.85202 5.79473 5.74026 - 5.68894 5.64085 5.59528 5.55012 5.50414 5.46096 - 5.42521 5.40984 5.39287 5.37829 5.36831 5.36600 - 5.36375 5.36352 5.36336 5.36326 5.36328 5.36902 - 6.51159 6.62965 6.66947 6.65041 6.59288 6.51919 - 6.43636 6.34993 6.26613 6.18526 6.10571 6.02657 - 5.95035 5.87867 5.81121 5.74620 5.68312 5.62663 - 5.57444 5.54450 5.51398 5.49145 5.47383 5.46918 - 5.46541 5.46511 5.46482 5.46457 5.46457 5.47736 - 7.38793 7.42850 7.40340 7.32839 7.21313 7.07028 - 6.91257 6.75684 6.62036 6.50171 6.39010 6.27868 - 6.17220 6.07345 5.98138 5.89220 5.80414 5.72389 - 5.64719 5.60155 5.55410 5.51843 5.49090 5.48348 - 5.47742 5.47693 5.47648 5.47609 5.47609 5.49464 - 7.99289 7.96867 7.87958 7.74351 7.56886 7.36737 - 7.15428 6.95008 6.77510 6.62623 6.48877 6.35299 - 6.22436 6.10626 5.99698 5.89164 5.78718 5.68949 - 5.59463 5.54053 5.48476 5.44243 5.40789 5.39876 - 5.39134 5.39065 5.39005 5.38968 5.38968 5.40576 - 8.44566 8.37159 8.22234 8.02332 7.78959 7.53867 - 7.28540 7.04780 6.84362 6.66871 6.50829 6.35231 - 6.20577 6.07191 5.94868 5.83084 5.71443 5.60259 - 5.49309 5.43493 5.37614 5.33111 5.29106 5.28084 - 5.27261 5.27170 5.27097 5.27072 5.27068 5.27971 - 8.80190 8.68958 8.48432 8.22300 7.93229 7.63937 - 7.35660 7.09571 6.86845 6.67047 6.48913 6.31566 - 6.15380 6.00636 5.87097 5.74267 5.61684 5.49305 - 5.37138 5.31158 5.25258 5.20698 5.16244 5.15149 - 5.14277 5.14163 5.14080 5.14067 5.14060 5.14076 - 9.33505 9.15864 8.85306 8.47946 8.08969 7.72989 - 7.40530 7.11292 6.85018 6.61369 6.39650 6.19357 - 6.00592 5.83513 5.67869 5.53234 5.39086 5.24818 - 5.10802 5.04616 4.98748 4.94153 4.89035 4.87836 - 4.86894 4.86749 4.86649 4.86658 4.86645 4.85308 - 9.88868 9.42538 8.97153 8.54663 8.14868 7.77646 - 7.42903 7.10552 6.80555 6.52994 6.27705 6.04467 - 5.83097 5.63596 5.45939 5.30077 5.15678 5.01287 - 4.85657 4.77872 4.71259 4.67111 4.61949 4.60269 - 4.59337 4.59262 4.59114 4.59110 4.59118 4.57276 - 10.51113 9.87523 9.27060 8.71528 8.20510 7.73647 - 7.30639 6.91342 6.55632 6.23280 5.93943 5.67179 - 5.42481 5.19578 4.98568 4.79292 4.61494 4.44108 - 4.26341 4.17737 4.10116 4.04943 3.99024 3.97321 - 3.96218 3.96113 3.95976 3.95963 3.95949 3.95342 - 10.86961 10.10859 9.39914 8.75479 8.16852 7.63546 - 7.15123 6.71269 6.31793 5.96266 5.64175 5.34948 - 5.07889 4.82571 4.59100 4.37380 4.17165 3.97719 - 3.78551 3.69337 3.60742 3.54468 3.48042 3.46516 - 3.45238 3.45090 3.44981 3.44954 3.44932 3.45980 - 11.32703 10.34842 9.47788 8.71034 8.02937 7.42437 - 6.88668 6.40569 5.97265 5.58136 5.22547 4.89830 - 4.59186 4.30123 4.02788 3.77474 3.54134 3.32429 - 3.12226 3.02704 2.93299 2.86011 2.79361 2.77716 - 2.76371 2.76219 2.76094 2.76067 2.76056 2.76752 - 11.60714 10.49607 9.53006 8.68554 7.94287 7.28776 - 6.71031 6.19742 5.73706 5.32178 4.94486 4.59908 - 4.27592 3.96979 3.68097 3.41081 3.15962 2.92481 - 2.70774 2.60733 2.51211 2.44067 2.37050 2.35334 - 2.33995 2.33836 2.33697 2.33684 2.33667 2.33398 - 11.80969 10.60675 9.57817 8.68197 7.89817 7.20976 - 6.60500 6.06953 5.58967 5.15702 4.76463 4.40511 - 4.06975 3.75273 3.45371 3.17316 2.91168 2.66685 - 2.43948 2.33397 2.23455 2.16064 2.08864 2.07132 - 2.05789 2.05626 2.05484 2.05473 2.05455 2.05085 - 11.97096 10.69865 9.62630 8.69366 7.88135 7.17082 - 6.54761 5.99619 5.50203 5.05626 4.65180 4.28129 - 3.93610 3.61043 3.30367 3.01586 2.74737 2.49592 - 2.26039 2.15000 2.04548 1.96776 1.89415 1.87663 - 1.86295 1.86131 1.85987 1.85974 1.85956 1.85777 - 12.22486 10.85173 9.72226 8.74439 7.89858 7.16425 - 6.52151 5.95217 5.44024 4.97683 4.55511 4.16804 - 3.80755 3.46821 3.14920 2.85027 2.57074 2.30775 - 2.05737 1.93792 1.82399 1.73900 1.66042 1.64175 - 1.62705 1.62530 1.62379 1.62361 1.62344 1.62432 - 12.42099 10.97907 9.81604 8.81457 7.95387 7.21027 - 6.56042 5.98365 5.46261 4.98867 4.55551 4.15658 - 3.78446 3.43411 3.10473 2.79592 2.50622 2.23090 - 1.96554 1.83723 1.71440 1.62228 1.53641 1.51576 - 1.49950 1.49758 1.49594 1.49573 1.49554 1.49659 - 12.73168 11.21828 10.03160 9.01477 8.14800 7.39781 - 6.74120 6.15637 5.62547 5.13988 4.69340 4.27936 - 3.89012 3.52062 3.17046 2.83984 2.52631 2.22089 - 1.91755 1.76640 1.61724 1.50129 1.39199 1.36518 - 1.34370 1.34119 1.33911 1.33883 1.33862 1.33865 - 12.88941 11.38086 10.21412 9.20969 8.35018 7.59910 - 6.93770 6.34738 5.81283 5.32503 4.87653 4.45914 - 4.06311 3.68227 3.31696 2.96853 2.63446 2.30284 - 1.96317 1.78881 1.60900 1.46311 1.32698 1.29418 - 1.26774 1.26450 1.26174 1.26140 1.26113 1.26150 - 13.03684 11.57039 10.46578 9.51134 8.68202 7.94658 - 7.29086 6.70045 6.16343 5.67198 5.21924 4.79756 - 4.39765 4.01231 3.63820 3.27076 2.90323 2.52405 - 2.11884 1.90085 1.66640 1.46392 1.26217 1.21825 - 1.18901 1.18525 1.17944 1.17833 1.17885 1.18293 - 13.06882 11.66907 10.63648 9.73435 8.93331 8.21177 - 7.56096 6.97217 6.43807 5.95128 5.50404 5.08736 - 4.69007 4.30344 3.92369 3.54551 3.15951 2.74737 - 2.28671 2.03036 1.75015 1.50309 1.23710 1.17292 - 1.14510 1.14301 1.13372 1.13133 1.13352 1.13987 - 13.09650 11.72029 10.73400 9.87112 9.09907 8.39994 - 7.76622 7.19015 6.66521 6.18474 5.74165 5.32757 - 4.93190 4.54593 4.16516 3.78283 3.38679 2.95294 - 2.45071 2.16246 1.83918 1.54954 1.22797 1.14754 - 1.11690 1.11530 1.10362 1.10045 1.10364 1.10994 - 13.10468 11.74788 10.80214 9.97128 9.22426 8.54503 - 7.92711 7.36342 6.84811 6.37507 5.93772 5.52819 - 5.13631 4.75344 4.37446 3.99144 3.58980 3.14035 - 2.60494 2.28995 1.92956 1.60123 1.22859 1.13262 - 1.09708 1.09557 1.08208 1.07835 1.08223 1.08734 - 13.08358 11.76351 10.88772 10.10931 9.40482 8.75985 - 8.16959 7.62810 7.13059 6.67200 6.24670 5.84787 - 5.46645 5.09413 4.72462 4.34758 3.94342 3.47185 - 2.88004 2.51882 2.09608 1.70529 1.25918 1.13483 - 1.05970 1.05850 1.05962 1.05659 1.04612 1.05532 - 13.06284 11.76776 10.94077 10.19948 9.52618 8.90758 - 8.33972 7.81736 7.33636 6.89225 6.47997 6.09328 - 5.72374 5.36320 5.00473 4.63660 4.23600 3.75506 - 3.12852 2.73411 2.26114 1.81323 1.29095 1.14074 - 1.04378 1.04043 1.04114 1.03783 1.02536 1.03375 - 13.08822 11.80559 11.02935 10.33103 9.69734 9.11680 - 8.58577 8.09944 7.65386 7.24455 6.86637 6.51246 - 6.17323 5.83969 5.50538 5.15923 4.77922 4.31719 - 3.68325 3.24459 2.66097 2.06811 1.36532 1.16731 - 1.04085 1.02580 1.00584 1.00348 1.00131 1.00221 - 13.05121 11.79500 11.06174 10.40057 9.79934 9.24846 - 8.74477 8.28413 7.86302 7.47750 7.12283 6.79263 - 6.47759 6.16883 5.85967 5.53819 5.17984 4.72946 - 4.08420 3.62377 2.99655 2.33200 1.47583 1.21860 - 1.03479 1.01281 0.99077 0.98794 0.98576 0.98521 - 12.96469 11.75269 11.08170 10.47332 9.91788 9.40806 - 8.94157 8.51526 8.12654 7.77244 7.44936 7.15225 - 6.87340 6.60501 6.34020 6.06551 5.75134 5.32785 - 4.67249 4.18802 3.51709 2.77372 1.71081 1.35677 - 1.03897 0.99875 0.97503 0.97177 0.96121 0.96722 - 12.95651 11.75372 11.10452 10.51611 9.98004 9.48996 - 9.04368 8.63839 8.27164 7.94065 7.64197 7.37060 - 7.11860 6.87820 6.64335 6.40169 6.12489 5.74362 - 5.12742 4.65022 3.95858 3.15031 1.91002 1.47569 - 1.06194 1.00314 0.96323 0.95961 0.95318 0.95773 - 12.93581 11.75803 11.13172 10.55947 10.03480 9.55352 - 9.11478 8.71767 8.36165 8.04451 7.76305 7.51250 - 7.28511 7.07229 6.86497 6.64443 6.38121 6.02472 - 5.46375 5.02354 4.35940 3.52115 2.09485 1.57811 - 1.07602 1.00548 0.96193 0.95908 0.95231 0.95186 - 12.92944 11.76017 11.14330 10.58040 10.06543 9.59442 - 9.16618 8.77951 8.43361 8.12663 7.85604 7.61802 - 7.40615 7.21290 7.02923 6.83557 6.60090 6.27157 - 5.73445 5.30696 4.65770 3.81828 2.28799 1.68599 - 1.09548 1.01412 0.96079 0.95413 0.95020 0.94788 - 12.93598 11.77293 11.16091 10.60576 10.10135 9.64389 - 9.23124 8.86138 8.53261 8.24299 7.99001 7.76978 - 7.57559 7.40121 7.24277 7.09052 6.91786 6.65209 - 6.16148 5.75644 5.13810 4.29978 2.61676 1.90347 - 1.14387 1.03302 0.95857 0.95175 0.94462 0.94284 - 12.90942 11.77045 11.17352 10.63043 10.13614 9.68749 - 9.28254 8.91972 8.59775 8.31546 8.07149 7.86363 - 7.68766 7.53830 7.40819 7.27916 7.12246 6.88875 - 6.46538 6.09950 5.51036 4.68089 2.91767 2.09472 - 1.19307 1.06016 0.95957 0.95015 0.93892 0.93975 - 12.88750 11.78203 11.19925 10.66797 10.18402 9.74515 - 9.35013 8.99818 8.68875 8.42095 8.19372 8.00517 - 7.85130 7.72787 7.63021 7.54474 7.44769 7.29277 - 6.97544 6.67543 6.15198 5.36606 3.52529 2.54464 - 1.31480 1.11957 0.96671 0.95136 0.93725 0.93560 - 12.87590 11.79692 11.21428 10.68474 10.20452 9.77096 - 9.38269 9.03858 8.73768 8.47891 8.26107 8.08195 - 7.93702 7.82300 7.74030 7.68549 7.64146 7.54803 - 7.29038 7.03113 6.57589 5.85117 3.98557 2.92387 - 1.43597 1.18566 0.97655 0.95440 0.93485 0.93352 - 12.79772 11.80337 11.22768 10.70434 10.22990 9.80222 - 9.42004 9.08240 8.78854 8.53770 8.32902 8.16074 - 8.02909 7.93166 7.87055 7.84515 7.84330 7.81371 - 7.65622 7.46756 7.10274 6.47781 4.69398 3.52640 - 1.66271 1.31801 1.00014 0.96222 0.93376 0.93141 - 12.72985 11.80562 11.23353 10.71333 10.24188 9.81734 - 9.43847 9.10432 8.81428 8.56773 8.36398 8.20155 - 8.07695 7.98828 7.93863 7.92913 7.95082 7.95868 - 7.86404 7.72273 7.42356 6.88018 5.20639 3.99717 - 1.87206 1.44499 1.02569 0.97173 0.93439 0.93036 - 12.65863 11.79919 11.23767 10.72314 10.25450 9.83118 - 9.45276 9.11908 8.83026 8.58574 8.38446 8.22552 - 8.10788 8.03058 7.99337 7.98931 8.00757 8.02914 - 7.98928 7.88822 7.64510 7.18738 5.62318 4.33868 - 2.06390 1.57699 1.05268 0.97466 0.94132 0.92973 - 12.62240 11.80029 11.24097 10.72743 10.25947 9.83731 - 9.46036 9.12809 8.84034 8.59700 8.39800 8.24272 - 8.12919 8.05588 8.02302 8.02494 8.05222 8.08772 - 8.08272 8.01733 7.81440 7.37917 5.89642 4.70405 - 2.25168 1.67987 1.07861 0.99389 0.93743 0.92930 - 12.57854 11.80128 11.24408 10.73229 10.26582 9.84522 - 9.46996 9.13960 8.85405 8.61322 8.41704 8.26501 - 8.15530 8.08683 8.06041 8.07145 8.11224 8.16929 - 8.20361 8.17403 8.03361 7.68290 6.35146 5.21220 - 2.59428 1.89408 1.13186 1.01754 0.94205 0.92877 - 12.55151 11.80182 11.24575 10.73521 10.26986 9.85026 - 9.47597 9.14668 8.86245 8.62320 8.42882 8.27878 - 8.17142 8.10596 8.08355 8.10017 8.14923 8.21987 - 8.27926 8.27284 8.17560 7.88740 6.68073 5.60095 - 2.89699 2.09025 1.18447 1.04246 0.94707 0.92844 - 12.51113 11.80255 11.24784 10.73890 10.27541 9.85725 - 9.48419 9.15624 8.87374 8.63665 8.44469 8.29737 - 8.19329 8.13204 8.11518 8.13933 8.19960 8.28928 - 8.38411 8.41076 8.37837 8.19251 7.22052 6.27702 - 3.52277 2.52487 1.31233 1.10791 0.96007 0.92802 - 12.48784 11.80284 11.24878 10.74075 10.27808 9.86070 - 9.48835 9.16112 8.87947 8.64335 8.45256 8.30668 - 8.20440 8.14538 8.13144 8.15948 8.22554 8.32526 - 8.43906 8.48330 8.48591 8.36132 7.55530 6.71889 - 4.01198 2.89862 1.43493 1.17505 0.97306 0.92780 - 12.46249 11.80313 11.24992 10.74250 10.28041 9.86382 - 9.49232 9.16599 8.88518 8.64997 8.46029 8.31586 - 8.21540 8.15868 8.14771 8.17975 8.25182 8.36192 - 8.49555 8.55819 8.59690 8.54156 7.95468 7.27293 - 4.73975 3.50029 1.66309 1.30730 0.99920 0.92760 - 12.47082 11.81031 11.24894 10.73798 10.27549 9.86011 - 9.49086 9.16706 8.88840 8.65477 8.46595 8.32119 - 8.21794 8.15612 8.14191 8.18188 8.27741 8.40471 - 8.53189 8.59226 8.64362 8.63102 8.19633 7.60550 - 5.25517 3.97508 1.87264 1.43551 1.02447 0.92749 - 12.46195 11.81004 11.24905 10.73843 10.27616 9.86104 - 9.49202 9.16848 8.89008 8.65672 8.46824 8.32390 - 8.22117 8.16005 8.14679 8.18811 8.28561 8.41594 - 8.54908 8.61562 8.67962 8.69071 8.34306 7.83530 - 5.64891 4.35585 2.08246 1.55840 1.05045 0.92743 - 12.45576 11.80989 11.24916 10.73866 10.27661 9.86165 - 9.49281 9.16943 8.89122 8.65806 8.46983 8.32576 - 8.22339 8.16272 8.15008 8.19230 8.29111 8.42354 - 8.56075 8.63143 8.70375 8.73091 8.44652 8.00121 - 5.95938 4.67471 2.27719 1.67836 1.07641 0.92739 - 12.42648 11.80342 11.25107 10.74410 10.28250 9.86689 - 9.49677 9.17196 8.89257 8.65868 8.47035 8.32747 - 8.22899 8.17502 8.16787 8.20538 8.28553 8.40875 - 8.56869 8.65684 8.74284 8.78317 8.57963 8.22829 - 6.42500 5.18310 2.62445 1.92004 1.12898 0.92733 - 12.42328 11.80338 11.25097 10.74442 10.28334 9.86785 - 9.49758 9.17255 8.89312 8.65941 8.47140 8.32894 - 8.23093 8.17740 8.17070 8.20863 8.28940 8.41406 - 8.57755 8.66895 8.76027 8.81314 8.66961 8.37185 - 6.75786 5.57851 2.92717 2.13354 1.18084 0.92729 - 1.31818 1.36579 1.41372 1.46211 1.51075 1.55940 - 1.60777 1.65554 1.70241 1.74810 1.79238 1.83526 - 1.87724 1.91866 1.95894 1.99735 2.03328 2.06727 - 2.09978 2.11553 2.13232 2.14781 2.16954 2.17678 - 2.18122 2.18135 2.18141 2.18143 2.18127 2.18201 - 1.74290 1.79798 1.85277 1.90758 1.96212 2.01610 - 2.06918 2.12097 2.17113 2.21941 2.26564 2.30998 - 2.35329 2.39623 2.43843 2.47940 2.51894 2.55826 - 2.59812 2.61724 2.63451 2.64681 2.66320 2.66958 - 2.67639 2.67627 2.67343 2.67260 2.67306 2.67720 - 2.10706 2.16821 2.22826 2.28770 2.34620 2.40334 - 2.45870 2.51186 2.56243 2.61013 2.65495 2.69724 - 2.73832 2.77933 2.82010 2.86039 2.90030 2.94138 - 2.98439 3.00492 3.02173 3.03167 3.04616 3.05242 - 3.05799 3.05779 3.05550 3.05482 3.05525 3.05864 - 2.70032 2.78199 2.85681 2.92540 2.98743 3.04289 - 3.09236 3.13734 3.17998 3.22076 3.25983 3.29745 - 3.33457 3.37194 3.40921 3.44565 3.48083 3.51607 - 3.55253 3.57058 3.58756 3.59989 3.61291 3.61612 - 3.61790 3.61827 3.61918 3.61936 3.61936 3.61855 - 3.18426 3.27820 3.36132 3.43445 3.49720 3.54981 - 3.59342 3.63057 3.66476 3.69685 3.72715 3.75605 - 3.78466 3.81386 3.84326 3.87192 3.89930 3.92724 - 3.95786 3.97399 3.98994 4.00195 4.01330 4.01556 - 4.01368 4.01433 4.01808 4.01892 4.01874 4.01424 - 3.59110 3.69420 3.78278 3.85789 3.91919 3.96713 - 4.00344 4.03162 4.05640 4.07900 4.09983 4.11944 - 4.13900 4.15949 4.18049 4.20083 4.21983 4.23972 - 4.26335 4.27682 4.29103 4.30228 4.31191 4.31341 - 4.30911 4.30994 4.31547 4.31673 4.31641 4.30960 - 3.94136 4.05097 4.14269 4.21782 4.27611 4.31826 - 4.34653 4.36531 4.38047 4.39349 4.40487 4.41530 - 4.42595 4.43784 4.45052 4.46262 4.47338 4.48528 - 4.50177 4.51231 4.52419 4.53407 4.54187 4.54277 - 4.53721 4.53808 4.54438 4.54581 4.54544 4.53760 - 4.52816 4.63323 4.71978 4.78972 4.84235 4.87774 - 4.89706 4.90308 4.89984 4.88924 4.87363 4.85715 - 4.84670 4.84722 4.85503 4.85924 4.85163 4.84287 - 4.84579 4.85156 4.85822 4.86349 4.86737 4.86630 - 4.86190 4.86273 4.86772 4.86915 4.86835 4.86191 - 4.99523 5.09872 5.18003 5.24179 5.28344 5.30531 - 5.30902 5.29803 5.27722 5.24892 5.21586 5.18279 - 5.15726 5.14459 5.14046 5.13229 5.11078 5.08865 - 5.08005 5.07994 5.08024 5.08014 5.07951 5.07835 - 5.07587 5.07626 5.07864 5.07932 5.07899 5.07564 - 5.85382 5.95800 6.02497 6.05970 6.06326 6.03881 - 5.99226 5.93322 5.87340 5.81561 5.76069 5.70894 - 5.66040 5.61496 5.57194 5.52929 5.48595 5.44571 - 5.41333 5.39973 5.38433 5.37066 5.36113 5.35972 - 5.36302 5.36224 5.35749 5.35641 5.35671 5.36253 - 6.47709 6.55746 6.59479 6.59632 6.56407 6.50234 - 6.41852 6.32388 6.23171 6.14531 6.06524 5.99118 - 5.92235 5.85753 5.79584 5.73483 5.67312 5.61476 - 5.56444 5.54108 5.51358 5.48890 5.47225 5.47009 - 5.47831 5.47673 5.46622 5.46381 5.46447 5.47745 - 7.35231 7.36978 7.33925 7.27222 7.17215 7.04486 - 6.89924 6.74813 6.60550 6.47523 6.35721 6.24987 - 6.15130 6.05873 5.97151 5.88772 5.80541 5.72413 - 5.64365 5.60335 5.56106 5.52597 5.49603 5.49521 - 5.50377 5.50132 5.48720 5.48323 5.48543 5.50325 - 7.95568 7.91390 7.82080 7.69155 7.53095 7.34624 - 7.14773 6.94967 6.76714 6.60389 6.45926 6.33020 - 6.21301 6.10321 5.99891 5.89622 5.79241 5.69135 - 5.59725 5.55097 5.49875 5.45368 5.42004 5.41411 - 5.42190 5.41957 5.40598 5.40290 5.40371 5.42015 - 8.41671 8.31343 8.15975 7.97379 7.76097 7.52914 - 7.28890 7.05438 6.84066 6.65093 6.48404 6.33596 - 6.20182 6.07651 5.95775 5.84135 5.72426 5.60982 - 5.50214 5.44989 5.39390 5.34723 5.30834 5.30009 - 5.30051 5.29871 5.29063 5.28882 5.28925 5.29854 - 8.78589 8.62379 8.41404 8.17706 7.91851 7.64651 - 7.37145 7.10680 6.86729 6.65560 6.46988 6.30549 - 6.15647 6.01763 5.88626 5.75818 5.63021 5.50503 - 5.38666 5.33027 5.27311 5.22728 5.18425 5.17369 - 5.16533 5.16427 5.16316 5.16300 5.16294 5.16322 - 9.29879 9.12430 8.82570 8.46118 8.07983 7.72575 - 7.40469 7.11491 6.85500 6.62157 6.40714 6.20644 - 6.02058 5.85129 5.69620 5.55128 5.41142 5.27011 - 5.13131 5.07059 5.01305 4.96805 4.91869 4.90498 - 4.88336 4.88328 4.89276 4.89548 4.89422 4.88091 - 9.85256 9.39979 8.95558 8.53882 8.14766 7.78103 - 7.43809 7.11807 6.82073 6.54692 6.29522 6.06369 - 5.85080 5.65681 5.48152 5.32448 5.18233 5.04022 - 4.88527 4.80788 4.74213 4.70143 4.65209 4.63237 - 4.60656 4.60739 4.62044 4.62397 4.62270 4.60415 - 10.48855 9.86497 9.27105 8.72423 8.22065 7.75695 - 7.33036 6.93966 6.58372 6.26051 5.96686 5.69873 - 5.45159 5.22305 5.01414 4.82326 4.64762 4.47576 - 4.29875 4.21252 4.13604 4.08435 4.02619 4.00843 - 3.99184 3.99130 3.99483 3.99589 3.99534 3.98913 - 10.85961 10.10936 9.40912 8.77182 8.19085 7.66160 - 7.17993 6.74285 6.34869 5.99333 5.67193 5.37910 - 5.10834 4.85565 4.62208 4.40667 4.20670 4.01399 - 3.82269 3.73023 3.64387 3.58062 3.51579 3.50267 - 3.49933 3.49692 3.48761 3.48529 3.48589 3.49640 - 11.31386 10.35134 9.49189 8.73099 8.05347 7.44970 - 6.91197 6.43063 5.99781 5.60740 5.25288 4.92739 - 4.62256 4.33325 4.06099 3.80871 3.57604 3.35955 - 3.15776 3.06245 2.96799 2.89453 2.82757 2.81205 - 2.80510 2.80292 2.79615 2.79472 2.79493 2.80201 - 11.60031 10.49350 9.53215 8.69208 7.95376 7.30276 - 6.72899 6.21920 5.76122 5.34768 4.97206 4.62722 - 4.30484 3.99942 3.71131 3.44188 3.19148 2.95732 - 2.74050 2.63999 2.54437 2.47246 2.40224 2.38468 - 2.36858 2.36724 2.36811 2.36847 2.36816 2.36536 - 11.80601 10.60019 9.57245 8.67954 7.90066 7.21803 - 6.61909 6.08864 5.61229 5.18177 4.79051 4.43148 - 4.09640 3.77975 3.48124 3.20134 2.94063 2.69645 - 2.46938 2.36384 2.26423 2.19003 2.11782 2.09990 - 2.08295 2.08166 2.08312 2.08363 2.08327 2.07949 - 11.96812 10.69009 9.61695 8.68706 7.87988 7.17574 - 6.55910 6.01336 5.52305 5.07945 4.67599 4.30572 - 3.96058 3.63513 3.32878 3.04157 2.77380 2.52295 - 2.28779 2.17750 2.07298 1.99513 1.92106 1.90316 - 1.88792 1.88640 1.88615 1.88627 1.88602 1.88424 - 12.21773 10.84261 9.71384 8.73917 7.89812 7.16924 - 6.53190 5.96714 5.45830 4.99662 4.57568 4.18882 - 3.82844 3.48937 3.17080 2.87236 2.59334 2.33086 - 2.08104 1.96190 1.84823 1.76329 1.68415 1.66545 - 1.65171 1.64984 1.64738 1.64699 1.64687 1.64782 - 12.40565 10.97113 9.81322 8.81633 7.95957 7.21928 - 6.57218 5.99759 5.47811 5.00521 4.57274 4.17430 - 3.80264 3.45283 3.12396 2.81559 2.52619 2.25129 - 1.98668 1.85883 1.73638 1.64439 1.55821 1.53760 - 1.52225 1.52022 1.51773 1.51734 1.51720 1.51826 - 12.70168 11.20804 10.03266 9.02237 8.15867 7.40932 - 6.75230 6.16678 5.63570 5.15045 4.70472 4.29169 - 3.90349 3.53494 3.18555 2.85544 2.54221 2.23733 - 1.93503 1.78449 1.63580 1.52008 1.41096 1.38414 - 1.36238 1.35989 1.35806 1.35783 1.35760 1.35758 - 12.85626 11.36265 10.20442 9.20589 8.35011 7.60142 - 6.94155 6.35235 5.81882 5.33203 4.88455 4.46816 - 4.07312 3.69324 3.32882 2.98123 2.64797 2.31728 - 1.97872 1.80493 1.62564 1.48008 1.34412 1.31136 - 1.28505 1.28181 1.27895 1.27858 1.27832 1.27871 - 12.95442 11.53881 10.46004 9.51566 8.68562 7.94324 - 7.27840 6.68100 6.14268 5.65510 5.20962 4.79651 - 4.40385 4.02281 3.65061 3.28363 2.91577 2.53539 - 2.12898 1.91187 1.68134 1.48298 1.27801 1.23154 - 1.20744 1.20419 1.19509 1.19290 1.19413 1.19802 - 13.01739 11.62614 10.59709 9.69838 8.90098 8.18344 - 7.53688 6.95255 6.42303 5.94083 5.49804 5.08552 - 4.69178 4.30790 3.93017 3.55341 3.16844 2.75738 - 2.29816 2.04255 1.76291 1.51605 1.25035 1.18776 - 1.16581 1.16319 1.14848 1.14454 1.14744 1.15370 - 13.04115 11.67237 10.68834 9.82809 9.05930 8.36413 - 7.73491 7.16378 6.64408 6.16900 5.73125 5.32219 - 4.93080 4.54814 4.16973 3.78899 3.39403 2.96132 - 2.46070 2.17331 1.85073 1.56131 1.24011 1.16156 - 1.13795 1.13578 1.11777 1.11277 1.11676 1.12295 - 13.04714 11.69745 10.75324 9.92438 9.18029 8.50488 - 7.89147 7.33289 6.82309 6.35578 5.92418 5.52010 - 5.13289 4.75364 4.37726 3.99596 3.59548 3.14726 - 2.61363 2.29962 1.94005 1.61202 1.23986 1.14586 - 1.11764 1.11562 1.09573 1.09011 1.09475 1.09978 - 13.02316 11.71094 10.83612 10.05949 9.35763 8.71621 - 8.13024 7.59366 7.10155 6.64863 6.22909 5.83580 - 5.45927 5.09085 4.72430 4.34937 3.94667 3.47640 - 2.88619 2.52584 2.10398 1.71411 1.27048 1.14803 - 1.07670 1.07555 1.07381 1.06925 1.05649 1.06701 - 13.00245 11.71567 10.88934 10.14938 9.47838 8.86298 - 8.29906 7.78128 7.30537 6.86666 6.45991 6.07859 - 5.71384 5.35718 5.00171 4.63579 4.23679 3.75739 - 3.13272 2.73940 2.26760 1.82090 1.30121 1.15277 - 1.05933 1.05613 1.05454 1.04991 1.03538 1.04496 - 13.03160 11.75709 10.98047 10.28266 9.65053 9.07250 - 8.54480 8.06249 7.62150 7.21714 6.84404 6.49505 - 6.16003 5.82962 5.49744 5.15264 4.77368 4.31367 - 3.68376 3.24755 2.66594 2.07414 1.37263 1.17626 - 1.05520 1.04044 1.01711 1.01327 1.01184 1.01273 - 12.99576 11.74915 11.01600 10.35556 9.75574 9.20699 - 8.70605 8.24866 7.83123 7.44969 7.09911 6.77290 - 6.46133 6.15525 5.84805 5.52798 5.17095 4.72295 - 4.08204 3.62423 2.99919 2.33610 1.48227 1.22671 - 1.04729 1.02563 1.00141 0.99761 0.99588 0.99537 - 12.90958 11.70995 11.04051 10.43366 9.87985 9.37183 - 8.90730 8.48311 8.09662 7.74485 7.42415 7.12943 - 6.85290 6.58663 6.32382 6.05106 5.73889 5.31784 - 4.66581 4.18355 3.51543 2.77516 1.71689 1.36439 - 1.04885 1.00906 0.98533 0.98180 0.97057 0.97699 - 12.90256 11.71316 11.06580 10.47907 9.94455 9.45608 - 9.01144 8.60779 8.24268 7.91337 7.61635 7.34663 - 7.09627 6.85748 6.62423 6.38425 6.10937 5.73054 - 5.11778 4.64297 3.95450 3.14981 1.91506 1.48249 - 1.07106 1.01273 0.97312 0.96935 0.96243 0.96730 - 12.89946 11.71843 11.08410 10.50950 9.98700 9.51116 - 9.07977 8.69018 8.34008 8.02688 7.74718 7.49601 - 7.26528 7.04730 6.83686 6.62288 6.37900 6.03835 - 5.46826 5.00944 4.31851 3.47406 2.10026 1.59599 - 1.09692 1.02118 0.96545 0.96104 0.95811 0.96131 - 12.87878 11.72191 11.10608 10.54451 10.03113 9.56189 - 9.13549 8.75056 8.40612 8.10034 7.83070 7.59345 - 7.38227 7.18969 7.00680 6.81415 6.58100 6.25414 - 5.72110 5.29652 4.65090 3.81518 2.29052 1.69113 - 1.10421 1.02336 0.97020 0.96346 0.95948 0.95726 - 12.88448 11.73512 11.12528 10.57174 10.06889 9.61283 - 9.20142 8.83267 8.50489 8.21612 7.96392 7.74438 - 7.55080 7.37701 7.21920 7.06769 6.89611 6.63226 - 6.14521 5.74297 5.12855 4.29464 2.61808 1.90763 - 1.15211 1.04191 0.96789 0.96100 0.95383 0.95212 - 12.87294 11.74037 11.14019 10.59510 10.10005 9.65182 - 9.24832 8.88780 8.56882 8.28969 8.04830 7.84124 - 7.66238 7.50628 7.37013 7.24558 7.10794 6.88627 - 6.45121 6.07969 5.49760 4.67493 2.90857 2.10822 - 1.20101 1.06456 0.96868 0.95983 0.95046 0.94898 - 12.83535 11.74441 11.16452 10.63532 10.15291 9.71516 - 9.32093 8.96957 8.66072 8.39352 8.16685 7.97882 - 7.82544 7.70240 7.60508 7.51992 7.42324 7.26910 - 6.95376 6.65587 6.13628 5.35556 3.52321 2.54619 - 1.32176 1.12760 0.97588 0.96051 0.94636 0.94474 - 12.82529 11.75922 11.17875 10.65118 10.17260 9.74045 - 9.35336 9.01020 8.71005 8.45187 8.23445 8.05561 - 7.91088 7.79705 7.71449 7.65987 7.61612 7.52319 - 7.26693 7.00936 6.55759 5.83785 3.98132 2.92416 - 1.44229 1.19315 0.98560 0.96359 0.94391 0.94262 - 12.72918 11.75681 11.19085 10.67395 10.20318 9.77701 - 9.39479 9.05624 8.76136 8.50983 8.30113 8.13422 - 8.00634 7.91483 7.85797 7.82688 7.80562 7.76187 - 7.61839 7.44533 7.09105 6.47798 4.69520 3.49661 - 1.67032 1.33246 1.00976 0.96720 0.94269 0.94047 - 12.66129 11.75837 11.19660 10.68314 10.21557 9.79253 - 9.41344 9.07822 8.78703 8.53971 8.33594 8.17484 - 8.05403 7.97127 7.92590 7.91075 7.91292 7.90595 - 7.82411 7.69828 7.41053 6.87979 5.20693 3.96444 - 1.87708 1.45918 1.03546 0.97573 0.94488 0.93940 - 12.61211 11.76166 11.20234 10.68955 10.22217 9.80014 - 9.42288 9.08998 8.80139 8.55694 8.35640 8.19904 - 8.08281 8.00591 7.96809 7.96281 7.97941 7.99840 - 7.96397 7.87264 7.62783 7.14108 5.58125 4.37688 - 2.06974 1.57095 1.06055 0.99178 0.94439 0.93875 - 12.57748 11.76267 11.20514 10.69323 10.22661 9.80578 - 9.43007 9.09891 8.81207 8.56945 8.37101 8.21613 - 8.10292 8.02976 7.99690 7.99867 8.02569 8.06090 - 8.05581 7.99064 7.78848 7.35567 5.88320 4.69678 - 2.25412 1.68502 1.08699 1.00287 0.94638 0.93832 - 12.53473 11.76377 11.20836 10.69789 10.23267 9.81343 - 9.43953 9.11040 8.82578 8.58565 8.39001 8.23839 - 8.12900 8.06069 8.03428 8.04515 8.08561 8.14227 - 8.17637 8.14682 8.00678 7.65771 6.33525 5.20233 - 2.59527 1.89845 1.13990 1.02629 0.95099 0.93778 - 12.50833 11.76442 11.21002 10.70071 10.23664 9.81841 - 9.44549 9.11745 8.83418 8.59563 8.40175 8.25214 - 8.14509 8.07979 8.05739 8.07384 8.12257 8.19277 - 8.25179 8.24534 8.14829 7.86124 6.66222 5.58892 - 2.89676 2.09394 1.19219 1.05098 0.95603 0.93745 - 12.46882 11.76505 11.21211 10.70450 10.24220 9.82539 - 9.45369 9.12699 8.84544 8.60903 8.41758 8.27070 - 8.16694 8.10585 8.08900 8.11298 8.17291 8.26211 - 8.35643 8.38292 8.35050 8.16512 7.19824 6.26095 - 3.52015 2.52702 1.31933 1.11587 0.96904 0.93701 - 12.44608 11.76535 11.21315 10.70644 10.24502 9.82893 - 9.45786 9.13181 8.85110 8.61568 8.42546 8.28002 - 8.17803 8.11918 8.10524 8.13309 8.19883 8.29808 - 8.41132 8.45531 8.45774 8.33330 7.53095 6.70023 - 4.00753 2.89921 1.44124 1.18250 0.98203 0.93679 - 12.42133 11.76574 11.21430 10.70830 10.24753 9.83217 - 9.46189 9.13666 8.85676 8.62225 8.43315 8.28916 - 8.18899 8.13243 8.12146 8.15334 8.22513 8.33478 - 8.46780 8.53009 8.56848 8.51301 7.92819 7.25091 - 4.73248 3.49828 1.66824 1.31388 1.00809 0.93658 - 12.43026 11.77273 11.21311 10.70377 10.24272 9.82865 - 9.46054 9.13774 8.85994 8.62700 8.43878 8.29445 - 8.19149 8.12983 8.11563 8.15545 8.25064 8.37748 - 8.50416 8.56419 8.61518 8.60226 8.16872 7.58145 - 5.24565 3.97101 1.87684 1.44142 1.03322 0.93647 - 12.42149 11.77246 11.21323 10.70422 10.24343 9.82962 - 9.46174 9.13921 8.86166 8.62901 8.44110 8.29718 - 8.19473 8.13376 8.12049 8.16167 8.25883 8.38871 - 8.52132 8.58756 8.65121 8.66191 8.31473 7.80992 - 5.63745 4.34992 2.08562 1.56375 1.05904 0.93641 - 12.41543 11.77231 11.21333 10.70445 10.24389 9.83024 - 9.46255 9.14018 8.86282 8.63037 8.44270 8.29904 - 8.19696 8.13642 8.12379 8.16583 8.26429 8.39627 - 8.53298 8.60338 8.67537 8.70214 8.41782 7.97506 - 5.94635 4.66722 2.27930 1.68334 1.08486 0.93637 - 12.38602 11.76554 11.21514 10.70989 10.24988 9.83557 - 9.46653 9.14264 8.86409 8.63095 8.44322 8.30077 - 8.20258 8.14872 8.14154 8.17888 8.25875 8.38155 - 8.54092 8.62873 8.71437 8.75439 8.55069 8.20078 - 6.40909 5.17287 2.62484 1.92367 1.13709 0.93631 - 12.38263 11.76520 11.21475 10.71011 10.25082 9.83665 - 9.46739 9.14321 8.86459 8.63164 8.44427 8.30225 - 8.20453 8.15114 8.14442 8.18218 8.26264 8.38680 - 8.54968 8.64075 8.73170 8.78428 8.64070 8.34378 - 6.73965 5.56593 2.92614 2.13616 1.18858 0.93627 - 1.28207 1.32878 1.37591 1.42359 1.47167 1.51987 - 1.56796 1.61563 1.66258 1.70854 1.75327 1.79673 - 1.83934 1.88132 1.92206 1.96075 1.99669 2.03031 - 2.06194 2.07699 2.09295 2.10773 2.12894 2.13613 - 2.14034 2.14040 2.14043 2.14045 2.14026 2.14106 - 1.69944 1.75409 1.80856 1.86315 1.91762 1.97165 - 2.02490 2.07702 2.12767 2.17657 2.22356 2.26874 - 2.31289 2.35659 2.39940 2.44076 2.48031 2.51906 - 2.55755 2.57576 2.59235 2.60441 2.62033 2.62646 - 2.63314 2.63304 2.63022 2.62939 2.62983 2.63394 - 2.05862 2.11965 2.17973 2.23932 2.29809 2.35565 - 2.41158 2.46546 2.51687 2.56555 2.61146 2.65489 - 2.69707 2.73906 2.78059 2.82136 2.86133 2.90188 - 2.94359 2.96326 2.97942 2.98912 3.00333 3.00944 - 3.01491 3.01472 3.01248 3.01182 3.01223 3.01556 - 2.64641 2.72770 2.80257 2.87163 2.93451 2.99118 - 3.04214 3.08875 3.13302 3.17536 3.21592 3.25494 - 3.29339 3.33202 3.37038 3.40761 3.44310 3.47814 - 3.51381 3.53129 3.54779 3.55995 3.57294 3.57618 - 3.57792 3.57830 3.57927 3.57945 3.57945 3.57857 - 3.12699 3.22080 3.30425 3.37817 3.44214 3.49636 - 3.54188 3.58109 3.61734 3.65140 3.68359 3.71426 - 3.74453 3.77525 3.80599 3.83570 3.86374 3.89191 - 3.92221 3.93801 3.95375 3.96578 3.97736 3.97970 - 3.97783 3.97849 3.98232 3.98318 3.98299 3.97841 - 3.53192 3.63507 3.72422 3.80037 3.86317 3.91301 - 3.95152 3.98205 4.00917 4.03404 4.05704 4.07868 - 4.10014 4.12238 4.14491 4.16654 4.18652 4.20703 - 4.23085 4.24428 4.25854 4.27001 4.28005 4.28168 - 4.27742 4.27826 4.28389 4.28517 4.28486 4.27794 - 3.88697 3.98859 4.07661 4.15226 4.21485 4.26414 - 4.30080 4.32669 4.34471 4.35620 4.36288 4.36792 - 4.37701 4.39428 4.41691 4.43637 4.44605 4.45417 - 4.47098 4.48286 4.49556 4.50564 4.51423 4.51397 - 4.50960 4.51069 4.51661 4.51828 4.51737 4.50982 - 4.46699 4.57287 4.66064 4.73218 4.78679 4.82447 - 4.84632 4.85505 4.85455 4.84671 4.83378 4.81984 - 4.81169 4.81421 4.82379 4.82976 4.82400 4.81699 - 4.82137 4.82780 4.83519 4.84114 4.84584 4.84497 - 4.84069 4.84157 4.84664 4.84809 4.84729 4.84074 - 4.93430 5.03886 5.12168 5.18531 5.22917 5.25354 - 5.25997 5.25182 5.23387 5.20840 5.17805 5.14753 - 5.12434 5.11373 5.11151 5.10534 5.08609 5.06627 - 5.05981 5.06070 5.06201 5.06274 5.06318 5.06240 - 5.05985 5.06024 5.06287 5.06364 5.06320 5.05977 - 5.79537 5.90087 5.96972 6.00680 6.01312 5.99172 - 5.94836 5.89248 5.83558 5.78046 5.72796 5.67844 - 5.63203 5.58872 5.54793 5.50772 5.46714 5.42992 - 5.40072 5.38873 5.37484 5.36231 5.35402 5.35292 - 5.35651 5.35578 5.35101 5.34991 5.35021 5.35608 - 6.42139 6.50358 6.54327 6.54758 6.51844 6.46007 - 6.37963 6.28828 6.19908 6.11531 6.03757 5.96560 - 5.89875 5.83596 5.77643 5.71785 5.65898 5.60389 - 5.55721 5.53575 5.50997 5.48650 5.47117 5.46936 - 5.47799 5.47642 5.46578 5.46334 5.46402 5.47719 - 7.30181 7.32210 7.29479 7.23126 7.13489 7.01135 - 6.86942 6.72176 6.58220 6.45460 6.33886 6.23352 - 6.13680 6.04604 5.96070 5.87899 5.79914 5.72081 - 5.64396 5.60568 5.56532 5.53159 5.50276 5.50225 - 5.51133 5.50888 5.49453 5.49047 5.49274 5.51089 - 7.90965 7.87148 7.78231 7.65716 7.50075 7.32014 - 7.12554 6.93107 6.75170 6.59115 6.44879 6.32168 - 6.20625 6.09814 5.99550 5.89451 5.79264 5.69412 - 5.60352 5.55927 5.50879 5.46478 5.43224 5.42661 - 5.43493 5.43259 5.41871 5.41554 5.41637 5.43322 - 8.37446 8.27559 8.12648 7.94510 7.73679 7.50928 - 7.27306 7.04219 6.83166 6.64465 6.48006 6.33398 - 6.20162 6.07797 5.96076 5.84583 5.73029 5.61792 - 5.51338 5.46303 5.40870 5.36302 5.32503 5.31701 - 5.31785 5.31604 5.30772 5.30586 5.30630 5.31591 - 8.74689 8.58990 8.38527 8.15327 7.89950 7.63196 - 7.36102 7.10006 6.86373 6.65476 6.47136 6.30897 - 6.16177 6.02459 5.89477 5.76804 5.64134 5.51785 - 5.40224 5.34758 5.29197 5.24709 5.20478 5.19439 - 5.18627 5.18520 5.18398 5.18379 5.18374 5.18417 - 9.26611 9.09608 8.80329 8.44506 8.06962 7.72039 - 7.40326 7.11673 6.85971 6.62885 6.41675 6.21819 - 6.03430 5.86682 5.71329 5.56959 5.43059 5.29040 - 5.15370 5.09442 5.03825 4.99408 4.94514 4.93147 - 4.90972 4.90965 4.91928 4.92204 4.92078 4.90726 - 9.82276 9.37745 8.93988 8.52905 8.14313 7.78117 - 7.44235 7.12594 6.83173 6.56061 6.31118 6.08163 - 5.87045 5.67797 5.50400 5.34815 5.20710 5.06618 - 4.91269 4.83618 4.77147 4.73164 4.68260 4.66259 - 4.63652 4.63741 4.65073 4.65434 4.65303 4.63411 - 10.46640 9.85133 9.26461 8.72402 8.22580 7.76672 - 7.34411 6.95677 6.60366 6.28281 5.99115 5.72472 - 5.47906 5.25186 5.04416 4.85438 4.67977 4.50883 - 4.33263 4.24678 4.17071 4.11935 4.06103 4.04296 - 4.02609 4.02558 4.02930 4.03041 4.02984 4.02336 - 10.84220 10.10098 9.40813 8.77704 8.20128 7.67642 - 7.19840 6.76438 6.37270 6.01936 5.69960 5.40819 - 5.13869 4.88714 4.65465 4.44023 4.24120 4.04930 - 3.85854 3.76621 3.67983 3.61642 3.55114 3.53782 - 3.53439 3.53196 3.52258 3.52025 3.52085 3.53144 - 11.30039 10.34865 9.49689 8.74190 8.06890 7.46860 - 6.93350 6.45429 6.02330 5.63452 5.28146 4.95724 - 4.65345 4.36491 4.09328 3.84173 3.60996 3.39417 - 3.19247 3.09697 3.00227 2.92853 2.86090 2.84518 - 2.83816 2.83595 2.82907 2.82762 2.82783 2.83503 - 11.58876 10.49305 9.53903 8.70442 7.97009 7.32202 - 6.75040 6.24228 5.78576 5.37358 4.99917 4.65541 - 4.33389 4.02909 3.74144 3.47256 3.22284 2.98921 - 2.77244 2.67178 2.57594 2.50375 2.43292 2.41517 - 2.39889 2.39754 2.39842 2.39879 2.39848 2.39564 - 11.79513 10.60037 9.57955 8.69167 7.91641 7.23640 - 6.63930 6.11022 5.63512 5.20574 4.81552 4.45741 - 4.12309 3.80700 3.50895 3.22950 2.96932 2.72558 - 2.49871 2.39314 2.29332 2.21879 2.14612 2.12807 - 2.11096 2.10966 2.11114 2.11166 2.11130 2.10747 - 11.95692 10.68997 9.62338 8.69829 7.89450 7.19274 - 6.57778 6.03329 5.54405 5.10147 4.69891 4.32948 - 3.98504 3.66015 3.35427 3.06749 2.80019 2.54977 - 2.31497 2.20474 2.10005 2.02183 1.94741 1.92941 - 1.91406 1.91253 1.91228 1.91240 1.91215 1.91035 - 12.20509 10.84073 9.71799 8.74780 7.90990 7.18325 - 6.54748 5.98389 5.47605 5.01527 4.59514 4.20901 - 3.84929 3.51081 3.19275 2.89483 2.61631 2.35435 - 2.10510 1.98618 1.87247 1.78724 1.70772 1.68891 - 1.67509 1.67320 1.67070 1.67031 1.67019 1.67116 - 12.39076 10.96683 9.81470 8.82213 7.96847 7.23039 - 6.58494 6.01160 5.49318 5.02117 4.58951 4.19179 - 3.82079 3.47159 3.14333 2.83556 2.54681 2.27257 - 2.00863 1.88108 1.75877 1.66666 1.57996 1.55916 - 1.54366 1.54161 1.53910 1.53871 1.53857 1.53963 - 12.68152 11.19830 10.02792 9.02168 8.16098 7.41401 - 6.75894 6.17505 5.64531 5.16122 4.71650 4.30434 - 3.91693 3.54909 3.20040 2.87103 2.55865 2.25467 - 1.95326 1.80316 1.65485 1.53924 1.42954 1.40248 - 1.38055 1.37804 1.37619 1.37597 1.37574 1.37571 - 12.83237 11.34851 10.19473 9.19987 8.34697 7.60078 - 6.94313 6.35589 5.82406 5.33874 4.89255 4.47730 - 4.08323 3.70420 3.34052 2.99363 2.66113 2.33142 - 1.99407 1.82085 1.64194 1.49649 1.36034 1.32751 - 1.30113 1.29787 1.29500 1.29462 1.29436 1.29479 - 12.92382 11.51846 10.44370 9.50256 8.67508 7.93507 - 7.27240 6.67710 6.14076 5.65505 5.21136 4.79990 - 4.40871 4.02892 3.65776 3.29169 2.92466 2.54516 - 2.13982 1.92326 1.69326 1.49538 1.29111 1.24493 - 1.22101 1.21778 1.20873 1.20655 1.20777 1.21160 - 12.98222 11.60132 10.57596 9.68004 8.88506 8.16987 - 7.52566 6.94360 6.41632 5.93629 5.49561 5.08503 - 4.69298 4.31049 3.93390 3.55806 3.17390 2.76378 - 2.30575 2.05085 1.77199 1.52588 1.26153 1.19952 - 1.17798 1.17541 1.16082 1.15692 1.15981 1.16588 - 13.00210 11.64405 10.66368 9.80607 9.03969 8.34692 - 7.72009 7.15133 6.63399 6.16122 5.72568 5.31871 - 4.92914 4.54797 4.17078 3.79103 3.39695 2.96526 - 2.46601 2.17951 1.85791 1.56948 1.25007 1.17230 - 1.14928 1.14720 1.12933 1.12437 1.12834 1.13430 - 13.00472 11.66631 10.72569 9.89965 9.15805 8.48508 - 7.87412 7.31793 6.81052 6.34555 5.91621 5.51424 - 5.12890 4.75120 4.37610 3.99588 3.59639 3.14933 - 2.61729 2.30429 1.94591 1.61906 1.24900 1.15590 - 1.12845 1.12653 1.10676 1.10117 1.10581 1.11059 - 12.97559 11.67580 10.80476 10.03097 9.33172 8.69285 - 8.10936 7.57522 7.08550 6.63491 6.21760 5.82640 - 5.45173 5.08490 4.71969 4.34595 3.94442 3.47561 - 2.88746 2.52846 2.10824 1.71991 1.27857 1.15706 - 1.08682 1.08584 1.08421 1.07968 1.06698 1.07720 - 12.95102 11.67757 10.85515 10.11839 9.45017 8.83740 - 8.27599 7.76063 7.28704 6.85054 6.44592 6.06659 - 5.70364 5.34856 4.99452 4.62993 4.23231 3.75462 - 3.13235 2.74057 2.27067 1.82579 1.30869 1.16127 - 1.06905 1.06606 1.06459 1.05997 1.04545 1.05481 - 12.97547 11.71507 10.94220 10.24767 9.61842 9.04311 - 8.51801 8.03817 7.59951 7.19739 6.82636 6.47927 - 6.14587 5.81682 5.48580 5.14212 4.76464 4.30726 - 3.68151 3.24740 2.66707 2.07640 1.37889 1.18430 - 1.06466 1.04998 1.02661 1.02282 1.02130 1.02216 - 12.93662 11.70475 10.97561 10.31858 9.72175 9.17577 - 8.67739 8.22239 7.80719 7.42770 7.07903 6.75452 - 6.44445 6.13966 5.83360 5.51474 5.15934 4.71419 - 4.07785 3.62244 2.99907 2.33745 1.48793 1.23414 - 1.05651 1.03502 1.01070 1.00690 1.00509 1.00461 - 12.84668 11.66295 10.99795 10.39481 9.84418 9.33896 - 8.87688 8.45484 8.07024 7.72014 7.40093 7.10757 - 6.83235 6.56744 6.30608 6.03495 5.72473 5.30623 - 4.65782 4.17799 3.51296 2.77594 1.72225 1.37111 - 1.05742 1.01805 0.99462 0.99102 0.97948 0.98607 - 12.83884 11.66533 11.02218 10.43900 9.90760 9.42185 - 8.97958 8.57799 8.21472 7.88699 7.59138 7.32296 - 7.07384 6.83631 6.60443 6.36599 6.09299 5.71665 - 5.10753 4.63525 3.95007 3.14905 1.91970 1.48877 - 1.07943 1.02156 0.98232 0.97849 0.97121 0.97631 - 12.83574 11.67027 11.03996 10.46877 9.94919 9.47595 - 9.04685 8.65927 8.31096 7.99930 7.72099 7.47107 - 7.24154 7.02479 6.81563 6.60310 6.36097 6.02268 - 5.45614 4.99985 4.31236 3.47184 2.10418 1.60188 - 1.10514 1.02989 0.97460 0.97013 0.96682 0.97029 - 12.81545 11.67374 11.06165 10.50317 9.99254 9.52576 - 9.10156 8.71862 8.37600 8.07187 7.80375 7.56789 - 7.35793 7.16645 6.98456 6.79291 6.56101 6.23639 - 5.70752 5.28599 4.64412 3.81212 2.29293 1.69607 - 1.11256 1.03221 0.97919 0.97235 0.96835 0.96621 - 12.82169 11.68694 11.08024 10.52964 10.02938 9.57569 - 9.16642 8.79962 8.47360 8.18644 7.93567 7.71741 - 7.52500 7.35225 7.19541 7.04490 6.87451 6.61256 - 6.12893 5.72946 5.11901 4.28956 2.61935 1.91166 - 1.16012 1.05052 0.97685 0.96988 0.96269 0.96105 - 12.81027 11.69199 11.09486 10.55259 10.06005 9.61409 - 9.21266 8.85403 8.53674 8.25915 8.01914 7.81331 - 7.63556 7.48047 7.34528 7.22166 7.08510 6.86504 - 6.43291 6.06394 5.48591 4.66809 2.90871 2.11149 - 1.20869 1.07294 0.97762 0.96872 0.95931 0.95789 - 12.77318 11.69583 11.11880 10.59224 10.11216 9.67657 - 9.28431 8.93470 8.62743 8.36160 8.13616 7.94925 - 7.79689 7.67483 7.57848 7.49426 7.39854 7.24555 - 6.93213 6.63622 6.12043 5.34501 3.52115 2.54773 - 1.32866 1.13549 0.98480 0.96939 0.95521 0.95363 - 12.76362 11.71045 11.13288 10.60782 10.13151 9.70144 - 9.31621 8.97472 8.67607 8.41919 8.20294 8.02513 - 7.88136 7.76842 7.68672 7.63291 7.59000 7.49803 - 7.24334 6.98749 6.53917 5.82444 3.97707 2.92448 - 1.44858 1.20055 0.99443 0.97254 0.95275 0.95150 - 12.66959 11.70804 11.14454 10.63001 10.16143 9.73727 - 9.35688 9.01995 8.72651 8.47620 8.26857 8.10258 - 7.97550 7.88475 7.82864 7.79828 7.77780 7.73494 - 7.59273 7.42094 7.06923 6.46045 4.68787 3.49453 - 1.67558 1.33918 1.01846 0.97620 0.95143 0.94935 - 12.60312 11.70962 11.15027 10.63915 10.17361 9.75248 - 9.37515 9.04147 8.75164 8.50550 8.30276 8.14253 - 8.02244 7.94036 7.89561 7.88108 7.88393 7.87780 - 7.79721 7.67247 7.38677 6.85975 5.19719 3.96028 - 1.88139 1.46536 1.04403 0.98467 0.95363 0.94827 - 12.55573 11.71261 11.15550 10.64504 10.17983 9.75965 - 9.38402 9.05281 8.76621 8.52358 8.32392 8.16625 - 8.04960 7.97299 7.93621 7.93253 7.95129 7.97364 - 7.93494 7.83499 7.59484 7.14392 5.60007 4.32578 - 2.07090 1.58876 1.06962 0.99233 0.95905 0.94762 - 12.52116 11.71382 11.15878 10.64910 10.18448 9.76543 - 9.39132 9.06161 8.77607 8.53461 8.33717 8.18313 - 8.07056 7.99791 7.96546 7.96760 7.99512 8.03113 - 8.02746 7.96333 7.76244 7.33206 5.86992 4.68961 - 2.25664 1.69017 1.09526 1.01170 0.95516 0.94719 - 12.47927 11.71493 11.16189 10.65364 10.19042 9.77294 - 9.40060 9.07287 8.78952 8.55052 8.35583 8.20499 - 8.09619 8.02833 8.00223 8.01335 8.05416 8.11139 - 8.14672 8.11822 7.97946 7.63248 6.31894 5.19249 - 2.59634 1.90285 1.14787 1.03493 0.95978 0.94664 - 12.45337 11.71547 11.16355 10.65644 10.19429 9.77781 - 9.40646 9.07982 8.79780 8.56034 8.36738 8.21847 - 8.11198 8.04709 8.02498 8.04160 8.09053 8.16111 - 8.22115 8.21570 8.12004 7.83496 6.64355 5.57681 - 2.89664 2.09771 1.19987 1.05941 0.96482 0.94631 - 12.41480 11.71611 11.16553 10.66012 10.19977 9.78470 - 9.41456 9.08923 8.80888 8.57351 8.38290 8.23668 - 8.13340 8.07267 8.05604 8.08012 8.14008 8.22930 - 8.32419 8.35147 8.32057 8.13721 7.17589 6.24479 - 3.51756 2.52919 1.32630 1.12378 0.97786 0.94587 - 12.39268 11.71642 11.16656 10.66195 10.20248 9.78812 - 9.41864 9.09396 8.81443 8.58002 8.39060 8.24577 - 8.14426 8.08573 8.07197 8.09988 8.16556 8.26473 - 8.37819 8.42278 8.42656 8.30408 7.50658 6.68140 - 4.00307 2.89980 1.44756 1.18992 0.99087 0.94565 - 12.36849 11.71671 11.16760 10.66380 10.20497 9.79135 - 9.42259 9.09869 8.81995 8.58645 8.39814 8.25475 - 8.15503 8.09872 8.08784 8.11971 8.19134 8.30083 - 8.43381 8.49632 8.53561 8.48191 7.90174 7.22889 - 4.72520 3.49630 1.67342 1.32047 1.01692 0.94544 - 12.37751 11.72370 11.16642 10.65927 10.20013 9.78778 - 9.42121 9.09976 8.82312 8.59115 8.40368 8.25996 - 8.15742 8.09602 8.08192 8.12164 8.21654 8.34303 - 8.46956 8.52979 8.58147 8.56992 8.14071 7.55785 - 5.23612 3.96688 1.88109 1.44737 1.04194 0.94533 - 12.36902 11.72343 11.16663 10.65972 10.20085 9.78875 - 9.42242 9.10122 8.82481 8.59311 8.40598 8.26263 - 8.16059 8.09986 8.08667 8.12770 8.22453 8.35402 - 8.48639 8.55274 8.61692 8.62881 8.28566 7.78502 - 5.62607 4.34401 2.08877 1.56917 1.06762 0.94527 - 12.36310 11.72328 11.16664 10.65995 10.20131 9.78938 - 9.42320 9.10217 8.82594 8.59444 8.40752 8.26444 - 8.16275 8.10246 8.08987 8.13176 8.22987 8.36143 - 8.49784 8.56827 8.64065 8.66842 8.38790 7.94906 - 5.93324 4.65965 2.28148 1.68832 1.09325 0.94523 - 12.33407 11.71671 11.16864 10.66538 10.20726 9.79464 - 9.42715 9.10464 8.82726 8.59506 8.40806 8.26614 - 8.16829 8.11464 8.10750 8.14468 8.22422 8.34657 - 8.50553 8.59327 8.67903 8.71974 8.51961 8.17310 - 6.39319 5.16264 2.62535 1.92735 1.14511 0.94517 - 12.33078 11.71658 11.16845 10.66581 10.20822 9.79572 - 9.42799 9.10516 8.82769 8.59567 8.40904 8.26759 - 8.17025 8.11705 8.11034 8.14792 8.22804 8.35176 - 8.51424 8.60511 8.69593 8.74895 8.60880 8.31470 - 6.72131 5.55342 2.92538 2.13896 1.19620 0.94513 - 1.24734 1.29317 1.33952 1.38650 1.43396 1.48169 - 1.52943 1.57692 1.62384 1.66996 1.71501 1.75894 - 1.80209 1.84461 1.88586 1.92498 1.96117 1.99471 - 2.02568 2.04007 2.05515 2.06903 2.08930 2.09627 - 2.10018 2.10018 2.10017 2.10018 2.09996 2.10081 - 1.65460 1.70843 1.76230 1.81650 1.87079 1.92492 - 1.97856 2.03139 2.08303 2.13324 2.18176 2.22859 - 2.27428 2.31917 2.36269 2.40413 2.44307 2.48070 - 2.51782 2.53533 2.55141 2.56316 2.57817 2.58382 - 2.59037 2.59027 2.58740 2.58657 2.58698 2.59112 - 2.00832 2.06874 2.12846 2.18795 2.24690 2.30497 - 2.36173 2.41678 2.46972 2.52023 2.56820 2.61378 - 2.65791 2.70136 2.74374 2.78455 2.82373 2.86297 - 2.90330 2.92236 2.93809 2.94759 2.96106 2.96678 - 2.97216 2.97198 2.96971 2.96905 2.96942 2.97277 - 2.59488 2.67283 2.74574 2.81426 2.87798 2.93673 - 2.99065 3.04053 3.08758 3.13204 3.17406 3.21407 - 3.25339 3.29305 3.33252 3.37060 3.40638 3.44108 - 3.47580 3.49263 3.50871 3.52074 3.53337 3.53649 - 3.53813 3.53852 3.53952 3.53971 3.53970 3.53877 - 3.07076 3.16496 3.24907 3.32388 3.38896 3.44448 - 3.49150 3.53240 3.57048 3.60653 3.64077 3.67351 - 3.70569 3.73804 3.77004 3.80058 3.82898 3.85710 - 3.88704 3.90258 3.91818 3.93023 3.94179 3.94412 - 3.94216 3.94285 3.94677 3.94764 3.94744 3.94275 - 3.46431 3.58934 3.68381 3.75357 3.80685 3.85320 - 3.89435 3.93076 3.96321 3.99213 4.01833 4.04251 - 4.06527 4.08732 4.10889 4.13066 4.15313 4.17577 - 4.19905 4.21206 4.22629 4.23841 4.24907 4.24945 - 4.24612 4.24718 4.25250 4.25400 4.25321 4.24649 - 3.81941 3.93599 4.03350 4.11307 4.17442 4.21852 - 4.24813 4.26841 4.28625 4.30331 4.31985 4.33605 - 4.35217 4.36842 4.38433 4.39887 4.41159 4.42514 - 4.44304 4.45418 4.46670 4.47723 4.48616 4.48738 - 4.48183 4.48276 4.48931 4.49080 4.49043 4.48231 - 4.39537 4.52184 4.62260 4.69939 4.75217 4.78260 - 4.79464 4.79542 4.79405 4.79283 4.79201 4.79181 - 4.79211 4.79291 4.79378 4.79369 4.79229 4.79259 - 4.79876 4.80474 4.81217 4.81875 4.82431 4.82485 - 4.81964 4.82041 4.82604 4.82733 4.82701 4.81996 - 4.86096 4.98858 5.08580 5.15510 5.19675 5.21294 - 5.20846 5.19168 5.17304 5.15517 5.13842 5.12307 - 5.10886 5.09575 5.08332 5.07050 5.05693 5.04580 - 5.04142 5.04223 5.04374 5.04515 5.04703 5.04715 - 5.04422 5.04459 5.04753 5.04821 5.04805 5.04435 - 5.73505 5.84622 5.91988 5.96069 5.96970 5.95010 - 5.90792 5.85311 5.79773 5.74469 5.69468 5.64790 - 5.60414 5.56315 5.52451 5.48675 5.44922 5.41527 - 5.38899 5.37823 5.36541 5.35373 5.34709 5.34647 - 5.35049 5.34978 5.34498 5.34387 5.34421 5.35018 - 6.36562 6.44827 6.48962 6.49660 6.47096 6.41668 - 6.34063 6.25344 6.16772 6.08663 6.01092 5.94052 - 5.87514 5.81409 5.75673 5.70102 5.64581 5.59456 - 5.55111 5.53094 5.50631 5.48380 5.47020 5.46893 - 5.47817 5.47662 5.46583 5.46334 5.46404 5.47746 - 7.25064 7.26756 7.23984 7.17845 7.08646 6.96897 - 6.83395 6.69294 6.55863 6.43473 6.32143 6.21784 - 6.12299 6.03478 5.95205 5.87158 5.79120 5.71462 - 5.64560 5.61169 5.57098 5.53438 5.51061 5.50764 - 5.52025 5.51788 5.50202 5.49837 5.49938 5.51900 - 7.86703 7.81993 7.72732 7.60365 7.45286 7.28091 - 7.09648 6.91161 6.73911 6.58244 6.44153 6.31430 - 6.19855 6.09111 5.99026 5.89198 5.79348 5.69845 - 5.61083 5.56783 5.51852 5.47549 5.44444 5.43929 - 5.44827 5.44594 5.43181 5.42858 5.42944 5.44664 - 8.33485 8.22916 8.07820 7.89922 7.69683 7.47774 - 7.25106 7.02907 6.82493 6.64166 6.47863 6.33273 - 6.20037 6.07753 5.96202 5.84946 5.73670 5.62722 - 5.52530 5.47612 5.42293 5.37821 5.34161 5.33402 - 5.33539 5.33359 5.32511 5.32321 5.32368 5.33351 - 8.70862 8.54974 8.34638 8.11821 7.87028 7.60991 - 7.34659 7.09256 6.86139 6.65573 6.47413 6.31257 - 6.16606 6.03006 5.90191 5.77721 5.65269 5.53145 - 5.41807 5.36451 5.31001 5.26607 5.22505 5.21506 - 5.20732 5.20626 5.20499 5.20480 5.20476 5.20528 - 9.22947 9.06805 8.78336 8.43202 8.06198 7.71661 - 7.40224 7.11799 6.86334 6.63501 6.42545 6.22933 - 6.04758 5.88181 5.72966 5.58724 5.44963 5.31090 - 5.17570 5.11728 5.06212 5.01894 4.97113 4.95774 - 4.93611 4.93609 4.94586 4.94866 4.94737 4.93372 - 9.62646 9.40867 9.04755 8.61434 8.17108 7.77080 - 7.41615 7.09966 6.81396 6.55580 6.31969 6.10121 - 5.89928 5.71394 5.54297 5.38205 5.22730 5.07656 - 4.93168 4.86516 4.80468 4.76157 4.71154 4.69162 - 4.66718 4.66808 4.68098 4.68486 4.68264 4.66419 - 10.45481 9.84881 9.26972 8.73520 8.24173 7.78623 - 7.36620 6.98060 6.62847 6.30803 6.01638 5.74987 - 5.50442 5.27800 5.07161 4.88369 4.71122 4.54188 - 4.36585 4.27971 4.20379 4.15310 4.09555 4.07758 - 4.06063 4.06017 4.06404 4.06519 4.06464 4.05794 - 10.83386 10.10198 9.41674 8.79167 8.22058 7.69921 - 7.22371 6.79138 6.40065 6.04773 5.72807 5.43665 - 5.16738 4.91652 4.68516 4.47226 4.27497 4.08433 - 3.89368 3.80106 3.71462 3.65147 3.58654 3.57331 - 3.57000 3.56758 3.55813 3.55577 3.55641 3.56705 - 11.28144 10.34366 9.50303 8.75665 8.09014 7.49441 - 6.96205 6.48378 6.05204 5.66139 5.30623 4.98084 - 4.67840 4.39423 4.12795 3.87894 3.64495 3.42630 - 3.22518 3.13106 3.03719 2.96286 2.89391 2.87959 - 2.87172 2.86945 2.86284 2.86113 2.86182 2.86876 - 11.57516 10.48772 9.54045 8.71154 7.98213 7.33827 - 6.77014 6.26477 5.81030 5.39958 5.02620 4.68326 - 4.36251 4.05856 3.77172 3.50337 3.25382 3.02039 - 2.80413 2.70372 2.60785 2.53533 2.46409 2.44621 - 2.42976 2.42839 2.42931 2.42968 2.42937 2.42647 - 11.78409 10.59129 9.57386 8.69079 7.92119 7.24709 - 6.65556 6.13104 5.65889 5.23110 4.84151 4.48351 - 4.14933 3.83374 3.53639 3.25758 2.99778 2.75439 - 2.52800 2.42266 2.32283 2.24804 2.17482 2.15657 - 2.13926 2.13794 2.13946 2.13998 2.13961 2.13573 - 11.94645 10.67831 9.61340 8.69270 7.89493 7.19994 - 6.59151 6.05239 5.56651 5.12552 4.72334 4.35362 - 4.00900 3.68442 3.37922 3.09318 2.82644 2.57649 - 2.34215 2.23212 2.12745 2.04904 1.97401 1.95580 - 1.94029 1.93873 1.93847 1.93859 1.93834 1.93654 - 12.19240 10.82845 9.70780 8.74192 7.90958 7.18896 - 6.55898 6.00008 5.49515 5.03575 4.61591 4.22954 - 3.86966 3.53147 3.21406 2.91691 2.63915 2.37782 - 2.12902 2.01025 1.89658 1.81124 1.73125 1.71226 - 1.69834 1.69643 1.69390 1.69349 1.69338 1.69439 - 12.37451 10.95776 9.81031 8.82233 7.97284 7.23850 - 6.59624 6.02544 5.50872 5.03776 4.60664 4.20924 - 3.83854 3.48983 3.16219 2.85517 2.56722 2.29369 - 2.03022 1.90282 1.78054 1.68835 1.60140 1.58051 - 1.56494 1.56289 1.56036 1.55996 1.55982 1.56089 - 12.66085 11.19326 10.03082 9.02907 8.17022 7.42357 - 6.76803 6.18368 5.65408 5.17075 4.72717 4.31632 - 3.93010 3.56317 3.21522 2.88659 2.57504 2.27191 - 1.97120 1.82133 1.67306 1.55738 1.44773 1.42070 - 1.39877 1.39626 1.39443 1.39421 1.39398 1.39392 - 12.81266 11.33941 10.19056 9.19893 8.34789 7.60290 - 6.94610 6.35965 5.82881 5.34469 4.89982 4.48591 - 4.09309 3.71510 3.35235 3.00634 2.67479 2.34613 - 2.00981 1.83697 1.65820 1.51268 1.37665 1.34383 - 1.31745 1.31419 1.31130 1.31092 1.31067 1.31111 - 12.96390 11.49544 10.38741 9.43801 8.61971 7.89952 - 7.26053 6.68563 6.16036 5.67701 5.22957 4.81124 - 4.41383 4.03086 3.65929 3.29487 2.93106 2.55630 - 2.15587 1.94004 1.70707 1.50521 1.30427 1.26160 - 1.23546 1.23132 1.22260 1.22068 1.22153 1.22565 - 12.93949 11.56590 10.54301 9.64968 8.85749 8.14556 - 7.50493 6.92675 6.40352 5.92760 5.49095 5.08412 - 4.69524 4.31512 3.94017 3.56538 3.18192 2.77268 - 2.31612 2.06218 1.78434 1.53899 1.27502 1.21288 - 1.19071 1.18803 1.17348 1.16959 1.17241 1.17862 - 12.95131 11.60089 10.62273 9.76768 9.00434 8.31525 - 7.69258 7.12837 6.61582 6.14796 5.71726 5.31476 - 4.92893 4.55050 4.17513 3.79642 3.40295 2.97211 - 2.47462 2.18932 1.86913 1.58174 1.26292 1.18501 - 1.16121 1.15899 1.14117 1.13623 1.14012 1.14622 - 12.94859 11.61819 10.67978 9.85620 9.11778 8.44870 - 7.84218 7.29088 6.78865 6.32902 5.90495 5.50786 - 5.12661 4.75188 4.37871 3.99957 3.60065 3.15448 - 2.62439 2.31283 1.95614 1.63061 1.26135 1.16812 - 1.13983 1.13777 1.11805 1.11249 1.11703 1.12197 - 12.91366 11.62245 10.75339 9.98212 9.28610 8.65123 - 8.07236 7.54333 7.05907 6.61411 6.20239 5.81639 - 5.44606 5.08240 4.71923 4.34660 3.94566 3.47790 - 2.89222 2.53506 2.11700 1.73036 1.28997 1.16842 - 1.09766 1.09653 1.09476 1.09022 1.07754 1.08791 - 12.88614 11.62202 10.80161 10.06743 9.40244 8.79363 - 8.23675 7.72641 7.25818 6.82724 6.42813 6.05396 - 5.69535 5.34346 4.99151 4.62809 4.23115 3.75466 - 3.13514 2.74547 2.27808 1.83526 1.31945 1.17206 - 1.07946 1.07636 1.07476 1.07012 1.05560 1.06512 - 12.91022 11.65970 10.88840 10.19613 9.56979 8.99814 - 8.47726 8.00213 7.56852 7.17164 6.80583 6.46359 - 6.13414 5.80776 5.47822 5.13509 4.75785 4.30202 - 3.68057 3.24946 2.67197 2.08338 1.38821 1.19413 - 1.07440 1.05969 1.03633 1.03251 1.03092 1.03195 - 12.87237 11.65146 10.92427 10.26937 9.67537 9.13265 - 8.63794 8.18694 7.77600 7.40090 7.05658 6.73615 - 6.42946 6.12703 5.82243 5.50430 5.14948 4.70624 - 4.07447 3.62217 3.00178 2.34253 1.49599 1.24296 - 1.06596 1.04454 1.02017 1.01634 1.01445 1.01414 - 12.78380 11.61317 10.95094 10.35055 9.80258 9.30011 - 8.84080 8.42157 8.03981 7.69253 7.37608 7.08537 - 6.81253 6.54968 6.29004 6.02042 5.71175 5.29540 - 4.65059 4.17340 3.51182 2.77827 1.72876 1.37863 - 1.06625 1.02720 1.00401 1.00033 0.98849 0.99534 - 12.77763 11.61775 10.97769 10.39720 9.86834 9.38502 - 8.94510 8.54581 8.18473 7.85913 7.56558 7.29910 - 7.05179 6.81592 6.58558 6.34863 6.07726 5.70317 - 5.09762 4.62794 3.94624 3.14897 1.92488 1.49544 - 1.08796 1.03052 0.99163 0.98772 0.98007 0.98544 - 12.77564 11.62412 10.99691 10.42838 9.91123 9.44026 - 9.01328 8.62767 8.28119 7.97126 7.69455 7.44616 - 7.21807 7.00270 6.79491 6.58381 6.34332 6.00727 - 5.44417 4.99042 4.30638 3.46984 2.10826 1.60791 - 1.11347 1.03870 0.98382 0.97930 0.97559 0.97934 - 12.76033 11.62949 11.01846 10.46170 9.95324 9.48885 - 9.06715 8.68672 8.34647 8.04441 7.77791 7.54330 - 7.33487 7.14491 6.96253 6.77009 6.53963 6.21715 - 5.69330 5.27885 4.64521 3.80556 2.28522 1.70107 - 1.12597 1.04399 0.98662 0.98149 0.97294 0.97521 - 12.76409 11.64291 11.03898 10.49088 9.99273 9.54098 - 9.13348 8.76828 8.44368 8.15779 7.90815 7.69090 - 7.49942 7.32755 7.17159 7.02202 6.85288 6.59289 - 6.11277 5.71601 5.10938 4.28421 2.62046 1.91565 - 1.16821 1.05920 0.98582 0.97877 0.97155 0.96998 - 12.75339 11.64847 11.05397 10.51407 10.02363 9.57953 - 9.17973 8.82253 8.50651 8.23002 7.99099 7.78598 - 7.60905 7.45474 7.32035 7.19764 7.06221 6.84382 - 6.41461 6.04818 5.47416 4.66117 2.90889 2.11485 - 1.21644 1.08136 0.98654 0.97759 0.96816 0.96678 - 12.71547 11.65254 11.07896 10.55484 10.07654 9.64221 - 9.25085 8.90203 8.59565 8.33083 8.10649 7.92065 - 7.76928 7.64803 7.55235 7.46879 7.37389 7.22194 - 6.91047 6.61653 6.10451 5.33486 3.52044 2.54963 - 1.33555 1.14338 0.99368 0.97822 0.96403 0.96248 - 12.68959 11.65918 11.09122 10.57246 10.09976 9.67118 - 9.28595 8.94371 8.64439 8.38735 8.17177 7.99607 - 7.85677 7.75026 7.67318 7.61386 7.55196 7.44767 - 7.21013 6.97035 6.52983 5.82233 3.97938 2.90456 - 1.45846 1.21397 1.00344 0.97913 0.95944 0.96033 - 12.61557 11.66449 11.10336 10.59081 10.12395 9.70128 - 9.32217 8.98638 8.69401 8.44464 8.23790 8.07268 - 7.94629 7.85613 7.80052 7.77063 7.75057 7.70822 - 7.56705 7.39650 7.04751 6.44339 4.68126 3.49281 - 1.68082 1.34586 1.02709 0.98513 0.96010 0.95815 - 12.55044 11.66567 11.10847 10.59933 10.13554 9.71598 - 9.34006 9.00762 8.71891 8.47375 8.27183 8.11230 - 7.99280 7.91118 7.86680 7.85259 7.85579 7.85014 - 7.77053 7.64678 7.36305 6.83947 5.18681 3.95582 - 1.88571 1.47154 1.05254 0.99353 0.96229 0.95705 - 12.50410 11.66827 11.11319 10.60470 10.14148 9.72297 - 9.34877 9.01884 8.73333 8.49167 8.29282 8.13584 - 8.01970 7.94348 7.90698 7.90349 7.92252 7.94531 - 7.90753 7.80844 7.56980 7.12157 5.58677 4.31870 - 2.07452 1.59468 1.07796 1.00101 0.96774 0.95639 - 12.47094 11.66899 11.11567 10.60816 10.14574 9.72839 - 9.35570 9.02744 8.74366 8.50381 8.30698 8.15239 - 8.03922 7.96687 7.93536 7.93852 7.96699 8.00575 - 7.99960 7.92755 7.72733 7.32684 5.88973 4.64152 - 2.25349 1.70565 1.10447 1.01278 0.97065 0.95596 - 12.42927 11.67020 11.11907 10.61288 10.15162 9.73592 - 9.36513 9.03874 8.75647 8.51835 8.32439 8.17416 - 8.06583 7.99828 7.97235 7.98355 8.02442 8.08182 - 8.11772 8.08994 7.95236 7.60703 6.30115 5.18235 - 2.59745 1.90723 1.15579 1.04352 0.96845 0.95540 - 12.40406 11.67075 11.12063 10.61557 10.15539 9.74069 - 9.37091 9.04560 8.76465 8.52805 8.33579 8.18749 - 8.08145 8.01686 7.99488 8.01152 8.06045 8.13107 - 8.19155 8.18667 8.09198 7.80872 6.62514 5.56475 - 2.89645 2.10141 1.20750 1.06778 0.97351 0.95507 - 12.36637 11.67150 11.12260 10.61914 10.16075 9.74748 - 9.37891 9.05491 8.77564 8.54107 8.35115 8.20549 - 8.10266 8.04219 8.02565 8.04968 8.10951 8.19861 - 8.29357 8.32120 8.29104 8.10965 7.15575 6.22906 - 3.51499 2.53141 1.33324 1.13162 0.98659 0.95463 - 12.34476 11.67191 11.12374 10.62107 10.16351 9.75091 - 9.38296 9.05960 8.78113 8.54753 8.35879 8.21452 - 8.11341 8.05510 8.04139 8.06922 8.13473 8.23366 - 8.34704 8.39181 8.39622 8.27529 7.48346 6.66292 - 3.99873 2.90051 1.45387 1.19729 0.99964 0.95441 - 12.32110 11.67230 11.12497 10.62301 10.16605 9.75411 - 9.38686 9.06423 8.78654 8.55386 8.36623 8.22340 - 8.12406 8.06796 8.05712 8.08886 8.16028 8.26942 - 8.40209 8.46459 8.50435 8.45135 7.87402 7.20674 - 4.71812 3.49444 1.67861 1.32704 1.02567 0.95419 - 12.33010 11.67940 11.12419 10.61878 10.16142 9.75061 - 9.38540 9.06517 8.78955 8.55846 8.37172 8.22854 - 8.12641 8.06524 8.05116 8.09074 8.18530 8.31137 - 8.43758 8.49776 8.54953 8.53846 8.11230 7.53369 - 5.22665 3.96288 1.88541 1.45329 1.05061 0.95408 - 12.32179 11.67923 11.12440 10.61933 10.16220 9.75163 - 9.38666 9.06664 8.79126 8.56044 8.37399 8.23118 - 8.12952 8.06903 8.05589 8.09678 8.19325 8.32221 - 8.45404 8.52027 8.58478 8.59756 8.25742 7.76038 - 5.61463 4.33807 2.09196 1.57454 1.07613 0.95401 - 12.31590 11.67908 11.12451 10.61966 10.16269 9.75229 - 9.38747 9.06760 8.79239 8.56173 8.37549 8.23295 - 8.13162 8.07158 8.05904 8.10080 8.19856 8.32950 - 8.46523 8.53551 8.60841 8.63744 8.36000 7.92420 - 5.92009 4.65204 2.28366 1.69326 1.10161 0.95397 - 12.28722 11.67251 11.12641 10.62509 10.16864 9.75753 - 9.39136 9.07003 8.79368 8.56236 8.37607 8.23465 - 8.13713 8.08367 8.07655 8.11358 8.19279 8.31468 - 8.47311 8.56055 8.64605 8.68756 8.49156 8.14578 - 6.37699 5.15241 2.62592 1.93103 1.15310 0.95391 - 12.28413 11.67228 11.12622 10.62541 10.16962 9.75862 - 9.39219 9.07052 8.79407 8.56294 8.37701 8.23605 - 8.13904 8.08601 8.07932 8.11676 8.19656 8.31982 - 8.48167 8.57234 8.66315 8.71550 8.57416 8.28509 - 6.70322 5.54090 2.92458 2.14175 1.20381 0.95388 - 1.21010 1.25686 1.30383 1.35113 1.39856 1.44592 - 1.49299 1.53961 1.58567 1.63103 1.67562 1.71966 - 1.76398 1.80897 1.85343 1.89477 1.93040 1.96056 - 1.98635 1.99918 2.01702 2.03601 2.05242 2.05659 - 2.06097 2.06136 2.06117 2.06113 2.06115 2.06185 - 1.62278 1.67344 1.72438 1.77597 1.82804 1.88042 - 1.93287 1.98511 2.03688 2.08794 2.13801 2.18697 - 2.23502 2.28217 2.32768 2.37060 2.41011 2.44663 - 2.48016 2.49530 2.51003 2.52199 2.53702 2.54235 - 2.54857 2.54849 2.54574 2.54491 2.54532 2.54932 - 1.97369 2.03036 2.08674 2.14334 2.19997 2.25635 - 2.31217 2.36710 2.42079 2.47295 2.52335 2.57190 - 2.61900 2.66487 2.70887 2.75028 2.78878 2.82612 - 2.86362 2.88133 2.89681 2.90711 2.91995 2.92476 - 2.93014 2.93006 2.92780 2.92715 2.92747 2.93074 - 2.55287 2.62627 2.69571 2.76193 2.82458 2.88345 - 2.93856 2.99041 3.03977 3.08672 3.13129 3.17367 - 3.21482 3.25551 3.29532 3.33359 3.36982 3.40464 - 3.43839 3.45445 3.47013 3.48220 3.49430 3.49723 - 3.49871 3.49909 3.50014 3.50035 3.50034 3.49931 - 3.01745 3.11388 3.19692 3.26873 3.33130 3.38724 - 3.43733 3.48253 3.52439 3.56345 3.60045 3.63577 - 3.66940 3.70145 3.73210 3.76235 3.79300 3.82323 - 3.85261 3.86751 3.88288 3.89532 3.90679 3.90811 - 3.90668 3.90750 3.91116 3.91218 3.91166 3.90714 - 3.41133 3.51906 3.61258 3.69275 3.75915 3.81221 - 3.85370 3.88725 3.91778 3.94646 3.97357 3.99935 - 4.02455 4.04977 4.07461 4.09824 4.12024 4.14240 - 4.16704 4.18059 4.19514 4.20701 4.21719 4.21879 - 4.21435 4.21522 4.22102 4.22234 4.22201 4.21487 - 3.75125 3.87096 3.97193 4.05517 4.12027 4.16805 - 4.20106 4.22432 4.24451 4.26326 4.28093 4.29783 - 4.31464 4.33189 4.34914 4.36531 4.37983 4.39505 - 4.41415 4.42570 4.43868 4.44957 4.45849 4.45964 - 4.45400 4.45494 4.46155 4.46306 4.46268 4.45448 - 4.31922 4.45235 4.55958 4.64241 4.70061 4.73567 - 4.75145 4.75503 4.75558 4.75547 4.75514 4.75514 - 4.75605 4.75836 4.76150 4.76380 4.76441 4.76656 - 4.77471 4.78171 4.79006 4.79722 4.80306 4.80360 - 4.79834 4.79911 4.80480 4.80611 4.80579 4.79867 - 4.78290 4.91895 5.02404 5.10037 5.14799 5.16897 - 5.16807 5.15373 5.13662 5.11955 5.10306 5.08790 - 5.07459 5.06364 5.05429 5.04441 5.03276 5.02330 - 5.02131 5.02354 5.02632 5.02849 5.03090 5.03111 - 5.02817 5.02855 5.03155 5.03224 5.03209 5.02832 - 5.65136 5.80210 5.88711 5.91954 5.91470 5.89033 - 5.85291 5.80858 5.76454 5.72074 5.67474 5.62598 - 5.57881 5.53689 5.49971 5.46465 5.43032 5.40134 - 5.37869 5.36662 5.35476 5.34644 5.34020 5.33953 - 5.34381 5.34315 5.33840 5.33711 5.33763 5.34355 - 6.29240 6.41728 6.46796 6.46194 6.41788 6.35644 - 6.28484 6.20937 6.13700 6.06712 5.99617 5.92317 - 5.85404 5.79311 5.73883 5.68594 5.63169 5.58535 - 5.54749 5.52435 5.50024 5.48246 5.46935 5.46789 - 5.47755 5.47605 5.46535 5.46245 5.46360 5.47695 - 7.37483 7.27797 7.17195 7.06632 6.96109 6.85615 - 6.75161 6.64759 6.54381 6.44096 6.33955 6.23945 - 6.14142 6.04532 5.95179 5.86172 5.77621 5.69619 - 5.62558 5.59751 5.57747 5.56452 5.52412 5.50789 - 5.52355 5.52477 5.50945 5.50437 5.50890 5.52617 - 7.98821 7.83252 7.66782 7.50602 7.34712 7.19107 - 7.03807 6.88838 6.74192 6.59962 6.46244 6.33021 - 6.20426 6.08497 5.97324 5.87024 5.77658 5.68976 - 5.60925 5.57394 5.54367 5.51843 5.45801 5.43626 - 5.45671 5.45973 5.44462 5.43944 5.44409 5.45904 - 8.44694 8.23910 8.02299 7.81251 7.60751 7.40801 - 7.21419 7.02624 6.84447 6.66980 6.50342 6.34513 - 6.19649 6.05844 5.93193 5.81834 5.71790 5.62579 - 5.53855 5.49874 5.46241 5.42987 5.35591 5.32890 - 5.34823 5.35295 5.34216 5.33812 5.34212 5.35006 - 8.69624 8.53060 8.32317 8.09336 7.84604 7.58814 - 7.32863 7.07914 6.85253 6.65121 6.47358 6.31542 - 6.17134 6.03658 5.90894 5.78511 5.66266 5.54391 - 5.43266 5.38018 5.32717 5.28472 5.24454 5.23470 - 5.22728 5.22625 5.22487 5.22464 5.22460 5.22530 - 9.20253 9.04469 8.76272 8.41397 8.04742 7.70710 - 7.39843 7.11912 6.86734 6.64058 6.43319 6.24031 - 6.06072 5.89464 5.74101 5.59893 5.46528 5.33047 - 5.19680 5.13948 5.08572 5.04369 4.99635 4.98304 - 4.96138 4.96138 4.97124 4.97406 4.97276 4.95905 - 9.59906 9.37018 9.01604 8.59950 8.17245 7.78010 - 7.42685 7.10928 6.82404 6.56810 6.33491 6.11885 - 5.91739 5.73013 5.55700 5.39824 5.25109 5.10184 - 4.95335 4.89195 4.83520 4.79065 4.73845 4.72327 - 4.69567 4.69604 4.71015 4.71415 4.71235 4.69311 - 10.25870 9.85014 9.34370 8.80198 8.27173 7.79122 - 7.36157 6.97821 6.63637 6.32916 6.04721 5.78393 - 5.53891 5.31271 5.10548 4.91367 4.73396 4.56003 - 4.39284 4.31692 4.24393 4.18713 4.12759 4.11210 - 4.09422 4.09331 4.09756 4.09888 4.09817 4.09124 - 10.77465 10.06759 9.40245 8.79361 8.23540 7.72395 - 7.25575 6.82840 6.44054 6.08868 5.76850 5.47528 - 5.20334 4.94922 4.71430 4.49806 4.29891 4.11095 - 3.92953 3.84160 3.75398 3.68472 3.62039 3.61028 - 3.60412 3.60106 3.59247 3.59026 3.59123 3.60132 - 11.20916 10.36119 9.54558 8.78824 8.10226 7.49866 - 6.96938 6.50069 6.08051 5.69917 5.34625 5.01575 - 4.70830 4.42394 4.16046 3.91313 3.67796 3.46104 - 3.26237 3.16502 3.06960 2.99680 2.92793 2.91181 - 2.90472 2.90235 2.89549 2.89378 2.89429 2.90133 - 11.56878 10.48863 9.54629 8.72142 7.99539 7.35447 - 6.78887 6.28581 5.83352 5.42483 5.05330 4.71186 - 4.39206 4.08843 3.80157 3.53344 3.28462 3.05190 - 2.83578 2.73527 2.63931 2.56662 2.49467 2.47654 - 2.45987 2.45849 2.45943 2.45981 2.45948 2.45656 - 11.79316 10.59807 9.57903 8.69612 7.92799 7.25639 - 6.66795 6.14682 5.67806 5.25348 4.86669 4.51078 - 4.17753 3.86160 3.56335 3.28431 3.02557 2.78333 - 2.55710 2.45155 2.35161 2.27676 2.20296 2.18450 - 2.16704 2.16570 2.16721 2.16774 2.16736 2.16374 - 11.96018 10.68652 9.61765 8.69571 7.89865 7.20585 - 6.60055 6.06504 5.58285 5.14534 4.74626 4.37889 - 4.03537 3.71057 3.40448 3.11814 2.85223 2.60319 - 2.36896 2.25876 2.15403 2.07561 2.00014 1.98177 - 1.96619 1.96462 1.96431 1.96442 1.96416 1.96280 - 12.19551 10.83136 9.70973 8.74423 7.91321 7.19462 - 6.56714 6.01105 5.50897 5.05235 4.63506 4.25077 - 3.89217 3.55436 3.23680 2.93956 2.66209 2.40107 - 2.15241 2.03368 1.92013 1.83489 1.75463 1.73554 - 1.72161 1.71968 1.71709 1.71668 1.71655 1.71776 - 12.35617 10.95078 9.80952 8.82602 7.97967 7.24755 - 6.60693 6.03756 5.52228 5.05278 4.62313 4.22707 - 3.85753 3.50964 3.18256 2.87580 2.58788 2.31441 - 2.05128 1.92417 1.80221 1.71021 1.62306 1.60208 - 1.58644 1.58439 1.58185 1.58146 1.58132 1.58201 - 12.61073 11.17001 10.02350 9.03189 8.17875 7.43478 - 6.78001 6.19551 5.66569 5.18226 4.73878 4.32834 - 3.94291 3.57712 3.23036 2.90251 2.59120 2.28844 - 1.98871 1.83948 1.69174 1.57625 1.46625 1.43906 - 1.41695 1.41444 1.41263 1.41242 1.41218 1.41167 - 12.76584 11.31449 10.17800 9.19463 8.34854 7.60639 - 6.95100 6.36529 5.83506 5.35155 4.90737 4.49428 - 4.10244 3.72557 3.36394 3.01880 2.68786 2.36004 - 2.02513 1.85303 1.67474 1.52923 1.39254 1.35948 - 1.33296 1.32967 1.32669 1.32629 1.32603 1.32691 - 12.94713 11.47917 10.36918 9.41942 8.60207 7.88401 - 7.24791 6.67630 6.15434 5.67422 5.22989 4.81450 - 4.41975 4.03905 3.66927 3.30601 2.94274 2.56834 - 2.16841 1.95283 1.72003 1.51811 1.31647 1.27350 - 1.24727 1.24309 1.23414 1.23215 1.23304 1.23765 - 13.03155 11.56609 10.48920 9.57425 8.78404 8.08947 - 7.47343 6.91858 6.40982 5.93970 5.50247 5.09150 - 4.69846 4.31652 3.94200 3.56947 3.18996 2.78648 - 2.33517 2.08021 1.79444 1.53990 1.28148 1.22746 - 1.20136 1.19674 1.18265 1.17924 1.18127 1.18783 - 13.06746 11.61208 10.56992 9.68623 8.92072 8.24722 - 7.64922 7.10957 6.61324 6.15303 5.72361 5.31857 - 4.92974 4.55014 4.17553 3.79948 3.41070 2.98712 - 2.49620 2.20909 1.87748 1.57724 1.26630 1.20006 - 1.17109 1.16622 1.14912 1.14486 1.14762 1.15410 - 13.07812 11.63638 10.62808 9.77163 9.02816 8.37311 - 7.79079 7.26448 6.77935 6.32852 5.90693 5.50845 - 5.12505 4.74967 4.37755 4.00128 3.60755 3.16989 - 2.64791 2.33412 1.96339 1.62217 1.26254 1.18358 - 1.14934 1.14415 1.12533 1.12058 1.12377 1.12928 - 13.06570 11.65424 10.70661 9.89521 9.18862 8.56408 - 8.00757 7.50334 7.03736 6.60327 6.19650 5.81137 - 5.44023 5.07589 4.71278 4.34177 3.94607 3.49166 - 2.92392 2.56756 2.13173 1.72030 1.27823 1.17407 - 1.11568 1.10941 1.09502 1.09128 1.09258 1.09498 - 12.91526 11.62736 10.78301 10.03148 9.35522 8.74054 - 8.18252 7.67504 7.21300 6.79082 6.40219 6.03904 - 5.69022 5.34563 4.99838 4.63707 4.23987 3.76154 - 3.13972 2.74918 2.28176 1.83967 1.32538 1.17864 - 1.08657 1.08348 1.08170 1.07698 1.06241 1.07233 - 12.84949 11.61303 10.84606 10.15699 9.53333 8.96404 - 8.44537 7.97249 7.54134 7.14742 6.78542 6.44829 - 6.12605 5.80900 5.48963 5.15474 4.77779 4.30162 - 3.64050 3.20082 2.64857 2.09986 1.42110 1.21549 - 1.06589 1.05518 1.05098 1.04654 1.03047 1.03948 - 12.87136 11.63801 10.89441 10.22786 9.62629 9.07989 - 8.58487 8.13651 7.73069 7.36272 7.02689 6.71537 - 6.41658 6.11992 5.81882 5.50201 5.14671 4.70253 - 4.07110 3.61994 3.00180 2.34508 1.50104 1.24875 - 1.07324 1.05200 1.02747 1.02361 1.02162 1.02183 - 12.75477 11.58403 10.91453 10.30891 9.75792 9.25434 - 8.79565 8.37858 8.00030 7.65760 7.34648 7.06138 - 6.79365 6.53482 6.27805 6.01019 5.70235 5.28674 - 4.64365 4.16815 3.50922 2.77881 1.73346 1.38447 - 1.07355 1.03483 1.01188 1.00812 0.99598 1.00322 - 12.73398 11.58046 10.93792 10.35595 9.82658 9.34370 - 8.90507 8.50782 8.14943 7.82705 7.53709 7.27431 - 7.03041 6.79731 6.56909 6.33368 6.06344 5.69073 - 5.08774 4.62021 3.94167 3.14805 1.92906 1.50107 - 1.09537 1.03831 0.99973 0.99576 0.98777 0.99345 - 12.72359 11.58229 10.95564 10.38777 9.87166 9.40207 - 8.97675 8.59309 8.24878 7.94119 7.66695 7.42100 - 7.19518 6.98176 6.77561 6.56588 6.32667 5.99231 - 5.43215 4.98074 4.30010 3.46753 2.11184 1.61331 - 1.12092 1.04657 0.99206 0.98748 0.98343 0.98744 - 12.70035 11.58325 10.97530 10.42109 9.91486 9.45269 - 9.03325 8.65517 8.31738 8.01791 7.75399 7.52146 - 7.31330 7.12174 6.93851 6.74585 6.51554 6.19844 - 5.68533 5.27261 4.63486 3.79926 2.28896 1.71036 - 1.13155 1.04828 0.99515 0.99138 0.98301 0.98338 - 12.70204 11.59546 10.99561 10.45091 9.95572 9.50649 - 9.10114 8.73776 8.41468 8.13002 7.88138 7.66498 - 7.47425 7.30317 7.14805 6.99948 6.83164 6.57360 - 6.09672 5.70255 5.09972 4.27898 2.62166 1.91953 - 1.17577 1.06729 0.99414 0.98701 0.97978 0.97826 - 12.66645 11.59143 11.01093 10.47990 9.99414 9.55153 - 9.15113 8.79250 8.47558 8.19915 7.96134 7.75919 - 7.58724 7.43941 7.30912 7.18022 7.02609 6.79880 - 6.39256 6.04278 5.47091 4.65141 2.90664 2.11363 - 1.22679 1.09124 0.99452 0.98638 0.97344 0.97513 - 12.65228 11.60359 11.03392 10.51311 10.03757 9.60547 - 9.21598 8.86870 8.56359 8.29989 8.07651 7.89157 - 7.74111 7.62088 7.52630 7.44380 7.34988 7.19900 - 6.88926 6.59719 6.08896 5.32461 3.51850 2.55117 - 1.34225 1.15099 1.00215 0.98663 0.97245 0.97093 - 12.62934 11.61063 11.04533 10.52906 10.05861 9.63214 - 9.24889 8.90843 8.61071 8.35506 8.14071 7.96612 - 7.82780 7.72221 7.64598 7.58751 7.52647 7.42320 - 7.18727 6.94912 6.51189 5.80917 3.97527 2.90499 - 1.46466 1.22113 1.01187 0.98773 0.96782 0.96883 - 12.55895 11.61695 11.05763 10.54692 10.08194 9.66123 - 9.28403 8.95002 8.65923 8.41128 8.20574 8.04159 - 7.91610 7.82672 7.77183 7.74263 7.72335 7.68193 - 7.54216 7.37293 7.02644 6.42636 4.67400 3.49079 - 1.68601 1.35243 1.03547 0.99379 0.96851 0.96670 - 12.49600 11.62094 11.06562 10.55720 10.09395 9.67528 - 9.30064 8.96977 8.68275 8.43922 8.23860 8.07997 - 7.96123 7.88053 7.83701 7.82311 7.82661 7.82516 - 7.75374 7.63003 7.33603 6.79398 5.17083 3.98003 - 1.88784 1.46986 1.05986 1.00780 0.96883 0.96564 - 12.44916 11.62214 11.06943 10.56265 10.10087 9.68399 - 9.31143 8.98278 8.69793 8.45672 8.25891 8.10381 - 7.98938 7.91397 7.87741 7.87336 7.89149 7.91269 - 7.88216 7.79390 7.55333 7.07412 5.54438 4.35957 - 2.07984 1.58773 1.08555 1.01819 0.97036 0.96500 - 12.41710 11.62286 11.07190 10.56629 10.10548 9.68984 - 9.31868 8.99156 8.70823 8.46866 8.27283 8.12015 - 8.00865 7.93686 7.90508 7.90784 7.93606 7.97317 - 7.97184 7.90974 7.71128 7.28460 5.84056 4.67487 - 2.26187 1.70046 1.11156 1.02907 0.97234 0.96457 - 12.37720 11.62378 11.07479 10.57069 10.11137 9.69733 - 9.32792 9.00268 8.72144 8.48418 8.29098 8.14140 - 8.03362 7.96652 7.94098 7.95246 7.99366 8.05157 - 8.08886 8.06229 7.92565 7.58177 6.28489 5.17261 - 2.59867 1.91166 1.16359 1.05194 0.97696 0.96402 - 12.35255 11.62434 11.07634 10.57328 10.11497 9.70190 - 9.33351 9.00942 8.72949 8.49376 8.30224 8.15455 - 8.04902 7.98483 7.96316 7.98000 8.02908 8.10003 - 8.16165 8.15791 8.06434 7.78258 6.60676 5.55278 - 2.89649 2.10522 1.21503 1.07601 0.98203 0.96370 - 12.31551 11.62509 11.07831 10.57662 10.11987 9.70816 - 9.34108 9.01843 8.74032 8.50669 8.31749 8.17238 - 8.06994 8.00978 7.99345 8.01754 8.07732 8.16642 - 8.26195 8.29046 8.26194 8.08270 7.13406 6.21297 - 3.51249 2.53359 1.34010 1.13938 0.99515 0.96327 - 12.29427 11.62560 11.07944 10.57845 10.12241 9.71138 - 9.34498 9.02304 8.74575 8.51312 8.32508 8.18133 - 8.08059 8.02254 8.00898 8.03682 8.10218 8.20098 - 8.31447 8.35975 8.36619 8.24814 7.45989 6.64419 - 3.99436 2.90115 1.46013 1.20460 1.00822 0.96305 - 12.27113 11.62599 11.08077 10.58048 10.12508 9.71471 - 9.34900 9.02777 8.75125 8.51948 8.33253 8.19016 - 8.09114 8.03525 8.02449 8.05618 8.12736 8.23625 - 8.36852 8.43108 8.47279 8.42300 7.84830 7.18496 - 4.71091 3.49254 1.68378 1.33358 1.03427 0.96284 - 12.28020 11.63289 11.07979 10.57645 10.12078 9.71157 - 9.34775 9.02875 8.75420 8.52399 8.33795 8.19530 - 8.09352 8.03256 8.01853 8.05792 8.15209 8.27765 - 8.40351 8.46391 8.51675 8.50755 8.08516 7.51030 - 5.21711 3.95886 1.88978 1.45921 1.05914 0.96273 - 12.27196 11.63262 11.08000 10.57699 10.12162 9.71266 - 9.34912 9.03031 8.75599 8.52601 8.34023 8.19793 - 8.09661 8.03628 8.02312 8.06380 8.15987 8.28838 - 8.41987 8.48604 8.55068 8.56421 8.22882 7.73626 - 5.60313 4.33211 2.09526 1.57997 1.08455 0.96267 - 12.26618 11.63237 11.08010 10.57731 10.12213 9.71334 - 9.34995 9.03132 8.75716 8.52737 8.34178 8.19971 - 8.09870 8.03880 8.02623 8.06774 8.16508 8.29561 - 8.43101 8.50103 8.57339 8.60234 8.33014 7.89929 - 5.90694 4.64441 2.28596 1.69831 1.10988 0.96263 - 12.23777 11.62531 11.08141 10.58235 10.12810 9.71871 - 9.35391 9.03367 8.75828 8.52782 8.34227 8.20144 - 8.10431 8.05095 8.04368 8.08039 8.15921 8.28062 - 8.43879 8.52618 8.61065 8.65148 8.46133 8.11891 - 6.36092 5.14215 2.62662 1.93485 1.16104 0.96258 - 12.23437 11.62507 11.08101 10.58227 10.12841 9.71915 - 9.35430 9.03399 8.75870 8.52851 8.34332 8.20290 - 8.10621 8.05330 8.04651 8.08368 8.16311 8.28594 - 8.44696 8.53714 8.62901 8.68350 8.54325 8.25646 - 6.68496 5.52847 2.92402 2.14471 1.21142 0.96254 - 1.17925 1.22341 1.26825 1.31391 1.36027 1.40715 - 1.45434 1.50158 1.54864 1.59524 1.64112 1.68617 - 1.73055 1.77427 1.81658 1.85649 1.89305 1.92624 - 1.95567 1.96871 1.98207 1.99434 2.01304 2.01968 - 2.02294 2.02281 2.02272 2.02273 2.02246 2.02340 - 1.57546 1.62759 1.68000 1.73297 1.78632 1.83983 - 1.89323 1.94622 1.99850 2.04980 2.09988 2.14869 - 2.19661 2.24384 2.28965 2.33312 2.37330 2.41023 - 2.44331 2.45767 2.47119 2.48185 2.49606 2.50151 - 2.50770 2.50757 2.50479 2.50397 2.50433 2.50835 - 1.91984 1.97902 2.03781 2.09668 2.15534 2.21349 - 2.27075 2.32675 2.38110 2.43351 2.48379 2.53200 - 2.57888 2.62497 2.66970 2.71231 2.75224 2.79027 - 2.82647 2.84273 2.85685 2.86639 2.87895 2.88386 - 2.88904 2.88892 2.88668 2.88602 2.88639 2.88961 - 2.49407 2.57235 2.64566 2.71463 2.77891 2.83839 - 2.89339 2.94488 2.99435 3.04204 3.08795 3.13215 - 3.17534 3.21796 3.25942 3.29869 3.33498 3.36915 - 3.40181 3.41718 3.43220 3.44385 3.45570 3.45859 - 3.46000 3.46038 3.46146 3.46169 3.46166 3.46059 - 2.96415 3.06181 3.14565 3.21793 3.28094 3.33759 - 3.38872 3.43527 3.47871 3.51958 3.55853 3.59582 - 3.63133 3.66503 3.69707 3.72838 3.75971 3.79002 - 3.81879 3.83323 3.84820 3.86044 3.87177 3.87305 - 3.87155 3.87238 3.87611 3.87715 3.87661 3.87201 - 3.36503 3.46913 3.56018 3.63910 3.70546 3.75964 - 3.80316 3.83929 3.87244 3.90363 3.93309 3.96101 - 3.98804 4.01475 4.04078 4.06553 4.08868 4.11162 - 4.13619 4.14943 4.16385 4.17583 4.18591 4.18748 - 4.18295 4.18384 4.18973 4.19106 4.19072 4.18349 - 3.73782 3.82208 3.89972 3.97213 4.03842 4.09771 - 4.14910 4.19181 4.22530 4.24945 4.26513 4.27436 - 4.28143 4.29040 4.30202 4.31704 4.33636 4.36094 - 4.39083 4.40574 4.41558 4.41889 4.42907 4.43297 - 4.42650 4.42690 4.43365 4.43530 4.43509 4.42665 - 4.29287 4.40364 4.49689 4.57422 4.63484 4.67866 - 4.70675 4.72173 4.72749 4.72587 4.71907 4.71105 - 4.70862 4.71666 4.73163 4.74296 4.74258 4.74083 - 4.75004 4.75861 4.76808 4.77564 4.78178 4.78115 - 4.77687 4.77781 4.78317 4.78469 4.78385 4.77701 - 4.75836 4.86937 4.95913 5.02988 5.08090 5.11237 - 5.12575 5.12432 5.11284 5.09355 5.06915 5.04440 - 5.02701 5.02246 5.02655 5.02689 5.01415 5.00081 - 5.00065 5.00455 5.00877 5.01172 5.01429 5.01396 - 5.01164 5.01212 5.01495 5.01576 5.01528 5.01169 - 5.62151 5.73371 5.81058 5.85646 5.87205 5.86012 - 5.82598 5.77861 5.72907 5.68019 5.63305 5.58862 - 5.54797 5.51183 5.47932 5.44753 5.41466 5.38507 - 5.36411 5.35638 5.34655 5.33702 5.33207 5.33186 - 5.33630 5.33562 5.33074 5.32961 5.32994 5.33604 - 6.24082 6.35951 6.41092 6.41031 6.37314 6.31696 - 6.24881 6.17575 6.10561 6.03794 5.96910 5.89804 - 5.83080 5.77183 5.71971 5.66934 5.61810 5.57508 - 5.54045 5.51876 5.49597 5.47917 5.46720 5.46602 - 5.47608 5.47459 5.46374 5.46080 5.46197 5.47552 - 7.14962 7.17511 7.15562 7.10176 7.01652 6.90507 - 6.77549 6.63958 6.51029 6.39136 6.28294 6.18401 - 6.09339 6.00909 5.93064 5.85627 5.78419 5.71404 - 5.64567 5.61176 5.57589 5.54585 5.52119 5.52207 - 5.53284 5.53042 5.51542 5.51117 5.51356 5.53263 - 7.77625 7.73937 7.65615 7.54063 7.39680 7.23080 - 7.05154 6.87147 6.70384 6.55222 6.41632 6.29392 - 6.18247 6.07874 5.98176 5.88914 5.79852 5.70950 - 5.62213 5.57886 5.53398 5.49721 5.46562 5.46412 - 5.47160 5.46919 5.45577 5.45201 5.45410 5.47090 - 8.25404 8.15809 8.01647 7.84593 7.65112 7.43877 - 7.21814 7.00166 6.80273 6.62442 6.46601 6.32431 - 6.19559 6.07591 5.96380 5.85645 5.75116 5.64765 - 5.54647 5.49709 5.44732 5.40778 5.37179 5.36673 - 5.36745 5.36559 5.35746 5.35525 5.35643 5.36618 - 8.60249 8.52291 8.33836 8.09055 7.81475 7.54503 - 7.29053 7.05669 6.84900 6.66394 6.49271 6.32913 - 6.17656 6.03742 5.90973 5.78909 5.67165 5.55786 - 5.44832 5.39504 5.34274 5.30253 5.26331 5.25380 - 5.24688 5.24582 5.24444 5.24416 5.24417 5.24496 - 9.16798 9.01818 8.74315 8.39987 8.03766 7.70103 - 7.39561 7.11929 6.87036 6.64627 6.44125 6.25042 - 6.07260 5.90808 5.75586 5.61510 5.48281 5.34958 - 5.21761 5.16103 5.10812 5.06696 5.02079 5.00781 - 4.98631 4.98636 4.99635 4.99918 4.99789 4.98405 - 9.73941 9.31632 8.89900 8.50580 8.13521 7.78641 - 7.45879 7.15182 6.86541 6.60057 6.35617 6.13074 - 5.92322 5.73423 5.56373 5.41150 5.27442 5.13818 - 4.99030 4.91677 4.85465 4.81655 4.76984 4.75044 - 4.72398 4.72497 4.73900 4.74279 4.74145 4.72174 - 10.40162 9.81571 9.25405 8.73422 8.25302 7.80774 - 7.39608 7.01714 6.67021 6.35365 6.06486 5.80049 - 5.55684 5.33213 5.12746 4.94133 4.77087 4.60378 - 4.43022 4.34526 4.27012 4.21968 4.16245 4.14450 - 4.12711 4.12667 4.13090 4.13214 4.13158 4.12441 - 10.77734 10.06948 9.40485 8.79715 8.24066 7.73149 - 7.26602 6.84178 6.45732 6.10901 5.79245 5.50272 - 5.23374 4.98183 4.74831 4.53268 4.33349 4.14509 - 3.96319 3.87510 3.78750 3.71846 3.65457 3.64458 - 3.63835 3.63526 3.62669 3.62447 3.62545 3.63560 - 11.24465 10.33222 9.51070 8.77865 8.12275 7.53473 - 7.00782 6.53350 6.10476 5.71649 5.36334 5.03982 - 4.73939 4.45745 4.19344 3.94628 3.71338 3.49501 - 3.29327 3.19861 3.10431 3.02968 2.95986 2.94520 - 2.93719 2.93490 2.92818 2.92643 2.92715 2.93405 - 11.54568 10.48446 9.55490 8.73798 8.01637 7.37739 - 6.81223 6.30914 5.85721 5.44939 5.07907 4.73902 - 4.42046 4.11772 3.83152 3.56393 3.31559 3.08326 - 2.86729 2.76667 2.67034 2.59718 2.52499 2.50681 - 2.49005 2.48866 2.48962 2.49001 2.48968 2.48667 - 11.75485 10.59039 9.59052 8.71823 7.95456 7.28332 - 6.69298 6.16954 5.69969 5.27530 4.88963 4.53534 - 4.20357 3.88860 3.59092 3.31229 3.05399 2.81220 - 2.58631 2.48076 2.38045 2.30504 2.23098 2.21248 - 2.19493 2.19358 2.19510 2.19563 2.19526 2.19151 - 11.91373 10.67599 9.62904 8.71887 7.92635 7.23330 - 6.62519 6.08648 5.60262 5.16504 4.76699 4.40125 - 4.05924 3.73537 3.42982 3.14384 2.87839 2.62987 - 2.39615 2.28604 2.18097 2.10198 2.02625 2.00784 - 1.99220 1.99062 1.99029 1.99039 1.99014 1.98869 - 12.14831 10.81767 9.71633 8.76204 7.93567 7.21736 - 6.58783 6.02925 5.52590 5.06925 4.65285 4.26991 - 3.91258 3.57564 3.25863 2.96185 2.68487 2.42444 - 2.17642 2.05792 1.94423 1.85860 1.77806 1.75891 - 1.74492 1.74298 1.74035 1.73993 1.73981 1.74105 - 12.31866 10.93636 9.80949 8.83476 7.99304 7.26268 - 6.62220 6.05243 5.53710 5.06804 4.63914 4.24403 - 3.87543 3.52835 3.20193 2.89574 2.60836 2.33546 - 2.07296 1.94615 1.82431 1.73223 1.64478 1.62368 - 1.60794 1.60587 1.60334 1.60295 1.60281 1.60362 - 12.59051 11.15570 10.01341 9.02603 8.17688 7.43665 - 6.78523 6.20350 5.67567 5.19356 4.75096 4.34115 - 3.95635 3.59135 3.24546 2.91841 2.60778 2.30564 - 2.00654 1.85764 1.71026 1.59501 1.48492 1.45765 - 1.43549 1.43297 1.43117 1.43096 1.43072 1.43030 - 12.74293 11.29840 10.16609 9.18646 8.34363 7.60449 - 6.95184 6.36851 5.84022 5.35830 4.91541 4.50341 - 4.11256 3.73663 3.37591 3.03167 2.70162 2.37466 - 2.04047 1.86864 1.69051 1.54513 1.40886 1.37594 - 1.34955 1.34626 1.34327 1.34287 1.34261 1.34361 - 12.89537 11.45136 10.35467 9.41277 8.59917 7.88235 - 7.24608 6.67403 6.15233 5.67322 5.23045 4.81695 - 4.42405 4.04501 3.67669 3.31473 2.95263 2.57925 - 2.18005 1.96467 1.73192 1.53014 1.32973 1.28746 - 1.26155 1.25744 1.24876 1.24682 1.24768 1.25357 - 12.88278 11.52005 10.49926 9.60795 8.81846 8.11018 - 7.47401 6.90099 6.38345 5.91362 5.48323 5.08259 - 4.69940 4.32419 3.95332 3.58178 3.20068 2.79278 - 2.33645 2.08225 1.80408 1.55877 1.29641 1.23527 - 1.21348 1.21087 1.19664 1.19281 1.19557 1.20402 - 12.89320 11.55105 10.57201 9.71689 8.95501 8.26897 - 7.65069 7.09205 6.58597 6.12527 5.70211 5.30714 - 4.92824 4.55570 4.18513 3.81013 3.41915 2.98950 - 2.49175 2.20598 1.88542 1.59826 1.28190 1.20535 - 1.18215 1.18006 1.16269 1.15785 1.16166 1.17013 - 12.88737 11.56423 10.62334 9.79863 9.06097 8.39462 - 7.79248 7.24699 6.75170 6.29985 5.88405 5.49531 - 5.12174 4.75352 4.38565 4.01053 3.61429 3.16929 - 2.63887 2.32682 1.96992 1.64493 1.27879 1.18717 - 1.15973 1.15784 1.13862 1.13316 1.13762 1.14492 - 12.84580 11.56163 10.68858 9.91517 9.21930 8.58685 - 8.01235 7.48936 7.01248 6.57593 6.17326 5.79640 - 5.43449 5.07789 4.72042 4.35206 3.95396 3.48766 - 2.90225 2.54515 2.12776 1.74243 1.30541 1.18556 - 1.11662 1.11576 1.11421 1.10975 1.09753 1.10969 - 12.81186 11.55590 10.73125 9.99481 9.32988 8.72340 - 8.17084 7.66650 7.20569 6.78323 6.39328 6.02841 - 5.67838 5.33374 4.98766 4.62871 4.23485 3.76015 - 3.14154 2.75242 2.28637 1.84559 1.33390 1.18839 - 1.09789 1.09515 1.09383 1.08925 1.07509 1.08621 - 12.75137 11.54376 10.79344 10.11739 9.50367 8.94170 - 8.42805 7.95821 7.52845 7.13455 6.77161 6.43319 - 6.11002 5.79310 5.47496 5.14242 4.76885 4.29655 - 3.63921 3.20139 2.65113 2.10439 1.42889 1.22458 - 1.07670 1.06640 1.06264 1.05829 1.04239 1.05200 - 12.78436 11.57569 10.84513 10.18873 9.59498 9.05440 - 8.56344 8.11761 7.71304 7.34526 7.00888 6.69654 - 6.39729 6.10113 5.80155 5.48736 5.13576 4.69600 - 4.06899 3.61954 3.00232 2.34680 1.50795 1.25780 - 1.08394 1.06290 1.03869 1.03498 1.03283 1.03356 - 12.68606 11.53300 10.87060 10.27074 9.72423 9.22428 - 8.76837 8.35334 7.97647 7.63463 7.32403 7.03926 - 6.77204 6.51414 6.25884 5.99302 5.68792 5.27563 - 4.63657 4.16350 3.50759 2.78039 1.73987 1.39237 - 1.08346 1.04521 1.02267 1.01888 1.00652 1.01404 - 12.67335 11.53469 10.89657 10.31821 9.79190 9.31158 - 8.87505 8.47948 8.12245 7.80113 7.51202 7.25001 - 7.00697 6.77500 6.54821 6.31465 6.04678 5.67706 - 5.07798 4.61303 3.93783 3.14795 1.93463 1.50840 - 1.10488 1.04831 1.01016 1.00613 0.99783 1.00375 - 12.66627 11.53847 10.91509 10.35000 9.83627 9.36875 - 8.94520 8.56306 8.22006 7.91359 7.64032 7.39529 - 7.17046 6.95819 6.75339 6.54534 6.30826 5.97665 - 5.42026 4.97146 4.29436 3.46587 2.11659 1.62011 - 1.13011 1.05626 1.00220 0.99756 0.99316 0.99740 - 12.64391 11.54027 10.93545 10.38360 9.87936 9.41880 - 9.00072 8.62384 8.28725 7.98895 7.72620 7.49482 - 7.28779 7.09734 6.91530 6.72399 6.49545 6.18094 - 5.67196 5.26216 4.62808 3.79636 2.29214 1.71627 - 1.14074 1.05792 1.00492 1.00109 0.99273 0.99311 - 12.64691 11.55252 10.95506 10.41230 9.91903 9.47149 - 9.06770 8.70572 8.38390 8.10041 7.85282 7.63737 - 7.44758 7.27741 7.12325 6.97578 6.80938 6.55353 - 6.08039 5.68910 5.09030 4.27410 2.62347 1.92420 - 1.18446 1.07653 1.00363 0.99643 0.98921 0.98769 - 12.63401 11.55622 10.96867 10.43468 9.94930 9.50955 - 9.11351 8.75945 8.44606 8.17170 7.93442 7.73090 - 7.55532 7.40248 7.26970 7.14893 7.01603 6.80128 - 6.37821 6.01687 5.45084 4.64748 2.90957 2.12188 - 1.23201 1.09818 1.00422 0.99516 0.98572 0.98440 - 12.59507 11.55873 10.99197 10.47348 10.00004 9.56972 - 9.18174 8.83576 8.53183 8.26916 8.04668 7.86250 - 7.71272 7.59310 7.49909 7.41727 7.32422 7.17462 - 6.86723 6.57739 6.07309 5.31403 3.51672 2.55314 - 1.34950 1.15914 1.01120 0.99564 0.98149 0.98001 - 12.59056 11.57319 11.00359 10.48561 10.01557 9.59113 - 9.21093 8.87379 8.57896 8.32541 8.11198 7.93661 - 7.79504 7.68415 7.60443 7.55255 7.51168 7.42224 - 7.17237 6.92191 6.48461 5.78564 3.96597 2.92661 - 1.46756 1.22264 1.02049 0.99891 0.97892 0.97782 - 12.52333 11.58074 11.01679 10.50387 10.03890 9.61974 - 9.24518 8.91425 8.62631 8.38060 8.17630 8.01174 - 7.88326 7.78860 7.72990 7.70658 7.70670 7.67970 - 7.52783 7.34568 6.99449 6.39155 4.65806 3.51717 - 1.68867 1.35135 1.04338 1.00680 0.97761 0.97558 - 12.44480 11.57704 11.02358 10.51705 10.05582 9.63900 - 9.26599 8.93651 8.65058 8.40788 8.20793 8.04985 - 7.93159 7.85126 7.80798 7.79418 7.79764 7.79638 - 7.72595 7.60337 7.31157 6.77351 5.16140 3.97613 - 1.89217 1.47607 1.06833 1.01662 0.97752 0.97443 - 12.40122 11.57816 11.02659 10.52210 10.06267 9.64765 - 9.27656 8.94930 8.66610 8.42640 8.22918 8.07355 - 7.95847 7.88308 7.84718 7.84424 7.86391 7.88782 - 7.85205 7.75467 7.51940 7.07787 5.56331 4.30624 - 2.08185 1.60645 1.09445 1.01814 0.98486 0.97374 - 12.37002 11.57898 11.02906 10.52573 10.06743 9.65360 - 9.28381 8.95797 8.67628 8.43827 8.24302 8.08975 - 7.97758 7.90597 7.87497 7.87852 7.90744 7.94711 - 7.94277 7.87225 7.67490 7.28041 5.86280 4.62568 - 2.25934 1.71670 1.12070 1.02971 0.98781 0.97328 - 12.32906 11.57981 11.03255 10.53073 10.07362 9.66127 - 9.29314 8.96895 8.68870 8.45240 8.26000 8.11104 - 8.00364 7.93676 7.91123 7.92262 7.96368 8.02145 - 8.05886 8.03276 7.89727 7.55588 6.26847 5.16279 - 2.60001 1.91623 1.17150 1.06043 0.98554 0.97270 - 12.30324 11.58007 11.03440 10.53352 10.07719 9.66570 - 9.29856 8.97552 8.69665 8.46191 8.27120 8.12410 - 8.01895 7.95494 7.93327 7.95001 7.99898 8.06969 - 8.13117 8.12771 8.03501 7.75532 6.58809 5.54075 - 2.89658 2.10911 1.22265 1.08432 0.99058 0.97236 - 12.26461 11.58043 11.03657 10.53706 10.08190 9.67163 - 9.30584 8.98437 8.70735 8.47473 8.28633 8.14175 - 8.03967 7.97969 7.96338 7.98738 8.04700 8.13581 - 8.23094 8.25940 8.23127 8.05345 7.11160 6.19689 - 3.51018 2.53595 1.34708 1.14720 1.00368 0.97190 - 12.24384 11.58075 11.03750 10.53869 10.08434 9.67476 - 9.30967 8.98892 8.71273 8.48107 8.29381 8.15060 - 8.05021 7.99234 7.97878 8.00650 8.07167 8.17016 - 8.28325 8.32835 8.33491 8.21777 7.43512 6.62536 - 3.99018 2.90202 1.46651 1.21198 1.01676 0.97167 - 12.22248 11.58125 11.03843 10.54031 10.08681 9.67804 - 9.31365 8.99358 8.71809 8.48725 8.30106 8.15928 - 8.06066 8.00495 7.99416 8.02567 8.09659 8.20520 - 8.33712 8.39942 8.44097 8.39155 7.82085 7.16259 - 4.70382 3.49089 1.68910 1.34018 1.04278 0.97145 - 12.21152 11.58144 11.03865 10.54098 10.08783 9.67935 - 9.31525 8.99565 8.72095 8.49103 8.30552 8.16406 - 8.06596 8.01133 8.00179 8.03370 8.10483 8.22056 - 8.37795 8.45442 8.48165 8.41225 8.08002 7.65286 - 5.13240 3.85606 1.90438 1.49789 1.06481 0.97133 - 12.22454 11.58828 11.03786 10.53672 10.08315 9.67577 - 9.31361 8.99606 8.72277 8.49368 8.30863 8.16686 - 8.06593 8.00585 7.99274 8.03329 8.12903 8.25707 - 8.38810 8.45403 8.51844 8.53200 8.19883 7.71017 - 5.59162 4.32640 2.09861 1.58539 1.09287 0.97126 - 12.21897 11.58813 11.03796 10.53705 10.08366 9.67643 - 9.31444 8.99702 8.72391 8.49498 8.31013 8.16860 - 8.06798 8.00832 7.99581 8.03722 8.13423 8.26428 - 8.39913 8.46890 8.54100 8.56994 8.29947 7.87205 - 5.89366 4.63704 2.28832 1.70331 1.11806 0.97121 - 12.19081 11.58147 11.03967 10.54228 10.08953 9.68164 - 9.31828 8.99933 8.72503 8.49541 8.31052 8.17020 - 8.07344 8.02033 8.01320 8.04988 8.12844 8.24928 - 8.40669 8.49383 8.57814 8.61897 8.42982 8.08989 - 6.34468 5.13201 2.62737 1.93865 1.16897 0.97116 - 12.18750 11.58173 11.03977 10.54240 10.08970 9.68185 - 9.31853 8.99967 8.72551 8.49612 8.31154 8.17161 - 8.07528 8.02260 8.01589 8.05298 8.13212 8.25455 - 8.41501 8.50476 8.59647 8.65094 8.51090 8.22629 - 6.66644 5.51607 2.92354 2.14773 1.21902 0.97114 - 1.14738 1.19043 1.23424 1.27900 1.32458 1.37084 - 1.41759 1.46462 1.51169 1.55855 1.60493 1.65067 - 1.69584 1.74031 1.78330 1.82376 1.86059 1.89365 - 1.92228 1.93455 1.94692 1.95818 1.97584 1.98225 - 1.98518 1.98498 1.98483 1.98483 1.98454 1.98554 - 1.53719 1.58853 1.64025 1.69264 1.74556 1.79879 - 1.85210 1.90518 1.95774 2.00955 2.06032 2.10995 - 2.15874 2.20675 2.25322 2.29712 2.33743 2.37410 - 2.40634 2.42000 2.43264 2.44252 2.45610 2.46145 - 2.46723 2.46707 2.46444 2.46368 2.46399 2.46779 - 1.87711 1.93572 1.99407 2.05263 2.11116 2.16934 - 2.22681 2.28324 2.33821 2.39145 2.44273 2.49206 - 2.54007 2.58717 2.63270 2.67583 2.71586 2.75342 - 2.78843 2.80389 2.81739 2.82666 2.83875 2.84338 - 2.84824 2.84815 2.84608 2.84548 2.84582 2.84878 - 2.44581 2.52351 2.59658 2.66564 2.73035 2.79057 - 2.84659 2.89929 2.95009 2.99917 3.04652 3.09221 - 3.13689 3.18097 3.22366 3.26366 3.29991 3.33342 - 3.36504 3.37984 3.39450 3.40606 3.41755 3.42031 - 3.42155 3.42193 3.42310 3.42336 3.42332 3.42212 - 2.91200 3.00971 3.09384 3.16666 3.23050 3.28832 - 3.34090 3.38908 3.43420 3.47677 3.51741 3.55645 - 3.59387 3.62969 3.66371 3.69619 3.72724 3.75646 - 3.78439 3.79877 3.81378 3.82602 3.83711 3.83828 - 3.83673 3.83756 3.84128 3.84232 3.84179 3.83718 - 3.31061 3.41492 3.50661 3.58649 3.65415 3.70991 - 3.75523 3.79325 3.82829 3.86136 3.89273 3.92265 - 3.95196 3.98121 4.00967 4.03577 4.05851 4.08041 - 4.10470 4.11817 4.13290 4.14505 4.15494 4.15646 - 4.15196 4.15283 4.15866 4.15998 4.15964 4.15249 - 3.66024 3.76534 3.85788 3.93886 4.00752 4.06355 - 4.10753 4.14122 4.16741 4.18731 4.20255 4.21605 - 4.23329 4.25812 4.28748 4.31239 4.32591 4.33669 - 4.35598 4.36929 4.38350 4.39472 4.40382 4.40351 - 4.39902 4.40016 4.40627 4.40801 4.40708 4.39929 - 4.23398 4.34660 4.44188 4.52133 4.58412 4.63014 - 4.66042 4.67758 4.68554 4.68612 4.68155 4.67585 - 4.67593 4.68669 4.70429 4.71744 4.71755 4.71590 - 4.72619 4.73581 4.74630 4.75444 4.76069 4.76005 - 4.75583 4.75678 4.76209 4.76360 4.76276 4.75601 - 4.69825 4.81179 4.90422 4.97764 5.03128 5.06528 - 5.08110 5.08202 5.07281 5.05575 5.03354 5.01097 - 4.99586 4.99371 5.00018 5.00249 4.99105 4.97899 - 4.98092 4.98616 4.99165 4.99537 4.99831 4.99802 - 4.99573 4.99622 4.99907 4.99989 4.99941 4.99582 - 5.56054 5.67698 5.75790 5.80743 5.82626 5.81713 - 5.78548 5.74042 5.69323 5.64678 5.60202 5.55977 - 5.52082 5.48581 5.45426 5.42425 5.39471 5.36920 - 5.35203 5.34599 5.33769 5.32920 5.32515 5.32510 - 5.32951 5.32885 5.32412 5.32303 5.32335 5.32929 - 6.18094 6.30616 6.36229 6.36490 6.33035 6.27709 - 6.21208 6.14195 6.07415 6.00853 5.94218 5.87405 - 5.80858 5.74931 5.69606 5.64682 5.60105 5.56439 - 5.53360 5.51342 5.49231 5.47694 5.46597 5.46501 - 5.47513 5.47369 5.46293 5.46002 5.46117 5.47462 - 7.09408 7.12724 7.11421 7.06531 6.98365 6.87460 - 6.74662 6.61206 6.48454 6.36784 6.26201 6.16585 - 6.07778 5.99548 5.91825 5.84403 5.77166 5.70443 - 5.64549 5.61676 5.58089 5.54784 5.52794 5.52601 - 5.54006 5.53769 5.52130 5.51752 5.51857 5.53893 - 7.73066 7.69763 7.61862 7.50722 7.36738 7.20517 - 7.02940 6.85243 6.68749 6.53809 6.40402 6.28304 - 6.17273 6.06997 5.97403 5.88301 5.79501 5.70957 - 5.62659 5.58564 5.54263 5.50677 5.47589 5.47473 - 5.48273 5.48032 5.46666 5.46281 5.46495 5.48207 - 8.21380 8.12166 7.98426 7.81788 7.62710 7.41863 - 7.20156 6.98828 6.79216 6.61619 6.45975 6.31971 - 6.19240 6.07399 5.96318 5.85742 5.75430 5.65353 - 5.55567 5.50806 5.45985 5.42125 5.38607 5.38131 - 5.38250 5.38064 5.37227 5.36997 5.37120 5.38126 - 8.56757 8.48993 8.30950 8.06680 7.79610 7.53057 - 7.27948 7.04846 6.84329 6.66053 6.49142 6.32983 - 6.17914 6.04180 5.91585 5.79684 5.68095 5.56897 - 5.46173 5.40972 5.35867 5.31941 5.28109 5.27183 - 5.26530 5.26424 5.26269 5.26236 5.26239 5.26342 - 9.13946 8.99211 8.72176 8.38400 8.02704 7.69460 - 7.39254 7.11921 6.87333 6.65196 6.44862 6.25854 - 6.08243 5.92160 5.77388 5.63560 5.50209 5.36752 - 5.23721 5.18185 5.12997 5.08945 5.04415 5.03137 - 5.01000 5.01008 5.02010 5.02295 5.02166 5.00780 - 9.71425 9.29651 8.88455 8.49622 8.13003 7.78524 - 7.46129 7.15765 6.87427 6.61216 6.37025 6.14710 - 5.94172 5.75475 5.58609 5.43550 5.29971 5.16393 - 5.01538 4.94147 4.87992 4.84326 4.79740 4.77777 - 4.75136 4.75244 4.76663 4.77046 4.76913 4.74920 - 10.38446 9.80472 9.24905 8.73447 8.25790 7.81664 - 7.40856 7.03276 6.68852 6.37430 6.08755 5.82498 - 5.58295 5.35969 5.15628 4.97125 4.80166 4.63507 - 4.46148 4.37642 4.30154 4.25166 4.19494 4.17699 - 4.15949 4.15910 4.16356 4.16486 4.16428 4.15682 - 10.76458 10.06374 9.40562 8.80339 8.25153 7.74622 - 7.28399 6.86242 6.48009 6.13350 5.81832 5.52973 - 5.26173 5.01068 4.77793 4.56303 4.36456 4.17698 - 3.99602 3.90842 3.82124 3.75241 3.68844 3.67834 - 3.67223 3.66920 3.66066 3.65845 3.65945 3.66951 - 11.23925 10.33278 9.51675 8.78931 8.13739 7.55274 - 7.02873 6.55679 6.13002 5.74330 5.39139 5.06881 - 4.76902 4.48746 4.22371 3.97692 3.74471 3.52724 - 3.32643 3.23207 3.13762 3.06250 2.99253 2.97795 - 2.96993 2.96761 2.96086 2.95912 2.95982 2.96675 - 11.54383 10.48784 9.56298 8.75002 8.03180 7.39573 - 6.83302 6.33194 5.88161 5.47506 5.10581 4.76674 - 4.44921 4.14755 3.86234 3.59532 3.34701 3.11450 - 2.89842 2.79777 2.70136 2.62803 2.55538 2.53706 - 2.52017 2.51877 2.51973 2.52012 2.51979 2.51676 - 11.75524 10.59489 9.59879 8.72987 7.96929 7.30081 - 6.71279 6.19123 5.72272 5.29930 4.91443 4.56092 - 4.23015 3.91649 3.62005 3.34202 3.08338 2.84106 - 2.61512 2.50968 2.40936 2.33372 2.25899 2.24027 - 2.22253 2.22117 2.22267 2.22320 2.22283 2.21908 - 11.91483 10.68066 9.63693 8.72974 7.94001 7.24949 - 6.64357 6.10663 5.62403 5.18737 4.79001 4.42491 - 4.08370 3.76084 3.45626 3.17080 2.90524 2.65650 - 2.42296 2.31303 2.20797 2.12872 2.05221 2.03355 - 2.01772 2.01611 2.01574 2.01583 2.01558 2.01417 - 12.14822 10.82101 9.72229 8.77059 7.94665 7.23059 - 6.60305 6.04616 5.54411 5.08842 4.67274 4.29036 - 3.93353 3.59705 3.28050 2.98414 2.70759 2.44759 - 2.20009 2.08182 1.96819 1.88234 1.80107 1.78167 - 1.76751 1.76554 1.76286 1.76243 1.76231 1.76360 - 12.31539 10.93688 9.81270 8.84052 8.00116 7.27296 - 6.63443 6.06633 5.55237 5.08436 4.65630 4.26181 - 3.89367 3.54692 3.22083 2.91511 2.62838 2.35618 - 2.09431 1.96776 1.84603 1.75383 1.66584 1.64455 - 1.62865 1.62656 1.62402 1.62362 1.62348 1.62428 - 12.57504 11.14720 10.00901 9.02514 8.17879 7.44091 - 6.79148 6.21145 5.68503 5.20412 4.76254 4.35362 - 3.96964 3.60538 3.26020 2.93387 2.62398 2.32258 - 2.02414 1.87554 1.72837 1.61318 1.50285 1.47548 - 1.45323 1.45070 1.44892 1.44872 1.44846 1.44800 - 12.71361 11.28054 10.15499 9.18036 8.34100 7.60443 - 6.95369 6.37191 5.84502 5.36441 4.92276 4.51194 - 4.12221 3.74734 3.38761 3.04434 2.71525 2.38922 - 2.05585 1.88437 1.70653 1.56127 1.42477 1.39177 - 1.36532 1.36202 1.35898 1.35856 1.35833 1.35934 - 12.84717 11.42074 10.33439 9.39949 8.59042 7.87654 - 7.24216 6.67147 6.15106 5.67324 5.23170 4.81928 - 4.42721 4.04876 3.68106 3.32021 2.95998 2.58901 - 2.19243 1.97819 1.74609 1.54433 1.34338 1.30093 - 1.27492 1.27069 1.26167 1.25970 1.26086 1.26689 - 12.82802 11.48252 10.47199 9.58828 8.80441 8.10022 - 7.46692 6.89575 6.37928 5.90992 5.47963 5.07896 - 4.69594 4.32135 3.95160 3.58177 3.20307 2.79838 - 2.34600 2.09378 1.81714 1.57235 1.30904 1.24731 - 1.22546 1.22269 1.20781 1.20391 1.20734 1.21598 - 12.83318 11.50965 10.54149 9.69427 8.93825 8.25643 - 7.64102 7.08411 6.57889 6.11835 5.69493 5.29956 - 4.92054 4.54846 4.17900 3.80588 3.41772 2.99203 - 2.49935 2.21617 1.89762 1.61115 1.29368 1.21648 - 1.19333 1.19102 1.17277 1.16782 1.17257 1.18130 - 12.82448 11.52062 10.59051 9.77384 9.04211 8.38000 - 7.78070 7.23687 6.74231 6.29048 5.87424 5.48491 - 5.11106 4.74320 4.37644 4.00331 3.61015 3.16960 - 2.64494 2.33586 1.98130 1.65712 1.28988 1.19765 - 1.17040 1.16825 1.14796 1.14239 1.14801 1.15559 - 12.78009 11.51567 10.65288 9.88740 9.19734 8.56907 - 7.99734 7.47595 6.99971 6.56308 6.15983 5.78225 - 5.41995 5.06367 4.70736 4.34114 3.94642 3.48499 - 2.90593 2.55212 2.13733 1.75314 1.31581 1.19553 - 1.12619 1.12512 1.12311 1.11862 1.10678 1.11979 - 12.74506 11.50860 10.69384 9.96493 9.30562 8.70325 - 8.15342 7.65070 7.19055 6.76804 6.37755 6.01199 - 5.66157 5.31726 4.97233 4.61556 4.22513 3.75546 - 3.14341 2.75775 2.29454 1.85516 1.34355 1.19778 - 1.10707 1.10414 1.10233 1.09773 1.08399 1.09598 - 12.76037 11.53814 10.77091 10.08311 9.46194 8.89642 - 8.38244 7.91494 7.48952 7.10124 6.74423 6.41064 - 6.08921 5.76983 5.44645 5.10904 4.73790 4.29031 - 3.68025 3.25490 2.68140 2.09579 1.40863 1.21814 - 1.10186 1.08741 1.06286 1.05852 1.05887 1.06130 - 12.71620 11.52552 10.80295 10.15282 9.56407 9.02738 - 8.53933 8.09556 7.69229 7.32517 6.98897 6.67651 - 6.37716 6.08115 5.78221 5.46941 5.12049 4.68577 - 4.06651 3.62099 3.00599 2.35122 1.51446 1.26536 - 1.09306 1.07213 1.04663 1.04231 1.04197 1.04259 - 12.61861 11.48300 10.82767 10.23344 9.69156 9.19518 - 8.74196 8.32886 7.95324 7.61212 7.30181 7.01716 - 6.75020 6.49298 6.23888 5.97491 5.67245 5.26379 - 4.62957 4.15946 3.50685 2.78268 1.74588 1.39936 - 1.09173 1.05371 1.03122 1.02737 1.01498 1.02284 - 12.61029 11.48736 10.85483 10.28115 9.75845 9.28113 - 8.84694 8.45315 8.09739 7.77695 7.48840 7.22679 - 6.98423 6.75306 6.52745 6.29554 6.02996 5.66330 - 5.06843 4.60621 3.93439 3.14801 1.93961 1.51481 - 1.11302 1.05678 1.01886 1.01478 1.00629 1.01248 - 12.59831 11.49558 10.88264 10.32341 9.81201 9.34407 - 8.91842 8.53368 8.18884 7.88160 7.60887 7.36597 - 7.14530 6.93853 6.73719 6.52372 6.27057 5.93005 - 5.39479 4.97184 4.32772 3.50929 2.11508 1.61239 - 1.12770 1.05949 1.01620 1.01289 1.00624 1.00612 - 12.58763 11.49850 10.89779 10.34889 9.84681 9.38776 - 8.97078 8.59480 8.25911 7.96182 7.70012 7.46981 - 7.26385 7.07443 6.89341 6.70326 6.47620 6.16398 - 5.65878 5.25174 4.62126 3.79333 2.29485 1.72146 - 1.14891 1.06649 1.01362 1.00974 1.00138 1.00183 - 12.59753 11.51420 10.91850 10.37738 9.88551 9.43931 - 9.03680 8.67600 8.35531 8.07285 7.82624 7.61171 - 7.42276 7.25341 7.10008 6.95351 6.78826 6.53423 - 6.06436 5.67571 5.08077 4.26904 2.62498 1.92839 - 1.19233 1.08494 1.01238 1.00516 0.99776 0.99641 - 12.58692 11.51942 10.93302 10.40015 9.91592 9.47724 - 9.08226 8.72929 8.41693 8.14362 7.90730 7.70471 - 7.52999 7.37790 7.24582 7.12574 6.99369 6.78036 - 6.36010 6.00126 5.43919 4.64062 2.90992 2.12534 - 1.23960 1.10637 1.01293 1.00386 0.99427 0.99309 - 12.55129 11.52258 10.95562 10.43773 9.96541 9.53660 - 9.15036 8.80602 8.50339 8.24164 8.01975 7.83594 - 7.68643 7.56715 7.47354 7.39225 7.29994 7.15143 - 6.84602 6.55814 6.05747 5.30352 3.51483 2.55488 - 1.35638 1.16691 1.01976 1.00411 0.99005 0.98861 - 12.54387 11.53606 10.96783 10.45105 9.98221 9.55887 - 9.17971 8.84354 8.54964 8.29694 8.08426 7.90958 - 7.76857 7.65811 7.57870 7.52705 7.48640 7.39747 - 7.14913 6.90044 6.46655 5.77242 3.96189 2.92713 - 1.47390 1.22997 1.02889 1.00732 0.98747 0.98637 - 12.45753 11.53363 10.97833 10.47130 10.00981 9.59233 - 9.21805 8.88660 8.59798 8.35180 8.14766 7.98454 - 7.85983 7.77103 7.71656 7.68770 7.66881 7.62815 - 7.49055 7.32392 6.98285 6.39153 4.65954 3.48706 - 1.69680 1.36590 1.05241 1.01125 0.98561 0.98410 - 12.39637 11.53726 10.98622 10.48157 10.02184 9.60631 - 9.23446 8.90604 8.62108 8.37924 8.18002 8.02244 - 7.90450 7.82438 7.78119 7.76739 7.77083 7.76966 - 7.69987 7.57815 7.28816 6.75365 5.15204 3.97225 - 1.89647 1.48222 1.07664 1.02524 0.98598 0.98296 - 12.35151 11.53838 10.98993 10.48711 10.02885 9.61499 - 9.24503 8.91862 8.63581 8.39640 8.20009 8.04608 - 7.93242 7.85754 7.82120 7.81710 7.83502 7.85621 - 7.82678 7.74012 7.50282 7.03009 5.52133 4.34842 - 2.08681 1.59908 1.10214 1.03563 0.98743 0.98228 - 12.32074 11.53911 10.99241 10.49075 10.03353 9.62082 - 9.25214 8.92718 8.64589 8.40818 8.21386 8.06229 - 7.95153 7.88022 7.84858 7.85121 7.87915 7.91604 - 7.91541 7.85461 7.65886 7.23781 5.81387 4.66071 - 2.26734 1.71097 1.12790 1.04641 0.98936 0.98182 - 12.28239 11.54015 10.99540 10.49524 10.03940 9.62823 - 9.26127 8.93818 8.65896 8.42355 8.23185 8.08337 - 7.97629 7.90960 7.88412 7.89543 7.93627 7.99375 - 8.03111 8.00532 7.87063 7.53120 6.25240 5.15310 - 2.60121 1.92065 1.17936 1.06891 0.99395 0.98124 - 12.25868 11.54081 10.99705 10.49782 10.04286 9.63269 - 9.26682 8.94494 8.66703 8.43309 8.24300 8.09638 - 7.99155 7.92772 7.90609 7.92272 7.97144 8.04183 - 8.10311 8.09979 8.00766 7.72951 6.56987 5.52887 - 2.89661 2.11290 1.23022 1.09256 0.99901 0.98089 - 12.22303 11.54178 10.99922 10.50117 10.04757 9.63876 - 9.27432 8.95398 8.67787 8.44592 8.25806 8.11397 - 8.01221 7.95240 7.93608 7.95992 8.01931 8.10771 - 8.20248 8.23087 8.20298 8.02604 7.08979 6.18096 - 3.50782 2.53826 1.35395 1.15491 1.01217 0.98044 - 12.20260 11.54210 11.00025 10.50289 10.05008 9.64194 - 9.27814 8.95851 8.68319 8.45221 8.26550 8.12276 - 8.02268 7.96498 7.95143 7.97898 8.04388 8.14197 - 8.25460 8.29953 8.30613 8.18959 7.41123 6.60686 - 3.98600 2.90283 1.47277 1.21924 1.02527 0.98020 - 12.18051 11.54231 11.00128 10.50472 10.05265 9.64519 - 9.28199 8.96297 8.68839 8.45833 8.27276 8.13143 - 8.03308 7.97754 7.96677 7.99812 8.06873 8.17692 - 8.30834 8.37037 8.41177 8.36257 7.79468 7.14086 - 4.69679 3.48921 1.69436 1.34675 1.05128 0.97998 - 12.19029 11.54911 11.00019 10.50048 10.04814 9.64189 - 9.28071 8.96400 8.69141 8.46282 8.27808 8.13642 - 8.03532 7.97474 7.96075 7.99984 8.09334 8.21801 - 8.34302 8.40296 8.45537 8.44623 8.02897 7.46226 - 5.19810 3.95118 1.89882 1.47118 1.07596 0.97987 - 12.18247 11.54894 11.00040 10.50102 10.04897 9.64295 - 9.28201 8.96550 8.69314 8.46478 8.28032 8.13898 - 8.03836 7.97842 7.96533 8.00571 8.10108 8.22865 - 8.35916 8.42483 8.48900 8.50252 8.17079 7.68527 - 5.58023 4.32079 2.10208 1.59085 1.10116 0.97980 - 12.17692 11.54879 11.00051 10.50135 10.04945 9.64359 - 9.28281 8.96645 8.69424 8.46607 8.28180 8.14072 - 8.04040 7.98090 7.96840 8.00962 8.10626 8.23581 - 8.37012 8.43962 8.51153 8.54043 8.27099 7.84627 - 5.88059 4.62980 2.29081 1.70839 1.12624 0.97976 - 12.14909 11.54214 11.00202 10.50649 10.05528 9.64882 - 9.28670 8.96883 8.69542 8.46654 8.28223 8.14232 - 8.04586 7.99290 7.98575 8.02224 8.10049 8.22084 - 8.37768 8.46450 8.54854 8.58923 8.40068 8.06268 - 6.32875 5.12205 2.62823 1.94249 1.17685 0.97970 - 12.14587 11.54220 11.00202 10.50650 10.05549 9.64915 - 9.28710 8.96928 8.69597 8.46726 8.28323 8.14373 - 8.04771 7.99517 7.98844 8.02533 8.10416 8.22612 - 8.38596 8.47539 8.56676 8.62102 8.48122 8.19803 - 6.64829 5.50379 2.92306 2.15071 1.22653 0.97966 - 1.11267 1.15656 1.20093 1.24589 1.29133 1.33710 - 1.38304 1.42905 1.47507 1.52102 1.56681 1.61268 - 1.65928 1.70683 1.75390 1.79739 1.83362 1.86085 - 1.88249 1.89558 1.91205 1.92776 1.94159 1.94472 - 1.94812 1.94847 1.94814 1.94798 1.94816 1.94889 - 1.51186 1.55782 1.60474 1.65306 1.70277 1.75379 - 1.80603 1.85935 1.91353 1.96832 2.02328 2.07784 - 2.13123 2.18248 2.23030 2.27323 2.31004 2.34165 - 2.36788 2.37700 2.38222 2.38676 2.41698 2.43332 - 2.42890 2.42527 2.42412 2.42435 2.42320 2.42774 - 1.85452 1.90518 1.95650 2.00909 2.06293 2.11792 - 2.17392 2.23075 2.28814 2.34577 2.40318 2.45968 - 2.51443 2.56635 2.61409 2.65612 2.69137 2.72139 - 2.74699 2.75655 2.76307 2.76930 2.80003 2.81540 - 2.80917 2.80553 2.80519 2.80563 2.80446 2.80809 - 2.40716 2.48042 2.55049 2.61800 2.68256 2.74388 - 2.80184 2.85666 2.90883 2.95842 3.00566 3.05113 - 3.09650 3.14289 3.18890 3.23133 3.26737 3.29896 - 3.32892 3.34338 3.35745 3.36823 3.37928 3.38177 - 3.38299 3.38342 3.38458 3.38488 3.38474 3.38351 - 2.86135 2.95768 3.04167 3.11532 3.18053 3.23981 - 3.29386 3.34357 3.39035 3.43468 3.47716 3.51806 - 3.55727 3.59470 3.63007 3.66350 3.69498 3.72402 - 3.75117 3.76501 3.77949 3.79140 3.80225 3.80336 - 3.80171 3.80254 3.80633 3.80739 3.80684 3.80215 - 3.24996 3.35577 3.44932 3.53139 3.60146 3.65980 - 3.70773 3.74828 3.78559 3.82068 3.85379 3.88528 - 3.91614 3.94707 3.97717 4.00457 4.02798 4.05003 - 4.07412 4.08737 4.10189 4.11395 4.12381 4.12533 - 4.12076 4.12163 4.12753 4.12888 4.12855 4.12130 - 3.58668 3.70299 3.80335 3.88865 3.95839 4.01300 - 4.05440 4.08659 4.11498 4.14094 4.16491 4.18744 - 4.20981 4.23290 4.25580 4.27635 4.29309 4.30930 - 4.32933 4.34145 4.35524 4.36685 4.37580 4.37695 - 4.37126 4.37221 4.37891 4.38044 4.38005 4.37177 - 4.15158 4.28001 4.38633 4.47185 4.53614 4.58012 - 4.60668 4.62143 4.63180 4.63977 4.64597 4.65135 - 4.65745 4.66546 4.67453 4.68219 4.68689 4.69250 - 4.70425 4.71315 4.72355 4.73228 4.73894 4.73965 - 4.73444 4.73525 4.74108 4.74240 4.74206 4.73483 - 4.61454 4.74632 4.85119 4.93109 4.98580 5.01672 - 5.02756 5.02518 5.01841 5.00966 4.99969 4.98969 - 4.98121 4.97559 4.97205 4.96819 4.96254 4.95897 - 4.96272 4.96775 4.97339 4.97774 4.98173 4.98227 - 4.97950 4.97993 4.98309 4.98381 4.98365 4.97974 - 5.49853 5.61822 5.70277 5.75611 5.77877 5.77340 - 5.74528 5.70338 5.65886 5.61459 5.57159 5.53084 - 5.49344 5.46029 5.43095 5.40349 5.37677 5.35416 - 5.33969 5.33486 5.32765 5.32002 5.31732 5.31765 - 5.32235 5.32173 5.31701 5.31591 5.31625 5.32219 - 6.13169 6.26152 6.31958 6.32238 6.28804 6.23667 - 6.17497 6.10854 6.04371 5.98026 5.91556 5.84892 - 5.78505 5.72770 5.67675 5.63012 5.58731 5.55402 - 5.52652 5.50747 5.48740 5.47302 5.46359 5.46308 - 5.47369 5.47225 5.46141 5.45848 5.45965 5.47324 - 7.07343 7.09980 7.08251 7.03167 6.95019 6.84308 - 6.71820 6.58709 6.46243 6.34787 6.24351 6.14831 - 6.06103 5.97973 5.90434 5.83388 5.76733 5.70423 - 5.64418 5.61455 5.58210 5.55378 5.53095 5.53280 - 5.54477 5.54237 5.52693 5.52255 5.52502 5.54466 - 7.86722 7.72079 7.56586 7.41348 7.26362 7.11630 - 6.97167 6.83003 6.69126 6.55630 6.42601 6.30031 - 6.18047 6.06689 5.96051 5.86261 5.77401 5.69302 - 5.62020 5.58988 5.56576 5.54622 5.48997 5.46839 - 5.48992 5.49303 5.47731 5.47189 5.47683 5.49272 - 8.33841 8.14094 7.93567 7.73553 7.54036 7.35022 - 7.16528 6.98579 6.81198 6.64480 6.48538 6.33359 - 6.19094 6.05837 5.93691 5.82799 5.73207 5.64501 - 5.56429 5.52867 5.49748 5.46979 5.40001 5.37354 - 5.39374 5.39848 5.38718 5.38297 5.38719 5.39596 - 8.58249 8.43896 8.25071 8.03613 7.80051 7.55135 - 7.29848 7.05473 6.83414 6.63936 6.46856 6.31729 - 6.17957 6.05022 5.92731 5.80809 5.69068 5.57784 - 5.47370 5.42503 5.37533 5.33517 5.29843 5.28963 - 5.28343 5.28242 5.28067 5.28033 5.28034 5.28162 - 9.11106 8.96715 8.70140 8.36851 8.01621 7.68783 - 7.38921 7.11882 6.87541 6.65623 6.45503 6.26714 - 6.09300 5.93372 5.78727 5.65024 5.51817 5.38523 - 5.25680 5.20256 5.15188 5.11229 5.06771 5.05507 - 5.03369 5.03379 5.04397 5.04684 5.04552 5.03152 - 9.57483 9.25420 8.90243 8.54229 8.17854 7.81781 - 7.46840 7.14074 6.84585 6.58550 6.35591 6.15171 - 5.96553 5.79234 5.62944 5.47247 5.31841 5.16926 - 5.03029 4.96791 4.91241 4.87231 4.82232 4.80704 - 4.77901 4.77967 4.79471 4.79835 4.79717 4.77674 - 10.33129 9.76772 9.22614 8.72332 8.25642 7.82300 - 7.42106 7.04990 6.70898 6.39692 6.11141 5.84949 - 5.60793 5.38524 5.18256 4.99846 4.83003 4.66473 - 4.49247 4.40804 4.33365 4.28407 4.22768 4.20972 - 4.19185 4.19148 4.19626 4.19763 4.19704 4.18917 - 10.72042 10.03510 9.39028 8.79902 8.25607 7.75789 - 7.30126 6.88390 6.50459 6.16001 5.84605 5.55816 - 5.29067 5.04019 4.80806 4.59388 4.39623 4.20950 - 4.02930 3.94199 3.85497 3.78614 3.72201 3.71186 - 3.70580 3.70278 3.69426 3.69205 3.69305 3.70306 - 11.21927 10.32416 9.51741 8.79715 8.15079 7.57043 - 7.04963 6.58019 6.15534 5.77015 5.41947 5.09793 - 4.79912 4.51851 4.25564 4.00959 3.77790 3.56065 - 3.35965 3.26500 3.17016 3.09466 3.02453 3.01000 - 3.00206 2.99973 2.99290 2.99113 2.99184 2.99887 - 11.54212 10.49258 9.57278 8.76370 8.04852 7.41488 - 6.85409 6.35458 5.90567 5.50042 5.13239 4.79446 - 4.47798 4.17727 3.89281 3.62632 3.37825 3.14578 - 2.92953 2.82865 2.73178 2.65796 2.58514 2.56680 - 2.54988 2.54848 2.54944 2.54982 2.54949 2.54647 - 11.76319 10.60645 9.61292 8.74594 7.98685 7.31960 - 6.73266 6.21212 5.74474 5.32255 4.93892 4.58662 - 4.25691 3.94401 3.64812 3.37045 3.11204 2.86985 - 2.64393 2.53838 2.43771 2.36163 2.28667 2.26791 - 2.25010 2.24873 2.25025 2.25078 2.25041 2.24666 - 11.92611 10.69441 9.65209 8.74593 7.95697 7.26714 - 6.66188 6.12571 5.64409 5.20855 4.81242 4.44854 - 4.10833 3.78614 3.48199 3.19683 2.93153 2.68304 - 2.44973 2.33983 2.23456 2.15492 2.07814 2.05942 - 2.04350 2.04188 2.04151 2.04160 2.04135 2.03997 - 12.15435 10.83056 9.73372 8.78339 7.96044 7.24512 - 6.61827 6.06212 5.56099 5.10639 4.69185 4.31056 - 3.95462 3.61873 3.30255 3.00649 2.73026 2.47071 - 2.22378 2.10575 1.99209 1.90595 1.82430 1.80479 - 1.79051 1.78853 1.78583 1.78540 1.78528 1.78659 - 12.30927 10.93743 9.81716 8.84797 8.01077 7.28415 - 6.64686 6.07985 5.56694 5.10000 4.67295 4.27943 - 3.91207 3.56594 3.24030 2.93497 2.64864 2.37698 - 2.11585 1.98965 1.86801 1.77559 1.68711 1.66566 - 1.64962 1.64751 1.64495 1.64455 1.64441 1.64519 - 12.54807 11.13146 10.00040 9.02207 8.17980 7.44502 - 6.79791 6.21966 5.69464 5.21483 4.77417 4.36607 - 3.98294 3.61960 3.27531 2.94968 2.64032 2.33956 - 2.04203 1.89390 1.74699 1.63172 1.52080 1.49321 - 1.47077 1.46822 1.46643 1.46623 1.46597 1.46546 - 12.68545 11.26218 10.14247 9.17265 8.33702 7.60349 - 6.95522 6.37540 5.85001 5.37054 4.92987 4.52000 - 4.13141 3.75793 3.39960 3.05740 2.72894 2.40355 - 2.07113 1.90014 1.72266 1.57744 1.44045 1.40727 - 1.38069 1.37736 1.37428 1.37385 1.37362 1.37469 - 12.83700 11.41252 10.32564 9.39067 8.58201 7.86903 - 7.23590 6.66668 6.14776 5.67146 5.23151 4.82075 - 4.43046 4.05384 3.68798 3.32876 2.96982 2.59988 - 2.20409 1.99015 1.75832 1.55673 1.35588 1.31351 - 1.28766 1.28340 1.27417 1.27212 1.27327 1.27976 - 12.83571 11.48680 10.47045 9.58225 8.79525 8.08930 - 7.45534 6.88450 6.36916 5.90156 5.47352 5.07536 - 4.69488 4.32262 3.95502 3.58710 3.21007 2.80670 - 2.35517 2.10319 1.82672 1.58208 1.31940 1.25811 - 1.23677 1.23396 1.21871 1.21467 1.21806 1.22749 - 12.85315 11.52205 10.54432 9.68966 8.92829 8.24306 - 7.62591 7.06866 6.56429 6.10555 5.68465 5.29224 - 4.91620 4.54685 4.17985 3.80892 3.42262 2.99836 - 2.50658 2.22367 1.90539 1.61921 1.30277 1.22621 - 1.20382 1.20148 1.18278 1.17767 1.18236 1.19201 - 12.85160 11.53790 10.59593 9.76993 9.03140 8.36482 - 7.76303 7.21842 6.72450 6.27446 5.86092 5.47481 - 5.10422 4.73936 4.37528 4.00451 3.61335 3.17433 - 2.65065 2.34193 1.98775 1.66403 1.29815 1.20670 - 1.18038 1.17822 1.15746 1.15172 1.15724 1.16581 - 12.81301 11.53698 10.66004 9.88343 9.18515 8.55131 - 7.97630 7.45360 6.97775 6.54289 6.14247 5.76837 - 5.40963 5.05657 4.70311 4.33940 3.94680 3.48708 - 2.90929 2.55607 2.14207 1.75875 1.32316 1.20374 - 1.13546 1.13448 1.13215 1.12749 1.11550 1.12944 - 12.77741 11.52955 10.70010 9.95977 9.29190 8.68364 - 8.13029 7.62607 7.16617 6.74536 6.35770 5.99565 - 5.64885 5.30781 4.96581 4.61160 4.22335 3.75552 - 3.14503 2.76016 2.29802 1.85985 1.35036 1.20555 - 1.11603 1.11323 1.11117 1.10640 1.09249 1.10534 - 12.78104 11.55044 10.77042 10.07261 9.44395 8.87327 - 8.35620 7.88740 7.46225 7.07558 6.72120 6.39093 - 6.07291 5.75665 5.43610 5.10122 4.73232 4.28685 - 3.67889 3.25468 2.68257 2.09858 1.41461 1.22547 - 1.11068 1.09629 1.07147 1.06709 1.06710 1.07035 - 12.72112 11.52665 10.79449 10.13690 9.54256 9.00211 - 8.51185 8.06729 7.66444 7.29879 6.96489 6.65526 - 6.35884 6.06552 5.76903 5.45850 5.11177 4.67938 - 4.06292 3.61902 3.00587 2.35312 1.51999 1.27229 - 1.10174 1.08094 1.05523 1.05089 1.05024 1.05154 - 12.59884 11.46668 10.80725 10.20982 9.66557 9.16770 - 8.71379 8.30068 7.92569 7.58573 7.27704 6.99430 - 6.72936 6.47411 6.22192 5.95992 5.65956 5.25337 - 4.62236 4.15441 3.50465 2.78358 1.75113 1.40589 - 1.09995 1.06229 1.04000 1.03606 1.02334 1.03167 - 12.57712 11.46137 10.82757 10.25290 9.72972 9.25221 - 8.81822 8.42494 8.06998 7.75057 7.46329 7.20310 - 6.96201 6.73234 6.50827 6.27803 6.01437 5.65015 - 5.05869 4.59887 3.93027 3.14747 1.94427 1.52101 - 1.12110 1.06527 1.02764 1.02348 1.01466 1.02120 - 12.56675 11.46242 10.84375 10.28251 9.77229 9.30780 - 8.88697 8.50720 8.16633 7.86175 7.59023 7.34690 - 7.12384 6.91360 6.71121 6.50608 6.27272 5.94610 - 5.39691 4.95319 4.28294 3.46223 2.12472 1.63194 - 1.14611 1.07310 1.01974 1.01499 1.00998 1.01476 - 12.54213 11.46327 10.86380 10.31616 9.81519 9.35726 - 8.94138 8.56648 8.23183 7.93550 7.67474 7.44533 - 7.24023 7.05165 6.87154 6.68247 6.45692 6.14701 - 5.64561 5.24135 4.61447 3.79032 2.29757 1.72664 - 1.15700 1.07498 1.02221 1.01828 1.00990 1.01040 - 12.54712 11.47530 10.88198 10.34291 9.85282 9.40821 - 9.00708 8.64753 8.32787 8.04631 7.80045 7.58660 - 7.39827 7.22955 7.07689 6.93115 6.76706 6.51495 - 6.04849 5.66253 5.07144 4.26410 2.62650 1.93260 - 1.20019 1.09329 1.02094 1.01367 1.00626 1.00491 - 12.53469 11.47914 10.89548 10.36495 9.88274 9.44584 - 9.05237 8.70070 8.38938 8.11692 7.88129 7.67924 - 7.50500 7.35338 7.22181 7.10237 6.97122 6.75948 - 6.34225 5.98596 5.42778 4.63386 2.91032 2.12886 - 1.24719 1.11452 1.02146 1.01235 1.00277 1.00158 - 12.49897 11.48213 10.91807 10.40249 9.93217 9.50504 - 9.12016 8.77695 8.47531 8.21436 7.99312 7.80984 - 7.66078 7.54183 7.44857 7.36765 7.27593 7.12837 - 6.82498 6.53910 6.04204 5.29306 3.51302 2.55673 - 1.36329 1.17465 1.02826 1.01256 0.99854 0.99713 - 12.49341 11.49634 10.93048 10.41589 9.94888 9.52717 - 9.14941 8.81443 8.52152 8.26960 8.05756 7.88333 - 7.74267 7.63249 7.55327 7.50179 7.46136 7.37298 - 7.12619 6.87924 6.44859 5.75918 3.95788 2.92776 - 1.48027 1.23728 1.03731 1.01582 0.99595 0.99492 - 12.41001 11.49503 10.94177 10.43662 9.97681 9.56077 - 9.18775 8.85737 8.56968 8.32427 8.12073 7.95808 - 7.83368 7.74512 7.69074 7.66189 7.64302 7.60253 - 7.46568 7.30018 6.96155 6.37438 4.65238 3.48529 - 1.70219 1.37258 1.06073 1.01982 0.99398 0.99265 - 12.35067 11.49936 10.95036 10.44728 9.98894 9.57479 - 9.20424 8.87695 8.59289 8.35173 8.15304 7.99589 - 7.87827 7.79833 7.75520 7.74134 7.74467 7.74346 - 7.67411 7.55313 7.26488 6.73389 5.14274 3.96842 - 1.90078 1.48835 1.08488 1.03377 0.99439 0.99149 - 12.30679 11.50079 10.95437 10.45302 9.99603 9.58350 - 9.21485 8.88961 8.60769 8.36890 8.17307 8.01951 - 7.90616 7.83144 7.79513 7.79095 7.80867 7.82969 - 7.80043 7.71431 7.47834 7.00856 5.50992 4.34289 - 2.09034 1.60474 1.11026 1.04414 0.99582 0.99079 - 12.27672 11.50173 10.95694 10.45675 10.00074 9.58935 - 9.22201 8.89819 8.61777 8.38066 8.18682 8.03568 - 7.92525 7.85408 7.82248 7.82498 7.85271 7.88934 - 7.88869 7.82826 7.63354 7.21502 5.80066 4.65361 - 2.27009 1.71620 1.13591 1.05487 0.99773 0.99032 - 12.23935 11.50277 10.96003 10.46124 10.00666 9.59677 - 9.23106 8.90909 8.63074 8.39597 8.20479 8.05672 - 7.94995 7.88342 7.85794 7.86910 7.90970 7.96682 - 8.00395 7.97832 7.84426 7.50668 6.23637 5.14333 - 2.60255 1.92517 1.18713 1.07723 1.00230 0.98973 - 12.21603 11.50334 10.96158 10.46382 10.01015 9.60123 - 9.23654 8.91572 8.63869 8.40545 8.21593 8.06974 - 7.96519 7.90152 7.87987 7.89636 7.94483 8.01483 - 8.07574 8.07243 7.98065 7.70394 6.55171 5.51689 - 2.89672 2.11676 1.23774 1.10073 1.00736 0.98938 - 12.18112 11.50412 10.96345 10.46706 10.01482 9.60726 - 9.24390 8.92458 8.64936 8.41820 8.23097 8.08730 - 7.98583 7.92613 7.90981 7.93351 7.99261 8.08062 - 8.17486 8.20305 8.17518 7.99898 7.06821 6.16523 - 3.50554 2.54060 1.36088 1.16266 1.02052 0.98892 - 12.16121 11.50444 10.96448 10.46868 10.01724 9.61036 - 9.24770 8.92909 8.65468 8.42446 8.23837 8.09607 - 7.99628 7.93869 7.92512 7.95253 8.01718 8.11485 - 8.22692 8.27160 8.27803 8.16177 7.38768 6.58895 - 3.98190 2.90369 1.47915 1.22658 1.03366 0.98869 - 12.13958 11.50465 10.96551 10.47050 10.01973 9.61355 - 9.25157 8.93365 8.65998 8.43063 8.24562 8.10471 - 8.00666 7.95125 7.94044 7.97164 8.04201 8.14974 - 8.28059 8.34233 8.38342 8.33412 7.76910 7.12021 - 4.68988 3.48757 1.69969 1.35335 1.05970 0.98847 - 12.14970 11.51135 10.96422 10.46617 10.01532 9.61040 - 9.25041 8.93470 8.66299 8.43513 8.25096 8.10971 - 8.00890 7.94848 7.93448 7.97339 8.06653 8.19074 - 8.31525 8.37492 8.42690 8.41749 8.00201 7.43896 - 5.18877 3.94742 1.90332 1.47717 1.08433 0.98836 - 12.14182 11.51109 10.96443 10.46671 10.01615 9.61147 - 9.25171 8.93623 8.66472 8.43707 8.25317 8.11225 - 8.01191 7.95212 7.93903 7.97923 8.07427 8.20133 - 8.33128 8.39667 8.46059 8.47390 8.14275 7.66003 - 5.56877 4.31519 2.10554 1.59633 1.10947 0.98829 - 12.13637 11.51095 10.96454 10.46703 10.01663 9.61214 - 9.25254 8.93721 8.66585 8.43839 8.25467 8.11401 - 8.01395 7.95459 7.94209 7.98314 8.07944 8.20848 - 8.34219 8.41142 8.48315 8.51185 8.24207 7.81947 - 5.86730 4.62255 2.29330 1.71348 1.13443 0.98824 - 12.10849 11.50409 10.96604 10.47217 10.02247 9.61731 - 9.25631 8.93942 8.66689 8.43878 8.25507 8.11558 - 8.01938 7.96654 7.95940 7.99575 8.07369 8.19362 - 8.34984 8.43628 8.51993 8.56044 8.37187 8.03470 - 6.31264 5.11205 2.62906 1.94633 1.18475 0.98818 - 12.10514 11.50375 10.96565 10.47198 10.02270 9.61764 - 9.25659 8.93964 8.66722 8.43941 8.25608 8.11703 - 8.02125 7.96884 7.96210 7.99885 8.07736 8.19887 - 8.35814 8.44723 8.53825 8.59206 8.45268 8.17199 - 6.63050 5.49146 2.92255 2.15368 1.23411 0.98815 - 1.08606 1.12816 1.17087 1.21436 1.25851 1.30322 - 1.34836 1.39381 1.43952 1.48542 1.53151 1.57807 - 1.62581 1.67490 1.72344 1.76725 1.80225 1.82961 - 1.85180 1.86254 1.87814 1.89474 1.90621 1.90888 - 1.91227 1.91250 1.91204 1.91196 1.91196 1.91284 - 1.45784 1.50788 1.55856 1.61020 1.66269 1.71585 - 1.76948 1.82333 1.87712 1.93061 1.98346 2.03546 - 2.08664 2.13678 2.18494 2.22990 2.27035 2.30604 - 2.33582 2.34756 2.35796 2.36596 2.37833 2.38361 - 2.38861 2.38831 2.38585 2.38516 2.38535 2.38899 - 1.78717 1.84509 1.90304 1.96152 2.02030 2.07910 - 2.13761 2.19549 2.25236 2.30793 2.36192 2.41424 - 2.46529 2.51523 2.56323 2.60816 2.64890 2.68538 - 2.71667 2.72937 2.74053 2.74861 2.75954 2.76386 - 2.76856 2.76848 2.76657 2.76602 2.76621 2.76896 - 2.34613 2.42274 2.49567 2.56550 2.63186 2.69457 - 2.75367 2.80978 2.86385 2.91599 2.96616 3.01451 - 3.06189 3.10877 3.15411 3.19601 3.23274 3.26525 - 3.29438 3.30748 3.32077 3.33167 3.34238 3.34493 - 3.34586 3.34625 3.34758 3.34786 3.34782 3.34641 - 2.80859 2.90316 2.98908 3.06699 3.13645 3.19759 - 3.25134 3.29991 3.34641 3.39147 3.43516 3.47742 - 3.51869 3.55910 3.59772 3.63292 3.66350 3.69125 - 3.71829 3.73168 3.74588 3.75763 3.76814 3.77015 - 3.76780 3.76850 3.77263 3.77355 3.77333 3.76836 - 3.20343 3.31237 3.40794 3.49085 3.56064 3.61782 - 3.66416 3.70342 3.74066 3.77703 3.81262 3.84733 - 3.88125 3.91428 3.94556 3.97363 3.99759 4.01993 - 4.04385 4.05686 4.07126 4.08339 4.09342 4.09499 - 4.09048 4.09137 4.09728 4.09862 4.09829 4.09104 - 3.54698 3.66664 3.76874 3.85409 3.92235 3.97431 - 4.01254 4.04211 4.06968 4.09686 4.12377 4.15032 - 4.17639 4.20180 4.22574 4.24682 4.26433 4.28126 - 4.30162 4.31374 4.32758 4.33937 4.34868 4.34994 - 4.34437 4.34532 4.35201 4.35354 4.35315 4.34489 - 4.12025 4.25153 4.35878 4.44330 4.50486 4.54488 - 4.56708 4.57829 4.58739 4.59658 4.60611 4.61606 - 4.62634 4.63682 4.64688 4.65515 4.66111 4.66819 - 4.68104 4.69032 4.70112 4.71025 4.71758 4.71850 - 4.71344 4.71425 4.72009 4.72143 4.72109 4.71387 - 4.58553 4.71892 4.82390 4.90239 4.95440 4.98177 - 4.98890 4.98367 4.97611 4.96876 4.96202 4.95631 - 4.95174 4.94852 4.94614 4.94326 4.93933 4.93780 - 4.94321 4.94892 4.95522 4.96016 4.96508 4.96587 - 4.96326 4.96373 4.96694 4.96767 4.96750 4.96356 - 5.46435 5.58203 5.66510 5.71744 5.73966 5.73438 - 5.70692 5.66620 5.62332 5.58108 5.54044 5.50218 - 5.46710 5.43591 5.40834 5.38288 5.35876 5.33897 - 5.32706 5.32336 5.31726 5.31056 5.30910 5.30976 - 5.31466 5.31407 5.30943 5.30834 5.30867 5.31456 - 6.09401 6.20824 6.26253 6.27015 6.24393 6.19867 - 6.14067 6.07643 6.01339 5.95165 5.88864 5.82375 - 5.76177 5.70652 5.65785 5.61365 5.57337 5.54296 - 5.51863 5.50102 5.48231 5.46900 5.46084 5.46064 - 5.47153 5.47014 5.45929 5.45634 5.45754 5.47116 - 7.00592 7.04856 7.03350 6.97639 6.88843 6.78253 - 6.66632 6.54874 6.43903 6.33729 6.23888 6.14142 - 6.04960 5.96632 5.89091 5.82006 5.75289 5.69808 - 5.64983 5.61677 5.58143 5.55525 5.53697 5.53510 - 5.55044 5.54815 5.53148 5.52698 5.52878 5.54955 - 7.64195 7.62805 7.55037 7.42989 7.28144 7.12103 - 6.95682 6.79755 6.65193 6.51937 6.39445 6.27351 - 6.16030 6.05680 5.96189 5.87190 5.78539 5.71017 - 5.64130 5.59916 5.55501 5.52175 5.49580 5.49175 - 5.50371 5.50139 5.48615 5.48206 5.48368 5.50243 - 8.12229 8.06684 7.93514 7.75568 7.55032 7.34126 - 7.13659 6.94327 6.76825 6.61010 6.46311 6.32287 - 6.19215 6.07232 5.96200 5.85741 5.75633 5.66364 - 5.57687 5.52984 5.48202 5.44555 5.41363 5.40718 - 5.41118 5.40937 5.39989 5.39737 5.39831 5.40960 - 8.50332 8.41735 8.23885 8.00518 7.74714 7.49454 - 7.25510 7.03310 6.83305 6.65286 6.48657 6.32947 - 6.18344 6.04967 5.92647 5.81013 5.69755 5.58975 - 5.48747 5.43798 5.38934 5.35182 5.31513 5.30632 - 5.30049 5.29941 5.29756 5.29715 5.29722 5.29867 - 9.07835 8.94145 8.68223 8.35481 8.00688 7.68180 - 7.38582 7.11779 6.87694 6.66036 6.46146 6.27545 - 6.10300 5.94540 5.80055 5.66483 5.53373 5.40198 - 5.27548 5.22242 5.17286 5.13402 5.09002 5.07750 - 5.05613 5.05626 5.06650 5.06941 5.06809 5.05396 - 9.49848 9.30871 8.97879 8.57503 8.15677 7.77562 - 7.43581 7.13213 6.85934 6.61365 6.38806 6.17773 - 5.98291 5.80478 5.64147 5.48908 5.34244 5.19350 - 5.05024 4.99253 4.93946 4.89766 4.84822 4.83359 - 4.80545 4.80598 4.82108 4.82534 4.82345 4.80300 - 10.36073 9.79485 9.25161 8.74738 8.27934 7.84501 - 7.44244 7.07090 6.72984 6.41788 6.13273 5.87146 - 5.63084 5.40940 5.20825 5.02596 4.85939 4.69538 - 4.52316 4.43847 4.36432 4.31545 4.25946 4.24131 - 4.22326 4.22297 4.22797 4.22939 4.22880 4.22061 - 10.74949 10.06271 9.41700 8.82499 8.28149 7.78296 - 7.32616 6.90882 6.52967 6.18541 5.87193 5.58469 - 5.31798 5.06838 4.83725 4.62416 4.42771 4.24203 - 4.06249 3.97532 3.88829 3.81932 3.75512 3.74500 - 3.73890 3.73588 3.72736 3.72516 3.72614 3.73619 - 11.21444 10.33247 9.53430 8.81897 8.17488 7.59496 - 7.07362 6.60356 6.17888 5.79467 5.44554 5.12585 - 4.82873 4.54934 4.28722 4.04155 3.80996 3.59284 - 3.39221 3.29784 3.20317 3.12762 3.05698 3.04225 - 3.03425 3.03190 3.02498 3.02319 3.02391 3.03110 - 11.52488 10.48475 9.57272 8.77007 8.06021 7.43097 - 6.87371 6.37698 5.93016 5.52643 5.15947 4.82233 - 4.50647 4.20627 3.92225 3.65610 3.40830 3.17610 - 2.96020 2.85952 2.76279 2.68890 2.61545 2.59688 - 2.57978 2.57836 2.57930 2.57969 2.57936 2.57633 - 11.73853 10.58797 9.60127 8.74157 7.98983 7.32961 - 6.74889 6.23324 5.76898 5.34835 4.96521 4.61280 - 4.28302 3.97045 3.67518 3.39812 3.14013 2.89821 - 2.67248 2.56703 2.46647 2.39037 2.31478 2.29579 - 2.27780 2.27641 2.27792 2.27846 2.27808 2.27421 - 11.89770 10.67054 9.63437 8.73586 7.95517 7.27355 - 6.67570 6.14533 5.66721 5.23319 4.83721 4.47278 - 4.13220 3.81030 3.50689 3.22256 2.95781 2.70961 - 2.47638 2.36650 2.26129 2.18165 2.10431 2.08538 - 2.06932 2.06768 2.06729 2.06739 2.06713 2.06559 - 12.12163 10.80060 9.71294 8.77482 7.96304 7.25524 - 6.63305 6.08014 5.58179 5.12872 4.71306 4.32864 - 3.97117 3.63726 3.32480 3.03107 2.75424 2.49384 - 2.24736 2.12939 2.01572 1.92947 1.84733 1.82798 - 1.81357 1.81133 1.80878 1.80831 1.80831 1.80948 - 12.27865 10.91610 9.80657 8.84814 8.01917 7.29678 - 6.66112 6.09509 5.58389 5.11833 4.69058 4.29452 - 3.92616 3.58222 3.26027 2.95719 2.67027 2.39768 - 2.13704 2.01116 1.88949 1.79673 1.70800 1.68679 - 1.67066 1.66829 1.66590 1.66549 1.66542 1.66628 - 12.52676 11.12677 10.00459 9.03094 8.19031 7.45529 - 6.80709 6.22785 5.70277 5.22377 4.78451 4.37807 - 3.99642 3.63413 3.29058 2.96557 2.65682 2.35666 - 2.05963 1.91167 1.76480 1.64946 1.53846 1.51082 - 1.48835 1.48581 1.48401 1.48381 1.48355 1.48318 - 12.65959 11.24977 10.13730 9.17185 8.33839 7.60579 - 6.95780 6.37827 5.85368 5.37551 4.93644 4.52831 - 4.14129 3.76905 3.41167 3.07015 2.74223 2.41756 - 2.08622 1.91575 1.73855 1.59329 1.45605 1.42277 - 1.39609 1.39275 1.38964 1.38923 1.38899 1.38971 - 12.78929 11.37007 10.28739 9.35809 8.55600 7.85006 - 7.22379 6.66053 6.14603 5.67273 5.23467 4.82503 - 4.43555 4.05971 3.69462 3.33625 2.97836 2.60981 - 2.21586 2.00288 1.77178 1.57048 1.36930 1.32665 - 1.30038 1.29610 1.28707 1.28512 1.28622 1.29112 - 12.83221 11.42216 10.37613 9.48438 8.71225 8.03230 - 7.42822 6.88339 6.38329 5.92069 5.49004 5.08482 - 4.69682 4.31946 3.94961 3.58272 3.21033 2.81525 - 2.37284 2.12184 1.83862 1.58497 1.32803 1.27494 - 1.24895 1.24421 1.23012 1.22682 1.22928 1.23679 - 12.83914 11.44462 10.43577 9.57740 8.83184 8.17448 - 7.58963 7.06089 6.57377 6.12139 5.69859 5.29917 - 4.91518 4.53997 4.17006 3.80017 3.41981 3.00648 - 2.52664 2.24452 1.91621 1.61717 1.30868 1.24396 - 1.21547 1.21045 1.19328 1.18916 1.19255 1.20024 - 12.82976 11.45304 10.47978 9.64997 8.92757 8.28953 - 7.72097 7.20595 6.73025 6.28731 5.87230 5.47930 - 5.10058 4.72952 4.36219 3.99250 3.60809 3.18201 - 2.67267 2.36465 1.99779 1.65817 1.30193 1.22501 - 1.19170 1.18635 1.16731 1.16270 1.16669 1.17345 - 12.79369 11.45283 10.54143 9.75811 9.07354 8.46662 - 7.92416 7.43129 6.97469 6.54833 6.14790 5.76803 - 5.40141 5.04144 4.68336 4.31954 3.93421 3.49288 - 2.93973 2.59026 2.15956 1.75093 1.31370 1.21196 - 1.15563 1.14928 1.13436 1.13076 1.13332 1.13660 - 12.75264 11.44563 10.58388 9.83690 9.18144 8.59814 - 8.07532 7.59940 7.15815 6.74602 6.35899 5.99194 - 5.63781 5.28987 4.94276 4.58747 4.20582 3.75823 - 3.17759 2.79841 2.31812 1.85072 1.33703 1.21202 - 1.13616 1.12784 1.11262 1.10906 1.11081 1.11237 - 12.66210 11.42996 10.65455 9.97100 9.36354 8.81769 - 8.32551 7.87739 7.46460 7.08217 6.72572 6.38937 - 6.06462 5.74328 5.41877 5.07988 4.70785 4.26695 - 3.67621 3.26240 2.69501 2.10443 1.41466 1.23943 - 1.11831 1.10235 1.07963 1.07514 1.07703 1.07743 - 12.60555 11.42059 10.69724 10.05362 9.47663 8.95505 - 8.48301 8.05328 7.65926 7.29671 6.96146 6.64783 - 6.34733 6.05143 5.75269 5.43777 5.08515 4.65534 - 4.05767 3.62556 3.01706 2.35597 1.51809 1.28673 - 1.10944 1.08658 1.06299 1.05900 1.05947 1.05877 - 12.51030 11.39795 10.74842 10.15931 9.62206 9.13004 - 8.68095 8.27174 7.89982 7.56222 7.25530 6.97389 - 6.71010 6.45599 6.20503 5.94444 5.64586 5.24224 - 4.61516 4.14986 3.50330 2.78531 1.75648 1.41214 - 1.10737 1.06998 1.04796 1.04399 1.03108 1.03920 - 12.51388 11.41327 10.78469 10.21388 9.69361 9.21829 - 8.78590 8.39396 8.04028 7.72220 7.43636 7.17785 - 6.93886 6.71112 6.48682 6.25023 5.97558 5.61514 - 5.05900 4.62188 3.96164 3.16206 1.93044 1.51826 - 1.12706 1.07239 1.03703 1.03379 1.02610 1.02895 - 12.50530 11.42004 10.80835 10.25119 9.74288 9.27889 - 8.85761 8.47713 8.13580 7.83100 7.55926 7.31645 - 7.09717 6.89452 6.69882 6.48960 6.23756 5.89868 - 5.36863 4.95061 4.31705 3.50967 2.12187 1.62109 - 1.14377 1.07740 1.03284 1.02890 1.02151 1.02267 - 12.49365 11.42530 10.82686 10.27970 9.77963 9.32350 - 8.91000 8.53760 8.20500 7.90998 7.64949 7.41967 - 7.21506 7.02889 6.85224 6.66567 6.44026 6.13018 - 5.63091 5.22948 4.60810 3.78870 2.29746 1.72787 - 1.16741 1.08686 1.02958 1.02415 1.01548 1.01843 - 12.50183 11.44015 10.84832 10.31060 9.82174 9.37826 - 8.97818 8.61960 8.30085 8.02013 7.77505 7.56190 - 7.37426 7.20617 7.05418 6.90921 6.74617 6.49585 - 6.03264 5.64931 5.06202 4.25908 2.62789 1.93657 - 1.20763 1.10119 1.02896 1.02161 1.01426 1.01307 - 12.49238 11.44621 10.86350 10.33381 9.85246 9.41635 - 9.02370 8.67277 8.36221 8.09046 7.85550 7.65410 - 7.48045 7.32939 7.19837 7.07954 6.94923 6.73890 - 6.32443 5.97058 5.41628 4.62709 2.91063 2.13218 - 1.25445 1.12232 1.02955 1.02036 1.01085 1.00980 - 12.45513 11.45143 10.88877 10.37270 9.90125 9.47364 - 9.08907 8.74694 8.44700 8.18800 7.96833 7.78584 - 7.63701 7.51791 7.42406 7.34213 7.24984 7.10573 - 6.80772 6.52114 6.02332 5.28028 3.51901 2.55303 - 1.36844 1.18452 1.03637 1.02120 1.00554 1.00540 - 12.45032 11.46215 10.89756 10.38408 9.91815 9.49739 - 9.12051 8.78632 8.49413 8.24284 8.03133 7.85757 - 7.71728 7.60739 7.52842 7.47714 7.43691 7.34896 - 7.10346 6.85810 6.43070 5.74604 3.95388 2.92831 - 1.48650 1.24443 1.04552 1.02409 1.00421 1.00320 - 12.36630 11.46096 10.90965 10.40517 9.94548 9.52955 - 9.15689 8.82737 8.54121 8.29747 8.09473 7.93161 - 7.80633 7.71737 7.66368 7.63760 7.62356 7.58529 - 7.43718 7.26328 6.93920 6.38706 4.65128 3.44473 - 1.71393 1.39181 1.06601 1.02116 1.00598 1.00096 - 12.30692 11.46290 10.91573 10.41422 9.95725 9.54425 - 9.17470 8.84831 8.56511 8.32476 8.12668 7.96999 - 7.85266 7.77293 7.72989 7.71600 7.71915 7.71783 - 7.64879 7.52845 7.24181 6.71425 5.13342 3.96461 - 1.90509 1.49444 1.09303 1.04221 1.00267 0.99984 - 12.26489 11.46364 10.91854 10.41905 9.96388 9.55270 - 9.18509 8.86097 8.58049 8.34308 8.14773 7.99351 - 7.87936 7.80451 7.76876 7.76563 7.78493 7.80844 - 7.77302 7.67701 7.44615 7.01436 5.52874 4.28801 - 2.09295 1.62403 1.11884 1.04340 1.00990 0.99917 - 12.23561 11.46428 10.92080 10.42248 9.96847 9.55851 - 9.19221 8.86952 8.59056 8.35483 8.16142 8.00956 - 7.89835 7.82726 7.79637 7.79965 7.82809 7.86718 - 7.86265 7.79294 7.59908 7.21322 5.82321 4.60232 - 2.26816 1.73319 1.14476 1.05474 1.01293 0.99872 - 12.19817 11.46544 10.92409 10.42716 9.97444 9.56606 - 9.20154 8.88053 8.60298 8.36890 8.17828 8.03067 - 7.92419 7.85784 7.83241 7.84346 7.88384 7.94063 - 7.97749 7.95189 7.81831 7.48244 6.22044 5.13369 - 2.60387 1.92966 1.19485 1.08549 1.01059 0.99816 - 12.17542 11.46611 10.92574 10.42974 9.97788 9.57045 - 9.20697 8.88714 8.61092 8.37836 8.18941 8.04364 - 7.93939 7.87588 7.85425 7.87062 7.91888 7.98851 - 8.04906 8.04570 7.95418 7.67869 6.53368 5.50511 - 2.89686 2.12061 1.24522 1.10883 1.01566 0.99783 - 12.14103 11.46709 10.92791 10.43307 9.98250 9.57637 - 9.21426 8.89597 8.62159 8.39109 8.20440 8.06116 - 7.95999 7.90045 7.88412 7.90769 7.96654 8.05416 - 8.14797 8.17597 8.14808 7.97243 7.04674 6.14949 - 3.50330 2.54296 1.36777 1.17036 1.02886 0.99739 - 12.12123 11.46742 10.92904 10.43489 9.98497 9.57948 - 9.21805 8.90046 8.62690 8.39738 8.21182 8.06994 - 7.97044 7.91301 7.89942 7.92670 7.99103 8.08828 - 8.19989 8.24434 8.25064 8.13461 7.36422 6.57068 - 3.97778 2.90456 1.48548 1.23388 1.04203 0.99717 - 12.09983 11.46763 10.93007 10.43671 9.98754 9.58271 - 9.22192 8.90499 8.63216 8.40351 8.21906 8.07857 - 7.98080 7.92552 7.91470 7.94575 8.01579 8.12308 - 8.25341 8.31493 8.35580 8.30647 7.74356 7.09880 - 4.68285 3.48597 1.70503 1.35995 1.06808 0.99694 - 12.11007 11.47453 10.92908 10.43257 9.98318 9.57953 - 9.22068 8.90597 8.63512 8.40798 8.22438 8.08356 - 7.98305 7.92277 7.90877 7.94749 8.04026 8.16398 - 8.28801 8.34743 8.39923 8.38976 7.97557 7.41569 - 5.17930 3.94373 1.90791 1.48316 1.09268 0.99682 - 12.10275 11.47447 10.92939 10.43321 9.98406 9.58064 - 9.22199 8.90749 8.63682 8.40991 8.22658 8.08612 - 7.98607 7.92645 7.91335 7.95336 8.04800 8.17457 - 8.30399 8.36914 8.43290 8.44612 8.11560 7.63545 - 5.55728 4.30962 2.10904 1.60180 1.11770 0.99674 - 12.09770 11.47453 10.92969 10.43364 9.98463 9.58134 - 9.22283 8.90846 8.63795 8.41120 8.22809 8.08785 - 7.98813 7.92892 7.91642 7.95728 8.05318 8.18168 - 8.31487 8.38385 8.45546 8.48409 8.21454 7.79403 - 5.85409 4.61531 2.29580 1.71848 1.14253 0.99669 - 12.07044 11.46777 10.93110 10.43867 9.99047 9.58658 - 9.22671 8.91079 8.63908 8.41167 8.22850 8.08944 - 7.99350 7.94081 7.93363 7.96982 8.04744 8.16693 - 8.32261 8.40868 8.49203 8.53246 8.34420 8.00805 - 6.29664 5.10210 2.62994 1.95014 1.19259 0.99664 - 12.06618 11.46754 10.93110 10.43889 9.99077 9.58686 - 9.22692 8.91098 8.63944 8.41230 8.22952 8.09087 - 7.99536 7.94309 7.93633 7.97292 8.05114 8.17221 - 8.33085 8.41958 8.51032 8.56396 8.42448 8.14480 - 6.61245 5.47916 2.92209 2.15665 1.24162 0.99663 - 1.05412 1.09645 1.13923 1.18257 1.22638 1.27057 - 1.31509 1.35992 1.40520 1.45092 1.49711 1.54407 - 1.59250 1.64256 1.69235 1.73755 1.77338 1.79883 - 1.81868 1.83106 1.84652 1.86079 1.87184 1.87408 - 1.87688 1.87714 1.87666 1.87647 1.87667 1.87747 - 1.42558 1.47418 1.52354 1.57401 1.62550 1.67787 - 1.73095 1.78455 1.83838 1.89225 1.94579 1.99876 - 2.05101 2.10219 2.15129 2.19698 2.23783 2.27335 - 2.30208 2.31284 2.32202 2.32894 2.34059 2.34583 - 2.35036 2.34999 2.34769 2.34707 2.34719 2.35061 - 1.75254 1.80869 1.86508 1.92219 1.97984 2.03781 - 2.09584 2.15361 2.21079 2.26709 2.32223 2.37599 - 2.42857 2.47991 2.52909 2.57484 2.61590 2.65203 - 2.68205 2.69369 2.70358 2.71062 2.72102 2.72539 - 2.72962 2.72948 2.72775 2.72728 2.72739 2.72991 - 2.30930 2.38118 2.45067 2.51845 2.58415 2.64745 - 2.70819 2.76641 2.82237 2.87599 2.92729 2.97652 - 3.02481 3.07289 3.11959 3.16263 3.19991 3.23222 - 3.26027 3.27252 3.28506 3.29547 3.30541 3.30774 - 3.30844 3.30882 3.31021 3.31052 3.31047 3.30895 - 2.76674 2.85705 2.94009 3.01655 3.08601 3.14842 - 3.20446 3.25574 3.30466 3.35168 3.39687 3.44032 - 3.48270 3.52439 3.56434 3.60065 3.63184 3.65966 - 3.68620 3.69912 3.71289 3.72429 3.73407 3.73588 - 3.73340 3.73408 3.73818 3.73910 3.73887 3.73393 - 3.15671 3.26260 3.35636 3.43869 3.50918 3.56813 - 3.61708 3.65928 3.69917 3.73776 3.77515 3.81132 - 3.84658 3.88099 3.91361 3.94277 3.96738 3.99004 - 4.01406 4.02703 4.04134 4.05327 4.06263 4.06401 - 4.05944 4.06031 4.06612 4.06745 4.06711 4.05997 - 3.49600 3.61413 3.71565 3.80140 3.87096 3.92504 - 3.96597 3.99844 4.02870 4.05821 4.08712 4.11537 - 4.14301 4.16991 4.19522 4.21739 4.23562 4.25312 - 4.27412 4.28658 4.30067 4.31245 4.32116 4.32222 - 4.31662 4.31756 4.32413 4.32564 4.32525 4.31712 - 4.06310 4.19591 4.30502 4.39163 4.45546 4.49786 - 4.52248 4.53612 4.54760 4.55910 4.57084 4.58288 - 4.59508 4.60730 4.61884 4.62831 4.63521 4.64331 - 4.65771 4.66792 4.67951 4.68896 4.69593 4.69669 - 4.69159 4.69239 4.69814 4.69945 4.69912 4.69197 - 4.52477 4.66241 4.77130 4.85320 4.90805 4.93772 - 4.94675 4.94326 4.93758 4.93235 4.92787 4.92449 - 4.92214 4.92086 4.92014 4.91862 4.91590 4.91582 - 4.92343 4.93046 4.93792 4.94345 4.94829 4.94899 - 4.94629 4.94674 4.94996 4.95069 4.95052 4.94655 - 5.40063 5.52720 5.61750 5.67521 5.70091 5.69748 - 5.67068 5.63023 5.58817 5.54750 5.50906 5.47341 - 5.44096 5.41207 5.38648 5.36281 5.34049 5.32290 - 5.31406 5.31218 5.30774 5.30203 5.30110 5.30179 - 5.30656 5.30599 5.30148 5.30043 5.30077 5.30646 - 6.02829 6.15998 6.22393 6.23486 6.20860 6.16317 - 6.10562 6.04278 5.98232 5.92370 5.86316 5.79952 - 5.73863 5.68522 5.63902 5.59737 5.55941 5.53157 - 5.51058 5.49484 5.47786 5.46571 5.45841 5.45835 - 5.46923 5.46785 5.45711 5.45420 5.45539 5.46888 - 6.94789 7.00582 6.99980 6.94662 6.85969 6.75419 - 6.63854 6.52217 6.41486 6.31614 6.22017 6.12406 - 6.03337 5.95184 5.87871 5.81040 5.74583 5.69384 - 5.64884 5.61742 5.58361 5.55851 5.54128 5.53968 - 5.55537 5.55307 5.53627 5.53174 5.53356 5.55450 - 7.59264 7.58948 7.51903 7.40275 7.25665 7.09788 - 6.93513 6.77755 6.63421 6.50430 6.38166 6.26234 - 6.15056 6.04871 5.95574 5.86800 5.78405 5.71164 - 5.64564 5.60487 5.56201 5.52971 5.50476 5.50100 - 5.51352 5.51119 5.49568 5.49149 5.49314 5.51229 - 8.08071 8.03162 7.90538 7.73030 7.52849 7.32235 - 7.12019 6.92917 6.75640 6.60049 6.45559 6.31725 - 6.18824 6.07000 5.96130 5.85864 5.76001 5.66995 - 5.58564 5.53979 5.49310 5.45749 5.42652 5.42035 - 5.42490 5.42309 5.41333 5.41074 5.41171 5.42338 - 8.46812 8.38492 8.21045 7.98136 7.72787 7.47932 - 7.24335 7.02421 6.82645 6.64819 6.48383 6.32882 - 6.18471 6.05248 5.93064 5.81597 5.70568 5.60027 - 5.50008 5.45163 5.40403 5.36734 5.33153 5.32297 - 5.31754 5.31648 5.31444 5.31398 5.31406 5.31579 - 9.05266 8.91388 8.65694 8.33442 7.99244 7.67296 - 7.38177 7.11745 6.87893 6.66384 6.46661 6.28291 - 6.11261 5.95647 5.81265 5.67821 5.54904 5.41922 - 5.29422 5.24201 5.19338 5.15532 5.11206 5.09972 - 5.07840 5.07856 5.08889 5.09182 5.09050 5.07627 - 9.64161 9.24117 8.84564 8.47190 8.11866 7.78528 - 7.47131 7.17637 6.90051 6.64478 6.40828 6.18986 - 5.98881 5.80591 5.64119 5.49449 5.36263 5.23089 - 5.08659 5.01496 4.95600 4.92167 4.87774 4.85807 - 4.83110 4.83234 4.84737 4.85141 4.85000 4.82899 - 10.34396 9.78393 9.24612 8.74671 8.28297 7.85247 - 7.45334 7.08486 6.74649 6.43688 6.15380 5.89435 - 5.65529 5.43519 5.23513 5.05370 4.88784 4.72445 - 4.55283 4.46845 4.39463 4.34607 4.29049 4.27241 - 4.25418 4.25391 4.25917 4.26068 4.26006 4.25155 - 10.74024 10.05969 9.41951 8.83227 8.29286 7.79782 - 7.34401 6.92919 6.55217 6.20968 5.89770 5.61175 - 5.34619 5.09762 4.86740 4.65511 4.45934 4.27419 - 4.09489 4.00770 3.92055 3.85144 3.78733 3.77737 - 3.77142 3.76840 3.75988 3.75768 3.75866 3.76871 - 11.20731 10.33437 9.54310 8.83280 8.19234 7.61501 - 7.09550 6.62691 6.20359 5.82070 5.47290 5.15450 - 4.85857 4.58021 4.31896 4.07394 3.84278 3.62577 - 3.42485 3.33013 3.23497 3.15900 3.08834 3.07375 - 3.06586 3.06350 3.05652 3.05470 3.05544 3.06274 - 11.51917 10.48655 9.58027 8.78219 8.07595 7.44959 - 6.89461 6.39974 5.95446 5.55206 5.18627 4.85016 - 4.53518 4.23573 3.95236 3.68671 3.43926 3.20717 - 2.99097 2.88997 2.79280 2.71854 2.64495 2.62637 - 2.60924 2.60781 2.60877 2.60915 2.60883 2.60578 - 11.73252 10.58923 9.60797 8.75264 8.00436 7.34696 - 6.76847 6.25460 5.79178 5.37236 4.99023 4.63872 - 4.30971 3.99781 3.70308 3.42641 3.16859 2.92672 - 2.70097 2.59545 2.49467 2.41826 2.34239 2.32332 - 2.30522 2.30382 2.30536 2.30590 2.30552 2.30161 - 11.89026 10.67111 9.64062 8.74644 7.96901 7.28988 - 6.69392 6.16505 5.68818 5.25525 4.86023 4.49667 - 4.15683 3.83560 3.53269 3.24862 2.98392 2.73578 - 2.50283 2.39309 2.28785 2.20797 2.13023 2.11117 - 2.09498 2.09332 2.09294 2.09304 2.09278 2.09122 - 12.11092 10.79911 9.71740 8.78363 7.97488 7.26911 - 6.64834 6.09655 5.59926 5.14727 4.73264 4.34914 - 3.99246 3.65914 3.34711 3.05359 2.77684 2.51666 - 2.27076 2.15312 2.03960 1.95322 1.87051 1.85096 - 1.83639 1.83412 1.83155 1.83108 1.83107 1.83226 - 12.26504 10.91155 9.80785 8.85402 8.02828 7.30794 - 6.67361 6.10860 5.59846 5.13403 4.70738 4.31232 - 3.94480 3.60148 3.28001 2.97726 2.69058 2.41838 - 2.15837 2.03285 1.91135 1.81847 1.72909 1.70764 - 1.69133 1.68893 1.68651 1.68611 1.68603 1.68690 - 12.50763 11.11677 9.99988 9.03030 8.19261 7.45980 - 6.81333 6.23551 5.71172 5.23392 4.79578 4.39039 - 4.00971 3.64832 3.30561 2.98140 2.67343 2.37404 - 2.07769 1.92998 1.78313 1.66757 1.55598 1.52815 - 1.50553 1.50296 1.50115 1.50095 1.50068 1.50031 - 12.63886 11.23707 10.12880 9.16674 8.33587 7.60544 - 6.95928 6.38130 5.85806 5.38111 4.94319 4.53615 - 4.15028 3.77921 3.42305 3.08284 2.75624 2.43273 - 2.10214 1.93180 1.75448 1.60893 1.47137 1.43800 - 1.41123 1.40787 1.40476 1.40434 1.40410 1.40482 - 12.76746 11.35543 10.27582 9.34882 8.54839 7.84387 - 7.21883 6.65671 6.14331 5.67111 5.23420 4.82588 - 4.43791 4.06386 3.70076 3.34446 2.98856 2.62168 - 2.22875 2.01597 1.78482 1.58333 1.38214 1.33957 - 1.31324 1.30896 1.29998 1.29803 1.29906 1.30395 - 12.80892 11.40661 10.36328 9.47310 8.70194 8.02268 - 7.41917 6.87492 6.37556 5.91387 5.48439 5.08063 - 4.69445 4.31932 3.95197 3.58766 3.21776 2.82473 - 2.38363 2.13297 1.84987 1.59622 1.33956 1.28665 - 1.26059 1.25584 1.24186 1.23857 1.24088 1.24841 - 12.81407 11.42778 10.42140 9.56425 8.81928 8.16224 - 7.57757 7.04909 6.56251 6.11097 5.68933 5.29148 - 4.90947 4.53672 4.16961 3.80262 3.42504 3.01406 - 2.53580 2.25416 1.92616 1.62728 1.31933 1.25488 - 1.22637 1.22136 1.20432 1.20020 1.20339 1.21112 - 12.80297 11.43477 10.46380 9.63504 8.91304 8.27512 - 7.70658 7.19167 6.71641 6.27428 5.86044 5.46906 - 5.09243 4.72393 4.35954 3.99294 3.61151 3.18798 - 2.68047 2.37309 2.00672 1.66741 1.31192 1.23537 - 1.20212 1.19679 1.17788 1.17326 1.17701 1.18387 - 12.76385 11.43186 10.52249 9.74004 9.05576 8.44887 - 7.90634 7.41354 6.95735 6.53180 6.13261 5.75440 - 5.38992 5.03256 4.67750 4.31686 3.93469 3.49618 - 2.94527 2.59673 2.16690 1.75894 1.32275 1.22144 - 1.16550 1.15921 1.14432 1.14067 1.14307 1.14646 - 12.72046 11.42258 10.56253 9.81631 9.16117 8.57795 - 8.05513 7.57936 7.13859 6.72732 6.34153 5.97615 - 5.62412 5.27874 4.93458 4.58243 4.20397 3.75937 - 3.18132 2.80331 2.32417 1.85774 1.34543 1.22097 - 1.14568 1.13745 1.12225 1.11862 1.12020 1.12192 - 12.62607 11.40292 10.62883 9.94613 9.33912 8.79364 - 8.30180 7.85414 7.44204 7.06057 6.70537 6.37056 - 6.04771 5.72859 5.40665 5.07061 4.70164 4.26402 - 3.67666 3.26449 2.69860 2.10930 1.42190 1.24765 - 1.12735 1.11153 1.08885 1.08429 1.08590 1.08656 - 12.56729 11.39116 10.66892 10.02614 9.44980 8.92886 - 8.45746 8.02845 7.63531 7.27378 6.93974 6.62751 - 6.32865 6.03467 5.73811 5.42570 5.07590 4.64937 - 4.05547 3.62536 3.01881 2.35948 1.52453 1.29433 - 1.11826 1.09559 1.07200 1.06791 1.06818 1.06770 - 12.46868 11.36563 10.71730 10.12917 9.59288 9.10185 - 8.65373 8.24551 7.87461 7.53807 7.23225 6.95203 - 6.68952 6.43685 6.18755 5.92890 5.63267 5.23196 - 4.60861 4.14570 3.50209 2.78707 1.76219 1.41896 - 1.11569 1.07866 1.05688 1.05282 1.03958 1.04794 - 12.47056 11.37926 10.75202 10.18235 9.66324 9.18912 - 8.75794 8.36714 8.01455 7.69751 7.41266 7.15513 - 6.91714 6.69052 6.46747 6.23244 5.95982 5.60214 - 5.04989 4.61534 3.95817 3.16178 1.93503 1.52454 - 1.13533 1.08099 1.04577 1.04247 1.03466 1.03761 - 12.45969 11.38404 10.77424 10.21929 9.71299 9.25075 - 8.83078 8.45100 8.10970 7.80480 7.53367 7.29247 - 7.07479 6.87306 6.67815 6.47073 6.22182 5.88447 - 5.35467 4.93900 4.31057 3.51233 2.13051 1.62354 - 1.15004 1.08609 1.04241 1.03604 1.03270 1.03127 - 12.44780 11.38932 10.79253 10.24714 9.74868 9.29395 - 8.88167 8.51035 8.17877 7.88467 7.62503 7.39601 - 7.19215 7.00672 6.83087 6.64527 6.42121 6.11333 - 5.61787 5.21924 4.60137 3.78564 2.30030 1.73331 - 1.17548 1.09527 1.03821 1.03274 1.02398 1.02700 - 12.45456 11.40339 10.81364 10.27778 9.79055 9.34848 - 8.94970 8.59225 8.27446 7.99459 7.75023 7.53771 - 7.35063 7.18307 7.03167 6.88739 6.72535 6.47676 - 6.01682 5.63614 5.05268 4.25415 2.62953 1.94085 - 1.21550 1.10955 1.03752 1.03010 1.02276 1.02162 - 12.44447 11.40886 10.82851 10.30075 9.82114 9.38653 - 8.99516 8.64537 8.33575 8.06478 7.83046 7.62958 - 7.45638 7.30574 7.17514 7.05680 6.92725 6.71830 - 6.30666 5.95530 5.40484 4.62034 2.91111 2.13576 - 1.26206 1.13048 1.03807 1.02884 1.01935 1.01833 - 12.40650 11.41430 10.85424 10.33989 9.86969 9.44345 - 9.06035 8.71946 8.42039 8.16195 7.94279 7.76082 - 7.61246 7.49366 7.40002 7.31830 7.22644 7.08314 - 6.78692 6.50220 6.00791 5.26988 3.51727 2.55497 - 1.37539 1.19225 1.04483 1.02967 1.01402 1.01390 - 12.40301 11.42474 10.86242 10.35083 9.88661 9.46736 - 9.09177 8.75865 8.46734 8.21676 8.00580 7.83243 - 7.69243 7.58277 7.50396 7.45278 7.41270 7.32514 - 7.08091 6.83713 6.41286 5.73288 3.94997 2.92902 - 1.49290 1.25174 1.05391 1.03257 1.01266 1.01169 - 12.33921 11.43057 10.87419 10.36800 9.90906 9.49527 - 9.12544 8.79860 8.51418 8.27141 8.06947 7.90673 - 7.77959 7.68588 7.62767 7.60445 7.60446 7.57782 - 7.42891 7.25119 6.90986 6.32345 4.62948 3.51027 - 1.70987 1.37788 1.07653 1.04070 1.01128 1.00945 - 12.28405 11.43312 10.87977 10.37633 9.92004 9.50911 - 9.14235 8.81887 8.53810 8.29947 8.10233 7.94520 - 7.82477 7.73936 7.69198 7.68381 7.70631 7.71595 - 7.62778 7.49465 7.21277 6.70119 5.11885 3.96262 - 1.91079 1.49982 1.10113 1.05027 1.01166 1.00832 - 12.22193 11.42756 10.88447 10.38636 9.93241 9.52246 - 9.15594 8.83261 8.55243 8.31520 8.12064 7.96797 - 7.85521 7.78086 7.74469 7.74039 7.75779 7.77841 - 7.74922 7.66385 7.43015 6.96595 5.48715 4.33196 - 2.09746 1.61606 1.12642 1.06104 1.01245 1.00764 - 12.19321 11.42811 10.88664 10.38977 9.93699 9.52826 - 9.16306 8.84112 8.56243 8.32689 8.13432 7.98407 - 7.87422 7.80342 7.77192 7.77428 7.80163 7.83776 - 7.83690 7.77690 7.58386 7.16995 5.77438 4.63964 - 2.27571 1.72671 1.15186 1.07169 1.01434 1.00719 - 12.15699 11.42907 10.88942 10.39415 9.94280 9.53562 - 9.17212 8.85206 8.57541 8.34217 8.15220 8.00502 - 7.89881 7.83262 7.80722 7.81819 7.85835 7.91488 - 7.95148 7.92591 7.79274 7.45841 6.20452 5.12410 - 2.60537 1.93426 1.20263 1.09381 1.01890 1.00661 - 12.13419 11.42955 10.89107 10.39672 9.94625 9.54006 - 9.17764 8.85875 8.58341 8.35161 8.16326 8.01793 - 7.91396 7.85060 7.82901 7.84526 7.89329 7.96263 - 8.02289 8.01945 7.92812 7.65369 6.51568 5.49335 - 2.89714 2.12457 1.25278 1.11702 1.02395 1.00627 - 12.09989 11.43023 10.89313 10.40005 9.95092 9.54605 - 9.18505 8.86772 8.59417 8.36439 8.17824 8.03541 - 7.93450 7.87511 7.85878 7.88222 7.94084 8.02812 - 8.12156 8.14940 8.12143 7.94620 7.02534 6.13380 - 3.50103 2.54535 1.37478 1.17816 1.03717 1.00582 - 12.08048 11.43047 10.89416 10.40176 9.95337 9.54917 - 9.18884 8.87222 8.59948 8.37065 8.18564 8.04416 - 7.94492 7.88763 7.87405 7.90119 7.96528 8.06217 - 8.17333 8.21757 8.22371 8.10783 7.34091 6.55245 - 3.97364 2.90549 1.49193 1.24128 1.05037 1.00559 - 12.05989 11.43078 10.89519 10.40358 9.95590 9.55236 - 9.19262 8.87664 8.60464 8.37669 8.19283 8.05276 - 7.95527 7.90012 7.88931 7.92021 7.98999 8.09689 - 8.22672 8.28795 8.32860 8.27922 7.71823 7.07748 - 4.67578 3.48438 1.71043 1.36660 1.07645 1.00538 - 12.07055 11.43779 10.89420 10.39934 9.95139 9.54905 - 9.19135 8.87765 8.60764 8.38119 8.19814 8.05772 - 7.95749 7.89736 7.88337 7.92192 8.01437 8.13766 - 8.26124 8.32041 8.37193 8.36229 7.94929 7.39255 - 5.16989 3.94003 1.91248 1.48921 1.10104 1.00528 - 12.06346 11.43773 10.89451 10.39998 9.95224 9.55012 - 9.19262 8.87912 8.60931 8.38309 8.20031 8.06026 - 7.96049 7.90101 7.88793 7.92779 8.02212 8.14824 - 8.27719 8.34208 8.40557 8.41858 8.08872 7.61117 - 5.54589 4.30402 2.11252 1.60734 1.12598 1.00522 - 12.05841 11.43778 10.89472 10.40030 9.95281 9.55082 - 9.19347 8.88012 8.61045 8.38440 8.20183 8.06201 - 7.96256 7.90352 7.89102 7.93172 8.02728 8.15534 - 8.28799 8.35672 8.42811 8.45657 8.18728 7.76889 - 5.84098 4.60811 2.29836 1.72356 1.15073 1.00518 - 12.03109 11.43143 10.89662 10.40574 9.95868 9.55601 - 9.19730 8.88244 8.61161 8.38486 8.20225 8.06360 - 7.96795 7.91540 7.90819 7.94422 8.02154 8.14062 - 8.29574 8.38148 8.46451 8.50476 8.31666 7.98168 - 6.28070 5.09211 2.63089 1.95406 1.20053 1.00514 - 12.02720 11.43159 10.89703 10.40595 9.95891 9.55625 - 9.19762 8.88286 8.61213 8.38556 8.20322 8.06498 - 7.96979 7.91765 7.91085 7.94727 8.02519 8.14583 - 8.30391 8.39233 8.48278 8.53616 8.39673 8.11807 - 6.59452 5.46693 2.92171 2.15972 1.24923 1.00511 - 1.02452 1.06632 1.10852 1.15126 1.19446 1.23804 - 1.28199 1.32638 1.37142 1.41714 1.46363 1.51121 - 1.56063 1.61195 1.66289 1.70825 1.74299 1.76896 - 1.78954 1.79936 1.81384 1.82907 1.83778 1.83962 - 1.84243 1.84258 1.84196 1.84187 1.84185 1.84284 - 1.39998 1.44505 1.49123 1.53894 1.58819 1.63894 - 1.69111 1.74458 1.79919 1.85469 1.91070 1.96665 - 2.02184 2.07528 2.12567 2.17141 2.21094 2.24425 - 2.26942 2.27608 2.27668 2.27584 2.30235 2.31901 - 2.31434 2.31057 2.30953 2.30984 2.30845 2.31264 - 1.72634 1.77924 1.83263 1.88703 1.94236 1.99845 - 2.05513 2.11215 2.16926 2.22617 2.28258 2.33813 - 2.39265 2.44573 2.49628 2.54289 2.58410 2.61956 - 2.64790 2.65827 2.66682 2.67291 2.68299 2.68745 - 2.69105 2.69079 2.68919 2.68877 2.68879 2.69119 - 2.27510 2.34171 2.40738 2.47285 2.53779 2.60180 - 2.66445 2.72531 2.78387 2.83979 2.89290 2.94322 - 2.99157 3.03853 3.08336 3.12508 3.16284 3.19704 - 3.22737 3.24010 3.25108 3.25868 3.26848 3.27132 - 3.27156 3.27180 3.27328 3.27362 3.27363 3.27194 - 2.71900 2.80894 2.89198 2.96879 3.03896 3.10243 - 3.15978 3.21258 3.26309 3.31173 3.35855 3.40362 - 3.44759 3.49076 3.53201 3.56927 3.60086 3.62846 - 3.65408 3.66635 3.67965 3.69091 3.70044 3.70218 - 3.69961 3.70030 3.70444 3.70539 3.70515 3.70013 - 3.09897 3.20652 3.30224 3.38677 3.45960 3.52100 - 3.57238 3.61687 3.65880 3.69913 3.73802 3.77553 - 3.81216 3.84812 3.88233 3.91276 3.93799 3.96068 - 3.98430 3.99692 4.01095 4.02280 4.03226 4.03370 - 4.02914 4.03002 4.03587 4.03720 4.03687 4.02967 - 3.43069 3.55211 3.65720 3.74662 3.81986 3.87747 - 3.92167 3.95699 3.98958 4.02091 4.05119 4.08054 - 4.10938 4.13788 4.16501 4.18874 4.20781 4.22564 - 4.24673 4.25912 4.27311 4.28487 4.29399 4.29521 - 4.28968 4.29063 4.29725 4.29876 4.29838 4.29022 - 3.99035 4.12831 4.24276 4.33469 4.40361 4.45070 - 4.47945 4.49651 4.51061 4.52397 4.53692 4.54981 - 4.56306 4.57694 4.59059 4.60204 4.61027 4.61934 - 4.63463 4.64521 4.65703 4.66666 4.67444 4.67547 - 4.67051 4.67134 4.67715 4.67848 4.67815 4.67098 - 4.45195 4.59509 4.70966 4.79715 4.85733 4.89187 - 4.90512 4.90512 4.90210 4.89873 4.89547 4.89295 - 4.89167 4.89210 4.89359 4.89431 4.89340 4.89488 - 4.90397 4.91166 4.91963 4.92555 4.93143 4.93245 - 4.92994 4.93043 4.93371 4.93445 4.93429 4.93029 - 5.32718 5.48769 5.58584 5.63327 5.64432 5.63591 - 5.61422 5.58518 5.55579 5.52578 5.49224 5.45459 - 5.41777 5.38624 5.36024 5.33848 5.32052 5.30955 - 5.30407 5.29970 5.29531 5.29287 5.29263 5.29337 - 5.29851 5.29802 5.29361 5.29241 5.29291 5.29853 - 5.99667 6.09752 6.15892 6.18644 6.18138 6.14723 - 6.09039 6.02113 5.95176 5.88550 5.82329 5.76557 - 5.71286 5.66538 5.62302 5.58453 5.54928 5.51976 - 5.49844 5.48915 5.47474 5.45981 5.45459 5.45542 - 5.46659 5.46518 5.45423 5.45170 5.45243 5.46621 - 6.93558 6.96594 6.95494 6.91203 6.83980 6.74281 - 6.62838 6.50725 6.39139 6.28430 6.18630 6.09668 - 6.01472 5.93897 5.86924 5.80426 5.74334 5.68858 - 5.64164 5.61849 5.58778 5.55862 5.54359 5.54311 - 5.55928 5.55692 5.53961 5.53561 5.53675 5.55836 - 7.73210 7.59622 7.45206 7.31013 7.17037 7.03279 - 6.89755 6.76491 6.63481 6.50809 6.38562 6.26731 - 6.15439 6.04724 5.94685 5.85448 5.77114 5.69567 - 5.62943 5.60302 5.58345 5.56814 5.51623 5.49552 - 5.51766 5.52063 5.50423 5.49861 5.50372 5.52071 - 8.21382 8.02816 7.83488 7.64620 7.46197 7.28228 - 7.10729 6.93724 6.77238 6.61363 6.46205 6.31757 - 6.18166 6.05526 5.93939 5.83553 5.74429 5.66206 - 5.58707 5.55485 5.52763 5.50371 5.43808 5.41254 - 5.43323 5.43781 5.42590 5.42149 5.42586 5.43566 - 8.59578 8.36584 8.12927 7.89967 7.67679 7.46075 - 7.25169 7.04965 6.85526 6.66953 6.49342 6.32691 - 6.17156 6.02880 5.89961 5.78559 5.68708 5.59875 - 5.51682 5.48051 5.44836 5.41912 5.34410 5.31403 - 5.32979 5.33583 5.33063 5.32813 5.33132 5.33153 - 9.02441 8.89059 8.63784 8.31882 7.98016 7.66430 - 7.37685 7.11599 6.88027 6.66737 6.47198 6.28997 - 6.12133 5.96680 5.82452 5.69149 5.56361 5.43526 - 5.31201 5.26060 5.21279 5.17543 5.13297 5.12083 - 5.09960 5.09979 5.11022 5.11317 5.11183 5.09759 - 9.44611 9.24664 8.92527 8.54024 8.14169 7.77393 - 7.44185 7.14276 6.87393 6.63218 6.41072 6.20461 - 6.01347 5.83810 5.67688 5.52667 5.38274 5.23654 - 5.09583 5.03959 4.98817 4.94773 4.89951 4.88509 - 4.85658 4.85721 4.87284 4.87725 4.87531 4.85427 - 10.14731 9.77958 9.31163 8.80290 8.30056 7.84378 - 7.43451 7.06884 6.74245 6.44863 6.17790 5.92409 - 5.68793 5.47056 5.27146 5.08579 4.90944 4.73810 - 4.57498 4.50177 4.43166 4.37712 4.31951 4.30424 - 4.28502 4.28432 4.29010 4.29183 4.29096 4.28216 - 10.69186 10.02755 9.40122 8.82544 8.29538 7.80785 - 7.35990 6.94952 6.57562 6.23520 5.92445 5.63913 - 5.37397 5.12583 4.89609 4.68437 4.48932 4.30506 - 4.12681 4.04020 3.95353 3.88463 3.82017 3.80987 - 3.80382 3.80084 3.79237 3.79018 3.79117 3.80097 - 11.14520 10.35427 9.58128 8.85443 8.19142 7.60688 - 7.09353 6.63818 6.22896 5.85698 5.51283 5.19053 - 4.88929 4.60854 4.34713 4.10244 3.87170 3.65863 - 3.46071 3.36249 3.26573 3.19161 3.12129 3.10482 - 3.09783 3.09538 3.08812 3.08632 3.08686 3.09421 - 11.51422 10.48925 9.58893 8.79527 8.09240 7.46860 - 6.91557 6.42225 5.97835 5.57721 5.21256 4.87747 - 4.56338 4.26463 3.98177 3.71655 3.46947 3.23769 - 3.02174 2.92079 2.82353 2.74901 2.67484 2.65607 - 2.63880 2.63736 2.63830 2.63867 2.63834 2.63527 - 11.73780 10.59932 9.62134 8.76841 8.02194 7.36591 - 6.78852 6.27566 5.81391 5.39561 5.01463 4.66417 - 4.33601 4.02469 3.73036 3.45416 3.19696 2.95555 - 2.72982 2.62414 2.52312 2.44643 2.37008 2.35086 - 2.33266 2.33125 2.33277 2.33330 2.33292 2.32927 - 11.89985 10.68382 9.65516 8.76236 7.98598 7.30769 - 6.71250 6.18442 5.70850 5.27664 4.88272 4.52019 - 4.18116 3.86039 3.55784 3.27432 3.01046 2.76293 - 2.52990 2.41989 2.31431 2.23413 2.15601 2.13686 - 2.12062 2.11895 2.11852 2.11861 2.11835 2.11723 - 12.12057 10.81518 9.73247 8.79520 7.98399 7.27896 - 6.66086 6.11167 5.61548 5.16411 4.75163 4.37173 - 4.01707 3.68274 3.36834 3.07410 2.79958 2.54126 - 2.29493 2.17695 2.06309 1.97647 1.89365 1.87377 - 1.85924 1.85721 1.85443 1.85399 1.85387 1.85534 - 12.26526 10.91917 9.81581 8.86006 8.03327 7.31464 - 6.68351 6.12132 5.61219 5.14823 4.72360 4.33214 - 3.96672 3.62252 3.29881 2.99535 2.71079 2.44057 - 2.18041 2.05447 1.93275 1.83989 1.75039 1.72860 - 1.71225 1.71012 1.70755 1.70716 1.70701 1.70757 - 12.48260 11.10179 9.99144 9.02702 8.19330 7.46361 - 6.81955 6.24363 5.72127 5.24458 4.80731 4.40269 - 4.02280 3.66229 3.32047 2.99713 2.68992 2.39124 - 2.09553 1.94804 1.80126 1.68560 1.57383 1.54593 - 1.52322 1.52065 1.51885 1.51865 1.51839 1.51759 - 12.60686 11.21621 10.11487 9.15822 8.33142 7.60417 - 6.96051 6.38455 5.86294 5.38735 4.95057 4.54455 - 4.15963 3.78952 3.43436 3.09517 2.76964 2.44711 - 2.11722 1.94711 1.76993 1.62441 1.48675 1.45335 - 1.42659 1.42322 1.42006 1.41963 1.41939 1.42087 - 12.74262 11.33796 10.26173 9.33731 8.53894 7.83630 - 7.21299 6.65252 6.14076 5.67017 5.23484 4.82804 - 4.44150 4.06877 3.70693 3.35193 2.99738 2.63173 - 2.23977 2.02731 1.79634 1.59498 1.39429 1.35200 - 1.32578 1.32154 1.31265 1.31069 1.31179 1.31924 - 12.79735 11.39726 10.35283 9.46199 8.69052 8.01152 - 7.40871 6.86557 6.36767 5.90771 5.48010 5.07825 - 4.69387 4.32030 3.95440 3.59159 3.22328 2.83174 - 2.39179 2.14154 1.85872 1.60535 1.34988 1.29759 - 1.27170 1.26705 1.25338 1.25014 1.25255 1.26339 - 12.81324 11.42525 10.41434 9.55388 8.80681 8.14875 - 7.56400 7.03620 6.55089 6.10109 5.68151 5.28582 - 4.90584 4.53483 4.16928 3.80392 3.42812 3.01884 - 2.54196 2.26085 1.93327 1.63485 1.32864 1.26504 - 1.23681 1.23193 1.21530 1.21127 1.21460 1.22582 - 12.80984 11.43711 10.45924 9.62533 8.89989 8.26003 - 7.69081 7.17624 6.70209 6.26168 5.84999 5.46092 - 5.08647 4.71982 4.35707 3.99219 3.61267 3.19103 - 2.68514 2.37840 2.01261 1.67394 1.32060 1.24509 - 1.21226 1.20707 1.18862 1.18412 1.18803 1.19828 - 12.77970 11.44002 10.52079 9.73094 9.04160 8.43166 - 7.88771 7.39480 6.93948 6.51557 6.11855 5.74278 - 5.38063 5.02521 4.67188 4.31307 3.93298 3.49660 - 2.94767 2.60008 2.17125 1.76440 1.33075 1.23053 - 1.17555 1.16944 1.15482 1.15128 1.15413 1.16032 - 12.62078 11.40396 10.58552 9.85476 9.19574 8.59608 - 8.05105 7.55495 7.10299 6.68992 6.30978 5.95499 - 5.61505 5.28041 4.94446 4.59617 4.21407 3.75323 - 3.15117 2.77110 2.31408 1.88011 1.37510 1.23175 - 1.14391 1.14154 1.14016 1.13559 1.12205 1.13527 - 12.62567 11.42573 10.65468 9.96488 9.34378 8.78056 - 8.27084 7.80930 7.39131 7.01167 6.66417 6.34049 - 6.02862 5.71796 5.40265 5.07302 4.71019 4.27320 - 3.67705 3.25899 2.69147 2.11113 1.43606 1.25046 - 1.13769 1.12350 1.09941 1.09541 1.09503 1.09888 - 12.56846 11.40508 10.68100 10.03069 9.44313 8.90927 - 8.42545 7.98716 7.59047 7.23083 6.90279 6.59881 - 6.30771 6.01937 5.72769 5.42219 5.08153 4.65792 - 4.05409 3.61711 3.00974 2.36201 1.53935 1.29549 - 1.12836 1.10795 1.08260 1.07850 1.07752 1.07926 - 12.44980 11.35028 10.69870 10.10800 9.56981 9.07753 - 8.62876 8.22044 7.84995 7.51421 7.20957 6.93079 - 6.66983 6.41871 6.17099 5.91402 5.61971 5.22137 - 4.60132 4.14071 3.50020 2.78861 1.76855 1.42675 - 1.12522 1.08859 1.06720 1.06315 1.04982 1.05853 - 12.43179 11.34863 10.72217 10.15365 9.63593 9.16339 - 8.73387 8.34466 7.99341 7.67742 7.39332 7.13619 - 6.89825 6.67190 6.45157 6.22570 5.96750 5.61063 - 5.02994 4.57769 3.91910 3.14721 1.95932 1.54049 - 1.14586 1.09117 1.05453 1.05024 1.04063 1.04769 - 12.42382 11.35193 10.74016 10.18480 9.67966 9.21976 - 8.80298 8.42686 8.08923 7.78757 7.51872 7.27791 - 7.05743 6.84995 6.65069 6.44933 6.22082 5.90095 - 5.36207 4.92593 4.26610 3.45731 2.13755 1.65023 - 1.17045 1.09867 1.04638 1.04151 1.03565 1.04105 - 12.40370 11.35501 10.76083 10.21816 9.72194 9.26860 - 8.85702 8.48602 8.15475 7.86128 7.60292 7.37557 - 7.17236 6.98574 6.80783 6.62163 6.40025 6.09701 - 5.60669 5.21055 4.59432 3.78160 2.30637 1.74281 - 1.18171 1.10078 1.04827 1.04418 1.03593 1.03658 - 12.40913 11.36831 10.78071 10.24668 9.76117 9.32053 - 8.92299 8.56661 8.24974 7.97064 7.72691 7.51492 - 7.32828 7.16118 7.01021 6.86648 6.70530 6.45828 - 6.00143 5.62328 5.04352 4.24938 2.63161 1.94574 - 1.22409 1.11863 1.04679 1.03933 1.03202 1.03095 - 12.37479 11.36440 10.79576 10.27522 9.79888 9.36468 - 8.97191 8.62011 8.30920 8.03803 7.80480 7.60661 - 7.43814 7.29352 7.16644 7.04131 6.89261 6.67456 - 6.28584 5.95099 5.40192 4.60966 2.90917 2.13659 - 1.27318 1.14079 1.04671 1.03863 1.02534 1.02751 - 12.36127 11.37546 10.81767 10.30741 9.84126 9.41757 - 9.03557 8.69485 8.39548 8.13669 7.91742 7.73584 - 7.58811 7.47012 7.37751 7.29727 7.20666 7.06131 - 6.76313 6.48284 5.99617 5.26194 3.50778 2.56255 - 1.38424 1.19804 1.05382 1.03795 1.02410 1.02287 - 12.34039 11.38172 10.82844 10.32283 9.86177 9.44371 - 9.06786 8.73382 8.44170 8.19081 7.98038 7.80892 - 7.67305 7.56934 7.49452 7.43724 7.37782 7.27781 - 7.05057 6.82219 6.40370 5.72863 3.95132 2.90942 - 1.50342 1.26521 1.06274 1.03955 1.01872 1.02055 - 12.27927 11.38946 10.84180 10.34087 9.88436 9.47109 - 9.10068 8.77303 8.48852 8.24621 8.04464 7.88244 - 7.75781 7.66926 7.61573 7.58963 7.57544 7.53708 - 7.38986 7.21768 6.89777 6.35316 4.63690 3.44126 - 1.72519 1.40567 1.08273 1.03825 1.02282 1.01819 - 12.22299 11.39222 10.84847 10.35019 9.89603 9.48557 - 9.11826 8.79381 8.51233 8.27341 8.07649 7.92066 - 7.80392 7.72456 7.68163 7.66763 7.67055 7.66893 - 7.60011 7.48073 7.19682 6.67556 5.11492 3.95718 - 1.91408 1.50695 1.10960 1.05936 1.01958 1.01700 - 12.18295 11.39338 10.85157 10.35510 9.90264 9.49393 - 9.12857 8.80643 8.52765 8.29167 8.09745 7.94410 - 7.83053 7.75601 7.72034 7.71708 7.73610 7.75921 - 7.72351 7.62792 7.39921 6.97300 5.50584 4.27626 - 2.10071 1.63598 1.13514 1.06028 1.02669 1.01628 - 12.15397 11.39442 10.85444 10.35902 9.90740 9.49992 - 9.13594 8.81504 8.53712 8.30211 8.10999 7.96015 - 7.85061 7.77998 7.74851 7.75076 7.77791 7.81376 - 7.81268 7.75278 7.56027 7.14824 5.76140 4.63273 - 2.27871 1.73214 1.15997 1.08024 1.02279 1.01580 - 12.11983 11.39309 10.85502 10.36269 9.91450 9.50941 - 9.14700 8.82723 8.55045 8.31687 8.12659 7.97942 - 7.87383 7.80889 7.78487 7.79598 7.83438 7.88954 - 7.92769 7.90283 7.76747 7.43225 6.19331 5.11250 - 2.60929 1.93743 1.20800 1.10509 1.02658 1.01519 - 12.09636 11.39587 10.85897 10.36595 9.91667 9.51165 - 9.15040 8.83250 8.55795 8.32672 8.13884 7.99391 - 7.89026 7.82708 7.80550 7.82163 7.86941 7.93838 - 7.99830 7.99480 7.90349 7.62983 6.49809 5.48167 - 2.89743 2.12857 1.26039 1.12525 1.03233 1.01483 - 12.06282 11.39666 10.86113 10.36927 9.92133 9.51758 - 9.15764 8.84127 8.56851 8.33937 8.15376 8.01134 - 7.91073 7.85149 7.83518 7.85850 7.91688 8.00379 - 8.09682 8.12452 8.09640 7.92137 7.00459 6.11834 - 3.49891 2.54784 1.38180 1.18596 1.04552 1.01435 - 12.04379 11.39710 10.86226 10.37109 9.92377 9.52065 - 9.16137 8.84574 8.57381 8.34564 8.16115 8.02008 - 7.92112 7.86397 7.85039 7.87739 7.94126 8.03778 - 8.14853 8.19257 8.19849 8.08259 7.31842 6.53459 - 3.96958 2.90648 1.49840 1.24868 1.05874 1.01411 - 12.02840 11.39562 10.85948 10.37000 9.92562 9.52514 - 9.16780 8.85313 8.58109 8.35207 8.16675 8.02576 - 7.92881 7.87610 7.86822 7.89919 7.96403 8.06677 - 8.20683 8.27716 8.30203 8.20969 7.70003 7.16550 - 4.62702 3.42803 1.71890 1.39109 1.08607 1.01388 - 12.03477 11.40432 10.86220 10.36866 9.92197 9.52075 - 9.16405 8.85122 8.58197 8.35617 8.17364 8.03363 - 7.93366 7.87369 7.85971 7.89812 7.99025 8.11312 - 8.23623 8.29520 8.34648 8.33666 7.92433 7.37022 - 5.16052 3.93642 1.91716 1.49532 1.10934 1.01377 - 12.02761 11.40417 10.86250 10.36930 9.92281 9.52182 - 9.16533 8.85271 8.58367 8.35809 8.17583 8.03617 - 7.93667 7.87734 7.86427 7.90397 7.99796 8.12363 - 8.25210 8.31677 8.38011 8.39298 8.06327 7.58779 - 5.53457 4.29855 2.11617 1.61297 1.13422 1.01370 - 12.02256 11.40412 10.86261 10.36962 9.92331 9.52249 - 9.16615 8.85368 8.58479 8.35937 8.17731 8.03788 - 7.93871 7.87980 7.86731 7.90785 8.00310 8.13071 - 8.26289 8.33138 8.40261 8.43090 8.16161 7.74492 - 5.82804 4.60098 2.30102 1.72871 1.15882 1.01365 - 11.99505 11.39717 10.86392 10.37455 9.92908 9.52766 - 9.16997 8.85598 8.58590 8.35983 8.17775 8.03950 - 7.94409 7.89165 7.88444 7.92031 7.99736 8.11605 - 8.27064 8.35611 8.43889 8.47900 8.29096 7.95685 - 6.26513 5.08232 2.63195 1.95804 1.20839 1.01358 - 11.99084 11.39644 10.86352 10.37457 9.92939 9.52802 - 9.17022 8.85614 8.58619 8.36042 8.17874 8.04092 - 7.94595 7.89391 7.88711 7.92338 8.00104 8.12128 - 8.27886 8.36700 8.45712 8.51027 8.37076 8.09282 - 6.57702 5.45491 2.92137 2.16279 1.25681 1.01352 - 0.99755 1.03820 1.07935 1.12116 1.16355 1.20648 - 1.24994 1.29401 1.33888 1.38461 1.43132 1.47935 - 1.52945 1.58167 1.63358 1.67959 1.71432 1.73978 - 1.75963 1.76896 1.78282 1.79737 1.80500 1.80653 - 1.80913 1.80924 1.80856 1.80846 1.80844 1.80946 - 1.36578 1.41045 1.45627 1.50367 1.55264 1.60317 - 1.65517 1.70855 1.76314 1.81874 1.87493 1.93121 - 1.98686 2.04090 2.09204 2.13865 2.17905 2.21294 - 2.23781 2.24371 2.24286 2.24034 2.26575 2.28259 - 2.27806 2.27429 2.27328 2.27363 2.27217 2.27623 - 1.68947 1.73990 1.79124 1.84409 1.89842 1.95416 - 2.01121 2.06940 2.12850 2.18822 2.24810 2.30748 - 2.36551 2.42108 2.47275 2.51877 2.55754 2.58946 - 2.61311 2.61907 2.61914 2.61824 2.64563 2.66238 - 2.65577 2.65186 2.65180 2.65242 2.65085 2.65399 - 2.22972 2.29854 2.36576 2.43206 2.49713 2.56064 - 2.62234 2.68213 2.73999 2.79578 2.84951 2.90141 - 2.95260 3.00370 3.05329 3.09854 3.13654 3.16719 - 3.19212 3.20354 3.21499 3.22418 3.23334 3.23513 - 3.23563 3.23607 3.23750 3.23788 3.23770 3.23607 - 2.67256 2.76232 2.84545 2.92259 2.99332 3.05760 - 3.11597 3.16997 3.22180 3.27189 3.32026 3.36694 - 3.41256 3.45736 3.50005 3.53832 3.57026 3.59762 - 3.62254 3.63435 3.64732 3.65843 3.66755 3.66916 - 3.66654 3.66722 3.67135 3.67229 3.67206 3.66704 - 3.05067 3.15822 3.25425 3.33940 3.41311 3.47565 - 3.52838 3.57437 3.61789 3.65989 3.70050 3.73975 - 3.77813 3.81580 3.85154 3.88310 3.90887 3.93163 - 3.95499 3.96743 3.98147 3.99344 4.00251 4.00381 - 3.99924 4.00010 4.00590 4.00722 4.00688 3.99976 - 3.38127 3.50284 3.60846 3.69874 3.77311 3.83213 - 3.87793 3.91500 3.94938 3.98252 4.01461 4.04577 - 4.07640 4.10666 4.13538 4.16036 4.18019 4.19839 - 4.21965 4.23213 4.24643 4.25853 4.26733 4.26842 - 4.26291 4.26385 4.27038 4.27188 4.27151 4.26344 - 3.93992 4.07830 4.19360 4.28673 4.35719 4.40609 - 4.43682 4.45593 4.47206 4.48736 4.50219 4.51690 - 4.53194 4.54761 4.56297 4.57592 4.58534 4.59537 - 4.61157 4.62267 4.63526 4.64558 4.65333 4.65429 - 4.64938 4.65020 4.65595 4.65727 4.65695 4.64982 - 4.40141 4.54515 4.66078 4.74974 4.81174 4.84834 - 4.86384 4.86610 4.86521 4.86383 4.86243 4.86166 - 4.86211 4.86434 4.86763 4.87008 4.87074 4.87369 - 4.88429 4.89281 4.90184 4.90868 4.91489 4.91594 - 4.91348 4.91396 4.91726 4.91801 4.91785 4.91381 - 5.27777 5.43925 5.53887 5.58814 5.60144 5.59563 - 5.57668 5.55025 5.52299 5.49469 5.46272 5.42668 - 5.39159 5.36194 5.33795 5.31832 5.30253 5.29380 - 5.29076 5.28775 5.28476 5.28341 5.28429 5.28526 - 5.29051 5.29004 5.28576 5.28460 5.28508 5.29055 - 5.94943 6.05135 6.11442 6.14406 6.14146 6.11001 - 6.05598 5.98941 5.92238 5.85813 5.79762 5.74142 - 5.69022 5.64445 5.60404 5.56778 5.53508 5.50830 - 5.48980 5.48194 5.46900 5.45529 5.45150 5.45270 - 5.46406 5.46269 5.45184 5.44933 5.45005 5.46375 - 6.89263 6.92444 6.91550 6.87506 6.80558 6.71154 - 6.60010 6.48180 6.36843 6.26347 6.16727 6.07925 - 5.99882 5.92471 5.85682 5.79400 5.73565 5.68369 - 5.63959 5.61786 5.58858 5.56059 5.54701 5.54692 - 5.56352 5.56118 5.54378 5.53978 5.54091 5.56270 - 7.69202 7.55901 7.41784 7.27880 7.14184 7.00700 - 6.87439 6.74432 6.61669 6.49236 6.37217 6.25605 - 6.14522 6.04005 5.94153 5.85098 5.76942 5.69586 - 5.63185 5.60677 5.58874 5.57486 5.52441 5.50401 - 5.52644 5.52939 5.51284 5.50717 5.51233 5.52963 - 8.17726 7.99482 7.80487 7.61936 7.43819 7.26143 - 7.08925 6.92189 6.75961 6.60330 6.45402 6.31172 - 6.17787 6.05338 5.93931 5.83714 5.74753 5.66701 - 5.59399 5.56293 5.53703 5.51433 5.45001 5.42478 - 5.44573 5.45027 5.43819 5.43374 5.43814 5.44825 - 8.56243 8.33606 8.10311 7.87697 7.65736 7.44443 - 7.23833 7.03910 6.84737 6.66412 6.49032 6.32598 - 6.17264 6.03173 5.90424 5.79177 5.69474 5.60793 - 5.52774 5.49243 5.46141 5.43322 5.35937 5.32956 - 5.34548 5.35149 5.34619 5.34365 5.34687 5.34727 - 8.99732 8.86601 8.61730 8.30292 7.96876 7.65668 - 7.37234 7.11408 6.88069 6.66993 6.47670 6.29687 - 6.13020 5.97724 5.83625 5.70442 5.57788 5.45122 - 5.32987 5.27924 5.23211 5.19528 5.15349 5.14152 - 5.12041 5.12062 5.13109 5.13406 5.13271 5.11839 - 9.42280 9.22677 8.91020 8.53032 8.13654 7.77259 - 7.44352 7.14692 6.88036 6.64077 6.42144 6.21744 - 6.02822 5.85440 5.69442 5.54524 5.40236 5.25752 - 5.11839 5.06270 5.01176 4.97169 4.92399 4.90969 - 4.88108 4.88175 4.89759 4.90204 4.90008 4.87877 - 10.13030 9.76793 9.30606 8.80315 8.30575 7.85268 - 7.44617 7.08274 6.75843 6.46663 6.19789 5.94593 - 5.71144 5.49545 5.29748 5.11271 4.93716 4.76668 - 4.60433 4.53121 4.46118 4.40676 4.34945 4.33425 - 4.31486 4.31419 4.32019 4.32198 4.32109 4.31203 - 10.67891 10.02141 9.40120 8.83065 8.30508 7.82133 - 7.37661 6.96892 6.59726 6.25867 5.94943 5.66541 - 5.40139 5.15431 4.92552 4.71468 4.52042 4.33677 - 4.15884 4.07222 3.98542 3.91633 3.85184 3.84165 - 3.83570 3.83273 3.82427 3.82208 3.82306 3.83295 - 11.13475 10.35276 9.58702 8.86580 8.20695 7.62529 - 7.11397 6.66028 6.25270 5.88240 5.53975 5.21874 - 4.91859 4.63876 4.37816 4.13428 3.90433 3.69157 - 3.49317 3.39454 3.29741 3.22310 3.15271 3.13624 - 3.12931 3.12685 3.11955 3.11773 3.11827 3.12584 - 11.50416 10.48926 9.59622 8.80788 8.10880 7.48764 - 6.93645 6.44451 6.00186 5.60193 5.23848 4.90453 - 4.59149 4.29367 4.01161 3.74705 3.50044 3.26880 - 3.05249 2.95120 2.85357 2.77876 2.70436 2.68553 - 2.66819 2.66675 2.66770 2.66808 2.66775 2.66467 - 11.72720 10.59912 9.62847 8.78073 8.03782 7.38420 - 6.80839 6.29670 5.83601 5.41879 5.03886 4.68944 - 4.36225 4.05177 3.75815 3.48249 3.22562 2.98435 - 2.75852 2.65266 2.55131 2.47423 2.39751 2.37819 - 2.35987 2.35845 2.35999 2.36053 2.36014 2.35626 - 11.88807 10.68276 9.66138 8.77368 8.00076 7.32473 - 6.73098 6.20394 5.72897 5.29806 4.90511 4.54353 - 4.20541 3.88546 3.58359 3.30056 3.03695 2.78957 - 2.55669 2.44666 2.34079 2.26015 2.18158 2.16230 - 2.14593 2.14425 2.14382 2.14392 2.14366 2.14221 - 12.10561 10.81160 9.73608 8.80388 7.99601 7.29311 - 6.67632 6.12806 5.63273 5.18225 4.77067 4.39170 - 4.03795 3.70446 3.39076 3.09699 2.82268 2.56456 - 2.31862 2.20079 2.08678 1.99973 1.91641 1.89637 - 1.88172 1.87967 1.87686 1.87642 1.87630 1.87766 - 12.24699 10.91256 9.81650 8.86587 8.04245 7.32591 - 6.69609 6.13482 5.62658 5.16353 4.73986 4.34937 - 3.98492 3.64164 3.31874 3.01581 2.73150 2.46153 - 2.20179 2.07606 1.95433 1.86120 1.77120 1.74925 - 1.73278 1.73063 1.72803 1.72763 1.72748 1.72834 - 12.45622 11.08799 9.98521 9.02614 8.19592 7.46852 - 6.82594 6.25114 5.72986 5.25428 4.81816 4.41469 - 4.03597 3.67658 3.33577 3.01318 2.70649 2.40832 - 2.11325 1.96606 1.81941 1.70365 1.59156 1.56353 - 1.54072 1.53814 1.53633 1.53614 1.53587 1.53537 - 12.57347 11.19614 10.10279 9.15174 8.32867 7.60396 - 6.96203 6.38741 5.86710 5.39281 4.95735 4.55266 - 4.16905 3.80020 3.44616 3.10789 2.78314 2.46151 - 2.13278 1.96315 1.78605 1.64029 1.50251 1.46909 - 1.44227 1.43888 1.43573 1.43530 1.43506 1.43593 - 12.69863 11.30890 10.24129 9.32287 8.52859 7.82874 - 7.20745 6.64859 6.13841 5.66945 5.23575 4.83053 - 4.44548 4.07410 3.71355 3.35983 3.00670 2.64266 - 2.25243 2.04067 1.80995 1.60840 1.40752 1.36534 - 1.33924 1.33495 1.32594 1.32399 1.32503 1.33042 - 12.74598 11.36221 10.32705 9.44250 8.67530 7.99920 - 7.39843 6.85697 6.36076 5.90261 5.47684 5.07680 - 4.69409 4.32201 3.95749 3.59614 3.22952 2.84007 - 2.40251 2.15323 1.87076 1.61713 1.36150 1.30944 - 1.28380 1.27907 1.26515 1.26189 1.26421 1.27231 - 12.75653 11.38622 10.38504 9.53114 8.78842 8.13327 - 7.55050 7.02430 6.54070 6.09276 5.67513 5.28138 - 4.90319 4.53376 4.16969 3.80593 3.43204 3.02519 - 2.55114 2.27122 1.94409 1.64540 1.33912 1.27586 - 1.24797 1.24299 1.22604 1.22197 1.22517 1.23351 - 12.74954 11.39535 10.42745 9.60028 8.87926 8.24230 - 7.67498 7.16193 6.68944 6.25089 5.84119 5.45412 - 5.08153 4.71653 4.35536 3.99218 3.61475 3.19579 - 2.69304 2.38766 2.02241 1.68351 1.33024 1.25515 - 1.22272 1.21743 1.19863 1.19406 1.19782 1.20529 - 12.71488 11.39487 10.48595 9.70300 9.01813 8.41098 - 7.86876 7.37717 6.92336 6.50122 6.10616 5.73241 - 5.37217 5.01852 4.66691 4.30998 3.93222 3.49882 - 2.95342 2.60739 2.17935 1.77252 1.33926 1.23950 - 1.18498 1.17880 1.16385 1.16025 1.16296 1.16673 - 12.55975 11.35773 10.54668 9.82185 9.16763 8.57187 - 8.03000 7.53642 7.08645 6.67496 6.29610 5.94247 - 5.60379 5.27070 4.93663 4.59061 4.21121 3.75351 - 3.15483 2.77638 2.32069 1.88748 1.38307 1.23995 - 1.15253 1.15022 1.14872 1.14407 1.13017 1.14153 - 12.56493 11.37922 10.61460 9.93002 9.31322 8.75354 - 8.24671 7.78753 7.37142 6.99327 6.64697 6.32433 - 6.01353 5.70415 5.39040 5.06277 4.70263 4.26943 - 3.67815 3.26224 2.69563 2.11548 1.44241 1.25784 - 1.14577 1.13154 1.10716 1.10307 1.10250 1.10529 - 12.50950 11.35978 10.64135 9.99561 9.41184 8.88115 - 8.39991 7.96371 7.56868 7.21037 6.88339 6.58032 - 6.29019 6.00302 5.71283 5.40925 5.07121 4.65135 - 4.05245 3.61784 3.01188 2.36498 1.54496 1.30221 - 1.13608 1.11570 1.09012 1.08594 1.08479 1.08596 - 12.39451 11.30760 10.66045 10.07349 9.53835 9.04861 - 8.60192 8.19528 7.82610 7.49141 7.18762 6.90959 - 6.64947 6.39945 6.15315 5.89803 5.60610 5.21086 - 4.59485 4.13673 3.49911 2.79025 1.77360 1.43271 - 1.13240 1.09603 1.07478 1.07065 1.05704 1.06574 - 12.37950 11.30817 10.68528 10.11967 9.60445 9.13402 - 8.70625 8.31849 7.96840 7.65336 7.37005 7.11363 - 6.87644 6.65106 6.43193 6.20762 5.95147 5.59738 - 5.02058 4.57092 3.91558 3.14702 1.96364 1.54608 - 1.15297 1.09860 1.06218 1.05782 1.04794 1.05518 - 12.37384 11.31298 10.70414 10.15128 9.64825 9.19015 - 8.77490 8.40008 8.06353 7.76276 7.49466 7.25454 - 7.03476 6.82813 6.62990 6.42986 6.20309 5.88567 - 5.35048 4.91693 4.26056 3.45557 2.14123 1.65554 - 1.17754 1.10611 1.05412 1.04919 1.04306 1.04872 - 12.35537 11.31718 10.72558 10.18502 9.69056 9.23875 - 8.82849 8.45864 8.12838 7.83583 7.57831 7.35171 - 7.14923 6.96331 6.78617 6.60096 6.38101 6.08004 - 5.59354 5.20017 4.58757 3.77861 2.30888 1.74754 - 1.18903 1.10843 1.05596 1.05181 1.04360 1.04436 - 12.34117 11.32540 10.74854 10.21993 9.73615 9.29535 - 8.89659 8.53882 8.22132 7.94235 7.69926 7.48887 - 7.30658 7.14674 7.00161 6.85313 6.67358 6.41745 - 5.98240 5.61927 5.03915 4.23631 2.63423 1.94994 - 1.23087 1.12791 1.05458 1.04771 1.03776 1.03887 - 12.32999 11.32830 10.76106 10.24183 9.76692 9.33410 - 8.94267 8.59209 8.28224 8.01197 7.77949 7.58190 - 7.41392 7.26971 7.14302 7.01837 6.87043 6.65377 - 6.26790 5.93554 5.39036 4.60273 2.90950 2.14011 - 1.28032 1.14839 1.05462 1.04655 1.03328 1.03552 - 12.31691 11.33929 10.78275 10.27377 9.80899 9.38665 - 9.00598 8.66650 8.36819 8.11026 7.89168 7.71063 - 7.56330 7.44562 7.35325 7.27326 7.18306 7.03847 - 6.74204 6.46366 5.98063 5.25148 3.50602 2.56438 - 1.39095 1.20549 1.06190 1.04598 1.03222 1.03101 - 12.29591 11.34536 10.79342 10.28906 9.82942 9.41270 - 9.03814 8.70529 8.41417 8.16413 7.95438 7.78345 - 7.64798 7.54454 7.46987 7.41273 7.35345 7.25385 - 7.02788 6.80103 6.38558 5.71515 3.94741 2.91023 - 1.50973 1.27232 1.07083 1.04778 1.02686 1.02876 - 12.23491 11.35262 10.80666 10.30708 9.85195 9.44002 - 9.07085 8.74436 8.46081 8.21929 8.01836 7.85665 - 7.73237 7.64409 7.59070 7.56464 7.55044 7.51213 - 7.36545 7.19421 6.87652 6.33583 4.62969 3.43958 - 1.73070 1.41240 1.09081 1.04651 1.03097 1.02647 - 12.17927 11.35529 10.81333 10.31649 9.86368 9.45452 - 9.08843 8.76511 8.48455 8.24637 8.05005 7.89472 - 7.77833 7.69920 7.65637 7.64238 7.64522 7.64357 - 7.57498 7.45610 7.17366 6.65576 5.10557 3.95352 - 1.91853 1.51309 1.11768 1.06771 1.02783 1.02533 - 12.13998 11.35635 10.81643 10.32140 9.87036 9.46296 - 9.09877 8.77766 8.49978 8.26453 8.07091 7.91803 - 7.80479 7.73049 7.69490 7.69165 7.71062 7.73362 - 7.69787 7.60252 7.37498 6.95171 5.49425 4.27044 - 2.10457 1.64186 1.14312 1.06854 1.03491 1.02464 - 12.11242 11.35710 10.81869 10.32490 9.87500 9.46880 - 9.10589 8.78618 8.50976 8.27617 8.08448 7.93394 - 7.82362 7.75307 7.72232 7.72544 7.75349 7.79195 - 7.78674 7.71726 7.52579 7.14725 5.78369 4.57967 - 2.27756 1.74994 1.16873 1.07964 1.03797 1.02419 - 12.07714 11.35827 10.82197 10.32967 9.88100 9.47637 - 9.11520 8.79713 8.52208 8.29007 8.10114 7.95482 - 7.84926 7.78342 7.75809 7.76887 7.80869 7.86468 - 7.90081 7.87521 7.74263 7.41103 6.17277 5.10497 - 2.60842 1.94351 1.21820 1.11044 1.03555 1.02360 - 12.05570 11.35886 10.82351 10.33213 9.88451 9.48082 - 9.12065 8.80369 8.52996 8.29947 8.11219 7.96769 - 7.86433 7.80131 7.77977 7.79582 7.84343 7.91215 - 7.97185 7.96830 7.87719 7.60458 6.47987 5.46986 - 2.89774 2.13252 1.26790 1.13335 1.04059 1.02325 - 12.02319 11.35965 10.82557 10.33545 9.88910 9.48672 - 9.12790 8.81246 8.54054 8.31210 8.12707 7.98509 - 7.88476 7.82568 7.80936 7.83254 7.89068 7.97729 - 8.07003 8.09763 8.06950 7.89492 6.98294 6.10249 - 3.49676 2.55032 1.38878 1.19371 1.05383 1.02278 - 12.00471 11.36019 10.82670 10.33726 9.89147 9.48973 - 9.13159 8.81690 8.54582 8.31836 8.13446 7.99380 - 7.89512 7.83811 7.82452 7.85139 7.91501 8.01116 - 8.12153 8.16545 8.17130 8.05559 7.29486 6.51613 - 3.96559 2.90756 1.50486 1.25605 1.06708 1.02254 - 11.98471 11.36072 10.82803 10.33907 9.89386 9.49275 - 9.13531 8.82137 8.55105 8.32446 8.14164 8.00237 - 7.90542 7.85055 7.83971 7.87035 7.93960 8.04571 - 8.17461 8.23541 8.27567 8.22620 7.66852 7.03520 - 4.66178 3.48142 1.72139 1.37999 1.09320 1.02231 - 11.99539 11.36742 10.82694 10.33503 9.88967 9.48971 - 9.13413 8.82229 8.55391 8.32883 8.14689 8.00734 - 7.90770 7.84788 7.83389 7.87212 7.96387 8.08625 - 8.20891 8.26767 8.31881 8.30895 7.89793 7.34695 - 5.15107 3.93277 1.92181 1.50144 1.11766 1.02219 - 11.98816 11.36726 10.82725 10.33556 9.89052 9.49080 - 9.13545 8.82382 8.55564 8.33077 8.14910 8.00987 - 7.91068 7.85151 7.83843 7.87794 7.97157 8.09675 - 8.22470 8.28915 8.35233 8.36516 8.03628 7.56338 - 5.52304 4.29301 2.11976 1.61856 1.14243 1.02213 - 11.98309 11.36702 10.82735 10.33589 9.89105 9.49151 - 9.13630 8.82482 8.55678 8.33207 8.15058 8.01158 - 7.91269 7.85396 7.84147 7.88184 7.97672 8.10383 - 8.23544 8.30371 8.37482 8.40313 8.13424 7.71960 - 5.81470 4.59375 2.30373 1.73387 1.16696 1.02208 - 11.95600 11.36017 10.82856 10.34082 9.89678 9.49665 - 9.14010 8.82709 8.55788 8.33253 8.15100 8.01315 - 7.91803 7.86575 7.85854 7.89427 7.97100 8.08923 - 8.24325 8.32838 8.41086 8.45092 8.26346 7.93040 - 6.24892 5.07225 2.63301 1.96203 1.21629 1.02203 - 11.95256 11.35954 10.82806 10.34063 9.89706 9.49706 - 9.14040 8.82728 8.55816 8.33311 8.15198 8.01456 - 7.91988 7.86799 7.86117 7.89730 7.97465 8.09447 - 8.25146 8.33923 8.42904 8.48207 8.34280 8.06580 - 6.55881 5.44258 2.92115 2.16600 1.26450 1.02200 - 0.97104 1.01087 1.05121 1.09222 1.13384 1.17604 - 1.21885 1.26241 1.30696 1.35261 1.39949 1.44798 - 1.49881 1.55198 1.60493 1.65170 1.68648 1.71144 - 1.73040 1.73913 1.75232 1.76616 1.77248 1.77361 - 1.77600 1.77603 1.77520 1.77520 1.77619 1.77622 - 1.33279 1.37700 1.42240 1.46941 1.51804 1.56828 - 1.62006 1.67328 1.72781 1.78343 1.83978 1.89634 - 1.95243 2.00709 2.05901 2.10655 2.14791 2.18244 - 2.20704 2.21214 2.20975 2.20538 2.22938 2.24629 - 2.24173 2.23761 2.23654 2.23760 2.23861 2.23965 - 1.65217 1.70235 1.75349 1.80619 1.86043 1.91614 - 1.97323 2.03154 2.09084 2.15087 2.21117 2.27109 - 2.32979 2.38618 2.43877 2.48579 2.52552 2.55802 - 2.58127 2.58634 2.58476 2.58199 2.60826 2.62526 - 2.61856 2.61437 2.61430 2.61543 2.61547 2.61653 - 2.18830 2.25646 2.32321 2.38927 2.45432 2.51807 - 2.58027 2.64078 2.69958 2.75651 2.81155 2.86490 - 2.91760 2.97016 3.02103 3.06713 3.10530 3.13530 - 3.15892 3.16968 3.18055 3.18935 3.19785 3.19927 - 3.19952 3.20018 3.20173 3.20171 3.19991 3.19998 - 2.62801 2.71730 2.80024 2.87748 2.94861 3.01356 - 3.07288 3.12804 3.18119 3.23271 3.28263 3.33093 - 3.37818 3.42451 3.46853 3.50769 3.53989 3.56697 - 3.59124 3.60259 3.61519 3.62605 3.63471 3.63620 - 3.63323 3.63408 3.63864 3.63902 3.63373 3.63387 - 3.00398 3.11143 3.20766 3.29324 3.36769 3.43120 - 3.48513 3.53253 3.57760 3.62128 3.66366 3.70471 - 3.74481 3.78400 3.82099 3.85346 3.87972 3.90263 - 3.92590 3.93821 3.95211 3.96394 3.97277 3.97403 - 3.96910 3.97021 3.97658 3.97710 3.96963 3.96984 - 3.33318 3.45501 3.56115 3.65219 3.72756 3.78779 - 3.83499 3.87364 3.90972 3.94469 3.97870 4.01176 - 4.04416 4.07591 4.10586 4.13179 4.15234 4.17110 - 4.19280 4.20544 4.21984 4.23194 4.24067 4.24177 - 4.23591 4.23712 4.24430 4.24490 4.23645 4.23669 - 3.89035 4.02951 4.14587 4.24025 4.31214 4.36260 - 4.39502 4.41592 4.43394 4.45122 4.46806 4.48473 - 4.50156 4.51874 4.53536 4.54946 4.56004 4.57130 - 4.58879 4.60052 4.61364 4.62423 4.63215 4.63317 - 4.62797 4.62904 4.63539 4.63591 4.62844 4.62867 - 4.35133 4.49623 4.61328 4.70384 4.76754 4.80599 - 4.82337 4.82756 4.82866 4.82928 4.82987 4.83103 - 4.83325 4.83702 4.84170 4.84554 4.84776 4.85244 - 4.86491 4.87439 4.88429 4.89167 4.89822 4.89932 - 4.89668 4.89733 4.90099 4.90129 4.89703 4.89718 - 5.22877 5.39110 5.49258 5.54434 5.56020 5.55661 - 5.53957 5.51504 5.48998 5.46399 5.43400 5.39944 - 5.36573 5.33775 5.31571 5.29818 5.28457 5.27814 - 5.27770 5.27617 5.27460 5.27417 5.27556 5.27662 - 5.28211 5.28129 5.27662 5.27635 5.28214 5.28194 - 5.90169 6.00546 6.07072 6.10273 6.10260 6.07369 - 6.02214 5.95791 5.89302 5.83068 5.77188 5.71730 - 5.66774 5.62372 5.58528 5.55124 5.52105 5.49700 - 5.48132 5.47492 5.46352 5.45099 5.44775 5.44897 - 5.46099 5.45912 5.44716 5.44619 5.46063 5.46024 - 6.84873 6.88271 6.87634 6.83862 6.77200 6.68084 - 6.57219 6.45650 6.34542 6.24243 6.14795 6.06152 - 5.98270 5.91040 5.84455 5.78403 5.72822 5.67893 - 5.63746 5.61705 5.58915 5.56228 5.54927 5.54925 - 5.56714 5.56398 5.54459 5.54301 5.56622 5.56557 - 7.65170 7.52159 7.38341 7.24726 7.11312 6.98100 - 6.85105 6.72356 6.59842 6.47650 6.35861 6.24470 - 6.13597 6.03281 5.93620 5.84746 5.76766 5.69594 - 5.63398 5.61007 5.59333 5.58063 5.53161 5.51190 - 5.53442 5.53506 5.51778 5.51695 5.54014 5.53710 - 8.14019 7.96104 7.77443 7.59215 7.41406 7.24026 - 7.07093 6.90629 6.74660 6.59276 6.44582 6.30572 - 6.17393 6.05136 5.93908 5.83858 5.75056 5.67167 - 5.60048 5.57043 5.54569 5.52404 5.46104 5.43638 - 5.45744 5.46052 5.44793 5.44651 5.46224 5.45970 - 8.52831 8.30563 8.07636 7.85373 7.63747 7.42771 - 7.22462 7.02823 6.83916 6.65843 6.48696 6.32481 - 6.17346 6.03438 5.90855 5.79761 5.70199 5.61662 - 5.53809 5.50373 5.47382 5.44665 5.37398 5.34450 - 5.36052 5.36622 5.36072 5.35875 5.36415 5.36230 - 8.96726 8.84061 8.59674 8.28696 7.95705 7.64880 - 7.36779 7.11240 6.88128 6.67241 6.48092 6.30287 - 6.13794 5.98658 5.84713 5.71689 5.59203 5.46683 - 5.34681 5.29714 5.25109 5.21511 5.17416 5.16230 - 5.14055 5.14178 5.15350 5.15414 5.13863 5.13928 - 9.39606 9.20597 8.89513 8.52037 8.13103 7.77093 - 7.44512 7.15129 6.88707 6.64943 6.43185 6.22947 - 6.04180 5.86944 5.71089 5.56313 5.42161 5.27793 - 5.13996 5.08521 5.03531 4.99607 4.94923 4.93496 - 4.90514 4.90736 4.92522 4.92621 4.90296 4.90392 - 10.10917 9.75531 9.30061 8.80345 8.31055 7.86110 - 7.45757 7.09669 6.77476 6.48510 6.21808 5.96742 - 5.73407 5.51924 5.32239 5.13863 4.96387 4.79421 - 4.63293 4.56050 4.49122 4.43741 4.38066 4.36547 - 4.34536 4.34540 4.35248 4.35281 4.34265 4.34300 - 10.66326 10.01358 9.40019 8.83541 8.31469 7.83502 - 7.39365 6.98871 6.61925 6.28237 5.97446 5.69150 - 5.42838 5.18210 4.95406 4.74393 4.55040 4.36750 - 4.19037 4.10418 4.01780 3.94903 3.88495 3.87501 - 3.86893 3.86485 3.85627 3.85658 3.86657 3.86586 - 11.12142 10.35083 9.59298 8.87701 8.22179 7.64302 - 7.13413 6.68262 6.27714 5.90872 5.56756 5.24753 - 4.94809 4.66885 4.40872 4.16507 3.93522 3.72300 - 3.52549 3.42696 3.32979 3.25540 3.18497 3.16854 - 3.16202 3.15903 3.15107 3.15049 3.15862 3.15807 - 11.49382 10.48877 9.60293 8.81995 8.12482 7.50654 - 6.95746 6.46716 6.02598 5.62740 5.26517 4.93230 - 4.62009 4.32281 4.04104 3.77665 3.53020 3.29882 - 3.08292 2.98180 2.88407 2.80898 2.73452 2.71571 - 2.69823 2.69689 2.69808 2.69812 2.69473 2.69478 - 11.71824 10.59932 9.63526 8.79243 8.05315 7.40220 - 6.82837 6.31820 5.85882 5.44275 5.06385 4.71532 - 4.38883 4.07887 3.78561 3.51021 3.25356 3.01251 - 2.78690 2.68108 2.57957 2.50223 2.42546 2.40617 - 2.38770 2.38641 2.38824 2.38833 2.38404 2.38437 - 11.87984 10.68301 9.66759 8.78439 8.01485 7.34136 - 6.74952 6.22394 5.75016 5.32026 4.92820 4.56737 - 4.22989 3.91045 3.60904 3.32638 3.06309 2.81595 - 2.58319 2.47314 2.36710 2.28624 2.20762 2.18836 - 2.17198 2.17033 2.16997 2.16989 2.16816 2.16854 - 12.09782 10.81084 9.74019 8.81185 8.00704 7.30651 - 6.69160 6.14483 5.65068 5.20114 4.79032 4.41200 - 4.05884 3.72593 3.41280 3.11957 2.84574 2.58799 - 2.34225 2.22444 2.11034 2.02314 1.93968 1.91962 - 1.90503 1.90292 1.89996 1.89967 1.90101 1.90103 - 12.23872 10.91037 9.81822 8.87093 8.05030 7.33607 - 6.70819 6.14851 5.64155 5.17953 4.75668 4.36690 - 4.00311 3.66046 3.33818 3.03587 2.75214 2.48270 - 2.22341 2.09783 1.97612 1.88289 1.79262 1.77057 - 1.75403 1.75184 1.74918 1.74891 1.74982 1.74935 - 12.44570 11.08163 9.98128 9.02469 8.19681 7.47167 - 6.83122 6.25831 5.73860 5.26431 4.82926 4.42676 - 4.04893 3.69043 3.35051 3.02880 2.72297 2.42562 - 2.13129 1.98441 1.83794 1.72210 1.60936 1.58110 - 1.55806 1.55547 1.55371 1.55347 1.55274 1.55241 - 12.56016 11.18612 10.09428 9.14519 8.32422 7.60178 - 6.96212 6.38959 5.87099 5.39809 4.96384 4.56025 - 4.17779 3.81020 3.45748 3.12051 2.79693 2.47627 - 2.14816 1.97871 1.80178 1.65597 1.51737 1.48366 - 1.45669 1.45326 1.44999 1.44958 1.44967 1.45062 - 12.67988 11.29318 10.22650 9.30944 8.51687 7.81910 - 7.20000 6.64325 6.13491 5.66754 5.23529 4.83155 - 4.44813 4.07865 3.72011 3.36833 3.01682 2.65389 - 2.26402 2.05217 1.82130 1.61962 1.41866 1.37652 - 1.35000 1.34523 1.33630 1.33535 1.33994 1.34250 - 12.72286 11.34261 10.30820 9.42478 8.65913 7.98496 - 7.38629 6.84685 6.35241 5.89582 5.47155 5.07312 - 4.69236 4.32264 3.96073 3.60185 3.23724 2.84891 - 2.41136 2.16181 1.87912 1.62556 1.37065 1.31897 - 1.29269 1.28718 1.27360 1.27213 1.28046 1.28311 - 12.72999 11.36383 10.36357 9.51078 8.76954 8.11621 - 7.53539 7.01111 6.52916 6.08270 5.66651 5.27439 - 4.89828 4.53148 4.17036 3.80943 3.43779 3.03218 - 2.55806 2.27779 1.95054 1.65213 1.34717 1.28453 - 1.25596 1.25009 1.23363 1.23166 1.24184 1.24368 - 12.72013 11.37103 10.40419 9.57821 8.85867 8.22343 - 7.65793 7.14663 6.67568 6.23850 5.83019 5.44473 - 5.07425 4.71200 4.35394 3.99380 3.61882 3.20124 - 2.69848 2.39279 2.02755 1.68915 1.33764 1.26334 - 1.23028 1.22410 1.20584 1.20346 1.21438 1.21513 - 12.68138 11.36784 10.46033 9.67890 8.99552 8.38998 - 7.84936 7.35928 6.90677 6.48581 6.09199 5.71973 - 5.36154 5.01066 4.66227 4.30859 3.93353 3.50175 - 2.95656 2.61043 2.18277 1.77700 1.34629 1.24731 - 1.19186 1.18496 1.17115 1.16974 1.17870 1.17628 - 12.52185 11.32812 10.51946 9.79643 9.14380 8.54957 - 8.00914 7.51698 7.06841 6.65834 6.28097 5.92893 - 5.59204 5.26094 4.92911 4.58553 4.20865 3.75315 - 3.15614 2.77848 2.32385 1.89192 1.38981 1.24729 - 1.15901 1.15635 1.15652 1.15382 1.14476 1.15095 - 12.52293 11.34702 10.58532 9.90298 9.28798 8.72983 - 8.22428 7.76618 7.35104 6.97380 6.62844 6.30691 - 5.99753 5.69006 5.37870 5.05388 4.69681 4.26636 - 3.67706 3.26198 2.69644 2.11785 1.44830 1.26506 - 1.15348 1.13901 1.11483 1.11167 1.11549 1.11449 - 12.46600 11.32627 10.61068 9.96726 9.38534 8.85619 - 8.37624 7.94115 7.54705 7.18958 6.86343 6.56130 - 6.27233 5.98674 5.69854 5.39742 5.06220 4.64529 - 4.04918 3.61598 3.01162 2.36668 1.55057 1.30921 - 1.14403 1.12357 1.09811 1.09457 1.09638 1.09499 - 12.34967 11.27290 10.62849 10.04363 9.51031 9.02215 - 8.57681 8.17131 7.80312 7.46929 7.16628 6.88903 - 6.62981 6.38088 6.13596 5.88254 5.59277 5.20020 - 4.58769 4.13187 3.49722 2.79152 1.77914 1.43938 - 1.14015 1.10402 1.08339 1.07964 1.06684 1.07454 - 12.33418 11.27298 10.65257 10.08909 9.57564 9.10674 - 8.68028 8.29363 7.94451 7.63030 7.34771 7.09199 - 6.85556 6.63107 6.41305 6.19014 5.93581 5.58419 - 5.01094 4.56379 3.91178 3.14687 1.96859 1.55245 - 1.16087 1.10683 1.07089 1.06667 1.05698 1.06388 - 12.32852 11.27771 10.67119 10.12023 9.61889 9.16227 - 8.74830 8.37459 8.03898 7.73902 7.47165 7.23218 - 7.01308 6.80723 6.60994 6.41107 6.18585 5.87065 - 5.33888 4.90788 4.25502 3.45402 2.14554 1.66160 - 1.18548 1.11443 1.06285 1.05795 1.05172 1.05737 - 12.31371 11.28312 10.69241 10.15317 9.66038 9.21033 - 8.80170 8.43301 8.10312 7.81032 7.55229 7.32553 - 7.12413 6.94113 6.76812 6.58666 6.36830 6.06555 - 5.57474 5.18177 4.57755 3.78408 2.31960 1.74735 - 1.19474 1.11829 1.06580 1.05840 1.05427 1.05299 - 12.29637 11.29035 10.71543 10.18812 9.70563 9.26618 - 8.86879 8.51232 8.19595 7.91786 7.67554 7.46574 - 7.28397 7.12459 6.97990 6.83196 6.65325 6.39869 - 5.96685 5.60639 5.03001 4.23134 2.63593 1.95466 - 1.23881 1.13627 1.06316 1.05624 1.04622 1.04748 - 12.28593 11.29297 10.72754 10.20983 9.73637 9.30493 - 8.91479 8.56539 8.25657 7.98718 7.75542 7.55844 - 7.39093 7.24710 7.12072 6.99644 6.84913 6.63373 - 6.25053 5.92055 5.37905 4.59590 2.91014 2.14408 - 1.28802 1.15659 1.06317 1.05508 1.04169 1.04412 - 12.27298 11.30408 10.74930 10.24180 9.77847 9.35746 - 8.97800 8.63960 8.34223 8.08511 7.86719 7.68667 - 7.53976 7.42238 7.33024 7.25045 7.16054 7.01656 - 6.72172 6.44510 5.96541 5.24112 3.50442 2.56650 - 1.39801 1.21333 1.07041 1.05443 1.04071 1.03959 - 12.25215 11.31006 10.75995 10.25726 9.79901 9.38358 - 9.01018 8.67834 8.38810 8.13880 7.92968 7.75925 - 7.62416 7.52100 7.44653 7.38949 7.33033 7.23099 - 7.00603 6.78050 6.36787 5.70183 3.94358 2.91118 - 1.51628 1.27969 1.07924 1.05634 1.03532 1.03732 - 12.19183 11.31743 10.77349 10.27575 9.82202 9.41128 - 9.04302 8.71719 8.43404 8.19286 7.99265 7.83213 - 7.70921 7.62194 7.56838 7.53926 7.51991 7.48462 - 7.35824 7.19278 6.84688 6.26124 4.62633 3.49798 - 1.72348 1.40015 1.10176 1.06653 1.03588 1.03502 - 12.13779 11.31991 10.77965 10.28455 9.83331 9.42543 - 9.06042 8.73798 8.45821 8.22070 8.02496 7.87012 - 7.75407 7.67517 7.63246 7.61848 7.62127 7.61951 - 7.55100 7.43251 7.15131 6.63643 5.09631 3.94987 - 1.92310 1.51938 1.12590 1.07620 1.03625 1.03386 - 12.09832 11.32118 10.78334 10.28985 9.84005 9.43393 - 9.07089 8.75056 8.47284 8.23763 8.04470 7.89337 - 7.78158 7.70783 7.67186 7.66744 7.68449 7.70461 - 7.67529 7.59063 7.35960 6.90288 5.45302 4.31581 - 2.10865 1.63343 1.15079 1.08647 1.03755 1.03316 - 12.07226 11.31993 10.78350 10.29275 9.84582 9.44167 - 9.07985 8.76027 8.48323 8.24885 8.05715 7.90779 - 7.79910 7.72987 7.69983 7.70238 7.72803 7.76263 - 7.76255 7.70337 7.51097 7.10156 5.73554 4.62049 - 2.28736 1.74020 1.17356 1.09958 1.03927 1.03270 - 12.03851 11.32081 10.78607 10.29701 9.85159 9.44905 - 9.08888 8.77112 8.49605 8.26390 8.07477 7.92847 - 7.82347 7.75889 7.73495 7.74595 7.78406 7.83883 - 7.87663 7.85179 7.71707 7.38459 6.16130 5.09351 - 2.61239 1.94658 1.22347 1.12170 1.04318 1.03211 - 12.01607 11.32360 10.79002 10.30006 9.85367 9.45124 - 9.09227 8.77638 8.50353 8.27370 8.08695 7.94289 - 7.83982 7.77696 7.75544 7.77141 7.81885 7.88733 - 7.94678 7.94321 7.85222 7.58046 6.46205 5.45811 - 2.89810 2.13655 1.27550 1.14156 1.04891 1.03175 - 11.98428 11.32450 10.79217 10.30337 9.85828 9.45714 - 9.09948 8.78511 8.51406 8.28632 8.10182 7.96023 - 7.86019 7.80124 7.78493 7.80801 7.86594 7.95222 - 8.04466 8.07221 8.04406 7.86979 6.96192 6.08691 - 3.49471 2.55284 1.39584 1.20155 1.06218 1.03129 - 11.96605 11.32504 10.79330 10.30518 9.86071 9.46019 - 9.10318 8.78952 8.51930 8.29254 8.10917 7.96893 - 7.87052 7.81364 7.80006 7.82682 7.89017 7.98595 - 8.09600 8.13980 8.14557 8.02999 7.27209 6.49808 - 3.96162 2.90863 1.51137 1.26350 1.07546 1.03106 - 11.94652 11.32547 10.79453 10.30709 9.86324 9.46332 - 9.10697 8.79399 8.52450 8.29857 8.11629 7.97744 - 7.88076 7.82602 7.81518 7.84568 7.91468 8.02042 - 8.14890 8.20948 8.24960 8.20017 7.64408 7.01426 - 4.65487 3.48001 1.72690 1.38672 1.10158 1.03083 - 11.95749 11.33208 10.79334 10.30295 9.85902 9.46031 - 9.10582 8.79496 8.52736 8.30296 8.12154 7.98238 - 7.88299 7.82333 7.80935 7.84743 7.93888 8.06085 - 8.18307 8.24162 8.29265 8.28280 7.87260 7.32435 - 5.14174 3.92924 1.92649 1.50758 1.12600 1.03072 - 11.95039 11.33192 10.79365 10.30348 9.85988 9.46141 - 9.10715 8.79648 8.52910 8.30490 8.12375 7.98490 - 7.88595 7.82695 7.81387 7.85325 7.94655 8.07129 - 8.19877 8.26301 8.32611 8.33896 8.01056 7.53984 - 5.51173 4.28761 2.12344 1.62422 1.15071 1.03065 - 11.94540 11.33168 10.79365 10.30380 9.86038 9.46209 - 9.10798 8.79746 8.53023 8.30620 8.12523 7.98662 - 7.88799 7.82939 7.81691 7.85711 7.95166 8.07833 - 8.20946 8.27752 8.34855 8.37682 8.10817 7.69536 - 5.80171 4.58667 2.30644 1.73903 1.17512 1.03061 - 11.91843 11.32493 10.79506 10.30883 9.86613 9.46721 - 9.11174 8.79969 8.53130 8.30661 8.12564 7.98818 - 7.89333 7.84115 7.83392 7.86949 7.94597 8.06381 - 8.21729 8.30210 8.38436 8.42444 8.23737 7.90520 - 6.23319 5.06245 2.63417 1.96606 1.22421 1.03054 - 11.91505 11.32440 10.79466 10.30865 9.86632 9.46750 - 9.11197 8.79986 8.53160 8.30723 8.12663 7.98958 - 7.89514 7.84337 7.83657 7.87257 7.94964 8.06904 - 8.22549 8.31293 8.40245 8.45535 8.31630 8.04026 - 6.54120 5.43055 2.92098 2.16922 1.27209 1.03049 - 0.94543 0.98447 1.02402 1.06426 1.10514 1.14665 - 1.18885 1.23191 1.27611 1.32162 1.36859 1.41743 - 1.46893 1.52306 1.57708 1.62455 1.65920 1.68350 - 1.70178 1.71015 1.72291 1.73619 1.74124 1.74203 - 1.74408 1.74397 1.74361 1.74406 1.74411 1.74425 - 1.30099 1.34474 1.38971 1.43633 1.48460 1.53453 - 1.58605 1.63909 1.69351 1.74912 1.80556 1.86236 - 1.91882 1.97401 2.02664 2.07504 2.11731 2.15252 - 2.17701 2.18149 2.17784 2.17192 2.19458 2.21131 - 2.20654 2.20284 2.20295 2.20407 2.20357 2.20456 - 1.61620 1.66611 1.71702 1.76954 1.82364 1.87929 - 1.93637 1.99474 2.05420 2.11448 2.17513 2.23552 - 2.29483 2.35194 2.40539 2.45336 2.49403 2.52714 - 2.55017 2.55454 2.55160 2.54724 2.57246 2.58951 - 2.58261 2.57866 2.57939 2.58056 2.57951 2.58057 - 2.14815 2.21564 2.28194 2.34776 2.41279 2.47674 - 2.53938 2.60055 2.66019 2.71813 2.77436 2.82904 - 2.88313 2.93705 2.98916 3.03615 3.07458 3.10403 - 3.12647 3.13669 3.14712 3.15563 3.16350 3.16478 - 3.16498 3.16536 3.16611 3.16599 3.16509 3.16520 - 2.58471 2.67346 2.75617 2.83350 2.90500 2.97063 - 3.03088 3.08715 3.14152 3.19436 3.24567 3.29542 - 3.34418 3.39201 3.43741 3.47755 3.51007 3.53689 - 3.56046 3.57137 3.58365 3.59444 3.60279 3.60398 - 3.60126 3.60262 3.60456 3.60276 3.60220 3.60173 - 2.95852 3.06574 3.16206 3.24806 3.32321 3.38770 - 3.44284 3.49164 3.53818 3.58342 3.62740 3.67008 - 3.71180 3.75252 3.79088 3.82435 3.85112 3.87411 - 3.89713 3.90921 3.92297 3.93483 3.94368 3.94463 - 3.94021 3.94203 3.94470 3.94216 3.94138 3.94074 - 3.28623 3.40812 3.51468 3.60644 3.68280 3.74425 - 3.79290 3.83312 3.87087 3.90755 3.94330 3.97809 - 4.01216 4.04547 4.07677 4.10378 4.12505 4.14422 - 4.16609 4.17873 4.19315 4.20538 4.21442 4.21525 - 4.21004 4.21206 4.21504 4.21217 4.21130 4.21060 - 3.84168 3.98141 4.09871 4.19430 4.26761 4.31969 - 4.35386 4.37661 4.39649 4.41564 4.43434 4.45281 - 4.47134 4.49007 4.50809 4.52346 4.53520 4.54750 - 4.56588 4.57797 4.59140 4.60233 4.61100 4.61193 - 4.60740 4.60920 4.61186 4.60932 4.60855 4.60794 - 4.30195 4.44778 4.56614 4.65824 4.72370 4.76404 - 4.78340 4.78960 4.79267 4.79521 4.79766 4.80057 - 4.80446 4.80980 4.81598 4.82132 4.82511 4.83136 - 4.84525 4.85534 4.86579 4.87369 4.88131 4.88257 - 4.88040 4.88150 4.88310 4.88163 4.88121 4.88087 - 5.17949 5.34346 5.44691 5.50073 5.51876 5.51743 - 5.50272 5.48045 5.45752 5.43348 5.40519 5.37214 - 5.33994 5.31364 5.29347 5.27794 5.26645 5.26249 - 5.26448 5.26370 5.26296 5.26346 5.26635 5.26806 - 5.27323 5.27245 5.27080 5.27194 5.27326 5.27356 - 5.85393 5.95953 6.02704 6.06145 6.06386 6.03748 - 5.98843 5.92652 5.86376 5.80332 5.74622 5.69320 - 5.64519 5.60285 5.56629 5.53447 5.50689 5.48558 - 5.47242 5.46713 5.45674 5.44499 5.44340 5.44573 - 5.45721 5.45403 5.44923 5.45417 5.45576 5.45698 - 6.80461 6.84093 6.83730 6.80239 6.73860 6.65025 - 6.54429 6.43107 6.32222 6.22120 6.12845 6.04364 - 5.96644 5.89590 5.83202 5.77376 5.72050 5.67391 - 5.63498 5.61572 5.58880 5.56254 5.55099 5.55244 - 5.56946 5.56408 5.55610 5.56413 5.56669 5.56866 - 7.61180 7.48434 7.34907 7.21576 7.08439 6.95495 - 6.82762 6.70265 6.57996 6.46040 6.34479 6.23308 - 6.12643 6.02525 5.93054 5.84361 5.76558 5.69569 - 5.63580 5.61305 5.59763 5.58614 5.53831 5.51816 - 5.53986 5.54358 5.53496 5.53477 5.54842 5.54460 - 8.10379 7.92761 7.74422 7.56505 7.38995 7.21904 - 7.05247 6.89048 6.73333 6.58192 6.43727 6.29935 - 6.16961 6.04897 5.93849 5.83969 5.75330 5.67608 - 5.60676 5.57777 5.55419 5.53358 5.47158 5.44668 - 5.46732 5.47232 5.46512 5.46410 5.47392 5.47088 - 8.49513 8.27568 8.04996 7.83070 7.61764 7.41095 - 7.21075 7.01713 6.83068 6.65240 6.48323 6.32323 - 6.17389 6.03665 5.91253 5.80317 5.70903 5.62518 - 5.54835 5.51494 5.48607 5.45984 5.38804 5.35862 - 5.37463 5.38069 5.37622 5.37434 5.37870 5.37673 - 8.93960 8.81613 8.57657 8.27123 7.94543 7.64066 - 7.36263 7.10984 6.88117 6.67457 6.48515 6.30897 - 6.14570 5.99581 5.85771 5.72888 5.60561 5.48215 - 5.36398 5.31524 5.26998 5.23458 5.19402 5.18153 - 5.16133 5.16265 5.16655 5.16332 5.15969 5.15897 - 9.37292 9.18651 8.88044 8.51046 8.12541 7.76886 - 7.44601 7.15479 6.89303 6.65771 6.44222 6.24164 - 6.05550 5.88443 5.72703 5.58050 5.44044 5.29825 - 5.16178 5.10787 5.05872 5.02005 4.97338 4.95805 - 4.93032 4.93270 4.93887 4.93404 4.92857 4.92744 - 10.09402 9.74481 9.29557 8.80342 8.31486 7.86894 - 7.46832 7.11001 6.79045 6.50299 6.23789 5.98882 - 5.75674 5.54296 5.34705 5.16431 4.99079 4.82212 - 4.66150 4.58952 4.52064 4.46707 4.41020 4.39446 - 4.37504 4.37517 4.37723 4.37499 4.37250 4.37191 - 10.65301 10.00878 9.40089 8.84085 8.32423 7.84809 - 7.40975 7.00742 6.64015 6.30511 5.99878 5.71717 - 5.45526 5.21004 4.98294 4.77363 4.58082 4.39850 - 4.22175 4.13564 4.04925 3.98041 3.91606 3.90565 - 3.89892 3.89638 3.89217 3.89279 3.89786 3.89675 - 11.11626 10.35172 9.59952 8.88795 8.23633 7.66059 - 7.15425 6.70483 6.30103 5.93399 5.59413 5.27539 - 4.97715 4.69894 4.43967 4.19679 3.96757 3.75554 - 3.55750 3.45849 3.36084 3.28611 3.21548 3.19941 - 3.19215 3.18908 3.18527 3.18678 3.18860 3.18872 - 11.49059 10.49162 9.61123 8.83246 8.14063 7.52499 - 6.97794 6.48932 6.04955 5.65221 5.29113 4.95934 - 4.64817 4.35189 4.07105 3.80737 3.56132 3.32995 - 3.11351 3.01190 2.91361 2.83811 2.76354 2.74459 - 2.72732 2.72629 2.72587 2.72460 2.72409 2.72378 - 11.71519 10.60248 9.64367 8.80479 8.06855 7.41994 - 6.84790 6.33916 5.88103 5.46608 5.08823 4.74069 - 4.41515 4.10608 3.81361 3.53885 3.28265 3.04172 - 2.81580 2.70961 2.60755 2.52974 2.45284 2.43337 - 2.41509 2.41420 2.41402 2.41242 2.41177 2.41174 - 11.87601 10.68543 9.67513 8.79577 8.02910 7.35779 - 6.76760 6.24333 5.77073 5.34191 4.95084 4.59095 - 4.25433 3.93567 3.63494 3.35289 3.09012 2.84328 - 2.61047 2.50018 2.39364 2.31224 2.23343 2.21407 - 2.19769 2.19620 2.19511 2.19438 2.19399 2.19436 - 12.09154 10.81097 9.74512 8.82043 8.01835 7.31988 - 6.70654 6.16106 5.66806 5.21962 4.80982 4.43242 - 4.08007 3.74782 3.43526 3.14260 2.86938 2.61212 - 2.36662 2.24875 2.13431 2.04663 1.96273 1.94262 - 1.92778 1.92552 1.92334 1.92366 1.92361 1.92385 - 12.22963 10.90750 9.82010 8.87642 8.05852 7.34636 - 6.72012 6.16183 5.65613 5.19527 4.77351 4.38470 - 4.02175 3.67979 3.35809 3.05635 2.77323 2.50431 - 2.24533 2.11981 1.99796 1.90439 1.81345 1.79123 - 1.77446 1.77213 1.77000 1.77018 1.77011 1.76959 - 12.42899 11.07183 9.97629 9.02342 8.19836 7.47544 - 6.83680 6.26546 5.74720 5.27426 4.84052 4.43922 - 4.06250 3.70499 3.36592 3.04492 2.73967 2.44286 - 2.14900 2.00230 1.85588 1.73991 1.62666 1.59819 - 1.57508 1.57252 1.57047 1.57003 1.56977 1.56925 - 12.53633 11.17040 10.08392 9.13884 8.32078 7.60058 - 6.96272 6.39174 5.87464 5.40324 4.97044 4.56833 - 4.18730 3.82108 3.46958 3.13356 2.81063 2.49061 - 2.16325 1.99407 1.81715 1.67121 1.53284 1.49924 - 1.47223 1.46877 1.46575 1.46549 1.46519 1.46659 - 12.64476 11.26894 10.20877 9.29621 8.50658 7.81087 - 7.19328 6.63791 6.13108 5.66540 5.23499 4.83315 - 4.45162 4.08391 3.72702 3.37669 3.02643 2.66457 - 2.27560 2.06414 1.83361 1.63237 1.43259 1.39075 - 1.36405 1.36009 1.35337 1.35249 1.35452 1.35831 - 12.68041 11.31295 10.28582 9.40712 8.64444 7.97215 - 7.37473 6.83642 6.34343 5.88862 5.46638 5.07014 - 4.69157 4.32396 3.96401 3.60690 3.24381 2.85687 - 2.42063 2.17171 1.88971 1.63696 1.38393 1.33263 - 1.30597 1.30186 1.29211 1.29075 1.29462 1.29888 - 12.68294 11.33074 10.33811 9.49016 8.75189 8.10031 - 7.52056 6.99722 6.51664 6.07197 5.65794 5.26816 - 4.89440 4.52986 4.17088 3.81189 3.44201 3.03806 - 2.56563 2.28624 1.95995 1.66259 1.35990 1.29772 - 1.26873 1.26455 1.25266 1.25083 1.25569 1.25916 - 12.67013 11.33576 10.37664 9.55555 8.83893 8.20534 - 7.64078 7.13032 6.66065 6.22525 5.81908 5.43603 - 5.06798 4.70807 4.35224 3.99417 3.62113 3.20547 - 2.70472 2.40012 2.03603 1.69887 1.34988 1.27611 - 1.24270 1.23830 1.22486 1.22262 1.22795 1.23022 - 12.62821 11.33006 10.43029 9.65359 8.97304 8.36903 - 7.82918 7.33976 6.88841 6.46917 6.07747 5.70763 - 5.35190 5.00337 4.65724 4.30570 3.93277 3.50323 - 2.96063 2.61602 2.19012 1.78596 1.35725 1.25867 - 1.20462 1.19949 1.18896 1.18733 1.19246 1.19055 - 12.47429 11.29022 10.48546 9.76591 9.11625 8.52463 - 7.98653 7.49647 7.04982 6.64149 6.26578 5.91535 - 5.58011 5.25078 4.92087 4.57943 4.20502 3.75242 - 3.15881 2.78307 2.33046 1.90012 1.39966 1.25790 - 1.17195 1.17067 1.17290 1.17003 1.15881 1.16452 - 12.47478 11.30879 10.55058 9.87126 9.25888 8.70306 - 8.19956 7.74328 7.32977 6.95400 6.61001 6.28982 - 5.98186 5.67594 5.36636 5.04368 4.68926 4.26230 - 3.67734 3.26428 2.70004 2.12272 1.45768 1.27609 - 1.16445 1.15032 1.13010 1.12861 1.12652 1.12684 - 12.41906 11.28906 10.57645 9.93556 9.35591 8.82879 - 8.35064 7.91714 7.52448 7.16831 6.84336 6.54241 - 6.25468 5.97045 5.68385 5.38467 5.05198 4.63853 - 4.04697 3.61610 3.01352 2.37032 1.55889 1.31914 - 1.15465 1.13451 1.11176 1.10939 1.10708 1.10657 - 12.30501 11.23766 10.59563 10.01278 9.48125 8.99469 - 8.55077 8.14653 7.77945 7.44664 7.14455 6.86822 - 6.60999 6.36222 6.11866 5.86691 5.57929 5.18957 - 4.58103 4.12783 3.49647 2.79408 1.78598 1.44748 - 1.15026 1.11479 1.09492 1.09110 1.07759 1.08523 - 12.29143 11.23934 10.62087 10.05903 9.54706 9.07949 - 8.65420 8.26859 7.92040 7.60702 7.32520 7.07024 - 6.83462 6.61107 6.39418 6.17269 5.92020 5.57112 - 5.00160 4.55706 3.90854 3.14742 1.97445 1.55990 - 1.17039 1.11689 1.08150 1.07723 1.06708 1.07409 - 12.28718 11.24525 10.64034 10.09080 9.59071 9.13523 - 8.72228 8.34946 8.01466 7.71544 7.44872 7.20990 - 6.99149 6.78644 6.59010 6.39239 6.16875 5.85578 - 5.32746 4.89901 4.24973 3.45284 2.15052 1.66852 - 1.19461 1.12404 1.07292 1.06799 1.06142 1.06727 - 12.27342 11.25161 10.66241 10.12434 9.63261 9.18348 - 8.77567 8.40772 8.07856 7.78647 7.52912 7.30302 - 7.10227 6.91994 6.74763 6.56701 6.34982 6.04902 - 5.56179 5.17159 4.57114 3.78169 2.32304 1.75335 - 1.20388 1.12783 1.07540 1.06796 1.06386 1.06268 - 12.25803 11.25970 10.68569 10.15949 9.67810 9.23963 - 8.84311 8.48739 8.17165 7.89409 7.65221 7.44286 - 7.26154 7.10262 6.95846 6.81111 6.63321 6.38013 - 5.95133 5.59349 5.02088 4.22643 2.63791 1.95986 - 1.24745 1.14531 1.07239 1.06545 1.05557 1.05690 - 12.24784 11.26285 10.69823 10.18148 9.70891 9.27837 - 8.88913 8.54054 8.23240 7.96354 7.73220 7.53551 - 7.36829 7.22470 7.09861 6.97471 6.82804 6.61386 - 6.23322 5.90553 5.36770 4.58909 2.91092 2.14837 - 1.29628 1.16533 1.07223 1.06414 1.05087 1.05337 - 12.23480 11.27382 10.72004 10.21369 9.75136 9.33129 - 8.95271 8.61506 8.31828 8.06160 7.84399 7.66365 - 7.51685 7.39952 7.30741 7.22774 7.13811 6.99476 - 6.70148 6.42660 5.95024 5.23079 3.50283 2.56875 - 1.40545 1.22156 1.07935 1.06336 1.04966 1.04861 - 12.21382 11.27953 10.73072 10.22928 9.77211 9.35762 - 8.98505 8.65390 8.36420 8.11535 7.90652 7.73627 - 7.60126 7.49807 7.42352 7.36640 7.30722 7.20817 - 6.98430 6.76017 6.35030 5.68855 3.93977 2.91223 - 1.52312 1.28742 1.08807 1.06533 1.04410 1.04624 - 12.15404 11.28694 10.74458 10.24790 9.79514 9.38531 - 9.01790 8.69279 8.41021 8.16950 7.96966 7.80942 - 7.68662 7.59921 7.54532 7.51590 7.49642 7.46113 - 7.33512 7.17034 6.82627 6.24436 4.61962 3.49642 - 1.72916 1.40719 1.11040 1.07539 1.04457 1.04382 - 12.10116 11.28943 10.75066 10.25671 9.80644 9.39943 - 9.03522 8.71352 8.43439 8.19746 8.00217 7.84758 - 7.73160 7.65261 7.60965 7.59534 7.59782 7.59577 - 7.52723 7.40912 7.12915 6.61721 5.08706 3.94628 - 1.92784 1.52585 1.13433 1.08490 1.04488 1.04260 - 12.06259 11.29070 10.75426 10.26192 9.81319 9.40796 - 9.04570 8.72609 8.44908 8.21449 8.02203 7.87096 - 7.75922 7.68544 7.64927 7.64454 7.66116 7.68082 - 7.65123 7.56672 7.33650 6.88213 5.44170 4.31048 - 2.11257 1.63941 1.15905 1.09505 1.04613 1.04187 - 12.03621 11.29157 10.75652 10.26542 9.81777 9.41374 - 9.05280 8.73461 8.45911 8.22618 8.03568 7.88700 - 7.77816 7.70792 7.67645 7.67831 7.70478 7.73973 - 7.73803 7.67842 7.48771 7.08167 5.72199 4.61203 - 2.28776 1.74838 1.18402 1.10550 1.04791 1.04138 - 12.00297 11.29256 10.75930 10.26969 9.82355 9.42114 - 9.06194 8.74562 8.47213 8.24144 8.05351 7.90786 - 7.80270 7.73706 7.71167 7.72208 7.76124 7.81633 - 7.85163 7.82587 7.69366 7.36445 6.14124 5.08586 - 2.61170 1.95299 1.23391 1.12715 1.05233 1.04076 - 11.98222 11.29306 10.76085 10.27225 9.82705 9.42564 - 9.06750 8.75234 8.48014 8.25090 8.06459 7.92076 - 7.81783 7.75504 7.73344 7.74911 7.79603 7.86377 - 7.92249 7.91860 7.82746 7.55641 6.44432 5.44643 - 2.89857 2.14068 1.28320 1.14984 1.05731 1.04038 - 11.95082 11.29386 10.76291 10.27557 9.83175 9.43170 - 9.07496 8.76134 8.49091 8.26366 8.07954 7.93821 - 7.83834 7.77949 7.76319 7.78601 7.84342 7.92894 - 8.02053 8.04762 8.01902 7.84479 6.94105 6.07136 - 3.49263 2.55544 1.40306 1.20953 1.07052 1.03989 - 11.93283 11.29431 10.76404 10.27738 9.83419 9.43478 - 9.07869 8.76580 8.49621 8.26993 8.08696 7.94697 - 7.84875 7.79201 7.77843 7.80498 7.86785 7.96291 - 8.07207 8.11537 8.12055 8.00466 7.24948 6.48010 - 3.95763 2.90974 1.51804 1.27108 1.08380 1.03964 - 11.91345 11.29474 10.76527 10.27929 9.83668 9.43787 - 9.08242 8.77021 8.50137 8.27601 8.09416 7.95559 - 7.85911 7.80451 7.79368 7.82399 7.89255 7.99763 - 8.12530 8.18535 8.22479 8.17475 7.61976 6.99339 - 4.64791 3.47863 1.73252 1.39355 1.10996 1.03941 - 11.92461 11.30155 10.76429 10.27515 9.83238 9.43473 - 9.08118 8.77111 8.50423 8.28039 8.09942 7.96059 - 7.86142 7.80186 7.78783 7.82572 7.91677 8.03819 - 8.15967 8.21771 8.26803 8.25745 7.84750 7.30190 - 5.13240 3.92574 1.93131 1.51384 1.13434 1.03929 - 11.91792 11.30150 10.76459 10.27578 9.83326 9.43582 - 9.08248 8.77262 8.50593 8.28232 8.10162 7.96315 - 7.86444 7.80552 7.79241 7.83158 7.92451 8.04871 - 8.17548 8.23924 8.30168 8.31377 7.98505 7.51639 - 5.50040 4.28218 2.12722 1.62998 1.15900 1.03923 - 11.91322 11.30146 10.76470 10.27611 9.83378 9.43649 - 9.08330 8.77357 8.50704 8.28359 8.10309 7.96483 - 7.86645 7.80797 7.79546 7.83547 7.92966 8.05578 - 8.18625 8.25384 8.32424 8.35180 8.08251 7.67126 - 5.78860 4.57955 2.30932 1.74438 1.18336 1.03919 - 11.88646 11.29461 10.76600 10.28104 9.83952 9.44167 - 9.08716 8.77592 8.50821 8.28408 8.10357 7.96651 - 7.87187 7.81974 7.81238 7.84774 7.92400 8.04146 - 8.19425 8.27861 8.36023 8.39958 8.21163 7.88002 - 6.21734 5.05260 2.63548 1.97029 1.23220 1.03913 - 11.88234 11.29408 10.76581 10.28105 9.83975 9.44200 - 9.08752 8.77630 8.50869 8.28478 8.10457 7.96789 - 7.87368 7.82197 7.81504 7.85083 7.92769 8.04671 - 8.20253 8.28957 8.37857 8.43075 8.29051 8.01476 - 6.52352 5.41856 2.92087 2.17248 1.27979 1.03910 - 0.92096 0.95873 0.99716 1.03645 1.07657 1.11753 - 1.15935 1.20219 1.24627 1.29175 1.33880 1.38785 - 1.43970 1.49438 1.54925 1.59803 1.63391 1.65653 - 1.67256 1.68299 1.69568 1.70631 1.71117 1.71169 - 1.71330 1.71323 1.71241 1.71241 1.71358 1.71349 - 1.27253 1.31575 1.36022 1.40635 1.45417 1.50367 - 1.55482 1.60753 1.66170 1.71714 1.77350 1.83033 - 1.88697 1.94250 1.99564 2.04469 2.08773 2.12352 - 2.14797 2.15195 2.14720 2.13981 2.16060 2.17703 - 2.17265 2.16864 2.16761 2.16860 2.16926 2.17035 - 1.58444 1.63397 1.68455 1.73676 1.79059 1.84600 - 1.90290 1.96115 2.02055 2.08083 2.14158 2.20217 - 2.26179 2.31933 2.37332 2.42193 2.46325 2.49679 - 2.51959 2.52336 2.51927 2.51347 2.53722 2.55414 - 2.54750 2.54336 2.54339 2.54449 2.54409 2.54523 - 2.10753 2.17687 2.24463 2.31142 2.37696 2.44099 - 2.50331 2.56398 2.62319 2.68090 2.73717 2.79235 - 2.84764 2.90354 2.95800 3.00656 3.04480 3.07311 - 3.09426 3.10356 3.11313 3.12121 3.12926 3.13039 - 3.13023 3.13091 3.13260 3.13257 3.13058 3.13064 - 2.54215 2.63097 2.71388 2.79145 2.86330 2.92938 - 2.99023 3.04732 3.10279 3.15697 3.20978 3.26103 - 3.31094 3.35938 3.40507 3.44591 3.47995 3.50768 - 3.52972 3.53904 3.55020 3.56115 3.57095 3.57206 - 3.56892 3.56982 3.57441 3.57477 3.56944 3.56958 - 2.91585 3.02045 3.11513 3.20048 3.27598 3.34176 - 3.39899 3.45030 3.49943 3.54709 3.59320 3.63749 - 3.67999 3.72053 3.75831 3.79230 3.82161 3.84669 - 3.86831 3.87850 3.89110 3.90358 3.91469 3.91555 - 3.91063 3.91181 3.91813 3.91861 3.91122 3.91144 - 3.24388 3.36087 3.46422 3.55456 3.63131 3.69481 - 3.74678 3.79096 3.83246 3.87237 3.91067 3.94712 - 3.98171 4.01437 4.04463 4.07210 4.09653 4.11858 - 4.13931 4.15003 4.16341 4.17659 4.18828 4.18904 - 4.18329 4.18459 4.19168 4.19224 4.18392 4.18416 - 3.79996 3.93202 4.04431 4.13768 4.21156 4.26671 - 4.30582 4.33426 4.35923 4.38241 4.40399 4.42410 - 4.44301 4.46111 4.47821 4.49423 4.50937 4.52496 - 4.54301 4.55375 4.56669 4.57882 4.58999 4.59086 - 4.58586 4.58703 4.59335 4.59383 4.58644 4.58668 - 4.26043 4.39783 4.51081 4.60068 4.66701 4.71095 - 4.73587 4.74830 4.75675 4.76337 4.76860 4.77307 - 4.77759 4.78302 4.78922 4.79565 4.80226 4.81130 - 4.82586 4.83559 4.84626 4.85528 4.86448 4.86572 - 4.86327 4.86400 4.86776 4.86804 4.86373 4.86389 - 5.14985 5.27818 5.37437 5.44136 5.47930 5.49032 - 5.47904 5.45372 5.42471 5.39481 5.36518 5.33718 - 5.31263 5.29306 5.27793 5.26486 5.25257 5.24559 - 5.24930 5.25428 5.25630 5.25472 5.25666 5.25879 - 5.26439 5.26373 5.25924 5.25888 5.26445 5.26431 - 5.81013 5.91467 5.98244 6.01821 6.02294 5.99962 - 5.95393 5.89523 5.83484 5.77605 5.72018 5.66858 - 5.62318 5.58513 5.55340 5.52424 5.49546 5.47336 - 5.46496 5.46388 5.45648 5.44432 5.43847 5.44095 - 5.45346 5.45152 5.43966 5.43873 5.45310 5.45269 - 6.75822 6.80312 6.80639 6.77646 6.71575 6.62879 - 6.52291 6.40908 6.29963 6.19840 6.10613 6.02296 - 5.94935 5.88448 5.82671 5.77121 5.71526 5.66684 - 5.63447 5.62109 5.59794 5.57028 5.55171 5.55332 - 5.57220 5.56883 5.54907 5.54751 5.57123 5.57052 - 7.58141 7.45594 7.32286 7.19169 7.06240 6.93497 - 6.80960 6.68652 6.56567 6.44790 6.33400 6.22392 - 6.11888 6.01926 5.92611 5.84079 5.76459 5.69705 - 5.64058 5.62009 5.60724 5.59724 5.54609 5.52412 - 5.54765 5.54863 5.53079 5.52988 5.55419 5.55085 - 8.07739 7.90337 7.72243 7.54557 7.37269 7.20390 - 7.03936 6.87930 6.72399 6.57431 6.43129 6.29492 - 6.16663 6.04734 5.93818 5.84070 5.75576 5.68043 - 5.61392 5.58685 5.56553 5.54646 5.48257 5.45639 - 5.47824 5.48151 5.46838 5.46691 5.48365 5.48089 - 8.47026 8.25335 8.03044 7.81382 7.60327 7.39894 - 7.20098 7.00947 6.82498 6.64854 6.48105 6.32261 - 6.17469 6.03874 5.91580 5.80753 5.71451 5.63205 - 5.55722 5.52520 5.49806 5.47328 5.40165 5.37179 - 5.38812 5.39384 5.38805 5.38608 5.39208 5.39014 - 8.91415 8.79105 8.55608 8.25712 7.93721 7.63596 - 7.35954 7.10759 6.88011 6.67546 6.48890 6.31591 - 6.15427 6.00339 5.86304 5.73394 5.61491 5.49819 - 5.38074 5.32692 5.28008 5.24883 5.21339 5.20072 - 5.17909 5.18054 5.19240 5.19301 5.17732 5.17802 - 9.35215 9.16661 8.86099 8.49181 8.10962 7.75898 - 7.44358 7.15892 6.90051 6.66624 6.45185 6.25346 - 6.06900 5.89787 5.73908 5.59100 5.45156 5.31673 - 5.18493 5.12344 5.06968 5.03539 4.99876 4.97904 - 4.95235 4.95641 4.97271 4.97203 4.94951 4.95072 - 10.21411 9.69147 9.18873 8.72015 8.28338 7.87645 - 7.49780 7.14694 6.82354 6.52650 6.25389 6.00311 - 5.77125 5.55705 5.36162 5.18382 5.02097 4.86093 - 4.69384 4.61193 4.54000 4.49278 4.44101 4.42411 - 4.40358 4.40401 4.41160 4.41180 4.40121 4.40142 - 10.64539 10.00181 9.39544 8.83706 8.32233 7.84830 - 7.41232 7.01258 6.64816 6.31627 6.01345 5.73578 - 5.47830 5.23798 5.01604 4.81170 4.62248 4.43930 - 4.25499 4.16477 4.07963 4.01623 3.94912 3.93505 - 3.93237 3.92943 3.91938 3.91877 3.92927 3.92874 - 11.16274 10.33131 9.57217 8.88507 8.26118 7.69559 - 7.18478 6.72381 6.30884 5.93520 5.59725 5.28875 - 5.00180 4.73100 4.47663 4.23913 4.01559 3.79942 - 3.58711 3.48560 3.39166 3.32292 3.24812 3.23062 - 3.22447 3.22183 3.21356 3.21306 3.22104 3.22056 - 11.48281 10.49426 9.62168 8.84809 8.15954 7.54584 - 6.99987 6.51201 6.07318 5.67697 5.31710 4.98647 - 4.67613 4.38023 4.09955 3.83623 3.59092 3.36002 - 3.14322 3.04127 2.94296 2.86788 2.79381 2.77463 - 2.75694 2.75561 2.75680 2.75683 2.75342 2.75346 - 11.70059 10.60776 9.66161 8.82952 8.09583 7.44695 - 6.87312 6.36244 5.90344 5.48869 5.11177 4.76547 - 4.44087 4.13213 3.83974 3.56539 3.31014 3.06983 - 2.84334 2.73661 2.63441 2.55705 2.48085 2.46109 - 2.44232 2.44105 2.44290 2.44298 2.43863 2.43912 - 11.85783 10.69118 9.69532 8.82329 8.05884 7.38635 - 6.79323 6.26592 5.79160 5.36243 4.97203 4.61337 - 4.27797 3.96014 3.65995 3.37833 3.11597 2.86935 - 2.63645 2.52607 2.41956 2.33829 2.25931 2.23968 - 2.22301 2.22136 2.22098 2.22089 2.21915 2.21979 - 12.07264 10.81324 9.76031 8.84235 8.04258 7.34345 - 6.72791 6.18004 5.68565 5.23687 4.82760 4.45135 - 4.10046 3.76967 3.45831 3.16617 2.89265 2.63515 - 2.39018 2.27277 2.15856 2.07060 1.98563 1.96531 - 1.95048 1.94832 1.94531 1.94501 1.94637 1.94651 - 12.21314 10.90408 9.82517 8.88669 8.07160 7.36058 - 6.73452 6.17612 5.67055 5.21016 4.78918 4.40145 - 4.03979 3.69923 3.37879 3.07769 2.79448 2.52544 - 2.26694 2.14177 2.02005 1.92623 1.83455 1.81224 - 1.79545 1.79320 1.79052 1.79025 1.79116 1.79045 - 12.41161 11.05741 9.96471 9.01526 8.19384 7.47460 - 6.83947 6.27118 5.75529 5.28414 4.85169 4.45141 - 4.07560 3.71901 3.38090 3.06088 2.75661 2.46056 - 2.16703 2.02033 1.87384 1.75782 1.64469 1.61622 - 1.59302 1.59042 1.58866 1.58841 1.58766 1.58709 - 12.50826 11.15088 10.07014 9.12973 8.31533 7.59812 - 6.96272 6.39377 5.87833 5.40832 4.97675 4.57576 - 4.19585 3.83080 3.48054 3.14578 2.82415 2.50529 - 2.17881 2.00989 1.83301 1.68692 1.54839 1.51478 - 1.48782 1.48438 1.48110 1.48069 1.48081 1.48226 - 12.59325 11.24552 10.20157 9.29762 8.51106 7.81483 - 7.19480 6.63672 6.12840 5.66260 5.23317 4.83315 - 4.45391 4.08868 3.73417 3.38575 3.03675 2.67615 - 2.28882 2.07811 1.84790 1.64625 1.44490 1.40284 - 1.37675 1.37211 1.36323 1.36225 1.36683 1.37122 - 12.56379 11.28442 10.30540 9.44635 8.68299 7.99712 - 7.38035 6.82443 6.32217 5.86632 5.44911 5.06143 - 4.69163 4.33069 3.97505 3.61977 3.25583 2.86528 - 2.42510 2.17762 1.90405 1.66038 1.39824 1.33732 - 1.31599 1.31283 1.29864 1.29649 1.30561 1.31029 - 12.55464 11.29658 10.35610 9.53046 8.79290 8.12805 - 7.52838 6.98635 6.49536 6.04865 5.63891 5.25734 - 4.89251 4.53522 4.18126 3.82431 3.45286 3.04359 - 2.56565 2.28854 1.97445 1.69002 1.37510 1.29928 - 1.27742 1.27481 1.25752 1.25463 1.26591 1.26977 - 12.53508 11.29712 10.39197 9.59464 8.87992 8.23372 - 7.64942 7.12003 6.63948 6.20146 5.79905 5.42383 - 5.06464 4.71222 4.36177 4.00595 3.63095 3.20870 - 2.70108 2.39939 2.05063 1.72952 1.36600 1.27560 - 1.25052 1.24825 1.22900 1.22551 1.23780 1.24037 - 12.48871 11.28540 10.43913 9.68738 9.01032 8.39538 - 7.83720 7.32966 6.86759 6.44539 6.05682 5.69412 - 5.34671 5.00539 4.66456 4.31517 3.93988 3.50255 - 2.95217 2.61205 2.20637 1.82161 1.37086 1.25273 - 1.21577 1.21331 1.19188 1.18759 1.20021 1.20025 - 12.51340 11.30914 10.48535 9.75194 9.09305 8.49620 - 7.95618 7.46689 7.02307 6.61896 6.24792 5.90145 - 5.56768 5.23658 4.90317 4.55964 4.19109 3.76587 - 3.21720 2.84781 2.35981 1.88152 1.38023 1.25948 - 1.19971 1.19036 1.16796 1.16558 1.17132 1.17401 - 12.43084 11.27913 10.52764 9.85340 9.24464 8.69125 - 8.18915 7.73341 7.31969 6.94313 6.59802 6.27663 - 5.96788 5.66197 5.35340 5.03304 4.68271 4.26235 - 3.68636 3.27741 2.71467 2.13540 1.46476 1.28196 - 1.17319 1.15921 1.13523 1.13226 1.13545 1.13602 - 12.37542 11.25839 10.55131 9.91468 9.33811 8.81316 - 8.33635 7.90349 7.51086 7.15423 6.82850 6.52665 - 6.23829 5.95405 5.66824 5.37097 5.04189 4.63474 - 4.05241 3.62599 3.02542 2.38097 1.56549 1.32505 - 1.16327 1.14334 1.11799 1.11459 1.11591 1.11557 - 12.26135 11.20600 10.56833 9.98885 9.45979 8.97499 - 8.53213 8.12841 7.76137 7.42821 7.12556 6.84866 - 6.59017 6.34279 6.10038 5.85074 5.56643 5.18147 - 4.57919 4.12942 3.50103 2.80028 1.79280 1.45431 - 1.15798 1.12276 1.10300 1.09913 1.08566 1.09403 - 12.24960 11.20806 10.59280 10.03337 9.52327 9.05712 - 8.63278 8.24776 7.89982 7.58643 7.30442 7.04925 - 6.81362 6.59048 6.37452 6.15460 5.90460 5.55919 - 4.99488 4.55354 3.90842 3.15012 1.98014 1.56636 - 1.17827 1.12513 1.09003 1.08572 1.07541 1.08283 - 12.24674 11.21451 10.61190 10.06420 9.56561 9.11127 - 8.69920 8.32701 7.99259 7.69357 7.42693 7.18817 - 6.96993 6.76529 6.56971 6.37324 6.15144 5.84124 - 5.31712 4.89155 4.24582 3.45258 2.15516 1.67463 - 1.20254 1.13238 1.08163 1.07666 1.06987 1.07600 - 12.23294 11.22120 10.63448 10.09805 9.60739 9.15891 - 8.75146 8.38377 8.05491 7.76320 7.50629 7.28071 - 7.08051 6.89877 6.72713 6.54732 6.33128 6.03246 - 5.54886 5.16144 4.56474 3.77917 2.32607 1.75877 - 1.21209 1.13637 1.08404 1.07661 1.07247 1.07141 - 12.22090 11.22984 10.65660 10.13134 9.65093 9.21340 - 8.81775 8.46284 8.14779 7.87084 7.62944 7.42048 - 7.23945 7.08077 6.93693 6.79020 6.61345 6.36195 - 5.93520 5.57903 5.00977 4.22016 2.63972 1.96472 - 1.25537 1.15367 1.08109 1.07414 1.06419 1.06561 - 12.21175 11.23312 10.66876 10.15261 9.68089 9.25138 - 8.86329 8.51578 8.20851 7.94030 7.70942 7.51305 - 7.34604 7.20271 7.07692 6.95346 6.80744 6.59414 - 6.21493 5.88885 5.35433 4.58073 2.91161 2.15251 - 1.30399 1.17352 1.08087 1.07281 1.05945 1.06206 - 12.19821 11.24363 10.69039 10.18468 9.72329 9.30430 - 8.92688 8.59033 8.29444 8.03849 7.82140 7.64137 - 7.49469 7.37737 7.28520 7.20557 7.11623 6.97337 - 6.68115 6.40769 5.93453 5.22009 3.50131 2.57093 - 1.41257 1.22944 1.08785 1.07179 1.05823 1.05724 - 12.19336 11.25647 10.70218 10.19787 9.74011 9.32670 - 8.95631 8.62779 8.34041 8.09322 7.88503 7.71381 - 7.57537 7.46667 7.38825 7.33696 7.29667 7.21007 - 6.97137 6.73493 6.32562 5.66820 3.93083 2.93316 - 1.52582 1.28910 1.09632 1.07532 1.05552 1.05482 - 12.13548 11.26270 10.71445 10.21553 9.76314 9.35522 - 8.99057 8.66825 8.38766 8.14811 7.94875 7.78793 - 7.66204 7.56903 7.51085 7.48702 7.48598 7.45875 - 7.31219 7.13900 6.80828 6.24058 4.59437 3.50253 - 1.73769 1.41202 1.11838 1.08347 1.05387 1.05239 - 12.08563 11.26571 10.72054 10.22435 9.77461 9.36951 - 9.00790 8.68888 8.41189 8.17641 7.98172 7.82641 - 7.70713 7.62234 7.57491 7.56602 7.58714 7.59543 - 7.50766 7.37702 7.10236 6.60597 5.07142 3.94483 - 1.93408 1.53129 1.14247 1.09299 1.05402 1.05119 - 12.02733 11.26069 10.72584 10.23486 9.78722 9.38301 - 9.02166 8.70282 8.42636 8.19217 8.00000 7.84915 - 7.73756 7.66378 7.62749 7.62245 7.63858 7.65756 - 7.62753 7.54323 7.31378 6.86160 5.43040 4.30522 - 2.11649 1.64534 1.16728 1.10365 1.05459 1.05047 - 12.00241 11.25946 10.72601 10.23787 9.79321 9.39102 - 9.03087 8.71272 8.43690 8.20351 8.01258 7.86374 - 7.75529 7.68606 7.65571 7.65763 7.68237 7.71580 - 7.71450 7.65504 7.46347 7.05785 5.70942 4.60696 - 2.29363 1.75120 1.18982 1.11666 1.05629 1.04999 - 11.96997 11.26056 10.72880 10.24224 9.79910 9.39853 - 9.04007 8.72374 8.44992 8.21878 8.03046 7.88470 - 7.77999 7.71541 7.69117 7.70155 7.73880 7.79231 - 7.82842 7.80279 7.66801 7.33796 6.12985 5.07467 - 2.61581 1.95605 1.23925 1.13860 1.06006 1.04939 - 11.94859 11.26316 10.73244 10.24530 9.80136 9.40094 - 9.04357 8.72903 8.45741 8.22868 8.04279 7.89929 - 7.79655 7.73372 7.71196 7.72728 7.77378 7.84109 - 7.89889 7.89413 7.80255 7.53237 6.42675 5.43482 - 2.89905 2.14480 1.29089 1.15814 1.06571 1.04902 - 11.91766 11.26388 10.73451 10.24852 9.80592 9.40683 - 9.05087 8.73792 8.46814 8.24150 8.05787 7.91685 - 7.81714 7.75829 7.74181 7.76437 7.82144 7.90646 - 7.99720 8.02366 7.99445 7.82017 6.92032 6.05587 - 3.49062 2.55804 1.41017 1.21740 1.07893 1.04852 - 11.89989 11.26433 10.73564 10.25033 9.80824 9.40978 - 9.05454 8.74238 8.47347 8.24782 8.06533 7.92568 - 7.82764 7.77088 7.75715 7.78344 7.84600 7.94058 - 8.04895 8.09166 8.09617 7.97985 7.22704 6.46219 - 3.95368 2.91088 1.52464 1.27859 1.09225 1.04827 - 11.88546 11.26286 10.73297 10.24924 9.81000 9.41415 - 9.06087 8.74978 8.48079 8.25432 8.07101 7.93148 - 7.83545 7.78316 7.77513 7.80540 7.86901 7.96989 - 8.10742 8.17618 8.19948 8.10648 7.60205 7.07947 - 4.59907 3.42338 1.74129 1.41797 1.12007 1.04801 - 11.89230 11.27147 10.73568 10.24790 9.80640 9.40982 - 9.05721 8.74796 8.48176 8.25846 8.07793 7.93938 - 7.84038 7.78090 7.76683 7.80452 7.89519 8.01611 - 8.13700 8.19461 8.24424 8.23287 7.82288 7.27973 - 5.12307 3.92223 1.93614 1.52012 1.14277 1.04788 - 11.88562 11.27142 10.73599 10.24854 9.80727 9.41092 - 9.05852 8.74947 8.48347 8.26041 8.08014 7.94195 - 7.84345 7.78461 7.77144 7.81042 7.90299 8.02672 - 8.15295 8.21632 8.27819 8.28953 7.96009 7.49317 - 5.48897 4.27675 2.13104 1.63574 1.16733 1.04781 - 11.88101 11.27138 10.73620 10.24896 9.80782 9.41161 - 9.05935 8.75044 8.48459 8.26169 8.08162 7.94367 - 7.84548 7.78709 7.77454 7.81436 7.90820 8.03389 - 8.16384 8.23109 8.30097 8.32780 8.05744 7.64743 - 5.77553 4.57247 2.31220 1.74966 1.19155 1.04777 - 11.85434 11.26473 10.73770 10.25389 9.81347 9.41663 - 9.06307 8.75268 8.48568 8.26213 8.08206 7.94528 - 7.85085 7.79887 7.79156 7.82680 7.90269 8.01964 - 8.17190 8.25594 8.33705 8.37568 8.18660 7.85543 - 6.20158 5.04274 2.63668 1.97440 1.24021 1.04772 - 11.85029 11.26420 10.73741 10.25381 9.81356 9.41680 - 9.06324 8.75289 8.48605 8.26278 8.08306 7.94668 - 7.85267 7.80110 7.79422 7.82989 7.90641 8.02502 - 8.18017 8.26663 8.35510 8.40685 8.26542 7.98971 - 6.50584 5.40651 2.92085 2.17588 1.28759 1.04770 - 0.90004 0.93611 0.97302 1.01097 1.05000 1.09009 - 1.13129 1.17370 1.21748 1.26278 1.30985 1.35917 - 1.41165 1.46730 1.52314 1.57195 1.60671 1.63023 - 1.64730 1.65483 1.66648 1.67840 1.68103 1.68120 - 1.68294 1.68285 1.68180 1.68179 1.68291 1.68294 - 1.23848 1.28149 1.32578 1.37179 1.41953 1.46903 - 1.52024 1.57309 1.62748 1.68324 1.74005 1.79743 - 1.85475 1.91108 1.96513 2.01516 2.05912 2.09548 - 2.11956 2.12270 2.11641 2.10726 2.12696 2.14355 - 2.13904 2.13503 2.13410 2.13509 2.13542 2.13658 - 1.54378 1.59350 1.64433 1.69686 1.75108 1.80697 - 1.86441 1.92329 1.98341 2.04450 2.10614 2.16770 - 2.22835 2.28696 2.34203 2.39163 2.43373 2.46760 - 2.48979 2.49262 2.48694 2.47945 2.50256 2.51985 - 2.51287 2.50867 2.50887 2.50997 2.50919 2.51042 - 2.06260 2.13196 2.19995 2.26720 2.33340 2.39830 - 2.46170 2.52360 2.58418 2.64334 2.70111 2.75776 - 2.81441 2.87146 2.92684 2.97618 3.01500 3.04320 - 3.06320 3.07177 3.08067 3.08831 3.09580 3.09669 - 3.09629 3.09698 3.09877 3.09873 3.09660 3.09668 - 2.49445 2.58533 2.67000 2.74897 2.82184 2.88860 - 2.94993 3.00748 3.06371 3.11901 3.17329 3.22622 - 3.27784 3.32779 3.37471 3.41638 3.45072 3.47828 - 3.49978 3.50870 3.51954 3.53029 3.53965 3.54059 - 3.53736 3.53825 3.54282 3.54319 3.53785 3.53800 - 2.86751 2.97594 3.07365 3.16110 3.23777 3.30388 - 3.36084 3.41178 3.46102 3.50944 3.55692 3.60304 - 3.64751 3.68984 3.72905 3.76390 3.79335 3.81826 - 3.83987 3.85012 3.86275 3.87515 3.88602 3.88680 - 3.88189 3.88305 3.88927 3.88976 3.88248 3.88268 - 3.19601 3.31809 3.42535 3.51826 3.59621 3.65971 - 3.71081 3.75393 3.79501 3.83538 3.87493 3.91327 - 3.94999 3.98463 4.01650 4.04489 4.06940 4.09134 - 4.11255 4.12371 4.13741 4.15064 4.16232 4.16304 - 4.15738 4.15866 4.16563 4.16617 4.15800 4.15824 - 3.75417 3.89234 4.00924 4.10549 4.18053 4.23531 - 4.27297 4.29972 4.32375 4.34705 4.36970 4.39165 - 4.41279 4.43305 4.45203 4.46920 4.48455 4.50032 - 4.51958 4.53127 4.54497 4.55745 4.56900 4.56995 - 4.56509 4.56624 4.57247 4.57296 4.56568 4.56592 - 4.21705 4.36013 4.47736 4.56989 4.63728 4.68086 - 4.70448 4.71537 4.72299 4.72970 4.73591 4.74211 - 4.74875 4.75638 4.76462 4.77247 4.77962 4.78925 - 4.80547 4.81643 4.82813 4.83771 4.84766 4.84909 - 4.84675 4.84750 4.85127 4.85155 4.84726 4.84740 - 5.10305 5.25604 5.35692 5.41439 5.43877 5.44273 - 5.43204 5.41323 5.39402 5.37376 5.34860 5.31796 - 5.28900 5.26787 5.25386 5.24301 5.23293 5.22983 - 5.23701 5.24111 5.24372 5.24456 5.24755 5.24986 - 5.25563 5.25490 5.25066 5.25042 5.25578 5.25560 - 5.77790 5.87921 5.94516 5.98048 5.98600 5.96453 - 5.92141 5.86543 5.80735 5.75032 5.69579 5.64530 - 5.60110 5.56466 5.53492 5.50795 5.48141 5.46159 - 5.45554 5.45566 5.44951 5.43844 5.43404 5.43694 - 5.44965 5.44777 5.43608 5.43516 5.44938 5.44897 - 6.73333 6.76700 6.76339 6.73075 6.67112 6.58833 - 6.48864 6.38139 6.27715 6.17942 6.08917 6.00695 - 5.93396 5.87004 5.81374 5.76042 5.70744 5.66201 - 5.63183 5.61928 5.59712 5.57049 5.55312 5.55517 - 5.57461 5.57124 5.55129 5.54973 5.57369 5.57300 - 7.53829 7.41531 7.28490 7.15638 7.02970 6.90490 - 6.78211 6.66163 6.54338 6.42818 6.31686 6.20938 - 6.10694 6.00992 5.91940 5.83672 5.76310 5.69802 - 5.64359 5.62383 5.61138 5.60152 5.55139 5.53018 - 5.55444 5.55534 5.53717 5.53629 5.56101 5.55768 - 8.03561 7.86474 7.68704 7.51336 7.34359 7.17782 - 7.01625 6.85908 6.70663 6.55972 6.41942 6.28568 - 6.16000 6.04325 5.93657 5.84152 5.75890 5.68574 - 5.62101 5.59457 5.57359 5.55464 5.49173 5.46626 - 5.48871 5.49186 5.47840 5.47696 5.49413 5.49138 - 8.43214 8.21879 7.99949 7.78637 7.57918 7.37806 - 7.18322 6.99470 6.81310 6.63942 6.47458 6.31865 - 6.17317 6.03952 5.91878 5.81262 5.72157 5.64094 - 5.56770 5.53631 5.50961 5.48512 5.41446 5.38518 - 5.40189 5.40750 5.40149 5.39954 5.40583 5.40389 - 8.88569 8.76848 8.53669 8.23940 7.92143 7.62389 - 7.35226 7.10486 6.88034 6.67735 6.49221 6.32103 - 6.16124 6.01194 5.87301 5.74541 5.62809 5.51283 - 5.39653 5.34352 5.29763 5.26717 5.23234 5.21978 - 5.19819 5.19966 5.21159 5.21220 5.19643 5.19713 - 9.32728 9.14631 8.84874 8.48837 8.11287 7.76484 - 7.44916 7.16341 6.90520 6.67249 6.46035 6.26433 - 6.08198 5.91246 5.75488 5.60788 5.46959 5.33592 - 5.20524 5.14443 5.09156 5.05813 5.02215 5.00234 - 4.97538 4.97953 4.99613 4.99544 4.97256 4.97375 - 10.05811 9.72087 9.28362 8.80211 8.32260 7.88413 - 7.48966 7.13644 6.82125 6.53777 6.27664 6.03146 - 5.80210 5.58930 5.39335 5.21138 5.04077 4.87643 - 4.71661 4.64171 4.57247 4.52230 4.46926 4.45335 - 4.43227 4.43261 4.44071 4.44108 4.42965 4.43005 - 10.63283 10.00122 9.40457 8.85370 8.34450 7.87431 - 7.44069 7.04201 6.67755 6.34478 6.04052 5.76129 - 5.50270 5.26217 5.04095 4.83818 4.65117 4.46989 - 4.28614 4.19572 4.11042 4.04705 3.98013 3.96607 - 3.96312 3.96019 3.95030 3.94968 3.96002 3.95951 - 11.09660 10.34799 9.60939 8.90846 8.26495 7.69526 - 7.19356 6.74822 6.34852 5.98527 5.64802 5.33080 - 5.03443 4.75923 4.50323 4.26198 4.03157 3.81709 - 3.62032 3.52492 3.42858 3.35161 3.27806 3.26208 - 3.25566 3.25251 3.24428 3.24371 3.25217 3.25154 - 11.47306 10.49162 9.62491 8.85624 8.17185 7.56166 - 7.01864 6.53323 6.09646 5.70196 5.34350 5.01399 - 4.70446 4.40907 4.12870 3.86568 3.62075 3.39022 - 3.17361 3.07162 2.97307 2.89764 2.82331 2.80408 - 2.78643 2.78509 2.78618 2.78620 2.78289 2.78294 - 11.69750 10.60315 9.65784 8.82867 8.09934 7.45556 - 6.88693 6.38088 5.92533 5.51293 5.13745 4.79193 - 4.46772 4.15918 3.86692 3.59290 3.33825 3.09846 - 2.87210 2.76527 2.66284 2.58522 2.50880 2.48899 - 2.47016 2.46889 2.47073 2.47081 2.46647 2.46688 - 11.85735 10.68514 9.68799 8.81806 8.05800 7.39122 - 6.80417 6.28230 5.81192 5.38526 4.99623 4.63818 - 4.30299 3.98529 3.68525 3.40403 3.14233 2.89628 - 2.66351 2.55304 2.44637 2.36493 2.28572 2.26602 - 2.24924 2.24758 2.24726 2.24717 2.24536 2.24587 - 12.06891 10.80645 9.75326 8.83766 8.04194 7.34777 - 6.73737 6.19405 5.70294 5.25626 4.84821 4.47257 - 4.12201 3.79158 3.48059 3.18891 2.91594 2.65887 - 2.41414 2.29679 2.18258 2.09454 2.00916 1.98869 - 1.97368 1.97151 1.96855 1.96827 1.96955 1.96962 - 12.20132 10.89760 9.82269 8.88796 8.07631 7.36840 - 6.74505 6.18893 5.68515 5.22614 4.80622 4.41933 - 4.05843 3.71859 3.39878 3.09816 2.81522 2.54645 - 2.28834 2.16342 2.04186 1.94796 1.85563 1.83307 - 1.81610 1.81383 1.81112 1.81085 1.81176 1.81115 - 12.38570 11.04813 9.96512 9.02139 8.20267 7.48418 - 6.84873 6.27991 5.76400 5.29339 4.86193 4.46294 - 4.08853 3.73329 3.39632 3.07699 2.77293 2.47713 - 2.18434 2.03812 1.89192 1.77583 1.66194 1.63318 - 1.60982 1.60719 1.60536 1.60510 1.60441 1.60397 - 12.48047 11.13468 10.06088 9.12522 8.31382 7.59855 - 6.96440 6.39641 5.88198 5.41307 4.98270 4.58301 - 4.20453 3.84095 3.49208 3.15843 2.83759 2.51950 - 2.19393 2.02545 1.84882 1.70270 1.56381 1.53007 - 1.50293 1.49948 1.49624 1.49583 1.49588 1.49712 - 12.57084 11.21690 10.16968 9.26660 8.48380 7.79321 - 7.17958 6.62750 6.12375 5.66109 5.23375 4.83510 - 4.45706 4.09314 3.74011 3.39338 3.04623 2.68735 - 2.30129 2.09099 1.86101 1.65949 1.45859 1.41672 - 1.39042 1.38582 1.37722 1.37625 1.38043 1.38398 - 12.59670 11.25194 10.23758 9.36799 8.61184 7.94442 - 7.35080 6.81574 6.32598 5.87452 5.45587 5.06359 - 4.68950 4.32684 3.97191 3.61916 3.25949 2.87599 - 2.44369 2.19652 1.91536 1.66207 1.40712 1.35584 - 1.33003 1.32484 1.31184 1.31033 1.31794 1.32191 - 12.59469 11.26545 10.28488 9.44535 8.71317 8.06613 - 7.48993 6.96972 6.49238 6.05124 5.64109 5.25569 - 4.88696 4.52799 4.17463 3.82042 3.45419 3.05421 - 2.58687 2.30987 1.98470 1.68656 1.38128 1.31915 - 1.29136 1.28590 1.27011 1.26810 1.27747 1.28066 - 12.58020 11.26837 10.32048 9.50719 8.79621 8.16681 - 7.60556 7.09808 6.63162 6.19982 5.79769 5.41921 - 5.05642 4.70234 4.35239 3.99928 3.63008 3.21895 - 2.72449 2.42289 2.06023 1.72205 1.36997 1.29628 - 1.26435 1.25864 1.24104 1.23861 1.24875 1.25076 - 12.53818 11.26196 10.37162 9.60160 8.92577 8.32524 - 7.78821 7.30148 6.85324 6.43765 6.05015 5.68504 - 5.33459 4.99171 4.65114 4.30422 3.93509 3.51149 - 2.97864 2.63896 2.21528 1.80845 1.37155 1.27415 - 1.22933 1.22271 1.20304 1.20000 1.21028 1.21001 - 12.47701 11.27113 10.44306 9.70742 9.04813 8.45254 - 7.91518 7.42974 6.99072 6.59207 6.22690 5.88623 - 5.55750 5.23019 4.89938 4.55743 4.18993 3.76639 - 3.22083 2.85309 2.36604 1.88835 1.38974 1.27023 - 1.21041 1.20097 1.17893 1.17670 1.18198 1.18341 - 12.39818 11.24585 10.49004 9.81322 9.20347 8.65058 - 8.15022 7.69728 7.28727 6.91510 6.57479 6.25824 - 5.95376 5.65113 5.34491 5.02609 4.67702 4.25877 - 3.68664 3.27983 2.71851 2.14031 1.47286 1.29137 - 1.18308 1.16905 1.14522 1.14239 1.14532 1.14506 - 12.34368 11.22762 10.51706 9.87822 9.30074 8.77602 - 8.30043 7.86966 7.47986 7.12662 6.80464 6.50664 - 6.22172 5.94017 5.65637 5.36059 5.03289 4.62815 - 4.05010 3.62614 3.02744 2.38450 1.57261 1.33352 - 1.17267 1.15277 1.12746 1.12416 1.12533 1.12451 - 12.22741 11.17655 10.53751 9.95730 9.42802 8.94351 - 8.50143 8.09887 7.73335 7.40204 7.10144 6.82671 - 6.57033 6.32488 6.08426 5.83635 5.55386 5.17127 - 4.57252 4.12519 3.49993 2.80239 1.79897 1.46156 - 1.16655 1.13162 1.11210 1.10822 1.09460 1.10292 - 12.21348 11.17823 10.56285 10.00355 9.49377 9.02816 - 8.60458 8.22048 7.87363 7.56147 7.28082 7.02704 - 6.79281 6.57099 6.35635 6.13782 5.88943 5.54627 - 4.98547 4.54668 3.90497 3.15035 1.98536 1.57299 - 1.18653 1.13373 1.09894 1.09461 1.08410 1.09166 - 12.20872 11.18379 10.58193 10.03499 9.53715 9.08364 - 8.67241 8.30108 7.96757 7.66950 7.40381 7.16601 - 6.94871 6.74502 6.55042 6.35504 6.13461 5.82645 - 5.30564 4.88261 4.24041 3.45118 2.15958 1.68079 - 1.21062 1.14084 1.09044 1.08545 1.07844 1.08477 - 12.19517 11.19000 10.60359 10.06797 9.57843 9.13129 - 8.72528 8.35896 8.03125 7.74042 7.48418 7.25911 - 7.05931 6.87792 6.70673 6.52765 6.31286 6.01611 - 5.53598 5.15124 4.55826 3.77664 2.32905 1.76417 - 1.22033 1.14494 1.09266 1.08523 1.08110 1.08014 - 12.17757 11.19475 10.62448 10.10245 9.62481 9.18896 - 8.79416 8.43954 8.12470 7.84822 7.60796 7.40061 - 7.22032 7.06062 6.91465 6.76649 6.59050 6.34174 - 5.92003 5.56805 5.00414 4.21733 2.63555 1.97012 - 1.26622 1.16083 1.08917 1.08323 1.07226 1.07430 - 12.16935 11.20045 10.63872 10.12453 9.65431 9.22591 - 8.83864 8.49177 8.18505 7.91737 7.68694 7.49100 - 7.32436 7.18136 7.05584 6.93263 6.78698 6.57455 - 6.19766 5.87382 5.34299 4.57397 2.91230 2.15647 - 1.31170 1.18173 1.08945 1.08140 1.06805 1.07074 - 12.15682 11.21168 10.66104 10.15722 9.69722 9.27923 - 8.90248 8.56642 8.27097 8.01543 7.79869 7.61902 - 7.47265 7.35558 7.26361 7.18399 7.09456 6.95189 - 6.66107 6.38935 5.91948 5.20981 3.49976 2.57310 - 1.41973 1.23736 1.09641 1.08032 1.06686 1.06593 - 12.13688 11.21793 10.67222 10.17327 9.71840 9.30590 - 8.93503 8.60537 8.31694 8.06921 7.86127 7.69167 - 7.55704 7.45399 7.37929 7.32182 7.26232 7.16356 - 6.94186 6.72055 6.31625 5.66290 3.93227 2.91430 - 1.53648 1.30236 1.10489 1.08243 1.06113 1.06353 - 12.09875 11.23227 10.68539 10.18762 9.73625 9.32928 - 8.96547 8.64389 8.36392 8.12489 7.92593 7.76542 - 7.63973 7.54681 7.48863 7.46469 7.46341 7.43593 - 7.28948 7.11692 6.78805 6.22395 4.58743 3.50114 - 1.74338 1.41895 1.12681 1.09208 1.06248 1.06109 - 12.05010 11.23539 10.69126 10.19619 9.74741 9.34322 - 8.98243 8.66415 8.38783 8.15292 7.95873 7.80380 - 7.68479 7.60017 7.55277 7.54376 7.56460 7.57250 - 7.48450 7.35412 7.08062 6.58706 5.06199 3.94141 - 1.93889 1.53769 1.15082 1.10162 1.06259 1.05986 - 11.99365 11.22828 10.69427 10.20573 9.76081 9.35836 - 8.99788 8.67925 8.40273 8.16831 7.97595 7.82516 - 7.71404 7.64128 7.60612 7.60142 7.61648 7.63409 - 7.60396 7.52016 7.29126 6.84012 5.41701 4.30353 - 2.12319 1.64826 1.17346 1.11439 1.06345 1.05912 - 11.96818 11.22885 10.69623 10.20910 9.76540 9.36423 - 9.00508 8.68786 8.41282 8.18010 7.98969 7.84124 - 7.73304 7.66394 7.63359 7.63541 7.65988 7.69291 - 7.69112 7.63151 7.44027 7.03633 5.69637 4.60023 - 2.29682 1.75673 1.19796 1.12522 1.06483 1.05863 - 11.93431 11.23135 10.70082 10.21376 9.76999 9.36967 - 9.01234 8.69764 8.42552 8.19596 8.00887 7.86378 - 7.75895 7.69349 7.66805 7.67804 7.71635 7.77050 - 7.80450 7.77767 7.64517 7.31832 6.10995 5.06692 - 2.61514 1.96255 1.24977 1.14407 1.06924 1.05801 - 11.91379 11.23146 10.70206 10.21622 9.77355 9.37431 - 9.01801 8.70440 8.43358 8.20548 8.02003 7.87681 - 7.77423 7.71157 7.68988 7.70509 7.75125 7.81812 - 7.87544 7.87044 7.77863 7.50890 6.40914 5.42320 - 2.89960 2.14896 1.29860 1.16645 1.07422 1.05764 - 11.88271 11.23158 10.70373 10.21933 9.77830 9.38050 - 9.02558 8.71348 8.44439 8.21830 8.03511 7.89445 - 7.79495 7.73613 7.71958 7.74199 7.79887 7.88355 - 7.97377 7.99996 7.97039 7.79598 6.89965 6.04042 - 3.48869 2.56069 1.41733 1.22534 1.08745 1.05716 - 11.86555 11.23213 10.70486 10.22124 9.78075 9.38359 - 9.02936 8.71799 8.44973 8.22462 8.04256 7.90323 - 7.80535 7.74863 7.73480 7.76096 7.82340 7.91770 - 8.02551 8.06796 8.07209 7.95545 7.20476 6.44435 - 3.94983 2.91209 1.53129 1.28616 1.10076 1.05692 - 11.84745 11.23297 10.70639 10.22315 9.78324 9.38662 - 9.03306 8.72241 8.45494 8.23073 8.04977 7.91183 - 7.81570 7.76116 7.75016 7.78017 7.84831 7.95263 - 8.07898 8.13817 8.17655 8.12552 7.57194 6.95202 - 4.63414 3.47605 1.74391 1.40734 1.12693 1.05669 - 11.85867 11.23998 10.70570 10.21921 9.77889 9.38338 - 9.03173 8.72332 8.45783 8.23513 8.05508 7.91690 - 7.81815 7.75880 7.74472 7.78224 7.87261 7.99309 - 8.11348 8.17083 8.22019 8.20845 7.79843 7.25754 - 5.11376 3.91880 1.94102 1.52647 1.15124 1.05657 - 11.85210 11.23993 10.70591 10.21974 9.77971 9.38444 - 9.03301 8.72484 8.45958 8.23714 8.05740 7.91959 - 7.82135 7.76266 7.74948 7.78828 7.88048 8.00373 - 8.12940 8.19252 8.25414 8.26520 7.93533 7.47008 - 5.47766 4.27143 2.13491 1.64158 1.17576 1.05650 - 11.84736 11.23979 10.70601 10.22006 9.78022 9.38511 - 9.03386 8.72582 8.46075 8.23850 8.05896 7.92144 - 7.82353 7.76526 7.75269 7.79233 7.88576 8.01092 - 8.14025 8.20723 8.27693 8.30354 8.03251 7.62373 - 5.76252 4.56546 2.31511 1.75501 1.19990 1.05645 - 11.82130 11.23324 10.70752 10.22509 9.78597 9.39031 - 9.03776 8.72822 8.46194 8.23897 8.05938 7.92303 - 7.82889 7.77704 7.76970 7.80472 7.88024 7.99672 - 8.14845 8.23217 8.31293 8.35132 8.16188 7.83091 - 6.18590 5.03302 2.63804 1.97866 1.24834 1.05638 - 11.81821 11.23391 10.70812 10.22551 9.78614 9.39045 - 9.03805 8.72869 8.46254 8.23968 8.06025 7.92415 - 7.83035 7.77887 7.77196 7.80754 7.88392 8.00221 - 8.15681 8.24291 8.33097 8.38243 8.24055 7.96510 - 6.48827 5.39454 2.92086 2.17928 1.29537 1.05632 - 0.87722 0.91248 0.94862 0.98583 1.02414 1.06358 - 1.10421 1.14614 1.18956 1.23466 1.28169 1.33118 - 1.38403 1.44024 1.49676 1.54610 1.58094 1.60421 - 1.62083 1.62800 1.63911 1.65039 1.65217 1.65217 - 1.65367 1.65343 1.65296 1.65346 1.65350 1.65366 - 1.20955 1.25209 1.29596 1.34155 1.38892 1.43806 - 1.48896 1.54155 1.59573 1.65136 1.70811 1.76553 - 1.82301 1.87962 1.93409 1.98468 2.02927 2.06616 - 2.09035 2.09321 2.08626 2.07622 2.09495 2.11129 - 2.10664 2.10300 2.10307 2.10409 2.10319 2.10431 - 1.51070 1.56012 1.61071 1.66302 1.71706 1.77280 - 1.83016 1.88902 1.94917 2.01038 2.07222 2.13407 - 2.19511 2.25421 2.30988 2.36015 2.40292 2.43729 - 2.45944 2.46189 2.45540 2.44693 2.46937 2.48666 - 2.47955 2.47554 2.47632 2.47743 2.47588 2.47712 - 2.02520 2.09393 2.16148 2.22846 2.29458 2.35959 - 2.42332 2.48574 2.54701 2.60705 2.66587 2.72371 - 2.78160 2.83989 2.89638 2.94648 2.98546 3.01316 - 3.03215 3.04020 3.04869 3.05610 3.06330 3.06420 - 3.06385 3.06422 3.06507 3.06493 3.06385 3.06398 - 2.45404 2.54431 2.62868 2.70766 2.78083 2.84818 - 2.91031 2.96881 3.02602 3.08234 3.13771 3.19194 - 3.24522 3.29728 3.34634 3.38928 3.42325 3.44958 - 3.47002 3.47857 3.48919 3.49990 3.50908 3.50977 - 3.50689 3.50827 3.51019 3.50837 3.50782 3.50736 - 2.82512 2.93310 3.03074 3.11847 3.19576 3.26279 - 3.32089 3.37304 3.42344 3.47298 3.52164 3.56917 - 3.61559 3.66054 3.70253 3.73900 3.76786 3.79120 - 3.81185 3.82196 3.83455 3.84702 3.85783 3.85831 - 3.85397 3.85581 3.85837 3.85590 3.85515 3.85455 - 3.15224 3.27408 3.38152 3.47498 3.55383 3.61850 - 3.67098 3.71551 3.75790 3.79947 3.84025 3.88005 - 3.91886 3.95638 3.99133 4.02156 4.04552 4.06590 - 4.08640 4.09760 4.11145 4.12486 4.13659 4.13701 - 4.13205 4.13406 4.13692 4.13416 4.13334 4.13267 - 3.70875 3.84716 3.96468 4.06193 4.13827 4.19459 - 4.23393 4.26234 4.28788 4.31254 4.33652 4.35998 - 4.38315 4.40611 4.42802 4.44716 4.46262 4.47772 - 4.49700 4.50902 4.52313 4.53598 4.54787 4.54864 - 4.54441 4.54625 4.54882 4.54636 4.54563 4.54504 - 4.17079 4.31456 4.43284 4.52671 4.59567 4.64099 - 4.66644 4.67913 4.68841 4.69666 4.70435 4.71203 - 4.72040 4.73008 4.74053 4.75025 4.75857 4.76897 - 4.78605 4.79750 4.80977 4.81992 4.83048 4.83188 - 4.82995 4.83113 4.83276 4.83127 4.83085 4.83050 - 5.05668 5.21101 5.31354 5.37290 5.39934 5.40547 - 5.39693 5.38008 5.36247 5.34371 5.32040 5.29192 - 5.26435 5.24316 5.22852 5.21878 5.21303 5.21454 - 5.22372 5.22838 5.23183 5.23363 5.23760 5.24037 - 5.24562 5.24493 5.24351 5.24455 5.24573 5.24600 - 5.73207 5.83568 5.90397 5.94153 5.94922 5.92982 - 5.88872 5.83479 5.77886 5.72400 5.67146 5.62241 - 5.57861 5.54138 5.51066 5.48485 5.46323 5.44933 - 5.44672 5.44754 5.44214 5.43191 5.42874 5.43252 - 5.44443 5.44128 5.43668 5.44150 5.44304 5.44421 - 6.69048 6.72711 6.72637 6.69637 6.63920 6.55869 - 6.46119 6.35614 6.25424 6.15889 6.07080 5.99013 - 5.91743 5.85237 5.79466 5.74239 5.69471 5.65574 - 5.62924 5.61736 5.59585 5.56983 5.55352 5.55693 - 5.57526 5.56960 5.56146 5.56978 5.57238 5.57440 - 7.50003 7.37970 7.25195 7.12600 7.00183 6.87941 - 6.75896 6.64071 6.52461 6.41147 6.30210 6.19646 - 6.09575 6.00038 5.91139 5.83019 5.75809 5.69480 - 5.64289 5.62483 5.61449 5.60655 5.55713 5.53477 - 5.55803 5.56228 5.55330 5.55307 5.56769 5.56352 - 8.00040 7.83252 7.65780 7.48699 7.31997 7.15684 - 6.99780 6.84306 6.69292 6.54820 6.40998 6.27820 - 6.15436 6.03934 5.93427 5.84073 5.75961 5.68810 - 5.62544 5.60027 5.58082 5.56321 5.50102 5.47494 - 5.49687 5.50218 5.49464 5.49362 5.50431 5.50101 - 8.39977 8.18972 7.97371 7.76373 7.55954 7.36129 - 7.16917 6.98324 6.80411 6.63275 6.47010 6.31625 - 6.17269 6.04083 5.92176 5.81714 5.72756 5.64841 - 5.57680 5.54629 5.52054 5.49687 5.42704 5.39783 - 5.41454 5.42065 5.41599 5.41416 5.41903 5.41695 - 8.85838 8.74449 8.51671 8.22349 7.90936 7.61513 - 7.34643 7.10175 6.87989 6.67918 6.49531 6.32465 - 6.16652 6.02107 5.88691 5.76191 5.64314 5.52649 - 5.41209 5.36016 5.31504 5.28505 5.25098 5.23786 - 5.21796 5.21954 5.22350 5.22021 5.21653 5.21582 - 9.30186 9.12799 8.83592 8.47949 8.10691 7.76126 - 7.44783 7.16471 6.90983 6.68050 6.47060 6.27545 - 6.09420 5.92717 5.77310 5.62952 5.49303 5.35773 - 5.22369 5.16356 5.11334 5.08197 5.04406 5.02738 - 4.99930 5.00213 5.00859 5.00350 4.99779 4.99665 - 10.04173 9.70991 9.27806 8.80150 8.32626 7.89132 - 7.49978 7.14911 6.83627 6.55478 6.29508 6.05090 - 5.82294 5.61241 5.41897 5.23840 5.06736 4.90266 - 4.74392 4.66959 4.60088 4.55120 4.49868 4.48230 - 4.46217 4.46263 4.46506 4.46255 4.45978 4.45914 - 10.62014 9.99540 9.40468 8.85885 8.35392 7.88733 - 7.45667 7.06044 6.69792 6.36665 6.06356 5.78522 - 5.52733 5.28739 5.06667 4.86442 4.67812 4.49811 - 4.31638 4.22694 4.14184 4.07798 4.01158 3.99789 - 3.99379 3.99101 3.98649 3.98848 3.99064 3.99108 - 11.08778 10.34747 9.61528 8.91921 8.27947 7.71282 - 7.21354 6.77003 6.37163 6.00958 5.67411 5.35903 - 5.06369 4.78769 4.53018 4.28896 4.06124 3.84913 - 3.65225 3.55652 3.45997 3.38292 3.30933 3.29375 - 3.28651 3.28331 3.27943 3.28100 3.28287 3.28300 - 11.46511 10.49238 9.63216 8.86839 8.18771 7.58026 - 7.03924 6.55534 6.11978 5.72635 5.36888 5.04040 - 4.73205 4.43801 4.15893 3.89672 3.65189 3.42112 - 3.20422 3.10204 3.00316 2.92742 2.85297 2.83359 - 2.81606 2.81502 2.81458 2.81329 2.81279 2.81247 - 11.68878 10.60353 9.66481 8.84052 8.11473 7.47352 - 6.90672 6.40196 5.94741 5.53585 5.16120 4.81664 - 4.49367 4.18666 3.89592 3.62271 3.36788 3.12760 - 2.90107 2.79416 2.69135 2.61324 2.53655 2.51650 - 2.49785 2.49696 2.49676 2.49513 2.49449 2.49444 - 11.84683 10.68440 9.69401 8.82895 8.07232 7.40791 - 6.82248 6.30177 5.83234 5.40654 5.01838 4.66125 - 4.32709 4.01056 3.71162 3.43111 3.16956 2.92352 - 2.69093 2.58046 2.47338 2.39130 2.31172 2.29188 - 2.27514 2.27361 2.27248 2.27176 2.27138 2.27173 - 12.05414 10.80253 9.75637 8.84571 8.05332 7.36133 - 6.75238 6.21013 5.72006 5.27442 4.86736 4.49265 - 4.14285 3.81297 3.50247 3.21140 2.93925 2.68302 - 2.43886 2.32153 2.20690 2.11818 2.03245 2.01199 - 1.99686 1.99452 1.99228 1.99263 1.99258 1.99285 - 12.18295 10.89040 9.82257 8.89283 8.08453 7.37882 - 6.75695 6.20198 5.69934 5.24146 4.82263 4.43673 - 4.07660 3.73729 3.41794 3.11802 2.83615 2.56838 - 2.31081 2.18587 2.06395 1.96953 1.87698 1.85444 - 1.83733 1.83496 1.83280 1.83296 1.83288 1.83242 - 12.36036 11.03440 9.95858 9.01988 8.20451 7.48828 - 6.85439 6.28679 5.77209 5.30270 4.87250 4.47476 - 4.10155 3.74742 3.41149 3.09315 2.79002 2.49501 - 2.20267 2.05651 1.91020 1.79385 1.67957 1.65066 - 1.62718 1.62460 1.62253 1.62206 1.62178 1.62123 - 12.44977 11.11682 10.05048 9.11991 8.31168 7.59839 - 6.96549 6.39851 5.88518 5.41757 4.98864 4.59050 - 4.21356 3.85147 3.50395 3.17143 2.85144 2.53414 - 2.20938 2.04122 1.86474 1.71841 1.57854 1.54448 - 1.51712 1.51357 1.51046 1.51025 1.50996 1.51114 - 12.53296 11.19376 10.15469 9.25673 8.47681 7.78773 - 7.17482 6.62330 6.12042 5.65900 5.23309 4.83595 - 4.45920 4.09629 3.74418 3.39858 3.05305 2.69625 - 2.31261 2.10341 1.87401 1.67228 1.46983 1.42702 - 1.40001 1.39600 1.38909 1.38824 1.39055 1.39371 - 12.55465 11.22563 10.21960 9.35508 8.60170 7.93558 - 7.34240 6.80763 6.31851 5.86811 5.45071 5.05961 - 4.68630 4.32396 3.96931 3.61753 3.26012 2.88004 - 2.45195 2.20674 1.92666 1.67318 1.41639 1.36393 - 1.33707 1.33293 1.32293 1.32161 1.32589 1.32943 - 12.55029 11.23684 10.26459 9.43010 8.70063 8.05480 - 7.47894 6.95889 6.48211 6.04189 5.63284 5.24840 - 4.88011 4.52102 4.16753 3.81419 3.45062 3.05492 - 2.59298 2.31851 1.99478 1.69650 1.38942 1.32608 - 1.29714 1.29294 1.28076 1.27898 1.28433 1.28717 - 12.53428 11.23833 10.29839 9.49002 8.78170 8.15352 - 7.59260 7.08528 6.61933 6.18837 5.78723 5.40957 - 5.04704 4.69260 4.34229 3.99001 3.62368 3.21734 - 2.72899 2.43030 2.06931 1.73111 1.37741 1.30259 - 1.26952 1.26515 1.25139 1.24919 1.25507 1.25686 - 12.40333 11.21190 10.36887 9.62034 8.94692 8.33610 - 7.78247 7.27986 6.82299 6.40620 6.02313 5.66584 - 5.32349 4.98674 4.65012 4.30478 3.93379 3.50193 - 2.95871 2.62260 2.22067 1.83824 1.38827 1.26953 - 1.23168 1.23067 1.21340 1.20940 1.21735 1.21599 - 12.43240 11.23736 10.41411 9.68224 9.02590 8.43264 - 7.89707 7.41295 6.97483 6.57676 6.21186 5.87126 - 5.54249 5.21520 4.88465 4.54355 4.17815 3.75935 - 3.22163 2.85773 2.37231 1.89429 1.39598 1.27651 - 1.21527 1.20592 1.18836 1.18827 1.18683 1.18956 - 12.34843 11.20747 10.45663 9.78374 9.17720 8.62691 - 8.12862 7.67729 7.26847 6.89713 6.55734 6.24110 - 5.93680 5.63439 5.32857 5.01064 4.66352 4.24958 - 3.68465 3.28157 2.72229 2.14454 1.47851 1.29745 - 1.18851 1.17461 1.15405 1.15276 1.15084 1.15168 - 12.29035 11.18603 10.48046 9.84582 9.27174 8.74988 - 8.27659 7.84769 7.45933 7.10718 6.78598 6.48853 - 6.20405 5.92296 5.63973 5.34492 5.01906 4.61801 - 4.04616 3.62560 3.02926 2.38756 1.57792 1.33948 - 1.17868 1.15896 1.13587 1.13362 1.13148 1.13147 - 12.17108 11.13205 10.49811 9.92203 9.39625 8.91468 - 8.47505 8.07451 7.71062 7.38058 7.08101 6.80712 - 6.55154 6.30697 6.06738 5.82077 5.54004 5.16007 - 4.56532 4.12070 3.49867 2.80408 1.80379 1.46714 - 1.17341 1.13895 1.12003 1.11611 1.10199 1.11033 - 12.15786 11.13394 10.52299 9.96738 9.46080 8.99794 - 8.57671 8.19460 7.84940 7.53863 7.25911 7.00632 - 6.77301 6.55215 6.33854 6.12122 5.87438 5.53347 - 4.97613 4.53985 3.90142 3.15026 1.98971 1.57858 - 1.19364 1.14123 1.10686 1.10249 1.09167 1.09935 - 12.15472 11.14040 10.54243 9.99874 9.50373 9.05269 - 8.64359 8.27412 7.94220 7.64547 7.38093 7.14414 - 6.92780 6.72508 6.53150 6.33728 6.11829 5.81214 - 5.29451 4.87386 4.23501 3.44958 2.16342 1.68628 - 1.21786 1.14845 1.09840 1.09338 1.08614 1.09265 - 12.14292 11.14781 10.56477 10.03205 9.54499 9.10001 - 8.69588 8.33118 8.00489 7.71531 7.46020 7.23615 - 7.03738 6.85709 6.68703 6.50903 6.29531 6.00023 - 5.52328 5.14111 4.55172 3.77395 2.33176 1.76911 - 1.22790 1.15284 1.10056 1.09307 1.08904 1.08815 - 12.12865 11.15458 10.58651 10.06660 9.59095 9.15696 - 8.76387 8.41081 8.09736 7.82209 7.58292 7.37651 - 7.19706 7.03816 6.89303 6.74578 6.57103 6.32404 - 5.90521 5.55551 4.99502 4.21229 2.63718 1.97457 - 1.27378 1.16874 1.09717 1.09122 1.08040 1.08249 - 12.12236 11.16129 10.60133 10.08886 9.62032 9.19355 - 8.80784 8.46243 8.15702 7.89050 7.66111 7.46605 - 7.30023 7.15795 7.03317 6.91082 6.76628 6.55546 - 6.18116 5.85944 5.33191 4.56709 2.91284 2.16033 - 1.31916 1.18961 1.09757 1.08953 1.07630 1.07904 - 12.11131 11.17463 10.62522 10.12210 9.66247 9.24499 - 8.86912 8.53449 8.24114 7.98794 7.77312 7.59448 - 7.44863 7.33177 7.23958 7.15924 7.06950 6.93107 - 6.64599 6.37256 5.90116 5.19726 3.50605 2.56980 - 1.42520 1.24738 1.10452 1.08938 1.07399 1.07439 - 12.10858 11.18668 10.63579 10.13437 9.67927 9.26826 - 8.90003 8.57343 8.28772 8.04197 7.83502 7.66485 - 7.52727 7.41933 7.34153 7.29082 7.25110 7.16541 - 6.92896 6.69520 6.29138 5.64250 3.92331 2.93499 - 1.53900 1.30401 1.11325 1.09245 1.07258 1.07206 - 12.05227 11.19244 10.64744 10.15140 9.70158 9.29605 - 8.93356 8.61315 8.33422 8.09613 7.89800 7.73821 - 7.61314 7.52079 7.46310 7.43960 7.43877 7.41189 - 7.26657 7.09516 6.76845 6.20790 4.58054 3.49965 - 1.74896 1.42578 1.13521 1.10068 1.07095 1.06970 - 12.00298 11.19447 10.65261 10.15942 9.71240 9.30978 - 8.95038 8.63333 8.35806 8.12406 7.93061 7.77630 - 7.65780 7.57362 7.52658 7.51786 7.53901 7.54741 - 7.46047 7.33111 7.05940 6.56887 5.05275 3.93789 - 1.94361 1.54405 1.15911 1.11016 1.07109 1.06851 - 11.94626 11.18856 10.65661 10.16879 9.72423 9.32264 - 8.96358 8.64698 8.37292 8.14087 7.94982 7.79887 - 7.68686 7.61322 7.57765 7.57389 7.59193 7.61381 - 7.57759 7.48344 7.26090 6.85030 5.43728 4.24217 - 2.12491 1.67231 1.18408 1.11089 1.07714 1.06780 - 11.92112 11.18884 10.65827 10.17195 9.72877 9.32850 - 8.97077 8.65553 8.38293 8.15251 7.96337 7.81474 - 7.70564 7.63572 7.60493 7.60743 7.63451 7.67167 - 7.66523 7.59596 7.40804 7.04043 5.71857 4.54287 - 2.29414 1.77856 1.20917 1.12163 1.08022 1.06732 - 11.88940 11.18964 10.66095 10.17614 9.73451 9.33588 - 8.97990 8.66650 8.39589 8.16765 7.98103 7.83540 - 7.73009 7.66498 7.64041 7.65097 7.68944 7.74609 - 7.78007 7.74675 7.61031 7.30622 6.13521 5.02450 - 2.60649 1.97588 1.25913 1.14486 1.08612 1.06672 - 11.86883 11.19055 10.66310 10.17916 9.73826 9.34054 - 8.98558 8.67313 8.40324 8.17591 7.99114 7.84851 - 7.74637 7.68392 7.66227 7.67751 7.72378 7.79077 - 7.84848 7.84404 7.75333 7.48540 6.39207 5.41174 - 2.90018 2.15318 1.30634 1.17477 1.08265 1.06635 - 11.83878 11.19158 10.66566 10.18276 9.74296 9.34645 - 8.99285 8.68194 8.41389 8.18865 8.00613 7.86596 - 7.76682 7.70826 7.69180 7.71419 7.77094 7.85550 - 7.94585 7.97237 7.94366 7.77077 6.87962 6.02539 - 3.48676 2.56336 1.42463 1.23340 1.09587 1.06588 - 11.82182 11.19203 10.66669 10.18451 9.74538 9.34951 - 8.99657 8.68638 8.41915 8.19489 8.01350 7.87470 - 7.77721 7.72074 7.70701 7.73308 7.79525 7.88928 - 7.99708 8.03972 8.04449 7.92917 7.18299 6.42708 - 3.94595 2.91330 1.53808 1.29386 1.10921 1.06564 - 11.80364 11.19217 10.66751 10.18617 9.74783 9.35267 - 9.00036 8.69083 8.42434 8.20096 8.02069 7.88329 - 7.78755 7.73322 7.72226 7.75209 7.81989 7.92386 - 8.05003 8.10923 8.14795 8.09790 7.54820 6.93207 - 4.62732 3.47479 1.74969 1.41432 1.13542 1.06541 - 11.81493 11.19909 10.66683 10.18220 9.74350 9.34946 - 8.99911 8.69182 8.42729 8.20540 8.02598 7.88829 - 7.78987 7.73069 7.71662 7.75398 7.84402 7.96410 - 8.08417 8.14151 8.19110 8.18010 7.77345 7.23609 - 5.10458 3.91540 1.94602 1.53287 1.15968 1.06530 - 11.80877 11.19923 10.66723 10.18287 9.74441 9.35057 - 9.00040 8.69331 8.42898 8.20732 8.02817 7.89082 - 7.79289 7.73436 7.72122 7.75987 7.85178 7.97460 - 8.09992 8.16295 8.22473 8.23638 7.90951 7.44744 - 5.46654 4.26616 2.13889 1.64747 1.18410 1.06523 - 11.80440 11.19930 10.66754 10.18330 9.74499 9.35128 - 9.00126 8.69428 8.43010 8.20859 8.02964 7.89253 - 7.79492 7.73683 7.72430 7.76380 7.85695 7.98170 - 8.11066 8.17752 8.24728 8.27435 8.00607 7.60019 - 5.74977 4.55857 2.31823 1.76053 1.20816 1.06519 - 11.77834 11.19315 10.66935 10.18850 9.75070 9.35629 - 9.00494 8.69652 8.43119 8.20904 8.03005 7.89409 - 7.80020 7.74848 7.74117 7.77613 7.85147 7.96759 - 8.11873 8.20219 8.28292 8.32171 8.13456 7.80602 - 6.17052 5.02343 2.63958 1.98308 1.25639 1.06513 - 11.77471 11.19282 10.66935 10.18866 9.75099 9.35660 - 9.00519 8.69674 8.43157 8.20970 8.03108 7.89549 - 7.80200 7.75069 7.74377 7.77915 7.85513 7.97295 - 8.12701 8.21283 8.30080 8.35244 8.21224 7.93911 - 6.47110 5.38288 2.92103 2.18286 1.30326 1.06509 - 0.85645 0.89059 0.92563 0.96181 0.99916 1.03775 - 1.07766 1.11906 1.16218 1.20721 1.25440 1.30420 - 1.35736 1.41378 1.47064 1.52101 1.55733 1.57907 - 1.59322 1.60253 1.61368 1.62244 1.62413 1.62362 - 1.62447 1.62446 1.62400 1.62405 1.62471 1.62459 - 1.17958 1.22218 1.26615 1.31187 1.35940 1.40874 - 1.45985 1.51270 1.56715 1.62306 1.68009 1.73779 - 1.79550 1.85227 1.90680 1.95728 2.00155 2.03790 - 2.06128 2.06359 2.05593 2.04521 2.06331 2.07951 - 2.07454 2.07085 2.07095 2.07197 2.07100 2.07213 - 1.47557 1.52540 1.57646 1.62929 1.68390 1.74023 - 1.79823 1.85773 1.91854 1.98040 2.04285 2.10524 - 2.16672 2.22610 2.28180 2.33182 2.37399 2.40746 - 2.42856 2.43040 2.42326 2.41431 2.43656 2.45387 - 2.44631 2.44223 2.44308 2.44421 2.44258 2.44382 - 1.97901 2.05311 2.12469 2.19426 2.26150 2.32633 - 2.38890 2.44991 2.51045 2.57067 2.63055 2.69007 - 2.74973 2.80933 2.86658 2.91689 2.95578 2.98410 - 3.00285 3.00884 3.01620 3.02395 3.03058 3.03158 - 3.03084 3.03155 3.03249 3.03166 3.03139 3.03116 - 2.41249 2.50338 2.58824 2.66756 2.74096 2.80847 - 2.87081 2.92976 2.98788 3.04560 3.10271 3.15876 - 3.21341 3.26600 3.31504 3.35829 3.39360 3.42117 - 3.44128 3.44905 3.45893 3.46929 3.47831 3.47895 - 3.47603 3.47742 3.47934 3.47752 3.47695 3.47650 - 2.78992 2.89398 2.98855 3.07418 3.15041 3.21747 - 3.27661 3.33067 3.38355 3.43597 3.48762 3.53779 - 3.58563 3.63025 3.67085 3.70692 3.73797 3.76398 - 3.78500 3.79439 3.80647 3.81889 3.82950 3.82989 - 3.82553 3.82736 3.82992 3.82746 3.82671 3.82611 - 3.12318 3.23715 3.33843 3.42767 3.50440 3.56903 - 3.62330 3.67098 3.71710 3.76266 3.80733 3.85033 - 3.89060 3.92724 3.95996 3.98936 4.01604 4.04001 - 4.06143 4.07208 4.08567 4.09929 4.11078 4.11108 - 4.10609 4.10811 4.11094 4.10820 4.10736 4.10672 - 3.71999 3.81286 3.89926 3.98055 4.05575 4.12387 - 4.18389 4.23490 4.27623 4.30761 4.32979 4.34473 - 4.35673 4.36978 4.38455 4.40163 4.42203 4.44755 - 4.47936 4.49572 4.50731 4.51221 4.52425 4.52884 - 4.52372 4.52427 4.52690 4.52538 4.52428 4.52365 - 4.16215 4.27969 4.38047 4.46591 4.53511 4.58787 - 4.62514 4.64948 4.66468 4.67240 4.67468 4.67515 - 4.68023 4.69459 4.71510 4.73224 4.73908 4.74647 - 4.76584 4.77880 4.79233 4.80303 4.81313 4.81412 - 4.81280 4.81338 4.81489 4.81462 4.81260 4.81296 - 5.08903 5.16388 5.22621 5.27906 5.32140 5.35224 - 5.37071 5.37622 5.36863 5.34835 5.31756 5.28004 - 5.24268 5.21189 5.18965 5.17792 5.17863 5.19176 - 5.21540 5.22717 5.22844 5.21965 5.22377 5.23246 - 5.23562 5.23412 5.23297 5.23395 5.23567 5.23560 - 5.69937 5.80005 5.86682 5.90424 5.91302 5.89569 - 5.85726 5.80597 5.75198 5.69837 5.64671 5.59874 - 5.55716 5.52381 5.49764 5.47462 5.45231 5.43717 - 5.43637 5.43927 5.43565 5.42617 5.42310 5.42693 - 5.43880 5.43565 5.43105 5.43587 5.43741 5.43857 - 6.63396 6.68340 6.69320 6.67115 6.61934 6.54178 - 6.44518 6.33959 6.23652 6.13979 6.05059 5.96991 - 5.89956 5.83979 5.78870 5.74032 5.69103 5.64937 - 5.62450 5.61500 5.59533 5.56980 5.55377 5.55732 - 5.57580 5.57008 5.56188 5.57026 5.57290 5.57493 - 7.29690 7.29345 7.24762 7.17010 7.06411 6.93482 - 6.79010 6.64127 6.50069 6.37217 6.25640 6.15295 - 6.06191 5.98180 5.91033 5.84138 5.77112 5.70794 - 5.66089 5.64028 5.60995 5.57654 5.55233 5.55348 - 5.56974 5.56398 5.55582 5.56398 5.56652 5.56850 - 7.80834 7.75452 7.65746 7.53026 7.37688 7.20341 - 7.01848 6.83394 6.66290 6.50875 6.37156 6.24966 - 6.14134 6.04391 5.95502 5.86909 5.78254 5.70214 - 5.63569 5.60573 5.56918 5.53384 5.50534 5.50296 - 5.51117 5.50708 5.50145 5.50680 5.50845 5.50978 - 8.22293 8.12195 7.97810 7.80643 7.61144 7.39984 - 7.18067 6.96594 6.76911 6.59325 6.43764 6.29964 - 6.17594 6.06312 5.95890 5.85863 5.75909 5.66471 - 5.58144 5.54368 5.50372 5.46981 5.43943 5.43310 - 5.43053 5.42892 5.42701 5.42833 5.42871 5.42909 - 8.83369 8.70726 8.48473 8.20708 7.90921 7.62391 - 7.35730 7.11052 6.88529 6.68159 6.49689 6.32796 - 6.17196 6.02736 5.89319 5.76847 5.65151 5.53869 - 5.42825 5.37663 5.33119 5.30141 5.26892 5.25451 - 5.23636 5.23674 5.24082 5.23968 5.23247 5.23352 - 9.33478 9.06536 8.76355 8.44861 8.12539 7.80065 - 7.48295 7.18325 6.91310 6.67442 6.46372 6.27582 - 6.10323 5.94108 5.78828 5.64379 5.50629 5.37297 - 5.24387 5.18475 5.13437 5.10246 5.06588 5.04953 - 5.02017 5.02464 5.03188 5.02324 5.02053 5.01850 - 10.19239 9.67604 9.18018 8.71858 8.28897 7.88940 - 7.51828 7.17509 6.85937 6.56998 6.30483 6.06114 - 5.83556 5.62641 5.43479 5.25965 5.09847 4.93972 - 4.77431 4.69368 4.62371 4.57855 4.52762 4.51033 - 4.49023 4.49069 4.49324 4.49055 4.48798 4.48716 - 10.64592 10.00128 9.39614 8.84074 8.33060 7.86265 - 7.43405 7.04279 6.68765 6.36563 6.07290 5.80498 - 5.55591 5.32187 5.10399 4.90157 4.71246 4.52869 - 4.34437 4.25470 4.17091 4.10924 4.04295 4.02826 - 4.02443 4.02183 4.01733 4.01932 4.02129 4.02174 - 11.08151 10.36884 9.63262 8.91671 8.25738 7.68329 - 7.18803 6.75729 6.37712 6.03276 5.70604 5.38902 - 5.09039 4.81599 4.56288 4.32401 4.09379 3.87918 - 3.68302 3.58767 3.49133 3.41433 3.34080 3.32520 - 3.31799 3.31479 3.31089 3.31246 3.31434 3.31439 - 11.45930 10.49573 9.64092 8.88027 8.20108 7.59424 - 7.05359 6.57056 6.13704 5.74660 5.39262 5.06743 - 4.76121 4.46759 4.18786 3.92515 3.68075 3.45070 - 3.23415 3.13206 3.03334 2.95776 2.88315 2.86371 - 2.84619 2.84513 2.84467 2.84340 2.84290 2.84257 - 11.66721 10.60682 9.68412 8.86956 8.14864 7.50879 - 6.94097 6.43403 5.97717 5.56354 5.18719 4.84149 - 4.51826 4.21190 3.92233 3.65012 3.39563 3.15553 - 2.92942 2.82277 2.72008 2.64190 2.56500 2.54489 - 2.52620 2.52530 2.52507 2.52346 2.52282 2.52289 - 11.81776 10.68745 9.71830 8.86652 8.11695 7.45484 - 6.86816 6.34385 5.86958 5.43842 5.04508 4.68390 - 4.34811 4.03281 3.73669 3.45827 3.19667 2.95002 - 2.71772 2.60761 2.50062 2.41831 2.33847 2.31856 - 2.30174 2.30021 2.29906 2.29833 2.29796 2.29851 - 12.02522 10.80301 9.77694 8.87967 8.09522 7.40679 - 6.79782 6.25270 5.75752 5.30549 4.89192 4.51196 - 4.16013 3.83206 3.52538 3.23694 2.96439 2.70700 - 2.46296 2.34603 2.23147 2.14244 2.05632 2.03575 - 2.02047 2.01812 2.01587 2.01621 2.01616 2.01650 - 12.16305 10.88668 9.83032 8.90922 8.10707 7.40529 - 6.78535 6.23036 5.72587 5.26491 4.84262 4.45389 - 4.09286 3.75510 3.43853 3.14051 2.85855 2.59017 - 2.33279 2.20815 2.08630 1.99166 1.89861 1.87589 - 1.85861 1.85622 1.85406 1.85421 1.85413 1.85347 - 12.35141 11.02264 9.94501 9.00668 8.19319 7.47997 - 6.84977 6.28615 5.77527 5.30943 4.88233 4.48713 - 4.11561 3.76229 3.42669 3.10888 2.80678 2.51274 - 2.22079 2.07463 1.92831 1.81193 1.69736 1.66834 - 1.64480 1.64220 1.64012 1.63965 1.63938 1.63867 - 12.43157 11.10172 10.03630 9.10653 8.29913 7.58702 - 6.95583 6.39126 5.88117 5.41736 4.99239 4.59782 - 4.22337 3.86239 3.51525 3.18344 2.86498 2.54906 - 2.22466 2.05635 1.87973 1.73343 1.59392 1.56003 - 1.53276 1.52923 1.52614 1.52592 1.52563 1.52728 - 12.48701 11.17617 10.15270 9.26238 8.48440 7.79361 - 7.17711 6.62195 6.11700 5.65516 5.23024 4.83515 - 4.46114 4.10128 3.75218 3.40897 3.06473 2.70819 - 2.32389 2.11420 1.88462 1.68329 1.48243 1.44036 - 1.41369 1.40974 1.40296 1.40206 1.40418 1.40905 - 12.44735 11.20214 10.24279 9.39842 8.64615 7.96883 - 7.35847 6.80728 6.30848 5.85515 5.43996 5.05431 - 4.68715 4.32993 3.97910 3.62959 3.27210 2.88787 - 2.45292 2.20742 1.93517 1.69220 1.43135 1.37069 - 1.34868 1.34677 1.33626 1.33426 1.33900 1.34437 - 12.42506 11.20585 10.28764 9.47832 8.75299 8.09715 - 7.50387 6.96610 6.47772 6.03243 5.62345 5.24265 - 4.87949 4.52540 4.17617 3.82543 3.46131 3.05950 - 2.58806 2.31360 2.00150 1.71829 1.40550 1.33019 - 1.30773 1.30665 1.29373 1.29101 1.29709 1.30171 - 12.39683 11.20058 10.31893 9.53908 8.83721 8.20036 - 7.62245 7.09705 6.61860 6.18131 5.77885 5.40357 - 5.04535 4.69570 4.34988 4.00046 3.63332 3.21934 - 2.71923 2.42074 2.07458 1.75523 1.39454 1.30485 - 1.27942 1.27878 1.26411 1.26080 1.26763 1.27099 - 12.34017 11.18151 10.35975 9.62627 8.96272 8.35746 - 7.80570 7.30192 6.84145 6.41925 6.02976 5.66604 - 5.31876 4.97960 4.64308 4.30014 3.93320 3.50513 - 2.96370 2.62773 2.22574 1.84375 1.39696 1.27987 - 1.24315 1.24238 1.22535 1.22121 1.22860 1.22941 - 12.35758 11.20026 10.40176 9.68732 9.04228 8.45519 - 7.92141 7.43547 6.99264 6.58775 6.21493 5.86661 - 5.53234 5.20319 4.87428 4.53786 4.17876 3.76422 - 3.22578 2.86046 2.37480 1.89831 1.40458 1.28703 - 1.22635 1.21724 1.20005 1.19974 1.19803 1.20240 - 12.26949 11.16374 10.43580 9.77949 9.18416 8.64047 - 8.14480 7.69269 7.28030 6.90329 6.55657 6.23331 - 5.92375 5.61918 5.31432 5.00022 4.65879 4.24946 - 3.68557 3.28217 2.72341 2.14754 1.48634 1.30714 - 1.19919 1.18556 1.16526 1.16379 1.16163 1.16352 - 12.21273 11.13949 10.45382 9.83376 9.26987 8.75430 - 8.28396 7.85505 7.46427 7.10778 6.78105 6.47784 - 6.18890 5.90584 5.62323 5.33149 5.01051 4.61405 - 4.04450 3.62456 3.02939 2.38985 1.58516 1.34851 - 1.18907 1.16963 1.14673 1.14434 1.14200 1.14269 - 12.10116 11.08469 10.46386 9.89797 9.37972 8.90335 - 8.46683 8.06757 7.70337 7.37174 7.06962 6.79281 - 6.53475 6.28883 6.04916 5.80381 5.52572 5.14935 - 4.55882 4.11671 3.49765 2.80613 1.81030 1.47506 - 1.18313 1.14908 1.13048 1.12650 1.11213 1.12083 - 12.09318 11.08657 10.48477 9.93646 9.43550 8.97678 - 8.55835 8.17788 7.83330 7.52227 7.24188 6.98789 - 6.75359 6.53240 6.31919 6.10312 5.85847 5.52055 - 4.96713 4.53339 3.89826 3.15069 1.99546 1.58595 - 1.20297 1.15100 1.11701 1.11260 1.10152 1.10946 - 12.09294 11.09874 10.50986 9.97165 9.47939 9.02928 - 8.61961 8.24825 7.91341 7.61384 7.34822 7.11357 - 6.90371 6.71029 6.52203 6.32125 6.08258 5.76212 - 5.26647 4.87926 4.27952 3.49138 2.15275 1.67716 - 1.22118 1.15658 1.11191 1.10755 1.09977 1.10252 - 12.08498 11.10145 10.52297 9.99392 9.50994 9.06748 - 8.66539 8.30238 7.97746 7.68903 7.43492 7.21187 - 7.01429 6.83550 6.66711 6.49065 6.27825 5.98484 - 5.51093 5.13121 4.54539 3.77160 2.33531 1.77520 - 1.23699 1.16233 1.11018 1.10268 1.09866 1.09786 - 12.09705 11.11703 10.54188 10.01889 9.54349 9.11223 - 8.72343 8.37512 8.06570 7.79340 7.55590 7.34960 - 7.16817 7.00594 6.85971 6.72107 6.56639 6.32997 - 5.89294 5.53156 4.97746 4.21457 2.64474 1.97757 - 1.28013 1.17788 1.10716 1.09934 1.09244 1.09200 - 12.08848 11.12214 10.55547 10.04004 9.57172 9.14752 - 8.76592 8.42509 8.12368 7.86021 7.63267 7.43786 - 7.27007 7.12425 6.99808 6.88417 6.76009 6.56043 - 6.16793 5.83422 5.31297 4.56590 2.91685 2.16665 - 1.32460 1.19727 1.10734 1.09780 1.08876 1.08842 - 12.05380 11.12409 10.57702 10.07679 9.62034 9.20582 - 8.83252 8.49981 8.20756 7.95507 7.74121 7.56410 - 7.41989 7.30455 7.21406 7.13629 7.04945 6.90992 - 6.62302 6.35455 5.89060 5.18968 3.49663 2.57765 - 1.43428 1.25342 1.11384 1.09773 1.08437 1.08359 - 12.04906 11.13616 10.58847 10.09003 9.63755 9.22890 - 8.86275 8.53800 8.25389 8.00957 7.80386 7.63479 - 7.49824 7.39132 7.31454 7.26490 7.22641 7.14230 - 6.90821 6.67623 6.27509 5.63002 3.91962 2.93607 - 1.54599 1.31191 1.12217 1.10144 1.08160 1.08118 - 11.99354 11.14212 10.60051 10.10754 9.66037 9.25713 - 8.89660 8.57787 8.30033 8.06339 7.86617 7.70712 - 7.58273 7.49105 7.43410 7.41142 7.41164 7.38627 - 7.24335 7.07367 6.74941 6.19223 4.57375 3.49827 - 1.75487 1.43298 1.14394 1.10959 1.07986 1.07872 - 11.94679 11.14526 10.60627 10.11572 9.67104 9.27048 - 8.91286 8.59736 8.32339 8.09048 7.89795 7.74440 - 7.62656 7.54299 7.49656 7.48850 7.51048 7.52017 - 7.43551 7.30786 7.03851 6.55119 5.04369 3.93445 - 1.94859 1.55069 1.16770 1.11902 1.07993 1.07748 - 11.89188 11.14015 10.61067 10.12524 9.68270 9.28293 - 8.92550 8.61032 8.33755 8.10664 7.91656 7.76644 - 7.65511 7.58204 7.54696 7.54370 7.56245 7.58550 - 7.55136 7.45883 7.23865 6.83124 5.42631 4.23668 - 2.12917 1.67861 1.19252 1.11963 1.08589 1.07674 - 11.86675 11.14103 10.61333 10.12902 9.68746 9.28872 - 8.93240 8.61829 8.34646 8.11675 7.92890 7.78218 - 7.67473 7.60546 7.57451 7.57653 7.60297 7.63826 - 7.63821 7.58056 7.39407 6.99700 5.67096 4.58487 - 2.30058 1.77075 1.21675 1.13986 1.08211 1.07625 - 11.83586 11.14194 10.61600 10.13324 9.69319 9.29597 - 8.94122 8.62884 8.35902 8.13163 7.94636 7.80260 - 7.69873 7.63390 7.60889 7.61921 7.65807 7.71312 - 7.74921 7.72457 7.59552 7.27367 6.07997 5.04829 - 2.61882 1.97240 1.26579 1.16108 1.08641 1.07562 - 11.81623 11.14245 10.61755 10.13574 9.69664 9.30043 - 8.94677 8.63553 8.36694 8.14087 7.95713 7.81520 - 7.71354 7.65147 7.63013 7.64558 7.69205 7.75944 - 7.81833 7.81517 7.72665 7.46176 6.37551 5.40049 - 2.90079 2.15746 1.31423 1.18326 1.09134 1.07525 - 11.78639 11.14318 10.61970 10.13902 9.70118 9.30644 - 8.95436 8.64478 8.37780 8.15346 7.97171 7.83221 - 7.73360 7.67540 7.65913 7.68159 7.73839 7.82304 - 7.91392 7.94129 7.91445 7.74456 6.86005 6.01062 - 3.48487 2.56606 1.43198 1.24152 1.10453 1.07476 - 11.76962 11.14373 10.62083 10.14073 9.70343 9.30936 - 8.95807 8.64930 8.38312 8.15962 7.97892 7.84077 - 7.74380 7.68765 7.67404 7.70011 7.76223 7.85622 - 7.96424 8.00743 8.01373 7.90110 7.16152 6.41020 - 3.94218 2.91456 1.54490 1.30160 1.11788 1.07452 - 11.75645 11.14238 10.61826 10.13963 9.70511 9.31348 - 8.96401 8.65623 8.39009 8.16597 7.98457 7.84644 - 7.75136 7.69954 7.69152 7.72147 7.78455 7.88458 - 8.02113 8.08978 8.11422 8.02461 7.53087 7.01768 - 4.57870 3.42039 1.75866 1.43869 1.14600 1.07429 - 11.76380 11.15099 10.62087 10.13825 9.70140 9.30901 - 8.96014 8.65415 8.39076 8.16982 7.99119 7.85409 - 7.75612 7.69722 7.68325 7.72049 7.81022 7.92994 - 8.04987 8.10735 8.15758 8.14816 7.74761 7.21495 - 5.09555 3.91199 1.95102 1.53930 1.16829 1.07417 - 11.75765 11.15094 10.62118 10.13878 9.70212 9.30995 - 8.96125 8.65547 8.39228 8.17159 7.99324 7.85652 - 7.75904 7.70080 7.68776 7.72628 7.81784 7.94026 - 8.06530 8.12836 8.19052 8.20344 7.88239 7.42485 - 5.45556 4.26090 2.14292 1.65340 1.19265 1.07410 - 11.75315 11.15091 10.62128 10.13909 9.70261 9.31056 - 8.96202 8.65638 8.39333 8.17281 7.99465 7.85816 - 7.76100 7.70321 7.69076 7.73012 7.82292 7.94723 - 8.07585 8.14265 8.21257 8.24064 7.97787 7.57640 - 5.73710 4.55167 2.32138 1.76615 1.21661 1.07405 - 11.72668 11.14396 10.62269 10.14419 9.70854 9.31586 - 8.96590 8.65866 8.39447 8.17336 7.99523 7.85981 - 7.76627 7.71474 7.70745 7.74226 7.81729 7.93295 - 8.08366 8.16705 8.24775 8.28711 8.10466 7.78017 - 6.15532 5.01395 2.64119 1.98764 1.26460 1.07398 - 11.72331 11.14313 10.62179 10.14367 9.70856 9.31637 - 8.96685 8.66003 8.39622 8.17529 7.99675 7.86053 - 7.76669 7.71609 7.71045 7.74637 7.82090 7.93582 - 8.09176 8.18286 8.26983 8.30325 8.15933 7.96204 - 6.45962 5.33085 2.91721 2.20704 1.30510 1.07391 - 0.83552 0.86881 0.90305 0.93847 0.97514 1.01310 - 1.05248 1.09344 1.13622 1.18104 1.22817 1.27806 - 1.33149 1.38835 1.44578 1.49666 1.53319 1.55475 - 1.56829 1.57716 1.58776 1.59593 1.59676 1.59589 - 1.59663 1.59685 1.59675 1.59667 1.59678 1.59672 - 1.15278 1.19488 1.23837 1.28366 1.33076 1.37969 - 1.43047 1.48301 1.53724 1.59300 1.64997 1.70772 - 1.76561 1.82272 1.87775 1.92888 1.97389 2.01084 - 2.03424 2.03612 2.02753 2.01560 2.03241 2.04837 - 2.04344 2.04010 2.04072 2.04155 2.03959 2.04090 - 1.44478 1.49424 1.54497 1.59752 1.65187 1.70800 - 1.76583 1.82525 1.88604 1.94796 2.01057 2.07323 - 2.13509 2.19499 2.25134 2.30211 2.34506 2.37913 - 2.40019 2.40156 2.39345 2.38329 2.40448 2.42168 - 2.41400 2.41001 2.41107 2.41212 2.41000 2.41136 - 1.94399 2.01736 2.08840 2.15760 2.22470 2.28957 - 2.35238 2.41381 2.47489 2.53578 2.59647 2.65694 - 2.71770 2.77851 2.83691 2.88798 2.92692 2.95474 - 2.97281 2.97849 2.98577 2.99351 2.99918 2.99996 - 2.99908 2.99891 2.99911 2.99913 2.99917 2.99912 - 2.37438 2.46473 2.54926 2.62847 2.70199 2.76984 - 2.83273 2.89242 2.95143 3.01020 3.06849 3.12580 - 3.18175 3.23557 3.28568 3.32965 3.36517 3.39257 - 3.41236 3.41998 3.42990 3.44034 3.44861 3.44930 - 3.44650 3.44605 3.44642 3.44643 3.44653 3.44646 - 2.74985 2.85355 2.94801 3.03375 3.11034 3.17799 - 3.23795 3.29301 3.34706 3.40079 3.45387 3.50551 - 3.55475 3.60058 3.64215 3.67893 3.71042 3.73663 - 3.75769 3.76710 3.77933 3.79190 3.80203 3.80266 - 3.79866 3.79801 3.79849 3.79851 3.79866 3.79859 - 3.10596 3.19518 3.28051 3.36296 3.44175 3.51603 - 3.58493 3.64758 3.70329 3.75156 3.79270 3.82772 - 3.85952 3.89072 3.92124 3.95087 3.97964 4.00878 - 4.03890 4.05314 4.06475 4.07199 4.08403 4.08748 - 4.08210 4.08087 4.08151 4.08160 4.08199 4.08175 - 3.67692 3.77023 3.85723 3.93928 4.01540 4.08457 - 4.14581 4.19818 4.24099 4.27396 4.29781 4.31442 - 4.32801 4.34251 4.35853 4.37664 4.39785 4.42414 - 4.45686 4.47373 4.48582 4.49112 4.50361 4.50864 - 4.50369 4.50239 4.50308 4.50315 4.50362 4.50336 - 4.11882 4.23669 4.33812 4.42448 4.49485 4.54901 - 4.58788 4.61392 4.63091 4.64044 4.64445 4.64655 - 4.65303 4.66855 4.69003 4.70828 4.71660 4.72559 - 4.74636 4.75989 4.77400 4.78521 4.79617 4.79775 - 4.79640 4.79610 4.79639 4.79654 4.79642 4.79655 - 5.04490 5.12122 5.18517 5.23966 5.28367 5.31622 - 5.33640 5.34359 5.33768 5.31906 5.28985 5.25390 - 5.21807 5.18882 5.16813 5.15799 5.16039 5.17540 - 5.20118 5.21407 5.21630 5.20819 5.21361 5.22264 - 5.22595 5.22577 5.22605 5.22592 5.22654 5.22621 - 5.65736 5.75884 5.82693 5.86605 5.87684 5.86176 - 5.82567 5.77659 5.72453 5.67253 5.62218 5.57539 - 5.53505 5.50319 5.47881 5.45788 5.43791 5.42510 - 5.42637 5.43016 5.42749 5.41899 5.41771 5.42123 - 5.43262 5.43430 5.43375 5.43377 5.43357 5.43369 - 6.59453 6.64540 6.65707 6.63721 6.58781 6.51280 - 6.41871 6.31547 6.21437 6.11925 6.03139 5.95194 - 5.88295 5.82491 5.77588 5.72977 5.68277 5.64333 - 5.62045 5.61187 5.59311 5.56853 5.55413 5.55677 - 5.57435 5.57706 5.57587 5.57588 5.57545 5.57569 - 7.26017 7.25873 7.21529 7.14033 7.03703 6.91045 - 6.76835 6.62191 6.48338 6.35657 6.24224 6.14015 - 6.05057 5.97226 5.90287 5.83611 5.76797 5.70680 - 5.66165 5.64192 5.61245 5.57985 5.55686 5.55706 - 5.57248 5.57495 5.57362 5.57361 5.57314 5.57339 - 7.77414 7.72289 7.62869 7.50442 7.35398 7.18339 - 7.00118 6.81910 6.65017 6.49780 6.36213 6.24166 - 6.13485 6.03919 5.95229 5.86842 5.78384 5.70533 - 5.64069 5.61161 5.57590 5.54127 5.51356 5.51055 - 5.51830 5.51965 5.51851 5.51847 5.51814 5.51832 - 8.19119 8.09328 7.95269 7.78427 7.59245 7.38390 - 7.16756 6.95536 6.76069 6.58666 6.43262 6.29606 - 6.17385 6.06272 5.96035 5.86199 5.76431 5.67175 - 5.59028 5.55339 5.51430 5.48102 5.45104 5.44460 - 5.44207 5.44188 5.44113 5.44106 5.44093 5.44101 - 8.80732 8.68291 8.46412 8.19098 7.89752 7.61581 - 7.35200 7.10746 6.88418 6.68221 6.49912 6.33177 - 6.17731 6.03421 5.90157 5.77843 5.66315 5.55208 - 5.44348 5.39280 5.34818 5.31872 5.28635 5.27315 - 5.25422 5.25139 5.25101 5.25134 5.25089 5.25114 - 9.31094 9.04617 8.74889 8.43813 8.11879 7.79755 - 7.48296 7.18593 6.91804 6.68123 6.47210 6.28555 - 6.11423 5.95336 5.80187 5.65882 5.52289 5.39125 - 5.26385 5.20559 5.15609 5.12464 5.08772 5.07259 - 5.04434 5.04031 5.04047 5.04032 5.04070 5.04047 - 10.17467 9.66449 9.17419 8.71741 8.29199 7.89602 - 7.52799 7.18743 6.87391 6.58632 6.32266 6.08024 - 5.85577 5.64768 5.45705 5.28291 5.12280 4.96535 - 4.80154 4.72169 4.65221 4.60709 4.55637 4.53963 - 4.51930 4.51657 4.51589 4.51586 4.51591 4.51572 - 10.63262 9.99468 9.39534 8.84489 8.33898 7.87461 - 7.44904 7.06031 6.70726 6.38694 6.09562 5.82888 - 5.58083 5.34774 5.13074 4.92915 4.74089 4.55807 - 4.37480 4.28561 4.20205 4.14035 4.07418 4.05918 - 4.05527 4.05538 4.05371 4.05339 4.05309 4.05303 - 11.07074 10.36832 9.63865 8.92686 8.27055 7.69937 - 7.20696 6.77871 6.40046 6.05752 5.73201 5.41614 - 5.11851 4.84501 4.59265 4.35434 4.12453 3.91051 - 3.71496 3.61951 3.52284 3.44559 3.37230 3.35616 - 3.34892 3.34818 3.34658 3.34625 3.34613 3.34582 - 11.45054 10.49570 9.64752 8.89184 8.21638 7.61233 - 7.07374 6.59235 6.16025 5.77114 5.41838 5.09430 - 4.78905 4.49624 4.21713 3.95492 3.71091 3.48115 - 3.26471 3.16254 3.06357 2.98762 2.91269 2.89336 - 2.87592 2.87378 2.87241 2.87221 2.87210 2.87200 - 11.65782 10.60674 9.69075 8.88110 8.16375 7.52645 - 6.96044 6.45491 5.99930 5.58685 5.21160 4.86693 - 4.54459 4.23897 3.95000 3.67826 3.42412 3.18423 - 2.95814 2.85142 2.74859 2.67013 2.59259 2.57252 - 2.55390 2.55155 2.55011 2.54993 2.54981 2.55014 - 11.80700 10.68646 9.72410 8.87724 8.13112 7.47139 - 6.88638 6.36334 5.89021 5.46012 5.06780 4.70758 - 4.37265 4.05809 3.76257 3.48461 3.22335 2.97687 - 2.74460 2.63448 2.52745 2.44496 2.36435 2.34427 - 2.32737 2.32526 2.32363 2.32346 2.32327 2.32388 - 12.01116 10.79937 9.78017 8.88778 8.10668 7.42047 - 6.81299 6.26900 5.77486 5.32387 4.91133 4.53238 - 4.18145 3.85416 3.54815 3.26020 2.98797 2.73072 - 2.48677 2.36988 2.25535 2.16623 2.07944 2.05853 - 2.04303 2.04118 2.03935 2.03916 2.03892 2.03913 - 12.14555 10.88006 9.83062 8.91442 8.11556 7.41593 - 6.79743 6.24355 5.74012 5.28027 4.85911 4.47149 - 4.11151 3.77467 3.45885 3.16139 2.87974 2.61153 - 2.35426 2.22967 2.10784 2.01312 1.91963 1.89670 - 1.87923 1.87721 1.87535 1.87512 1.87490 1.87425 - 12.32712 11.00943 9.93859 9.00512 8.19491 7.48391 - 6.85525 6.29286 5.78318 5.31856 4.89276 4.49886 - 4.12866 3.77663 3.44219 3.12525 2.82372 2.53011 - 2.23858 2.09258 1.94629 1.82976 1.71479 1.68566 - 1.66201 1.65924 1.65702 1.65670 1.65648 1.65584 - 12.40258 11.08339 10.02446 9.09946 8.29540 7.58571 - 6.95629 6.39312 5.88431 5.42173 4.99800 4.60474 - 4.23177 3.87239 3.52684 3.19636 2.87889 2.56385 - 2.24038 2.07245 1.89598 1.74944 1.60904 1.57481 - 1.54731 1.54385 1.54082 1.54051 1.54017 1.54151 - 12.45169 11.15109 10.13357 9.24769 8.47295 7.78466 - 7.17013 6.61658 6.11309 5.65262 5.22906 4.83538 - 4.46294 4.10481 3.75760 3.41637 3.07413 2.71960 - 2.33717 2.12823 1.89903 1.69744 1.49493 1.45195 - 1.42493 1.42153 1.41566 1.41450 1.41509 1.41935 - 12.40852 11.17270 10.21852 9.37823 8.62925 7.95463 - 7.34656 6.79729 6.30012 5.84826 5.43446 5.05016 - 4.68454 4.32909 3.98028 3.63307 3.27818 2.89670 - 2.46444 2.22005 1.94844 1.70525 1.44241 1.38057 - 1.35808 1.35705 1.34803 1.34560 1.34792 1.35259 - 12.38341 11.17362 10.26035 9.45499 8.73282 8.07966 - 7.48862 6.95277 6.46605 6.02227 5.61470 5.23533 - 4.87377 4.52155 4.17449 3.82626 3.46500 3.06635 - 2.59810 2.32502 2.01377 1.73043 1.41561 1.33908 - 1.31614 1.31602 1.30476 1.30157 1.30496 1.30894 - 12.35338 11.16652 10.28965 9.51350 8.81473 8.18049 - 7.60482 7.08133 6.60457 6.16880 5.76780 5.39399 - 5.03742 4.68969 4.34610 3.99927 3.63514 3.22454 - 2.72796 2.43105 2.08593 1.76656 1.40396 1.31313 - 1.28725 1.28757 1.27454 1.27076 1.27495 1.27777 - 12.29452 11.14514 10.32782 9.59778 8.93715 8.33442 - 7.78486 7.28302 6.82426 6.40364 6.01566 5.65347 - 5.30785 4.97064 4.63637 4.29605 3.93219 3.50770 - 2.97018 2.63605 2.23541 1.85370 1.40545 1.28746 - 1.25043 1.25049 1.23487 1.23033 1.23546 1.23595 - 12.31079 11.16269 10.36813 9.65692 9.01469 8.43009 - 7.89852 7.41457 6.97353 6.57031 6.19907 5.85232 - 5.51971 5.19237 4.86554 4.53152 4.17534 3.76449 - 3.23053 2.86736 2.38307 1.90677 1.41245 1.29440 - 1.23328 1.22512 1.20903 1.20790 1.20524 1.20902 - 12.22137 11.12466 10.40002 9.74669 9.15391 8.61257 - 8.11903 7.66890 7.25833 6.88303 6.53794 6.21628 - 5.90834 5.60546 5.30244 4.99047 4.65167 4.24588 - 3.68664 3.28568 2.72874 2.15373 1.49317 1.31402 - 1.20616 1.19314 1.17350 1.17158 1.16882 1.17051 - 12.16405 11.09969 10.41717 9.79982 9.23837 8.72503 - 8.25677 7.82980 7.44081 7.08603 6.76092 6.45926 - 6.17187 5.89036 5.60943 5.31957 5.00096 4.60777 - 4.04277 3.62537 3.03243 2.39436 1.59132 1.35507 - 1.19621 1.17722 1.15474 1.15208 1.14935 1.14998 - 12.05179 11.04420 10.42641 9.86308 9.34713 8.87291 - 8.43833 8.04088 7.67835 7.34828 7.04763 6.77223 - 6.51557 6.27109 6.03292 5.78928 5.51324 5.13956 - 4.55283 4.11319 3.49710 2.80836 1.81568 1.48123 - 1.19047 1.15677 1.13849 1.13445 1.11971 1.12855 - 12.04354 11.04588 10.44687 9.90107 9.40233 8.94564 - 8.52912 8.15037 7.80738 7.49782 7.21881 6.96613 - 6.73310 6.51319 6.30133 6.08673 5.84384 5.50827 - 4.95834 4.52705 3.89513 3.15093 2.00014 1.59188 - 1.21040 1.15880 1.12514 1.12070 1.10934 1.11743 - 12.04440 11.05266 10.46363 9.92753 9.43885 8.99310 - 8.58834 8.22234 7.89316 7.59854 7.33560 7.10010 - 6.88508 6.68399 6.49245 6.30085 6.08529 5.78374 - 5.27280 4.85696 4.22480 3.44705 2.17243 1.69885 - 1.23440 1.16582 1.11657 1.11150 1.10376 1.11066 - 12.03529 11.06047 10.48461 9.95795 9.47610 9.03556 - 8.63523 8.27382 7.95037 7.66329 7.41043 7.18855 - 6.99209 6.81439 6.64711 6.47182 6.26076 5.96925 - 5.49849 5.12123 4.53893 3.76900 2.33817 1.78031 - 1.24475 1.17043 1.11839 1.11088 1.10686 1.10612 - 12.04739 11.07596 10.50339 9.98261 9.50925 9.07984 - 8.69272 8.34594 8.03790 7.76686 7.53050 7.32524 - 7.14481 6.98353 6.83825 6.70062 6.54715 6.31240 - 5.87817 5.51904 4.96836 4.20971 2.64656 1.98198 - 1.28783 1.18601 1.11547 1.10764 1.10081 1.10041 - 12.03884 11.08098 10.51676 10.00353 9.53720 9.11479 - 8.73480 8.39544 8.09536 7.83306 7.60657 7.41273 - 7.24585 7.10091 6.97560 6.86261 6.73960 6.54143 - 6.15142 5.81983 5.30194 4.55925 2.91754 2.17042 - 1.33219 1.20534 1.11569 1.10616 1.09722 1.09693 - 12.00442 11.08285 10.53809 10.03993 9.58534 9.17249 - 8.80070 8.46932 8.17829 7.92688 7.71397 7.53772 - 7.39429 7.27967 7.18989 7.11289 7.02702 6.88874 - 6.60378 6.33702 5.87611 5.17958 3.49506 2.57982 - 1.44143 1.26123 1.12220 1.10615 1.09296 1.09224 - 11.99996 11.09482 10.54942 10.05293 9.60227 9.19525 - 8.83057 8.50713 8.22416 7.98085 7.77603 7.60772 - 7.47187 7.36558 7.28944 7.24043 7.20264 7.11954 - 6.88724 6.65687 6.25850 5.61746 3.91591 2.93705 - 1.55270 1.31940 1.13053 1.10992 1.09025 1.08990 - 11.94549 11.10070 10.56125 10.07022 9.62480 9.22312 - 8.86401 8.54652 8.27006 8.03406 7.83765 7.67929 - 7.55550 7.46436 7.40786 7.38564 7.38635 7.36177 - 7.22032 7.05198 6.72999 6.17636 4.56697 3.49689 - 1.76065 1.43996 1.15236 1.11821 1.08855 1.08752 - 11.89945 11.10374 10.56690 10.07830 9.63534 9.23631 - 8.88008 8.56580 8.29290 8.06091 7.86914 7.71625 - 7.59893 7.51580 7.46974 7.46199 7.48430 7.49458 - 7.41119 7.28472 7.01735 6.53317 5.03456 3.93101 - 1.95347 1.55721 1.17615 1.12772 1.08863 1.08632 - 11.84532 11.09873 10.57139 10.08774 9.64690 9.24865 - 8.89258 8.57861 8.30691 8.07689 7.88760 7.73807 - 7.62722 7.55452 7.51972 7.51670 7.53573 7.55928 - 7.52618 7.43463 7.21621 6.81175 5.41525 4.23121 - 2.13340 1.68488 1.20093 1.12832 1.09453 1.08560 - 11.82060 11.09962 10.57395 10.09148 9.65161 9.25440 - 8.89944 8.58650 8.31573 8.08691 7.89980 7.75364 - 7.64663 7.57771 7.54700 7.54919 7.57583 7.61147 - 7.61233 7.55563 7.37070 6.97620 5.65846 4.57812 - 2.30385 1.77648 1.22511 1.14858 1.09079 1.08511 - 11.79012 11.10043 10.57653 10.09559 9.65724 9.26153 - 8.90814 8.59694 8.32815 8.10163 7.91708 7.77390 - 7.67043 7.60589 7.58102 7.59143 7.63039 7.68562 - 7.72232 7.69845 7.57079 7.25123 6.06495 5.03897 - 2.62068 1.97739 1.27391 1.16970 1.09509 1.08450 - 11.77081 11.10095 10.57797 10.09802 9.66063 9.26594 - 8.91362 8.60356 8.33600 8.11081 7.92777 7.78637 - 7.68509 7.62327 7.60204 7.61751 7.66401 7.73148 - 7.79077 7.78825 7.70095 7.43816 6.35860 5.38913 - 2.90150 2.16177 1.32209 1.19173 1.10002 1.08414 - 11.74157 11.10168 10.58002 10.10124 9.66508 9.27185 - 8.92112 8.61269 8.34673 8.12324 7.94217 7.80319 - 7.70495 7.64695 7.63076 7.65318 7.70988 7.79444 - 7.88540 7.91310 7.88723 7.71907 6.84010 5.99578 - 3.48307 2.56874 1.43924 1.24961 1.11322 1.08366 - 11.72509 11.10214 10.58125 10.10291 9.66733 9.27476 - 8.92481 8.61718 8.35198 8.12928 7.94921 7.81156 - 7.71498 7.65904 7.64551 7.67152 7.73347 7.82726 - 7.93520 7.97857 7.98559 7.87446 7.13976 6.39312 - 3.93843 2.91578 1.55167 1.30935 1.12658 1.08342 - 11.71212 11.10088 10.57868 10.10190 9.66899 9.27882 - 8.93063 8.62399 8.35881 8.13551 7.95473 7.81711 - 7.72238 7.67075 7.66283 7.69271 7.75555 7.85529 - 7.99152 8.06014 8.08505 7.99675 7.50706 6.99716 - 4.57201 3.41954 1.76460 1.44574 1.15479 1.08319 - 11.71962 11.10950 10.58139 10.10053 9.66531 9.27437 - 8.92678 8.62192 8.35948 8.13936 7.96135 7.82476 - 7.72712 7.66842 7.65451 7.69163 7.78106 7.90039 - 8.01999 8.07743 8.12790 8.11931 7.72240 7.19338 - 5.08637 3.90869 1.95619 1.54589 1.17692 1.08309 - 11.71356 11.10945 10.58159 10.10102 9.66599 9.27527 - 8.92787 8.62321 8.36101 8.14111 7.96342 7.82719 - 7.73006 7.67202 7.65901 7.69736 7.78859 7.91057 - 8.03522 8.09819 8.16048 8.17406 7.85627 7.40207 - 5.44445 4.25573 2.14710 1.65947 1.20120 1.08303 - 11.70914 11.10941 10.58170 10.10133 9.66646 9.27588 - 8.92864 8.62413 8.36206 8.14235 7.96486 7.82887 - 7.73206 7.67444 7.66201 7.70118 7.79359 7.91741 - 8.04562 8.11231 8.18233 8.21096 7.95099 7.55248 - 5.72430 4.54483 2.32459 1.77177 1.22505 1.08299 - 11.68276 11.10256 10.58320 10.10648 9.67239 9.28115 - 8.93247 8.62639 8.36320 8.14293 7.96544 7.83055 - 7.73733 7.68593 7.67857 7.71318 7.78792 7.90317 - 8.05336 8.13648 8.21711 8.25687 8.07678 7.75476 - 6.13998 5.00449 2.64282 1.99219 1.27284 1.08293 - 11.67944 11.10184 10.58251 10.10612 9.67252 9.28174 - 8.93349 8.62779 8.36494 8.14478 7.96684 7.83107 - 7.73755 7.68713 7.68153 7.71731 7.79154 7.90597 - 8.06133 8.15217 8.23901 8.27262 8.13060 7.93571 - 6.44255 5.31921 2.91755 2.21097 1.31313 1.08289 - 0.81220 0.84645 0.88130 0.91694 0.95341 0.99080 - 1.02930 1.06923 1.11112 1.15526 1.20200 1.25191 - 1.30585 1.36371 1.42216 1.47291 1.50782 1.53021 - 1.54557 1.55182 1.56154 1.57104 1.56988 1.56894 - 1.56973 1.56983 1.56963 1.56970 1.56956 1.56965 - 1.12698 1.16835 1.21113 1.25573 1.30217 1.35050 - 1.40071 1.45276 1.50660 1.56207 1.61892 1.67672 - 1.73488 1.79253 1.84839 1.90065 1.94700 1.98507 - 2.00868 2.00998 2.00003 1.98641 2.00202 2.01816 - 2.01357 2.01022 2.01071 2.01153 2.00951 2.01085 - 1.41599 1.46463 1.51458 1.56636 1.62000 1.67547 - 1.73273 1.79166 1.85210 1.91383 1.97643 2.03932 - 2.10169 2.16243 2.21999 2.27233 2.31707 2.35263 - 2.37397 2.37459 2.36474 2.35245 2.37252 2.39018 - 2.38301 2.37900 2.37991 2.38094 2.37874 2.38014 - 1.92195 1.98673 2.05132 2.11637 2.18166 2.24694 - 2.31196 2.37649 2.44033 2.50326 2.56520 2.62620 - 2.68697 2.74760 2.80596 2.85788 2.89866 2.92650 - 2.94280 2.94904 2.95592 2.96234 2.96838 2.96904 - 2.96812 2.96795 2.96810 2.96818 2.96813 2.96811 - 2.34591 2.43081 2.51130 2.58801 2.66057 2.72892 - 2.79346 2.85537 2.91636 2.97663 3.03597 3.09398 - 3.15052 3.20505 3.25596 3.30077 3.33702 3.36474 - 3.38409 3.39120 3.40071 3.41096 3.41921 3.41991 - 3.41714 3.41667 3.41705 3.41707 3.41718 3.41711 - 2.71351 2.81669 2.91080 2.99638 3.07299 3.14085 - 3.20120 3.25685 3.31166 3.36631 3.42048 3.47334 - 3.52386 3.57096 3.61368 3.65136 3.68336 3.70976 - 3.73074 3.73998 3.75199 3.76439 3.77461 3.77531 - 3.77139 3.77076 3.77124 3.77126 3.77140 3.77135 - 3.03831 3.15626 3.26082 3.35247 3.43070 3.49605 - 3.55056 3.59850 3.64563 3.69305 3.74041 3.78664 - 3.83023 3.86979 3.90487 3.93597 3.96367 3.98830 - 4.01039 4.02136 4.03518 4.04889 4.06038 4.06115 - 4.05676 4.05605 4.05659 4.05661 4.05677 4.05674 - 3.59146 3.72816 3.84449 3.94105 4.01734 4.07442 - 4.11556 4.14715 4.17753 4.20858 4.23997 4.27083 - 4.29960 4.32510 4.34737 4.36763 4.38737 4.40779 - 4.43054 4.44351 4.45865 4.47244 4.48481 4.48604 - 4.48242 4.48181 4.48233 4.48233 4.48250 4.48251 - 4.05066 4.19488 4.31380 4.40840 4.47830 4.52493 - 4.55234 4.56810 4.58200 4.59636 4.61121 4.62623 - 4.64059 4.65380 4.66597 4.67778 4.69039 4.70608 - 4.72779 4.74120 4.75537 4.76696 4.77866 4.78053 - 4.77902 4.77871 4.77912 4.77912 4.77924 4.77927 - 4.93918 5.07611 5.18060 5.25513 5.29976 5.31670 - 5.31093 5.29117 5.26854 5.24595 5.22442 5.20503 - 5.18915 5.17793 5.17096 5.16619 5.16271 5.16535 - 5.17973 5.19028 5.19758 5.19989 5.20653 5.20972 - 5.21496 5.21568 5.21563 5.21564 5.21559 5.21567 - 5.59940 5.71202 5.78885 5.83410 5.84846 5.83471 - 5.79830 5.74833 5.69602 5.64466 5.59579 5.55110 - 5.51312 5.48358 5.46138 5.44238 5.42405 5.41299 - 5.41648 5.42147 5.41976 5.41180 5.41143 5.41516 - 5.42665 5.42834 5.42782 5.42783 5.42761 5.42775 - 6.54981 6.60087 6.61381 6.59619 6.54985 6.47849 - 6.38837 6.28894 6.19109 6.09856 6.01269 5.93478 - 5.86713 5.81048 5.76302 5.71894 5.67452 5.63772 - 5.61691 5.60909 5.59100 5.56699 5.55351 5.55645 - 5.57444 5.57721 5.57604 5.57605 5.57559 5.57582 - 7.22653 7.21803 7.17112 7.09601 6.99546 6.87395 - 6.73830 6.59839 6.46508 6.34194 6.22991 6.12906 - 6.04026 5.96278 5.89458 5.82976 5.76454 5.70633 - 5.66296 5.64365 5.61463 5.58255 5.56045 5.56099 - 5.57701 5.57957 5.57824 5.57823 5.57777 5.57798 - 7.73883 7.70324 7.60517 7.46640 7.30325 7.13254 - 6.96073 6.79358 6.63737 6.49380 6.36287 6.24322 - 6.13442 6.03528 5.94505 5.86143 5.78286 5.71160 - 5.64781 5.61594 5.58047 5.54889 5.52055 5.51872 - 5.52645 5.52782 5.52708 5.52662 5.52696 5.52672 - 8.15272 8.08303 7.94191 7.75636 7.54737 7.33604 - 7.12936 6.93258 6.75170 6.58769 6.43918 6.30353 - 6.17883 6.06329 5.95664 5.85830 5.76733 5.68183 - 5.60056 5.56178 5.52270 5.49152 5.46200 5.45575 - 5.45379 5.45363 5.45295 5.45280 5.45277 5.45283 - 8.78480 8.66058 8.44356 8.17330 7.88330 7.60517 - 7.34485 7.10349 6.88285 6.68304 6.50178 6.33604 - 6.18306 6.04131 5.91001 5.78835 5.67478 5.56535 - 5.45795 5.40772 5.36356 5.33463 5.30324 5.29033 - 5.27152 5.26872 5.26836 5.26867 5.26823 5.26857 - 9.24656 9.07506 8.79275 8.45025 8.09242 7.75949 - 7.45614 7.18012 6.92923 6.70215 6.49526 6.30490 - 6.12831 5.96430 5.81207 5.67035 5.53736 5.40924 - 5.28439 5.22636 5.17583 5.14368 5.10977 5.09344 - 5.06624 5.06201 5.06171 5.06229 5.06153 5.06206 - 10.16377 9.66128 9.17738 8.72578 8.30441 7.91150 - 7.54566 7.20649 6.89370 6.60629 6.34243 6.09967 - 5.87513 5.66748 5.47783 5.30521 5.14701 4.99121 - 4.82812 4.74833 4.67911 4.63448 4.58430 4.56760 - 4.54695 4.54415 4.54348 4.54345 4.54355 4.54331 - 10.62517 9.99500 9.40210 8.85681 8.35493 7.89364 - 7.47030 7.08308 6.73092 6.41099 6.11973 5.85292 - 5.60498 5.37238 5.15626 4.95592 4.76917 4.58759 - 4.40477 4.31558 4.23220 4.17083 4.10468 4.08949 - 4.08547 4.08559 4.08391 4.08357 4.08329 4.08306 - 11.06393 10.36794 9.64506 8.93939 8.28751 7.71853 - 7.22691 6.79928 6.42248 6.08154 5.75780 5.44301 - 5.14625 4.87370 4.62230 4.38479 4.15548 3.94159 - 3.74610 3.65090 3.55443 3.47713 3.40334 3.38703 - 3.37977 3.37902 3.37740 3.37707 3.37695 3.37638 - 11.44615 10.49532 9.65104 8.89913 8.22737 7.62682 - 7.09143 6.61277 6.18286 5.79540 5.44393 5.12088 - 4.81652 4.52454 4.24620 3.98463 3.74110 3.51161 - 3.29518 3.19293 3.09382 3.01773 2.94254 2.92313 - 2.90566 2.90351 2.90214 2.90194 2.90183 2.90169 - 11.65372 10.60532 9.69228 8.88607 8.17243 7.53891 - 6.97649 6.47407 6.02086 5.61013 5.23611 4.89232 - 4.57070 4.26578 3.97747 3.70637 3.45284 3.21331 - 2.98715 2.88019 2.77699 2.69824 2.62089 2.60092 - 2.58236 2.58000 2.57858 2.57839 2.57828 2.57896 - 11.80135 10.68403 9.72487 8.88151 8.13903 7.48295 - 6.90133 6.38121 5.91032 5.48188 5.09075 4.73137 - 4.39713 4.08319 3.78830 3.51103 3.25047 3.00444 - 2.77207 2.66163 2.55409 2.47123 2.39111 2.37126 - 2.35449 2.35240 2.35079 2.35062 2.35044 2.35159 - 12.00054 10.79500 9.78042 8.89203 8.11438 7.43115 - 6.82622 6.28436 5.79195 5.34235 4.93092 4.55286 - 4.20270 3.87610 3.57076 3.28358 3.01216 2.75547 - 2.51147 2.39429 2.27929 2.18983 2.10350 2.08281 - 2.06742 2.06560 2.06378 2.06360 2.06336 2.06378 - 12.12980 10.87363 9.83029 8.91862 8.12304 7.42578 - 6.80902 6.25652 5.75434 5.29565 4.87558 4.48896 - 4.12991 3.79388 3.47887 3.18225 2.90146 2.63386 - 2.37669 2.25196 2.12988 2.03496 1.94152 1.91861 - 1.90113 1.89910 1.89724 1.89702 1.89679 1.89564 - 12.30162 10.99762 9.93503 9.00687 8.19972 7.49029 - 6.86234 6.30039 5.79137 5.32769 4.90301 4.51039 - 4.14150 3.79067 3.45732 3.14131 2.84051 2.54755 - 2.25664 2.11090 1.96473 1.84813 1.73272 1.70342 - 1.67967 1.67689 1.67464 1.67433 1.67411 1.67297 - 12.37080 11.06638 10.01613 9.09667 8.29567 7.58749 - 6.95869 6.39588 5.88774 5.42617 5.00375 4.61199 - 4.24058 3.88271 3.53846 3.20885 2.89184 2.57743 - 2.25513 2.08778 1.91151 1.76483 1.62444 1.59024 - 1.56270 1.55925 1.55623 1.55590 1.55556 1.55806 - 12.41033 11.12514 10.11656 9.23634 8.46489 7.77836 - 7.16472 6.61190 6.10950 5.65057 5.22881 4.83703 - 4.46638 4.10978 3.76381 3.42352 3.08203 2.72832 - 2.34704 2.13875 1.91019 1.70922 1.50804 1.46554 - 1.43827 1.43480 1.42894 1.42772 1.42833 1.43682 - 12.36696 11.14078 10.19243 9.35679 8.61168 7.94043 - 7.33525 6.78847 6.29350 5.84354 5.43141 5.04862 - 4.68434 4.33011 3.98244 3.63629 3.28243 2.90206 - 2.47109 2.22750 1.95690 1.71496 1.45466 1.39369 - 1.37065 1.36944 1.36046 1.35798 1.36027 1.37080 - 12.33564 11.13643 10.22926 9.42894 8.71103 8.06154 - 7.47369 6.94060 6.45629 6.01460 5.60885 5.23110 - 4.87097 4.52002 4.17411 3.82696 3.46675 3.06927 - 2.60252 2.33044 2.02056 1.73889 1.42737 1.35196 - 1.32840 1.32808 1.31687 1.31364 1.31697 1.32731 - 12.30052 11.12499 10.25486 9.48411 8.78994 8.15968 - 7.58739 7.06687 6.59263 6.15904 5.75991 5.38773 - 5.03260 4.68616 4.34375 3.99801 3.63499 3.22567 - 2.73078 2.43506 2.09160 1.77422 1.41540 1.32582 - 1.29940 1.29953 1.28655 1.28274 1.28686 1.29599 - 12.23448 11.09789 10.28790 9.56400 8.90851 8.31015 - 7.76429 7.26560 6.80946 6.39105 6.00491 5.64430 - 5.30006 4.96412 4.63104 4.29190 3.92928 3.50629 - 2.97086 2.63821 2.23963 1.86038 1.41644 1.29982 - 1.26256 1.26248 1.24692 1.24235 1.24741 1.25353 - 12.24671 11.11214 10.32531 9.62058 8.98373 8.40370 - 7.87597 7.39523 6.95685 6.55581 6.18636 5.84111 - 5.50980 5.18367 4.85800 4.52518 4.17041 3.76148 - 3.23027 2.86874 2.38617 1.91195 1.42302 1.30704 - 1.24535 1.23695 1.22116 1.22012 1.21732 1.22586 - 12.15537 11.07231 10.35516 9.70806 9.12054 8.58362 - 8.09379 7.64672 7.23866 6.86539 6.52193 6.20161 - 5.89487 5.59315 5.29135 4.98070 4.64351 4.23998 - 3.68399 3.28502 2.73027 2.15781 1.50288 1.32572 - 1.21817 1.20508 1.18569 1.18383 1.18090 1.18569 - 12.10010 11.04873 10.37273 9.76099 9.20424 8.69492 - 8.23003 7.80588 7.41921 7.06633 6.74276 6.44239 - 6.15617 5.87582 5.59611 5.30763 4.99072 4.59991 - 4.03841 3.62323 3.03279 2.39758 1.60022 1.36588 - 1.20803 1.18913 1.16681 1.16421 1.16131 1.16393 - 11.99296 10.99673 10.38398 9.82495 9.31276 8.84177 - 8.40999 8.01491 7.65440 7.32603 7.02683 6.75269 - 6.49719 6.25387 6.01693 5.77465 5.50023 5.12877 - 4.54541 4.10827 3.49568 2.81080 1.82346 1.49056 - 1.20160 1.16829 1.15033 1.14624 1.13133 1.14097 - 11.98774 11.00042 10.40569 9.86347 9.36790 8.91397 - 8.49984 8.12318 7.78200 7.47401 7.19633 6.94485 - 6.71296 6.49420 6.28354 6.07030 5.82901 5.49561 - 4.94894 4.52013 3.89174 3.15164 2.00685 1.60039 - 1.22102 1.16988 1.13665 1.13217 1.12056 1.12908 - 11.98720 11.01450 10.43302 9.90007 9.41197 8.96552 - 8.55924 8.19118 7.85980 7.56358 7.30086 7.06858 - 6.86094 6.66995 6.48416 6.28589 6.05001 5.73355 - 5.24480 4.86289 4.26988 3.48876 2.16150 1.69053 - 1.23927 1.17534 1.13112 1.12675 1.11892 1.12186 - 11.98283 11.01763 10.44507 9.92116 9.44174 9.00332 - 8.60485 8.24507 7.92313 7.63743 7.38583 7.16515 - 6.96984 6.79329 6.62717 6.45306 6.24336 5.95376 - 5.48620 5.11147 4.53274 3.76684 2.34227 1.78717 - 1.25489 1.18104 1.12917 1.12163 1.11764 1.11703 - 11.97416 11.02542 10.46461 9.95131 9.48175 9.05345 - 8.66574 8.31776 8.00917 7.73853 7.50374 7.30145 - 7.12582 6.97040 6.82856 6.68465 6.51375 6.27201 - 5.86168 5.51871 4.96830 4.19792 2.64375 1.99016 - 1.29960 1.19595 1.12523 1.11929 1.10867 1.11094 - 11.96972 11.03225 10.47817 9.97148 9.50856 9.08723 - 8.70682 8.36650 8.06598 7.80410 7.57909 7.38813 - 7.22603 7.08709 6.96539 6.84611 6.70511 6.49908 - 6.13255 5.81716 5.29943 4.54711 2.91568 2.17356 - 1.34404 1.21603 1.12523 1.11728 1.10423 1.10720 - 11.95746 11.04483 10.50167 10.00384 9.54926 9.13684 - 8.76611 8.43659 8.14821 7.89961 7.68854 7.51269 - 7.36927 7.25498 7.16558 7.08822 7.00177 6.86765 - 6.58897 6.32058 5.85813 5.16726 3.50168 2.57723 - 1.44800 1.27243 1.13156 1.11654 1.10145 1.10211 - 11.95347 11.05511 10.51129 10.01640 9.56718 9.16152 - 8.79812 8.47588 8.19400 7.95172 7.74784 7.58039 - 7.44534 7.33978 7.26429 7.21592 7.17886 7.09675 - 6.86625 6.63752 6.24194 5.60499 3.91241 2.93838 - 1.56007 1.32770 1.13990 1.11941 1.09976 1.09954 - 11.89882 11.06020 10.52261 10.03318 9.58929 9.18904 - 8.83121 8.51491 8.23951 8.00446 7.80890 7.65128 - 7.52815 7.43755 7.38157 7.35980 7.36100 7.33713 - 7.19715 7.03018 6.71055 6.16055 4.56028 3.49566 - 1.76684 1.44745 1.16145 1.12752 1.09784 1.09694 - 11.85255 11.06245 10.52756 10.04081 9.59949 9.20196 - 8.84709 8.53401 8.26218 8.03110 7.84012 7.68790 - 7.57114 7.48847 7.44279 7.43536 7.45800 7.46886 - 7.38675 7.26147 6.99615 6.51521 5.02551 3.92771 - 1.95867 1.56409 1.18505 1.13694 1.09781 1.09565 - 11.79839 11.05675 10.53154 10.04990 9.61086 9.21418 - 8.85947 8.54669 8.27602 8.04691 7.85836 7.70948 - 7.59915 7.52682 7.49232 7.48955 7.50887 7.53291 - 7.50087 7.41036 7.19378 6.79232 5.40427 4.22585 - 2.13786 1.69142 1.20968 1.13738 1.10359 1.09487 - 11.77407 11.05734 10.53370 10.05337 9.61548 9.21992 - 8.86630 8.55450 8.28474 8.05682 7.87044 7.72491 - 7.61837 7.54978 7.51933 7.52173 7.54854 7.58452 - 7.58632 7.53062 7.34733 6.95546 5.64606 4.57153 - 2.30734 1.78243 1.23374 1.15765 1.09984 1.09436 - 11.74448 11.05835 10.53627 10.05740 9.62102 9.22696 - 8.87490 8.56484 8.29703 8.07137 7.88754 7.74492 - 7.64190 7.57767 7.55300 7.56353 7.60253 7.65792 - 7.69531 7.67227 7.54600 7.22878 6.05009 5.02983 - 2.62272 1.98254 1.28230 1.17861 1.10406 1.09371 - 11.72579 11.05907 10.53801 10.05992 9.62433 9.23123 - 8.88026 8.57137 8.30479 8.08046 7.89812 7.75727 - 7.65641 7.59488 7.57380 7.58933 7.63582 7.70333 - 7.76306 7.76119 7.67515 7.41453 6.34190 5.37795 - 2.90223 2.16620 1.33023 1.20049 1.10893 1.09332 - 11.69723 11.06031 10.54046 10.06329 9.62871 9.23694 - 8.88756 8.58035 8.31540 8.09274 7.91234 7.77389 - 7.67602 7.61827 7.60218 7.62459 7.68116 7.76559 - 7.85666 7.88474 7.85981 7.69348 6.82035 5.98098 - 3.48124 2.57156 1.44682 1.25798 1.12206 1.09280 - 11.68081 11.06066 10.54149 10.06490 9.63093 9.23986 - 8.89124 8.58480 8.32060 8.09874 7.91933 7.78219 - 7.68594 7.63022 7.61675 7.64272 7.70450 7.79807 - 7.90594 7.94951 7.95724 7.84763 7.11813 6.37609 - 3.93462 2.91712 1.55871 1.31732 1.13539 1.09254 - 11.66343 11.06061 10.54201 10.06614 9.63293 9.24253 - 8.89461 8.58908 8.32611 8.10546 7.92669 7.78965 - 7.69447 7.64176 7.63257 7.66209 7.72614 7.82674 - 7.96198 8.03016 8.05545 7.96875 7.48341 6.97670 - 4.56528 3.41867 1.77062 1.45290 1.16368 1.09229 - 11.67449 11.06723 10.54122 10.06239 9.62888 9.23948 - 8.89324 8.58955 8.32810 8.10876 7.93140 7.79526 - 7.69794 7.63942 7.62551 7.66249 7.75161 7.87055 - 7.98988 8.04731 8.09795 8.09008 7.69709 7.17197 - 5.07735 3.90543 1.96140 1.55255 1.18568 1.09216 - 11.66853 11.06728 10.54153 10.06291 9.62962 9.24041 - 8.89436 8.59087 8.32961 8.11052 7.93344 7.79766 - 7.70083 7.64295 7.62995 7.66817 7.75906 7.88064 - 8.00495 8.06783 8.13016 8.14428 7.82995 7.37928 - 5.43342 4.25062 2.15133 1.66562 1.20987 1.09209 - 11.66447 11.06735 10.54184 10.06330 9.63013 9.24104 - 8.89511 8.59175 8.33065 8.11172 7.93484 7.79933 - 7.70282 7.64537 7.63293 7.67194 7.76402 7.88740 - 8.01520 8.08175 8.15173 8.18076 7.92394 7.52871 - 5.71174 4.53813 2.32791 1.77751 1.23366 1.09204 - 11.63908 11.06130 10.54374 10.06862 9.63602 9.24619 - 8.89884 8.59392 8.33172 8.11222 7.93536 7.80093 - 7.70802 7.65678 7.64941 7.68388 7.75835 7.87317 - 8.02282 8.10573 8.18619 8.22614 8.04865 7.72943 - 6.12489 4.99515 2.64455 1.99688 1.28124 1.09197 - 11.63722 11.06137 10.54334 10.06827 9.63597 9.24655 - 8.89966 8.59523 8.33346 8.11412 7.93682 7.80149 - 7.70826 7.65798 7.65239 7.68803 7.76194 7.87595 - 8.03078 8.12134 8.20798 8.24169 8.10169 7.90937 - 6.42556 5.30769 2.91798 2.21496 1.32118 1.09192 - 0.79300 0.82654 0.86068 0.89560 0.93137 0.96809 - 1.00596 1.04535 1.08678 1.13061 1.17720 1.22711 - 1.28120 1.33934 1.39814 1.44915 1.48402 1.50616 - 1.52122 1.52727 1.53673 1.54591 1.54420 1.54310 - 1.54379 1.54389 1.54367 1.54373 1.54360 1.54368 - 1.10508 1.14568 1.18771 1.23153 1.27722 1.32480 - 1.37430 1.42569 1.47892 1.53386 1.59027 1.64778 - 1.70583 1.76357 1.81977 1.87265 1.91985 1.95873 - 1.98261 1.98364 1.97292 1.95822 1.97269 1.98872 - 1.98452 1.98122 1.98160 1.98239 1.98038 1.98174 - 1.39033 1.43830 1.48758 1.53873 1.59174 1.64663 - 1.70334 1.76179 1.82181 1.88320 1.94558 2.00839 - 2.07086 2.13190 2.18998 2.24309 2.28877 2.32515 - 2.34670 2.34696 2.33622 2.32277 2.34183 2.35953 - 2.35271 2.34873 2.34953 2.35054 2.34832 2.34977 - 1.88931 1.95342 2.01748 2.08212 2.14715 2.21235 - 2.27744 2.34220 2.40642 2.46990 2.53254 2.59436 - 2.65603 2.71758 2.77682 2.82948 2.87071 2.89847 - 2.91405 2.91979 2.92623 2.93237 2.93826 2.93886 - 2.93785 2.93766 2.93781 2.93789 2.93784 2.93783 - 2.30932 2.39208 2.47126 2.54749 2.62043 2.68990 - 2.75611 2.81987 2.88241 2.94382 3.00391 3.06242 - 3.11950 3.17487 3.22686 3.27270 3.30961 3.33751 - 3.35637 3.36303 3.37222 3.38241 3.39056 3.39123 - 3.38842 3.38796 3.38835 3.38836 3.38846 3.38839 - 2.67496 2.77428 2.86608 2.95096 3.02845 3.09855 - 3.16211 3.22115 3.27861 3.33492 3.38982 3.44272 - 3.49320 3.54070 3.58437 3.62349 3.65722 3.68469 - 3.70496 3.71325 3.72468 3.73737 3.74835 3.74850 - 3.74482 3.74413 3.74452 3.74475 3.74461 3.74470 - 2.99854 3.11145 3.21307 3.30396 3.38356 3.45208 - 3.51094 3.56334 3.61369 3.66284 3.71058 3.75634 - 3.79964 3.83995 3.87670 3.90969 3.93879 3.96404 - 3.98577 3.99626 4.00988 4.02399 4.03615 4.03644 - 4.03238 4.03159 4.03204 4.03229 4.03211 4.03225 - 3.54856 3.68179 3.79637 3.89293 3.97089 4.03106 - 4.07620 4.11186 4.14543 4.17856 4.21104 4.24229 - 4.27138 4.29767 4.32116 4.34280 4.36378 4.38518 - 4.40859 4.42179 4.43726 4.45145 4.46417 4.46547 - 4.46192 4.46133 4.46185 4.46186 4.46204 4.46202 - 4.00764 4.14995 4.26819 4.36331 4.43484 4.48406 - 4.51463 4.53363 4.55019 4.56653 4.58272 4.59862 - 4.61377 4.62800 4.64142 4.65458 4.66852 4.68548 - 4.70831 4.72224 4.73697 4.74905 4.76132 4.76332 - 4.76190 4.76161 4.76202 4.76203 4.76217 4.76217 - 4.89820 5.03807 5.14493 5.22113 5.26679 5.28421 - 5.27861 5.25911 5.23727 5.21608 5.19646 5.17926 - 5.16544 5.15587 5.15019 5.14664 5.14461 5.14893 - 5.16520 5.17673 5.18488 5.18776 5.19528 5.19873 - 5.20412 5.20484 5.20481 5.20483 5.20479 5.20486 - 5.56073 5.67967 5.76091 5.80854 5.82343 5.80869 - 5.77045 5.71880 5.66608 5.61574 5.56909 5.52735 - 5.49221 5.46470 5.44388 5.42607 5.40926 5.40005 - 5.40575 5.41190 5.41112 5.40373 5.40426 5.40831 - 5.42002 5.42172 5.42121 5.42123 5.42102 5.42116 - 6.49456 6.59630 6.62096 6.58805 6.51837 6.43431 - 6.34352 6.25243 6.16747 6.08743 6.00678 5.92457 - 5.85104 5.79335 5.74869 5.70733 5.66324 5.63015 - 5.61488 5.60515 5.58669 5.56495 5.55214 5.55487 - 5.57333 5.57620 5.57521 5.57475 5.57477 5.57482 - 7.17793 7.21218 7.17526 7.08794 6.96861 6.83678 - 6.70049 6.56736 6.44505 6.33314 6.22691 6.12427 - 6.03144 5.95226 5.88457 5.82135 5.75824 5.70473 - 5.66539 5.64431 5.61507 5.58512 5.56336 5.56368 - 5.58021 5.58285 5.58171 5.58123 5.58123 5.58129 - 7.70086 7.68193 7.59196 7.45459 7.28909 7.11543 - 6.94147 6.77432 6.62143 6.48289 6.35539 6.23618 - 6.12734 6.02970 5.94208 5.86074 5.78313 5.71306 - 5.65221 5.62189 5.58663 5.55452 5.52772 5.52491 - 5.53370 5.53516 5.53417 5.53384 5.53382 5.53387 - 8.11935 8.06069 7.92557 7.74215 7.53337 7.32227 - 7.11624 6.92076 6.74195 6.58039 6.43404 6.29990 - 6.17653 6.06253 5.95762 5.86109 5.77189 5.68811 - 5.60859 5.57074 5.53245 5.50168 5.47237 5.46620 - 5.46447 5.46433 5.46365 5.46349 5.46346 5.46351 - 8.75830 8.63480 8.42185 8.15730 7.87277 7.59823 - 7.33999 7.10000 6.88090 6.68288 6.50352 6.33966 - 6.18840 6.04811 5.91811 5.79781 5.68582 5.57810 - 5.47241 5.42297 5.37957 5.35114 5.32002 5.30710 - 5.28822 5.28540 5.28504 5.28537 5.28493 5.28521 - 9.22589 9.04634 8.76648 8.43260 8.08435 7.75760 - 7.45739 7.18294 6.93352 6.70813 6.50309 6.31455 - 6.13940 5.97628 5.82481 5.68467 5.55445 5.42826 - 5.30314 5.24514 5.19606 5.16595 5.13155 5.11472 - 5.08737 5.08322 5.08293 5.08350 5.08281 5.08322 - 10.13130 9.63687 9.16032 8.71523 8.29965 7.91187 - 7.55055 7.21532 6.90593 6.62141 6.35998 6.11922 - 5.89629 5.68983 5.50100 5.32890 5.17107 5.01596 - 4.85433 4.77544 4.70682 4.66236 4.61247 4.59586 - 4.57487 4.57201 4.57137 4.57135 4.57145 4.57122 - 10.59295 9.97178 9.38687 8.84862 8.35298 7.89718 - 7.47870 7.09573 6.74724 6.43049 6.14192 5.87732 - 5.63111 5.39971 5.18426 4.98416 4.79739 4.61604 - 4.43422 4.34568 4.26265 4.20123 4.13522 4.12018 - 4.11611 4.11619 4.11453 4.11421 4.11392 4.11378 - 11.05868 10.34871 9.62679 8.93079 8.29091 7.73132 - 7.24605 6.82209 6.44661 6.10579 5.78249 5.46919 - 5.17407 4.90270 4.65208 4.41512 4.18626 3.97264 - 3.77725 3.68202 3.58544 3.50802 3.43425 3.41799 - 3.41084 3.41010 3.40848 3.40815 3.40804 3.40759 - 11.43534 10.49300 9.65525 8.90860 8.24102 7.64381 - 7.11101 6.63438 6.20603 5.81982 5.46936 5.14721 - 4.84375 4.55272 4.27528 4.01443 3.77129 3.54190 - 3.32531 3.22291 3.12371 3.04758 2.97215 2.95266 - 2.93515 2.93300 2.93162 2.93143 2.93131 2.93119 - 11.64401 10.61146 9.70814 8.90722 8.19569 7.56216 - 6.99859 6.49496 6.04147 5.63140 5.25872 4.91663 - 4.59661 4.29285 4.00532 3.73471 3.48144 3.24198 - 3.01572 2.90870 2.80552 2.72677 2.64890 2.62874 - 2.61003 2.60766 2.60621 2.60603 2.60591 2.60641 - 11.79220 10.69527 9.74750 8.90925 8.16742 7.50915 - 6.92404 6.40078 5.92852 5.50043 5.11086 4.75367 - 4.42144 4.10879 3.81462 3.53770 3.27735 3.03140 - 2.79907 2.68869 2.58127 2.49842 2.41758 2.39746 - 2.38050 2.37837 2.37674 2.37657 2.37639 2.37726 - 11.98685 10.80392 9.80178 8.91910 8.14229 7.45677 - 6.84805 6.30258 5.80818 5.35820 4.94762 4.57117 - 4.22278 3.89769 3.59355 3.30713 3.03603 2.77953 - 2.53593 2.41896 2.30401 2.21434 2.12733 2.10631 - 2.09069 2.08894 2.08712 2.08679 2.08672 2.08695 - 12.11830 10.87658 9.84123 8.93361 8.13927 7.44146 - 6.82335 6.26970 5.76733 5.30943 4.89081 4.50595 - 4.14850 3.81368 3.49947 3.20335 2.92286 2.65552 - 2.39871 2.27419 2.15225 2.05726 1.96324 1.94012 - 1.92248 1.92044 1.91856 1.91833 1.91810 1.91722 - 12.28110 10.97991 9.92029 8.99614 8.19349 7.48874 - 6.86522 6.30694 5.80045 5.33829 4.91448 4.52241 - 4.15422 3.80449 3.47245 3.15761 2.85767 2.56534 - 2.27485 2.12920 1.98295 1.86618 1.75071 1.72139 - 1.69760 1.69482 1.69258 1.69226 1.69205 1.69116 - 12.32762 11.04417 9.99993 9.08007 8.27847 7.57384 - 6.95157 6.39628 5.89458 5.43688 5.01411 4.61875 - 4.24523 3.88938 3.54931 3.22261 2.90579 2.59281 - 2.27186 2.10280 1.92645 1.78102 1.63955 1.60569 - 1.57861 1.57481 1.57190 1.57155 1.57123 1.57313 - 12.35041 11.10341 10.10672 9.22447 8.44666 7.75674 - 7.14362 6.59522 6.10082 5.65091 5.23565 4.84602 - 4.47400 4.11379 3.76397 3.42282 3.08594 2.74203 - 2.36677 2.15475 1.92086 1.71700 1.51934 1.47900 - 1.45220 1.44705 1.44156 1.44092 1.44055 1.44748 - 12.34425 11.11039 10.15889 9.32519 8.58553 7.92166 - 7.32407 6.78324 6.29090 5.84076 5.42674 5.04178 - 4.67694 4.32478 3.98102 3.63915 3.28926 2.91433 - 2.48913 2.24484 1.96600 1.71415 1.46083 1.40962 - 1.38289 1.37960 1.37131 1.36948 1.37092 1.37898 - 12.31324 11.11266 10.20445 9.40523 8.69001 8.04410 - 7.45986 6.92943 6.44604 6.00386 5.59695 5.21832 - 4.85894 4.51104 4.16977 3.82745 3.47203 3.08178 - 2.62301 2.34983 2.02815 1.73247 1.43034 1.36874 - 1.34008 1.33684 1.32657 1.32421 1.32637 1.33422 - 12.28024 11.10699 10.23647 9.46598 8.77242 8.14302 - 7.57157 7.05147 6.57699 6.14274 5.74300 5.37089 - 5.01738 4.67455 4.33707 3.99639 3.63860 3.23802 - 2.75340 2.45647 2.09832 1.76357 1.41595 1.34329 - 1.31076 1.30734 1.29546 1.29270 1.29539 1.30227 - 12.21873 11.08797 10.27817 9.55305 8.89536 8.29435 - 7.74574 7.24461 6.78681 6.36760 5.98163 5.62233 - 5.28084 4.94906 4.62102 4.28677 3.92955 3.51754 - 2.99653 2.66297 2.24560 1.84389 1.41365 1.31817 - 1.27356 1.26917 1.25488 1.25156 1.25488 1.25936 - 12.21602 11.09052 10.30719 9.60474 8.96924 8.38990 - 7.86229 7.38124 6.94229 6.54056 6.17050 5.82504 - 5.49435 5.17002 4.84730 4.51840 4.16815 3.76309 - 3.23400 2.87296 2.39084 1.91710 1.42938 1.31415 - 1.25350 1.24514 1.22912 1.22808 1.22545 1.23169 - 12.12899 11.05308 10.33759 9.69143 9.10435 8.56747 - 8.07739 7.62985 7.22120 6.84732 6.50340 6.18299 - 5.87686 5.57677 5.27759 4.97048 4.63748 4.23776 - 3.68437 3.28639 2.73277 2.16150 1.50854 1.33225 - 1.22585 1.21282 1.19318 1.19131 1.18858 1.19200 - 12.07376 11.02859 10.35348 9.74214 9.18550 8.67614 - 8.21103 7.78657 7.39956 7.04637 6.72263 6.42242 - 6.13692 5.85808 5.58068 5.29532 4.98211 4.59489 - 4.03627 3.62244 3.03368 2.40027 1.60551 1.37213 - 1.21558 1.19678 1.17423 1.17161 1.16892 1.17075 - 11.96415 10.98509 10.37705 9.81721 9.29999 8.82154 - 8.38161 7.97997 7.61662 7.28907 6.99355 6.72479 - 6.47464 6.23476 5.99788 5.74973 5.46669 5.10432 - 4.56158 4.14468 3.52829 2.81389 1.80210 1.48837 - 1.21359 1.17840 1.15538 1.15263 1.14704 1.14850 - 11.94296 10.97718 10.39091 9.85100 9.35295 8.89350 - 8.47251 8.08990 7.74582 7.43809 7.16330 6.91652 - 6.68986 6.47522 6.26541 6.04582 5.79275 5.46280 - 4.95260 4.54660 3.92436 3.16387 1.98956 1.59699 - 1.22868 1.17786 1.14480 1.14146 1.13379 1.13695 - 11.94062 10.97807 10.40081 9.87126 9.38507 8.93879 - 8.53168 8.16294 7.83205 7.53730 7.27622 7.04518 - 6.83810 6.64771 6.46481 6.26989 6.03545 5.72137 - 5.23327 4.84836 4.25877 3.49888 2.17206 1.68975 - 1.24394 1.18328 1.14013 1.13375 1.13048 1.12993 - 11.93450 10.97910 10.40974 9.88806 9.41016 8.97278 - 8.57507 8.21604 7.89511 7.61067 7.36055 7.14139 - 6.94755 6.77223 6.60721 6.43426 6.22595 5.93832 - 5.47388 5.10154 4.52630 3.76423 2.34506 1.79221 - 1.26256 1.18904 1.13725 1.12971 1.12581 1.12523 - 11.92434 10.98281 10.42405 9.91283 9.44553 9.01952 - 8.63400 8.28807 7.98120 7.71196 7.47831 7.27699 - 7.10222 6.94770 6.80679 6.66398 6.49444 6.25456 - 5.84716 5.50645 4.95940 4.19305 2.64551 1.99469 - 1.30720 1.20397 1.13353 1.12760 1.11707 1.11931 - 11.91882 10.98784 10.43548 9.93094 9.47050 9.05185 - 8.67411 8.33624 8.03767 7.77723 7.55327 7.36306 - 7.20159 7.06335 6.94245 6.82417 6.68445 6.48017 - 6.11636 5.80309 5.28862 4.54045 2.91636 2.17750 - 1.35157 1.22406 1.13365 1.12575 1.11276 1.11571 - 11.90621 10.99804 10.45666 9.96228 9.51176 9.10313 - 8.73544 8.40780 8.11977 7.87069 7.65954 7.48464 - 7.34244 7.22917 7.14091 7.06568 6.98191 6.84633 - 6.56555 6.30238 5.84761 5.15975 3.49218 2.58482 - 1.45669 1.27806 1.14046 1.12440 1.11145 1.11085 - 11.88587 11.00533 10.47028 9.98067 9.53440 9.13022 - 8.76734 8.44512 8.16328 7.92126 7.71805 7.55224 - 7.42105 7.32153 7.25058 7.19723 7.14348 7.05648 - 6.84883 6.62757 6.21800 5.57832 3.93696 2.92675 - 1.56282 1.33860 1.14905 1.12826 1.10777 1.10841 - 11.84951 11.01763 10.48228 9.99506 9.55306 9.15450 - 8.79817 8.48317 8.20890 7.97479 7.78003 7.62309 - 7.50053 7.41044 7.35493 7.33362 7.33535 7.31232 - 7.17395 7.00842 6.69121 6.14482 4.55352 3.49430 - 1.77275 1.45461 1.17007 1.13632 1.10675 1.10593 - 11.80530 11.02088 10.48812 10.00316 9.56353 9.16752 - 8.81399 8.50210 8.23129 8.00110 7.81088 7.65927 - 7.54303 7.46082 7.41552 7.40844 7.43147 7.44296 - 7.36220 7.23818 6.97495 6.49730 5.01644 3.92435 - 1.96373 1.57076 1.19361 1.14577 1.10672 1.10467 - 11.75029 11.01648 10.49391 10.01350 9.57520 9.17961 - 8.82616 8.51446 8.24435 8.01559 7.82795 7.68071 - 7.57194 7.50036 7.46572 7.46206 7.47970 7.50128 - 7.47724 7.39880 7.17904 6.74329 5.36465 4.27405 - 2.14096 1.68219 1.21786 1.15626 1.10708 1.10392 - 11.72734 11.01697 10.49566 10.01651 9.57947 9.18498 - 8.83264 8.52215 8.25351 8.02654 7.84093 7.69598 - 7.58990 7.52165 7.49144 7.49400 7.52099 7.55731 - 7.56009 7.50541 7.32382 6.93470 5.63362 4.56484 - 2.31071 1.78821 1.24214 1.16646 1.10872 1.10341 - 11.69834 11.01739 10.49743 10.01996 9.58469 9.19188 - 8.84118 8.53240 8.26571 8.04094 7.85784 7.71580 - 7.61319 7.54925 7.52474 7.53537 7.57443 7.63001 - 7.66805 7.64582 7.52106 7.20627 6.03520 5.02061 - 2.62465 1.98758 1.29050 1.18735 1.11293 1.10277 - 11.67995 11.01741 10.49827 10.02185 9.58774 9.19609 - 8.84651 8.53889 8.27338 8.04990 7.86827 7.72798 - 7.62754 7.56628 7.54533 7.56090 7.60738 7.67495 - 7.73512 7.73391 7.64918 7.39077 6.32521 5.36672 - 2.90295 2.17058 1.33825 1.20911 1.11779 1.10239 - 11.65185 11.01765 10.49962 10.02444 9.59181 9.20176 - 8.85383 8.54783 8.28387 8.06201 7.88229 7.74440 - 7.64695 7.58942 7.57340 7.59576 7.65227 7.73660 - 7.82772 7.85615 7.83220 7.66774 6.80059 5.96624 - 3.47946 2.57438 1.45432 1.26628 1.13092 1.10189 - 11.63600 11.01801 10.50044 10.02585 9.59382 9.20444 - 8.85731 8.55232 8.28961 8.06893 7.88977 7.75194 - 7.65545 7.60079 7.58885 7.61468 7.67350 7.76538 - 7.88168 7.93078 7.92358 7.78833 7.12070 6.42171 - 3.89431 2.88976 1.56886 1.33228 1.15103 1.10164 - 11.61790 11.01876 10.50246 10.02839 9.59666 9.20762 - 8.86089 8.55623 8.29377 8.07362 7.89596 7.76066 - 7.66642 7.61297 7.60224 7.63173 7.69871 7.80160 - 7.92694 7.98641 8.02718 7.98241 7.45268 6.85332 - 4.60032 3.47006 1.77345 1.44300 1.17041 1.10141 - 11.62970 11.02528 10.50128 10.02423 9.59236 9.20444 - 8.85949 8.55691 8.29641 8.07788 7.90115 7.76548 - 7.66851 7.61018 7.59633 7.63318 7.72202 7.84058 - 7.95961 8.01698 8.06784 8.06074 7.67167 7.15043 - 5.06831 3.90219 1.96656 1.55916 1.19448 1.10130 - 11.62374 11.02513 10.50148 10.02465 9.59302 9.20529 - 8.86054 8.55818 8.29790 8.07962 7.90317 7.76787 - 7.67138 7.61369 7.60072 7.63878 7.72935 7.85050 - 7.97447 8.03723 8.09965 8.11436 7.80356 7.35643 - 5.42240 4.24551 2.15554 1.67173 1.21857 1.10123 - 11.61954 11.02500 10.50159 10.02492 9.59344 9.20585 - 8.86125 8.55903 8.29891 8.08080 7.90456 7.76952 - 7.67334 7.61607 7.60367 7.64252 7.73423 7.85718 - 7.98460 8.05101 8.12102 8.15053 7.89678 7.50475 - 5.69904 4.53140 2.33122 1.78323 1.24225 1.10119 - 11.59444 11.01895 10.50339 10.03019 9.59930 9.21097 - 8.86493 8.56117 8.29995 8.08128 7.90507 7.77111 - 7.67853 7.62745 7.62011 7.65441 7.72854 7.84289 - 7.99208 8.07477 8.15513 8.19534 8.02037 7.70396 - 6.10971 4.98582 2.64631 2.00155 1.28963 1.10113 - 11.59283 11.01993 10.50389 10.03034 9.59937 9.21127 - 8.86567 8.56241 8.30165 8.08315 7.90653 7.77168 - 7.67877 7.62864 7.62302 7.65846 7.73206 7.84560 - 7.99990 8.09027 8.17676 8.21065 8.07257 7.88282 - 6.40863 5.29622 2.91844 2.21896 1.32931 1.10109 - 0.77418 0.80710 0.84061 0.87490 0.91005 0.94616 - 0.98345 1.02231 1.06331 1.10681 1.15318 1.20302 - 1.25716 1.31548 1.37458 1.42595 1.46113 1.48339 - 1.49816 1.50381 1.51262 1.52107 1.51874 1.51749 - 1.51803 1.51811 1.51788 1.51794 1.51780 1.51789 - 1.08063 1.12072 1.16226 1.20561 1.25085 1.29801 - 1.34713 1.39819 1.45113 1.50588 1.56218 1.61970 - 1.67787 1.73590 1.79256 1.84606 1.89397 1.93342 - 1.95727 1.95784 1.94616 1.93025 1.94365 1.95967 - 1.95577 1.95250 1.95280 1.95357 1.95153 1.95291 - 1.36214 1.40969 1.45860 1.50940 1.56211 1.61672 - 1.67321 1.73149 1.79141 1.85280 1.91528 1.97829 - 2.04109 2.10260 2.16131 2.21516 2.26164 2.29860 - 2.32003 2.31975 2.30793 2.29318 2.31138 2.32925 - 2.32270 2.31872 2.31946 2.32045 2.31820 2.31966 - 1.85756 1.92090 1.98434 2.04853 2.11327 2.17836 - 2.24352 2.30855 2.37320 2.43725 2.50062 2.56329 - 2.62589 2.68837 2.74847 2.80180 2.84333 2.87086 - 2.88562 2.89085 2.89682 2.90266 2.90826 2.90880 - 2.90774 2.90754 2.90768 2.90777 2.90772 2.90770 - 2.27400 2.35701 2.43639 2.51274 2.58573 2.65523 - 2.72148 2.78538 2.84829 2.91031 2.97128 3.03088 - 3.08917 3.14577 3.19885 3.24544 3.28254 3.31021 - 3.32865 3.33504 3.34396 3.35398 3.36198 3.36261 - 3.35973 3.35925 3.35962 3.35964 3.35976 3.35968 - 2.63626 2.73750 2.83075 2.91655 2.99442 3.06444 - 3.12762 3.18631 3.24383 3.30074 3.35677 3.41124 - 3.46350 3.51272 3.55775 3.59737 3.63045 3.65716 - 3.67793 3.68690 3.69872 3.71112 3.72131 3.72197 - 3.71797 3.71732 3.71780 3.71782 3.71798 3.71792 - 2.95743 3.07366 3.17772 3.27011 3.35023 3.41848 - 3.47655 3.52820 3.57854 3.62857 3.67796 3.72588 - 3.77122 3.81295 3.85043 3.88361 3.91259 3.93793 - 3.96049 3.97162 3.98564 3.99956 4.01122 4.01200 - 4.00754 4.00683 4.00738 4.00740 4.00757 4.00753 - 3.50692 3.64289 3.75966 3.85782 3.93674 3.99730 - 4.04245 4.07807 4.11200 4.14596 4.17972 4.21259 - 4.24338 4.27120 4.29598 4.31851 4.33997 4.36187 - 4.38628 4.40013 4.41613 4.43053 4.44341 4.44473 - 4.44108 4.44047 4.44101 4.44102 4.44120 4.44119 - 3.96540 4.11024 4.23064 4.32744 4.40016 4.45011 - 4.48112 4.50048 4.51772 4.53508 4.55262 4.57010 - 4.58690 4.60267 4.61744 4.63168 4.64643 4.66427 - 4.68853 4.70334 4.71885 4.73138 4.74387 4.74589 - 4.74443 4.74413 4.74455 4.74457 4.74470 4.74472 - 4.85687 4.99756 5.10554 5.18307 5.23022 5.24927 - 5.24535 5.22754 5.20730 5.18763 5.16943 5.15362 - 5.14121 5.13309 5.12891 5.12689 5.12639 5.13236 - 5.15057 5.16321 5.17252 5.17627 5.18411 5.18760 - 5.19310 5.19383 5.19380 5.19382 5.19378 5.19386 - 5.52120 5.63937 5.72073 5.76933 5.78594 5.77353 - 5.73797 5.68903 5.63862 5.59017 5.54502 5.50453 - 5.47060 5.44450 5.42529 5.40930 5.39447 5.38731 - 5.39502 5.40225 5.40276 5.39647 5.39743 5.40156 - 5.41347 5.41520 5.41469 5.41472 5.41449 5.41463 - 6.45621 6.55900 6.58349 6.55014 6.48117 6.40017 - 6.31405 6.22772 6.14592 6.06752 5.98773 5.90635 - 5.83400 5.77811 5.73573 5.69673 5.65467 5.62323 - 5.60973 5.60126 5.58408 5.56324 5.55117 5.55411 - 5.57280 5.57569 5.57472 5.57428 5.57428 5.57432 - 7.14226 7.17762 7.14046 7.05266 6.93420 6.80592 - 6.67494 6.54708 6.42816 6.31789 6.21260 6.11102 - 6.01958 5.94217 5.87660 5.81563 5.75461 5.70279 - 5.66495 5.64493 5.61677 5.58764 5.56673 5.56730 - 5.58408 5.58675 5.58563 5.58516 5.58515 5.58520 - 7.68432 7.62912 7.53519 7.41476 7.27131 7.11010 - 6.93866 6.76742 6.60798 6.46348 6.33422 6.21895 - 6.11652 6.02489 5.94216 5.86349 5.78563 5.71388 - 5.65421 5.62694 5.59320 5.56039 5.53458 5.53229 - 5.54128 5.54280 5.54168 5.54165 5.54130 5.54148 - 8.08841 8.03206 7.89737 7.71381 7.50619 7.29895 - 7.09854 6.90860 6.73334 6.57361 6.42846 6.29574 - 6.17391 6.06150 5.95827 5.86352 5.77618 5.69414 - 5.61612 5.57898 5.54141 5.51125 5.48271 5.47678 - 5.47531 5.47522 5.47455 5.47439 5.47434 5.47442 - 8.73133 8.61138 8.40049 8.13727 7.85462 7.58350 - 7.32971 7.09424 6.87869 6.68321 6.50567 6.34322 - 6.19319 6.05415 5.92547 5.80663 5.69624 5.59025 - 5.48615 5.43733 5.39444 5.36640 5.33589 5.32318 - 5.30449 5.30170 5.30136 5.30170 5.30125 5.30161 - 9.20193 9.02805 8.75211 8.42092 8.07515 7.75145 - 7.45470 7.18360 6.93694 6.71373 6.51044 6.32345 - 6.14985 5.98839 5.83838 5.69895 5.56866 5.44364 - 5.32200 5.26537 5.21604 5.18466 5.15153 5.13532 - 5.10799 5.10371 5.10342 5.10402 5.10325 5.10381 - 10.11717 9.63003 9.15972 8.71979 8.30838 7.92388 - 7.56506 7.23162 6.92339 6.63951 6.37834 6.13765 - 5.91488 5.70891 5.52092 5.35005 5.19381 5.04042 - 4.88025 4.80190 4.73355 4.68911 4.63962 4.62323 - 4.60212 4.59921 4.59859 4.59858 4.59870 4.59844 - 10.58518 9.97390 9.39694 8.86486 8.37377 7.92114 - 7.50459 7.12249 6.77399 6.45651 6.16675 5.90086 - 5.65374 5.42217 5.20738 5.00871 4.82400 4.64467 - 4.46402 4.37570 4.29272 4.23132 4.16576 4.15097 - 4.14672 4.14675 4.14510 4.14478 4.14454 4.14423 - 11.12349 10.32792 9.59963 8.93946 8.33938 7.79497 - 7.30294 6.85875 6.45878 6.09865 5.77291 5.47537 - 5.19787 4.93481 4.68644 4.45325 4.23255 4.01799 - 3.80627 3.70479 3.61104 3.54264 3.46768 3.44945 - 3.44283 3.44265 3.44084 3.44055 3.44015 3.43968 - 11.42681 10.49533 9.66520 8.92369 8.25939 7.66414 - 7.13242 6.65652 6.22905 5.84389 5.49463 5.17371 - 4.87134 4.58115 4.30435 4.04398 3.80126 3.57227 - 3.35602 3.25374 3.15452 3.07832 3.00315 2.98377 - 2.96637 2.96424 2.96286 2.96266 2.96255 2.96240 - 11.64331 10.60976 9.70732 8.90888 8.20092 7.57163 - 7.01247 6.51291 6.06261 5.65493 5.28395 4.94297 - 4.62358 4.32011 4.03276 3.76259 3.51016 3.27147 - 3.04538 2.93821 2.83475 2.75577 2.67804 2.65797 - 2.63937 2.63702 2.63558 2.63540 2.63528 2.63604 - 11.79627 10.69058 9.73922 8.90172 8.16369 7.51112 - 6.93250 6.41532 5.94770 5.52279 5.13518 4.77903 - 4.44715 4.13451 3.84029 3.56382 3.30457 3.05962 - 2.82740 2.71672 2.60886 2.52565 2.44484 2.42478 - 2.40789 2.40578 2.40416 2.40399 2.40381 2.40510 - 11.99569 10.79940 9.79054 8.90671 8.13277 7.45267 - 6.85067 6.31184 5.82283 5.37685 4.96903 4.59423 - 4.24648 3.92124 3.61667 3.33036 3.06030 2.80476 - 2.56114 2.44386 2.32860 2.23873 2.15142 2.13042 - 2.11479 2.11293 2.11109 2.11090 2.11065 2.11114 - 12.11675 10.87101 9.83420 8.92790 8.13669 7.44309 - 6.82957 6.28017 5.78108 5.32546 4.90836 4.52447 - 4.16769 3.83341 3.51973 3.22430 2.94467 2.67800 - 2.42138 2.29677 2.17462 2.07935 1.98492 1.96167 - 1.94388 1.94182 1.93993 1.93970 1.93947 1.93822 - 12.26747 10.97619 9.92211 9.00143 8.20062 7.49668 - 6.87338 6.31520 5.80905 5.34753 4.92464 4.53374 - 4.16692 3.81869 3.48807 3.17429 2.87490 2.58293 - 2.29284 2.14738 2.00121 1.88430 1.76819 1.73864 - 1.71469 1.71188 1.70961 1.70930 1.70907 1.70779 - 12.32516 11.03147 9.98877 9.07675 8.28277 7.58124 - 6.95837 6.40046 5.89584 5.43673 5.01610 4.62602 - 4.25679 3.90191 3.56110 3.23475 2.92032 2.60776 - 2.28635 2.11903 1.94250 1.79543 1.65475 1.62051 - 1.59292 1.58946 1.58644 1.58611 1.58577 1.58844 - 12.35403 11.07559 10.07133 9.19657 8.43134 7.75156 - 7.14465 6.59792 6.10042 5.64534 5.22672 4.83781 - 4.47022 4.11720 3.77526 3.43927 3.10197 2.75153 - 2.37178 2.16351 1.93454 1.73315 1.53242 1.49039 - 1.46308 1.45954 1.45368 1.45247 1.45305 1.46235 - 12.29651 11.08262 10.14056 9.31028 8.57010 7.90362 - 7.30311 6.76097 6.27058 5.82522 5.41770 5.03954 - 4.67994 4.33036 3.98733 3.64576 3.29624 2.91953 - 2.49096 2.24795 1.97749 1.73549 1.47606 1.41569 - 1.39265 1.39136 1.38235 1.37988 1.38216 1.39387 - 12.26302 11.07461 10.17223 9.37605 8.66226 8.01707 - 7.43366 6.90517 6.42562 5.98883 5.58811 5.21547 - 4.86048 4.51466 4.17383 3.83168 3.47624 3.08285 - 2.61898 2.34777 2.03839 1.75702 1.44702 1.37242 - 1.34890 1.34847 1.33722 1.33401 1.33735 1.34901 - 12.22665 11.06131 10.19467 9.42733 8.73671 8.11036 - 7.54230 7.02628 6.55683 6.12826 5.73433 5.36749 - 5.01773 4.67663 4.33951 3.99900 3.64099 3.23608 - 2.74451 2.44994 2.10734 1.79066 1.43391 1.34529 - 1.31903 1.31905 1.30603 1.30223 1.30638 1.31688 - 12.15897 11.03207 10.22444 9.50299 8.85038 8.25542 - 7.71344 7.21901 6.76755 6.35411 5.97322 5.61802 - 5.27925 4.94871 4.62102 4.28722 3.92982 3.51161 - 2.98021 2.64926 2.25229 1.87450 1.43353 1.31812 - 1.28131 1.28116 1.26554 1.26099 1.26612 1.27356 - 12.10334 11.00673 10.24337 9.55661 8.93329 8.36310 - 7.84212 7.36561 6.92955 6.52954 6.16066 5.81659 - 5.48867 5.16887 4.85140 4.52628 4.17357 3.75021 - 3.19321 2.83582 2.39655 1.96764 1.45164 1.31093 - 1.25893 1.25758 1.24023 1.23527 1.24076 1.24548 - 12.07442 11.00218 10.28694 9.64190 9.05688 8.52293 - 8.03648 7.59320 7.18925 6.82040 6.48160 6.16613 - 5.86423 5.56731 5.27028 4.96447 4.63231 4.23415 - 3.68396 3.28794 2.73598 2.16630 1.51748 1.34269 - 1.23618 1.22308 1.20375 1.20199 1.19910 1.20487 - 12.01494 10.97568 10.30216 9.69303 9.13912 8.63293 - 8.17145 7.75097 7.36819 7.01941 6.70009 6.40406 - 6.12215 5.84604 5.57055 5.28637 4.97407 4.58857 - 4.03347 3.62191 3.03527 2.40395 1.61372 1.38188 - 1.22594 1.20719 1.18491 1.18238 1.17953 1.18293 - 11.90126 10.91938 10.31044 9.75499 9.24629 8.77881 - 8.35055 7.95901 7.60204 7.27722 6.98157 6.71094 - 6.45891 6.21899 5.98547 5.74672 5.47623 5.10954 - 4.53268 4.09999 3.49327 2.81464 1.83564 1.50512 - 1.21893 1.18622 1.16879 1.16468 1.14960 1.15980 - 11.89260 10.92088 10.33055 9.79238 9.30065 8.85041 - 8.43980 8.06655 7.72866 7.42385 7.14927 6.90080 - 6.67186 6.45600 6.24827 6.03813 5.80037 5.47141 - 4.93118 4.50700 3.88503 3.15212 2.01754 1.61409 - 1.23813 1.18773 1.15521 1.15072 1.13880 1.14778 - 11.88957 10.93217 10.35612 9.82871 9.34545 8.90262 - 8.49911 8.13370 7.80545 7.51265 7.25295 7.02287 - 6.81667 6.62726 6.44552 6.25201 6.01933 5.70753 - 5.22276 4.84026 4.25404 3.49786 2.17672 1.69691 - 1.25378 1.19345 1.15049 1.14419 1.14085 1.14046 - 11.88399 10.93561 10.36833 9.84905 9.37360 8.93876 - 8.54353 8.18680 7.86778 7.58494 7.33608 7.11802 - 6.92517 6.75091 6.58702 6.41532 6.20856 5.92299 - 5.46173 5.09181 4.52007 3.76197 2.34891 1.79871 - 1.27216 1.19904 1.14748 1.13999 1.13605 1.13556 - 11.87495 10.94242 10.38661 9.87772 9.41229 8.98777 - 8.60351 8.25869 7.95293 7.68483 7.45232 7.25214 - 7.07847 6.92502 6.78517 6.64348 6.47525 6.23718 - 5.83269 5.49427 4.95060 4.18838 2.64797 2.00025 - 1.31633 1.21361 1.14353 1.13762 1.12715 1.12940 - 11.87024 10.94847 10.39932 9.89700 9.43819 9.02067 - 8.64375 8.30658 8.00881 7.74931 7.52638 7.33727 - 7.17690 7.03969 6.91977 6.80250 6.66393 6.46128 - 6.10013 5.78904 5.27788 4.53393 2.91753 2.18220 - 1.36032 1.23338 1.14347 1.13561 1.12266 1.12564 - 11.85776 10.95838 10.41978 9.92757 9.47859 9.07104 - 8.70414 8.37720 8.08997 7.84181 7.63165 7.45776 - 7.31651 7.20404 7.11652 7.04205 6.95925 6.82500 - 6.54639 6.28508 5.83341 5.14990 3.49087 2.58747 - 1.46464 1.28684 1.15000 1.13394 1.12111 1.12057 - 11.85316 10.96998 10.43118 9.94061 9.49530 9.09315 - 8.73288 8.41338 8.13388 7.89365 7.69154 7.52561 - 7.39193 7.28764 7.21338 7.16629 7.13073 7.05084 - 6.82429 6.59899 6.20908 5.58021 3.90525 2.94063 - 1.57419 1.34363 1.15787 1.13756 1.11815 1.11804 - 11.80118 10.97558 10.44247 9.95720 9.51698 9.12002 - 8.76513 8.45143 8.17827 7.94514 7.75122 7.59500 - 7.47306 7.38351 7.32846 7.30759 7.30978 7.28752 - 7.15071 6.98661 6.67184 6.12911 4.54688 3.49307 - 1.77894 1.46211 1.17918 1.14564 1.11615 1.11545 - 11.75730 10.97844 10.44781 9.96493 9.52711 9.13272 - 8.78067 8.47007 8.20040 7.97119 7.78181 7.63087 - 7.51521 7.43344 7.38850 7.38168 7.40500 7.41703 - 7.33758 7.21480 6.95374 6.47940 5.00743 3.92104 - 1.96894 1.57766 1.20257 1.15504 1.11606 1.11414 - 11.70351 10.97365 10.45289 9.97465 9.53851 9.14477 - 8.79291 8.48249 8.21342 7.98553 7.79862 7.65203 - 7.54378 7.47257 7.43820 7.43474 7.45265 7.47471 - 7.45175 7.37437 7.15646 6.72374 5.35391 4.26897 - 2.14529 1.68863 1.22668 1.16548 1.11637 1.11336 - 11.68083 10.97414 10.45474 9.97771 9.54280 9.15015 - 8.79932 8.49010 8.22250 7.99638 7.81147 7.66712 - 7.56153 7.49362 7.46365 7.46638 7.49353 7.53018 - 7.53388 7.48018 7.30029 6.91394 5.62129 4.55832 - 2.31428 1.79420 1.25083 1.17562 1.11797 1.11284 - 11.65209 10.97466 10.45681 9.98145 9.54818 9.15708 - 8.80779 8.50019 8.23449 8.01058 7.82818 7.68672 - 7.58456 7.52094 7.49662 7.50733 7.54644 7.60216 - 7.64083 7.61938 7.49607 7.18374 6.02038 5.01151 - 2.62678 1.99281 1.29896 1.19637 1.12212 1.11217 - 11.63400 10.97508 10.45805 9.98363 9.55141 9.16132 - 8.81306 8.50656 8.24204 8.01941 7.83849 7.69878 - 7.59875 7.53776 7.51697 7.53261 7.57905 7.64664 - 7.70723 7.70661 7.62316 7.36700 6.30854 5.35564 - 2.90381 2.17510 1.34647 1.21799 1.12693 1.11177 - 11.60625 10.97563 10.45980 9.98663 9.55568 9.16703 - 8.82028 8.51532 8.25233 8.03137 7.85236 7.71499 - 7.61791 7.56065 7.54473 7.56709 7.62349 7.70768 - 7.79887 7.82763 7.80457 7.64193 6.78081 5.95154 - 3.47777 2.57732 1.46202 1.27478 1.13998 1.11125 - 11.59075 10.97609 10.46072 9.98797 9.55759 9.16962 - 8.82372 8.51980 8.25804 8.03818 7.85971 7.72241 - 7.62631 7.57187 7.55999 7.58576 7.64447 7.73615 - 7.85226 7.90150 7.89505 7.76162 7.09909 6.40388 - 3.89080 2.89163 1.57605 1.34024 1.16019 1.11099 - 11.57362 10.97674 10.46224 9.98995 9.55991 9.17238 - 8.82705 8.52381 8.26282 8.04385 7.86641 7.73038 - 7.63589 7.58354 7.57440 7.60375 7.66742 7.76747 - 7.90202 7.97010 7.99625 7.91225 7.43570 6.93571 - 4.55204 3.41720 1.78287 1.46743 1.18171 1.11074 - 11.58527 10.98347 10.46145 9.98616 9.55591 9.16942 - 8.82578 8.52433 8.26480 8.04708 7.87101 7.73584 - 7.63921 7.58109 7.56729 7.60398 7.69248 7.81067 - 7.92941 7.98676 8.03778 8.03141 7.64627 7.12892 - 5.05925 3.89900 1.97196 1.56603 1.20338 1.11062 - 11.57950 10.98342 10.46166 9.98664 9.55659 9.17030 - 8.82683 8.52559 8.26628 8.04880 7.87300 7.73820 - 7.64205 7.58457 7.57163 7.60953 7.69975 7.82049 - 7.94410 8.00678 8.06926 8.08452 7.77716 7.33359 - 5.41144 4.24046 2.15987 1.67801 1.22741 1.11055 - 11.57547 10.98348 10.46186 9.98695 9.55702 9.17086 - 8.82752 8.52641 8.26725 8.04994 7.87436 7.73980 - 7.64398 7.58692 7.57453 7.61322 7.70458 7.82708 - 7.95412 8.02039 8.09037 8.12025 7.86958 7.48085 - 5.68645 4.52471 2.33461 1.78907 1.25103 1.11050 - 11.55004 10.97714 10.46357 9.99204 9.56271 9.17584 - 8.83114 8.52854 8.26829 8.05041 7.87485 7.74139 - 7.64916 7.59824 7.59086 7.62498 7.69882 7.81277 - 7.96148 8.04396 8.12418 8.16458 7.99207 7.67846 - 6.09461 4.97649 2.64807 2.00626 1.29820 1.11043 - 11.54848 10.97651 10.46247 9.99134 9.56276 9.17650 - 8.83221 8.52993 8.26998 8.05222 7.87622 7.74191 - 7.64937 7.59941 7.59378 7.62902 7.70229 7.81542 - 7.96926 8.05936 8.14564 8.17956 8.04344 7.85631 - 6.39173 5.28479 2.91893 2.22304 1.33753 1.11038 - 0.75600 0.78838 0.82133 0.85505 0.88961 0.92512 - 0.96184 1.00016 1.04069 1.08382 1.12994 1.17965 - 1.23384 1.29237 1.35178 1.40337 1.43847 1.46052 - 1.47519 1.48080 1.48942 1.49752 1.49454 1.49309 - 1.49350 1.49356 1.49331 1.49337 1.49323 1.49331 - 1.06343 1.10110 1.14032 1.18151 1.22479 1.27025 - 1.31799 1.36807 1.42054 1.47538 1.53241 1.59131 - 1.65148 1.71195 1.77126 1.82698 1.87500 1.90829 - 1.91824 1.91548 1.91732 1.92442 1.92586 1.92411 - 1.92499 1.92545 1.92533 1.92519 1.92550 1.92525 - 1.33592 1.38302 1.43150 1.48187 1.53419 1.58844 - 1.64460 1.70260 1.76230 1.82353 1.88591 1.94893 - 2.01185 2.07361 2.13270 2.18707 2.23417 2.27170 - 2.29337 2.29293 2.28064 2.26521 2.28263 2.30034 - 2.29378 2.28978 2.29045 2.29144 2.28917 2.29067 - 1.82674 1.88946 1.95239 2.01614 2.08057 2.14545 - 2.21055 2.27564 2.34050 2.40492 2.46880 2.53213 - 2.59550 2.65883 2.71979 2.77385 2.81579 2.84332 - 2.85773 2.86278 2.86858 2.87427 2.87949 2.87986 - 2.87862 2.87840 2.87854 2.87862 2.87857 2.87856 - 2.24037 2.32247 2.40117 2.47710 2.54991 2.61948 - 2.68606 2.75050 2.81411 2.87700 2.93894 2.99958 - 3.05891 3.11645 3.17038 3.21770 3.25542 3.28340 - 3.30166 3.30780 3.31660 3.32662 3.33435 3.33487 - 3.33192 3.33144 3.33181 3.33183 3.33194 3.33187 - 2.60156 2.70099 2.79302 2.87819 2.95604 3.02664 - 3.09085 3.15085 3.20968 3.26781 3.32495 3.38038 - 3.43345 3.48337 3.52915 3.56994 3.60477 3.63271 - 3.65279 3.66080 3.67210 3.68489 3.69577 3.69582 - 3.69207 3.69138 3.69177 3.69200 3.69187 3.69194 - 2.92201 3.03571 3.13818 3.22989 3.31029 3.37962 - 3.43939 3.49294 3.54491 3.59616 3.64644 3.69505 - 3.74120 3.78411 3.82310 3.85788 3.88824 3.91430 - 3.93641 3.94696 3.96076 3.97513 3.98744 3.98771 - 3.98365 3.98287 3.98331 3.98356 3.98339 3.98353 - 3.46818 3.60325 3.71959 3.81775 3.89714 3.95858 - 4.00499 4.04216 4.07779 4.11357 4.14917 4.18380 - 4.21608 4.24499 4.27056 4.29399 4.31673 4.33986 - 4.36485 4.37874 4.39479 4.40940 4.42279 4.42427 - 4.42080 4.42021 4.42077 4.42078 4.42096 4.42092 - 3.92551 4.06994 4.19035 4.28755 4.36107 4.41217 - 4.44461 4.46564 4.48464 4.50383 4.52320 4.54243 - 4.56074 4.57769 4.59344 4.60878 4.62502 4.64435 - 4.66954 4.68455 4.70021 4.71294 4.72630 4.72861 - 4.72734 4.72706 4.72752 4.72752 4.72766 4.72766 - 4.81570 4.95735 5.06652 5.14541 5.19406 5.21467 - 5.21235 5.19614 5.17748 5.15938 5.14270 5.12837 - 5.11739 5.11069 5.10797 5.10755 5.10886 5.11668 - 5.13644 5.14962 5.15919 5.16313 5.17233 5.17629 - 5.18198 5.18274 5.18277 5.18277 5.18276 5.18282 - 5.48000 5.60020 5.68368 5.73433 5.75288 5.74227 - 5.70838 5.66093 5.61192 5.56479 5.52090 5.48167 - 5.44911 5.42457 5.40712 5.39303 5.38017 5.37500 - 5.38459 5.39253 5.39338 5.38723 5.38959 5.39421 - 5.40638 5.40816 5.40770 5.40772 5.40752 5.40765 - 6.41928 6.52075 6.54761 6.51880 6.45445 6.37623 - 6.29122 6.20516 6.12385 6.04638 5.96802 5.88845 - 5.81796 5.76372 5.72288 5.68556 5.64553 5.61650 - 5.60515 5.59719 5.58035 5.55982 5.54867 5.55194 - 5.57107 5.57405 5.57309 5.57264 5.57265 5.57271 - 7.10830 7.14187 7.10751 7.02513 6.91209 6.78691 - 6.65697 6.52922 6.41070 6.30138 6.19761 6.09797 - 6.00845 5.93268 5.86858 5.80925 5.75028 5.70070 - 5.66481 5.64544 5.61773 5.58886 5.56845 5.56925 - 5.58653 5.58927 5.58815 5.58767 5.58766 5.58773 - 7.63650 7.61720 7.53040 7.39867 7.24012 7.07359 - 6.90627 6.74467 6.59569 6.45989 6.33508 6.21916 - 6.11380 6.01945 5.93511 5.85735 5.78374 5.71745 - 5.65976 5.63103 5.59720 5.56608 5.54043 5.53802 - 5.54748 5.54905 5.54807 5.54771 5.54769 5.54776 - 8.05977 8.00165 7.87049 7.69331 7.49193 7.28817 - 7.08893 6.89909 6.72430 6.56564 6.42216 6.29150 - 6.17166 6.06082 5.95890 5.86562 5.78015 5.69998 - 5.62351 5.58714 5.55020 5.52038 5.49209 5.48625 - 5.48503 5.48499 5.48432 5.48416 5.48410 5.48417 - 8.70676 8.58652 8.37959 8.12254 7.84581 7.57837 - 7.32635 7.09169 6.87704 6.68274 6.50671 6.34606 - 6.19785 6.06046 5.93327 5.81585 5.70688 5.60229 - 5.49961 5.45152 5.40935 5.38182 5.35166 5.33898 - 5.32025 5.31746 5.31713 5.31746 5.31700 5.31730 - 9.18020 9.00827 8.73658 8.41068 8.06981 7.74965 - 7.45527 7.18584 6.94073 6.71906 6.51739 6.33210 - 6.16017 6.00022 5.85162 5.71350 5.58444 5.46061 - 5.34014 5.28416 5.23555 5.20481 5.17218 5.15596 - 5.12838 5.12408 5.12382 5.12443 5.12364 5.12414 - 10.10179 9.61837 9.15171 8.71526 8.30713 7.92578 - 7.56997 7.23941 6.93391 6.65260 6.39385 6.15539 - 5.93457 5.73022 5.54348 5.37354 5.21796 5.06511 - 4.90560 4.82770 4.75998 4.71624 4.66737 4.65100 - 4.62965 4.62669 4.62610 4.62610 4.62621 4.62598 - 10.57550 9.96638 9.39191 8.86246 8.37417 7.92449 - 7.51100 7.13206 6.78676 6.47247 6.18586 5.92292 - 5.67832 5.44866 5.23514 5.03712 4.85255 4.67321 - 4.49277 4.40473 4.32223 4.26139 4.19634 4.18160 - 4.17741 4.17745 4.17583 4.17551 4.17526 4.17508 - 11.11824 10.32562 9.60036 8.94307 8.34588 7.80433 - 7.31511 6.87373 6.47652 6.11907 5.79592 5.50078 - 5.22534 4.96385 4.71655 4.48397 4.26346 4.04888 - 3.83714 3.73569 3.64207 3.57388 3.49914 3.48099 - 3.47457 3.47443 3.47262 3.47232 3.47191 3.47165 - 11.42176 10.49608 9.67067 8.93316 8.27228 7.67991 - 7.15065 6.67682 6.25108 5.86740 5.51941 5.19961 - 4.89825 4.60895 4.33295 4.07333 3.83128 3.60271 - 3.38649 3.28412 3.18487 3.10872 3.03356 3.01420 - 2.99685 2.99472 2.99335 2.99315 2.99304 2.99292 - 11.63362 10.61159 9.71710 8.92416 8.21978 7.59265 - 7.03460 6.53556 6.08565 5.67830 5.30772 4.96729 - 4.64872 4.34637 4.06020 3.79090 3.53881 3.30022 - 3.07432 2.96727 2.86389 2.78490 2.70699 2.68686 - 2.66818 2.66582 2.66437 2.66419 2.66407 2.66459 - 11.78288 10.69223 9.75090 8.91978 8.18538 7.53443 - 6.95609 6.43853 5.97046 5.54523 5.15755 4.80166 - 4.47054 4.15913 3.86630 3.59076 3.33167 3.08666 - 2.85475 2.74433 2.63661 2.55336 2.47224 2.45206 - 2.43503 2.43290 2.43127 2.43109 2.43091 2.43182 - 11.97972 10.79906 9.80033 8.92283 8.15229 7.47355 - 6.87159 6.33220 5.84262 5.39630 4.98840 4.61390 - 4.26695 3.94298 3.63981 3.35444 3.08455 2.82901 - 2.58579 2.46879 2.35362 2.26357 2.17584 2.15469 - 2.13890 2.13702 2.13517 2.13498 2.13473 2.13507 - 12.10192 10.86763 9.83816 8.93679 8.14865 7.45678 - 6.84413 6.29518 5.79649 5.34137 4.92486 4.54172 - 4.18592 3.85278 3.54030 3.24576 2.96658 2.70021 - 2.44394 2.31946 2.19721 2.10164 2.00678 1.98340 - 1.96551 1.96344 1.96153 1.96130 1.96108 1.96016 - 12.25331 10.96580 9.91437 8.99634 8.19808 7.49665 - 6.87577 6.31987 5.81578 5.35611 4.93489 4.54549 - 4.18001 3.83294 3.50339 3.19064 2.89224 2.60108 - 2.31141 2.16596 2.01959 1.90236 1.78595 1.75632 - 1.73232 1.72951 1.72723 1.72692 1.72669 1.72577 - 12.30550 11.01652 9.97675 9.06755 8.27613 7.57705 - 6.95648 6.40066 5.89789 5.44040 5.02128 4.63266 - 4.26496 3.91168 3.57243 3.24744 2.93410 2.62244 - 2.30182 2.13479 1.95838 1.81126 1.67039 1.63609 - 1.60840 1.60492 1.60189 1.60156 1.60122 1.60317 - 12.31988 11.05466 10.05799 9.18805 8.42552 7.74710 - 7.14072 6.59420 6.09713 5.64273 5.22509 4.83742 - 4.47138 4.12015 3.78013 3.44595 3.11023 2.76126 - 2.38298 2.17546 1.94724 1.74640 1.54585 1.50372 - 1.47620 1.47259 1.46675 1.46560 1.46612 1.47271 - 12.26092 11.05815 10.12277 9.29742 8.56080 7.89687 - 7.29807 6.75698 6.26713 5.82194 5.41439 5.03624 - 4.67693 4.32817 3.98647 3.64676 3.29954 2.92543 - 2.49951 2.25778 1.98843 1.74713 1.48808 1.42770 - 1.40446 1.40307 1.39408 1.39170 1.39387 1.40184 - 12.22306 11.04729 10.15247 9.36174 8.65187 8.00937 - 7.42766 6.90003 6.42069 5.98366 5.58245 5.20934 - 4.85427 4.50903 4.16948 3.82930 3.47650 3.08619 - 2.62555 2.35595 2.04799 1.76753 1.45807 1.38350 - 1.35981 1.35929 1.34806 1.34493 1.34814 1.35579 - 12.18353 11.03166 10.17300 9.41148 8.72501 8.10148 - 7.53513 7.01990 6.55051 6.12147 5.72680 5.35923 - 5.00918 4.66852 4.33265 3.99419 3.63902 3.23750 - 2.74959 2.45684 2.11591 1.80028 1.44420 1.35565 - 1.32928 1.32923 1.31622 1.31250 1.31651 1.32306 - 12.11170 10.99913 10.19967 9.48430 8.83605 8.24407 - 7.70383 7.21019 6.75871 6.34467 5.96283 5.60668 - 5.26743 4.93723 4.61074 4.27908 3.92474 3.51031 - 2.98308 2.65426 2.25928 1.88280 1.44272 1.32744 - 1.29068 1.29049 1.27488 1.27039 1.27538 1.27934 - 12.05386 10.97159 10.21632 9.53561 8.91667 8.34949 - 7.83034 7.35465 6.91859 6.51800 6.14817 5.80312 - 5.47467 5.15518 4.83892 4.51597 4.16641 3.74699 - 3.19445 2.83940 2.40232 1.97493 1.46005 1.31955 - 1.26775 1.26638 1.24904 1.24413 1.24948 1.25128 - 12.02226 10.96415 10.25659 9.61734 9.03654 8.50550 - 8.02083 7.57836 7.17444 6.80502 6.46527 6.14881 - 5.84645 5.54994 5.25430 4.95093 4.62223 4.22826 - 3.68268 3.28904 2.73930 2.17128 1.52456 1.35044 - 1.24432 1.23122 1.21193 1.21021 1.20719 1.21111 - 11.96332 10.93706 10.27015 9.66606 9.11592 8.61245 - 8.15270 7.73316 7.35061 7.00154 6.68160 6.38489 - 6.10271 5.82707 5.55288 5.27095 4.96189 4.58048 - 4.03017 3.62115 3.03691 2.40751 1.61999 1.38901 - 1.23380 1.21513 1.19287 1.19037 1.18742 1.18965 - 11.85208 10.88107 10.27687 9.72524 9.21952 8.75432 - 8.32770 7.93728 7.58094 7.25639 6.96076 6.69007 - 6.43818 6.19884 5.96641 5.72943 5.46148 5.09820 - 4.52580 4.09587 3.49234 2.81666 1.84111 1.51149 - 1.22641 1.19398 1.17680 1.17269 1.15744 1.16724 - 11.84516 10.88307 10.29645 9.76135 9.27207 8.82383 - 8.41477 8.04268 7.70561 7.40136 7.12713 6.87896 - 6.65041 6.43524 6.22857 6.01994 5.78429 5.45822 - 4.92200 4.50049 3.88185 3.15234 2.02226 1.62007 - 1.24560 1.19554 1.16334 1.15883 1.14673 1.15568 - 11.84273 10.89497 10.32249 9.79771 9.31643 8.87505 - 8.47263 8.10810 7.78065 7.48864 7.22969 7.00037 - 6.79490 6.60629 6.42550 6.23330 6.00251 5.69327 - 5.21200 4.83198 4.24914 3.49650 2.18022 1.70245 - 1.26155 1.20151 1.15862 1.15232 1.14900 1.14866 - 11.83899 10.89902 10.33428 9.81716 9.34353 8.91019 - 8.51623 8.16056 7.84251 7.56054 7.31250 7.09521 - 6.90316 6.72974 6.56680 6.39622 6.19083 5.90728 - 5.44936 5.08198 4.51371 3.75938 2.35180 1.80387 - 1.27995 1.20718 1.15573 1.14823 1.14433 1.14397 - 11.83197 10.90645 10.35234 9.84511 9.38122 8.95813 - 8.57522 8.23162 7.92699 7.65991 7.42833 7.22898 - 7.05611 6.90338 6.76426 6.62334 6.45609 6.21960 - 5.81798 5.48191 4.94168 4.18356 2.64981 2.00486 - 1.32407 1.22179 1.15197 1.14607 1.13568 1.13807 - 11.82796 10.91280 10.36494 9.86413 9.40675 8.99061 - 8.61505 8.27915 7.98253 7.72405 7.50203 7.31372 - 7.15405 7.01747 6.89816 6.78147 6.64366 6.44225 - 6.08365 5.77475 5.26699 4.52730 2.91831 2.18623 - 1.36800 1.24155 1.15204 1.14421 1.13133 1.13446 - 11.81612 10.92283 10.38568 9.89472 9.44708 9.04085 - 8.67524 8.34949 8.06330 7.81605 7.60664 7.43337 - 7.29261 7.18051 7.09329 7.01918 6.93693 6.80364 - 6.52697 6.26748 5.81897 5.13995 3.48943 2.58985 - 1.47197 1.29493 1.15878 1.14272 1.13003 1.12956 - 11.81115 10.93433 10.39717 9.90813 9.46420 9.06328 - 8.70412 8.38562 8.10697 7.86749 7.66600 7.50060 - 7.36733 7.26337 7.18940 7.14253 7.10726 7.02800 - 6.80306 6.57938 6.19236 5.56772 3.90170 2.94176 - 1.58113 1.35146 1.16670 1.14648 1.12717 1.12709 - 11.75940 10.93955 10.40836 9.92463 9.48584 9.09016 - 8.73639 8.42365 8.15130 7.91885 7.72548 7.56967 - 7.44804 7.35873 7.30385 7.28306 7.28539 7.26343 - 7.12765 6.96471 6.65219 6.11315 4.54018 3.49185 - 1.78497 1.46942 1.18802 1.15468 1.12525 1.12462 - 11.71593 10.94221 10.41349 9.93219 9.49584 9.10275 - 8.75181 8.44223 8.17337 7.94485 7.75601 7.60551 - 7.49018 7.40861 7.36380 7.35703 7.38033 7.39246 - 7.31361 7.19163 6.93234 6.46119 4.99833 3.91779 - 1.97410 1.58448 1.21136 1.16410 1.12516 1.12339 - 11.66276 10.93723 10.41837 9.94182 9.50725 9.11483 - 8.76405 8.45455 8.18629 7.95911 7.77280 7.62667 - 7.51879 7.44780 7.41357 7.41013 7.42796 7.44997 - 7.42728 7.35042 7.13382 6.70384 5.34305 4.26387 - 2.14958 1.69501 1.23540 1.17454 1.12546 1.12266 - 11.64043 10.93782 10.42012 9.94486 9.51150 9.12016 - 8.77045 8.46214 8.19535 7.96992 7.78560 7.64174 - 7.53653 7.46893 7.43913 7.44183 7.46872 7.50516 - 7.50904 7.45572 7.27685 6.89288 5.60877 4.55170 - 2.31783 1.80017 1.25945 1.18466 1.12705 1.12217 - 11.61244 10.93865 10.42248 9.94863 9.51678 9.12695 - 8.77879 8.47219 8.20733 7.98411 7.80226 7.66124 - 7.55947 7.49616 7.47205 7.48268 7.52140 7.57679 - 7.61553 7.59428 7.47163 7.16110 6.00536 5.00238 - 2.62885 1.99798 1.30737 1.20532 1.13120 1.12155 - 11.59473 10.93927 10.42392 9.95090 9.51993 9.13109 - 8.78399 8.47853 8.21487 7.99295 7.81255 7.67326 - 7.57358 7.51287 7.49223 7.50775 7.55384 7.62111 - 7.68164 7.68111 7.59810 7.34332 6.29159 5.34445 - 2.90468 2.17960 1.35467 1.22683 1.13603 1.12118 - 11.56762 10.94022 10.42597 9.95396 9.52413 9.13665 - 8.79111 8.48726 8.22519 8.00491 7.82643 7.68946 - 7.59263 7.53551 7.51963 7.54190 7.59804 7.68193 - 7.77285 7.80159 7.77871 7.61685 6.76080 5.93673 - 3.47604 2.58020 1.46968 1.28328 1.14910 1.12068 - 11.55187 10.94059 10.42709 9.95564 9.52635 9.13952 - 8.79466 8.49154 8.23020 8.01073 7.83325 7.69754 - 7.60228 7.54710 7.53377 7.55949 7.62078 7.71362 - 7.82089 7.86473 7.87385 7.76774 7.05296 6.32500 - 3.92355 2.92139 1.58001 1.34151 1.16240 1.12043 - 11.53520 10.94074 10.42791 9.95707 9.52841 9.14215 - 8.79795 8.49571 8.23558 8.01731 7.84042 7.70480 - 7.61056 7.55834 7.54916 7.57838 7.64182 7.74151 - 7.87557 7.94339 7.96950 7.88595 7.41197 6.91495 - 4.54530 3.41640 1.78903 1.47476 1.19090 1.12017 - 11.54669 10.94726 10.42692 9.95326 9.52445 9.13924 - 8.79670 8.49625 8.23756 8.02053 7.84500 7.71025 - 7.61390 7.55593 7.54212 7.57864 7.66681 7.78454 - 7.90283 7.95995 8.01084 8.00456 7.62133 7.10706 - 5.05011 3.89581 1.97728 1.57286 1.21239 1.12004 - 11.54090 10.94711 10.42713 9.95373 9.52512 9.14012 - 8.79778 8.49752 8.23905 8.02225 7.84702 7.71261 - 7.61674 7.55941 7.54645 7.58419 7.67406 7.79433 - 7.91745 7.97989 8.04220 8.05750 7.75152 7.31052 - 5.40036 4.23543 2.16423 1.68434 1.23637 1.11997 - 11.53683 10.94718 10.42733 9.95404 9.52558 9.14070 - 8.79850 8.49838 8.24005 8.02342 7.84838 7.71424 - 7.61868 7.56175 7.54936 7.58788 7.67890 7.80092 - 7.92741 7.99343 8.06323 8.09316 7.84351 7.45694 - 5.67373 4.51806 2.33807 1.79494 1.25987 1.11992 - 11.51189 10.94083 10.42894 9.95912 9.53133 9.14577 - 8.80215 8.50048 8.24104 8.02385 7.84882 7.71575 - 7.62378 7.57299 7.56562 7.59960 7.67314 7.78667 - 7.93480 8.01691 8.09684 8.13726 7.96552 7.65348 - 6.07938 4.96721 2.64998 2.01109 1.30681 1.11986 - 11.51047 10.94051 10.42794 9.95840 9.53121 9.14620 - 8.80308 8.50182 8.24274 8.02568 7.85023 7.71626 - 7.62393 7.57405 7.56835 7.60347 7.67657 7.78934 - 7.94257 8.03231 8.11828 8.15209 8.01655 7.83077 - 6.37461 5.27327 2.91951 2.22713 1.34575 1.11983 - 0.73870 0.77046 0.80280 0.83593 0.86992 0.90488 - 0.94108 0.97892 1.01902 1.06176 1.10757 1.15708 - 1.21118 1.26975 1.32934 1.38111 1.41624 1.43818 - 1.45257 1.45794 1.46625 1.47403 1.47078 1.46927 - 1.46962 1.46968 1.46943 1.46948 1.46935 1.46942 - 1.04169 1.07864 1.11718 1.15771 1.20036 1.24526 - 1.29250 1.34216 1.39431 1.44894 1.50590 1.56487 - 1.62523 1.68601 1.74573 1.80193 1.85036 1.88369 - 1.89290 1.88956 1.89111 1.89826 1.89940 1.89743 - 1.89821 1.89867 1.89854 1.89839 1.89872 1.89846 - 1.31018 1.35684 1.40491 1.45490 1.50684 1.56075 - 1.61661 1.67434 1.73383 1.79491 1.85723 1.92027 - 1.98332 2.04533 2.10481 2.15971 2.20742 2.24549 - 2.26731 2.26668 2.25386 2.23773 2.25452 2.27221 - 2.26574 2.26175 2.26236 2.26334 2.26106 2.26258 - 1.79675 1.85879 1.92117 1.98453 2.04870 2.11348 - 2.17865 2.24394 2.30911 2.37396 2.43836 2.50230 - 2.56631 2.63026 2.69180 2.74631 2.78849 2.81598 - 2.83016 2.83516 2.84095 2.84658 2.85143 2.85164 - 2.85027 2.85004 2.85016 2.85025 2.85019 2.85019 - 2.20741 2.28871 2.36693 2.44268 2.51563 2.58563 - 2.65285 2.71803 2.78232 2.84577 2.90821 2.96935 - 3.02928 3.08762 3.14244 3.19046 3.22843 3.25642 - 3.27469 3.28089 3.28982 3.29994 3.30735 3.30774 - 3.30469 3.30419 3.30455 3.30457 3.30467 3.30460 - 2.56633 2.66519 2.75699 2.84227 2.92057 2.99188 - 3.05703 3.11805 3.17782 3.23678 3.29462 3.35067 - 3.40438 3.45497 3.50148 3.54298 3.57841 3.60677 - 3.62703 3.63508 3.64659 3.65966 3.67042 3.67029 - 3.66645 3.66575 3.66613 3.66636 3.66623 3.66630 - 2.88522 2.99851 3.10096 3.19303 3.27414 3.34448 - 3.40545 3.46026 3.51336 3.56556 3.61662 3.66587 - 3.71266 3.75629 3.79607 3.83164 3.86273 3.88937 - 3.91188 3.92262 3.93678 3.95153 3.96383 3.96395 - 3.95980 3.95902 3.95946 3.95972 3.95956 3.95967 - 3.42949 3.56436 3.68102 3.77992 3.86045 3.92335 - 3.97138 4.01014 4.04708 4.08383 4.12017 4.15538 - 4.18837 4.21830 4.24510 4.26964 4.29309 4.31681 - 4.34266 4.35713 4.37387 4.38902 4.40249 4.40392 - 4.40039 4.39981 4.40036 4.40038 4.40055 4.40052 - 3.88564 4.03030 4.15137 4.24961 4.32447 4.37714 - 4.41129 4.43395 4.45434 4.47465 4.49493 4.51495 - 4.53415 4.55223 4.56928 4.58583 4.60300 4.62323 - 4.64963 4.66541 4.68194 4.69537 4.70895 4.71124 - 4.70997 4.70969 4.71015 4.71016 4.71030 4.71029 - 4.77474 4.91758 5.02814 5.10850 5.15868 5.18084 - 5.18006 5.16535 5.14814 5.13142 5.11611 5.10310 - 5.09347 5.08818 5.08688 5.08785 5.09049 5.09973 - 5.12127 5.13549 5.14620 5.15100 5.16069 5.16471 - 5.17052 5.17129 5.17132 5.17134 5.17130 5.17137 - 5.43924 5.56131 5.64664 5.69904 5.71920 5.71009 - 5.67760 5.63155 5.58402 5.53848 5.49627 5.45876 - 5.42788 5.40492 5.38899 5.37639 5.36508 5.36160 - 5.37318 5.38225 5.38428 5.37902 5.38198 5.38674 - 5.39912 5.40090 5.40043 5.40046 5.40026 5.40039 - 6.38136 6.48358 6.51278 6.48701 6.42525 6.34827 - 6.26368 6.17833 6.09921 6.02490 5.94921 5.87112 - 5.80175 5.74903 5.71006 5.67467 5.63637 5.60902 - 5.59961 5.59271 5.57690 5.55711 5.54665 5.55014 - 5.56959 5.57261 5.57166 5.57121 5.57122 5.57126 - 7.07320 7.10730 7.07559 6.99677 6.88678 6.76288 - 6.63319 6.50603 6.38990 6.28418 6.18352 6.08561 - 5.99731 5.92302 5.86068 5.80322 5.74608 5.69827 - 5.66411 5.64562 5.61874 5.59046 5.57075 5.57179 - 5.58940 5.59219 5.59107 5.59060 5.59061 5.59066 - 7.60426 7.58542 7.50158 7.37384 7.21859 7.05323 - 6.88590 6.72478 6.57846 6.44681 6.32553 6.21146 - 6.10728 6.01433 5.93163 5.85566 5.78386 5.71935 - 5.66330 5.63529 5.60211 5.57147 5.54648 5.54430 - 5.55410 5.55572 5.55474 5.55438 5.55437 5.55442 - 8.03025 7.97272 7.84484 7.67200 7.47402 7.27126 - 7.07166 6.88215 6.71038 6.55646 6.41693 6.28812 - 6.16930 6.05974 5.95937 5.86779 5.78405 5.70567 - 5.63085 5.59508 5.55866 5.52925 5.50158 5.49594 - 5.49500 5.49500 5.49433 5.49417 5.49414 5.49418 - 8.67920 8.56419 8.36208 8.10880 7.83433 7.56745 - 7.31518 7.08084 6.86849 6.67830 6.50732 6.35143 - 6.20582 6.06788 5.93868 5.82164 5.71757 5.61644 - 5.51248 5.46465 5.42380 5.39740 5.36627 5.35499 - 5.33565 5.33284 5.33272 5.33289 5.33283 5.33284 - 9.15822 8.99033 8.72272 8.40042 8.06239 7.74416 - 7.45122 7.18349 6.94096 6.72245 6.52379 6.34086 - 6.17067 6.01190 5.86412 5.72695 5.59933 5.47727 - 5.35841 5.30297 5.25471 5.22412 5.19187 5.17577 - 5.14817 5.14383 5.14357 5.14420 5.14340 5.14388 - 10.08355 9.60721 9.14676 8.71556 8.31187 7.93421 - 7.58140 7.25322 6.94953 6.66955 6.41174 6.17396 - 5.95375 5.75006 5.56406 5.39502 5.24057 5.08914 - 4.93131 4.85415 4.78665 4.74260 4.69380 4.67761 - 4.65598 4.65295 4.65238 4.65238 4.65251 4.65227 - 10.55595 9.95813 9.39303 8.87110 8.38874 7.94356 - 7.53332 7.15650 6.81235 6.49841 6.21152 5.94797 - 5.70282 5.47294 5.25960 5.06221 4.87877 4.70101 - 4.52239 4.43505 4.35252 4.29100 4.22577 4.21126 - 4.20681 4.20678 4.20517 4.20484 4.20460 4.20445 - 11.10113 10.32125 9.60599 8.95657 8.36541 7.82827 - 7.34210 6.90256 6.50624 6.14888 5.82527 5.52938 - 5.25329 4.99152 4.74433 4.51228 4.29273 4.07939 - 3.86885 3.76778 3.67395 3.60508 3.52998 3.51195 - 3.50540 3.50521 3.50341 3.50311 3.50272 3.50248 - 11.41274 10.49484 9.67591 8.94389 8.28764 7.69910 - 7.17282 6.70113 6.27669 5.89364 5.54583 5.22611 - 4.92508 4.63662 4.36172 4.10303 3.86147 3.63322 - 3.41733 3.31505 3.21568 3.13920 3.06370 3.04425 - 3.02685 3.02471 3.02332 3.02313 3.02301 3.02289 - 11.62276 10.61104 9.72339 8.93483 8.23310 7.60745 - 7.05031 6.55219 6.10377 5.69846 5.33019 4.99207 - 4.67531 4.37398 4.08831 3.81936 3.56774 3.32959 - 3.10387 2.99677 2.89319 2.81392 2.73572 2.71551 - 2.69678 2.69441 2.69296 2.69277 2.69266 2.69312 - 11.77052 10.69170 9.75717 8.92957 8.19640 7.54539 - 6.96663 6.44927 5.98290 5.56068 5.17672 4.82456 - 4.49616 4.18592 3.89320 3.61766 3.35906 3.11461 - 2.88284 2.77231 2.66437 2.58086 2.49949 2.47925 - 2.46217 2.46003 2.45840 2.45822 2.45804 2.45886 - 11.96539 10.79693 9.80456 8.92999 8.16000 7.48055 - 6.87766 6.33825 5.85051 5.40758 5.00392 4.63363 - 4.28968 3.96693 3.66379 3.37835 3.10896 2.85402 - 2.61100 2.49393 2.37860 2.28835 2.20040 2.17918 - 2.16335 2.16146 2.15960 2.15941 2.15917 2.15949 - 12.08674 10.86277 9.83920 8.94115 8.15457 7.46321 - 6.85079 6.30246 5.80542 5.35278 4.93921 4.55897 - 4.20535 3.87338 3.56130 3.26705 2.98836 2.72251 - 2.46659 2.34219 2.21991 2.12420 2.02911 2.00565 - 1.98769 1.98560 1.98369 1.98346 1.98323 1.98244 - 12.23312 10.95333 9.90735 8.99407 8.19978 7.50165 - 6.88340 6.32943 5.82650 5.36744 4.94650 4.55739 - 4.19258 3.84674 3.51863 3.20702 2.90919 2.61847 - 2.32944 2.18435 2.03822 1.92100 1.80419 1.77440 - 1.75026 1.74743 1.74514 1.74482 1.74459 1.74372 - 12.27672 10.99678 9.96332 9.05956 8.27266 7.57732 - 6.95969 6.40592 5.90427 5.44721 5.02817 4.63972 - 4.27280 3.92112 3.58385 3.26044 2.94783 2.63667 - 2.31683 2.15026 1.97427 1.82727 1.68580 1.65127 - 1.62344 1.61994 1.61688 1.61656 1.61622 1.61779 - 12.24674 11.02553 10.05245 9.19220 8.42967 7.74541 - 7.13101 6.57816 6.07971 5.62850 5.21699 4.83648 - 4.47607 4.12757 3.78829 3.45463 3.12000 2.77104 - 2.39137 2.18437 1.96017 1.76393 1.55901 1.51239 - 1.48711 1.48454 1.47832 1.47690 1.47783 1.48309 - 12.21666 11.02158 10.09072 9.26930 8.53624 7.87562 - 7.27993 6.74179 6.25474 5.81223 5.40727 5.03160 - 4.67468 4.32820 3.98868 3.65102 3.30575 2.93333 - 2.50873 2.26746 1.99839 1.75710 1.49764 1.43710 - 1.41397 1.41262 1.40361 1.40125 1.40348 1.41005 - 12.17594 11.00664 10.11531 9.32780 8.62112 7.98184 - 7.40335 6.87898 6.40291 5.96911 5.57111 5.20111 - 4.84901 4.50649 4.16944 3.83155 3.48079 3.09225 - 2.63303 2.36394 2.05639 1.77605 1.46640 1.39176 - 1.36829 1.36781 1.35657 1.35347 1.35677 1.36302 - 12.13455 10.98839 10.13250 9.37368 8.69011 8.06970 - 7.50665 6.99486 6.52901 6.10361 5.71256 5.34853 - 5.00180 4.66416 4.33098 3.99491 3.64184 3.24212 - 2.75568 2.46355 2.12314 1.80781 1.45180 1.36329 - 1.33720 1.33718 1.32416 1.32047 1.32460 1.32989 - 12.06089 10.95295 10.15526 9.44194 8.79620 8.20716 - 7.67025 7.18024 6.73264 6.32265 5.94493 5.59283 - 5.25734 4.93045 4.60684 4.27762 3.92534 3.51268 - 2.98704 2.65899 2.26484 1.88902 1.44953 1.33446 - 1.29807 1.29793 1.28230 1.27784 1.28298 1.28605 - 12.00223 10.92421 10.16996 9.49092 8.87421 8.30982 - 7.79394 7.32195 6.88990 6.49357 6.12810 5.78735 - 5.46285 5.14680 4.83345 4.51290 4.16532 3.74762 - 3.19675 2.84261 2.40666 1.98028 1.46647 1.32632 - 1.27498 1.27367 1.25631 1.25143 1.25697 1.25816 - 11.97046 10.91617 10.20891 9.57078 8.99179 8.46324 - 7.98164 7.54273 7.14280 6.77766 6.44239 6.13039 - 5.83213 5.53915 5.24642 4.94531 4.61830 4.22558 - 3.68133 3.28890 2.74136 2.17560 1.53061 1.35691 - 1.25162 1.23865 1.21929 1.21755 1.21478 1.21848 - 11.91238 10.88987 10.22300 9.61975 9.07115 8.56990 - 8.11300 7.69679 7.31803 6.97307 6.65743 6.36503 - 6.08680 5.81449 5.54298 5.26311 4.95553 4.57534 - 4.02660 3.61905 3.03740 2.41076 1.62576 1.39542 - 1.24129 1.22279 1.20047 1.19794 1.19522 1.19740 - 11.80158 10.83518 10.23135 9.68071 9.17649 8.71330 - 8.28916 7.90159 7.54846 7.22737 6.93534 6.66824 - 6.41966 6.18310 5.95297 5.71779 5.45128 5.08954 - 4.51946 4.09135 3.49056 2.81797 1.84645 1.51793 - 1.23406 1.20189 1.18495 1.18083 1.16552 1.17548 - 11.79370 10.83739 10.25208 9.71843 9.23090 8.78469 - 8.37791 8.00831 7.67392 7.37247 7.10114 6.85582 - 6.62993 6.41707 6.21238 6.00543 5.77129 5.44693 - 4.91326 4.49377 3.87815 3.15219 2.02709 1.62634 - 1.25342 1.20368 1.17179 1.16727 1.15504 1.16420 - 11.78657 10.84880 10.27999 9.75784 9.27843 8.83843 - 8.43719 8.07402 7.74850 7.45893 7.20280 6.97641 - 6.77357 6.58696 6.40763 6.21652 5.98678 5.67922 - 5.20120 4.82372 4.24428 3.49516 2.18394 1.70829 - 1.26969 1.20997 1.16716 1.16082 1.15758 1.15738 - 11.78407 10.85285 10.29137 9.77677 9.30533 8.87391 - 8.48170 8.12780 7.81161 7.53160 7.28561 7.07033 - 6.88009 6.70824 6.54667 6.37744 6.17363 5.89212 - 5.43725 5.07219 4.50735 3.75685 2.35493 1.80935 - 1.28814 1.21574 1.16441 1.15690 1.15303 1.15283 - 11.77796 10.85989 10.30850 9.80384 9.34254 8.92196 - 8.54140 8.19994 7.89706 7.63144 7.40102 7.20268 - 7.03079 6.87915 6.74129 6.60191 6.43655 6.20238 - 5.80384 5.46996 4.93291 4.17871 2.65180 2.00974 - 1.33219 1.23037 1.16085 1.15494 1.14456 1.14711 - 11.77355 10.86555 10.32038 9.82224 9.36755 8.95404 - 8.58094 8.24719 7.95228 7.69506 7.47397 7.28638 - 7.12743 6.99177 6.87362 6.75845 6.62254 6.42347 - 6.06784 5.76105 5.25641 4.52067 2.91916 2.19044 - 1.37600 1.25009 1.16102 1.15321 1.14032 1.14361 - 11.75963 10.87409 10.33980 9.85164 9.40664 9.00289 - 8.63952 8.31572 8.03108 7.78503 7.57656 7.40407 - 7.26412 7.15304 7.06704 6.99432 6.91363 6.78219 - 6.50804 6.25048 5.80502 5.13017 3.48796 2.59228 - 1.47954 1.30330 1.16788 1.15182 1.13917 1.13885 - 11.73828 10.87801 10.34969 9.86691 9.42696 9.02823 - 8.66996 8.35166 8.07314 7.83412 7.63373 7.47068 - 7.34192 7.24432 7.17493 7.12312 7.07043 6.98099 - 6.77473 6.56648 6.18379 5.56176 3.90317 2.92406 - 1.59236 1.36499 1.17576 1.15461 1.13293 1.13646 - 11.68595 10.88273 10.36096 9.88378 9.44897 9.05527 - 8.70206 8.38913 8.11660 7.88431 7.69180 7.53818 - 7.42095 7.33798 7.28782 7.26243 7.24734 7.21344 - 7.09282 6.94524 6.64190 6.11304 4.54180 3.46250 - 1.79492 1.48490 1.19757 1.16054 1.13276 1.13405 - 11.66196 10.89390 10.36759 9.88851 9.45417 9.06294 - 8.71370 8.40562 8.13813 7.91082 7.72304 7.57345 - 7.45891 7.37805 7.33384 7.32764 7.35158 7.36477 - 7.28801 7.16779 6.91112 6.44356 4.98943 3.91449 - 1.97933 1.59139 1.22029 1.17336 1.13448 1.13285 - 11.61119 10.88912 10.37206 9.89785 9.46560 9.07504 - 8.72584 8.41794 8.15153 7.92608 7.74062 7.59427 - 7.48594 7.41508 7.38166 7.37978 7.40017 7.42611 - 7.39843 7.31222 7.10344 6.71439 5.36043 4.20468 - 2.15566 1.71740 1.24446 1.17349 1.13998 1.13215 - 11.58871 10.89032 10.37471 9.90139 9.46993 9.08044 - 8.73243 8.42566 8.16009 7.93565 7.75215 7.60901 - 7.50436 7.43715 7.40762 7.41068 7.43820 7.47552 - 7.48102 7.42932 7.25291 6.87223 5.59658 4.54513 - 2.32137 1.80617 1.26819 1.19387 1.13635 1.13167 - 11.56085 10.89145 10.37727 9.90526 9.47512 9.08705 - 8.74064 8.43560 8.17196 7.94962 7.76853 7.62817 - 7.52691 7.46386 7.43990 7.45079 7.49000 7.54604 - 7.58597 7.56607 7.44573 7.13845 5.99073 4.99327 - 2.63099 2.00323 1.31591 1.21444 1.14048 1.13107 - 11.54313 10.89197 10.37881 9.90754 9.47820 9.09106 - 8.74565 8.44171 8.17926 7.95826 7.77864 7.63998 - 7.54077 7.48033 7.45982 7.47552 7.52194 7.58963 - 7.65101 7.65163 7.57073 7.31913 6.27514 5.33330 - 2.90550 2.18413 1.36300 1.23583 1.14528 1.13071 - 11.51603 10.89263 10.38065 9.91054 9.48239 9.09649 - 8.75242 8.44995 8.18911 7.96989 7.79226 7.65591 - 7.55953 7.50269 7.48697 7.50928 7.56542 7.64934 - 7.74068 7.77010 7.74890 7.58995 6.74122 5.92220 - 3.47439 2.58318 1.47749 1.29192 1.15832 1.13023 - 11.50062 10.89289 10.38158 9.91214 9.48458 9.09931 - 8.75588 8.45408 8.19396 7.97557 7.79894 7.66383 - 7.56900 7.51412 7.50091 7.52663 7.58776 7.68048 - 7.78791 7.83218 7.84261 7.73905 7.03131 6.30828 - 3.91993 2.92289 1.58729 1.34978 1.17162 1.12998 - 11.48441 10.89325 10.38260 9.91378 9.48686 9.10217 - 8.75933 8.45812 8.19866 7.98107 7.80545 7.67161 - 7.57837 7.52549 7.51487 7.54405 7.61036 7.71231 - 7.83682 7.89629 7.93805 7.89638 7.38046 6.79399 - 4.58027 3.46694 1.79209 1.46547 1.19768 1.12973 - 11.49643 10.89977 10.38161 9.90978 9.48271 9.09907 - 8.75797 8.45879 8.20122 7.98514 7.81040 7.67625 - 7.58036 7.52266 7.50892 7.54531 7.63314 7.75048 - 7.86854 7.92576 7.97710 7.97222 7.59508 7.08562 - 5.04113 3.89263 1.98273 1.57985 1.22153 1.12961 - 11.49083 10.89972 10.38181 9.91027 9.48340 9.09999 - 8.75909 8.46008 8.20271 7.98686 7.81239 7.67859 - 7.58315 7.52607 7.51316 7.55072 7.64022 7.76004 - 7.88286 7.94531 8.00790 8.02428 7.72387 7.28746 - 5.38940 4.23038 2.16864 1.69076 1.24544 1.12954 - 11.48682 10.89969 10.38192 9.91058 9.48387 9.10057 - 8.75980 8.46095 8.20371 7.98802 7.81373 7.68017 - 7.58503 7.52835 7.51599 7.55432 7.64494 7.76648 - 7.89266 7.95861 8.02852 8.05926 7.81474 7.43259 - 5.66118 4.51143 2.34155 1.80092 1.26886 1.12949 - 11.46185 10.89285 10.38302 9.91523 9.48942 9.10562 - 8.76353 8.46315 8.20479 7.98847 7.81416 7.68169 - 7.59011 7.53951 7.53210 7.56589 7.63914 7.75220 - 7.89981 7.98179 8.06170 8.10259 7.93496 7.62700 - 6.06440 4.95802 2.65185 2.01593 1.31555 1.12943 - 11.45868 10.89222 10.38232 9.91477 9.48928 9.10580 - 8.76408 8.46411 8.20622 7.99018 7.81554 7.68222 - 7.59031 7.54065 7.53497 7.56990 7.64258 7.75479 - 7.90747 7.99700 8.08289 8.11707 7.98483 7.80282 - 6.35786 5.26205 2.92011 2.23129 1.35420 1.12940 - 0.72208 0.75320 0.78493 0.81746 0.85089 0.88533 - 0.92105 0.95845 0.99816 1.04056 1.08609 1.13537 - 1.18931 1.24778 1.30736 1.35926 1.39465 1.41675 - 1.43096 1.43605 1.44397 1.45138 1.44777 1.44616 - 1.44645 1.44650 1.44624 1.44630 1.44615 1.44624 - 1.02073 1.05705 1.09496 1.13490 1.17699 1.22134 - 1.26809 1.31733 1.36911 1.42348 1.48028 1.53921 - 1.59966 1.66066 1.72073 1.77739 1.82629 1.85979 - 1.86847 1.86459 1.86561 1.87248 1.87365 1.87173 - 1.87248 1.87293 1.87281 1.87266 1.87298 1.87271 - 1.28566 1.33183 1.37943 1.42897 1.48048 1.53399 - 1.58947 1.64690 1.70612 1.76700 1.82920 1.89223 - 1.95539 2.01764 2.07752 2.13297 2.18135 2.21998 - 2.24195 2.24106 2.22763 2.21074 2.22710 2.24499 - 2.23889 2.23493 2.23548 2.23644 2.23414 2.23567 - 1.76788 1.82927 1.89109 1.95398 2.01779 2.08234 - 2.14739 2.21270 2.27804 2.34317 2.40799 2.47249 - 2.53715 2.60182 2.66409 2.71930 2.76202 2.78968 - 2.80346 2.80802 2.81339 2.81885 2.82403 2.82439 - 2.82308 2.82286 2.82300 2.82308 2.82303 2.82301 - 2.17547 2.25613 2.33389 2.40935 2.48218 2.55222 - 2.61967 2.68521 2.74996 2.81399 2.87710 2.93899 - 2.99976 3.05899 3.11471 3.16357 3.20217 3.23044 - 3.24845 3.25432 3.26301 3.27313 3.28088 3.28139 - 3.27843 3.27794 3.27831 3.27833 3.27844 3.27836 - 2.53224 2.63056 2.72203 2.80721 2.88560 2.95722 - 3.02287 3.08451 3.14501 3.20477 3.26348 3.32047 - 3.37514 3.42673 3.47421 3.51660 3.55274 3.58152 - 3.60177 3.60967 3.62110 3.63427 3.64536 3.64534 - 3.64158 3.64089 3.64129 3.64152 3.64140 3.64148 - 2.84957 2.96245 3.06472 3.15687 3.23829 3.30915 - 3.37085 3.42652 3.48054 3.53372 3.58579 3.63609 - 3.68395 3.72865 3.76944 3.80597 3.83784 3.86504 - 3.88777 3.89851 3.91275 3.92772 3.94032 3.94053 - 3.93647 3.93570 3.93614 3.93640 3.93624 3.93638 - 3.39196 3.52663 3.64337 3.74266 3.82383 3.88760 - 3.93670 3.97662 4.01476 4.05271 4.09024 4.12665 - 4.16083 4.19193 4.21986 4.24547 4.26988 4.29442 - 4.32089 4.33562 4.35272 4.36825 4.38201 4.38348 - 4.38004 4.37947 4.38003 4.38004 4.38021 4.38021 - 3.84710 3.99178 4.11320 4.21206 4.28782 4.34160 - 4.37703 4.40103 4.42277 4.44441 4.46597 4.48724 - 4.50771 4.52706 4.54536 4.56311 4.58138 4.60264 - 4.63002 4.64629 4.66334 4.67719 4.69111 4.69348 - 4.69225 4.69199 4.69245 4.69247 4.69260 4.69261 - 4.73563 4.87894 4.99030 5.07173 5.12320 5.14683 - 5.14762 5.13449 5.11880 5.10351 5.08954 5.07786 - 5.06960 5.06576 5.06599 5.06845 5.07248 5.08314 - 5.10625 5.12127 5.13266 5.13788 5.14802 5.15218 - 5.15802 5.15879 5.15883 5.15884 5.15883 5.15888 - 5.40070 5.52357 5.61003 5.66378 5.68549 5.67805 - 5.64729 5.60296 5.55702 5.51297 5.47212 5.43596 - 5.40650 5.38512 5.37088 5.35998 5.35024 5.34841 - 5.36179 5.37175 5.37448 5.36957 5.37302 5.37795 - 5.39041 5.39219 5.39173 5.39176 5.39156 5.39168 - 6.34539 6.44807 6.47873 6.45506 6.39563 6.32081 - 6.23820 6.15456 6.07690 6.00389 5.92958 5.85308 - 5.78543 5.73445 5.69727 5.66364 5.62703 5.60148 - 5.59393 5.58786 5.57263 5.55311 5.54304 5.54668 - 5.56635 5.56939 5.56844 5.56800 5.56800 5.56802 - 7.03961 7.07443 7.04456 6.96825 6.86098 6.73959 - 6.61208 6.48674 6.37210 6.26769 6.16847 6.07229 - 5.98582 5.91328 5.85265 5.79692 5.74155 5.69552 - 5.66307 5.64533 5.61897 5.59090 5.57150 5.57268 - 5.59058 5.59342 5.59230 5.59181 5.59180 5.59185 - 7.57287 7.55507 7.47346 7.34864 7.19651 7.03391 - 6.86892 6.70972 6.56497 6.43469 6.31492 6.20263 - 6.10027 6.00903 5.92797 5.85365 5.78360 5.72080 - 5.66630 5.63898 5.60635 5.57597 5.55123 5.54916 - 5.55924 5.56091 5.55993 5.55957 5.55953 5.55961 - 8.00082 7.94468 7.81947 7.65000 7.45547 7.25569 - 7.05853 6.87104 6.70093 6.54849 6.41052 6.28348 - 6.16645 6.05853 5.95972 5.86972 5.78763 5.71084 - 5.63747 5.60240 5.56655 5.53747 5.51008 5.50454 - 5.50382 5.50384 5.50317 5.50301 5.50296 5.50305 - 8.65304 8.54028 8.34174 8.09261 7.82214 7.55853 - 7.30883 7.07659 6.86608 6.67759 6.50826 6.35401 - 6.21002 6.07360 5.94585 5.83023 5.72757 5.62779 - 5.52516 5.47803 5.43789 5.41198 5.38120 5.36998 - 5.35066 5.34784 5.34774 5.34792 5.34784 5.34795 - 9.13470 8.97016 8.70685 8.38914 8.05537 7.74055 - 7.45029 7.18478 6.94421 6.72748 6.53047 6.34911 - 6.18040 6.02304 5.87660 5.74071 5.61430 5.49340 - 5.37578 5.32103 5.27352 5.24355 5.21178 5.19569 - 5.16794 5.16360 5.16335 5.16399 5.16318 5.16376 - 10.06505 9.59466 9.13952 8.71299 8.31337 7.93925 - 7.58949 7.26393 6.96245 6.68431 6.42803 6.19156 - 5.97252 5.76995 5.58500 5.41698 5.26353 5.11310 - 4.95629 4.87967 4.81283 4.76941 4.72117 4.70500 - 4.68316 4.68010 4.67955 4.67956 4.67969 4.67942 - 10.54203 9.95062 9.39105 8.87386 8.39558 7.95390 - 7.54662 7.17232 6.83025 6.51804 6.23260 5.97029 - 5.72624 5.49742 5.28506 5.08862 4.90609 4.72914 - 4.55121 4.46421 4.38214 4.32110 4.25632 4.24185 - 4.23738 4.23735 4.23575 4.23543 4.23519 4.23487 - 11.09273 10.31938 9.60960 8.96476 8.37741 7.84350 - 7.35999 6.92266 6.52813 6.17226 5.84991 5.55510 - 5.28002 5.01919 4.77293 4.54175 4.32300 4.11029 - 3.90010 3.79912 3.70544 3.63674 3.56175 3.54371 - 3.53724 3.53707 3.53526 3.53495 3.53456 3.53406 - 11.40344 10.49482 9.68267 8.95548 8.30265 7.71647 - 7.19184 6.72144 6.29827 5.91654 5.57011 5.25174 - 4.95199 4.66462 4.39064 4.13268 3.89164 3.66377 - 3.44815 3.34597 3.24663 3.17012 3.09440 3.07488 - 3.05743 3.05529 3.05390 3.05371 3.05359 3.05343 - 11.61351 10.61110 9.73009 8.94628 8.24786 7.62449 - 7.06893 6.57202 6.12475 5.72062 5.35358 5.01668 - 4.70110 4.40086 4.11612 3.84791 3.59680 3.35899 - 3.13353 3.02651 2.92290 2.84347 2.76481 2.74445 - 2.72561 2.72322 2.72176 2.72157 2.72146 2.72226 - 11.76047 10.69098 9.76289 8.93996 8.21009 7.56135 - 6.98417 6.46801 6.00276 5.58165 5.19882 4.84778 - 4.52050 4.21132 3.91958 3.64482 3.38674 3.14263 - 2.91113 2.80067 2.69267 2.60891 2.52692 2.50648 - 2.48925 2.48711 2.48545 2.48527 2.48508 2.48646 - 11.95327 10.79371 9.80745 8.93737 8.17065 7.49352 - 6.89230 6.35419 5.86761 5.42576 5.02315 4.65389 - 4.31101 3.98932 3.68720 3.40262 3.13387 2.87936 - 2.63661 2.51958 2.40409 2.31349 2.22487 2.20344 - 2.18742 2.18552 2.18364 2.18345 2.18320 2.18373 - 12.07258 10.85712 9.83917 8.94540 8.16199 7.47297 - 6.86232 6.31540 5.81962 5.36813 4.95565 4.57647 - 4.22391 3.89300 3.58197 3.28867 3.01078 2.74552 - 2.48989 2.36546 2.24292 2.14681 2.05117 2.02755 - 2.00941 2.00730 2.00537 2.00514 2.00491 2.00360 - 12.21627 10.94346 9.90188 8.99208 8.20052 7.50459 - 6.88818 6.33579 5.83430 5.37657 4.95690 4.56902 - 4.20541 3.86078 3.53388 3.22350 2.92687 2.63711 - 2.34856 2.20342 2.05692 1.93922 1.82217 1.79234 - 1.76815 1.76531 1.76301 1.76270 1.76247 1.76109 - 12.25930 10.98474 9.95451 9.05339 8.26866 7.57523 - 6.95932 6.40717 5.90701 5.45139 5.03375 4.64671 - 4.28121 3.93099 3.59520 3.27327 2.96212 2.65224 - 2.33320 2.16670 1.99040 1.84293 1.70148 1.66700 - 1.63917 1.63568 1.63264 1.63230 1.63196 1.63470 - 12.22898 11.01119 10.03944 9.18046 8.41913 7.73619 - 7.12322 6.57193 6.07510 5.62560 5.21587 4.83719 - 4.47861 4.13192 3.79442 3.46250 3.12958 2.78218 - 2.40379 2.19726 1.97342 1.77740 1.57289 1.52638 - 1.50076 1.49813 1.49191 1.49042 1.49136 1.50086 - 12.19819 11.00529 10.07468 9.25362 8.52115 7.86151 - 7.26711 6.73052 6.24523 5.80468 5.40179 5.02827 - 4.67346 4.32899 3.99139 3.65559 3.31212 2.94148 - 2.51859 2.27815 2.00991 1.76936 1.51102 1.45072 - 1.42678 1.42527 1.41627 1.41384 1.41606 1.42847 - 12.15593 10.98838 10.09667 9.30909 8.60278 7.96434 - 7.38709 6.86431 6.39011 5.95843 5.56269 5.19505 - 4.84522 4.50482 4.16976 3.83375 3.48486 3.09823 - 2.64102 2.37303 2.06668 1.78746 1.47944 1.40516 - 1.38078 1.38010 1.36886 1.36569 1.36897 1.38153 - 12.11239 10.96799 10.11157 9.35257 8.66930 8.04969 - 7.48791 6.97777 6.51389 6.09069 5.70203 5.34046 - 4.99611 4.66064 4.32948 3.99532 3.64412 3.24639 - 2.76221 2.47137 2.13246 1.81854 1.46454 1.37650 - 1.34957 1.34936 1.33634 1.33258 1.33668 1.34820 - 12.03429 10.92872 10.13056 9.41718 8.77185 8.18375 - 7.64823 7.15998 6.71445 6.30679 5.93157 5.58201 - 5.24896 4.92429 4.60268 4.27535 3.92495 3.51438 - 2.99131 2.66485 2.27262 1.89867 1.46174 1.34733 - 1.31045 1.31015 1.29451 1.28998 1.29511 1.30367 - 11.97164 10.89668 10.14233 9.46352 8.84747 8.28421 - 7.76985 7.29971 6.86981 6.47583 6.11286 5.77466 - 5.45259 5.13872 4.82735 4.50866 4.16294 3.74736 - 3.19928 2.84694 2.41321 1.98905 1.47820 1.33884 - 1.28740 1.28601 1.26862 1.26367 1.26921 1.27504 - 11.93239 10.88271 10.17617 9.53910 8.96136 8.43438 - 7.95459 7.51771 7.11999 6.75720 6.42437 6.11480 - 5.81880 5.52782 5.23689 4.93748 4.61222 4.22176 - 3.68084 3.29055 2.74547 2.18213 1.54117 1.36884 - 1.26398 1.25096 1.23169 1.23000 1.22711 1.23381 - 11.86898 10.85241 10.18729 9.58569 9.03887 8.53950 - 8.08460 7.67046 7.29385 6.95108 6.63765 6.34742 - 6.07123 5.80075 5.53095 5.25271 4.94691 4.56907 - 4.02385 3.61862 3.03967 2.41580 1.63530 1.40646 - 1.25349 1.23508 1.21281 1.21034 1.20750 1.21161 - 11.75242 10.79361 10.19264 9.64445 9.14255 8.68159 - 8.25956 7.87402 7.52283 7.20359 6.91334 6.64796 - 6.40101 6.16604 5.93746 5.70388 5.43919 5.07977 - 4.51310 4.08745 3.49003 2.82110 1.85462 1.52760 - 1.24555 1.21378 1.19717 1.19302 1.17757 1.18832 - 11.73339 10.80102 10.22673 9.69746 9.20920 8.75887 - 8.34644 7.97196 7.63571 7.33556 7.06804 6.82817 - 6.60793 6.39918 6.19497 5.98121 5.73495 5.41404 - 4.91732 4.52093 3.91145 3.16503 2.01145 1.62576 - 1.26527 1.21579 1.18361 1.18029 1.17271 1.17632 - 11.73496 10.80554 10.23981 9.72040 9.24343 8.80564 - 8.40639 8.04500 7.72111 7.43303 7.17828 6.95318 - 6.75161 6.56631 6.38833 6.19868 5.97061 5.66528 - 5.19070 4.81575 4.23976 3.49441 2.18913 1.71616 - 1.28062 1.22129 1.17865 1.17237 1.16912 1.16907 - 11.73290 10.80969 10.25106 9.73915 9.27006 8.84078 - 8.45054 8.09835 7.78371 7.50508 7.26033 7.04619 - 6.85709 6.68643 6.52615 6.35832 6.15616 5.87682 - 5.42519 5.06259 4.50125 3.75476 2.35918 1.81646 - 1.29869 1.22677 1.17567 1.16818 1.16435 1.16423 - 11.72759 10.81724 10.26836 9.76612 9.30697 8.88837 - 8.50961 8.16975 7.86832 7.60395 7.37466 7.17735 - 7.00644 6.85581 6.71904 6.58089 6.41705 6.18493 - 5.78948 5.45790 4.92419 4.17410 2.65455 2.01577 - 1.34207 1.24083 1.17173 1.16585 1.15557 1.15815 - 11.72408 10.82341 10.28053 9.78452 9.33181 8.92013 - 8.54870 8.21648 7.92293 7.66693 7.44690 7.26028 - 7.10225 6.96749 6.85029 6.73620 6.60164 6.40441 - 6.05166 5.74708 5.24573 4.51416 2.92055 2.19554 - 1.38539 1.26013 1.17162 1.16388 1.15106 1.15441 - 11.71148 10.83265 10.30033 9.81397 9.37066 8.96847 - 8.60657 8.28413 8.00074 7.75584 7.54842 7.37688 - 7.23777 7.12744 7.04214 6.97020 6.89051 6.76048 - 6.48870 6.23311 5.79085 5.12038 3.48676 2.59520 - 1.48799 1.31265 1.17809 1.16206 1.14953 1.14932 - 11.70645 10.84368 10.31130 9.82662 9.38668 8.98942 - 8.63360 8.31814 8.04221 7.80520 7.60593 7.44251 - 7.31104 7.20880 7.13644 7.09120 7.05780 6.98118 - 6.76074 6.54079 6.15969 5.54324 3.89478 2.94431 - 1.59597 1.36826 1.18573 1.16574 1.14654 1.14676 - 11.65680 10.84901 10.32216 9.84247 9.40741 9.01517 - 8.66455 8.35469 8.08494 7.85485 7.66357 7.50961 - 7.38962 7.30173 7.24812 7.22851 7.23211 7.21214 - 7.08017 6.92056 6.61344 6.08207 4.52702 3.48945 - 1.79767 1.48481 1.20670 1.17382 1.14447 1.14416 - 11.61488 10.85178 10.32749 9.85013 9.41743 9.02768 - 8.67980 8.37293 8.10653 7.88017 7.69322 7.54435 - 7.43040 7.35001 7.30619 7.30027 7.32452 7.33827 - 7.26284 7.14395 6.88963 6.42564 4.98049 3.91130 - 1.98486 1.59868 1.22976 1.18316 1.14431 1.14287 - 11.56309 10.84690 10.33226 9.85971 9.42886 9.03978 - 8.69199 8.38516 8.11929 7.89421 7.70962 7.56487 - 7.45807 7.38797 7.35449 7.35176 7.37049 7.39390 - 7.37423 7.30026 7.08819 6.66483 5.32167 4.25385 - 2.15854 1.70824 1.25355 1.19351 1.14452 1.14210 - 11.54154 10.84750 10.33401 9.86266 9.43296 9.04501 - 8.69838 8.39279 8.12833 7.90483 7.72206 7.57944 - 7.47521 7.40831 7.37908 7.38239 7.41014 7.44778 - 7.45416 7.40348 7.22892 6.85128 5.58430 4.53863 - 2.32514 1.81248 1.27735 1.20350 1.14606 1.14159 - 11.51391 10.84824 10.33616 9.86628 9.43806 9.05163 - 8.70657 8.40267 8.14006 7.91864 7.73825 7.59840 - 7.49749 7.43475 7.41101 7.42206 7.46142 7.51760 - 7.55808 7.53901 7.42021 7.11561 5.97598 4.98426 - 2.63323 2.00869 1.32477 1.22389 1.15011 1.14094 - 11.49635 10.84857 10.33740 9.86841 9.44113 9.05563 - 8.71154 8.40871 8.14726 7.92717 7.74826 7.61012 - 7.51128 7.45109 7.43073 7.44653 7.49299 7.56071 - 7.62246 7.62370 7.54413 7.29497 6.25850 5.32230 - 2.90650 2.18887 1.37160 1.24510 1.15486 1.14056 - 11.46966 10.84902 10.33924 9.87136 9.44524 9.06101 - 8.71825 8.41685 8.15697 7.93863 7.76170 7.62591 - 7.52991 7.47331 7.45763 7.47990 7.53597 7.61978 - 7.71116 7.74090 7.72064 7.56363 6.72134 5.90753 - 3.47278 2.58625 1.48547 1.30077 1.16781 1.14004 - 11.45459 10.84959 10.34036 9.87305 9.44743 9.06375 - 8.72162 8.42091 8.16178 7.94425 7.76833 7.63375 - 7.53925 7.48457 7.47140 7.49705 7.55805 7.65057 - 7.75787 7.80230 7.81339 7.71140 7.00941 6.29129 - 3.91632 2.92446 1.59471 1.35822 1.18107 1.13977 - 11.43862 10.85035 10.34178 9.87491 9.44969 9.06649 - 8.72494 8.42489 8.16645 7.94973 7.77479 7.64141 - 7.54847 7.49576 7.48517 7.51427 7.58037 7.68203 - 7.80627 7.86576 7.90781 7.86720 7.35609 6.77404 - 4.57362 3.46602 1.79849 1.47318 1.20705 1.13951 - 11.45108 10.85707 10.34089 9.87093 9.44554 9.06340 - 8.72363 8.42559 8.16900 7.95374 7.77964 7.64600 - 7.55043 7.49294 7.47924 7.51548 7.60298 7.71992 - 7.83770 7.89487 7.94636 7.94220 7.56915 7.06375 - 5.03207 3.88954 1.98828 1.58692 1.23081 1.13938 - 11.44565 10.85712 10.34120 9.87149 9.44627 9.06432 - 8.72472 8.42686 8.17048 7.95543 7.78162 7.64832 - 7.55323 7.49635 7.48348 7.52087 7.61002 7.72939 - 7.85184 7.91416 7.97676 7.99367 7.69687 7.26416 - 5.37838 4.22543 2.17322 1.69728 1.25462 1.13931 - 11.44170 10.85709 10.34140 9.87178 9.44670 9.06489 - 8.72541 8.42769 8.17145 7.95659 7.78298 7.64991 - 7.55513 7.49864 7.48631 7.52447 7.61471 7.73576 - 7.86149 7.92728 7.99717 8.02833 7.78690 7.40810 - 5.64851 4.50483 2.34520 1.80702 1.27792 1.13927 - 11.41671 10.85025 10.34230 9.87636 9.45217 9.06987 - 8.72915 8.42994 8.17254 7.95700 7.78335 7.65141 - 7.56022 7.50981 7.50239 7.53598 7.60884 7.72142 - 7.86852 7.95024 8.03003 8.07125 7.90599 7.60096 - 6.04920 4.94878 2.65393 2.02098 1.32438 1.13922 - 11.41308 10.84782 10.34030 9.87581 9.45327 9.07194 - 8.73147 8.43193 8.17379 7.95739 7.78311 7.65109 - 7.56033 7.51086 7.50485 7.54013 7.61429 7.72559 - 7.87321 7.96090 8.04833 8.09943 7.98087 7.71816 - 6.32221 5.30744 2.93394 2.20546 1.36950 1.13921 - 0.70613 0.73673 0.76794 0.79993 0.83280 0.86669 - 0.90187 0.93878 0.97806 1.02011 1.06538 1.11447 - 1.16821 1.22644 1.28578 1.33754 1.37299 1.39527 - 1.40966 1.41474 1.42239 1.42935 1.42546 1.42378 - 1.42398 1.42402 1.42375 1.42380 1.42367 1.42374 - 1.00085 1.03659 1.07396 1.11335 1.15489 1.19872 - 1.24496 1.29372 1.34507 1.39905 1.45553 1.51423 - 1.57455 1.63554 1.69574 1.75266 1.80193 1.83569 - 1.84427 1.84018 1.84095 1.84758 1.84843 1.84643 - 1.84718 1.84764 1.84750 1.84735 1.84768 1.84742 - 1.26241 1.30807 1.35520 1.40427 1.45532 1.50840 - 1.56347 1.62049 1.67939 1.73998 1.80196 1.86486 - 1.92798 1.99032 2.05043 2.10626 2.15515 2.19431 - 2.21660 2.21569 2.20202 2.18470 2.20042 2.21817 - 2.21231 2.20840 2.20890 2.20984 2.20756 2.20910 - 1.73981 1.80057 1.86187 1.92431 1.98779 2.05210 - 2.11703 2.18235 2.24778 2.31315 2.37830 2.44323 - 2.50840 2.57359 2.63643 2.69219 2.73540 2.76321 - 2.77676 2.78128 2.78671 2.79228 2.79727 2.79752 - 2.79616 2.79593 2.79606 2.79614 2.79609 2.79609 - 2.14463 2.22406 2.30093 2.37588 2.44858 2.51886 - 2.58682 2.65306 2.71852 2.78321 2.84693 2.90941 - 2.97077 3.03064 3.08703 3.13654 3.17572 3.20432 - 3.22229 3.22809 3.23697 3.24746 3.25513 3.25555 - 3.25248 3.25198 3.25235 3.25237 3.25248 3.25241 - 2.49945 2.59614 2.68653 2.77119 2.84964 2.92185 - 2.98851 3.05139 3.11307 3.17387 3.23350 3.29128 - 3.34666 3.39894 3.44707 3.49009 3.52682 3.55608 - 3.57660 3.58461 3.59629 3.60980 3.62107 3.62099 - 3.61708 3.61637 3.61678 3.61701 3.61689 3.61696 - 2.83501 2.92583 3.01365 3.09936 3.18218 3.26129 - 3.33582 3.40487 3.46766 3.52365 3.57296 3.61637 - 3.65645 3.69549 3.73316 3.76895 3.80254 3.83492 - 3.86651 3.88105 3.89374 3.90269 3.91576 3.91899 - 3.91371 3.91255 3.91319 3.91329 3.91367 3.91345 - 3.35611 3.48880 3.60443 3.70343 3.78518 3.85030 - 3.90129 3.94332 3.98337 4.02293 4.06174 4.09914 - 4.13414 4.16599 4.19466 4.22108 4.24651 4.27202 - 4.29919 4.31423 4.33183 4.34793 4.36214 4.36369 - 4.36020 4.35960 4.36017 4.36019 4.36038 4.36034 - 3.81016 3.95337 4.07408 4.17303 4.24961 4.30489 - 4.34226 4.36840 4.39208 4.41536 4.43830 4.46069 - 4.48208 4.50230 4.52144 4.54015 4.55959 4.58204 - 4.61043 4.62715 4.64475 4.65916 4.67370 4.67621 - 4.67507 4.67480 4.67526 4.67528 4.67543 4.67542 - 4.69755 4.84117 4.95320 5.03560 5.08830 5.11336 - 5.11573 5.10422 5.09009 5.07629 5.06372 5.05335 - 5.04631 5.04363 5.04501 5.04874 5.05424 5.06647 - 5.09106 5.10675 5.11874 5.12441 5.13534 5.13979 - 5.14600 5.14682 5.14686 5.14687 5.14685 5.14692 - 5.36261 5.48733 5.57560 5.63097 5.65414 5.64800 - 5.61840 5.57519 5.53047 5.48772 5.44827 5.41355 - 5.38552 5.36554 5.35269 5.34327 5.33519 5.33507 - 5.35011 5.36081 5.36414 5.35965 5.36395 5.36920 - 5.38212 5.38398 5.38355 5.38356 5.38337 5.38350 - 6.30889 6.41489 6.44867 6.42757 6.36990 6.29595 - 6.21367 6.13060 6.05444 5.98357 5.91109 5.83567 - 5.76899 5.71950 5.68421 5.65251 5.61761 5.59372 - 5.58788 5.58248 5.56784 5.54881 5.53952 5.54345 - 5.56352 5.56661 5.56566 5.56521 5.56523 5.56529 - 7.00525 7.04405 7.01786 6.94460 6.83941 6.71902 - 6.59188 6.46706 6.35390 6.25163 6.15435 6.05946 - 5.97418 5.90316 5.84434 5.79051 5.73694 5.69258 - 5.66164 5.64453 5.61877 5.59119 5.57245 5.57386 - 5.59205 5.59492 5.59381 5.59334 5.59332 5.59340 - 7.54071 7.52726 7.44968 7.32820 7.17839 7.01704 - 6.85264 6.69413 6.55092 6.42275 6.30497 6.19414 - 6.09310 6.00337 5.92399 5.85148 5.78323 5.72209 - 5.66900 5.64228 5.61020 5.58028 5.55612 5.55422 - 5.56450 5.56619 5.56523 5.56487 5.56485 5.56491 - 7.97083 7.91932 7.79836 7.63238 7.44038 7.24211 - 7.04585 6.85928 6.69080 6.54049 6.40453 6.27904 - 6.16339 6.05693 5.95969 5.87135 5.79102 5.71590 - 5.64391 5.60939 5.57407 5.54540 5.51850 5.51310 - 5.51252 5.51256 5.51190 5.51175 5.51169 5.51176 - 8.62902 8.51901 8.32349 8.07744 7.81017 7.54978 - 7.30317 7.07366 6.86519 6.67787 6.50866 6.35408 - 6.21117 6.07832 5.95506 5.84118 5.73582 5.63583 - 5.53880 5.49302 5.45193 5.42444 5.39605 5.38402 - 5.36542 5.36255 5.36223 5.36259 5.36207 5.36243 - 9.11229 8.95191 8.69260 8.37853 8.04801 7.73611 - 7.44851 7.18534 6.94691 6.73208 6.53680 6.35701 - 6.18972 6.03363 5.88840 5.75377 5.62881 5.50942 - 5.39316 5.33896 5.29191 5.26222 5.23077 5.21476 - 5.18700 5.18265 5.18242 5.18305 5.18224 5.18275 - 10.04525 9.57998 9.12961 8.70740 8.31169 7.94114 - 7.59462 7.27197 6.97311 6.69731 6.44312 6.20849 - 5.99102 5.78976 5.60586 5.43867 5.28594 5.13638 - 4.98081 4.90491 4.83864 4.79552 4.74757 4.73143 - 4.70942 4.70632 4.70580 4.70582 4.70594 4.70569 - 10.52324 9.93758 9.38327 8.87084 8.39686 7.95906 - 7.55533 7.18425 6.84508 6.53547 6.25234 5.99206 - 5.74970 5.52217 5.31073 5.11487 4.93272 4.75626 - 4.57928 4.49292 4.41146 4.35084 4.28635 4.27186 - 4.26723 4.26717 4.26558 4.26527 4.26502 4.26484 - 11.07860 10.31197 9.60798 8.96811 8.38509 7.85492 - 7.37464 6.94012 6.54801 6.19423 5.87369 5.58045 - 5.30668 5.04691 4.80146 4.57088 4.35258 4.14030 - 3.93068 3.83007 3.73681 3.66848 3.59373 3.57568 - 3.56926 3.56910 3.56730 3.56699 3.56659 3.56631 - 11.39354 10.49326 9.68753 8.96530 8.31626 7.73299 - 7.21056 6.74190 6.32019 5.93974 5.59447 5.27717 - 4.97840 4.69194 4.41881 4.16161 3.92125 3.69389 - 3.47859 3.37655 3.27747 3.20124 3.12567 3.10620 - 3.08889 3.08676 3.08536 3.08517 3.08505 3.08491 - 11.60029 10.61245 9.74081 8.96273 8.26729 7.64504 - 7.08949 6.59235 6.14538 5.74214 5.37640 5.04100 - 4.72679 4.42755 4.14354 3.87589 3.62529 3.38792 - 3.16279 3.05591 2.95246 2.87315 2.79465 2.77433 - 2.75558 2.75322 2.75175 2.75157 2.75144 2.75197 - 11.74448 10.69305 9.77614 8.95935 8.23196 7.58328 - 7.00486 6.48741 6.02185 5.60145 5.22004 4.87077 - 4.54505 4.23692 3.94581 3.67150 3.41383 3.17012 - 2.93896 2.82864 2.72070 2.63697 2.55515 2.53476 - 2.51758 2.51543 2.51378 2.51361 2.51342 2.51434 - 11.93174 10.79061 9.81621 8.95341 8.19047 7.51461 - 6.91308 6.37393 5.88638 5.44388 5.04105 4.67216 - 4.33047 4.01074 3.71077 3.42752 3.15874 2.90391 - 2.66148 2.54475 2.42930 2.33853 2.25001 2.22859 - 2.21257 2.21077 2.20891 2.20858 2.20851 2.20880 - 12.05344 10.85200 9.84282 8.95435 8.17372 7.48579 - 6.87531 6.32847 5.83326 5.38289 4.97189 4.59434 - 4.24324 3.91343 3.60321 3.31041 3.03283 2.76773 - 2.51224 2.38788 2.26539 2.16931 2.07376 2.05016 - 2.03201 2.02990 2.02798 2.02775 2.02753 2.02666 - 12.19887 10.93044 9.89228 8.98592 8.19767 7.50494 - 6.89147 6.34163 5.84216 5.38600 4.96760 4.58087 - 4.21848 3.87518 3.54965 3.24042 2.94455 2.65516 - 2.36658 2.22136 2.07489 1.95728 1.84018 1.81031 - 1.78610 1.78327 1.78097 1.78065 1.78043 1.77944 - 12.24346 10.97087 9.94211 9.04323 8.26110 7.57054 - 6.95748 6.40784 5.90962 5.45546 5.03899 4.65302 - 4.28878 3.94019 3.60626 3.28620 2.97670 2.66780 - 2.34878 2.18204 2.00562 1.85816 1.71652 1.68200 - 1.65414 1.65064 1.64759 1.64726 1.64692 1.64861 - 12.24303 10.99884 10.01333 9.15128 8.39433 7.72019 - 7.11738 6.57432 6.08106 5.63096 5.21811 4.83572 - 4.47544 4.13042 3.79682 3.46896 3.13901 2.79472 - 2.41941 2.21261 1.98460 1.78353 1.58260 1.54044 - 1.51267 1.50899 1.50311 1.50198 1.50248 1.50859 - 12.20384 11.00001 10.06207 9.23813 8.50603 7.84873 - 7.25736 6.72309 6.23825 5.79656 5.39190 5.01710 - 4.66308 4.32218 3.98995 3.65943 3.32022 2.95465 - 2.53669 2.29510 2.01833 1.76771 1.51612 1.46545 - 1.43731 1.43361 1.42534 1.42361 1.42489 1.43294 - 12.14724 10.98153 10.08890 9.30025 8.59292 7.95362 - 7.37570 6.85246 6.37803 5.94638 5.55105 5.18425 - 4.83591 4.49772 4.16557 3.83307 3.48802 3.10485 - 2.64983 2.38219 2.07551 1.79550 1.48686 1.41271 - 1.38900 1.38836 1.37703 1.37392 1.37716 1.38454 - 12.10426 10.96152 10.10380 9.34335 8.65873 8.03797 - 7.47520 6.96429 6.49991 6.07651 5.68803 5.32715 - 4.98417 4.65090 4.32274 3.99230 3.64526 3.25136 - 2.76970 2.47937 2.14024 1.82562 1.47114 1.38328 - 1.35707 1.35690 1.34377 1.34008 1.34414 1.35065 - 12.02525 10.92154 10.12179 9.40676 8.75985 8.17032 - 7.63357 7.14430 6.69799 6.28987 5.91457 5.56548 - 5.23364 4.91106 4.59247 4.26898 3.92302 3.51669 - 2.99666 2.67099 2.27884 1.90448 1.46745 1.35332 - 1.31716 1.31691 1.30115 1.29667 1.30177 1.30610 - 11.96059 10.88790 10.13200 9.45160 8.83400 8.26934 - 7.75371 7.28249 6.85176 6.45722 6.09406 5.75620 - 5.43519 5.12331 4.81485 4.49995 4.15871 3.74757 - 3.20289 2.85160 2.41827 1.99403 1.48347 1.34448 - 1.29376 1.29241 1.27490 1.26999 1.27551 1.27793 - 11.91529 10.86913 10.16177 9.52364 8.94479 8.41671 - 7.93584 7.49797 7.09937 6.73592 6.40270 6.09324 - 5.79809 5.50894 5.22083 4.92526 4.60464 4.21894 - 3.68187 3.29279 2.74807 2.18487 1.54586 1.37456 - 1.27019 1.25713 1.23781 1.23617 1.23325 1.23801 - 11.84655 10.83412 10.16871 9.56666 9.01923 8.51925 - 8.06370 7.64896 7.27181 6.92862 6.61500 6.32493 - 6.04950 5.78060 5.51322 5.23831 4.93666 4.56332 - 4.02226 3.61866 3.04075 2.41770 1.63982 1.41207 - 1.25982 1.24143 1.21912 1.21667 1.21384 1.21685 - 11.71704 10.78022 10.18729 9.63952 9.13243 8.66279 - 8.23090 7.83720 7.48232 7.16380 6.87769 6.61841 - 6.37730 6.14581 5.91700 5.67745 5.40452 5.05492 - 4.52970 4.12443 3.52263 2.82321 1.83200 1.52479 - 1.25742 1.22343 1.20101 1.19826 1.19295 1.19493 - 11.69485 10.77084 10.19894 9.67109 9.18346 8.73322 - 8.32062 7.94599 7.60991 7.31029 7.04359 6.80478 - 6.58572 6.37823 6.17547 5.96352 5.71965 5.40171 - 4.90874 4.51471 3.90810 3.16467 2.01542 1.63115 - 1.27220 1.22297 1.19091 1.18758 1.18003 1.18368 - 11.69362 10.77226 10.20899 9.69121 9.21521 8.77795 - 8.37904 8.01802 7.69480 7.40766 7.15405 6.93018 - 6.72969 6.54521 6.36806 6.17970 5.95381 5.65130 - 5.18018 4.80755 4.23478 3.49289 2.19237 1.72132 - 1.28790 1.22885 1.18627 1.17998 1.17675 1.17688 - 11.68990 10.77422 10.21782 9.70762 9.23989 8.81170 - 8.42235 8.07105 7.75734 7.47971 7.23601 7.02295 - 6.83487 6.66513 6.50574 6.33900 6.13832 5.86113 - 5.41290 5.05280 4.49489 3.75212 2.36194 1.82137 - 1.30612 1.23455 1.18357 1.17608 1.17227 1.17235 - 11.68279 10.77928 10.23250 9.73209 9.27468 8.85768 - 8.48041 8.14192 7.84173 7.57847 7.35020 7.15379 - 6.98372 6.83388 6.69787 6.56053 6.39769 6.16716 - 5.77468 5.44552 4.91532 4.16937 2.65635 2.02025 - 1.34964 1.24885 1.18004 1.17416 1.16392 1.16666 - 11.67848 10.78446 10.24355 9.74945 9.29862 8.88875 - 8.51903 8.18837 7.89613 7.64125 7.42216 7.23630 - 7.07895 6.94483 6.82823 6.71476 6.58099 6.38512 - 6.03506 5.73277 5.23491 4.50766 2.92135 2.19951 - 1.39299 1.26825 1.18019 1.17247 1.15967 1.16318 - 11.66609 10.79342 10.26293 9.77848 9.33712 8.93684 - 8.57673 8.25587 7.97371 7.72970 7.52289 7.35177 - 7.21299 7.10303 7.01819 6.94676 6.86776 6.73883 - 6.46911 6.21545 5.77649 5.11056 3.48535 2.59756 - 1.49536 1.32082 1.18701 1.17099 1.15853 1.15845 - 11.64656 10.79914 10.27480 9.79531 9.35829 8.96211 - 8.60613 8.29006 8.01387 7.77702 7.57832 7.41624 - 7.28813 7.19118 7.12263 7.07222 7.02271 6.94160 - 6.74331 6.53028 6.13491 5.51636 3.92040 2.93239 - 1.59878 1.37961 1.19531 1.17499 1.15489 1.15608 - 11.61267 10.81079 10.28615 9.80845 9.37509 8.98431 - 8.63495 8.32614 8.05723 7.82780 7.63702 7.48342 - 7.36369 7.27603 7.22260 7.20318 7.20702 7.18755 - 7.05681 6.89848 6.59370 6.06606 4.52038 3.48831 - 1.80383 1.49228 1.21579 1.18313 1.15386 1.15369 - 11.57210 10.81417 10.29177 9.81628 9.38516 8.99682 - 8.65014 8.34430 8.07876 7.85310 7.66668 7.51821 - 7.40456 7.32439 7.28072 7.27489 7.29920 7.31313 - 7.23842 7.12043 6.86799 6.40732 4.97144 3.90812 - 1.99014 1.60564 1.23880 1.19253 1.15376 1.15249 - 11.52068 10.80969 10.29724 9.82632 9.39681 9.00889 - 8.66211 8.35622 8.09123 7.86695 7.68304 7.53882 - 7.43241 7.36256 7.32918 7.32645 7.34508 7.36848 - 7.34919 7.27581 7.06518 6.64477 5.31085 4.24886 - 2.16297 1.71477 1.26252 1.20289 1.15400 1.15179 - 11.49945 10.81059 10.29918 9.82933 9.40082 9.01399 - 8.66844 8.36386 8.10026 7.87751 7.69541 7.55334 - 7.44957 7.38301 7.35394 7.35715 7.38453 7.42199 - 7.42872 7.37848 7.20507 6.82999 5.57183 4.53207 - 2.32874 1.81856 1.28623 1.21287 1.15555 1.15132 - 11.47264 10.81143 10.30134 9.83283 9.40575 9.02048 - 8.67655 8.37371 8.11197 7.89127 7.71149 7.57218 - 7.47174 7.40936 7.38580 7.39671 7.43558 7.49142 - 7.53209 7.51326 7.39525 7.09265 5.96093 4.97512 - 2.63543 2.01401 1.33346 1.23318 1.15963 1.15072 - 11.45574 10.81176 10.30247 9.83476 9.40865 9.02438 - 8.68150 8.37978 8.11922 7.89979 7.72145 7.58381 - 7.48539 7.42552 7.40532 7.42099 7.46700 7.53436 - 7.59616 7.59752 7.51849 7.27089 6.24154 5.31110 - 2.90744 2.19350 1.38008 1.25429 1.16439 1.15036 - 11.42985 10.81222 10.30391 9.83740 9.41255 9.02962 - 8.68817 8.38793 8.12895 7.91125 7.73487 7.59948 - 7.50381 7.44739 7.43178 7.45394 7.50973 7.59323 - 7.68440 7.71415 7.69410 7.53800 6.70123 5.89273 - 3.47113 2.58928 1.49344 1.30961 1.17734 1.14988 - 11.41479 10.81269 10.30513 9.83910 9.41472 9.03235 - 8.69151 8.39197 8.13372 7.91686 7.74147 7.60732 - 7.51313 7.45859 7.44541 7.47092 7.53171 7.62390 - 7.73086 7.77523 7.78639 7.68497 6.98739 6.27411 - 3.91269 2.92604 1.60215 1.36668 1.19057 1.14964 - 11.39847 10.81335 10.30665 9.84116 9.41712 9.03515 - 8.69482 8.39588 8.13834 7.92229 7.74791 7.61501 - 7.52238 7.46979 7.45916 7.48807 7.55392 7.65521 - 7.77899 7.83834 7.88033 7.83997 7.33188 6.75387 - 4.56692 3.46507 1.80491 1.48093 1.21649 1.14939 - 11.41105 10.81957 10.30526 9.83697 9.41306 9.03227 - 8.69366 8.39663 8.14090 7.92634 7.75280 7.61957 - 7.52429 7.46692 7.45322 7.48929 7.57644 7.69296 - 7.81033 7.86729 7.91862 7.91455 7.54380 7.04173 - 5.02296 3.88645 1.99387 1.59407 1.24019 1.14928 - 11.40540 10.81933 10.30537 9.83742 9.41375 9.03317 - 8.69477 8.39794 8.14242 7.92808 7.75480 7.62188 - 7.52704 7.47029 7.45741 7.49464 7.58347 7.70240 - 7.82440 7.88650 7.94891 7.96583 7.67067 7.24083 - 5.36736 4.22048 2.17779 1.70387 1.26390 1.14921 - 11.40131 10.81919 10.30547 9.83764 9.41416 9.03374 - 8.69547 8.39880 8.14341 7.92924 7.75613 7.62346 - 7.52891 7.47255 7.46021 7.49820 7.58812 7.70876 - 7.83402 7.89956 7.96922 8.00033 7.76020 7.38386 - 5.63581 4.49824 2.34888 1.81320 1.28711 1.14917 - 11.37649 10.81245 10.30657 9.84233 9.41966 9.03866 - 8.69906 8.40084 8.14431 7.92954 7.75644 7.62488 - 7.53389 7.48361 7.47622 7.50971 7.58235 7.69449 - 7.84101 7.92242 8.00190 8.04300 7.87864 7.57534 - 6.03397 4.93953 2.65600 2.02606 1.33340 1.14912 - 11.37391 10.81053 10.30458 9.84166 9.42056 9.04057 - 8.70131 8.40285 8.14562 7.92993 7.75622 7.62459 - 7.53405 7.48468 7.47862 7.51377 7.58769 7.69864 - 7.84571 7.93305 8.02015 8.07112 7.95313 7.69198 - 6.30523 5.29621 2.93473 2.20961 1.37827 1.14911 - 0.69500 0.72251 0.75168 0.78259 0.81503 0.84877 - 0.88387 0.92057 0.95921 1.00034 1.04483 1.09358 - 1.14721 1.20537 1.26490 1.31761 1.35418 1.37342 - 1.38523 1.39499 1.40358 1.40662 1.40337 1.40224 - 1.40209 1.40205 1.40187 1.40183 1.40181 1.40183 - 0.96626 1.00693 1.04846 1.09113 1.13497 1.17998 - 1.22627 1.27400 1.32344 1.37488 1.42866 1.48546 - 1.54650 1.61197 1.67847 1.73744 1.77936 1.80320 - 1.81408 1.81821 1.82195 1.82385 1.82254 1.82218 - 1.82305 1.82320 1.82308 1.82301 1.82308 1.82298 - 1.22343 1.27454 1.32615 1.37861 1.43183 1.48575 - 1.54039 1.59585 1.65242 1.71029 1.76971 1.83127 - 1.89622 1.96478 2.03349 2.09403 2.13735 2.16246 - 2.17362 2.17703 2.18006 2.18205 2.18282 2.18300 - 2.18345 2.18351 2.18347 2.18345 2.18347 2.18340 - 1.69217 1.76120 1.82901 1.89599 1.96194 2.02677 - 2.09062 2.15405 2.21790 2.28236 2.34738 2.41295 - 2.47947 2.54651 2.61112 2.66728 2.70895 2.73679 - 2.75182 2.75494 2.76004 2.76662 2.77089 2.77126 - 2.76985 2.76959 2.76978 2.76980 2.76983 2.76977 - 2.10570 2.18907 2.26888 2.34566 2.41910 2.48910 - 2.55607 2.62117 2.68608 2.75100 2.81571 2.87969 - 2.94261 3.00363 3.06070 3.11051 3.14976 3.17842 - 3.19668 3.20266 3.21154 3.22185 3.22947 3.22987 - 3.22676 3.22625 3.22663 3.22665 3.22675 3.22668 - 2.47422 2.56795 2.65594 2.73878 2.81605 2.88774 - 2.95450 3.01792 3.08041 3.14221 3.20299 3.26200 - 3.31857 3.37185 3.42075 3.46433 3.50144 3.53099 - 3.55181 3.55997 3.57180 3.58539 3.59658 3.59642 - 3.59246 3.59174 3.59215 3.59238 3.59226 3.59233 - 2.80375 2.90527 2.99884 3.08519 3.16383 3.23479 - 3.29892 3.35832 3.41596 3.47225 3.52691 3.57927 - 3.62881 3.67494 3.71696 3.75463 3.78773 3.81615 - 3.84001 3.85128 3.86609 3.88152 3.89439 3.89452 - 3.89023 3.88942 3.88988 3.89015 3.88999 3.89012 - 3.36733 3.47857 3.57767 3.66560 3.74185 3.80665 - 3.86130 3.90878 3.95322 3.99541 4.03525 4.07251 - 4.10719 4.13941 4.16909 4.19681 4.22342 4.24986 - 4.27760 4.29282 4.31074 4.32734 4.34183 4.34289 - 4.33963 4.33894 4.33941 4.33966 4.33949 4.33967 - 3.82676 3.95589 4.05768 4.13686 4.19891 4.25056 - 4.29379 4.33046 4.36322 4.39244 4.41821 4.44059 - 4.46001 4.47740 4.49400 4.51292 4.53675 4.56343 - 4.59153 4.60741 4.62551 4.64145 4.65558 4.65795 - 4.65684 4.65662 4.65703 4.65714 4.65715 4.65722 - 4.71210 4.84809 4.94154 5.00049 5.03434 5.05415 - 5.06363 5.06630 5.06635 5.06276 5.05250 5.03612 - 5.02206 5.01745 5.02118 5.02788 5.03434 5.04953 - 5.07780 5.09169 5.10355 5.11143 5.12233 5.12648 - 5.13286 5.13376 5.13381 5.13376 5.13378 5.13383 - 5.35490 5.48802 5.56547 5.59895 5.60183 5.58939 - 5.56678 5.53862 5.50998 5.47932 5.44202 5.39875 - 5.36167 5.34039 5.33221 5.32698 5.31818 5.32040 - 5.34093 5.34945 5.35228 5.35016 5.35479 5.35970 - 5.37287 5.37483 5.37446 5.37423 5.37426 5.37432 - 6.28140 6.35272 6.38447 6.38334 6.35115 6.29181 - 6.21201 6.12206 6.03391 5.95154 5.87628 5.80943 - 5.75323 5.70838 5.67320 5.64179 5.61033 5.58661 - 5.57869 5.57695 5.56435 5.54417 5.53531 5.53990 - 5.56016 5.56324 5.56208 5.56212 5.56166 5.56189 - 6.93334 6.96711 6.95570 6.90847 6.82852 6.72129 - 6.59531 6.46299 6.33821 6.22511 6.12444 6.03601 - 5.95999 5.89518 5.83957 5.78733 5.73461 5.68878 - 5.65744 5.64373 5.61964 5.59090 5.57277 5.57480 - 5.59320 5.59609 5.59478 5.59479 5.59430 5.59454 - 7.44976 7.44311 7.38850 7.29761 7.17452 7.02582 - 6.86116 6.69404 6.53954 6.40153 6.28012 6.17377 - 6.08073 5.99841 5.92480 5.85480 5.78497 5.72103 - 5.66931 5.64574 5.61490 5.58374 5.56046 5.55908 - 5.56955 5.57128 5.57016 5.57014 5.56978 5.56998 - 8.05018 7.87808 7.69937 7.52472 7.35401 7.18743 - 7.02512 6.86721 6.71422 6.56703 6.42645 6.29260 - 6.16689 6.05049 5.94453 5.85073 5.77017 5.70036 - 5.64128 5.61908 5.60383 5.59039 5.52969 5.50108 - 5.51714 5.52395 5.52104 5.51902 5.52236 5.52034 - 8.53834 8.47977 8.30842 8.06744 7.79790 7.53864 - 7.29652 7.07218 6.86684 6.68059 6.51151 6.35691 - 6.21428 6.08225 5.96043 5.84869 5.74587 5.64757 - 5.55057 5.50480 5.46467 5.43866 5.41035 5.39815 - 5.37970 5.37694 5.37663 5.37694 5.37650 5.37686 - 9.05869 8.92593 8.68071 8.37121 8.04159 7.73206 - 7.44815 7.18870 6.95261 6.73886 6.54411 6.36491 - 6.19844 6.04351 5.89968 5.76651 5.64288 5.52480 - 5.40988 5.35630 5.30982 5.28055 5.24960 5.23371 - 5.20595 5.20159 5.20134 5.20197 5.20117 5.20174 - 9.92267 9.62181 9.22078 8.77405 8.32893 7.92552 - 7.56611 7.24645 6.96159 6.70429 6.46423 6.23505 - 6.01879 5.81790 5.63283 5.46124 5.30123 5.14939 - 5.00234 4.93183 4.86757 4.82235 4.77328 4.75784 - 4.73583 4.73270 4.73220 4.73231 4.73222 4.73206 - 10.55289 9.95866 9.39788 8.88078 8.40377 7.96441 - 7.56046 7.19035 6.85315 6.54635 6.26666 6.01009 - 5.77115 5.54635 5.33688 5.14221 4.96056 4.78422 - 4.60736 4.52128 4.44057 4.38091 4.31656 4.30172 - 4.29733 4.29735 4.29573 4.29543 4.29514 4.29491 - 11.04392 10.35970 9.66531 8.99525 8.37643 7.83104 - 7.35537 6.93963 6.57378 6.24350 5.92974 5.62395 - 5.33510 5.06940 4.82393 4.59153 4.36660 4.15663 - 3.96445 3.87035 3.77460 3.69765 3.62444 3.60834 - 3.60151 3.60083 3.59921 3.59887 3.59875 3.59817 - 11.38130 10.53315 9.73084 8.98723 8.31551 7.72538 - 7.20907 6.75296 6.34378 5.97207 5.62813 5.30522 - 5.00127 4.71486 4.44535 4.19157 3.95193 3.72492 - 3.51035 3.40787 3.30867 3.23271 3.15679 3.13738 - 3.12003 3.11774 3.11641 3.11625 3.11612 3.11597 - 11.61814 10.62074 9.74503 8.96717 8.27494 7.65770 - 7.10770 6.61534 6.17115 5.76886 5.40283 5.06659 - 4.75194 4.45322 4.17042 3.90412 3.65457 3.41793 - 3.19317 3.08628 2.98259 2.90296 2.82431 2.80399 - 2.78515 2.78277 2.78131 2.78113 2.78100 2.78169 - 11.75788 10.69558 9.77472 8.95958 8.23754 7.59621 - 7.02541 6.51398 6.05125 5.63084 5.24755 4.89573 - 4.56842 4.26054 3.97100 3.69848 3.44198 3.19892 - 2.96798 2.85756 2.74931 2.66521 2.58317 2.56277 - 2.54553 2.54337 2.54172 2.54154 2.54136 2.54254 - 11.93202 10.78676 9.81248 8.95321 8.19597 7.52679 - 6.93178 6.39771 5.91270 5.47052 5.06648 4.69572 - 4.35251 4.03235 3.73290 3.45082 3.18352 2.92990 - 2.68790 2.57103 2.45518 2.36391 2.27501 2.25352 - 2.23741 2.23559 2.23373 2.23340 2.23332 2.23370 - 12.04251 10.84454 9.83927 8.95557 8.18000 7.49699 - 6.89079 6.34701 5.85321 5.40288 4.99109 4.61262 - 4.26127 3.93235 3.62367 3.33233 3.05556 2.79094 - 2.53584 2.41158 2.28897 2.19253 2.09632 2.07252 - 2.05420 2.05207 2.05013 2.04989 2.04966 2.04853 - 12.16522 10.91630 9.88947 8.98927 8.20338 7.51063 - 6.89604 6.34525 5.84609 5.39144 4.97538 4.59133 - 4.23138 3.88990 3.56561 3.25718 2.96185 2.67306 - 2.38539 2.24062 2.09434 1.97652 1.85863 1.82845 - 1.80402 1.80116 1.79883 1.79851 1.79828 1.79708 - 12.19968 10.94758 9.93090 9.03880 8.25961 7.56959 - 6.95588 6.40570 5.90812 5.45572 5.04177 4.65865 - 4.29702 3.95039 3.61785 3.29880 2.99008 2.68212 - 2.36438 2.19827 2.02224 1.87475 1.73258 1.69790 - 1.66987 1.66634 1.66328 1.66295 1.66261 1.66491 - 12.19317 10.96039 9.98306 9.12788 8.37667 7.70741 - 7.10862 6.56876 6.07788 5.62949 5.21785 4.83646 - 4.47723 4.13345 3.80135 3.47513 3.14692 2.80441 - 2.43083 2.22482 1.99748 1.79685 1.59642 1.55442 - 1.52639 1.52263 1.51673 1.51559 1.51613 1.52431 - 12.12259 10.94772 10.02798 9.21531 8.48949 7.83515 - 7.24498 6.71177 6.22924 5.79099 5.39021 5.01884 - 4.66662 4.32540 3.99171 3.66046 3.32198 2.95617 - 2.53726 2.29823 2.03077 1.79039 1.53257 1.47267 - 1.44901 1.44743 1.43832 1.43595 1.43821 1.44847 - 12.07667 10.92739 10.04625 9.26678 8.56684 7.93347 - 7.36023 6.84062 6.36893 5.93931 5.54545 5.17977 - 4.83240 4.49527 4.16429 3.83313 3.48968 3.10852 - 2.65601 2.38981 2.08459 1.80583 1.49887 1.42524 - 1.40141 1.40067 1.38930 1.38620 1.38955 1.39980 - 12.03216 10.90565 10.05900 9.30754 8.63025 8.01544 - 7.45741 6.95025 6.48876 6.06751 5.68063 5.32096 - 4.97904 4.64685 4.31982 3.99066 3.64517 3.25329 - 2.77432 2.48558 2.14815 1.83499 1.48251 1.39532 - 1.36923 1.36899 1.35581 1.35213 1.35634 1.36559 - 11.95473 10.86575 10.07570 9.36870 8.72847 8.14453 - 7.61236 7.12684 6.68354 6.27780 5.90437 5.55677 - 5.22618 4.90478 4.58733 4.26505 3.92050 3.51617 - 2.99903 2.67517 2.28502 1.91246 1.47786 1.36459 - 1.32904 1.32881 1.31300 1.30853 1.31383 1.32043 - 11.89349 10.83392 10.08631 9.41284 8.80114 8.24153 - 7.73020 7.26261 6.83491 6.44287 6.08179 5.74563 - 5.42608 5.11548 4.80819 4.49446 4.15455 3.74534 - 3.20362 2.85427 2.42318 2.00101 1.49320 1.35519 - 1.30547 1.30423 1.28668 1.28178 1.28753 1.29175 - 11.85734 10.82054 10.11827 9.48468 8.91004 8.38586 - 7.90864 7.47415 7.07867 6.71806 6.38740 6.08012 - 5.78670 5.49873 5.21139 4.91633 4.59650 4.21297 - 3.68034 3.29388 2.75111 2.18934 1.55424 1.38473 - 1.28167 1.26865 1.24944 1.24797 1.24502 1.25095 - 11.79357 10.78913 10.12724 9.52857 8.98438 8.48753 - 8.03503 7.62322 7.24889 6.90839 6.59725 6.30941 - 6.03579 5.76818 5.50169 5.22743 4.92661 4.55539 - 4.01865 3.61774 3.04216 2.42111 1.64754 1.42158 - 1.27106 1.25283 1.23064 1.22833 1.22545 1.22924 - 11.67171 10.72543 10.12774 9.58252 9.08336 8.62504 - 8.20551 7.82239 7.47357 7.15668 6.86877 6.60578 - 6.36136 6.12912 5.90363 5.67362 5.41324 5.05930 - 4.49995 4.07910 3.48764 2.82478 1.86629 1.54165 - 1.26259 1.23151 1.21555 1.21139 1.19571 1.20664 - 11.65547 10.72076 10.14226 9.61477 9.13290 8.69196 - 8.29011 7.92516 7.59513 7.29784 7.03049 6.78906 - 6.56705 6.35820 6.15776 5.95553 5.72700 5.40987 - 4.88656 4.47440 3.86876 3.15385 2.04455 1.64862 - 1.28144 1.23300 1.20236 1.19781 1.18503 1.19499 - 11.64754 10.72759 10.16358 9.64709 9.17396 8.74061 - 8.34599 7.98892 7.66851 7.38308 7.13031 6.90683 - 6.70692 6.52366 6.34827 6.16187 5.93791 5.63766 - 5.16972 4.79944 4.23009 3.49206 2.19735 1.72871 - 1.29815 1.23953 1.19720 1.19094 1.18769 1.18794 - 11.63795 10.72766 10.17284 9.66487 9.19987 8.77467 - 8.38836 8.03984 7.72838 7.45245 7.21004 6.99804 - 6.81106 6.64271 6.48495 6.31996 6.12109 5.84606 - 5.40094 5.04318 4.48870 3.75003 2.36622 1.82813 - 1.31612 1.24506 1.19437 1.18688 1.18305 1.18323 - 11.62415 10.73042 10.18773 9.69062 9.23579 8.82084 - 8.44526 8.10830 7.80965 7.54801 7.32140 7.12667 - 6.95822 6.80993 6.67541 6.53957 6.37839 6.14993 - 5.76047 5.43357 4.90668 4.16485 2.65909 2.02608 - 1.35917 1.25897 1.19062 1.18475 1.17451 1.17733 - 11.61843 10.73511 10.19897 9.70832 9.25997 8.85181 - 8.48330 8.15371 7.86271 7.60932 7.39187 7.20778 - 7.05214 6.91958 6.80443 6.69239 6.56014 6.36622 - 6.01910 5.71903 5.22439 4.50113 2.92245 2.20430 - 1.40216 1.27809 1.19060 1.18293 1.17011 1.17373 - 11.60835 10.74528 10.21883 9.73733 9.29806 8.89924 - 8.54020 8.22029 7.93928 7.69666 7.49137 7.32182 - 7.18449 7.07572 6.99188 6.92155 6.84398 6.71693 - 6.44997 6.19844 5.76271 5.10046 3.48271 2.60013 - 1.50379 1.33014 1.19719 1.18118 1.16879 1.16889 - 11.60700 10.75792 10.23029 9.74988 9.31377 8.91992 - 8.56710 8.25428 7.98064 7.74559 7.54798 7.38600 - 7.25582 7.15477 7.08362 7.03971 7.00798 6.93402 - 6.71834 6.50218 6.12664 5.51778 3.88682 2.94620 - 1.61077 1.38506 1.20476 1.18500 1.16590 1.16647 - 11.56046 10.76427 10.24183 9.76610 9.33455 8.94546 - 8.59763 8.29020 8.02255 7.79424 7.60443 7.45174 - 7.33281 7.24587 7.19314 7.17442 7.17912 7.16099 - 7.03267 6.87626 6.57433 6.05046 4.51367 3.48706 - 1.81044 1.50031 1.22557 1.19315 1.16393 1.16400 - 11.51991 10.76715 10.24695 9.77350 9.34423 8.95757 - 8.61242 8.30797 8.04365 7.81907 7.63360 7.48595 - 7.37303 7.29348 7.25037 7.24508 7.26999 7.28490 - 7.21217 7.09601 6.84666 6.39029 4.96353 3.90558 - 1.99577 1.61303 1.24842 1.20249 1.16378 1.16275 - 11.46995 10.76018 10.24951 9.78218 9.35640 8.97120 - 8.62611 8.32111 8.05649 7.83230 7.64853 7.50476 - 7.39927 7.33079 7.29892 7.29699 7.31527 7.33879 - 7.32168 7.25006 7.04201 6.62526 5.30017 4.24856 - 2.17029 1.71844 1.27005 1.21471 1.16455 1.16200 - 11.44733 10.76268 10.25336 9.78556 9.35903 8.97409 - 8.63027 8.32722 8.06485 7.84307 7.66179 7.52046 - 7.41731 7.35122 7.32250 7.32602 7.35381 7.39198 - 7.40037 7.35164 7.18046 6.80962 5.56248 4.52608 - 2.33249 1.82499 1.29557 1.22269 1.16550 1.16150 - 11.42032 10.76272 10.25501 9.78882 9.36393 8.98048 - 8.63814 8.33666 8.07615 7.85652 7.67764 7.53903 - 7.43912 7.37713 7.35383 7.36494 7.40404 7.46033 - 7.50220 7.48465 7.36883 7.06984 5.94731 4.96635 - 2.63775 2.01959 1.34251 1.24285 1.16950 1.16086 - 11.40317 10.76276 10.25584 9.79066 9.36677 8.98433 - 8.64294 8.34250 8.08316 7.86486 7.68744 7.55046 - 7.45253 7.39300 7.37301 7.38880 7.43496 7.50256 - 7.56519 7.56765 7.49080 7.24616 6.22393 5.29994 - 2.90850 2.19829 1.38887 1.26379 1.17420 1.16048 - 11.37726 10.76302 10.25728 9.79329 9.37066 8.98949 - 8.64941 8.35041 8.09265 7.87611 7.70065 7.56589 - 7.47062 7.41449 7.39904 7.42124 7.47699 7.56045 - 7.65189 7.68235 7.66415 7.51026 6.67860 5.87771 - 3.46971 2.59241 1.50160 1.31870 1.18708 1.15998 - 11.36283 10.76369 10.25850 9.79496 9.37280 8.99217 - 8.65275 8.35441 8.09735 7.88160 7.70708 7.57353 - 7.47975 7.42546 7.41242 7.43791 7.49858 7.59061 - 7.69763 7.74242 7.75486 7.65577 6.96488 6.25725 - 3.90917 2.92768 1.60976 1.37535 1.20030 1.15974 - 11.34754 10.76455 10.26012 9.79695 9.37516 8.99502 - 8.65617 8.35844 8.10201 7.88694 7.71335 7.58101 - 7.48878 7.43646 7.42593 7.45477 7.52039 7.62140 - 7.74508 7.80449 7.84695 7.80909 7.31039 6.73481 - 4.56012 3.46416 1.81149 1.48885 1.22618 1.15951 - 11.35964 10.77118 10.25923 9.79308 9.37109 8.99202 - 8.65492 8.35924 8.10462 7.89100 7.71821 7.58554 - 7.49066 7.43355 7.41991 7.45587 7.54269 7.65875 - 7.77578 7.83281 7.88481 7.88250 7.51812 7.02073 - 5.01401 3.88334 1.99958 1.60138 1.24981 1.15940 - 11.35417 10.77103 10.25943 9.79356 9.37180 8.99293 - 8.65604 8.36056 8.10615 7.89275 7.72022 7.58787 - 7.49340 7.43685 7.42397 7.46102 7.54947 7.66807 - 7.78998 7.85204 7.91423 7.93136 7.64102 7.21613 - 5.35641 4.21564 2.18250 1.71064 1.27342 1.15934 - 11.35013 10.77090 10.25943 9.79379 9.37220 8.99348 - 8.65674 8.36140 8.10714 7.89392 7.72157 7.58944 - 7.49527 7.43908 7.42671 7.46444 7.55397 7.67433 - 7.79966 7.86511 7.93398 7.96420 7.72754 7.35630 - 5.62338 4.49195 2.35261 1.81950 1.29648 1.15929 - 11.32569 10.76436 10.26074 9.79852 9.37771 8.99842 - 8.66033 8.36344 8.10800 7.89412 7.72174 7.59073 - 7.50015 7.45006 7.44263 7.47594 7.54825 7.65992 - 7.80586 7.88716 7.96697 8.00759 7.84318 7.54778 - 6.01935 4.93039 2.65809 2.03123 1.34249 1.15923 - 11.32275 10.76473 10.26114 9.79871 9.37766 8.99833 - 8.66037 8.36366 8.10843 7.89472 7.72256 7.59180 - 7.50153 7.45180 7.44479 7.47853 7.55145 7.66480 - 7.81344 7.89656 7.98259 8.03741 7.92358 7.67269 - 6.30192 5.27008 2.92663 2.22261 1.38669 1.15918 - 0.68036 0.70734 0.73597 0.76631 0.79819 0.83141 - 0.86605 0.90234 0.94063 0.98143 1.02559 1.07397 - 1.12725 1.18512 1.24444 1.29703 1.33360 1.35296 - 1.36480 1.37438 1.38272 1.38562 1.38243 1.38132 - 1.38119 1.38116 1.38097 1.38094 1.38092 1.38095 - 0.94720 0.98794 1.02918 1.07118 1.11405 1.15794 - 1.20316 1.25032 1.30020 1.35309 1.40897 1.46765 - 1.52866 1.59094 1.65249 1.70931 1.75596 1.78706 - 1.79614 1.79328 1.79437 1.80005 1.80007 1.79821 - 1.79909 1.79954 1.79939 1.79924 1.79954 1.79928 - 1.20209 1.25238 1.30321 1.35490 1.40744 1.46078 - 1.51500 1.57032 1.62707 1.68548 1.74572 1.80820 - 1.87382 1.94245 2.01058 2.07013 2.11271 2.13903 - 2.15058 2.15122 2.15379 2.15796 2.15775 2.15778 - 2.15844 2.15849 2.15841 2.15845 2.15839 2.15833 - 1.66582 1.73418 1.80142 1.86796 1.93359 1.99823 - 2.06200 2.12544 2.18941 2.25405 2.31931 2.38518 - 2.45203 2.51939 2.58431 2.64076 2.68270 2.71074 - 2.72592 2.72912 2.73439 2.74116 2.74534 2.74567 - 2.74425 2.74399 2.74417 2.74419 2.74422 2.74415 - 2.07635 2.15908 2.23839 2.31479 2.38798 2.45792 - 2.52498 2.59033 2.65565 2.72110 2.78632 2.85063 - 2.91332 2.97343 3.02940 3.07925 3.12077 3.15275 - 3.17331 3.17925 3.18630 3.19446 3.20452 3.20559 - 3.20209 3.20129 3.20166 3.20190 3.20157 3.20177 - 2.44280 2.53577 2.62330 2.70595 2.78331 2.85532 - 2.92250 2.98637 3.04909 3.11091 3.17152 3.23032 - 3.28686 3.34050 3.39017 3.43478 3.47310 3.50410 - 3.52668 3.53566 3.54796 3.56155 3.57291 3.57286 - 3.56878 3.56803 3.56845 3.56868 3.56854 3.56864 - 2.77084 2.87163 2.96483 3.05113 3.13002 3.20148 - 3.26625 3.32625 3.38423 3.44059 3.49508 3.54718 - 3.59669 3.64325 3.68618 3.72509 3.75964 3.78983 - 3.81583 3.82813 3.84348 3.85888 3.87203 3.87233 - 3.86793 3.86707 3.86754 3.86782 3.86763 3.86779 - 3.33240 3.44314 3.54209 3.63021 3.70697 3.77253 - 3.82809 3.87646 3.92157 3.96418 4.00424 4.04165 - 4.07666 4.10959 4.14033 4.16939 4.19748 4.22572 - 4.25564 4.27192 4.29044 4.30708 4.32198 4.32328 - 4.31996 4.31922 4.31972 4.31999 4.31978 4.31999 - 3.79066 3.91943 4.02134 4.10105 4.16387 4.21642 - 4.26066 4.29851 4.33256 4.36297 4.38928 4.41160 - 4.43152 4.45075 4.46988 4.49018 4.51330 4.54101 - 4.57268 4.58866 4.60684 4.62329 4.63803 4.64052 - 4.63947 4.63925 4.63969 4.63979 4.63980 4.63989 - 4.67540 4.81113 4.90499 4.96491 5.00007 5.02138 - 5.03235 5.03619 5.03694 5.03447 5.02748 5.01651 - 5.00635 5.00148 5.00253 5.00901 5.02046 5.03729 - 5.06144 5.07664 5.08977 5.09773 5.10908 5.11349 - 5.12014 5.12108 5.12113 5.12106 5.12109 5.12116 - 5.33324 5.43714 5.51046 5.55706 5.57752 5.57414 - 5.55149 5.51729 5.48109 5.44559 5.41186 5.38094 - 5.35428 5.33332 5.31876 5.31079 5.30959 5.31552 - 5.32856 5.33658 5.34132 5.34134 5.34458 5.35033 - 5.36342 5.36562 5.36533 5.36490 5.36531 5.36511 - 6.24508 6.31871 6.35248 6.35302 6.32225 6.26421 - 6.18580 6.09769 6.01213 5.93304 5.86145 5.79817 - 5.74449 5.70067 5.66568 5.63543 5.60701 5.58495 - 5.57379 5.56967 5.55781 5.54082 5.53118 5.53552 - 5.55622 5.55936 5.55818 5.55823 5.55773 5.55794 - 6.89945 6.93529 6.92602 6.88085 6.80290 6.69767 - 6.57369 6.44349 6.32106 6.21048 6.11240 6.02639 - 5.95235 5.88888 5.83438 5.78396 5.73413 5.68989 - 5.65650 5.64126 5.61802 5.59192 5.57316 5.57494 - 5.59362 5.59655 5.59520 5.59525 5.59470 5.59493 - 7.41827 7.41358 7.36126 7.27277 7.15219 7.00602 - 6.84382 6.67900 6.52659 6.39043 6.27065 6.16578 - 6.07420 5.99338 5.92142 5.85343 5.78588 5.72351 - 5.67166 5.64782 5.61786 5.58830 5.56478 5.56327 - 5.57388 5.57564 5.57450 5.57450 5.57412 5.57432 - 8.02074 7.85129 7.67523 7.50311 7.33483 7.17058 - 7.01050 6.85470 6.70375 6.55848 6.41970 6.28755 - 6.16342 6.04848 5.94388 5.85133 5.77196 5.70343 - 5.64591 5.62465 5.61048 5.59797 5.53783 5.50909 - 5.52503 5.53186 5.52897 5.52695 5.53030 5.52830 - 8.68912 8.45039 8.20680 7.97060 7.74149 7.51963 - 7.30521 7.09824 6.89940 6.71003 6.53050 6.36120 - 6.20341 6.05922 5.92959 5.81641 5.72043 5.63702 - 5.56382 5.53430 5.51148 5.49148 5.42134 5.38740 - 5.39057 5.39473 5.39132 5.38969 5.39220 5.39099 - 9.03481 8.90703 8.66608 8.36015 8.03372 7.72728 - 7.44626 7.18925 6.95487 6.74211 6.54782 6.36876 - 6.20266 6.04857 5.90584 5.77338 5.65010 5.53448 - 5.42501 5.37366 5.32806 5.29833 5.26775 5.25240 - 5.22481 5.22037 5.22014 5.22080 5.21994 5.22062 - 9.90474 9.61088 9.21516 8.77229 8.33020 7.92952 - 7.57266 7.25535 6.97261 6.71710 6.47827 6.24988 - 6.03465 5.83535 5.65184 5.48051 5.31949 5.16989 - 5.02758 4.95662 4.89196 4.84728 4.79924 4.78403 - 4.76207 4.75893 4.75847 4.75859 4.75848 4.75833 - 10.54177 9.95260 9.39640 8.88333 8.40989 7.97372 - 7.57259 7.20501 6.87008 6.56532 6.28751 6.03269 - 5.79547 5.57231 5.36441 5.17116 4.99059 4.81445 - 4.63648 4.54959 4.46873 4.40972 4.34621 4.33152 - 4.32721 4.32723 4.32566 4.32535 4.32508 4.32470 - 11.03559 10.36025 9.67163 9.00506 8.38868 7.84563 - 7.37218 6.95832 6.59388 6.26505 5.95371 5.65110 - 5.36441 5.09889 4.85292 4.62190 4.40081 4.19090 - 3.99469 3.90111 3.80602 3.72918 3.65619 3.64021 - 3.63347 3.63280 3.63118 3.63084 3.63074 3.62992 - 11.37492 10.53528 9.73858 8.99861 8.32949 7.74155 - 7.22719 6.77285 6.36527 5.99494 5.65200 5.32977 - 5.02667 4.74152 4.47339 4.22046 3.98101 3.75476 - 3.54143 3.43893 3.33979 3.26407 3.18817 3.16875 - 3.15146 3.14917 3.14784 3.14769 3.14755 3.14735 - 11.61237 10.62198 9.75160 8.97786 8.28886 7.67409 - 7.12600 6.63508 6.19203 5.79068 5.42548 5.09009 - 4.77641 4.47884 4.19716 3.93166 3.68245 3.44633 - 3.22277 3.11653 3.01299 2.93305 2.85447 2.83416 - 2.81531 2.81293 2.81147 2.81127 2.81116 2.81213 - 11.75055 10.69565 9.78022 8.96926 8.25041 7.61149 - 7.04252 6.53254 6.07100 5.65163 5.26932 4.91850 - 4.59227 4.28557 3.99716 3.72545 3.46936 3.22667 - 2.99645 2.88640 2.77824 2.69393 2.61187 2.59146 - 2.57420 2.57205 2.57040 2.57021 2.57003 2.57168 - 11.92089 10.78387 9.81511 8.96005 8.20592 7.53906 - 6.94579 6.41319 5.92956 5.48872 5.08600 4.71653 - 4.37457 4.05558 3.75718 3.47598 3.20929 2.95597 - 2.71393 2.59694 2.48099 2.38967 2.30072 2.27921 - 2.26309 2.26128 2.25941 2.25907 2.25899 2.25958 - 12.02839 10.83854 9.83881 8.95931 8.18688 7.50620 - 6.90181 6.35954 5.86713 5.41816 5.00772 4.63055 - 4.28052 3.95286 3.64536 3.35498 3.07884 2.81449 - 2.55932 2.43491 2.31209 2.21551 2.11931 2.09553 - 2.07719 2.07505 2.07311 2.07288 2.07265 2.07113 - 12.14631 10.90512 9.88330 8.98694 8.20395 7.51342 - 6.90057 6.35125 5.85343 5.40005 4.98524 4.60250 - 4.24398 3.90404 3.58126 3.27408 2.97958 2.69136 - 2.40405 2.25928 2.11274 1.99459 1.87675 1.84661 - 1.82220 1.81934 1.81701 1.81669 1.81647 1.81480 - 12.16666 10.93997 9.93041 9.03636 8.25320 7.56244 - 6.95098 6.40492 5.91209 5.46339 5.05007 4.66483 - 4.30220 3.95783 3.62917 3.31256 3.00375 2.69705 - 2.38077 2.21315 2.03717 1.89095 1.74745 1.71296 - 1.68536 1.68151 1.67855 1.67817 1.67786 1.68094 - 12.16908 10.94372 9.97005 9.11716 8.36725 7.69880 - 7.10065 6.56165 6.07213 5.62559 5.21612 4.83703 - 4.48000 4.13818 3.80777 3.48302 3.15607 2.81465 - 2.44202 2.23641 2.00943 1.80903 1.60873 1.56670 - 1.53850 1.53474 1.52885 1.52764 1.52820 1.53948 - 12.10344 10.93023 10.01054 9.19823 8.47318 7.82006 - 7.23145 6.70014 6.21972 5.78378 5.38538 5.01640 - 4.66639 4.32710 3.99511 3.66530 3.32811 2.96351 - 2.54581 2.30741 2.04060 1.80077 1.54351 1.48368 - 1.45971 1.45811 1.44904 1.44660 1.44884 1.46349 - 12.05700 10.90853 10.02649 9.24674 8.54716 7.91480 - 7.34310 6.82548 6.35612 5.92910 5.53797 5.17501 - 4.83012 4.49507 4.16579 3.83601 3.49374 3.11374 - 2.66264 2.39727 2.09303 1.81510 1.50898 1.43550 - 1.41149 1.41078 1.39948 1.39629 1.39962 1.41471 - 12.01166 10.88537 10.03734 9.28519 8.60803 7.99411 - 7.43763 6.93253 6.47351 6.05506 5.67115 5.31444 - 4.97517 4.64517 4.31987 3.99203 3.64762 3.25691 - 2.77951 2.49179 2.15558 1.84349 1.49204 1.40508 - 1.37906 1.37891 1.36583 1.36206 1.36624 1.38037 - 11.93233 10.84326 10.05122 9.34314 8.70280 8.11961 - 7.58895 7.10556 6.66491 6.26218 5.89197 5.54757 - 5.21987 4.90077 4.58508 4.26408 3.92056 3.51740 - 3.00211 2.67955 2.29102 1.91989 1.48660 1.37370 - 1.33881 1.33880 1.32312 1.31855 1.32382 1.33493 - 11.86950 10.80983 10.05992 9.38521 8.77326 8.21432 - 7.70446 7.23900 6.81397 6.42503 6.06727 5.73443 - 5.41787 5.10962 4.80410 4.49165 4.15273 3.74475 - 3.20513 2.85730 2.42815 2.00769 1.50139 1.36387 - 1.31535 1.31446 1.29706 1.29204 1.29778 1.30595 - 11.83141 10.79425 10.08924 9.45409 8.87894 8.35526 - 7.87941 7.44701 7.05425 6.69681 6.36960 6.06578 - 5.77541 5.48977 5.20403 4.90996 4.59076 4.20825 - 3.67814 3.29395 2.75439 2.19530 1.56149 1.39244 - 1.29185 1.27939 1.26031 1.25879 1.25566 1.26442 - 11.76601 10.76153 10.09694 9.49666 8.95191 8.45545 - 8.00416 7.59428 7.22248 6.88497 6.57712 6.29257 - 6.02186 5.75648 5.49152 5.21820 4.91804 4.54803 - 4.01427 3.61599 3.04401 2.42599 1.65409 1.42880 - 1.28142 1.26385 1.24178 1.23941 1.23637 1.24210 - 11.65962 10.70894 10.10396 9.55292 9.04939 8.58818 - 8.16730 7.78446 7.43765 7.12418 6.84066 6.58231 - 6.34165 6.11109 5.88393 5.64709 5.37825 5.03429 - 4.51675 4.11653 3.52086 2.82752 1.84466 1.54069 - 1.27837 1.24546 1.22375 1.22095 1.21564 1.21870 - 11.62772 10.69727 10.11646 9.58553 9.10042 8.65748 - 8.25457 7.88900 7.55840 7.26142 6.99680 6.76130 - 6.54767 6.34692 6.14814 5.93466 5.68390 5.35987 - 4.87667 4.50147 3.92094 3.18126 2.01956 1.64121 - 1.29389 1.24584 1.21309 1.20968 1.20380 1.20662 - 11.60639 10.68931 10.12490 9.60911 9.13746 8.70621 - 8.31402 7.95939 7.64111 7.35742 7.10609 6.88380 - 6.68498 6.50280 6.32852 6.14344 5.92117 5.62330 - 5.15913 4.79151 4.22557 3.49125 2.20208 1.73562 - 1.30853 1.25044 1.20834 1.20212 1.19880 1.19930 - 11.59084 10.68648 10.13342 9.62725 9.16418 8.74098 - 8.35665 8.01000 7.70018 7.42571 7.18457 6.97372 - 6.78787 6.62066 6.46416 6.30056 6.10335 5.83057 - 5.38892 5.03369 4.48265 3.74782 2.37038 1.83513 - 1.32635 1.25578 1.20539 1.19794 1.19411 1.19442 - 11.57183 10.68925 10.14975 9.65376 9.19946 8.78567 - 8.41183 8.07688 7.78010 7.51981 7.29359 7.09856 - 6.93085 6.78547 6.65522 6.52290 6.36261 6.13314 - 5.74376 5.41951 4.89859 4.16274 2.65965 2.02732 - 1.37239 1.27446 1.20079 1.19310 1.18274 1.18831 - 11.58420 10.69745 10.15718 9.66533 9.21814 8.81286 - 8.44823 8.12253 7.83458 7.58301 7.36607 7.18084 - 7.02211 6.88528 6.76836 6.66461 6.55283 6.37040 - 6.00566 5.69382 5.20560 4.50111 2.92805 2.21029 - 1.40893 1.28748 1.20183 1.19235 1.18404 1.18459 - 11.55502 10.70083 10.17801 9.69944 9.26239 8.86526 - 8.50752 8.18868 7.90872 7.66712 7.46289 7.29429 - 7.15785 7.04986 6.96676 6.89724 6.82070 6.69513 - 6.43057 6.18104 5.74857 5.09080 3.48152 2.60290 - 1.51232 1.33962 1.20757 1.19159 1.17936 1.17956 - 11.55716 10.71467 10.18946 9.71120 9.27704 8.88495 - 8.53371 8.22230 7.94989 7.71592 7.51924 7.35805 - 7.22855 7.12813 7.05752 7.01415 6.98305 6.91014 - 6.69662 6.48247 6.11036 5.50591 3.88270 2.94671 - 1.61856 1.39402 1.21494 1.19529 1.17634 1.17704 - 11.51284 10.72204 10.20140 9.72743 9.29755 8.90998 - 8.56357 8.25745 7.99098 7.76374 7.57491 7.42302 - 7.30478 7.21838 7.16604 7.14759 7.15257 7.13504 - 7.00840 6.85375 6.55489 6.03515 4.50627 3.48491 - 1.81704 1.50847 1.23550 1.20332 1.17422 1.17447 - 11.47310 10.72482 10.20661 9.73476 9.30709 8.92191 - 8.57811 8.27490 8.01173 7.78815 7.60358 7.45671 - 7.34442 7.26536 7.22259 7.21751 7.24261 7.25799 - 7.18658 7.07186 6.82507 6.37240 4.95424 3.90199 - 2.00140 1.62052 1.25816 1.21259 1.17401 1.17317 - 11.42398 10.71945 10.21007 9.74310 9.31756 8.93323 - 8.58969 8.28683 8.02477 7.80301 7.62059 7.47671 - 7.37033 7.30095 7.26865 7.26770 7.28916 7.31694 - 7.29342 7.21160 7.01136 6.63651 5.31907 4.18520 - 2.17472 1.74504 1.28174 1.21228 1.17915 1.17239 - 11.40177 10.71996 10.21231 9.74638 9.32171 8.93840 - 8.59597 8.29414 8.03290 7.81210 7.63156 7.49070 - 7.38790 7.32219 7.29385 7.29767 7.32561 7.36401 - 7.37325 7.32553 7.15622 6.78834 5.55042 4.52055 - 2.33653 1.83146 1.30501 1.23267 1.17563 1.17186 - 11.37434 10.72021 10.21436 9.74993 9.32673 8.94482 - 8.60381 8.30356 8.04413 7.82543 7.64722 7.50902 - 7.40944 7.34779 7.32485 7.33620 7.37535 7.43166 - 7.47408 7.45733 7.34304 7.04657 5.93284 4.95867 - 2.64033 2.02521 1.35168 1.25268 1.17957 1.17120 - 11.35714 10.72024 10.21539 9.75196 9.32967 8.94869 - 8.60864 8.30939 8.05110 7.83367 7.65692 7.52038 - 7.42277 7.36356 7.34384 7.35978 7.40588 7.47345 - 7.53641 7.53950 7.46390 7.22156 6.20761 5.29010 - 2.90979 2.20319 1.39778 1.27345 1.18423 1.17080 - 11.33121 10.72050 10.21683 9.75469 9.33368 8.95397 - 8.61520 8.31731 8.06050 7.84476 7.66995 7.53574 - 7.44086 7.38495 7.36959 7.39176 7.44738 7.53071 - 7.62220 7.65293 7.63559 7.48362 6.65866 5.86296 - 3.46816 2.59564 1.50992 1.32793 1.19704 1.17029 - 11.31699 10.72098 10.21795 9.75626 9.33576 8.95662 - 8.61848 8.32126 8.06514 7.85018 7.67634 7.54333 - 7.44994 7.39587 7.38285 7.40824 7.46872 7.56056 - 7.66744 7.71232 7.72536 7.62796 6.94253 6.23871 - 3.90544 2.92945 1.61750 1.38415 1.21021 1.17004 - 11.30222 10.72184 10.21927 9.75799 9.33791 8.95925 - 8.62168 8.32508 8.06964 7.85545 7.68256 7.55077 - 7.45891 7.40675 7.39620 7.42488 7.49027 7.59101 - 7.71439 7.77371 7.81642 7.77984 7.28522 6.71226 - 4.55318 3.46342 1.81817 1.49687 1.23599 1.16981 - 11.31464 10.72857 10.21848 9.75413 9.33376 8.95612 - 8.62032 8.32577 8.07217 7.85939 7.68729 7.55516 - 7.46068 7.40380 7.39020 7.42599 7.51244 7.62806 - 7.74470 7.80169 7.85387 7.85228 7.49134 6.99785 - 5.00484 3.88033 2.00534 1.60875 1.25948 1.16970 - 11.30935 10.72862 10.21878 9.75463 9.33444 8.95699 - 8.62138 8.32703 8.07362 7.86108 7.68925 7.55746 - 7.46339 7.40706 7.39421 7.43106 7.51912 7.63731 - 7.75888 7.82079 7.88276 7.90020 7.61452 7.19386 - 5.34558 4.21067 2.18720 1.71742 1.28294 1.16964 - 11.30566 10.72859 10.21898 9.75491 9.33484 8.95753 - 8.62206 8.32785 8.07460 7.86222 7.69059 7.55902 - 7.46524 7.40925 7.39690 7.43443 7.52356 7.64351 - 7.76855 7.83377 7.90213 7.93239 7.70114 7.33435 - 5.61114 4.48535 2.35639 1.82581 1.30587 1.16959 - 11.28098 10.72205 10.22009 9.75958 9.34031 8.96246 - 8.62573 8.33005 8.07564 7.86256 7.69084 7.56033 - 7.47008 7.42014 7.41270 7.44583 7.51782 7.62903 - 7.77444 7.85553 7.93517 7.97571 7.81422 7.52382 - 6.00456 4.92111 2.66023 2.03641 1.35168 1.16953 - 11.27828 10.72163 10.21979 9.75946 9.34048 8.96283 - 8.62621 8.33056 8.07617 7.86316 7.69160 7.56138 - 7.47148 7.42194 7.41490 7.44843 7.52103 7.63394 - 7.78197 7.86473 7.95061 8.00594 7.89258 7.64114 - 6.28438 5.25916 2.92751 2.22691 1.39569 1.16948 - 0.66198 0.69104 0.72074 0.75127 0.78271 0.81522 - 0.84906 0.88465 0.92262 0.96337 1.00738 1.05525 - 1.10789 1.16519 1.22388 1.27539 1.31102 1.33370 - 1.34833 1.35329 1.36039 1.36658 1.36229 1.36053 - 1.36060 1.36062 1.36035 1.36040 1.36026 1.36032 - 0.94380 0.97816 1.01414 1.05216 1.09235 1.13485 - 1.17981 1.22733 1.27754 1.33048 1.38605 1.44400 - 1.50377 1.56442 1.62456 1.68171 1.73147 1.76579 - 1.77465 1.77049 1.77093 1.77708 1.77743 1.77539 - 1.77626 1.77674 1.77658 1.77642 1.77675 1.77653 - 1.19559 1.24000 1.28593 1.33381 1.38372 1.43569 - 1.48972 1.54580 1.60381 1.66366 1.72504 1.78752 - 1.85044 1.91284 1.97330 2.02983 2.07971 2.11999 - 2.14319 2.14250 2.12871 2.11087 2.12548 2.14292 - 2.13763 2.13386 2.13426 2.13515 2.13291 2.13448 - 1.66064 1.71954 1.77925 1.84037 1.90280 1.96638 - 2.03090 2.09613 2.16177 2.22762 2.29355 2.35947 - 2.42575 2.49208 2.55604 2.61292 2.65717 2.68585 - 2.70008 2.70494 2.71066 2.71631 2.72101 2.72114 - 2.71974 2.71951 2.71963 2.71970 2.71966 2.71968 - 2.05600 2.13435 2.21027 2.28438 2.35640 2.42620 - 2.49398 2.56045 2.62668 2.69271 2.75830 2.82301 - 2.88663 2.94846 3.00649 3.05738 3.09777 3.12746 - 3.14646 3.15279 3.16230 3.17328 3.18084 3.18112 - 3.17784 3.17731 3.17768 3.17770 3.17780 3.17774 - 2.40407 2.50038 2.59048 2.67486 2.75312 2.82525 - 2.89206 2.95551 3.01838 3.08109 3.14323 3.20398 - 3.26241 3.31744 3.36789 3.41277 3.45089 3.48128 - 3.50299 3.51169 3.52434 3.53875 3.55020 3.54986 - 3.54565 3.54491 3.54532 3.54555 3.54543 3.54548 - 2.71509 2.82640 2.92780 3.01974 3.10163 3.17365 - 3.23720 3.29537 3.35253 3.40945 3.46578 3.52062 - 3.57292 3.62156 3.66570 3.70495 3.73905 3.76819 - 3.79294 3.80486 3.82068 3.83717 3.85047 3.85043 - 3.84588 3.84504 3.84552 3.84580 3.84563 3.84570 - 3.24914 3.38340 3.50044 3.60062 3.68329 3.74919 - 3.80106 3.84449 3.88692 3.92994 3.97310 4.01530 - 4.05473 4.08996 4.12101 4.14943 4.17700 4.20485 - 4.23453 4.25092 4.26999 4.28730 4.30225 4.30381 - 4.30009 4.29946 4.30005 4.30008 4.30026 4.30018 - 3.69979 3.84480 3.96741 4.06817 4.14648 4.20346 - 4.24268 4.27108 4.29780 4.32495 4.35240 4.37960 - 4.40547 4.42930 4.45126 4.47246 4.49453 4.51987 - 4.55142 4.56981 4.58906 4.60469 4.62027 4.62298 - 4.62188 4.62162 4.62213 4.62215 4.62230 4.62224 - 4.58485 4.72984 4.84409 4.92938 4.98553 5.01450 - 5.02108 5.01392 5.00407 4.99443 4.98593 4.97952 - 4.97637 4.97755 4.98273 4.99018 4.99934 5.01541 - 5.04426 5.06210 5.07591 5.08272 5.09520 5.10021 - 5.10713 5.10804 5.10810 5.10811 5.10809 5.10815 - 5.25121 5.37679 5.46741 5.52643 5.55432 5.55371 - 5.53005 5.49265 5.45300 5.41449 5.37863 5.34712 - 5.32246 5.30643 5.29803 5.29316 5.28941 5.29367 - 5.31339 5.32639 5.33162 5.32830 5.33438 5.34036 - 5.35426 5.35624 5.35580 5.35584 5.35562 5.35580 - 6.22047 6.28948 6.32076 6.32080 6.29127 6.23577 - 6.16058 6.07531 5.99123 5.91219 5.83961 5.77507 - 5.72112 5.67889 5.64663 5.61835 5.59007 5.56957 - 5.56483 5.56457 5.55324 5.53394 5.52638 5.53146 - 5.55236 5.55552 5.55439 5.55442 5.55395 5.55429 - 6.91754 6.92976 6.90410 6.84958 6.76875 6.66593 - 6.54784 6.42431 6.30640 6.19775 6.09948 6.01212 - 5.93705 5.87407 5.82119 5.77239 5.72346 5.68128 - 5.65288 5.64039 5.61765 5.59012 5.57306 5.57540 - 5.59419 5.59713 5.59583 5.59584 5.59535 5.59568 - 7.45817 7.42083 7.34568 7.24384 7.11854 6.97472 - 6.81954 6.66311 6.51675 6.38374 6.26468 6.15894 - 6.06635 5.98551 5.91448 5.84793 5.78203 5.72183 - 5.67293 5.65049 5.62101 5.59113 5.56871 5.56753 - 5.57825 5.58001 5.57890 5.57888 5.57853 5.57876 - 7.89713 7.81758 7.69998 7.55726 7.39315 7.21323 - 7.02522 6.83955 6.66808 6.51383 6.37666 6.25496 - 6.14686 6.05006 5.96279 5.88077 5.80070 5.72552 - 5.65921 5.62880 5.59568 5.56687 5.54182 5.53695 - 5.53665 5.53677 5.53607 5.53603 5.53588 5.53595 - 8.55464 8.44961 8.26261 8.02719 7.77135 7.52196 - 7.28527 7.06389 6.86116 6.67770 6.51169 6.36046 - 6.22113 6.09201 5.97280 5.86346 5.76308 5.66750 - 5.57356 5.52928 5.49043 5.46519 5.43747 5.42539 - 5.40701 5.40426 5.40398 5.40433 5.40387 5.40405 - 9.04644 8.89595 8.64780 8.34507 8.02555 7.72386 - 7.44536 7.18985 6.95727 6.74688 6.55544 6.37946 - 6.21600 6.06373 5.92230 5.79140 5.67006 5.55451 - 5.44240 5.39020 5.34493 5.31644 5.28600 5.27016 - 5.24242 5.23805 5.23784 5.23848 5.23766 5.23803 - 9.85956 9.59350 9.21167 8.77308 8.33141 7.93227 - 7.57820 7.26404 6.98390 6.73053 6.49374 6.26740 - 6.05372 5.85528 5.67251 5.50303 5.34498 5.19520 - 5.05032 4.98083 4.91762 4.87323 4.82479 4.80941 - 4.78720 4.78403 4.78356 4.78368 4.78358 4.78344 - 10.50088 9.92659 9.38278 8.87978 8.41434 7.98431 - 7.58770 7.22313 6.88994 6.58582 6.30783 6.05238 - 5.81454 5.59124 5.38371 5.19146 5.01260 4.83891 - 4.66400 4.57857 4.49839 4.43915 4.37566 4.36112 - 4.35645 4.35641 4.35484 4.35452 4.35427 4.35435 - 11.06891 10.31485 9.62174 8.99139 8.41681 7.89415 - 7.42058 6.99210 6.60546 6.25673 5.94090 5.65213 - 5.38259 5.12683 4.88511 4.65798 4.44275 4.23278 - 4.02432 3.92400 3.83130 3.76377 3.68966 3.67166 - 3.66546 3.66536 3.66356 3.66323 3.66284 3.66302 - 11.37031 10.49555 9.70811 8.99891 8.35887 7.78171 - 7.26353 6.79847 6.38078 6.00488 5.66450 5.35211 - 5.05772 4.77476 4.50437 4.24957 4.01151 3.78615 - 3.57224 3.47058 3.37161 3.29532 3.22002 3.20067 - 3.18347 3.18137 3.17997 3.17978 3.17966 3.17965 - 11.58287 10.61216 9.75492 8.98958 8.30532 7.69278 - 7.14533 6.65460 6.21225 5.81219 5.44869 5.11514 - 4.80309 4.50671 4.22595 3.96134 3.71312 3.47751 - 3.25351 3.14686 3.04326 2.96358 2.88500 2.86470 - 2.84596 2.84359 2.84212 2.84194 2.84182 2.84184 - 11.72941 10.68948 9.78411 8.97982 8.26504 7.62835 - 7.06048 6.55117 6.09055 5.67239 5.29152 4.94219 - 4.61730 4.31169 4.02417 3.75328 3.49798 3.25583 - 3.02572 2.91560 2.80738 2.72305 2.64085 2.62039 - 2.60312 2.60095 2.59929 2.59912 2.59894 2.59899 - 11.91167 10.78204 9.81861 8.96755 8.21642 7.55180 - 6.96027 6.42907 5.94674 5.50708 5.10549 4.73707 - 4.39612 4.07804 3.78050 3.50007 3.23409 2.98145 - 2.74011 2.62342 2.50753 2.41602 2.32667 2.30503 - 2.28878 2.28693 2.28505 2.28473 2.28464 2.28449 - 12.02619 10.83870 9.84086 8.96350 8.19331 7.51487 - 6.91263 6.37229 5.88147 5.43379 5.02444 4.64827 - 4.29926 3.97268 3.66622 3.37664 3.10102 2.83722 - 2.58286 2.45885 2.33613 2.23931 2.14268 2.11874 - 2.10026 2.09811 2.09616 2.09591 2.09569 2.09540 - 12.14944 10.90443 9.88043 8.98394 8.20220 7.51387 - 6.90370 6.35702 5.86131 5.40959 4.99610 4.61448 - 4.25709 3.91839 3.59688 3.29088 2.99738 2.70993 - 2.42307 2.27843 2.13196 2.01379 1.89568 1.86545 - 1.84096 1.83810 1.83577 1.83544 1.83522 1.83493 - 12.17900 10.92895 9.91343 9.02400 8.24833 7.56247 - 6.95317 6.40714 5.91306 5.46361 5.05227 4.67169 - 4.31286 3.96942 3.64027 3.32444 3.01848 2.71262 - 2.39604 2.23009 2.05386 1.90605 1.76397 1.72937 - 1.70139 1.69786 1.69481 1.69448 1.69414 1.69524 - 12.15788 10.92914 9.95331 9.10043 8.35209 7.68625 - 7.09114 6.55493 6.06743 5.62216 5.21355 4.83524 - 4.47937 4.13937 3.81133 3.48929 3.16509 2.82595 - 2.45455 2.24907 2.02188 1.82119 1.62123 1.57966 - 1.55193 1.54818 1.54230 1.54117 1.54164 1.54897 - 12.07108 10.90473 9.98883 9.17943 8.45663 7.80532 - 7.21819 6.68810 6.20874 5.77378 5.37639 5.00862 - 4.66018 4.32297 3.99354 3.66672 3.33275 2.97115 - 2.55559 2.31777 2.05105 1.81097 1.55384 1.49445 - 1.47154 1.47008 1.46096 1.45854 1.46072 1.47214 - 12.01404 10.87508 9.99870 9.22320 8.52685 7.89695 - 7.32708 6.81076 6.34236 5.91607 5.52562 5.16352 - 4.81997 4.48695 4.16041 3.83399 3.49549 3.11908 - 2.67064 2.40604 2.10201 1.82389 1.51802 1.44507 - 1.42233 1.42181 1.41044 1.40724 1.41050 1.42276 - 11.95998 10.84549 10.00460 9.25791 8.58487 7.97400 - 7.41970 6.91608 6.45800 6.04013 5.65668 5.30056 - 4.96242 4.63436 4.31183 3.98754 3.64722 3.26046 - 2.78611 2.49933 2.16348 1.85131 1.50027 1.41389 - 1.38925 1.38931 1.37614 1.37234 1.37645 1.38788 - 11.86786 10.79368 10.01112 9.31032 8.67550 8.09640 - 7.56861 7.08707 6.64747 6.24521 5.87517 5.53100 - 5.20407 4.88668 4.57367 4.25628 3.91708 3.51830 - 3.00655 2.68522 2.29737 1.92643 1.49390 1.38167 - 1.34820 1.34841 1.33263 1.32802 1.33319 1.34166 - 11.79665 10.75385 10.01484 9.34865 8.74322 8.18912 - 7.68264 7.21937 6.79554 6.40706 6.04932 5.71647 - 5.40042 5.09367 4.79066 4.48172 4.14715 3.74369 - 3.20793 2.86155 2.43335 2.01338 1.50818 1.37139 - 1.32430 1.32362 1.30611 1.30105 1.30668 1.31232 - 11.74672 10.72987 10.03801 9.41321 8.84601 8.32816 - 7.85630 7.42636 7.03475 6.67748 6.34979 6.04538 - 5.75505 5.47067 5.18748 4.89722 4.58280 4.20511 - 3.67874 3.29583 2.75708 2.19874 1.56752 1.39979 - 1.30040 1.28806 1.26892 1.26734 1.26414 1.27103 - 11.67910 10.69494 10.04369 9.45397 8.91735 8.42695 - 7.97991 7.57269 7.20222 6.86498 6.55668 6.27150 - 6.00071 5.73638 5.47370 5.20388 4.90819 4.54275 - 4.01266 3.61580 3.04513 2.42850 1.65979 1.43584 - 1.28984 1.27244 1.25031 1.24788 1.24480 1.24941 - 11.55856 10.63145 10.04313 9.50596 9.01374 8.56139 - 8.14704 7.76834 7.42327 7.10958 6.82446 6.56400 - 6.32213 6.09269 5.87034 5.64400 5.38804 5.03960 - 4.48748 4.07129 3.48560 2.82852 1.87778 1.55573 - 1.28084 1.25087 1.23588 1.23160 1.21525 1.22714 - 11.54592 10.62919 10.05881 9.53836 9.06260 8.62704 - 8.22984 7.86891 7.54235 7.24806 6.98333 6.74431 - 6.52470 6.31845 6.12088 5.92200 5.69749 5.38548 - 4.86919 4.46183 3.86253 3.15449 2.05509 1.66241 - 1.29975 1.25242 1.22281 1.21818 1.20479 1.21563 - 11.53900 10.63853 10.08315 9.57331 9.10530 8.67591 - 8.28442 7.93009 7.61243 7.32983 7.07999 6.85943 - 6.66238 6.48189 6.30925 6.12583 5.90539 5.60974 - 5.14868 4.78336 4.22071 3.48997 2.20590 1.74161 - 1.31710 1.25938 1.21736 1.21111 1.20784 1.20861 - 11.53487 10.64101 10.09275 9.59024 9.12985 8.70862 - 8.32572 7.98025 7.67165 7.39845 7.15864 6.94913 - 6.76461 6.59871 6.44351 6.28133 6.08583 5.81528 - 5.37685 5.02401 4.47639 3.74539 2.37360 1.84077 - 1.33494 1.26480 1.21456 1.20709 1.20332 1.20390 - 11.52756 10.64669 10.10811 9.61507 9.16418 8.75305 - 8.38106 8.04741 7.75171 7.49266 7.26832 7.07563 - 6.90915 6.76284 6.63045 6.49708 6.33898 6.11479 - 5.73177 5.40958 4.88927 4.15547 2.66446 2.03776 - 1.37755 1.27835 1.21082 1.20502 1.19493 1.19798 - 11.52372 10.65209 10.11939 9.63231 9.18760 8.78311 - 8.41814 8.09184 7.80374 7.55281 7.33749 7.15524 - 7.00133 6.87049 6.75719 6.64729 6.51780 6.32778 - 5.98674 5.69122 5.20311 4.48812 2.92544 2.21451 - 1.42006 1.29713 1.21077 1.20324 1.19055 1.19438 - 11.51243 10.66139 10.13859 9.66073 9.22501 8.82961 - 8.47378 8.15684 7.87843 7.63807 7.43475 7.26687 - 7.13105 7.02371 6.94130 6.87259 6.79709 6.67304 - 6.41107 6.16367 5.73449 5.08108 3.48027 2.60563 - 1.52032 1.34849 1.21730 1.20137 1.18928 1.18953 - 11.49345 10.66644 10.14952 9.67676 9.24568 8.85480 - 8.50345 8.19125 7.91813 7.68383 7.48757 7.32813 - 7.20256 7.10802 7.04210 6.99528 6.95011 6.87055 - 6.67500 6.47051 6.08922 5.48224 3.89961 2.94118 - 1.62365 1.40327 1.22537 1.20467 1.18695 1.18711 - 11.46302 10.67821 10.16020 9.68850 9.26062 8.87480 - 8.52990 8.22508 7.95970 7.73337 7.54526 7.39397 - 7.27625 7.19036 7.13850 7.12060 7.12620 7.10956 - 6.98455 6.83139 6.53519 6.01943 4.49977 3.48386 - 1.82359 1.51642 1.24522 1.21332 1.18434 1.18466 - 11.42378 10.68100 10.16528 9.69574 9.27005 8.88662 - 8.54434 8.24243 7.98031 7.75763 7.57376 7.42743 - 7.31557 7.23690 7.19449 7.18975 7.21524 7.23123 - 7.16118 7.04776 6.80334 6.35434 4.94532 3.89888 - 2.00703 1.62791 1.26779 1.22259 1.18414 1.18343 - 11.37519 10.67434 10.16786 9.70436 9.28205 8.90003 - 8.55778 8.25529 7.99286 7.77054 7.58831 7.44578 - 7.34126 7.27349 7.24213 7.24062 7.25941 7.28384 - 7.26888 7.19949 6.99557 6.58556 5.27876 4.23904 - 2.17975 1.73226 1.28916 1.23469 1.18489 1.18270 - 11.35337 10.67705 10.17187 9.70768 9.28452 8.90272 - 8.56175 8.26126 8.00111 7.78118 7.60137 7.46114 - 7.35882 7.29340 7.26518 7.26908 7.29720 7.33593 - 7.34603 7.29932 7.13189 6.76715 5.53815 4.51403 - 2.34038 1.83788 1.31440 1.24260 1.18573 1.18221 - 11.32742 10.67729 10.17352 9.71095 9.28941 8.90908 - 8.56950 8.27051 8.01214 7.79430 7.61685 7.47929 - 7.38017 7.31875 7.29585 7.30719 7.34639 7.40288 - 7.44587 7.42991 7.31716 7.02344 5.91807 4.94968 - 2.64269 2.03078 1.36082 1.26248 1.18967 1.18160 - 11.31095 10.67733 10.17445 9.71288 9.29236 8.91293 - 8.57425 8.27619 8.01893 7.80240 7.62642 7.49051 - 7.39334 7.33436 7.31466 7.33057 7.37665 7.44425 - 7.50756 7.51124 7.43695 7.19703 6.19093 5.27915 - 2.91089 2.20802 1.40667 1.28312 1.19431 1.18123 - 11.28569 10.67750 10.17578 9.71554 9.29630 8.91809 - 8.58063 8.28387 8.02811 7.81330 7.63925 7.50561 - 7.41113 7.35546 7.34016 7.36227 7.41777 7.50091 - 7.59243 7.62346 7.60699 7.45688 6.63872 5.84842 - 3.46666 2.59882 1.51824 1.33721 1.20709 1.18074 - 11.27147 10.67797 10.17690 9.71710 9.29836 8.92073 - 8.58389 8.28780 8.03274 7.81870 7.64557 7.51306 - 7.42001 7.36614 7.35322 7.37857 7.43887 7.53045 - 7.63721 7.68222 7.69582 7.59990 6.92051 6.22176 - 3.90190 2.93113 1.62527 1.39303 1.22022 1.18050 - 11.25642 10.67874 10.17832 9.71886 9.30048 8.92339 - 8.58722 8.29181 8.03737 7.82397 7.65169 7.52035 - 7.42879 7.37684 7.36635 7.39499 7.46017 7.56056 - 7.68362 7.74292 7.78590 7.75029 7.26061 6.69218 - 4.54652 3.46259 1.82491 1.50501 1.24591 1.18026 - 11.26866 10.68537 10.17753 9.71506 9.29640 8.92031 - 8.58588 8.29250 8.03989 7.82792 7.65646 7.52479 - 7.43062 7.37393 7.36035 7.39598 7.48213 7.59735 - 7.71368 7.77059 7.82285 7.82191 7.46518 6.97585 - 4.99579 3.87736 2.01123 1.61624 1.26933 1.18015 - 11.26354 10.68552 10.17783 9.71556 9.29708 8.92116 - 8.58691 8.29372 8.04131 7.82958 7.65840 7.52708 - 7.43332 7.37717 7.36435 7.40102 7.48874 7.60649 - 7.72768 7.78946 7.85137 7.86924 7.58722 7.17040 - 5.33460 4.20583 2.19205 1.72434 1.29269 1.18008 - 11.26000 10.68549 10.17793 9.71583 9.29748 8.92167 - 8.58756 8.29451 8.04224 7.83070 7.65972 7.52863 - 7.43518 7.37939 7.36704 7.40440 7.49316 7.61265 - 7.73726 7.80230 7.87050 7.90105 7.67297 7.30973 - 5.59851 4.47883 2.36025 1.83224 1.31554 1.18003 - 11.23559 10.67915 10.17934 9.72056 9.30290 8.92653 - 8.59115 8.29662 8.04319 7.83094 7.65989 7.52991 - 7.44001 7.39025 7.38280 7.41575 7.48740 7.59813 - 7.74302 7.82389 7.90329 7.94393 7.78507 7.49755 - 5.98942 4.91196 2.66247 2.04172 1.36110 1.17997 - 11.23193 10.67902 10.17964 9.72093 9.30320 8.92672 - 8.59127 8.29677 8.04350 7.83150 7.66071 7.53092 - 7.44129 7.39191 7.38491 7.41830 7.49050 7.60289 - 7.75042 7.83295 7.91862 7.97403 7.86249 7.61360 - 6.26748 5.24804 2.92842 2.23133 1.40474 1.17992 - 0.65271 0.67862 0.70629 0.73577 0.76685 0.79929 - 0.83313 0.86859 0.90598 0.94583 0.98905 1.03654 - 1.08890 1.14579 1.20420 1.25623 1.29287 1.31287 - 1.32528 1.33475 1.34286 1.34555 1.34229 1.34116 - 1.34098 1.34094 1.34076 1.34073 1.34071 1.34072 - 0.91227 0.95165 0.99169 1.03264 1.07459 1.11766 - 1.16213 1.20845 1.25730 1.30892 1.36335 1.42060 - 1.48050 1.54233 1.60415 1.66188 1.70979 1.74204 - 1.75158 1.74861 1.74953 1.75508 1.75510 1.75332 - 1.75442 1.75491 1.75475 1.75459 1.75490 1.75469 - 1.16048 1.20974 1.25965 1.31054 1.36233 1.41500 - 1.46853 1.52302 1.57872 1.63584 1.69463 1.75575 - 1.82051 1.88920 1.95853 2.02034 2.06532 2.09098 - 2.10110 2.10438 2.10763 2.10995 2.11048 2.11064 - 2.11144 2.11157 2.11151 2.11147 2.11152 2.11149 - 1.61574 1.68283 1.74901 1.81467 1.87960 1.94373 - 2.00718 2.07041 2.13424 2.19882 2.26410 2.33015 - 2.39740 2.46543 2.53126 2.58866 2.63139 2.66019 - 2.67626 2.67992 2.68558 2.69256 2.69695 2.69734 - 2.69602 2.69578 2.69597 2.69599 2.69602 2.69600 - 2.01978 2.10151 2.18005 2.25590 2.32876 2.39856 - 2.46572 2.53133 2.59703 2.66303 2.72905 2.79451 - 2.85893 2.92134 2.97960 3.03033 3.07030 3.10028 - 3.12126 3.12887 3.13862 3.14892 3.15726 3.15775 - 3.15444 3.15392 3.15432 3.15433 3.15445 3.15438 - 2.38085 2.47386 2.56134 2.64385 2.72101 2.79284 - 2.86003 2.92430 2.98815 3.05183 3.11494 3.17655 - 3.23559 3.29083 3.34098 3.38486 3.42163 3.45215 - 3.47754 3.48886 3.50234 3.51544 3.52686 3.52752 - 3.52297 3.52226 3.52281 3.52282 3.52301 3.52289 - 2.70603 2.80657 2.89966 2.98596 3.06503 3.13689 - 3.20236 3.26350 3.32323 3.38189 3.43914 3.49413 - 3.54607 3.59411 3.63754 3.67631 3.71058 3.74103 - 3.76867 3.78226 3.79873 3.81471 3.82844 3.82885 - 3.82426 3.82335 3.82386 3.82416 3.82395 3.82406 - 3.26173 3.37391 3.47406 3.56309 3.64050 3.70657 - 3.76276 3.81227 3.85948 3.90514 3.94897 3.99030 - 4.02839 4.06274 4.09347 4.12205 4.15030 4.17979 - 4.21241 4.23030 4.24968 4.26629 4.28232 4.28416 - 4.28037 4.27974 4.28037 4.28039 4.28061 4.28049 - 3.71954 3.84810 3.95053 4.03128 4.09555 4.14978 - 4.19588 4.23564 4.27164 4.30435 4.33385 4.36019 - 4.38340 4.40401 4.42319 4.44401 4.46956 4.49992 - 4.53301 4.54977 4.56890 4.58630 4.60213 4.60490 - 4.60403 4.60383 4.60428 4.60441 4.60443 4.60442 - 4.60188 4.73787 4.83319 4.89535 4.93307 4.95679 - 4.97014 4.97671 4.98078 4.98123 4.97486 4.96212 - 4.95173 4.95118 4.95959 4.97197 4.98447 5.00197 - 5.02950 5.04562 5.05945 5.06814 5.08095 5.08589 - 5.09328 5.09431 5.09438 5.09431 5.09435 5.09440 - 5.25908 5.36396 5.43958 5.48947 5.51396 5.51489 - 5.49627 5.46500 5.42976 5.39349 5.35800 5.32584 - 5.30092 5.28625 5.28086 5.28022 5.28078 5.28662 - 5.30231 5.31231 5.31783 5.31769 5.32336 5.32926 - 5.34379 5.34585 5.34537 5.34545 5.34518 5.34539 - 6.17481 6.25009 6.28672 6.29100 6.26461 6.21121 - 6.13726 6.05276 5.96934 5.89103 5.81939 5.75615 - 5.70418 5.66483 5.63630 5.61225 5.58776 5.56814 - 5.55901 5.55582 5.54504 5.52917 5.52109 5.52600 - 5.54731 5.55052 5.54937 5.54943 5.54891 5.54927 - 6.83185 6.87148 6.86660 6.82611 6.75295 6.65241 - 6.53276 6.40621 6.28650 6.17779 6.08105 5.99644 - 5.92473 5.86516 5.81571 5.77015 5.72383 5.68217 - 5.65099 5.63676 5.61472 5.58978 5.57246 5.57466 - 5.59362 5.59658 5.59528 5.59531 5.59480 5.59513 - 7.35390 7.35480 7.30812 7.22503 7.10949 6.96796 - 6.80994 6.64886 6.49975 6.36652 6.24944 6.14719 - 6.05846 5.98088 5.91250 5.84800 5.78354 5.72389 - 5.67441 5.65166 5.62290 5.59441 5.57208 5.57086 - 5.58161 5.58338 5.58226 5.58226 5.58191 5.58213 - 7.96181 7.79786 7.62733 7.46050 7.29731 7.13792 - 6.98249 6.83116 6.68442 6.54313 6.40810 6.27946 - 6.15857 6.04660 5.94468 5.85452 5.77730 5.71083 - 5.65547 5.63535 5.62238 5.61096 5.55233 5.52398 - 5.53964 5.54638 5.54359 5.54162 5.54494 5.54285 - 8.46117 8.41186 8.25097 8.02043 7.76054 7.50958 - 7.27458 7.05658 6.85717 6.67654 6.51281 6.36325 - 6.22493 6.09611 5.97660 5.86660 5.76600 5.67304 - 5.58441 5.54157 5.50299 5.47719 5.44995 5.43819 - 5.41986 5.41709 5.41681 5.41715 5.41669 5.41687 - 8.99208 8.87007 8.63643 8.33814 8.01864 7.71771 - 7.44115 7.18827 6.95840 6.75063 6.56158 6.38755 - 6.22513 6.07268 5.93014 5.79803 5.67657 5.56380 - 5.45734 5.40725 5.36262 5.33335 5.30288 5.28751 - 5.25997 5.25555 5.25531 5.25597 5.25511 5.25551 - 9.87566 9.58891 9.20129 8.76650 8.33173 7.93725 - 7.58558 7.27269 6.99384 6.74202 6.50716 6.28292 - 6.07100 5.87353 5.69091 5.52094 5.36258 5.21564 - 5.07523 5.00541 4.94185 4.89780 4.84981 4.83452 - 4.81235 4.80919 4.80874 4.80886 4.80876 4.80863 - 10.51833 9.94007 9.39345 8.88858 8.42216 7.99196 - 7.59592 7.23260 6.90122 6.59942 6.32414 6.07162 - 5.83663 5.61585 5.41046 5.21990 5.04213 4.86860 - 4.69264 4.60654 4.52645 4.46807 4.40507 4.39036 - 4.38571 4.38570 4.38415 4.38383 4.38359 4.38368 - 11.02231 10.35751 9.67853 9.02046 8.41125 7.87401 - 7.40529 6.99544 6.63455 6.30854 5.99873 5.69671 - 5.41146 5.14934 4.90774 4.67998 4.45980 4.25084 - 4.05672 3.96374 3.86918 3.79281 3.72050 3.70467 - 3.69796 3.69732 3.69576 3.69541 3.69531 3.69531 - 11.39770 10.51189 9.71834 9.00695 8.36769 7.79333 - 7.27901 6.81776 6.40288 6.02877 5.68942 5.37760 - 5.08372 4.80141 4.53180 4.27769 4.04017 3.81560 - 3.60302 3.50206 3.40336 3.32694 3.25195 3.23269 - 3.21556 3.21347 3.21209 3.21189 3.21178 3.21177 - 11.60001 10.62393 9.76416 8.99856 8.31577 7.70579 - 7.16144 6.67369 6.23366 5.83525 5.47288 5.14013 - 4.82872 4.53298 4.25279 3.98862 3.74075 3.50589 - 3.28339 3.17753 3.07407 2.99401 2.91568 2.89551 - 2.87686 2.87446 2.87296 2.87279 2.87265 2.87268 - 11.73722 10.69660 9.79166 8.98870 8.27592 7.64166 - 7.07634 6.56939 6.11069 5.69403 5.31434 4.96597 - 4.64194 4.33715 4.05040 3.78021 3.52550 3.28400 - 3.05468 2.94489 2.83669 2.75213 2.67001 2.64964 - 2.63247 2.63026 2.62853 2.62838 2.62816 2.62822 - 11.90833 10.78302 9.82263 8.97415 8.22520 7.56250 - 6.97272 6.44323 5.96264 5.52478 5.12498 4.75828 - 4.41884 4.10200 3.80545 3.52584 3.26044 3.00804 - 2.76651 2.64965 2.53377 2.44236 2.35285 2.33120 - 2.31494 2.31296 2.31103 2.31085 2.31059 2.31052 - 12.00670 10.83089 9.84066 8.96850 8.20165 7.52520 - 6.92417 6.38475 5.89501 5.44860 5.04067 4.66601 - 4.31846 3.99323 3.68799 3.39943 3.12458 2.86123 - 2.60692 2.48283 2.36004 2.26313 2.16617 2.14209 - 2.12344 2.12131 2.11941 2.11914 2.11894 2.11865 - 12.11351 10.88538 9.87204 8.98244 8.20468 7.51838 - 6.90907 6.36286 5.86798 5.41745 5.00548 4.62559 - 4.26997 3.93294 3.61294 3.30812 3.01539 2.72852 - 2.44218 2.29769 2.15114 2.03270 1.91433 1.88398 - 1.85934 1.85652 1.85425 1.85389 1.85369 1.85339 - 12.13721 10.90350 9.89855 9.01617 8.24479 7.56139 - 6.95336 6.40814 5.91493 5.46657 5.05657 4.67757 - 4.32056 3.97915 3.65209 3.33806 3.03342 2.72834 - 2.41199 2.24593 2.06953 1.92158 1.77955 1.74509 - 1.71730 1.71368 1.71047 1.71022 1.70980 1.71093 - 12.11506 10.89836 9.93037 9.08325 8.33904 7.67617 - 7.08320 6.54861 6.06246 5.61847 5.21115 4.83432 - 4.48031 4.14264 3.81724 3.49780 3.17578 2.83790 - 2.46648 2.26061 2.03312 1.83249 1.63361 1.59279 - 1.56560 1.56159 1.55498 1.55375 1.55442 1.56197 - 12.02913 10.87165 9.96148 9.15667 8.43761 7.78943 - 7.20492 6.67705 6.19959 5.76632 5.37052 5.00433 - 4.65764 4.32244 3.99526 3.67087 3.33928 2.97954 - 2.56483 2.32704 2.06018 1.82018 1.56466 1.50645 - 1.48455 1.48264 1.47218 1.46958 1.47212 1.48398 - 11.97379 10.84235 9.97042 9.19849 8.50518 7.87791 - 7.31032 6.79607 6.32955 5.90502 5.51629 5.15596 - 4.81439 4.48359 4.15952 3.83572 3.49982 3.12547 - 2.67801 2.41351 2.10952 1.83171 1.52806 1.45662 - 1.43529 1.43417 1.42092 1.41747 1.42124 1.43401 - 11.92211 10.81384 9.97625 9.23224 8.56156 7.95285 - 7.40054 6.89879 6.44252 6.02645 5.64479 5.29058 - 4.95455 4.62885 4.30893 3.98741 3.64984 3.26529 - 2.79208 2.50550 2.16984 1.85821 1.50985 1.42523 - 1.40237 1.40171 1.38623 1.38213 1.38687 1.39882 - 11.83441 10.76473 9.98348 9.28395 8.65039 8.07267 - 7.54631 7.06631 6.62836 6.22785 5.85970 5.51760 - 5.19294 4.87809 4.56783 4.25336 3.91708 3.52073 - 3.01043 2.68952 2.30217 1.93218 1.50295 1.39279 - 1.36170 1.36108 1.34240 1.33741 1.34340 1.35231 - 11.83062 10.76461 10.00526 9.32417 8.70856 8.14846 - 7.63953 7.17682 6.75593 6.37221 6.02025 5.69320 - 5.38148 5.07687 4.77483 4.46785 4.14082 3.75992 - 3.25532 2.90632 2.43544 1.97138 1.50387 1.39835 - 1.34324 1.33318 1.31484 1.31474 1.31079 1.32287 - 11.72007 10.70504 10.01201 9.38639 8.81878 8.30096 - 7.82954 7.40038 7.00991 6.65410 6.32819 6.02584 - 5.73788 5.45614 5.17586 4.88874 4.57752 4.20262 - 3.67822 3.29619 2.75872 2.20220 1.57544 1.41031 - 1.31415 1.30047 1.27860 1.27757 1.27359 1.28152 - 11.65273 10.67012 10.01715 9.42624 8.88896 8.39843 - 7.95169 7.54521 7.17586 6.84007 6.53357 6.25042 - 5.98185 5.71990 5.45971 5.19257 4.89973 4.53714 - 4.00983 3.61446 3.04557 2.43110 1.66715 1.44567 - 1.30283 1.28446 1.26017 1.25817 1.25446 1.25990 - 11.54186 10.61805 10.02700 9.48558 8.98829 8.53074 - 8.11182 7.73019 7.38478 7.07317 6.79195 6.53640 - 6.29908 6.07247 5.84984 5.61794 5.35430 5.01588 - 4.50463 4.10829 3.51773 2.83015 1.85667 1.55624 - 1.29784 1.26516 1.24271 1.23973 1.23478 1.23766 - 11.51817 10.60840 10.03846 9.51642 9.03765 8.59829 - 8.19718 7.83309 7.50500 7.21103 6.94864 6.71419 - 6.50167 6.30378 6.11100 5.90371 5.65629 5.33604 - 4.85738 4.48393 3.91239 3.19404 2.03132 1.64809 - 1.31241 1.26711 1.23252 1.22791 1.22469 1.22616 - 11.50314 10.60485 10.04861 9.53903 9.07211 8.64441 - 8.25493 7.90257 7.58653 7.30514 7.05618 6.83635 - 6.64005 6.46051 6.28906 6.10709 5.88843 5.59531 - 5.13807 4.77540 4.21607 3.48881 2.21039 1.74862 - 1.32697 1.26960 1.22771 1.22152 1.21819 1.21916 - 11.49396 10.60484 10.05751 9.55620 9.09723 8.67759 - 8.29634 7.95245 7.64521 7.37320 7.13439 6.92576 - 6.74204 6.57695 6.42266 6.26164 6.06775 5.79954 - 5.36471 5.01444 4.47028 3.74312 2.37741 1.84708 - 1.34430 1.27478 1.22499 1.21746 1.21374 1.21446 - 11.48113 10.60783 10.07203 9.58126 9.13223 8.72261 - 8.35190 8.01935 7.72472 7.46667 7.24328 7.05151 - 6.88585 6.74032 6.60869 6.47621 6.31935 6.09703 - 5.71719 5.39744 4.88066 4.15105 2.66697 2.04311 - 1.38644 1.28798 1.22124 1.21550 1.20535 1.20856 - 11.47567 10.61244 10.08310 9.59861 9.15586 8.75282 - 8.38896 8.06356 7.77634 7.52629 7.31186 7.13046 - 6.97731 6.84718 6.73457 6.62542 6.49696 6.30852 - 5.97030 5.67710 5.19250 4.48185 2.92673 2.21915 - 1.42886 1.30670 1.22118 1.21372 1.20098 1.20497 - 11.46578 10.62245 10.10265 9.62713 9.19317 8.79908 - 8.44424 8.12809 7.85044 7.61077 7.40814 7.24092 - 7.10571 6.99893 6.91707 6.84894 6.77415 6.65119 - 6.39137 6.14599 5.72023 5.07140 3.47900 2.60865 - 1.52923 1.35814 1.22761 1.21182 1.19967 1.20015 - 11.45016 10.62971 10.11452 9.64269 9.21226 8.82218 - 8.47188 8.16117 7.89000 7.65758 7.46228 7.30255 - 7.17646 7.08195 7.01651 6.97028 6.92585 6.84870 - 6.65209 6.44453 6.07274 5.48392 3.89852 2.92492 - 1.63458 1.42029 1.23544 1.21379 1.19378 1.19775 - 11.42052 10.64079 10.12456 9.65447 9.22802 8.84348 - 8.49972 8.19589 7.93137 7.70573 7.51820 7.36738 - 7.25003 7.16442 7.11280 7.09507 7.10086 7.08464 - 6.96076 6.80888 6.51522 6.00342 4.49321 3.48312 - 1.83092 1.52497 1.25530 1.22371 1.19473 1.19532 - 11.38165 10.64338 10.12942 9.66150 9.23726 8.85515 - 8.51404 8.21317 7.95196 7.73004 7.54680 7.40098 - 7.28953 7.21111 7.16884 7.16413 7.18957 7.20562 - 7.13622 7.02377 6.78146 6.33604 4.93636 3.89577 - 2.01268 1.63545 1.27773 1.23291 1.19457 1.19411 - 11.35317 10.64472 10.13203 9.66540 9.24251 8.86189 - 8.52246 8.22346 7.96437 7.74484 7.56433 7.42167 - 7.31387 7.23988 7.20333 7.20666 7.24452 7.28171 - 7.24962 7.16554 6.96247 6.57044 5.27264 4.22763 - 2.18204 1.74196 1.30087 1.24251 1.19536 1.19339 - 11.31154 10.63913 10.13567 9.67312 9.25142 8.87096 - 8.53126 8.23192 7.97284 7.75384 7.57475 7.43501 - 7.33295 7.26760 7.23934 7.24314 7.27123 7.30990 - 7.32008 7.27384 7.10762 6.74570 5.52607 4.50714 - 2.34344 1.84405 1.32409 1.25277 1.19618 1.19290 - 11.28576 10.63918 10.13731 9.67638 9.25630 8.87732 - 8.53903 8.24119 7.98383 7.76682 7.59002 7.45295 - 7.35413 7.29282 7.26989 7.28112 7.32021 7.37651 - 7.41937 7.40366 7.29175 7.00021 5.90331 4.94034 - 2.64444 2.03620 1.37023 1.27252 1.20007 1.19228 - 11.26932 10.63932 10.13824 9.67834 9.25930 8.88127 - 8.54384 8.24689 7.99053 7.77471 7.59929 7.46385 - 7.36702 7.30822 7.28857 7.30439 7.35031 7.41764 - 7.48074 7.48458 7.41085 7.17262 6.17409 5.26801 - 2.91182 2.21289 1.41581 1.29303 1.20466 1.19191 - 11.24521 10.63949 10.13937 9.68068 9.26297 8.88626 - 8.55020 8.25477 8.00022 7.78623 7.61225 7.47799 - 7.38330 7.32855 7.31460 7.33665 7.38979 7.47235 - 7.56968 7.60197 7.57226 7.41283 6.65334 5.85445 - 3.43812 2.59258 1.52959 1.34559 1.22735 1.19141 - 11.23130 10.64007 10.14051 9.68228 9.26507 8.88888 - 8.55342 8.25866 8.00481 7.79161 7.61855 7.48540 - 7.39217 7.33934 7.32786 7.35307 7.41046 7.50026 - 7.61453 7.66434 7.66332 7.54367 6.92294 6.25977 - 3.86365 2.90798 1.63645 1.40753 1.23846 1.19116 - 11.21616 10.64093 10.14225 9.68443 9.26748 8.89165 - 8.55661 8.26223 8.00870 7.79608 7.62443 7.49357 - 7.40230 7.35050 7.34001 7.36848 7.43336 7.53336 - 7.65599 7.71509 7.75795 7.72259 7.23603 6.67179 - 4.53983 3.46177 1.83175 1.51328 1.25607 1.19091 - 11.22831 10.64746 10.14132 9.68049 9.26331 8.88854 - 8.55528 8.26296 8.01123 7.80001 7.62916 7.49796 - 7.40411 7.34757 7.33401 7.36946 7.45524 7.56998 - 7.68588 7.74259 7.79469 7.79386 7.43936 6.95331 - 4.98633 3.87420 2.01713 1.62381 1.27936 1.19079 - 11.22316 10.64732 10.14153 9.68091 9.26396 8.88938 - 8.55631 8.26416 8.01264 7.80166 7.63106 7.50018 - 7.40672 7.35073 7.33791 7.37443 7.46179 7.57907 - 7.69983 7.76139 7.82313 7.84100 7.56056 7.14662 - 5.32348 4.20098 2.19692 1.73131 1.30258 1.19072 - 11.21937 10.64729 10.14161 9.68117 9.26435 8.88991 - 8.55697 8.26498 8.01358 7.80276 7.63234 7.50168 - 7.40849 7.35286 7.34051 7.37769 7.46611 7.58515 - 7.70935 7.77418 7.84221 7.87269 7.64579 7.28509 - 5.58600 4.47252 2.36422 1.83874 1.32528 1.19067 - 11.19513 10.64105 10.14310 9.68605 9.26991 8.89488 - 8.56064 8.26711 8.01454 7.80298 7.63247 7.50286 - 7.41324 7.36365 7.35625 7.38906 7.46036 7.57067 - 7.71505 7.79558 7.87481 7.91545 7.75709 7.47174 - 5.97462 4.90303 2.66473 2.04704 1.37057 1.19063 - 11.19241 10.64112 10.14340 9.68649 9.27040 8.89531 - 8.56099 8.26741 8.01492 7.80357 7.63334 7.50406 - 7.41475 7.36546 7.35838 7.39156 7.46354 7.57551 - 7.72240 7.80462 7.89001 7.94529 7.83436 7.58677 - 6.25002 5.23666 2.92939 2.23578 1.41404 1.19060 - 0.63961 0.66522 0.69255 0.72165 0.75232 0.78430 - 0.81768 0.85267 0.88963 0.92908 0.97185 1.01884 - 1.07066 1.12703 1.18495 1.23658 1.27303 1.29344 - 1.30642 1.31573 1.32408 1.32726 1.32341 1.32215 - 1.32207 1.32204 1.32186 1.32183 1.32180 1.32183 - 0.89544 0.93454 0.97422 1.01474 1.05619 1.09873 - 1.14268 1.18859 1.23723 1.28889 1.34356 1.40110 - 1.46110 1.52257 1.58358 1.64023 1.68717 1.71897 - 1.72922 1.72718 1.72930 1.73558 1.73409 1.73153 - 1.73286 1.73351 1.73332 1.73312 1.73350 1.73319 - 1.14143 1.18996 1.23915 1.28933 1.34046 1.39253 - 1.44561 1.49989 1.55570 1.61326 1.67274 1.73459 - 1.79970 1.86798 1.93606 1.99599 2.03948 2.06692 - 2.07948 2.08073 2.08439 2.08941 2.08779 2.08743 - 2.08866 2.08882 2.08869 2.08875 2.08864 2.08861 - 1.59192 1.65844 1.72410 1.78929 1.85382 1.91762 - 1.98082 2.04392 2.10772 2.17237 2.23781 2.30405 - 2.37143 2.43946 2.50521 2.56267 2.60581 2.63535 - 2.65224 2.65602 2.66102 2.66715 2.67287 2.67375 - 2.67232 2.67204 2.67226 2.67226 2.67233 2.67223 - 1.99312 2.07412 2.15208 2.22750 2.30007 2.36974 - 2.43691 2.50265 2.56857 2.63481 2.70101 2.76647 - 2.83048 2.89200 2.94949 3.00099 3.04426 3.07792 - 3.09972 3.10584 3.11242 3.12002 3.13226 3.13494 - 3.13147 3.13041 3.13074 3.13104 3.13061 3.13090 - 2.35274 2.44426 2.53078 2.61286 2.69009 2.76240 - 2.83030 2.89520 2.95922 3.02253 3.08486 3.14550 - 3.20395 3.25948 3.31104 3.35756 3.39786 3.43096 - 3.45539 3.46452 3.47526 3.48706 3.50283 3.50521 - 3.50062 3.49944 3.49993 3.50029 3.49994 3.50018 - 2.67573 2.77536 2.86791 2.95405 3.03329 3.10558 - 3.17162 3.23323 3.29308 3.35151 3.40826 3.46273 - 3.51461 3.56348 3.60862 3.64970 3.68646 3.71897 - 3.74700 3.75941 3.77299 3.78638 3.80467 3.80777 - 3.80277 3.80141 3.80199 3.80241 3.80197 3.80229 - 3.23056 3.34075 3.43979 3.52855 3.60651 3.67377 - 3.73149 3.78237 3.83020 3.87568 3.91877 3.95924 - 3.99725 4.03303 4.06649 4.09816 4.12884 4.15971 - 4.19194 4.20855 4.22577 4.24089 4.26076 4.26469 - 4.26096 4.25979 4.26038 4.26078 4.26036 4.26071 - 3.68490 3.81358 3.91629 3.99744 4.06221 4.11709 - 4.16400 4.20486 4.24228 4.27629 4.30622 4.33198 - 4.35515 4.37750 4.39964 4.42293 4.44906 4.47939 - 4.51373 4.53117 4.54875 4.56380 4.58346 4.58715 - 4.58598 4.58577 4.58626 4.58636 4.58643 4.58647 - 4.56559 4.70257 4.79866 4.86152 4.90008 4.92500 - 4.93971 4.94744 4.95217 4.95376 4.95078 4.94371 - 4.93733 4.93620 4.94094 4.95115 4.96642 4.98689 - 5.01328 5.02920 5.04631 5.05926 5.06722 5.07106 - 5.07920 5.08030 5.08033 5.08030 5.08025 5.08036 - 5.22304 5.32981 5.40662 5.45708 5.48170 5.48267 - 5.46447 5.43471 5.40288 5.37163 5.34202 5.31518 - 5.29262 5.27583 5.26549 5.26162 5.26424 5.27336 - 5.28935 5.30009 5.31099 5.31725 5.31530 5.31728 - 5.33206 5.33519 5.33481 5.33416 5.33499 5.33451 - 6.13818 6.21696 6.25627 6.26241 6.23718 6.18454 - 6.11134 6.02817 5.94734 5.87274 5.80542 5.74625 - 5.69662 5.65695 5.62644 5.60141 5.57871 5.56012 - 5.54887 5.54697 5.54654 5.54240 5.51879 5.51808 - 5.54150 5.54533 5.54373 5.54406 5.54310 5.54356 - 6.79787 6.84054 6.83831 6.79997 6.72858 6.62952 - 6.51129 6.38644 6.26899 6.16308 6.06938 5.98760 - 5.91769 5.85848 5.80858 5.76344 5.71929 5.67860 - 5.64541 5.63241 5.62004 5.60610 5.57447 5.57145 - 5.59229 5.59581 5.59409 5.59439 5.59345 5.59389 - 7.32271 7.32611 7.28196 7.20128 7.08804 6.94868 - 6.79272 6.63364 6.48648 6.35519 6.23991 6.13936 - 6.05201 5.97550 5.90809 5.84510 5.78275 5.72406 - 5.67357 5.65178 5.62951 5.60836 5.57692 5.57236 - 5.58434 5.58648 5.58513 5.58529 5.58464 5.58498 - 7.93302 7.77162 7.60366 7.43931 7.27847 7.12135 - 6.96809 6.81883 6.67407 6.53464 6.40136 6.27435 - 6.15499 6.04442 5.94379 5.85482 5.77874 5.71352 - 5.65975 5.64060 5.62874 5.61819 5.55949 5.53065 - 5.54605 5.55284 5.55014 5.54816 5.55150 5.54947 - 8.61514 8.38535 8.15066 7.92291 7.70186 7.48766 - 7.28052 7.08047 6.88819 6.70495 6.53119 6.36728 - 6.21452 6.07491 5.94944 5.83995 5.74714 5.66626 - 5.59469 5.56544 5.54246 5.52264 5.45695 5.42584 - 5.42984 5.43372 5.43014 5.42857 5.43096 5.42988 - 8.96837 8.85092 8.62134 8.32660 8.01040 7.71277 - 7.43934 7.18900 6.96069 6.75354 6.56436 6.39002 - 6.22813 6.07774 5.93838 5.80935 5.69001 5.57914 - 5.47352 5.42137 5.37080 5.33588 5.31497 5.30582 - 5.27855 5.27315 5.27277 5.27371 5.27234 5.27342 - 9.85720 9.57619 9.19381 8.76347 8.33241 7.94095 - 7.59181 7.28118 7.00449 6.75450 6.52070 6.29684 - 6.08569 5.89011 5.70993 5.54165 5.38339 5.23628 - 5.09862 5.03066 4.96248 4.91155 4.87376 4.86090 - 4.83778 4.83455 4.83419 4.83424 4.83431 4.83405 - 10.50551 9.93224 9.39026 8.88954 8.42688 8.00006 - 7.60708 7.24650 6.91757 6.61797 6.34462 6.09374 - 5.86012 5.64034 5.43563 5.24541 5.06773 4.89430 - 4.71919 4.63455 4.55779 4.50289 4.43692 4.41886 - 4.41497 4.41544 4.41367 4.41331 4.41303 4.41265 - 11.00994 10.35491 9.68253 9.02883 8.42269 7.88804 - 7.42149 7.01335 6.65366 6.32900 6.02162 5.72295 - 5.44014 5.17836 4.93586 4.70767 4.48876 4.28143 - 4.08730 3.99438 3.90396 3.83259 3.75393 3.73652 - 3.73031 3.72969 3.72806 3.72776 3.72757 3.72672 - 11.38764 10.51029 9.72328 9.01681 8.38122 7.80956 - 7.29715 6.83730 6.42356 6.05045 5.71205 5.40129 - 5.10870 4.82797 4.55995 4.30700 4.07003 3.84612 - 3.63481 3.53433 3.43514 3.35783 3.28406 3.26520 - 3.24789 3.24575 3.24438 3.24416 3.24409 3.24386 - 11.59000 10.62235 9.76900 9.00831 8.32919 7.72194 - 7.17954 6.69320 6.25420 5.85661 5.49502 5.16315 - 4.85299 4.55889 4.28044 4.01751 3.77011 3.53584 - 3.31459 3.20897 3.10426 3.02260 2.94654 2.92716 - 2.90822 2.90575 2.90431 2.90409 2.90401 2.90505 - 11.72289 10.69168 9.79419 8.99731 8.28935 7.65881 - 7.09612 6.59076 6.13262 5.71582 5.33568 4.98712 - 4.66386 4.36109 4.07696 3.80873 3.55458 3.31318 - 3.08431 2.97469 2.86618 2.78113 2.69960 2.67959 - 2.66249 2.66030 2.65853 2.65829 2.65812 2.65995 - 11.88997 10.77647 9.82432 8.98172 8.23680 7.57672 - 6.98863 6.46032 5.98071 5.54381 5.14494 4.77922 - 4.44080 4.12506 3.82964 3.55101 3.28636 3.03448 - 2.79337 2.67674 2.56118 2.46999 2.37993 2.35788 - 2.34159 2.33978 2.33785 2.33750 2.33745 2.33809 - 11.99000 10.82396 9.84041 8.97298 8.20933 7.53508 - 6.93556 6.39742 5.90902 5.46404 5.05760 4.68440 - 4.33822 4.01419 3.70998 3.42233 3.14819 2.88518 - 2.63079 2.50676 2.38453 2.28821 2.19019 2.16574 - 2.14709 2.14496 2.14303 2.14279 2.14256 2.14094 - 12.09229 10.87332 9.86598 8.98072 8.20598 7.52177 - 6.91395 6.36896 5.87523 5.42589 5.01516 4.63661 - 4.28248 3.94706 3.62866 3.32519 3.03341 2.74716 - 2.46118 2.31672 2.17003 2.05137 1.93277 1.90233 - 1.87759 1.87473 1.87245 1.87210 1.87190 1.87007 - 12.11274 10.88763 9.88803 9.00952 8.24086 7.55938 - 6.95278 6.40873 5.91673 5.46961 5.06094 4.68342 - 4.32805 3.98840 3.66309 3.35061 3.04717 2.74305 - 2.42743 2.26163 2.08542 1.93748 1.79510 1.76052 - 1.73257 1.72895 1.72574 1.72546 1.72505 1.72832 - 12.08630 10.87748 9.91396 9.06980 8.32751 7.66599 - 7.07413 6.54075 6.05622 5.61419 5.20907 4.83446 - 4.48247 4.14643 3.82232 3.50388 3.18275 2.84615 - 2.47703 2.27305 2.04825 1.84964 1.64873 1.60587 - 1.57778 1.57393 1.56739 1.56605 1.56687 1.57881 - 12.00834 10.85146 9.94084 9.13621 8.41797 7.77122 - 7.18865 6.66309 6.18823 5.75769 5.36464 5.00101 - 4.65639 4.32262 3.99633 3.67253 3.34176 2.98411 - 2.57392 2.33948 2.07666 1.83926 1.58083 1.51964 - 1.49543 1.49357 1.48341 1.48076 1.48341 1.49909 - 11.95561 10.82241 9.94807 9.17494 8.48157 7.85527 - 7.28949 6.77771 6.31415 5.89287 5.50747 5.15023 - 4.81103 4.48166 4.15819 3.83456 3.49911 3.12716 - 2.68579 2.42603 2.12769 1.85340 1.54531 1.46974 - 1.44557 1.44455 1.43173 1.42824 1.43217 1.44845 - 11.90622 10.79449 9.95296 9.20664 8.53519 7.92703 - 7.37638 6.87718 6.42412 6.01167 5.63377 5.28304 - 4.94964 4.62537 4.30585 3.98417 3.64678 3.26488 - 2.79904 2.51827 2.18953 1.88202 1.52786 1.43829 - 1.41239 1.41194 1.39696 1.39281 1.39775 1.41316 - 11.81174 10.74098 9.95730 9.25646 8.62270 8.04577 - 7.52103 7.04335 6.60827 6.21102 5.84634 5.50760 - 5.18584 4.87309 4.56417 4.25040 3.91435 3.51840 - 3.01066 2.69371 2.31462 1.95492 1.53574 1.41991 - 1.35781 1.35922 1.36095 1.35744 1.34742 1.36692 - 11.74288 10.70257 9.96118 9.29384 8.68851 8.13570 - 7.63160 7.17162 6.75186 6.36813 6.01561 5.68826 - 5.37765 5.07602 4.77780 4.47322 4.14245 3.74186 - 3.20920 2.86657 2.44677 2.03911 1.55229 1.41281 - 1.33296 1.33342 1.33571 1.33175 1.31892 1.33768 - 11.69921 10.68221 9.98521 9.35700 8.78805 8.27003 - 7.79939 7.37189 6.98378 6.63093 6.30839 6.00957 - 5.72486 5.44582 5.16753 4.88149 4.57016 4.19353 - 3.67040 3.29700 2.78101 2.24119 1.59511 1.41736 - 1.32465 1.31279 1.29023 1.28899 1.28507 1.29592 - 11.63116 10.64679 9.98994 9.39638 8.85764 8.36673 - 7.92055 7.51548 7.14824 6.81516 6.51179 6.23195 - 5.96649 5.70714 5.44896 5.18302 4.89036 4.52660 - 4.00089 3.61351 3.06425 2.46524 1.68454 1.45268 - 1.31358 1.29682 1.27199 1.26983 1.26616 1.27350 - 11.50596 10.57982 9.98638 9.44575 8.95165 8.49891 - 8.08545 7.70881 7.36679 7.05695 6.77627 6.52047 - 6.28294 6.05713 5.83780 5.61421 5.36150 5.01874 - 4.47728 4.06904 3.49315 2.84403 1.89732 1.57523 - 1.30223 1.27305 1.25865 1.25410 1.23678 1.25009 - 11.48271 10.57669 10.00656 9.48457 9.00616 8.56752 - 8.16758 7.80521 7.47949 7.18817 6.92818 6.69497 - 6.48125 6.27953 6.08321 5.87881 5.64428 5.33913 - 4.86565 4.48604 3.89899 3.17478 2.04654 1.66954 - 1.32203 1.27515 1.24466 1.24125 1.23354 1.23812 - 11.46799 10.57174 10.01472 9.50521 9.03915 8.61289 - 8.22521 7.87473 7.56035 7.28039 7.03261 6.81375 - 6.61826 6.43947 6.26895 6.08857 5.87233 5.58139 - 5.12626 4.76665 4.21462 3.49417 2.21627 1.75611 - 1.33786 1.28103 1.23939 1.23328 1.22992 1.23093 - 11.45334 10.56904 10.02274 9.52270 9.06521 8.64709 - 8.26742 7.92502 7.61906 7.34810 7.11017 6.90230 - 6.71934 6.55508 6.40178 6.24202 6.04981 5.78388 - 5.35246 5.00484 4.46461 3.74168 2.38175 1.85419 - 1.35495 1.28598 1.23656 1.22909 1.22539 1.22616 - 11.43370 10.56864 10.03630 9.54821 9.10128 8.69326 - 8.32376 7.99217 7.69837 7.44106 7.21837 7.02721 - 6.86215 6.71724 6.58635 6.45489 6.29956 6.07964 - 5.70321 5.38517 4.86946 4.14221 2.66885 2.04945 - 1.39666 1.29876 1.23262 1.22696 1.21682 1.22017 - 11.44723 10.57996 10.04619 9.56020 9.11831 8.71781 - 8.35746 8.03564 7.75111 7.50259 7.28835 7.10550 - 6.94893 6.81413 6.69924 6.59779 6.48919 6.31218 - 5.95690 5.65151 5.17095 4.47694 2.93059 2.22464 - 1.43599 1.31663 1.23300 1.22361 1.21552 1.21650 - 11.41921 10.58428 10.06752 9.59384 9.16090 8.76743 - 8.41317 8.09806 7.82231 7.58493 7.38403 7.21747 - 7.08243 6.97572 6.89354 6.82422 6.74823 6.62933 - 6.37629 6.12931 5.70135 5.05748 3.48546 2.60671 - 1.53666 1.37027 1.23812 1.22375 1.20954 1.21147 - 11.40486 10.59045 10.07804 9.60902 9.18110 8.79287 - 8.44376 8.13352 7.86218 7.62951 7.43470 7.27651 - 7.15196 7.05821 6.99288 6.94668 6.90233 6.82395 - 6.63115 6.43033 6.05695 5.46044 3.89355 2.94437 - 1.64057 1.42211 1.24632 1.22603 1.20831 1.20893 - 11.36197 10.59623 10.08799 9.62321 9.19986 8.81668 - 8.47302 8.16863 7.90359 7.67779 7.49079 7.34175 - 7.22826 7.14830 7.10065 7.07757 7.06535 7.03627 - 6.92618 6.78940 6.50590 6.00533 4.49555 3.45460 - 1.84190 1.54149 1.26621 1.23130 1.20341 1.20638 - 11.32177 10.60034 10.09516 9.63180 9.20948 8.82797 - 8.48670 8.18523 7.92345 7.70125 7.51845 7.37432 - 7.26669 7.19392 7.15556 7.14528 7.15275 7.15896 - 7.10881 7.00970 6.76464 6.31095 4.93774 3.88901 - 2.01627 1.64478 1.28822 1.24403 1.20460 1.20511 - 11.31209 10.60748 10.09657 9.63146 9.20999 8.83063 - 8.49233 8.19434 7.93614 7.71735 7.53747 7.39531 - 7.28792 7.21421 7.17783 7.18120 7.21901 7.25614 - 7.22434 7.14090 6.93942 6.55043 5.26172 4.22286 - 2.18704 1.74919 1.31095 1.25309 1.20615 1.20436 - 11.27145 10.60149 10.09957 9.63881 9.21887 8.83987 - 8.50132 8.20294 7.94472 7.72645 7.54788 7.40842 - 7.30660 7.24155 7.21360 7.21759 7.24559 7.28407 - 7.29458 7.24888 7.08311 6.72287 5.51349 4.50078 - 2.34756 1.85082 1.33400 1.26327 1.20692 1.20385 - 11.24531 10.60184 10.10156 9.64226 9.22369 8.84606 - 8.50894 8.21211 7.95567 7.73944 7.56316 7.42634 - 7.32770 7.26666 7.24400 7.25537 7.29432 7.35032 - 7.39339 7.37812 7.26588 6.97492 5.88806 4.93146 - 2.64699 2.04205 1.37983 1.28284 1.21075 1.20322 - 11.22891 10.60199 10.10265 9.64429 9.22664 8.84988 - 8.51363 8.21774 7.96234 7.74733 7.57248 7.43738 - 7.34074 7.28214 7.26263 7.27849 7.32424 7.39126 - 7.45443 7.45854 7.38449 7.14666 6.15688 5.25703 - 2.91309 2.21798 1.42512 1.30315 1.21529 1.20284 - 11.20434 10.60236 10.10422 9.64709 9.23064 8.85506 - 8.52000 8.22534 7.97131 7.75787 7.58496 7.45220 - 7.35838 7.30309 7.28788 7.30981 7.36484 7.44739 - 7.53838 7.56940 7.55329 7.40494 6.59812 5.81923 - 3.46448 2.60580 1.53538 1.35638 1.22789 1.20233 - 11.19082 10.60284 10.10531 9.64865 9.23273 8.85771 - 8.52324 8.22922 7.97585 7.76318 7.59120 7.45965 - 7.36725 7.31374 7.30082 7.32591 7.38574 7.47666 - 7.58266 7.62741 7.64148 7.54715 6.87601 6.18754 - 3.89557 2.93503 1.64121 1.41131 1.24092 1.20207 - 11.17659 10.60361 10.10658 9.65031 9.23482 8.86032 - 8.52646 8.23312 7.98045 7.76855 7.59746 7.46699 - 7.37602 7.32432 7.31381 7.34214 7.40685 7.50653 - 7.62860 7.68743 7.73074 7.69635 7.21174 6.65133 - 4.53322 3.46103 1.83866 1.52167 1.26644 1.20180 - 11.16905 10.60394 10.10714 9.65110 9.23583 8.86162 - 8.52810 8.23510 7.98278 7.77125 7.60058 7.47066 - 7.38035 7.32956 7.32027 7.35027 7.41745 7.52140 - 7.65198 7.71862 7.77581 7.77168 7.40510 6.93462 - 4.98322 3.86756 2.02260 1.63078 1.29063 1.20168 - 11.18377 10.61019 10.10604 9.64699 9.23142 8.85812 - 8.52618 8.23502 7.98435 7.77407 7.60404 7.47360 - 7.38046 7.32463 7.31180 7.34813 7.43512 7.55194 - 7.67225 7.73366 7.79542 7.81353 7.53442 7.12302 - 5.31236 4.19611 2.20186 1.73841 1.31269 1.20160 - 11.18013 10.61006 10.10613 9.64722 9.23180 8.85862 - 8.52680 8.23578 7.98527 7.77515 7.60533 7.47511 - 7.38224 7.32675 7.31441 7.35141 7.43945 7.55801 - 7.68172 7.74636 7.81427 7.84482 7.61907 7.26073 - 5.57336 4.46603 2.36814 1.84527 1.33527 1.20156 - 11.15585 10.60352 10.10722 9.65184 9.23724 8.86356 - 8.53047 8.23792 7.98619 7.77533 7.60543 7.47634 - 7.38705 7.33757 7.33007 7.36267 7.43369 7.54356 - 7.68747 7.76775 7.84649 7.88675 7.72974 7.44614 - 5.95939 4.89386 2.66703 2.05243 1.38028 1.20152 - 11.15276 10.60300 10.10701 9.65196 9.23760 8.86396 - 8.53079 8.23821 7.98659 7.77599 7.60634 7.47742 - 7.38834 7.33921 7.33215 7.36522 7.43689 7.54837 - 7.69479 7.77681 7.86140 7.91582 7.80644 7.56046 - 6.23296 5.22541 2.93031 2.24023 1.42348 1.20152 - 0.62702 0.65236 0.67932 0.70798 0.73818 0.76975 - 0.80275 0.83738 0.87396 0.91298 0.95526 1.00168 - 1.05286 1.10855 1.16585 1.21715 1.25378 1.27469 - 1.28801 1.29719 1.30539 1.30853 1.30490 1.30370 - 1.30364 1.30362 1.30344 1.30341 1.30338 1.30341 - 0.87947 0.91808 0.95729 0.99736 1.03838 1.08050 - 1.12404 1.16954 1.21775 1.26894 1.32313 1.38019 - 1.43972 1.50080 1.56151 1.61802 1.66503 1.69715 - 1.70795 1.70623 1.70858 1.71492 1.71336 1.71084 - 1.71244 1.71314 1.71295 1.71274 1.71312 1.71282 - 1.12261 1.17062 1.21933 1.26903 1.31972 1.37139 - 1.42408 1.47800 1.53345 1.59066 1.64979 1.71130 - 1.77612 1.84415 1.91208 1.97203 2.01578 2.04364 - 2.05675 2.05835 2.06243 2.06775 2.06599 2.06563 - 2.06716 2.06737 2.06722 2.06729 2.06716 2.06716 - 1.56883 1.63475 1.69989 1.76464 1.82880 1.89231 - 1.95529 2.01821 2.08188 2.14643 2.21181 2.27804 - 2.34548 2.41364 2.47960 2.53732 2.58078 2.61075 - 2.62834 2.63260 2.63816 2.64471 2.65047 2.65135 - 2.65003 2.64977 2.64998 2.64998 2.65005 2.64995 - 1.96698 2.04736 2.12483 2.19987 2.27217 2.34171 - 2.40883 2.47463 2.54066 2.60708 2.67352 2.73928 - 2.80363 2.86553 2.92343 2.97535 3.01908 3.05330 - 3.07584 3.08242 3.08955 3.09761 3.11017 3.11282 - 3.10927 3.10820 3.10853 3.10882 3.10840 3.10868 - 2.32436 2.41526 2.50133 2.58311 2.66020 2.73253 - 2.80058 2.86576 2.93013 2.99387 3.05667 3.11785 - 3.17687 3.23299 3.28511 3.33220 3.37304 3.40675 - 3.43195 3.44154 3.45284 3.46515 3.48133 3.48371 - 3.47891 3.47768 3.47819 3.47857 3.47820 3.47843 - 2.64569 2.74471 2.83686 2.92280 3.00201 3.07448 - 3.14087 3.20296 3.26336 3.32242 3.37985 3.43504 - 3.48766 3.53725 3.58309 3.62483 3.66221 3.69538 - 3.72421 3.73710 3.75122 3.76512 3.78388 3.78700 - 3.78173 3.78031 3.78090 3.78133 3.78088 3.78119 - 3.19829 3.30795 3.40669 3.49543 3.57361 3.64133 - 3.69971 3.75140 3.80012 3.84652 3.89056 3.93199 - 3.97096 4.00765 4.04197 4.07443 4.10587 4.13752 - 4.17063 4.18774 4.20548 4.22105 4.24137 4.24533 - 4.24139 4.24018 4.24078 4.24118 4.24076 4.24109 - 3.65165 3.77927 3.88169 3.96321 4.02876 4.08452 - 4.13235 4.17413 4.21242 4.24734 4.27833 4.30532 - 4.32977 4.35325 4.37636 4.40043 4.42724 4.45841 - 4.49393 4.51192 4.52998 4.54535 4.56536 4.56910 - 4.56790 4.56769 4.56819 4.56827 4.56835 4.56839 - 4.53099 4.66712 4.76333 4.82701 4.86683 4.89312 - 4.90921 4.91822 4.92409 4.92673 4.92493 4.91927 - 4.91432 4.91444 4.92025 4.93143 4.94764 4.96916 - 4.99677 5.01333 5.03104 5.04432 5.05221 5.05611 - 5.06467 5.06584 5.06585 5.06581 5.06577 5.06587 - 5.18785 5.29494 5.37244 5.42387 5.44972 5.45210 - 5.43547 5.40732 5.37701 5.34720 5.31893 5.29336 - 5.27200 5.25639 5.24721 5.24449 5.24826 5.25858 - 5.27585 5.28727 5.29884 5.30551 5.30348 5.30548 - 5.32078 5.32401 5.32362 5.32294 5.32380 5.32332 - 6.10377 6.18377 6.22458 6.23237 6.20890 6.15808 - 6.08671 6.00531 5.92609 5.85295 5.78698 5.72908 - 5.68069 5.64228 5.61304 5.58924 5.56770 5.55032 - 5.54053 5.53948 5.53990 5.53636 5.51293 5.51228 - 5.53597 5.53982 5.53821 5.53856 5.53759 5.53808 - 6.76472 6.80952 6.80951 6.77338 6.70413 6.60710 - 6.49080 6.36772 6.25193 6.14755 6.05524 5.97478 - 5.90618 5.84827 5.79966 5.75576 5.71274 5.67327 - 5.64163 5.62953 5.61807 5.60479 5.57367 5.57073 - 5.59155 5.59506 5.59337 5.59366 5.59272 5.59317 - 7.29088 7.29721 7.25593 7.17793 7.06713 6.92999 - 6.77602 6.61873 6.47326 6.34353 6.22975 6.13058 - 6.04459 5.96941 5.90330 5.84150 5.78026 5.72279 - 5.67386 5.65297 5.63158 5.61107 5.58032 5.57586 - 5.58770 5.58982 5.58849 5.58865 5.58803 5.58835 - 7.90384 7.74515 7.57991 7.41815 7.25981 7.10505 - 6.95406 6.80695 6.66422 6.52670 6.39520 6.26984 - 6.15199 6.04276 5.94333 5.85541 5.78026 5.71598 - 5.66335 5.64491 5.63390 5.62421 5.56660 5.53794 - 5.55302 5.55974 5.55709 5.55513 5.55846 5.55642 - 8.58955 8.36297 8.13143 7.90666 7.68842 7.47688 - 7.27225 7.07454 6.88445 6.70324 6.53134 6.36913 - 6.21791 6.07965 5.95537 5.84691 5.75499 5.67499 - 5.60446 5.57584 5.55361 5.53455 5.46978 5.43886 - 5.44273 5.44658 5.44304 5.44147 5.44388 5.44274 - 8.94383 8.83175 8.60684 8.31588 8.00275 7.70772 - 7.43652 7.18818 6.96182 6.75651 6.56909 6.39636 - 6.23593 6.08684 5.94863 5.82072 5.70254 5.59292 - 5.48863 5.43709 5.38707 5.35252 5.33208 5.32314 - 5.29607 5.29069 5.29032 5.29125 5.28989 5.29091 - 9.84005 9.56443 9.18690 8.76069 8.33300 7.94427 - 7.59737 7.28873 7.01393 6.76577 6.53367 6.31136 - 6.10162 5.90733 5.72832 5.56110 5.40390 5.25811 - 5.12187 5.05432 4.98651 4.93591 4.89863 4.88594 - 4.86299 4.85978 4.85942 4.85948 4.85955 4.85930 - 10.49459 9.92619 9.38852 8.89159 8.43220 8.00827 - 7.61777 7.25936 6.93230 6.63429 6.36237 6.11277 - 5.88035 5.66174 5.45819 5.26914 5.09268 4.92051 - 4.74667 4.66262 4.58630 4.53164 4.46615 4.44828 - 4.44441 4.44487 4.44312 4.44277 4.44249 4.44220 - 11.00769 10.35484 9.68591 9.03605 8.43359 7.90189 - 7.43762 7.03120 6.67282 6.34927 6.04309 5.74583 - 5.46434 5.20366 4.96214 4.73505 4.51749 4.31151 - 4.11848 4.02604 3.93604 3.86496 3.78649 3.76912 - 3.76293 3.76232 3.76069 3.76039 3.76020 3.75952 - 11.38730 10.51362 9.72984 9.02635 8.39351 7.82438 - 7.31421 6.85632 6.44421 6.07244 5.73517 5.42541 - 5.13381 4.85405 4.58708 4.33532 4.09969 3.87703 - 3.66660 3.56646 3.46760 3.39053 3.31673 3.29785 - 3.28056 3.27842 3.27706 3.27684 3.27676 3.27655 - 11.58981 10.62592 9.77583 9.01806 8.34160 7.73678 - 7.19654 6.71208 6.27470 5.87848 5.51807 5.18727 - 4.87807 4.58490 4.30743 4.04564 3.79956 3.56642 - 3.34577 3.24031 3.13580 3.05432 2.97818 2.95876 - 2.93979 2.93731 2.93587 2.93565 2.93558 2.93640 - 11.72440 10.69700 9.80210 9.00703 8.30045 7.67109 - 7.10965 6.60589 6.14994 5.73578 5.35841 5.01229 - 4.69054 4.38811 4.10370 3.83561 3.58265 3.34262 - 3.11443 3.00486 2.89622 2.81109 2.72994 2.70989 - 2.69250 2.69025 2.68854 2.68837 2.68818 2.68963 - 11.88385 10.77597 9.82786 8.98859 8.24641 7.58861 - 7.00243 6.47579 5.99771 5.56220 5.16466 4.80017 - 4.46292 4.14830 3.85391 3.57625 3.31247 3.06128 - 2.82056 2.70401 2.58840 2.49709 2.40686 2.38475 - 2.36836 2.36653 2.36460 2.36425 2.36419 2.36470 - 11.97835 10.81968 9.84108 8.97737 8.21652 7.54436 - 6.94650 6.40980 5.92283 5.47931 5.07432 4.70253 - 4.35762 4.03469 3.73148 3.44477 3.17154 2.90923 - 2.65521 2.53123 2.40894 2.31247 2.21415 2.18960 - 2.17087 2.16873 2.16680 2.16655 2.16632 2.16500 - 12.06875 10.85992 9.85931 8.97871 8.20710 7.52495 - 6.91857 6.37471 5.88219 5.43417 5.02487 4.64783 - 4.29525 3.96140 3.64447 3.34217 3.05124 2.76569 - 2.48036 2.33613 2.18946 2.07060 1.95176 1.92124 - 1.89646 1.89361 1.89132 1.89096 1.89077 1.88927 - 12.06906 10.87253 9.88330 9.00543 8.23444 7.55280 - 6.94826 6.40783 5.92013 5.47649 5.06856 4.68925 - 4.33315 3.99583 3.67445 3.36475 3.06166 2.75812 - 2.44321 2.27679 2.10166 1.95540 1.81076 1.77640 - 1.74936 1.74529 1.74205 1.74170 1.74130 1.74400 - 12.01754 10.84716 9.90457 9.06950 8.32797 7.66217 - 7.06418 6.52619 6.04140 5.60301 5.20389 4.83573 - 4.48809 4.15305 3.82793 3.50904 3.18942 2.85447 - 2.48625 2.28361 2.06249 1.86768 1.66336 1.61682 - 1.59108 1.58814 1.58120 1.57964 1.58077 1.59012 - 11.96007 10.81394 9.91044 9.11153 8.39788 7.75485 - 7.17524 6.65206 6.17911 5.75014 5.35843 4.99609 - 4.65294 4.32091 3.99668 3.67519 3.34689 2.99154 - 2.58314 2.34939 2.08712 1.85020 1.59289 1.53219 - 1.50790 1.50589 1.49570 1.49316 1.49575 1.50813 - 11.90265 10.78065 9.91369 9.14645 8.45784 7.83537 - 7.27269 6.76337 6.30176 5.88209 5.49806 5.14213 - 4.80443 4.47690 4.15563 3.83453 3.50180 3.13243 - 2.69318 2.43426 2.13669 1.86307 1.55642 1.48145 - 1.45722 1.45604 1.44317 1.43979 1.44367 1.45639 - 11.85027 10.75001 9.91594 9.17558 8.50894 7.90469 - 7.35719 6.86047 6.40940 5.99855 5.62202 5.27260 - 4.94074 4.61836 4.30113 3.98210 3.64761 3.26852 - 2.80504 2.52526 2.19745 1.89078 1.53830 1.44939 - 1.42348 1.42285 1.40781 1.40376 1.40868 1.42057 - 11.75311 10.69380 9.91732 9.22230 8.59330 8.02023 - 7.49864 7.02347 6.59039 6.19477 5.83146 5.49404 - 5.17380 4.86295 4.55636 4.24530 3.91231 3.51946 - 3.01454 2.69894 2.32120 1.96268 1.54523 1.43001 - 1.36810 1.36939 1.37107 1.36768 1.35779 1.37402 - 11.68349 10.65449 9.91990 9.25815 8.65741 8.10837 - 7.60732 7.14979 6.73201 6.34984 5.99869 5.67262 - 5.36349 5.06374 4.76783 4.46601 4.13838 3.74106 - 3.21152 2.87042 2.45223 2.04601 1.56116 1.42235 - 1.34280 1.34319 1.34544 1.34159 1.32889 1.34488 - 11.64080 10.63473 9.94399 9.32088 8.75601 8.24130 - 7.77326 7.34777 6.96122 6.60955 6.28801 5.99020 - 5.70686 5.42975 5.15403 4.87115 4.56344 4.19036 - 3.67022 3.29820 2.78379 2.24573 1.60291 1.42633 - 1.33409 1.32214 1.29952 1.29836 1.29446 1.30369 - 11.57614 10.60161 9.94993 9.36063 8.82536 8.33727 - 7.89337 7.49010 7.12428 6.79232 6.48990 6.21104 - 5.94684 5.68925 5.43339 5.17036 4.88109 4.52088 - 3.99852 3.61285 3.06551 2.46859 1.69160 1.46100 - 1.32282 1.30609 1.28121 1.27910 1.27546 1.28184 - 11.46941 10.55125 9.95945 9.41854 8.92283 8.46778 - 8.05201 7.67388 7.33208 7.02404 6.74638 6.49427 - 6.26022 6.03660 5.81670 5.58732 5.32658 4.99316 - 4.49230 4.10498 3.52714 2.84916 1.87509 1.57344 - 1.31732 1.28568 1.26423 1.26123 1.25597 1.25923 - 11.44032 10.54122 9.97205 9.45000 8.97190 8.53489 - 8.13730 7.77696 7.45201 7.16067 6.90101 6.66973 - 6.46092 6.26630 6.07405 5.86775 5.62540 5.31054 - 4.84037 4.47723 3.91567 3.19267 2.04327 1.67085 - 1.33258 1.28589 1.25366 1.25021 1.24465 1.24769 - 11.42210 10.53338 9.97918 9.47203 9.00791 8.58325 - 8.19691 7.84760 7.53427 7.25531 7.00850 6.79058 - 6.59607 6.41836 6.24907 6.07013 5.85569 5.56720 - 5.11571 4.75865 4.20993 3.49297 2.22037 1.76252 - 1.34692 1.29050 1.24907 1.24298 1.23960 1.24077 - 11.40868 10.53118 9.98741 9.48947 9.03380 8.61728 - 8.23901 7.89784 7.59301 7.32309 7.08612 6.87913 - 6.69699 6.53354 6.38109 6.22244 6.03180 5.76814 - 5.34023 4.99520 4.45843 3.73929 2.38517 1.86013 - 1.36398 1.29551 1.24640 1.23893 1.23521 1.23617 - 11.39203 10.53460 10.00347 9.51523 9.06815 8.66107 - 8.29334 7.96389 7.67199 7.41594 7.19344 7.00165 - 6.83684 6.69418 6.56677 6.43803 6.28301 6.06199 - 5.68615 5.37102 4.86134 4.13972 2.66842 2.04986 - 1.40881 1.31324 1.24211 1.23468 1.22405 1.23042 - 11.40454 10.54332 10.01140 9.52712 9.08679 8.68774 - 8.32869 8.00807 7.72461 7.47704 7.26363 7.08152 - 6.92557 6.79131 6.67693 6.57599 6.46809 6.29251 - 5.94017 5.63722 5.16024 4.47064 2.93180 2.22905 - 1.44477 1.32617 1.24319 1.23382 1.22574 1.22689 - 11.37730 10.54805 10.03292 9.56071 9.12915 8.73701 - 8.38398 8.06997 7.79515 7.55856 7.35833 7.19242 - 7.05794 6.95171 6.86995 6.80099 6.72546 6.60745 - 6.35648 6.11153 5.68696 5.04773 3.48427 2.60951 - 1.54502 1.37961 1.24845 1.23417 1.22002 1.22208 - 11.36360 10.55553 10.04446 9.57596 9.14836 8.76079 - 8.41269 8.10377 7.83391 7.60273 7.40922 7.25199 - 7.12808 7.03459 6.96892 6.92133 6.87551 6.80090 - 6.61426 6.41132 6.03612 5.44558 3.89917 2.93952 - 1.64660 1.43393 1.25658 1.23716 1.21747 1.21965 - 11.33716 10.56692 10.05393 9.58684 9.16317 8.78120 - 8.43977 8.13803 7.87540 7.65141 7.46531 7.31569 - 7.19931 7.11445 7.06331 7.04580 7.05161 7.03549 - 6.91307 6.76403 6.47719 5.97533 4.48138 3.48084 - 1.84474 1.54187 1.27603 1.24504 1.21633 1.21721 - 11.29879 10.56913 10.05856 9.59375 9.17238 8.79285 - 8.45409 8.15529 7.89591 7.67557 7.49365 7.34890 - 7.23829 7.16050 7.11861 7.11401 7.13935 7.15530 - 7.08678 6.97623 6.73875 6.30125 4.91900 3.88955 - 2.02448 1.65104 1.29813 1.25413 1.21613 1.21600 - 11.27041 10.56997 10.06097 9.59758 9.17765 8.79968 - 8.46261 8.16568 7.90838 7.69034 7.51107 7.36939 - 7.26236 7.18888 7.15263 7.15600 7.19369 7.23075 - 7.19926 7.11640 6.91638 6.53029 5.25072 4.21809 - 2.19203 1.75639 1.32095 1.26359 1.21687 1.21529 - 11.22944 10.56419 10.06435 9.60509 9.18641 8.80867 - 8.47141 8.17421 7.91695 7.69947 7.52151 7.38255 - 7.28107 7.21617 7.18824 7.19217 7.22011 7.25858 - 7.26922 7.22385 7.05907 6.70134 5.50109 4.49431 - 2.35166 1.85757 1.34387 1.27371 1.21763 1.21481 - 11.20375 10.56435 10.06614 9.60845 9.19126 8.81493 - 8.47902 8.18332 7.92780 7.71235 7.53671 7.40039 - 7.30209 7.24115 7.21842 7.22968 7.26857 7.32451 - 7.36754 7.35243 7.24083 6.95174 5.87299 4.92238 - 2.64960 2.04795 1.38943 1.29314 1.22143 1.21422 - 11.18776 10.56449 10.06716 9.61048 9.19428 8.81882 - 8.48373 8.18886 7.93434 7.72010 7.54589 7.41129 - 7.31499 7.25649 7.23692 7.25266 7.29832 7.36523 - 7.42827 7.43246 7.35884 7.12246 6.13983 5.24589 - 2.91434 2.22309 1.43446 1.31330 1.22595 1.21386 - 11.16373 10.56476 10.06866 9.61325 9.19834 8.82403 - 8.49005 8.19634 7.94312 7.73043 7.55813 7.42589 - 7.33238 7.27723 7.26198 7.28378 7.33870 7.42104 - 7.51179 7.54277 7.52685 7.37934 6.57780 5.80437 - 3.46302 2.60917 1.54410 1.36612 1.23848 1.21338 - 11.15030 10.56524 10.06967 9.61475 9.20034 8.82661 - 8.49327 8.20021 7.94769 7.73574 7.56434 7.43323 - 7.34113 7.28774 7.27481 7.29979 7.35948 7.45016 - 7.55580 7.60049 7.61464 7.52085 6.85375 6.17019 - 3.89204 2.93687 1.64935 1.42062 1.25146 1.21314 - 11.13607 10.56601 10.07094 9.61633 9.20228 8.82911 - 8.49646 8.20417 7.95239 7.74117 7.57063 7.44056 - 7.34982 7.29826 7.28774 7.31599 7.38049 7.47985 - 7.60145 7.66011 7.70340 7.66932 7.18733 6.63089 - 4.52655 3.46030 1.84571 1.53020 1.27690 1.21289 - 11.12853 10.56635 10.07157 9.61712 9.20327 8.83037 - 8.49808 8.20618 7.95476 7.74391 7.57378 7.44423 - 7.35418 7.30351 7.29422 7.32411 7.39106 7.49465 - 7.62469 7.69111 7.74825 7.74431 7.37951 6.91234 - 4.97420 3.86467 2.02867 1.63861 1.30099 1.21277 - 11.14362 10.57250 10.07025 9.61294 9.19890 8.82697 - 8.49624 8.20612 7.95631 7.74674 7.57727 7.44721 - 7.35433 7.29864 7.28581 7.32197 7.40862 7.52499 - 7.64489 7.70612 7.76777 7.78595 7.50825 7.09955 - 5.30141 4.19137 2.20683 1.74559 1.32295 1.21270 - 11.14023 10.57257 10.07042 9.61321 9.19931 8.82748 - 8.49686 8.20687 7.95721 7.74783 7.57855 7.44873 - 7.35614 7.30081 7.28845 7.32527 7.41296 7.53106 - 7.65432 7.71876 7.78650 7.81699 7.59232 7.23634 - 5.56075 4.45958 2.37215 1.85188 1.34537 1.21266 - 11.11601 10.56643 10.07207 9.61813 9.20477 8.83229 - 8.50036 8.20888 7.95803 7.74793 7.57860 7.44991 - 7.36090 7.31159 7.30414 7.33657 7.40720 7.51660 - 7.66001 7.74002 7.81854 7.85877 7.70253 7.42063 - 5.94427 4.88472 2.66936 2.05787 1.39014 1.21262 - 11.11316 10.56621 10.07211 9.61841 9.20517 8.83263 - 8.50058 8.20906 7.95838 7.74857 7.57952 7.45100 - 7.36217 7.31318 7.30611 7.33902 7.41034 7.52136 - 7.66727 7.74901 7.83332 7.88764 7.77888 7.53426 - 6.21600 5.21426 2.93133 2.24479 1.43294 1.21261 - 0.61330 0.63927 0.66627 0.69451 0.72409 0.75513 - 0.78780 0.82234 0.85907 0.89830 0.94043 0.98608 - 1.03614 1.09067 1.14676 1.19677 1.23276 1.25686 - 1.27272 1.27804 1.28510 1.29105 1.28716 1.28554 - 1.28577 1.28583 1.28559 1.28564 1.28551 1.28558 - 0.87035 0.90568 0.94250 0.98115 1.02172 1.06428 - 1.10889 1.15560 1.20442 1.25532 1.30815 1.36269 - 1.41852 1.47498 1.53103 1.58503 1.63459 1.67637 - 1.70245 1.70375 1.69209 1.67492 1.68345 1.69750 - 1.69569 1.69310 1.69313 1.69371 1.69191 1.69317 - 1.11534 1.15861 1.20343 1.25023 1.29908 1.35000 - 1.40303 1.45811 1.51518 1.57412 1.63463 1.69627 - 1.75841 1.82009 1.87993 1.93593 1.98552 2.02599 - 2.05035 2.05084 2.03878 2.02253 2.03705 2.05383 - 2.04928 2.04583 2.04631 2.04716 2.04505 2.04646 - 1.56410 1.61959 1.67643 1.73528 1.79612 1.85890 - 1.92351 1.98978 2.05746 2.12619 2.19547 2.26450 - 2.33224 2.39729 2.45781 2.51147 2.55587 2.59044 - 2.61167 2.61306 2.60517 2.59625 2.62378 2.64351 - 2.63164 2.62647 2.62797 2.62934 2.62681 2.62840 - 1.95397 2.02426 2.09460 2.16571 2.23727 2.30895 - 2.38029 2.45085 2.52012 2.58762 2.65305 2.71616 - 2.77737 2.83679 2.89317 2.94484 2.98989 3.02736 - 3.05486 3.06342 3.06950 3.07386 3.08590 3.09105 - 3.08821 3.08680 3.08692 3.08727 3.08652 3.08708 - 2.29302 2.38331 2.46913 2.55106 2.62868 2.70184 - 2.77093 2.83718 2.90240 2.96672 3.02983 3.09112 - 3.15022 3.20655 3.25905 3.30669 3.34826 3.38278 - 3.40875 3.41872 3.43039 3.44307 3.46000 3.46256 - 3.45766 3.45638 3.45691 3.45729 3.45691 3.45716 - 2.61772 2.70481 2.78980 2.87352 2.95533 3.03450 - 3.11025 3.18178 3.24834 3.30933 3.36475 3.41498 - 3.46200 3.50746 3.55087 3.59157 3.62936 3.66619 - 3.70329 3.72023 3.73347 3.74187 3.76115 3.76829 - 3.76105 3.75909 3.76011 3.76034 3.76068 3.76046 - 3.16280 3.25756 3.34800 3.43520 3.51830 3.59631 - 3.66830 3.73332 3.79055 3.83954 3.88065 3.91507 - 3.94617 3.97700 4.00779 4.03880 4.07106 4.10787 - 4.15186 4.17414 4.19040 4.19853 4.21938 4.22821 - 4.22205 4.22016 4.22123 4.22144 4.22186 4.22161 - 3.62037 3.71695 3.80718 3.89243 3.97166 4.04383 - 4.10790 4.16292 4.20817 4.24337 4.26931 4.28802 - 4.30400 4.32150 4.34138 4.36458 4.39278 4.42916 - 4.47608 4.50061 4.51765 4.52449 4.54375 4.55307 - 4.55029 4.54900 4.54988 4.55000 4.55048 4.55023 - 4.47998 4.60270 4.70208 4.78018 4.83664 4.87251 - 4.89066 4.89662 4.89772 4.89602 4.89267 4.88931 - 4.88853 4.89270 4.90180 4.91447 4.92986 4.95035 - 4.97923 4.99712 5.01557 5.02876 5.03698 5.04065 - 5.04970 5.05100 5.05087 5.05100 5.05080 5.05097 - 5.13738 5.25007 5.33258 5.38827 5.41754 5.42256 - 5.40784 5.38109 5.35200 5.32329 5.29603 5.27144 - 5.25112 5.23670 5.22882 5.22745 5.23247 5.24389 - 5.26201 5.27383 5.28596 5.29315 5.29107 5.29305 - 5.30881 5.31216 5.31175 5.31105 5.31196 5.31146 - 6.07944 6.16082 6.20248 6.21054 6.18688 6.13558 - 6.06368 5.98207 5.90336 5.83146 5.76731 5.71154 - 5.66512 5.62815 5.59995 5.57713 5.55682 5.54075 - 5.53207 5.53150 5.53244 5.52931 5.50611 5.50555 - 5.52942 5.53331 5.53170 5.53204 5.53107 5.53158 - 6.77880 6.79645 6.78090 6.74004 6.67522 6.58907 - 6.48607 6.37304 6.25800 6.14534 6.03903 5.94434 - 5.87058 5.82244 5.79280 5.76154 5.71326 5.66540 - 5.63639 5.62676 5.61574 5.60100 5.57188 5.57079 - 5.58855 5.59209 5.59185 5.59113 5.59208 5.59123 - 7.46804 7.34453 7.21433 7.08629 6.96043 6.83685 - 6.71574 6.59730 6.48177 6.36989 6.26249 6.15965 - 6.06267 5.97227 5.88964 5.81643 5.75408 5.70201 - 5.66240 5.65084 5.64689 5.64276 5.58992 5.56307 - 5.58506 5.59343 5.59123 5.58905 5.59286 5.59034 - 7.90472 7.74392 7.57686 7.41349 7.25374 7.09783 - 6.94591 6.79813 6.65500 6.51738 6.38609 6.26129 - 6.14439 6.03656 5.93901 5.85349 5.78117 5.71974 - 5.66929 5.65142 5.64033 5.62990 5.57128 5.54260 - 5.55853 5.56537 5.56256 5.56055 5.56387 5.56187 - 8.58167 8.35533 8.12419 7.89987 7.68214 7.47117 - 7.26717 7.07020 6.88091 6.70059 6.52968 6.36857 - 6.21859 6.08173 5.95903 5.85232 5.76232 5.68424 - 5.61532 5.58724 5.56523 5.54596 5.48068 5.44967 - 5.45399 5.45792 5.45432 5.45274 5.45514 5.45398 - 8.92442 8.81570 8.59365 8.30510 7.99430 7.70177 - 7.43315 7.18730 6.96312 6.75963 6.57379 6.40247 - 6.24333 6.09543 5.95839 5.83166 5.71472 5.60641 - 5.50342 5.45247 5.40287 5.36844 5.34787 5.33888 - 5.31196 5.30662 5.30624 5.30717 5.30580 5.30680 - 9.81629 9.52053 9.14673 8.73784 8.32880 7.95019 - 7.60623 7.29718 7.02259 6.77578 6.54568 6.32551 - 6.11763 5.92465 5.74655 5.58025 5.42426 5.27979 - 5.14470 5.07761 5.01015 4.95973 4.92254 4.90984 - 4.88696 4.88376 4.88341 4.88346 4.88352 4.88330 - 10.44549 9.89024 9.36401 8.87681 8.42568 8.00861 - 7.62376 7.26989 6.94637 6.65103 6.38103 6.13281 - 5.90145 5.68380 5.48110 5.29287 5.11728 4.94626 - 4.77395 4.69062 4.61457 4.55972 4.49467 4.47718 - 4.47314 4.47354 4.47183 4.47147 4.47121 4.47097 - 10.99376 10.31851 9.65311 9.02077 8.43719 7.91628 - 7.45592 7.04983 6.69136 6.36823 6.06339 5.76826 - 5.48891 5.22984 4.98948 4.76345 4.54706 4.34219 - 4.14985 4.05745 3.96752 3.89668 3.81891 3.80175 - 3.79565 3.79503 3.79343 3.79313 3.79294 3.79233 - 11.34170 10.51989 9.74893 9.03708 8.39240 7.82111 - 7.31722 6.87000 6.46872 6.10458 5.76790 5.45201 - 5.15515 4.87604 4.61364 4.36591 4.13089 3.90865 - 3.69924 3.59834 3.49931 3.42292 3.34942 3.33065 - 3.31363 3.31141 3.31010 3.30993 3.30982 3.30963 - 11.57608 10.62263 9.78014 9.02786 8.35527 7.75305 - 7.21456 6.73136 6.29509 5.89997 5.54069 5.21110 - 4.90323 4.61147 4.33543 4.07491 3.82976 3.59733 - 3.37719 3.27187 3.16735 3.08579 3.00980 2.99045 - 2.97160 2.96914 2.96770 2.96749 2.96741 2.96815 - 11.71196 10.69608 9.80938 9.02023 8.31768 7.69086 - 7.13078 6.62754 6.17157 5.75710 5.37943 5.03344 - 4.71271 4.41239 4.13061 3.86454 3.61229 3.37243 - 3.14461 3.03529 2.92684 2.84164 2.75992 2.73985 - 2.72271 2.72050 2.71873 2.71850 2.71832 2.71968 - 11.87840 10.78002 9.83785 9.00212 8.26173 7.60458 - 7.01845 6.49182 6.01425 5.57973 5.18353 4.82061 - 4.48493 4.17171 3.87856 3.60196 3.33900 3.08841 - 2.84810 2.73165 2.61602 2.52456 2.43401 2.41180 - 2.39532 2.39349 2.39155 2.39120 2.39114 2.39162 - 11.97308 10.82086 9.84616 8.98516 8.22606 7.55502 - 6.95797 6.42210 5.93620 5.49402 5.09054 4.72033 - 4.37692 4.05532 3.75330 3.46767 3.19541 2.93381 - 2.68008 2.55611 2.43377 2.33719 2.23862 2.21397 - 2.19514 2.19299 2.19104 2.19079 2.19056 2.18941 - 12.05391 10.84779 9.84949 8.97181 8.20335 7.52444 - 6.92115 6.38002 5.88961 5.44319 5.03515 4.65926 - 4.30797 3.97564 3.66039 3.35969 3.07006 2.78535 - 2.50023 2.35591 2.20912 2.09016 1.97109 1.94052 - 1.91568 1.91282 1.91052 1.91016 1.90996 1.90854 - 12.04819 10.83920 9.85226 8.98519 8.22647 7.55350 - 6.95367 6.41431 5.92458 5.47803 5.06930 4.69239 - 4.34006 4.00642 3.68810 3.38016 3.07706 2.77246 - 2.45852 2.29419 2.11917 1.97120 1.82668 1.79233 - 1.76468 1.76116 1.75786 1.75737 1.75711 1.75928 - 11.95682 10.80231 9.87127 9.04535 8.31090 7.65061 - 7.05677 6.52183 6.03923 5.60235 5.20426 4.83695 - 4.49026 4.15649 3.83298 3.51597 3.19843 2.86544 - 2.49869 2.29643 2.07534 1.88019 1.67522 1.62845 - 1.60260 1.59965 1.59273 1.59120 1.59232 1.60034 - 11.88134 10.75600 9.86763 9.08053 8.37595 7.73976 - 7.16512 6.64534 6.17456 5.74676 5.35560 4.99350 - 4.65079 4.31977 3.99711 3.67773 3.35193 2.99913 - 2.59282 2.35977 2.09778 1.86068 1.60282 1.54185 - 1.51724 1.51519 1.50507 1.50258 1.50515 1.51584 - 11.81205 10.71395 9.86446 9.11080 8.43259 7.81791 - 7.26078 6.75513 6.29567 5.87696 5.49308 5.13694 - 4.79931 4.47256 4.15280 3.83391 3.50399 3.13758 - 2.70092 2.44298 2.14596 1.87236 1.56541 1.49022 - 1.46548 1.46422 1.45144 1.44814 1.45199 1.46306 - 11.75176 10.67740 9.86225 9.13666 8.48133 7.88552 - 7.34396 6.85112 6.40219 5.99215 5.61550 5.26556 - 4.93347 4.61166 4.29588 3.97910 3.64760 3.27178 - 2.81129 2.53273 2.20572 1.89931 1.54683 1.45775 - 1.43120 1.43046 1.41553 1.41157 1.41646 1.42688 - 11.64605 10.61458 9.85835 9.17925 8.56249 7.99856 - 7.48339 7.01236 6.58148 6.18652 5.82280 5.48447 - 5.16361 4.85306 4.54770 4.23887 3.90901 3.51979 - 3.01852 2.70458 2.32819 1.97041 1.55331 1.43800 - 1.37552 1.37664 1.37830 1.37503 1.36538 1.38039 - 11.57347 10.57268 9.85857 9.21301 8.62476 8.08510 - 7.59062 7.13732 6.72174 6.34018 5.98847 5.66128 - 5.35133 5.05168 4.75689 4.45722 4.13277 3.73930 - 3.21380 2.87466 2.45823 2.05312 1.56906 1.43027 - 1.35023 1.35045 1.35265 1.34892 1.33650 1.35163 - 11.53247 10.55392 9.88276 9.27516 8.72226 8.21646 - 7.75461 7.33299 6.94830 6.59689 6.27444 5.97518 - 5.69077 5.41370 5.13920 4.85880 4.55474 4.18598 - 3.67017 3.30012 2.78726 2.25047 1.61040 1.43464 - 1.34175 1.32969 1.30725 1.30609 1.30241 1.31135 - 11.47720 10.52670 9.89185 9.31597 8.79114 8.31091 - 7.87257 7.47284 7.10883 6.77727 6.47418 6.19416 - 5.92908 5.67154 5.41675 5.15593 4.87001 4.51399 - 3.99623 3.61280 3.06737 2.47214 1.69856 1.46902 - 1.33090 1.31416 1.28940 1.28731 1.28385 1.29014 - 11.37705 10.47634 9.89786 9.36950 8.88535 8.44056 - 8.03321 7.66107 7.32216 7.01425 6.73463 6.47947 - 6.24277 6.01858 5.80181 5.58189 5.33420 4.99788 - 4.46463 4.06149 3.49172 2.84863 1.90973 1.58989 - 1.31954 1.29094 1.27711 1.27260 1.25517 1.26836 - 11.36871 10.47762 9.91622 9.40375 8.93528 8.50643 - 8.11544 7.76027 7.43907 7.14977 6.88978 6.65531 - 6.44021 6.23861 6.04609 5.85305 5.63600 5.33474 - 4.83518 4.43978 3.85592 3.16317 2.08137 1.69346 - 1.33784 1.29237 1.26461 1.25986 1.24537 1.25731 - 11.36729 10.48899 9.94015 9.43727 8.97644 8.55432 - 8.16987 7.82196 7.50970 7.23154 6.98537 6.76802 - 6.57419 6.39741 6.22927 6.05171 5.83891 5.55281 - 5.10512 4.75070 4.20527 3.49167 2.22435 1.76894 - 1.35603 1.29998 1.25876 1.25271 1.24936 1.25069 - 11.36180 10.49199 9.95143 9.45614 9.00263 8.58791 - 8.21108 7.87113 7.56737 7.29838 7.06224 6.85604 - 6.67469 6.51207 6.36058 6.20300 6.01375 5.75223 - 5.32795 4.98558 4.45232 3.73682 2.38839 1.86612 - 1.37313 1.30513 1.25631 1.24888 1.24518 1.24631 - 11.35213 10.49792 9.96847 9.48315 9.03887 8.63343 - 8.26635 7.93709 7.64545 7.39018 7.16932 6.97985 - 6.81628 6.67268 6.54304 6.41305 6.25987 6.04357 - 5.67365 5.36067 4.85201 4.13294 2.67336 2.06000 - 1.41462 1.31797 1.25286 1.24726 1.23717 1.24085 - 11.36852 10.51125 9.97962 9.49579 9.05602 8.65768 - 8.29940 7.97962 7.69711 7.45052 7.23811 7.05699 - 6.90195 6.76849 6.65477 6.55447 6.44733 6.27302 - 5.92332 5.62272 5.14944 4.46454 2.93327 2.23367 - 1.45372 1.33587 1.25354 1.24420 1.23617 1.23749 - 11.34215 10.51279 9.99656 9.52539 9.09626 8.70718 - 8.35715 8.04512 7.77042 7.53261 7.33108 7.16470 - 7.03092 6.92662 6.84750 6.78060 6.70509 6.58444 - 6.33140 6.09062 5.67887 5.04773 3.47315 2.61028 - 1.55708 1.39128 1.25862 1.24439 1.22817 1.23293 - 11.32201 10.51907 10.00948 9.54222 9.11583 8.72956 - 8.38294 8.07560 7.80745 7.57763 7.38456 7.22663 - 7.10197 7.00852 6.94388 6.89833 6.85486 6.77932 - 6.58691 6.38463 6.02347 5.44951 3.89049 2.93052 - 1.65855 1.44764 1.26701 1.24604 1.22605 1.23062 - 11.27678 10.52127 10.01701 9.55577 9.13554 8.75513 - 8.41389 8.11162 7.84837 7.62407 7.43829 7.29022 - 7.17750 7.09815 7.05095 7.02822 7.01634 6.98783 - 6.87937 6.74470 6.46581 5.97304 4.48267 3.45302 - 1.85577 1.55825 1.28689 1.25270 1.22486 1.22831 - 11.23755 10.52488 10.02367 9.56411 9.14517 8.76645 - 8.42748 8.12799 7.86805 7.64749 7.46593 7.32262 - 7.21560 7.14337 7.10547 7.09545 7.10295 7.10927 - 7.06007 6.96243 6.72089 6.27349 4.91854 3.88252 - 2.02803 1.66040 1.30867 1.26535 1.22626 1.22716 - 11.20865 10.52593 10.02659 9.56838 9.15067 8.77341 - 8.43614 8.13855 7.88067 7.66232 7.48326 7.34287 - 7.23939 7.17166 7.13972 7.13793 7.15743 7.18258 - 7.16849 7.10120 6.90285 6.50471 5.23617 4.21439 - 2.19612 1.76409 1.33118 1.27487 1.22715 1.22649 - 11.18874 10.52665 10.02854 9.57123 9.15434 8.77808 - 8.44196 8.14567 7.88919 7.67236 7.49504 7.35666 - 7.25562 7.19098 7.16308 7.16697 7.19483 7.23322 - 7.24395 7.19899 7.03542 6.67936 5.48582 4.48742 - 2.35587 1.86434 1.35390 1.28439 1.22858 1.22604 - 11.16359 10.52731 10.03087 9.57482 9.15913 8.78412 - 8.44938 8.15466 7.89997 7.68520 7.51016 7.37438 - 7.27650 7.21581 7.19314 7.20431 7.24303 7.29879 - 7.34182 7.32693 7.21604 6.92848 5.85697 4.91317 - 2.65221 2.05385 1.39919 1.30367 1.23237 1.22547 - 11.14782 10.52775 10.03221 9.57698 9.16208 8.78787 - 8.45395 8.16012 7.90649 7.69296 7.51935 7.38522 - 7.28930 7.23103 7.21153 7.22718 7.27260 7.33927 - 7.40227 7.40655 7.33328 7.09856 6.12397 5.23495 - 2.91558 2.22825 1.44396 1.32366 1.23687 1.22513 - 11.12401 10.52823 10.03388 9.57987 9.16613 8.79300 - 8.46015 8.16751 7.91525 7.70335 7.53164 7.39975 - 7.30649 7.25155 7.23641 7.25815 7.31278 7.39478 - 7.48537 7.51633 7.50040 7.35439 6.56056 5.79006 - 3.46149 2.61263 1.55297 1.37601 1.24934 1.22467 - 11.11066 10.52851 10.03473 9.58128 9.16815 8.79564 - 8.46340 8.17139 7.91977 7.70859 7.53778 7.40705 - 7.31521 7.26203 7.24920 7.27408 7.33345 7.42374 - 7.52911 7.57371 7.58792 7.49485 6.83231 6.15299 - 3.88851 2.93875 1.65758 1.43007 1.26225 1.22443 - 11.09663 10.52888 10.03559 9.58268 9.17015 8.79831 - 8.46677 8.17542 7.92443 7.71389 7.54391 7.41431 - 7.32392 7.27255 7.26208 7.29018 7.35437 7.45330 - 7.57445 7.63301 7.67651 7.64200 7.15985 6.60984 - 4.52007 3.45954 1.85278 1.53883 1.28755 1.22419 - 11.08930 10.52912 10.03604 9.58331 9.17107 8.79957 - 8.46844 8.17748 7.92682 7.71659 7.54700 7.41793 - 7.32825 7.27777 7.26849 7.29822 7.36486 7.46802 - 7.59760 7.66382 7.72097 7.71686 7.35253 6.88977 - 4.96519 3.86173 2.03475 1.64651 1.31153 1.22407 - 11.10415 10.53527 10.03491 9.57924 9.16669 8.79608 - 8.46649 8.17735 7.92839 7.71951 7.55058 7.42092 - 7.32833 7.27281 7.26000 7.29603 7.38235 7.49822 - 7.61748 7.67851 7.74044 7.75943 7.48388 7.07752 - 5.29030 4.18641 2.21186 1.75286 1.33336 1.22401 - 11.10081 10.53534 10.03512 9.57954 9.16710 8.79659 - 8.46712 8.17810 7.92928 7.72055 7.55181 7.42237 - 7.33006 7.27490 7.26261 7.29934 7.38670 7.50418 - 7.62659 7.69083 7.75928 7.79141 7.56938 7.21506 - 5.54798 4.45287 2.37623 1.85858 1.35568 1.22396 - 11.07704 10.52950 10.03685 9.58445 9.17248 8.80126 - 8.47049 8.18003 7.93006 7.72066 7.55188 7.42359 - 7.33483 7.28564 7.27815 7.31045 7.38085 7.48989 - 7.63279 7.71246 7.79041 7.83151 7.67994 7.39622 - 5.92873 4.87558 2.67185 2.06345 1.40013 1.22392 - 11.07383 10.52938 10.03718 9.58500 9.17303 8.80159 - 8.47050 8.17988 7.93011 7.72116 7.55280 7.42474 - 7.33618 7.28729 7.28021 7.31298 7.38409 7.49465 - 7.63983 7.72141 7.80606 7.85854 7.74305 7.50647 - 6.19945 5.20285 2.93233 2.24950 1.44263 1.22391 - 0.60345 0.62817 0.65443 0.68235 0.71181 0.74267 - 0.77498 0.80890 0.84471 0.88286 0.92415 0.96944 - 1.01925 1.07330 1.12889 1.17897 1.21550 1.23760 - 1.25223 1.26125 1.26916 1.27232 1.26948 1.26851 - 1.26855 1.26855 1.26840 1.26837 1.26835 1.26836 - 0.85121 0.88667 0.92448 0.96449 1.00595 1.04805 - 1.09091 1.13514 1.18161 1.23063 1.28223 1.33682 - 1.39554 1.45863 1.52308 1.58114 1.62376 1.64833 - 1.66042 1.66696 1.67288 1.67520 1.67164 1.67149 - 1.67399 1.67432 1.67414 1.67410 1.67406 1.67409 - 1.08720 1.13469 1.18277 1.23173 1.28153 1.33220 - 1.38381 1.43666 1.49112 1.54745 1.60581 1.66662 - 1.73066 1.79782 1.86492 1.92456 1.96889 1.99807 - 2.01284 2.01527 2.01987 2.02532 2.02394 2.02386 - 2.02617 2.02650 2.02633 2.02641 2.02626 2.02634 - 1.52540 1.59019 1.65430 1.71813 1.78149 1.84430 - 1.90670 1.96915 2.03241 2.09664 2.16176 2.22777 - 2.29498 2.36292 2.42877 2.48678 2.53121 2.56269 - 2.58210 2.58731 2.59366 2.60071 2.60722 2.60835 - 2.60741 2.60720 2.60742 2.60742 2.60748 2.60745 - 1.91781 1.99639 2.07245 2.14647 2.21815 2.28745 - 2.35467 2.42074 2.48707 2.55375 2.62042 2.68639 - 2.75100 2.81326 2.87166 2.92434 2.96916 3.00483 - 3.02921 3.03684 3.04500 3.05387 3.06736 3.07024 - 3.06668 3.06558 3.06593 3.06624 3.06581 3.06611 - 2.27058 2.36086 2.44518 2.52471 2.60003 2.67216 - 2.74136 2.80828 2.87394 2.93854 3.00228 3.06478 - 3.12507 3.18201 3.23446 3.28155 3.32242 3.35690 - 3.38537 3.39773 3.41019 3.42183 3.43938 3.44214 - 3.43703 3.43587 3.43631 3.43668 3.43630 3.43653 - 2.58750 2.68766 2.77832 2.86123 2.93779 3.00994 - 3.07814 3.14309 3.20583 3.26660 3.32561 3.38251 - 3.43650 3.48669 3.53254 3.57429 3.61238 3.64725 - 3.67932 3.69422 3.70924 3.72293 3.74335 3.74663 - 3.74090 3.73958 3.74009 3.74050 3.74006 3.74034 - 3.13661 3.24377 3.34097 3.42912 3.50763 3.57657 - 3.63684 3.69077 3.74161 3.78996 3.83572 3.87868 - 3.91910 3.95725 3.99306 4.02707 4.06016 4.09352 - 4.12838 4.14640 4.16516 4.18173 4.20328 4.20742 - 4.20309 4.20178 4.20242 4.20286 4.20240 4.20268 - 3.58720 3.71205 3.81332 3.89509 3.96198 4.01971 - 4.06991 4.11405 4.15432 4.19092 4.22368 4.25276 - 4.27935 4.30481 4.32976 4.35568 4.38439 4.41720 - 4.45415 4.47313 4.49227 4.50851 4.52939 4.53330 - 4.53207 4.53185 4.53237 4.53248 4.53256 4.53252 - 4.46248 4.59826 4.69526 4.76057 4.80243 4.83076 - 4.84889 4.86009 4.86845 4.87377 4.87452 4.87111 - 4.86835 4.87079 4.87903 4.89264 4.91109 4.93435 - 4.96330 4.98071 4.99944 5.01345 5.02129 5.02541 - 5.03495 5.03625 5.03624 5.03619 5.03614 5.03625 - 5.10429 5.24089 5.32543 5.36829 5.38154 5.37916 - 5.36608 5.34683 5.32677 5.30569 5.28121 5.25369 - 5.22964 5.21483 5.20957 5.21178 5.21911 5.23041 - 5.24679 5.25891 5.27318 5.28226 5.27662 5.28001 - 5.29768 5.30017 5.29968 5.29950 5.29933 5.29956 - 6.01771 6.14175 6.19208 6.18597 6.14311 6.08504 - 6.01879 5.95003 5.88482 5.82344 5.76320 5.70390 - 5.65164 5.61109 5.58217 5.56172 5.54617 5.53339 - 5.52369 5.52244 5.52399 5.52205 5.49780 5.49871 - 5.52267 5.52616 5.52510 5.52478 5.52450 5.52482 - 6.67680 6.77814 6.78980 6.73558 6.64189 6.53646 - 6.42731 6.31987 6.21980 6.12761 6.04120 5.95970 - 5.88721 5.82630 5.77669 5.73546 5.69924 5.66586 - 5.63453 5.62135 5.61075 5.59976 5.56832 5.56680 - 5.58739 5.59045 5.58929 5.58894 5.58868 5.58897 - 7.20236 7.27543 7.24725 7.14752 7.00830 6.86215 - 6.71732 6.57822 6.44958 6.33197 6.22398 6.12430 - 6.03472 5.95602 5.88787 5.82804 5.77393 5.72363 - 5.67543 5.65273 5.63192 5.61417 5.58350 5.57995 - 5.59148 5.59326 5.59231 5.59204 5.59185 5.59204 - 7.64491 7.68644 7.61850 7.47602 7.29570 7.11388 - 6.93853 6.77261 6.61963 6.48018 6.35334 6.23750 - 6.13244 6.03761 5.95268 5.87622 5.80657 5.74226 - 5.68079 5.65061 5.62137 5.59861 5.57302 5.56780 - 5.56777 5.56785 5.56727 5.56716 5.56707 5.56712 - 8.54334 8.32233 8.09631 7.87680 7.66353 7.45671 - 7.25653 7.06305 6.87694 6.69942 6.53097 6.37194 - 6.22366 6.08806 5.96617 5.85981 5.76979 5.69160 - 5.62298 5.59536 5.57417 5.55600 5.49236 5.46170 - 5.46543 5.46922 5.46577 5.46424 5.46662 5.46527 - 8.90012 8.79807 8.58060 8.29500 7.98637 7.69598 - 7.42961 7.18601 6.96393 6.76243 6.57838 6.40865 - 6.25093 6.10431 5.96838 5.84262 5.72655 5.61914 - 5.51718 5.46682 5.41785 5.38395 5.36385 5.35502 - 5.32826 5.32295 5.32260 5.32354 5.32218 5.32294 - 9.81067 9.53920 9.16720 8.74742 8.32694 7.94591 - 7.60655 7.30416 7.03337 6.78771 6.55819 6.33930 - 6.13299 5.94147 5.76464 5.59937 5.44417 5.30052 - 5.16658 5.10019 5.03346 4.98363 4.94693 4.93435 - 4.91158 4.90841 4.90805 4.90811 4.90817 4.90796 - 10.46430 9.90576 9.37708 8.88816 8.43599 8.01853 - 7.63388 7.28073 6.95839 6.66464 6.39652 6.15038 - 5.92106 5.70520 5.50403 5.31707 5.14249 4.97223 - 4.80051 4.71757 4.64230 4.58846 4.52402 4.50644 - 4.50244 4.50287 4.50116 4.50080 4.50051 4.50067 - 10.99676 10.33830 9.67462 9.03624 8.44660 7.92521 - 7.46841 7.06690 6.71114 6.38902 6.08470 5.79042 - 5.51220 5.25445 5.01563 4.79118 4.57629 4.37256 - 4.18099 4.08907 3.99966 3.92926 3.85192 3.83488 - 3.82886 3.82826 3.82667 3.82637 3.82617 3.82622 - 11.34164 10.52839 9.76055 9.04905 8.40439 7.83457 - 7.33313 6.88852 6.48926 6.12650 5.79079 5.47571 - 5.17978 4.90189 4.64099 4.39488 4.16143 3.94033 - 3.73152 3.63092 3.53222 3.45612 3.38283 3.36413 - 3.34725 3.34506 3.34374 3.34357 3.34347 3.34341 - 11.57129 10.62338 9.78530 9.03673 8.36724 7.76766 - 7.23137 6.75001 6.31530 5.92154 5.56346 5.23501 - 4.92830 4.63779 4.36306 4.10390 3.86010 3.62872 - 3.40912 3.30393 3.19963 3.11832 3.04236 3.02300 - 3.00422 3.00177 3.00032 3.00011 3.00004 2.99998 - 11.70128 10.69279 9.81167 9.02708 8.32818 7.70431 - 7.14663 6.64535 6.19105 5.77805 5.40170 5.05695 - 4.73745 4.43837 4.15782 3.89296 3.64177 3.40273 - 3.17542 3.06627 2.95797 2.87286 2.79110 2.77099 - 2.75379 2.75156 2.74979 2.74959 2.74939 2.74942 - 11.86002 10.77122 9.83603 9.00570 8.26943 7.61539 - 7.03168 6.50702 6.03117 5.59822 5.20348 4.84194 - 4.50758 4.19561 3.90366 3.62808 3.36593 3.11591 - 2.87592 2.75957 2.64404 2.55264 2.46192 2.43959 - 2.42299 2.42113 2.41918 2.41885 2.41879 2.41864 - 11.94730 10.80689 9.84079 8.98641 8.23223 7.56480 - 6.97032 6.43620 5.95150 5.51013 5.10730 4.73784 - 4.39562 4.07571 3.77548 3.49103 3.21902 2.95774 - 2.70514 2.58168 2.45899 2.36165 2.26346 2.23857 - 2.21959 2.21752 2.21560 2.21527 2.21515 2.21490 - 12.03208 10.83492 9.84255 8.96923 8.20384 7.52714 - 6.92547 6.38568 5.89660 5.45152 5.04489 4.67048 - 4.32075 3.99006 3.67639 3.37700 3.08826 2.80418 - 2.51949 2.37530 2.22854 2.10953 1.99045 1.95988 - 1.93507 1.93221 1.92992 1.92955 1.92935 1.92905 - 12.03245 10.82914 9.84546 8.98078 8.22372 7.55200 - 6.95318 6.41479 5.92614 5.48083 5.07346 4.69807 - 4.34740 4.01553 3.69905 3.39288 3.09137 2.78797 - 2.47464 2.31040 2.13540 1.98745 1.84325 1.80904 - 1.78143 1.77790 1.77462 1.77415 1.77387 1.77491 - 11.95373 10.79864 9.86601 9.03890 8.30368 7.64308 - 7.04936 6.51490 6.03309 5.59733 5.20063 4.83495 - 4.49010 4.15835 3.83701 3.52232 3.20710 2.87617 - 2.51088 2.30908 2.08827 1.89334 1.68923 1.64288 - 1.61690 1.61387 1.60697 1.60547 1.60652 1.61455 - 11.88675 10.75732 9.86432 9.07358 8.36637 7.72848 - 7.15298 6.63306 6.16276 5.73600 5.34634 4.98614 - 4.64562 4.31699 3.99691 3.68026 3.35726 3.00697 - 2.60255 2.37016 2.10871 1.87214 1.61578 1.55544 - 1.53050 1.52833 1.51824 1.51573 1.51822 1.53167 - 11.82300 10.71853 9.86223 9.10327 8.42115 7.80386 - 7.24523 6.73906 6.27992 5.86226 5.48005 5.12607 - 4.79089 4.46680 4.14985 3.83393 3.50702 3.14337 - 2.70886 2.45177 2.15552 1.88272 1.57775 1.50333 - 1.47825 1.47686 1.46411 1.46078 1.46453 1.47932 - 11.76612 10.68376 9.86044 9.12841 8.46834 7.86928 - 7.32581 6.83223 6.38356 5.97464 5.59982 5.25224 - 4.92282 4.60385 4.29103 3.97733 3.64895 3.27601 - 2.81786 2.54028 2.21425 1.90887 1.55872 1.47053 - 1.44371 1.44285 1.42797 1.42398 1.42875 1.44287 - 11.68626 10.63964 9.86821 9.17634 8.54911 7.97693 - 7.45561 6.98046 6.54747 6.15235 5.79034 5.45560 - 5.14026 4.83682 4.53914 4.23649 3.91143 3.53181 - 3.04500 2.73208 2.34091 1.96152 1.54566 1.44987 - 1.39974 1.39510 1.38336 1.38083 1.38537 1.39535 - 11.61492 10.59904 9.86901 9.20955 8.60952 8.06030 - 7.55864 7.10070 6.68327 6.30242 5.95363 5.63121 - 5.32723 5.03415 4.74560 4.45033 4.12954 3.74755 - 3.24246 2.90682 2.47436 2.04323 1.55700 1.44045 - 1.37541 1.36945 1.35690 1.35419 1.35817 1.36565 - 11.54261 10.55468 9.87359 9.25828 8.69975 8.19016 - 7.72621 7.30395 6.91990 6.57022 6.25037 5.95430 - 5.67323 5.39931 5.12778 4.85023 4.54893 4.18299 - 3.67020 3.30173 2.79059 2.25579 1.62020 1.44612 - 1.35380 1.34174 1.31954 1.31847 1.31456 1.32436 - 11.47773 10.52016 9.87701 9.29477 8.76538 8.28221 - 7.84236 7.44242 7.07930 6.74960 6.44913 6.17220 - 5.91029 5.65565 5.40354 5.14519 4.86170 4.50836 - 3.99389 3.61236 3.06908 2.47627 1.70751 1.47970 - 1.34282 1.32623 1.30170 1.29969 1.29601 1.30297 - 11.36856 10.47000 9.88746 9.35333 8.86238 8.41066 - 7.99725 7.62109 7.28144 6.97585 6.70088 6.45162 - 6.22049 5.99982 5.78308 5.55742 5.30124 4.97352 - 4.48002 4.09745 3.52548 2.85373 1.88880 1.59014 - 1.33747 1.30647 1.28544 1.28246 1.27733 1.28115 - 11.33908 10.45819 9.89900 9.38536 8.91328 8.47947 - 8.08331 7.72417 7.40168 7.11373 6.85721 6.62759 - 6.41753 6.21963 6.02747 5.82798 5.59956 5.30233 - 4.83975 4.46750 3.88985 3.17591 2.06343 1.69194 - 1.35106 1.30541 1.27583 1.27245 1.26482 1.26992 - 11.33047 10.45687 9.90870 9.40630 8.94587 8.52416 - 8.14022 7.79312 7.48209 7.20552 6.96113 6.74558 - 6.55317 6.37723 6.20966 6.03297 5.82194 5.53852 - 5.09467 4.74287 4.20083 3.49086 2.22948 1.77682 - 1.36719 1.31167 1.27080 1.26479 1.26142 1.26309 - 11.31950 10.45897 9.92023 9.42460 8.97030 8.55573 - 8.18001 7.84191 7.54041 7.27377 7.03964 6.83473 - 6.65387 6.49107 6.33921 6.18221 5.99532 5.73726 - 5.31603 4.97523 4.44574 3.73526 2.39342 1.87274 - 1.38391 1.31696 1.26781 1.26133 1.25700 1.25852 - 11.30682 10.45931 9.93261 9.44970 9.00757 8.60401 - 8.23855 7.91065 7.62009 7.36566 7.14543 6.95644 - 6.79332 6.65019 6.52116 6.39198 6.23996 6.02555 - 5.65886 5.34840 4.84332 4.12851 2.67624 2.06618 - 1.42504 1.32913 1.26465 1.25910 1.24909 1.25279 - 11.32168 10.47184 9.94346 9.46235 9.02494 8.62852 - 8.27186 7.95339 7.67186 7.42600 7.21410 7.03333 - 6.87856 6.74542 6.63210 6.53234 6.42608 6.25334 - 5.90662 5.60845 5.13876 4.45832 2.93490 2.23878 - 1.46378 1.34678 1.26520 1.25591 1.24800 1.24931 - 11.29838 10.47510 9.96134 9.49227 9.06499 8.67756 - 8.32891 8.01803 7.74425 7.50713 7.30610 7.14010 - 7.00666 6.90274 6.82406 6.75758 6.68249 6.56264 - 6.31155 6.07277 5.66444 5.03780 3.47198 2.61376 - 1.56630 1.40150 1.27003 1.25599 1.23983 1.24465 - 11.28058 10.48148 9.97392 9.50946 9.08581 8.70154 - 8.35606 8.04904 7.78047 7.55007 7.35716 7.20051 - 7.07728 6.98470 6.92044 6.87516 6.83180 6.75507 - 6.56642 6.37021 6.00582 5.42369 3.88606 2.94920 - 1.66479 1.45006 1.27851 1.25857 1.24133 1.24234 - 11.23786 10.48779 9.98469 9.52384 9.10372 8.72358 - 8.38298 8.08182 7.82023 7.59758 7.41265 7.26426 - 7.15084 7.07118 7.02466 7.00464 6.99745 6.97116 - 6.85254 6.71038 6.44477 5.98352 4.47978 3.41391 - 1.87139 1.58234 1.29433 1.25531 1.23943 1.24000 - 11.21644 10.49521 9.98827 9.52673 9.10830 8.73143 - 8.39503 8.09834 7.84082 7.62203 7.44142 7.29771 - 7.18791 7.11067 7.06908 7.06452 7.08973 7.10577 - 7.03829 6.92922 6.69498 6.26352 4.89990 3.88298 - 2.03657 1.66699 1.31918 1.27611 1.23851 1.23883 - 11.18882 10.49606 9.99059 9.53044 9.11343 8.73810 - 8.40341 8.10857 7.85312 7.63665 7.45869 7.31802 - 7.21177 7.13881 7.10279 7.10614 7.14361 7.18058 - 7.14980 7.06800 6.87020 6.48879 5.22699 4.20746 - 2.20225 1.77121 1.34169 1.28546 1.23922 1.23813 - 11.14917 10.48988 9.99338 9.53774 9.12240 8.74737 - 8.41225 8.11690 7.86151 7.64574 7.46917 7.33114 - 7.23028 7.16579 7.13805 7.14197 7.16975 7.20804 - 7.21890 7.17426 7.01159 6.65783 5.47327 4.48091 - 2.36013 1.87136 1.36430 1.29543 1.23993 1.23766 - 11.12424 10.49044 9.99548 9.54117 9.12715 8.75352 - 8.41990 8.12614 7.87239 7.65849 7.48409 7.34874 - 7.25108 7.19052 7.16794 7.17909 7.21771 7.27329 - 7.31627 7.30157 7.19123 6.90537 5.84179 4.90403 - 2.65488 2.05995 1.40926 1.31452 1.24364 1.23706 - 11.10868 10.49089 9.99683 9.54333 9.13010 8.75731 - 8.42459 8.13177 7.87897 7.66614 7.49310 7.35941 - 7.26379 7.20567 7.18621 7.20179 7.24710 7.31358 - 7.37644 7.38084 7.30793 7.07450 6.10685 5.22375 - 2.91687 2.23352 1.45373 1.33431 1.24808 1.23670 - 11.08538 10.49157 9.99869 9.54625 9.13412 8.76248 - 8.43095 8.13934 7.88778 7.67637 7.50511 7.37375 - 7.28090 7.22612 7.21094 7.23255 7.28703 7.36878 - 7.45909 7.49006 7.47429 7.32902 6.54028 5.77512 - 3.46005 2.61613 1.56204 1.38617 1.26044 1.23623 - 11.07281 10.49185 9.99929 9.54735 9.13582 8.76480 - 8.43395 8.14325 7.89287 7.68257 7.51181 7.38041 - 7.28833 7.23607 7.22458 7.24933 7.30598 7.39459 - 7.50723 7.55644 7.55633 7.44065 6.83537 6.18700 - 3.85018 2.91706 1.66933 1.44441 1.28188 1.23599 - 11.05848 10.49232 10.00050 9.54915 9.13814 8.76760 - 8.43718 8.14680 7.89667 7.68687 7.51749 7.38830 - 7.29818 7.24693 7.23641 7.26439 7.32841 7.42703 - 7.54770 7.60605 7.64952 7.61531 7.13565 6.58938 - 4.51346 3.45894 1.86005 1.54764 1.29844 1.23576 - 11.05114 10.49256 10.00096 9.54985 9.13910 8.76882 - 8.43872 8.14870 7.89896 7.68958 7.52064 7.39195 - 7.30246 7.25208 7.24278 7.27239 7.33885 7.44166 - 7.57073 7.63671 7.69370 7.68974 7.32726 6.86755 - 4.95623 3.85891 2.04098 1.65458 1.32233 1.23564 - 11.06576 10.49892 10.00009 9.54590 9.13470 8.76530 - 8.43680 8.14865 7.90054 7.69239 7.52405 7.39486 - 7.30258 7.24723 7.23446 7.27031 7.35629 7.47168 - 7.59050 7.65134 7.71308 7.73207 7.45789 7.05419 - 5.27929 4.18167 2.21703 1.76029 1.34404 1.23557 - 11.06236 10.49889 10.00028 9.54620 9.13512 8.76583 - 8.43745 8.14941 7.90143 7.69343 7.52528 7.39630 - 7.30432 7.24934 7.23705 7.27362 7.36062 7.47763 - 7.59957 7.66359 7.73187 7.76398 7.54297 7.19091 - 5.53533 4.44644 2.38044 1.86545 1.36623 1.23553 - 11.03896 10.49295 10.00181 9.55097 9.14049 8.77060 - 8.44096 8.15146 7.90231 7.69358 7.52536 7.39750 - 7.30906 7.26004 7.25257 7.28469 7.35473 7.46333 - 7.60579 7.68516 7.76281 7.80383 7.65316 7.37092 - 5.91345 4.86640 2.67432 2.06906 1.41037 1.23547 - 11.03598 10.49292 10.00204 9.55137 9.14092 8.77096 - 8.44119 8.15164 7.90255 7.69403 7.52609 7.39855 - 7.31043 7.26174 7.25463 7.28719 7.35794 7.46804 - 7.61273 7.69405 7.77841 7.83072 7.71586 7.48054 - 6.18231 5.19158 2.93343 2.25420 1.45243 1.23542 - 0.59229 0.61668 0.64267 0.67035 0.69956 0.73009 - 0.76201 0.79553 0.83094 0.86869 0.90955 0.95425 - 1.00331 1.05642 1.11100 1.16037 1.19690 1.21959 - 1.23479 1.24378 1.25168 1.25503 1.25281 1.25202 - 1.25219 1.25220 1.25207 1.25205 1.25202 1.25205 - 0.83673 0.87208 0.90958 0.94915 0.99018 1.03199 - 1.07460 1.11837 1.16390 1.21193 1.26353 1.31947 - 1.37941 1.44210 1.50461 1.56035 1.60177 1.62691 - 1.64055 1.64721 1.65333 1.65602 1.65277 1.65282 - 1.65583 1.65623 1.65605 1.65601 1.65596 1.65596 - 1.06989 1.11738 1.16530 1.21393 1.26325 1.31331 - 1.36426 1.41651 1.47066 1.52696 1.58556 1.64673 - 1.71101 1.77797 1.84439 1.90289 1.94593 1.97459 - 1.99077 1.99443 1.99961 2.00485 2.00395 2.00413 - 2.00693 2.00734 2.00718 2.00725 2.00711 2.00712 - 1.50427 1.56868 1.63243 1.69590 1.75890 1.82137 - 1.88343 1.94558 2.00859 2.07260 2.13754 2.20340 - 2.27047 2.33824 2.40393 2.46191 2.50652 2.53859 - 2.55916 2.56512 2.57211 2.57952 2.58655 2.58787 - 2.58718 2.58700 2.58723 2.58724 2.58730 2.58721 - 1.89440 1.97218 2.04749 2.12086 2.19210 2.26126 - 2.32856 2.39481 2.46119 2.52760 2.59349 2.65836 - 2.72248 2.78566 2.84602 2.90029 2.94491 2.97886 - 3.00365 3.01417 3.02411 3.03297 3.04763 3.04962 - 3.04567 3.04508 3.04552 3.04562 3.04570 3.04562 - 2.24410 2.33390 2.41799 2.49744 2.57268 2.64458 - 2.71356 2.78056 2.84691 2.91219 2.97534 3.03561 - 3.09394 3.15094 3.20532 3.25501 3.29781 3.33339 - 3.36285 3.37601 3.38852 3.39993 3.41982 3.42229 - 3.41625 3.41537 3.41597 3.41611 3.41624 3.41615 - 2.55928 2.65893 2.74944 2.83241 2.90901 2.98101 - 3.04907 3.11425 3.17803 3.23987 3.29837 3.35271 - 3.40440 3.45469 3.50284 3.54771 3.58820 3.62456 - 3.65762 3.67305 3.68782 3.70125 3.72436 3.72722 - 3.72033 3.71933 3.72002 3.72018 3.72032 3.72025 - 3.10258 3.21690 3.31510 3.39991 3.47405 3.54115 - 3.60235 3.65904 3.71311 3.76409 3.81057 3.85197 - 3.89042 3.92794 3.96453 4.00034 4.03572 4.07159 - 4.10856 4.12695 4.14497 4.16077 4.18510 4.18859 - 4.18326 4.18247 4.18315 4.18330 4.18343 4.18341 - 3.55541 3.67950 3.78070 3.86289 3.93039 3.98864 - 4.03931 4.08416 4.12558 4.16344 4.19684 4.22569 - 4.25219 4.27853 4.30520 4.33305 4.36319 4.39677 - 4.43422 4.45375 4.47339 4.48990 4.51107 4.51500 - 4.51369 4.51346 4.51399 4.51408 4.51417 4.51420 - 4.42892 4.56452 4.66175 4.72765 4.77051 4.80017 - 4.81965 4.83171 4.84003 4.84545 4.84861 4.85036 - 4.85236 4.85644 4.86352 4.87492 4.89209 4.91598 - 4.94673 4.96434 4.98327 4.99751 5.00497 5.00913 - 5.01921 5.02058 5.02056 5.02051 5.02044 5.02058 - 5.07058 5.20734 5.29237 5.33608 5.35067 5.35018 - 5.33896 5.32065 5.29989 5.27826 5.25702 5.23736 - 5.22045 5.20758 5.19965 5.19760 5.20234 5.21426 - 5.23318 5.24535 5.25970 5.26905 5.26294 5.26640 - 5.28479 5.28739 5.28687 5.28669 5.28650 5.28669 - 5.98567 6.10991 6.16111 6.15648 6.11561 6.05992 - 5.99584 5.92820 5.86246 5.80064 5.74356 5.69173 - 5.64618 5.60748 5.57614 5.55181 5.53399 5.52209 - 5.51512 5.51399 5.51565 5.51406 5.49000 5.49102 - 5.51534 5.51889 5.51782 5.51748 5.51719 5.51741 - 6.64696 6.74839 6.76129 6.70914 6.61795 6.51503 - 6.40802 6.30194 6.20214 6.11025 6.02628 5.94978 - 5.88177 5.82239 5.77176 5.72862 5.69150 5.65924 - 5.63026 5.61737 5.60701 5.59643 5.56573 5.56435 - 5.58492 5.58798 5.58684 5.58651 5.58624 5.58641 - 7.17457 7.24786 7.22128 7.12406 6.98763 6.84400 - 6.70127 6.56378 6.43627 6.31972 6.21348 6.11633 - 6.02908 5.95164 5.88386 5.82405 5.77030 5.72132 - 5.67500 5.65275 5.63228 5.61496 5.58522 5.58184 - 5.59322 5.59496 5.59405 5.59380 5.59362 5.59376 - 7.61893 7.66096 7.59499 7.45534 7.27797 7.09865 - 6.92538 6.76136 6.61026 6.47254 6.34688 6.23162 - 6.12716 6.03338 5.94992 5.87501 5.80673 5.74383 - 5.68383 5.65418 5.62539 5.60304 5.57835 5.57331 - 5.57317 5.57324 5.57267 5.57256 5.57248 5.57259 - 8.52075 8.30219 8.07862 7.86142 7.65036 7.44565 - 7.24748 7.05589 6.87157 6.69574 6.52886 6.37132 - 6.22442 6.09009 5.96939 5.86415 5.77521 5.69822 - 5.63107 5.60435 5.58421 5.56696 5.50381 5.47304 - 5.47684 5.48069 5.47723 5.47568 5.47810 5.47696 - 8.87698 8.78159 8.56807 8.28450 7.97723 7.68884 - 7.42506 7.18455 6.96573 6.76676 6.58320 6.41184 - 6.25275 6.10683 5.97331 5.85039 5.73661 5.63176 - 5.53293 5.48314 5.43194 5.39566 5.38188 5.37239 - 5.34296 5.33877 5.33908 5.33930 5.33948 5.33943 - 9.79462 9.52807 9.16024 8.74385 8.32623 7.94782 - 7.61095 7.31102 7.04265 6.79906 6.57063 6.35184 - 6.14571 5.95528 5.78027 5.61709 5.46370 5.32142 - 5.18851 5.12279 5.05669 5.00726 4.97087 4.95841 - 4.93583 4.93268 4.93233 4.93239 4.93245 4.93221 - 10.45399 9.89938 9.37437 8.88880 8.43971 8.02508 - 7.64305 7.29232 6.97220 6.68050 6.41427 6.16984 - 5.94204 5.72747 5.52734 5.34120 5.16731 4.99776 - 4.82701 4.74469 4.67014 4.61693 4.55289 4.53528 - 4.53130 4.53173 4.53002 4.52968 4.52938 4.52908 - 10.98825 10.33673 9.67819 9.04367 8.45710 7.93840 - 7.48380 7.08367 6.72838 6.40667 6.10416 5.81327 - 5.53817 5.28198 5.04349 4.81909 4.60477 4.40229 - 4.21227 4.12090 4.03198 3.96194 3.88479 3.86776 - 3.86173 3.86113 3.85953 3.85923 3.85903 3.85828 - 11.33548 10.52824 9.76562 9.05846 8.41719 7.84974 - 7.34996 6.90659 6.50842 6.14674 5.81206 5.49807 - 5.20342 4.92708 4.66790 4.42350 4.19154 3.97174 - 3.76402 3.66388 3.56552 3.48955 3.41628 3.39760 - 3.38079 3.37859 3.37727 3.37711 3.37699 3.37678 - 11.56521 10.62397 9.79089 9.04628 8.37988 7.78269 - 7.24823 6.76830 6.33474 5.94197 5.58485 5.25739 - 4.95190 4.66287 4.38984 4.13241 3.89023 3.66018 - 3.44143 3.33647 3.23227 3.15094 3.07506 3.05575 - 3.03703 3.03460 3.03315 3.03293 3.03286 3.03379 - 11.69463 10.69286 9.81677 9.03601 8.34007 7.71846 - 7.16255 6.66276 6.20981 5.79811 5.42306 5.07960 - 4.76145 4.46375 4.18462 3.92113 3.67122 3.43326 - 3.20669 3.09771 2.98935 2.90407 2.82242 2.80243 - 2.78528 2.78308 2.78131 2.78108 2.78089 2.78257 - 11.85138 10.76918 9.83871 9.01212 8.27879 7.62708 - 7.04531 6.52239 6.04822 5.61693 5.22382 4.86383 - 4.53084 4.22007 3.92912 3.65440 3.39300 3.14359 - 2.90410 2.78788 2.67223 2.58058 2.48996 2.46775 - 2.45117 2.44931 2.44737 2.44703 2.44697 2.44757 - 11.93997 10.80429 9.84155 8.98977 8.23773 7.57217 - 6.97951 6.44739 5.96502 5.52620 5.12592 4.75869 - 4.41796 4.09861 3.79847 3.51437 3.24330 2.98269 - 2.72984 2.60616 2.48379 2.38694 2.28822 2.26353 - 2.24458 2.24241 2.24046 2.24021 2.23998 2.23853 - 12.01372 10.82333 9.83573 8.96629 8.20401 7.52990 - 6.93043 6.39259 5.90526 5.46182 5.05667 4.68358 - 4.33499 4.00523 3.69238 3.39390 3.10624 2.82310 - 2.53897 2.39491 2.24823 2.12921 2.00986 1.97920 - 1.95437 1.95150 1.94919 1.94884 1.94863 1.94694 - 12.00609 10.81177 9.83393 8.97346 8.21934 7.54968 - 6.95238 6.41523 5.92781 5.48379 5.07780 4.70389 - 4.35486 4.02476 3.71013 3.40575 3.10582 2.80368 - 2.49114 2.32710 2.15222 2.00429 1.85985 1.82550 - 1.79775 1.79423 1.79094 1.79044 1.79017 1.79301 - 11.92185 10.77327 9.84489 9.02117 8.28868 7.63038 - 7.03863 6.50587 6.02560 5.59126 5.19600 4.83186 - 4.48882 4.15923 3.84039 3.52847 3.21617 2.88783 - 2.52429 2.32297 2.10231 1.90735 1.70344 1.65714 - 1.63048 1.62729 1.62036 1.61884 1.61987 1.63031 - 11.85109 10.72756 9.83796 9.04999 8.34509 7.70924 - 7.13556 6.61730 6.14857 5.72338 5.33537 4.97701 - 4.63870 4.31275 3.99579 3.68264 3.36329 3.01624 - 2.61399 2.38221 2.12103 1.88462 1.62914 1.56906 - 1.54293 1.54043 1.53030 1.52784 1.53025 1.54430 - 11.78638 10.69253 9.84164 9.08513 8.40336 7.78491 - 7.22416 6.71547 6.25401 5.83469 5.45211 5.09997 - 4.77012 4.45511 4.14907 3.84222 3.52040 3.16044 - 2.72824 2.46849 2.16273 1.87996 1.58578 1.52436 - 1.49159 1.48687 1.47519 1.47277 1.47528 1.49066 - 11.72731 10.65844 9.84124 9.11125 8.45025 7.84830 - 7.30094 6.80347 6.35195 5.94162 5.56723 5.22251 - 4.89927 4.58984 4.28810 3.98358 3.66061 3.29264 - 2.83884 2.55868 2.22083 1.90245 1.56460 1.49262 - 1.45716 1.45233 1.43867 1.43577 1.43904 1.45393 - 11.63320 10.60272 9.83969 9.15184 8.52553 7.95223 - 7.42890 6.95201 6.51873 6.12482 5.76535 5.43425 - 5.12337 4.82491 4.53235 4.23437 3.91297 3.53604 - 3.05109 2.73897 2.34892 1.97088 1.55737 1.46211 - 1.41122 1.40622 1.39420 1.39171 1.39641 1.40676 - 11.56171 10.56093 9.83853 9.18283 8.58373 8.03362 - 7.53020 7.07079 6.65322 6.27365 5.92736 5.60847 - 5.30878 5.02044 4.73679 4.44604 4.12889 3.74973 - 3.24682 2.91222 2.48114 2.05163 1.56810 1.45225 - 1.38681 1.38057 1.36776 1.36506 1.36923 1.37757 - 11.49640 10.51457 9.83600 9.22283 8.66618 8.15829 - 7.69588 7.27505 6.89241 6.54415 6.22585 5.93158 - 5.65276 5.38170 5.11369 4.84024 4.54347 4.18174 - 3.67208 3.30478 2.79479 2.26153 1.63006 1.45747 - 1.36495 1.35274 1.33062 1.32959 1.32570 1.33659 - 11.42882 10.47825 9.83819 9.25858 8.73144 8.25022 - 7.81209 7.41366 7.05192 6.72352 6.42438 6.14894 - 5.88887 5.63661 5.38745 5.13266 4.85321 4.50395 - 3.99306 3.61313 3.07146 2.48061 1.71636 1.49014 - 1.35393 1.33737 1.31291 1.31092 1.30726 1.31495 - 11.31224 10.42710 9.85141 9.32148 8.83270 8.38168 - 7.96812 7.59169 7.25238 6.94781 6.67446 6.42729 - 6.19848 5.98020 5.76593 5.54279 5.28922 4.96439 - 4.47445 4.09413 3.52503 2.85638 1.89620 1.59916 - 1.34836 1.31768 1.29683 1.29386 1.28881 1.29267 - 11.28731 10.41730 9.86332 9.35315 8.88313 8.45039 - 8.05466 7.69583 7.37395 7.08701 6.83180 6.60375 - 6.39537 6.19915 6.00876 5.81112 5.58485 5.29027 - 4.83135 4.46154 3.88705 3.17662 2.06968 1.70019 - 1.36173 1.31655 1.28732 1.28396 1.27636 1.28137 - 11.28320 10.41828 9.87382 9.37406 8.91542 8.49489 - 8.11178 7.76537 7.45522 7.17973 6.93659 6.72233 - 6.53118 6.35637 6.18989 6.01444 5.80511 5.52417 - 5.08418 4.73506 4.19638 3.48994 2.23438 1.78437 - 1.37786 1.32284 1.28228 1.27629 1.27295 1.27462 - 11.27616 10.42240 9.88607 9.39232 8.93948 8.52611 - 8.15146 7.81446 7.51428 7.24900 7.01599 6.81186 - 6.63166 6.46960 6.31863 6.16270 5.97723 5.72131 - 5.30369 4.96559 4.43971 3.73311 2.39741 1.87970 - 1.39441 1.32803 1.27929 1.27284 1.26857 1.27015 - 11.26816 10.42474 9.89885 9.41709 8.97635 8.57435 - 8.21047 7.88406 7.59478 7.34135 7.12192 6.93353 - 6.77088 6.62821 6.49963 6.37106 6.22004 6.00740 - 5.64392 5.33601 4.83453 4.12395 2.67897 2.07218 - 1.43515 1.33997 1.27612 1.27064 1.26071 1.26458 - 11.28239 10.43758 9.91055 9.43076 8.99457 8.59937 - 8.24382 7.92641 7.64589 7.40098 7.18993 7.00991 - 6.85579 6.72316 6.61024 6.51085 6.40511 6.23359 - 5.88965 5.59391 5.12788 4.45203 2.93645 2.24375 - 1.47360 1.35747 1.27665 1.26742 1.25962 1.26115 - 11.25836 10.43975 9.92731 9.45963 9.03377 8.64774 - 8.30044 7.99082 7.71811 7.48187 7.28154 7.11607 - 6.98296 6.87926 6.80072 6.73448 6.65991 6.54093 - 6.29171 6.05489 5.64992 5.02779 3.47079 2.61718 - 1.57541 1.41162 1.28138 1.26754 1.25144 1.25649 - 11.23919 10.44614 9.93996 9.47621 9.05317 8.66991 - 8.32582 8.02059 7.75401 7.52539 7.33335 7.17644 - 7.05273 6.96013 6.89620 6.85123 6.80819 6.73350 - 6.54379 6.34470 5.98950 5.42423 3.88397 2.93434 - 1.67554 1.46703 1.28949 1.26906 1.24919 1.25413 - 11.21137 10.45576 9.94861 9.48671 9.06766 8.68982 - 8.35202 8.05347 7.79355 7.57182 7.38757 7.23942 - 7.12419 7.04022 6.98971 6.97259 6.97866 6.96309 - 6.84295 6.69705 6.41718 5.92707 4.46192 3.47845 - 1.86618 1.56800 1.30847 1.27851 1.25036 1.25175 - 11.17465 10.45788 9.95299 9.49327 9.07645 8.70099 - 8.36583 8.07022 7.81357 7.59551 7.41548 7.27222 - 7.16274 7.08576 7.04434 7.03989 7.06514 7.08124 - 7.01418 6.90580 6.67322 6.24494 4.89077 3.88003 - 2.04277 1.67518 1.33003 1.28745 1.25011 1.25058 - 11.14789 10.45913 9.95550 9.49707 9.08159 8.70762 - 8.37413 8.08034 7.82577 7.61004 7.43267 7.29247 - 7.18657 7.11386 7.07800 7.08138 7.11879 7.15571 - 7.12518 7.04385 6.84731 6.46853 5.21582 4.20266 - 2.20750 1.77879 1.35235 1.29670 1.25078 1.24988 - 11.10819 10.45335 9.95889 9.50476 9.09064 8.71672 - 8.38267 8.08838 7.83394 7.61909 7.44323 7.30569 - 7.20513 7.14082 7.11315 7.11704 7.14474 7.18298 - 7.19403 7.14967 6.98780 6.63621 5.46068 4.47450 - 2.36445 1.87845 1.37479 1.30659 1.25145 1.24941 - 11.08418 10.45392 9.96082 9.50805 9.09538 8.72295 - 8.39044 8.09770 7.84488 7.63180 7.45807 7.32315 - 7.22580 7.16543 7.14288 7.15397 7.19244 7.24790 - 7.29093 7.27640 7.16653 6.88227 5.82656 4.89492 - 2.65761 2.06610 1.41942 1.32548 1.25511 1.24883 - 11.06932 10.45427 9.96196 9.51006 9.09832 8.72685 - 8.39530 8.10348 7.85153 7.63941 7.46695 7.33373 - 7.23842 7.18048 7.16105 7.17655 7.22170 7.28799 - 7.35077 7.35527 7.28270 7.05049 6.08967 5.21255 - 2.91827 2.23885 1.46358 1.34508 1.25949 1.24848 - 11.04713 10.45485 9.96327 9.51249 9.10206 8.73187 - 8.40163 8.11127 7.86102 7.65059 7.47947 7.34738 - 7.25417 7.20018 7.18628 7.20785 7.26016 7.34152 - 7.43722 7.46893 7.44071 7.28786 6.55456 5.77659 - 3.43183 2.61163 1.57405 1.39428 1.28239 1.24802 - 11.03404 10.45523 9.96430 9.51402 9.10404 8.73439 - 8.40473 8.11501 7.86543 7.65577 7.48552 7.35449 - 7.26269 7.21060 7.19915 7.22383 7.28030 7.36860 - 7.48086 7.52993 7.52996 7.41509 6.81332 6.16861 - 3.84679 2.91942 1.67784 1.45401 1.29326 1.24779 - 11.01929 10.45581 9.96584 9.51598 9.10629 8.73698 - 8.40772 8.11837 7.86912 7.66005 7.49120 7.36239 - 7.27250 7.22139 7.21093 7.23883 7.30261 7.40086 - 7.52112 7.57931 7.62273 7.58877 7.11152 6.56892 - 4.50672 3.45823 1.86740 1.55658 1.30949 1.24755 - 11.01195 10.45614 9.96644 9.51677 9.10723 8.73814 - 8.40913 8.12012 7.87129 7.66268 7.49432 7.36604 - 7.27681 7.22657 7.21730 7.24682 7.31298 7.41540 - 7.54402 7.60978 7.66664 7.66279 7.30214 6.84530 - 4.94701 3.85602 2.04733 1.66279 1.33319 1.24744 - 11.02693 10.46230 9.96524 9.51261 9.10282 8.73470 - 8.40733 8.12015 7.87290 7.66544 7.49767 7.36890 - 7.27693 7.22175 7.20899 7.24469 7.33037 7.44531 - 7.56367 7.62429 7.68590 7.70494 7.43208 7.03090 - 5.26813 4.17684 2.22229 1.76785 1.35475 1.24737 - 11.02367 10.46237 9.96546 9.51294 9.10328 8.73526 - 8.40800 8.12095 7.87382 7.66652 7.49894 7.37039 - 7.27869 7.22389 7.21160 7.24800 7.33465 7.45120 - 7.57265 7.63647 7.70460 7.73674 7.51674 7.16685 - 5.52254 4.43993 2.38468 1.87236 1.37680 1.24732 - 11.00012 10.45634 9.96697 9.51772 9.10867 8.74008 - 8.41158 8.12308 7.87474 7.66669 7.49903 7.37163 - 7.28350 7.23459 7.22704 7.25896 7.32874 7.43692 - 7.57885 7.65796 7.73538 7.77631 7.62646 7.34574 - 5.89816 4.85720 2.67685 2.07479 1.42068 1.24726 - 10.99788 10.45601 9.96655 9.51749 9.10867 8.74023 - 8.41188 8.12369 7.87593 7.66837 7.50051 7.37220 - 7.28359 7.23546 7.22950 7.26252 7.33191 7.43933 - 7.58589 7.67218 7.75516 7.78860 7.66763 7.50684 - 6.16910 5.13679 2.93024 2.28202 1.45566 1.24724 - 0.58168 0.60571 0.63141 0.65883 0.68778 0.71805 - 0.74968 0.78287 0.81791 0.85522 0.89553 0.93958 - 0.98781 1.03993 1.09347 1.14207 1.17848 1.20176 - 1.21775 1.22689 1.23489 1.23839 1.23662 1.23594 - 1.23614 1.23616 1.23603 1.23601 1.23599 1.23601 - 0.82318 0.85805 0.89513 0.93434 0.97505 1.01653 - 1.05882 1.10222 1.14733 1.19486 1.24589 1.30120 - 1.36036 1.42212 1.48370 1.53886 1.58044 1.60646 - 1.62121 1.62826 1.63475 1.63772 1.63458 1.63474 - 1.63819 1.63866 1.63847 1.63843 1.63838 1.63843 - 1.05380 1.10078 1.14825 1.19646 1.24539 1.29507 - 1.34570 1.39761 1.45138 1.50725 1.56535 1.62594 - 1.68953 1.75573 1.82145 1.87963 1.92305 1.95264 - 1.97000 1.97429 1.97998 1.98547 1.98474 1.98504 - 1.98833 1.98882 1.98864 1.98872 1.98856 1.98865 - 1.48417 1.54801 1.61127 1.67430 1.73693 1.79907 - 1.86088 1.92278 1.98554 2.04929 2.11395 2.17950 - 2.24621 2.31360 2.37902 2.43707 2.48232 2.51544 - 2.53721 2.54378 2.55131 2.55909 2.56658 2.56805 - 2.56761 2.56748 2.56771 2.56772 2.56777 2.56775 - 1.87130 1.94843 2.02325 2.09627 2.16727 2.23623 - 2.30338 2.36952 2.43577 2.50210 2.56794 2.63281 - 2.69694 2.76010 2.82052 2.87512 2.92054 2.95559 - 2.98147 2.99245 3.00286 3.01219 3.02758 3.02973 - 3.02579 3.02520 3.02566 3.02575 3.02584 3.02577 - 2.21862 2.30782 2.39151 2.47068 2.54578 2.61759 - 2.68657 2.75360 2.82001 2.88542 2.94875 3.00925 - 3.06784 3.12512 3.17987 3.23012 3.27378 3.31039 - 3.34080 3.35435 3.36727 3.37914 3.39995 3.40258 - 3.39637 3.39546 3.39609 3.39623 3.39635 3.39625 - 2.53190 2.63104 2.72124 2.80404 2.88060 2.95264 - 3.02082 3.08620 3.15022 3.21237 3.27123 3.32599 - 3.37816 3.42898 3.47774 3.52334 3.56472 3.60202 - 3.63589 3.65165 3.66678 3.68063 3.70474 3.70777 - 3.70061 3.69956 3.70028 3.70044 3.70059 3.70048 - 3.07244 3.18651 3.28461 3.36944 3.44375 3.51112 - 3.57272 3.62989 3.68451 3.73607 3.78320 3.82531 - 3.86455 3.90293 3.94045 3.97719 4.01345 4.05012 - 4.08770 4.10633 4.12462 4.14081 4.16600 4.16966 - 4.16411 4.16328 4.16399 4.16415 4.16428 4.16418 - 3.52344 3.64755 3.74887 3.83128 3.89912 3.95786 - 4.00919 4.05478 4.09696 4.13561 4.16983 4.19957 - 4.22703 4.25444 4.28222 4.31110 4.34209 4.37634 - 4.41432 4.43406 4.45396 4.47079 4.49249 4.49656 - 4.49530 4.49506 4.49560 4.49570 4.49579 4.49575 - 4.39458 4.53092 4.62879 4.69531 4.73888 4.76951 - 4.79014 4.80341 4.81281 4.81926 4.82344 4.82632 - 4.82952 4.83487 4.84322 4.85572 4.87369 4.89815 - 4.92936 4.94720 4.96644 4.98091 4.98821 4.99245 - 5.00311 5.00458 5.00454 5.00448 5.00442 5.00454 - 5.03555 5.17363 5.25976 5.30442 5.32004 5.32084 - 5.31110 5.29428 5.27480 5.25429 5.23416 5.21570 - 5.20006 5.18847 5.18180 5.18083 5.18642 5.19898 - 5.21846 5.23092 5.24562 5.25519 5.24877 5.25230 - 5.27138 5.27408 5.27353 5.27334 5.27315 5.27339 - 5.95134 6.07765 6.13066 6.12756 6.08824 6.03429 - 5.97208 5.90621 5.84190 5.78126 5.72531 5.67473 - 5.63044 5.59294 5.56273 5.53948 5.52269 5.51169 - 5.50552 5.50478 5.50684 5.50557 5.48168 5.48279 - 5.50730 5.51087 5.50981 5.50948 5.50921 5.50952 - 6.61444 6.71826 6.73340 6.68328 6.59406 6.49316 - 6.38820 6.28398 6.18570 6.09507 6.01228 5.93706 - 5.87028 5.81203 5.76246 5.72041 5.68446 5.65330 - 5.62525 5.61282 5.60290 5.59268 5.56258 5.56129 - 5.58165 5.58467 5.58356 5.58321 5.58295 5.58325 - 7.14420 7.21989 7.19588 7.10115 6.96709 6.82570 - 6.68503 6.54940 6.42349 6.30833 6.20337 6.10752 - 6.02147 5.94514 5.87842 5.81973 5.76722 5.71937 - 5.67403 5.65230 5.63232 5.61537 5.58630 5.58300 - 5.59406 5.59575 5.59484 5.59459 5.59442 5.59460 - 7.59084 7.63512 7.57194 7.43517 7.26055 7.08360 - 6.91234 6.75010 6.60069 6.46453 6.34030 6.22634 - 6.12307 6.03046 5.94811 5.87436 5.80731 5.74551 - 5.68646 5.65737 5.62910 5.60713 5.58291 5.57792 - 5.57754 5.57757 5.57701 5.57690 5.57682 5.57688 - 8.49680 8.28109 8.06035 7.84582 7.63733 7.43503 - 7.23914 7.04971 6.86740 6.69346 6.52832 6.37237 - 6.22694 6.09392 5.97437 5.87014 5.78207 5.70592 - 5.63965 5.61338 5.59372 5.57687 5.51416 5.48345 - 5.48709 5.49090 5.48748 5.48596 5.48838 5.48701 - 8.85679 8.76305 8.55277 8.27309 7.96947 7.68370 - 7.42182 7.18295 6.96600 6.76901 6.58716 6.41712 - 6.25927 6.11472 5.98267 5.86114 5.74849 5.64447 - 5.54645 5.49728 5.44669 5.41068 5.39662 5.38710 - 5.35794 5.35378 5.35407 5.35430 5.35449 5.35418 - 9.78036 9.51633 9.15204 8.73957 8.32553 7.94995 - 7.61527 7.31720 7.05068 6.80884 6.58195 6.36450 - 6.15975 5.97092 5.79765 5.63601 5.48378 5.34240 - 5.21043 5.14524 5.07963 5.03046 4.99404 4.98156 - 4.95916 4.95603 4.95567 4.95572 4.95579 4.95559 - 10.44219 9.89212 9.37117 8.88918 8.44321 8.03134 - 7.65172 7.30310 6.98483 6.69476 6.43001 6.18697 - 5.96054 5.74737 5.54869 5.36407 5.19173 5.02362 - 4.85396 4.77203 4.69781 4.64486 4.58133 4.56389 - 4.55976 4.56015 4.55845 4.55810 4.55783 4.55799 - 10.97878 10.33508 9.68073 9.04830 8.46364 7.94803 - 7.49708 7.10012 6.74652 6.42549 6.12365 5.83402 - 5.56046 5.30592 5.06911 4.84631 4.63346 4.43242 - 4.24360 4.15252 4.06391 3.99427 3.91791 3.90107 - 3.89510 3.89450 3.89293 3.89263 3.89244 3.89247 - 11.35796 10.50642 9.74145 9.05429 8.43565 7.87873 - 7.37886 6.92939 6.52391 6.15735 5.82442 5.51869 - 5.23157 4.95721 4.69633 4.45079 4.22092 4.00303 - 3.79577 3.69666 3.59879 3.52265 3.45015 3.43174 - 3.41511 3.41306 3.41172 3.41152 3.41142 3.41136 - 11.55929 10.62221 9.79304 9.05206 8.38906 7.79504 - 7.26344 6.78597 6.35445 5.96332 5.60756 5.28127 - 4.97685 4.68890 4.41702 4.16089 3.92012 3.69131 - 3.47330 3.36856 3.26465 3.18367 3.10822 3.08907 - 3.07058 3.06818 3.06673 3.06653 3.06645 3.06639 - 11.68823 10.69077 9.81845 9.04130 8.34874 7.73028 - 7.17724 6.67995 6.22910 5.81914 5.44555 5.10335 - 4.78635 4.48973 4.21168 3.94924 3.70038 3.46334 - 3.23753 3.12885 3.02073 2.93560 2.85424 2.83437 - 2.81731 2.81509 2.81333 2.81314 2.81294 2.81297 - 11.84322 10.76559 9.83899 9.01594 8.28585 7.63711 - 7.05803 6.53748 6.06538 5.63586 5.24430 4.88565 - 4.55390 4.24422 3.95428 3.68050 3.41996 3.17132 - 2.93244 2.81644 2.70092 2.60928 2.51860 2.49636 - 2.47971 2.47783 2.47588 2.47555 2.47548 2.47537 - 11.92972 10.79923 9.84033 8.99195 8.24291 7.57995 - 6.98964 6.45962 5.97915 5.54206 5.14335 4.77757 - 4.43813 4.11996 3.82090 3.53783 3.26772 3.00792 - 2.75563 2.63213 2.50981 2.41284 2.31380 2.28898 - 2.26989 2.26770 2.26575 2.26550 2.26526 2.26512 - 12.00057 10.81490 9.83055 8.96392 8.20408 7.53212 - 6.93456 6.39843 5.91266 5.47065 5.06689 4.69520 - 4.34809 4.01993 3.70869 3.41166 3.12512 2.84288 - 2.55939 2.41549 2.26872 2.14944 2.02978 1.99903 - 1.97410 1.97123 1.96892 1.96856 1.96835 1.96803 - 11.99146 10.80066 9.82502 8.96673 8.21459 7.54685 - 6.95139 6.41593 5.93005 5.48745 5.08283 4.71032 - 4.36280 4.03437 3.72151 3.41887 3.12049 2.81951 - 2.50753 2.34352 2.16854 2.02048 1.87620 1.84199 - 1.81432 1.81078 1.80749 1.80702 1.80674 1.80778 - 11.90200 10.75697 9.83050 9.00844 8.27746 7.62066 - 7.03035 6.49906 6.02026 5.58742 5.19370 4.83115 - 4.48978 4.16193 3.84490 3.53482 3.22430 2.89748 - 2.53493 2.33387 2.11333 1.91852 1.71550 1.66980 - 1.64373 1.64056 1.63359 1.63210 1.63312 1.64176 - 11.82718 10.70707 9.81919 9.03266 8.32914 7.69467 - 7.12238 6.60555 6.13828 5.71461 5.32816 4.97146 - 4.63488 4.31078 3.99575 3.68460 3.36725 3.02196 - 2.62094 2.38960 2.12881 1.89287 1.63899 1.57985 - 1.55463 1.55219 1.54198 1.53950 1.54195 1.55660 - 11.76231 10.66920 9.81831 9.06263 8.38239 7.76598 - 7.20745 6.70090 6.24115 5.82322 5.44186 5.09093 - 4.76260 4.44952 4.14581 3.84149 3.52212 3.16409 - 2.73291 2.47350 2.16829 1.88642 1.59457 1.53434 - 1.50257 1.49790 1.48612 1.48364 1.48623 1.50315 - 11.69936 10.63200 9.81522 9.08627 8.42691 7.82699 - 7.28182 6.78645 6.33665 5.92775 5.55462 5.21119 - 4.88950 4.58207 4.28268 3.98074 3.66032 3.29443 - 2.84190 2.56223 2.22515 1.90790 1.57279 1.50216 - 1.46779 1.46302 1.44922 1.44626 1.44962 1.46614 - 11.59941 10.57198 9.81004 9.12362 8.49909 7.92782 - 7.40657 6.93168 6.50013 6.10773 5.74964 5.41996 - 5.11072 4.81427 4.52406 4.22865 3.90989 3.53524 - 3.05195 2.74064 2.35180 1.97536 1.56506 1.47120 - 1.42164 1.41671 1.40447 1.40192 1.40680 1.41817 - 11.52457 10.52770 9.80673 9.15268 8.55540 8.00725 - 7.50585 7.04836 6.63252 6.25452 5.90972 5.59234 - 5.29436 5.00798 4.72661 4.43839 4.12388 3.74717 - 3.24628 2.91274 2.48316 2.05556 1.57560 1.46126 - 1.39723 1.39106 1.37802 1.37528 1.37964 1.38838 - 11.40257 10.46104 9.80654 9.20667 8.65492 8.14600 - 7.67914 7.25333 6.86796 6.51956 6.20334 5.91293 - 5.63909 5.37298 5.10780 4.83138 4.52551 4.15960 - 3.66179 3.30591 2.80599 2.26900 1.62675 1.47351 - 1.37533 1.36239 1.34134 1.33750 1.33957 1.34716 - 11.33919 10.42642 9.80879 9.24149 8.71878 8.23635 - 7.79375 7.39037 7.02593 6.69742 6.40042 6.12893 - 5.87396 5.62675 5.38036 5.12196 4.83225 4.47862 - 3.98174 3.61448 3.08251 2.48570 1.71170 1.50788 - 1.36445 1.34643 1.32371 1.31972 1.32112 1.32592 - 11.27809 10.39428 9.81769 9.28788 8.80005 8.35059 - 7.93899 7.56462 7.22713 6.92417 6.65222 6.40632 - 6.17873 5.96170 5.74881 5.52735 5.27592 4.95381 - 4.46739 4.08938 3.52321 2.85779 1.90275 1.60757 - 1.35900 1.32869 1.30800 1.30501 1.30005 1.30432 - 11.25092 10.38358 9.82946 9.31986 8.85097 8.41975 - 8.02582 7.66879 7.34852 7.06297 6.80899 6.58202 - 6.37465 6.17946 5.99017 5.79393 5.56953 5.27750 - 4.82222 4.45491 3.88364 3.17679 2.07556 1.70816 - 1.37228 1.32758 1.29871 1.29535 1.28778 1.29323 - 11.24391 10.38318 9.83971 9.34115 8.88390 8.46490 - 8.08336 7.73848 7.42972 7.15549 6.91344 6.70015 - 6.50987 6.33585 6.17020 5.99585 5.78811 5.50960 - 5.07341 4.72697 4.19168 3.48885 2.23914 1.79182 - 1.38846 1.33395 1.29373 1.28780 1.28443 1.28649 - 11.23470 10.38590 9.85141 9.35967 8.90871 8.49692 - 8.12356 7.78773 7.48868 7.22451 6.99249 6.78920 - 6.60976 6.44843 6.29821 6.14322 5.95909 5.70531 - 5.29130 4.95591 4.43366 3.73096 2.40142 1.88663 - 1.40489 1.33909 1.29084 1.28442 1.28013 1.28198 - 11.22347 10.38715 9.86426 9.38491 8.94608 8.54560 - 8.18295 7.85755 7.56917 7.31656 7.09788 6.91018 - 6.74816 6.60608 6.47811 6.35027 6.20031 5.98942 - 5.62915 5.32377 4.82590 4.11958 2.68176 2.07818 - 1.44531 1.35089 1.28774 1.28231 1.27239 1.27633 - 11.23798 10.39970 9.87545 9.39799 8.96382 8.57034 - 8.21624 7.90005 7.62051 7.37636 7.16588 6.98632 - 6.83259 6.70035 6.58786 6.48903 6.38413 6.21410 - 5.87301 5.57966 5.11725 4.44592 2.93805 2.24876 - 1.48355 1.36830 1.28829 1.27912 1.27132 1.27290 - 11.21521 10.40287 9.89283 9.42718 9.00305 8.61846 - 8.27237 7.96373 7.69187 7.45632 7.25657 7.09158 - 6.95895 6.85569 6.77759 6.71173 6.63754 6.51927 - 6.27194 6.03710 5.63550 5.01787 3.46964 2.62066 - 1.58474 1.42199 1.29295 1.27927 1.26316 1.26831 - 11.19736 10.40877 9.90491 9.44384 9.02325 8.64178 - 8.29877 7.99392 7.72716 7.49824 7.30652 7.15081 - 7.02836 6.93649 6.87285 6.82813 6.78537 6.70962 - 6.52342 6.33009 5.97161 5.39868 3.88001 2.95245 - 1.68184 1.46975 1.30127 1.28161 1.26476 1.26604 - 11.15552 10.41450 9.91510 9.45774 9.04077 8.66329 - 8.32494 8.02570 7.76580 7.54464 7.36101 7.21369 - 7.10113 7.02213 6.97603 6.95628 6.94931 6.92340 - 6.80619 6.66598 6.40456 5.95054 4.46651 3.41251 - 1.88608 1.60026 1.31645 1.27822 1.26260 1.26374 - 11.11709 10.41582 9.91940 9.46449 9.04978 8.67472 - 8.33896 8.04265 7.78605 7.56858 7.38908 7.24651 - 7.13951 7.06731 7.03022 7.02319 7.03546 7.04056 - 6.97419 6.87065 6.65984 6.27407 4.89676 3.80425 - 2.05959 1.70736 1.33815 1.28552 1.26603 1.26259 - 11.10799 10.42278 9.92090 9.46400 9.04993 8.67723 - 8.34488 8.05212 7.79843 7.58347 7.40674 7.26706 - 7.16155 7.08912 7.05341 7.05680 7.09412 7.13096 - 7.10067 7.01980 6.82438 6.44816 5.20486 4.19803 - 2.21236 1.78602 1.36309 1.30822 1.26249 1.26190 - 11.06853 10.41680 9.92400 9.47155 9.05899 8.68640 - 8.35347 8.06013 7.80660 7.59253 7.41729 7.28020 - 7.17998 7.11589 7.08835 7.09228 7.11991 7.15809 - 7.16925 7.12521 6.96415 6.61469 5.44807 4.46820 - 2.36863 1.88538 1.38541 1.31800 1.26314 1.26144 - 11.04423 10.41737 9.92614 9.47500 9.06373 8.69257 - 8.36118 8.06945 7.81753 7.60520 7.43208 7.29762 - 7.20056 7.14040 7.11794 7.12903 7.16737 7.22267 - 7.26570 7.25134 7.14199 6.85931 5.81138 4.88576 - 2.66097 2.07292 1.42988 1.33660 1.26682 1.26086 - 11.02917 10.41782 9.92750 9.47714 9.06670 8.69645 - 8.36601 8.07522 7.82417 7.61279 7.44093 7.30813 - 7.21313 7.15540 7.13603 7.15148 7.19648 7.26253 - 7.32523 7.32986 7.25763 7.02671 6.07257 5.20089 - 2.92095 2.24560 1.47388 1.35591 1.27122 1.26051 - 11.00718 10.41851 9.92898 9.47969 9.07048 8.70147 - 8.37234 8.08299 7.83361 7.62391 7.45337 7.32173 - 7.22882 7.17501 7.16114 7.18263 7.23474 7.31580 - 7.41119 7.44289 7.41501 7.26312 6.53397 5.76087 - 3.43224 2.61689 1.58368 1.40462 1.29405 1.26005 - 10.99446 10.41889 9.92995 9.48115 9.07244 8.70398 - 8.37543 8.08672 7.83801 7.62908 7.45942 7.32884 - 7.23733 7.18539 7.17395 7.19850 7.25474 7.34272 - 7.45461 7.50357 7.50379 7.38970 6.79131 6.15023 - 3.84347 2.92187 1.68653 1.46380 1.30488 1.25982 - 10.98039 10.41947 9.93122 9.48293 9.07462 8.70656 - 8.37843 8.09007 7.84167 7.63331 7.46504 7.33669 - 7.24712 7.19615 7.18565 7.21338 7.27693 7.37482 - 7.49464 7.55268 7.59612 7.56229 7.08731 6.54923 - 4.49720 3.45459 1.87437 1.56594 1.32064 1.25959 - 10.97335 10.41960 9.93166 9.48360 9.07551 8.70770 - 8.37985 8.09181 7.84383 7.63592 7.46815 7.34030 - 7.25136 7.20125 7.19194 7.22130 7.28723 7.38928 - 7.51743 7.58298 7.63976 7.63594 7.27696 6.82384 - 4.93526 3.85029 2.05324 1.67134 1.34426 1.25948 - 10.98828 10.42576 9.93048 9.47945 9.07110 8.70426 - 8.37803 8.09184 7.84542 7.63867 7.47144 7.34310 - 7.25141 7.19639 7.18364 7.21918 7.30452 7.41905 - 7.53700 7.59745 7.65889 7.67792 7.40640 7.00773 - 5.25680 4.17177 2.22749 1.77548 1.36580 1.25942 - 10.98497 10.42583 9.93069 9.47978 9.07156 8.70482 - 8.37869 8.09263 7.84633 7.63972 7.47267 7.34453 - 7.25310 7.19845 7.18619 7.22244 7.30878 7.42487 - 7.54583 7.60948 7.67766 7.70991 7.49019 7.14264 - 5.51210 4.43561 2.38929 1.87922 1.38781 1.25938 - 10.96148 10.41999 9.93238 9.48467 9.07698 8.70963 - 8.38227 8.09477 7.84730 7.63995 7.47281 7.34577 - 7.25785 7.20910 7.20160 7.23340 7.30285 7.41062 - 7.55210 7.63091 7.70801 7.74900 7.60007 7.31996 - 5.88594 4.85144 2.67998 2.08030 1.43143 1.25933 - 10.95847 10.41987 9.93259 9.48504 9.07742 8.71008 - 8.38272 8.09527 7.84791 7.64074 7.47379 7.34692 - 7.25922 7.21075 7.20362 7.23590 7.30606 7.41534 - 7.55895 7.63965 7.72352 7.77562 7.66173 7.42926 - 6.14626 5.16701 2.93544 2.26401 1.47267 1.25929 - 0.57152 0.59537 0.62081 0.64791 0.67653 0.70649 - 0.73784 0.77074 0.80543 0.84231 0.88209 0.92545 - 0.97279 1.02382 1.07622 1.12402 1.16039 1.18436 - 1.20110 1.21023 1.21822 1.22190 1.22114 1.22127 - 1.22100 1.22084 1.22078 1.22081 1.22077 1.22080 - 0.81013 0.84471 0.88146 0.92028 0.96060 1.00175 - 1.04372 1.08678 1.13143 1.17838 1.22878 1.28342 - 1.34180 1.40259 1.46315 1.51767 1.55940 1.58620 - 1.60199 1.60959 1.61661 1.61965 1.61773 1.62078 - 1.62191 1.62151 1.62150 1.62165 1.62151 1.62152 - 1.03833 1.08490 1.13194 1.17976 1.22832 1.27766 - 1.32791 1.37944 1.43277 1.48814 1.54568 1.60563 - 1.66849 1.73392 1.79891 1.85670 1.90030 1.93066 - 1.94932 1.95442 1.96084 1.96655 1.96689 1.96931 - 1.97088 1.97076 1.97072 1.97086 1.97074 1.97072 - 1.46477 1.52810 1.59089 1.65350 1.71576 1.77757 - 1.83905 1.90067 1.96312 2.02654 2.09086 2.15603 - 2.22235 2.28935 2.35446 2.41245 2.45809 2.49203 - 2.51512 2.52258 2.53111 2.53973 2.54700 2.54752 - 2.54847 2.54872 2.54886 2.54885 2.54887 2.54882 - 1.84892 1.92564 1.99989 2.07228 2.14281 2.21169 - 2.27901 2.34522 2.41110 2.47678 2.54236 2.60763 - 2.67219 2.73524 2.79518 2.84963 2.89582 2.93221 - 2.95913 2.97052 2.98236 2.99323 3.00583 3.00635 - 3.00569 3.00601 3.00655 3.00656 3.00658 3.00653 - 2.19389 2.28278 2.36586 2.44434 2.51900 2.59094 - 2.66040 2.72777 2.79377 2.85840 2.92161 2.98313 - 3.04280 3.10025 3.15453 3.20464 3.24934 3.28734 - 3.31836 3.33226 3.34687 3.36057 3.37706 3.37730 - 3.37582 3.37624 3.37700 3.37701 3.37703 3.37700 - 2.50546 2.60396 2.69370 2.77621 2.85264 2.92467 - 2.99294 3.05846 3.12266 3.18503 3.24427 3.29957 - 3.35230 3.40360 3.45277 3.49884 3.54088 3.57905 - 3.61393 3.63022 3.64609 3.66149 3.68388 3.67981 - 3.67978 3.68112 3.68143 3.68107 3.68145 3.68137 - 3.04348 3.15692 3.25466 3.33936 3.41371 3.48128 - 3.54319 3.60077 3.65588 3.70803 3.75589 3.79885 - 3.83896 3.87814 3.91638 3.95381 3.99078 4.02827 - 4.06669 4.08566 4.10449 4.12198 4.14572 4.14316 - 4.14396 4.14524 4.14559 4.14528 4.14563 4.14559 - 3.49289 3.61645 3.71753 3.79995 3.86802 3.92715 - 3.97899 4.02520 4.06811 4.10758 4.14276 4.17355 - 4.20209 4.23050 4.25919 4.28890 4.32063 4.35565 - 4.39436 4.41434 4.43462 4.45226 4.47335 4.47427 - 4.47647 4.47737 4.47772 4.47758 4.47778 4.47781 - 4.36226 4.49830 4.59627 4.66319 4.70739 4.73879 - 4.76032 4.77460 4.78508 4.79266 4.79806 4.80223 - 4.80672 4.81331 4.82281 4.83631 4.85512 4.88024 - 4.91204 4.93015 4.94962 4.96361 4.97289 4.98293 - 4.98843 4.98808 4.98838 4.98873 4.98846 4.98863 - 5.00307 5.14112 5.22764 5.27304 5.28960 5.29150 - 5.28294 5.26735 5.24908 5.22980 5.21095 5.19387 - 5.17959 5.16932 5.16386 5.16399 5.17048 5.18366 - 5.20370 5.21664 5.23158 5.23983 5.23763 5.25343 - 5.26067 5.25936 5.25957 5.26027 5.25968 5.25989 - 5.92014 6.04695 6.10091 6.09912 6.06127 6.00885 - 5.94814 5.88371 5.82072 5.76133 5.70667 5.65746 - 5.61455 5.57834 5.54935 5.52725 5.51150 5.50112 - 5.49559 5.49569 5.49815 5.49511 5.47776 5.49585 - 5.50292 5.50074 5.50073 5.50166 5.50083 5.50107 - 6.58480 6.68982 6.70650 6.65814 6.57076 6.47166 - 6.36838 6.26569 6.16877 6.07940 5.99790 5.92403 - 5.85861 5.80161 5.75320 5.71230 5.67747 5.64699 - 5.61966 5.60818 5.59880 5.58719 5.56337 5.57703 - 5.58151 5.57940 5.57923 5.58002 5.57927 5.57946 - 7.11582 7.19357 7.17173 7.07914 6.94715 6.80768 - 6.66880 6.53478 6.41032 6.29652 6.19292 6.09846 - 6.01374 5.93860 5.87297 5.81539 5.76404 5.71699 - 5.67236 5.65146 5.63206 5.61449 5.58978 5.59586 - 5.59673 5.59517 5.59488 5.59534 5.59485 5.59501 - 7.56336 7.61070 7.55028 7.41601 7.24360 7.06864 - 6.89924 6.73868 6.59085 6.45620 6.33344 6.22094 - 6.11901 6.02750 5.94615 5.87347 5.80760 5.74673 - 5.68834 5.65982 5.63212 5.61039 5.58783 5.58517 - 5.58216 5.58138 5.58100 5.58106 5.58091 5.58103 - 8.47198 8.25948 8.04179 7.83015 7.62435 7.42459 - 7.23108 7.04385 6.86361 6.69153 6.52808 6.37366 - 6.22956 6.09766 5.97905 5.87559 5.78816 5.71273 - 5.64751 5.62188 5.60269 5.58530 5.51789 5.48567 - 5.49505 5.50078 5.49799 5.49614 5.49884 5.49742 - 8.83186 8.74452 8.53901 8.26272 7.96160 7.67800 - 7.41813 7.18114 6.96610 6.77100 6.59102 6.42272 - 6.26631 6.12277 5.99146 5.87079 5.75939 5.65675 - 5.55929 5.50983 5.45957 5.42589 5.40654 5.38219 - 5.36937 5.37042 5.36977 5.36885 5.36954 5.36948 - 9.75874 9.50287 9.14442 8.73591 8.32475 7.95164 - 7.61918 7.32308 7.05834 6.81819 6.59317 6.37767 - 6.17458 5.98681 5.81422 5.65348 5.50276 5.36300 - 5.23171 5.16623 5.10075 5.05309 5.01414 4.99331 - 4.98050 4.98039 4.97951 4.97893 4.97927 4.97901 - 10.42592 9.88179 9.36592 8.88831 8.44612 8.03745 - 7.66057 7.31425 6.99790 6.70942 6.44601 6.20417 - 5.97886 5.76688 5.56949 5.38621 5.21535 5.04880 - 4.88053 4.79888 4.72410 4.67075 4.61207 4.59710 - 4.58915 4.58832 4.58678 4.58673 4.58632 4.58599 - 10.96638 10.32976 9.68083 9.05284 8.47188 7.95947 - 7.51118 7.11619 6.76379 6.44362 6.14296 5.85506 - 5.58328 5.33014 5.09455 4.87313 4.66201 4.46265 - 4.27513 4.18461 4.09634 4.02635 3.95255 3.94109 - 3.92963 3.92724 3.92601 3.92612 3.92576 3.92494 - 11.34920 10.50392 9.74398 9.06103 8.44591 7.89196 - 7.39456 6.94710 6.54323 6.17800 5.84620 5.54158 - 5.25570 4.98279 4.72351 4.47960 4.25125 4.03480 - 3.82891 3.73045 3.63317 3.55740 3.48416 3.46457 - 3.44928 3.44763 3.44617 3.44593 3.44581 3.44561 - 11.55311 10.62167 9.79686 9.05971 8.40004 7.80886 - 7.27968 6.80421 6.37432 5.98451 5.62989 5.30470 - 5.00150 4.71496 4.44462 4.19002 3.95065 3.72313 - 3.50635 3.40224 3.29899 3.21852 3.14160 3.12030 - 3.10395 3.10222 3.10060 3.10033 3.10020 3.10126 - 11.68317 10.69121 9.82299 9.04936 8.35981 7.74393 - 7.19309 6.69770 6.24847 5.83995 5.46764 5.12668 - 4.81090 4.51559 4.23887 3.97778 3.73019 3.49435 - 3.26967 3.16157 3.05402 2.96914 2.88667 2.86611 - 2.84954 2.84758 2.84582 2.84552 2.84541 2.84717 - 11.83797 10.76612 9.84335 9.02345 8.29591 7.64925 - 7.07192 6.55295 6.08232 5.65424 5.26408 4.90684 - 4.57645 4.26810 3.97945 3.70686 3.44736 3.19958 - 2.96142 2.84575 2.73054 2.63909 2.54842 2.52612 - 2.50879 2.50675 2.50477 2.50445 2.50435 2.50506 - 11.91879 10.79591 9.84220 8.99792 8.25198 7.59136 - 7.00275 6.47393 5.99429 5.55781 5.15968 4.79467 - 4.45653 4.14023 3.84319 3.56153 3.29187 3.03249 - 2.78135 2.65838 2.53587 2.43838 2.33989 2.31490 - 2.29537 2.29315 2.29120 2.29092 2.29076 2.28917 - 11.97442 10.80757 9.83111 8.96638 8.20558 7.53253 - 6.93495 6.40098 5.92001 5.48289 5.08022 4.70559 - 4.35686 4.03141 3.72509 3.43111 3.14388 2.86165 - 2.57951 2.43479 2.28784 2.16919 2.04937 2.01860 - 1.99392 1.99085 1.98864 1.98830 1.98813 1.98626 - 11.96323 10.78095 9.81090 8.95688 8.20797 7.54276 - 6.94929 6.41551 5.93116 5.49000 5.08683 4.71584 - 4.37002 4.04349 3.73267 3.43201 3.13537 2.83565 - 2.52425 2.36025 2.18518 2.03707 1.89311 1.85903 - 1.83128 1.82772 1.82444 1.82395 1.82367 1.82662 - 11.85378 10.71994 9.80117 8.98537 8.25938 7.60660 - 7.01955 6.49086 6.01416 5.58305 5.19083 4.82972 - 4.48992 4.16393 3.84906 3.54141 3.23351 2.90922 - 2.54872 2.34835 2.12809 1.93297 1.72874 1.68272 - 1.65768 1.65490 1.64809 1.64650 1.64755 1.65856 - 11.76748 10.66012 9.78122 9.00185 8.30408 7.67425 - 7.10568 6.59180 6.12688 5.70508 5.32024 4.96505 - 4.63016 4.30810 3.99552 3.68720 3.37304 3.03108 - 2.63316 2.40299 2.14273 1.90618 1.64924 1.58919 - 1.56677 1.56533 1.55552 1.55288 1.55538 1.57025 - 11.69307 10.61059 9.76787 9.01989 8.34708 7.73783 - 7.18620 6.68625 6.23275 5.82034 5.44327 5.09466 - 4.76553 4.44844 4.13953 3.83260 3.51536 3.16110 - 2.73438 2.48018 2.18575 1.91316 1.60707 1.53292 - 1.51208 1.51191 1.49961 1.49607 1.49989 1.51553 - 11.63045 10.56966 9.75895 9.03737 8.38626 7.79510 - 7.25863 6.77137 6.32850 5.92507 5.55569 5.21376 - 4.89064 4.57893 4.27439 3.96999 3.65170 3.28881 - 2.83944 2.56533 2.24167 1.93672 1.58502 1.49713 - 1.47614 1.47695 1.46262 1.45834 1.46324 1.47827 - 11.55076 10.52041 9.75784 9.07457 8.45586 7.89199 - 7.37850 6.91033 6.48322 6.09311 5.73578 5.40611 - 5.09721 4.80221 4.51460 4.22285 3.90863 3.53891 - 3.06022 2.75073 2.36278 1.98510 1.56878 1.47347 - 1.43011 1.42784 1.41792 1.41514 1.41877 1.43073 - 11.47937 10.47741 9.75427 9.10227 8.51021 7.96925 - 7.47564 7.02508 6.61388 6.23834 5.89440 5.57704 - 5.27930 4.99419 4.71517 4.43037 4.12031 3.74867 - 3.25286 2.92149 2.49307 2.06419 1.57772 1.46201 - 1.40522 1.40203 1.39155 1.38852 1.39154 1.40147 - 11.39948 10.43082 9.75859 9.15107 8.59951 8.09636 - 7.63837 7.22171 6.84301 6.49858 6.18404 5.89357 - 5.61877 5.35205 5.08872 4.82035 4.52895 4.17261 - 3.66908 3.30663 2.80411 2.27551 1.63748 1.46349 - 1.38484 1.37619 1.35400 1.35218 1.34865 1.36050 - 11.33840 10.39887 9.76323 9.18773 8.66456 8.18723 - 7.75290 7.35823 7.00024 6.67557 6.38020 6.10855 - 5.85234 5.60407 5.35907 5.10867 4.83397 4.48990 - 3.98574 3.61112 3.07740 2.49198 1.72387 1.49740 - 1.37430 1.36090 1.33645 1.33384 1.33043 1.33886 - 11.23939 10.35420 9.77590 9.24665 8.76116 8.31534 - 7.90794 7.53756 7.20311 6.90214 6.63137 6.38609 - 6.15903 5.94279 5.73109 5.51141 5.26259 4.94414 - 4.46271 4.08764 3.52431 2.86033 1.90516 1.61110 - 1.36860 1.34011 1.32090 1.31781 1.31224 1.31663 - 11.21128 10.34529 9.79078 9.28214 8.81522 8.38673 - 7.99583 7.64171 7.32373 7.03983 6.78700 6.56077 - 6.35406 6.15963 5.97132 5.77649 5.55414 5.26511 - 4.81425 4.44979 3.88172 3.17746 2.07905 1.71349 - 1.38252 1.33912 1.31132 1.30794 1.30003 1.30540 - 11.20327 10.34568 9.80286 9.30563 8.85021 8.43341 - 8.05421 7.71153 7.40458 7.13168 6.89063 6.67810 - 6.48848 6.31521 6.15047 5.97733 5.77130 5.49528 - 5.06285 4.71909 4.18737 3.48852 2.24353 1.79739 - 1.39937 1.34589 1.30599 1.30009 1.29667 1.29870 - 11.19349 10.34841 9.81522 9.32554 8.87679 8.46690 - 8.09520 7.76079 7.46301 7.19998 6.96897 6.76655 - 6.58792 6.42737 6.27794 6.12388 5.94104 5.68932 - 5.27891 4.94627 4.42767 3.72894 2.40557 1.89363 - 1.41588 1.35077 1.30301 1.29663 1.29241 1.29428 - 11.18024 10.35026 9.82978 9.35246 8.91530 8.51622 - 8.15475 7.83042 7.54305 7.29143 7.07368 6.88682 - 6.72555 6.58412 6.45675 6.32959 6.18059 5.97141 - 5.61427 5.31131 4.81679 4.11477 2.68578 2.08591 - 1.45617 1.36226 1.29978 1.29447 1.28462 1.28878 - 11.19532 10.36281 9.84062 9.36505 8.93257 8.54064 - 8.18790 7.87289 7.59439 7.35114 7.14144 6.96253 - 6.80937 6.67763 6.56564 6.46735 6.36325 6.19470 - 5.85649 5.56532 5.10583 4.43884 2.94125 2.25587 - 1.49407 1.37943 1.30025 1.29119 1.28357 1.28540 - 11.17091 10.36489 9.85743 9.39393 8.97158 8.58846 - 8.24356 7.93593 7.66491 7.43011 7.23102 7.06663 - 6.93460 6.83194 6.75445 6.68909 6.61528 6.49766 - 6.25214 6.01922 5.62088 5.00774 3.46887 2.62474 - 1.59431 1.43254 1.30478 1.29132 1.27534 1.28077 - 11.15298 10.37039 9.86898 9.40995 8.99109 8.61105 - 8.26926 7.96543 7.69962 7.47154 7.28056 7.12551 - 7.00362 6.91221 6.84897 6.80464 6.76229 6.68709 - 6.50201 6.31005 5.95453 5.38638 3.87660 2.95296 - 1.69048 1.47995 1.31307 1.29356 1.27696 1.27843 - 11.11140 10.37632 9.87936 9.42368 9.00809 8.63207 - 8.29509 7.99687 7.73745 7.51657 7.33376 7.18802 - 7.07706 6.99890 6.95234 6.92983 6.91905 6.89727 - 6.79866 6.66223 6.37359 5.88194 4.47133 3.46489 - 1.87674 1.58893 1.33173 1.30249 1.27330 1.27606 - 11.07485 10.37764 9.88312 9.42996 9.01686 8.64322 - 8.30877 8.01358 7.75795 7.54130 7.36251 7.22050 - 7.11395 7.04210 7.00526 6.99840 7.01082 7.01612 - 6.95028 6.84748 6.63833 6.25555 4.88683 3.80036 - 2.06599 1.71602 1.34956 1.29740 1.27806 1.27489 - 11.06629 10.38490 9.88485 9.42962 9.01706 8.64572 - 8.31460 8.02293 7.77020 7.55606 7.38001 7.24090 - 7.13584 7.06375 7.02825 7.03174 7.06907 7.10599 - 7.07614 6.99587 6.80171 6.42805 5.19362 4.19313 - 2.21768 1.79381 1.37430 1.32013 1.27453 1.27419 - 11.02757 10.37903 9.88789 9.43709 9.02608 8.65489 - 8.32318 8.03092 7.77832 7.56505 7.39051 7.25399 - 7.15419 7.09037 7.06295 7.06690 7.09457 7.13288 - 7.14444 7.10082 6.94061 6.59319 5.43560 4.46225 - 2.37305 1.89262 1.39635 1.32969 1.27515 1.27373 - 11.00357 10.37960 9.89008 9.44055 9.03081 8.66102 - 8.33086 8.04021 7.78920 7.57766 7.40518 7.27124 - 7.17457 7.11464 7.09229 7.10336 7.14166 7.19698 - 7.24027 7.22625 7.11751 6.83633 5.79637 4.87742 - 2.66393 2.07926 1.44024 1.34775 1.27882 1.27315 - 10.98850 10.38005 9.89140 9.44266 9.03373 8.66485 - 8.33565 8.04595 7.79583 7.58522 7.41397 7.28166 - 7.18698 7.12947 7.11019 7.12563 7.17052 7.23652 - 7.29938 7.30427 7.23256 7.00287 6.05561 5.19023 - 2.92257 2.25116 1.48374 1.36660 1.28319 1.27280 - 10.96640 10.38054 9.89283 9.44519 9.03744 8.66980 - 8.34191 8.05367 7.80521 7.59625 7.42629 7.29506 - 7.20245 7.14883 7.13503 7.15648 7.20846 7.28933 - 7.38463 7.41644 7.38907 7.23842 6.51365 5.74503 - 3.43122 2.62084 1.59279 1.41473 1.30594 1.27234 - 10.95375 10.38102 9.89384 9.44668 9.03945 8.67232 - 8.34501 8.05737 7.80957 7.60136 7.43223 7.30206 - 7.21084 7.15907 7.14771 7.17222 7.22830 7.31603 - 7.42768 7.47666 7.47732 7.36431 6.76919 6.13156 - 3.84005 2.92434 1.69538 1.47378 1.31672 1.27211 - 10.93995 10.38150 9.89519 9.44855 9.04169 8.67496 - 8.34799 8.06067 7.81317 7.60553 7.43782 7.30984 - 7.22052 7.16973 7.15932 7.18700 7.25031 7.34785 - 7.46737 7.52533 7.56898 7.53572 7.06322 6.52867 - 4.49015 3.45373 1.88263 1.57609 1.33203 1.27188 - 10.93310 10.38183 9.89573 9.44930 9.04267 8.67613 - 8.34941 8.06238 7.81525 7.60808 7.44087 7.31344 - 7.22479 7.17485 7.16559 7.19484 7.26051 7.36220 - 7.48996 7.55536 7.61223 7.60886 7.25203 6.80206 - 4.92590 3.84721 2.06033 1.68060 1.35550 1.27177 - 10.94810 10.38789 9.89446 9.44508 9.03822 8.67269 - 8.34764 8.06247 7.81690 7.61086 7.44421 7.31627 - 7.22486 7.17000 7.15724 7.19264 7.27765 7.39179 - 7.50939 7.56972 7.63112 7.65041 7.38107 6.98519 - 5.24574 4.16694 2.23292 1.78331 1.37699 1.27171 - 10.94483 10.38796 9.89464 9.44539 9.03865 8.67324 - 8.34829 8.06325 7.81782 7.61190 7.44542 7.31771 - 7.22656 7.17205 7.15980 7.19589 7.28189 7.39756 - 7.51815 7.58163 7.64972 7.68218 7.46444 7.11948 - 5.49972 4.42926 2.39310 1.88568 1.39892 1.27167 - 10.92129 10.38203 9.89633 9.45026 9.04401 8.67796 - 8.35175 8.06526 7.81865 7.61203 7.44550 7.31893 - 7.23134 7.18272 7.17515 7.20676 7.27594 7.38332 - 7.52432 7.60291 7.67981 7.72089 7.57356 7.29527 - 5.87099 4.84249 2.68183 2.08521 1.44224 1.27163 - 10.91851 10.38191 9.89631 9.45031 9.04414 8.67816 - 8.35207 8.06572 7.81929 7.61287 7.44649 7.32006 - 7.23263 7.18429 7.17713 7.20925 7.27916 7.38802 - 7.53109 7.61152 7.69521 7.74742 7.63423 7.40257 - 6.12869 5.15555 2.93715 2.26949 1.48291 1.27161 - 0.56172 0.58540 0.61066 0.63755 0.66593 0.69560 - 0.72662 0.75915 0.79346 0.82993 0.86916 0.91179 - 0.95819 1.00808 1.05930 1.10632 1.14278 1.16757 - 1.18505 1.19414 1.20214 1.20606 1.20609 1.20640 - 1.20631 1.20618 1.20614 1.20617 1.20614 1.20616 - 0.79771 0.83186 0.86825 0.90676 0.94677 0.98757 - 1.02912 1.07173 1.11593 1.16239 1.21218 1.26604 - 1.32346 1.38319 1.44274 1.49668 1.53867 1.56655 - 1.58361 1.59156 1.59895 1.60233 1.60081 1.60441 - 1.60584 1.60543 1.60544 1.60561 1.60546 1.60547 - 1.02355 1.06962 1.11623 1.16362 1.21177 1.26071 - 1.31059 1.36171 1.41459 1.46943 1.52635 1.58560 - 1.64765 1.71219 1.77638 1.83381 1.87786 1.90929 - 1.92939 1.93527 1.94230 1.94827 1.94904 1.95201 - 1.95388 1.95374 1.95371 1.95388 1.95375 1.95374 - 1.44615 1.50885 1.57111 1.63324 1.69507 1.75652 - 1.81769 1.87899 1.94111 2.00416 2.06805 2.13276 - 2.19857 2.26509 2.32983 2.38780 2.43403 2.46913 - 2.49386 2.50224 2.51154 2.52057 2.52839 2.52920 - 2.53033 2.53059 2.53074 2.53073 2.53076 2.53071 - 1.82730 1.90335 1.97705 2.04900 2.11919 2.18779 - 2.25490 2.32094 2.38665 2.45217 2.51756 2.58262 - 2.64699 2.70994 2.76990 2.82460 2.87141 2.90893 - 2.93748 2.94974 2.96238 2.97380 2.98698 2.98759 - 2.98695 2.98729 2.98784 2.98785 2.98787 2.98782 - 2.16995 2.25789 2.34059 2.41904 2.49364 2.56516 - 2.63402 2.70105 2.76751 2.83300 2.89651 2.95732 - 3.01630 3.07405 3.12939 3.18042 3.22524 3.26375 - 3.29690 3.31193 3.32642 3.34031 3.36037 3.35664 - 3.35658 3.35779 3.35806 3.35773 3.35808 3.35798 - 2.47953 2.57748 2.66679 2.74900 2.82524 2.89720 - 2.96553 3.03122 3.09566 3.15832 3.21781 3.27330 - 3.32631 3.37809 3.42787 3.47454 3.51712 3.55619 - 3.59258 3.60961 3.62613 3.64205 3.66517 3.66073 - 3.66059 3.66199 3.66230 3.66192 3.66233 3.66224 - 3.01482 3.12786 3.22533 3.30991 3.38428 3.45201 - 3.51425 3.57228 3.62792 3.68066 3.72911 3.77264 - 3.81339 3.85336 3.89247 3.93065 3.96817 4.00639 - 4.04604 4.06565 4.08502 4.10291 4.12711 4.12421 - 4.12488 4.12621 4.12656 4.12623 4.12660 4.12654 - 3.46251 3.58577 3.68674 3.76925 3.83755 3.89708 - 3.94944 3.99631 4.03997 4.08027 4.11627 4.14791 - 4.17732 4.20670 4.23637 4.26690 4.29919 4.33483 - 4.37454 4.39508 4.41583 4.43372 4.45487 4.45568 - 4.45782 4.45873 4.45908 4.45894 4.45914 4.45915 - 4.32999 4.46580 4.56402 4.63152 4.67651 4.70876 - 4.73122 4.74647 4.75804 4.76677 4.77338 4.77874 - 4.78442 4.79215 4.80267 4.81702 4.83642 4.86207 - 4.89457 4.91313 4.93297 4.94694 4.95558 4.96605 - 4.97168 4.97126 4.97154 4.97193 4.97165 4.97182 - 4.97061 5.10844 5.19549 5.24191 5.25975 5.26285 - 5.25544 5.24100 5.22399 5.20605 5.18858 5.17282 - 5.15980 5.15067 5.14624 5.14719 5.15431 5.16804 - 5.18875 5.20209 5.21739 5.22560 5.22267 5.23904 - 5.24649 5.24508 5.24527 5.24601 5.24540 5.24562 - 5.88907 6.01572 6.07064 6.07055 6.03463 5.98389 - 5.92465 5.86159 5.80006 5.74218 5.68897 5.64108 - 5.59937 5.56427 5.53627 5.51499 5.49984 5.49012 - 5.48554 5.48611 5.48900 5.48615 5.46881 5.48705 - 5.49421 5.49202 5.49201 5.49294 5.49211 5.49234 - 6.55554 6.66064 6.67870 6.63251 6.54748 6.45040 - 6.34878 6.24762 6.15229 6.06452 5.98447 5.91184 - 5.84754 5.79162 5.74423 5.70415 5.66986 5.64011 - 5.61399 5.60311 5.59423 5.58304 5.55986 5.57331 - 5.57776 5.57569 5.57552 5.57630 5.57557 5.57576 - 7.08817 7.16649 7.14644 7.05634 6.92697 6.78973 - 6.65270 6.52035 6.39759 6.28546 6.18328 6.08998 - 6.00636 5.93235 5.86778 5.81102 5.76015 5.71381 - 5.67054 5.65034 5.63156 5.61454 5.59067 5.59643 - 5.59724 5.59575 5.59546 5.59590 5.59544 5.59559 - 7.53702 7.58557 7.52738 7.39583 7.22620 7.05364 - 6.88628 6.72758 6.58150 6.44851 6.32716 6.21581 - 6.11497 6.02466 5.94446 5.87259 5.80711 5.74688 - 5.68994 5.66222 5.63523 5.61408 5.59227 5.58941 - 5.58635 5.58563 5.58524 5.58528 5.58516 5.58528 - 8.44759 8.23811 8.02337 7.81451 7.61135 7.41406 - 7.22287 7.03783 6.85960 6.68935 6.52760 6.37467 - 6.23192 6.10116 5.98350 5.88080 5.79397 5.71915 - 5.65474 5.62965 5.61118 5.59458 5.52822 5.49623 - 5.50533 5.51098 5.50824 5.50642 5.50909 5.50770 - 8.80958 8.72613 8.52422 8.25117 7.95294 7.67205 - 7.41467 7.17992 6.96678 6.77327 6.59463 6.42751 - 6.27234 6.13024 6.00037 5.88066 5.76954 5.66729 - 5.57128 5.52291 5.47370 5.44057 5.42121 5.39716 - 5.38445 5.38546 5.38482 5.38393 5.38460 5.38454 - 9.74059 9.49082 9.13697 8.73188 8.32346 7.95298 - 7.62301 7.32912 7.06613 6.82741 6.60363 6.38942 - 6.18777 6.00166 5.83073 5.67126 5.52114 5.38182 - 5.25188 5.18773 5.12357 5.07658 5.03744 5.01680 - 5.00401 5.00387 5.00299 5.00240 5.00273 5.00249 - 10.41314 9.87377 9.36213 8.88820 8.44922 8.04334 - 7.66885 7.32462 7.01002 6.72307 6.46101 6.22039 - 5.99631 5.78558 5.58952 5.40766 5.23828 5.07319 - 4.90633 4.82550 4.75187 4.69966 4.64121 4.62583 - 4.61784 4.61705 4.61547 4.61541 4.61502 4.61468 - 10.95673 10.32776 9.68397 9.05923 8.48054 7.97019 - 7.52380 7.13057 6.77970 6.46091 6.16156 5.87501 - 5.60472 5.35330 5.11957 4.89994 4.69029 4.49198 - 4.30571 4.21639 4.12937 4.06021 3.98674 3.97518 - 3.96368 3.96131 3.96008 3.96018 3.95982 3.95901 - 11.34312 10.50375 9.74844 9.06904 8.45672 7.90497 - 7.40932 6.96338 6.56095 6.19713 5.86679 5.56367 - 5.27933 5.00803 4.75038 4.50806 4.28122 4.06614 - 3.86151 3.76368 3.66715 3.59205 3.51935 3.49995 - 3.48478 3.48315 3.48171 3.48148 3.48135 3.48115 - 11.54844 10.62236 9.80174 9.06794 8.41099 7.82208 - 7.29482 6.82107 6.39281 6.00460 5.65154 5.32788 - 5.02614 4.74098 4.47200 4.21883 3.98099 3.75485 - 3.53909 3.43532 3.33232 3.25209 3.17601 3.15506 - 3.13894 3.13723 3.13564 3.13537 3.13524 3.13630 - 11.67934 10.69188 9.82738 9.05691 8.37012 7.75667 - 7.20799 6.71452 6.26706 5.86016 5.48938 5.14988 - 4.83552 4.54155 4.26616 4.00639 3.76009 3.52542 - 3.30163 3.19376 3.08617 3.00117 2.91951 2.89944 - 2.88314 2.88118 2.87945 2.87917 2.87904 2.88081 - 11.83380 10.76580 9.84622 9.02929 8.30446 7.66032 - 7.08529 6.56837 6.09954 5.67304 5.28431 4.92838 - 4.59924 4.29213 4.00470 3.73335 3.47509 3.22839 - 2.99095 2.87536 2.75984 2.66796 2.57775 2.55583 - 2.53868 2.53663 2.53467 2.53437 2.53425 2.53496 - 11.91295 10.79393 9.84330 9.00189 8.25861 7.60044 - 7.01403 6.48717 6.00917 5.57406 5.17715 4.81327 - 4.47626 4.16119 3.86546 3.58513 3.31678 3.05855 - 2.80815 2.68528 2.56248 2.46450 2.36594 2.34106 - 2.32154 2.31930 2.31736 2.31709 2.31691 2.31534 - 11.96910 10.79613 9.82075 8.96172 8.20807 7.54113 - 6.94750 6.41418 5.93009 5.48904 5.08604 4.71564 - 4.37124 4.04747 3.74120 3.44776 3.16243 2.88101 - 2.59953 2.45667 2.30998 2.18976 2.06906 2.03843 - 2.01358 2.01066 2.00835 2.00805 2.00775 2.00596 - 11.94546 10.76953 9.80375 8.95311 8.20679 7.54364 - 6.95174 6.41915 5.93565 5.49514 5.09255 4.72225 - 4.37745 4.05240 3.74341 3.44468 3.14983 2.85157 - 2.54101 2.37714 2.20197 2.05361 1.90943 1.87533 - 1.84752 1.84394 1.84066 1.84018 1.83989 1.84283 - 11.82652 10.70063 9.78703 8.97520 8.25220 7.60168 - 7.01628 6.48880 6.01295 5.58244 5.19069 4.83009 - 4.49103 4.16615 3.85273 3.54687 3.24096 2.91856 - 2.55949 2.35956 2.13953 1.94451 1.74088 1.69524 - 1.67044 1.66766 1.66084 1.65926 1.66032 1.67129 - 11.75147 10.64213 9.76297 8.98562 8.29123 7.66520 - 7.09976 6.58718 6.12075 5.69543 5.30655 4.94877 - 4.61545 4.30023 3.99740 3.69736 3.38696 3.04588 - 2.64644 2.41305 2.14609 1.90394 1.65696 1.60605 - 1.57887 1.57534 1.56647 1.56446 1.56617 1.58146 - 11.67222 10.59196 9.75080 9.00490 8.33432 7.72703 - 7.17654 6.67624 6.22042 5.80446 5.42387 5.07348 - 4.74672 4.43712 4.13851 3.84036 3.52749 3.17533 - 2.74849 2.49072 2.18701 1.90575 1.61192 1.55078 - 1.52389 1.52085 1.50975 1.50707 1.50978 1.52608 - 11.60712 10.55040 9.74188 9.02219 8.37262 7.78245 - 7.24609 6.75773 6.31228 5.90548 5.53300 5.18982 - 4.86940 4.56523 4.27090 3.97523 3.66164 3.30214 - 2.85469 2.57712 2.24205 1.92561 1.58767 1.51586 - 1.48798 1.48531 1.47235 1.46910 1.47266 1.48855 - 11.50711 10.48675 9.73040 9.05202 8.43708 7.87606 - 7.36457 6.89762 6.47103 6.08095 5.72341 5.39362 - 5.08520 4.79153 4.50604 4.21686 3.90528 3.53793 - 3.06109 2.75252 2.36584 1.98982 1.57677 1.48266 - 1.44010 1.43781 1.42780 1.42506 1.42891 1.44094 - 11.43398 10.44176 9.72449 9.07737 8.48925 7.95136 - 7.46005 7.01095 6.60042 6.22489 5.88063 5.56296 - 5.26548 4.98156 4.70456 4.42233 4.11502 3.74598 - 3.25237 2.92213 2.49526 2.06833 1.58544 1.47106 - 1.41523 1.41206 1.40148 1.39850 1.40177 1.41182 - 11.31590 10.37677 9.72374 9.12915 8.58540 8.08607 - 7.62896 7.21145 6.83138 6.48547 6.16973 5.87888 - 5.60524 5.34117 5.07992 4.80914 4.51018 4.15151 - 3.66079 3.30903 2.81427 2.28086 1.63549 1.48026 - 1.39432 1.38493 1.36453 1.36003 1.36289 1.37125 - 11.25393 10.34452 9.72822 9.16555 8.64987 8.17589 - 7.74195 7.34604 6.98647 6.66037 6.36401 6.09225 - 5.83749 5.59202 5.34899 5.09552 4.81212 4.46553 - 3.97627 3.61368 3.08756 2.49514 1.72020 1.51575 - 1.38410 1.36925 1.34713 1.34260 1.34469 1.34993 - 11.19381 10.31616 9.74183 9.21620 8.73396 8.29096 - 7.88588 7.51720 7.18369 6.88302 6.61208 6.36649 - 6.13940 5.92376 5.71333 5.49553 5.24918 4.93369 - 4.45582 4.08300 3.52253 2.86174 1.91164 1.61940 - 1.37912 1.35102 1.33205 1.32899 1.32358 1.32810 - 11.17386 10.31006 9.75595 9.24888 8.78437 8.35869 - 7.97057 7.61851 7.30141 7.01740 6.76411 6.53807 - 6.33364 6.14406 5.96084 5.76635 5.53641 5.23730 - 4.78613 4.43429 3.89655 3.21136 2.07624 1.70607 - 1.39603 1.35498 1.32185 1.31759 1.31419 1.31709 - 11.16015 10.30875 9.76858 9.27384 8.82071 8.40600 - 8.02861 7.68739 7.38141 7.10912 6.86839 6.65609 - 6.46688 6.29443 6.13088 5.95904 5.75447 5.48063 - 5.05202 4.71101 4.18267 3.48740 2.24826 1.80478 - 1.41006 1.35712 1.31757 1.31173 1.30835 1.31054 - 11.15160 10.31018 9.77931 9.29288 8.84750 8.44034 - 8.07047 7.73695 7.43906 7.17542 6.94416 6.74235 - 6.56499 6.40616 6.25854 6.10569 5.92318 5.67242 - 5.26628 4.93741 4.42207 3.72613 2.40902 1.90098 - 1.42659 1.36177 1.31516 1.30795 1.30435 1.30621 - 11.13892 10.31444 9.79580 9.32007 8.88433 8.48652 - 8.12622 7.80299 7.51669 7.26612 7.04936 6.86344 - 6.70300 6.56226 6.43551 6.30902 6.16097 5.95343 - 5.59944 5.29901 4.80811 4.11035 2.68859 2.09199 - 1.46651 1.37338 1.31162 1.30639 1.29659 1.30083 - 11.15517 10.32730 9.80643 9.33214 8.90093 8.51020 - 8.15865 7.84481 7.56744 7.32526 7.11658 6.93860 - 6.78626 6.65523 6.54383 6.44608 6.34264 6.17532 - 5.83973 5.55087 5.09504 4.43270 2.94291 2.26096 - 1.50416 1.39047 1.31216 1.30316 1.29561 1.29753 - 11.13051 10.32919 9.82310 9.36093 8.93985 8.55794 - 8.21418 7.90767 7.63772 7.40393 7.20577 7.04221 - 6.91083 6.80865 6.73146 6.66638 6.59298 6.47611 - 6.23242 6.00141 5.60639 4.99776 3.46775 2.62826 - 1.60374 1.44307 1.31668 1.30342 1.28745 1.29303 - 11.11250 10.33450 9.83461 9.37701 8.95950 8.58073 - 8.24013 7.93741 7.67261 7.44543 7.25525 7.10085 - 6.97945 6.88837 6.82532 6.78119 6.73920 6.66456 - 6.48060 6.29000 5.93736 5.37381 3.87358 2.95461 - 1.69921 1.49011 1.32493 1.30557 1.28917 1.29076 - 11.07137 10.34003 9.84464 9.39063 8.97669 8.60214 - 8.26640 7.96925 7.71071 7.49054 7.30829 7.16302 - 7.05242 6.97448 6.92809 6.90573 6.89516 6.87362 - 6.77559 6.64000 6.35338 5.86557 4.46503 3.46399 - 1.88423 1.59824 1.34336 1.31450 1.28553 1.28848 - 11.03538 10.34126 9.84829 9.39689 8.98552 8.61340 - 8.28020 7.98603 7.73121 7.51518 7.33689 7.19530 - 7.08908 7.01747 6.98078 6.97401 6.98650 6.99189 - 6.92644 6.82423 6.61660 6.23681 4.87755 3.79736 - 2.07264 1.72475 1.36091 1.30927 1.29021 1.28735 - 11.00815 10.34202 9.85087 9.40092 8.99088 8.62021 - 8.28864 7.99629 7.74348 7.52971 7.35398 7.21531 - 7.11253 7.04511 7.01389 7.01476 7.03897 7.06455 - 7.03492 6.95941 6.78795 6.45782 5.19980 4.11524 - 2.23140 1.82518 1.38327 1.31793 1.29382 1.28668 - 10.98857 10.34275 9.85317 9.40408 8.99473 8.62498 - 8.29453 8.00327 7.75141 7.53870 7.36465 7.22861 - 7.12918 7.06557 7.03821 7.04216 7.06982 7.10811 - 7.11981 7.07653 6.91710 6.57175 5.42294 4.45584 - 2.37757 1.90000 1.40739 1.34148 1.28736 1.28623 - 10.96477 10.34352 9.85550 9.40758 8.99935 8.63090 - 8.30190 8.01222 7.76202 7.55116 7.37924 7.24577 - 7.14947 7.08973 7.06742 7.07845 7.11665 7.17184 - 7.21518 7.20139 7.09317 6.81347 5.78111 4.86829 - 2.66681 2.08567 1.45093 1.35934 1.29098 1.28567 - 10.94988 10.34398 9.85692 9.40971 9.00218 8.63455 - 8.30644 8.01770 7.76846 7.55862 7.38798 7.25614 - 7.16179 7.10446 7.08525 7.10063 7.14535 7.21113 - 7.27395 7.27901 7.20771 6.97918 6.03841 5.17895 - 2.92408 2.25674 1.49411 1.37798 1.29531 1.28533 - 10.92757 10.34467 9.85878 9.41255 9.00602 8.63950 - 8.31260 8.02509 7.77706 7.56857 7.39963 7.26997 - 7.17834 7.12430 7.10937 7.13066 7.18431 7.26495 - 7.35454 7.38578 7.37106 7.22901 6.45916 5.71422 - 3.45633 2.63240 1.59955 1.42777 1.30724 1.28487 - 10.91517 10.34505 9.85964 9.41396 9.00800 8.64204 - 8.31569 8.02878 7.78141 7.57366 7.40561 7.27703 - 7.18674 7.13441 7.12172 7.14612 7.20439 7.29309 - 7.39698 7.44141 7.45638 7.36611 6.72165 6.06517 - 3.87105 2.94888 1.70095 1.48005 1.31952 1.28464 - 10.90205 10.34533 9.86042 9.41538 9.01007 8.64466 - 8.31881 8.03245 7.78574 7.57880 7.41164 7.28412 - 7.19513 7.14453 7.13416 7.16170 7.22472 7.32189 - 7.44099 7.49875 7.54239 7.50946 7.03928 6.50824 - 4.48347 3.45313 1.89028 1.58547 1.34378 1.28439 - 10.89529 10.34537 9.86079 9.41606 9.01108 8.64595 - 8.32036 8.03427 7.78791 7.58136 7.41468 7.28768 - 7.19935 7.14960 7.14035 7.16946 7.23481 7.33612 - 7.46347 7.52861 7.58537 7.58220 7.22715 6.77994 - 4.91677 3.84441 2.06693 1.68918 1.36709 1.28427 - 10.90975 10.35173 9.85994 9.41210 9.00665 8.64238 - 8.31843 8.03423 7.78951 7.58416 7.41805 7.29055 - 7.19941 7.14470 7.13198 7.16720 7.25187 7.36557 - 7.48274 7.54288 7.60419 7.62356 7.35554 6.96212 - 5.23464 4.16218 2.23840 1.79119 1.38838 1.28420 - 10.90661 10.35180 9.86013 9.41242 9.00708 8.64291 - 8.31908 8.03500 7.79039 7.58518 7.41925 7.29194 - 7.20108 7.14673 7.13448 7.17039 7.25605 7.37127 - 7.49141 7.55471 7.62267 7.65512 7.43850 7.09568 - 5.48695 4.42280 2.39758 1.89292 1.41015 1.28416 - 10.88363 10.34586 9.86161 9.41710 9.01235 8.64758 - 8.32248 8.03695 7.79119 7.58532 7.41935 7.29318 - 7.20581 7.15729 7.14969 7.18117 7.25012 7.35710 - 7.49755 7.57593 7.65261 7.69363 7.54722 7.27035 - 5.85570 4.83335 2.68459 2.09120 1.45311 1.28412 - 10.88078 10.34594 9.86191 9.41732 9.01241 8.64761 - 8.32262 8.03729 7.79179 7.58616 7.42038 7.29431 - 7.20711 7.15886 7.15168 7.18370 7.25337 7.36184 - 7.50433 7.58447 7.66790 7.72000 7.60740 7.37692 - 6.11148 5.14424 2.93847 2.27452 1.49345 1.28412 - 0.55250 0.57596 0.60092 0.62749 0.65557 0.68502 - 0.71588 0.74823 0.78222 0.81819 0.85678 0.89864 - 0.94410 0.99288 1.04292 1.08897 1.12509 1.15061 - 1.16930 1.17844 1.18646 1.19069 1.19136 1.19138 - 1.19199 1.19207 1.19202 1.19201 1.19200 1.19201 - 0.78577 0.81968 0.85575 0.89389 0.93353 0.97403 - 1.01532 1.05764 1.10143 1.14735 1.19644 1.24945 - 1.30588 1.36452 1.42299 1.47615 1.51806 1.54692 - 1.56554 1.57389 1.58179 1.58601 1.58376 1.58456 - 1.58984 1.59057 1.59038 1.59033 1.59027 1.59033 - 1.00934 1.05501 1.10125 1.14829 1.19611 1.24472 - 1.29426 1.34501 1.39744 1.45175 1.50803 1.56651 - 1.62767 1.69121 1.75446 1.81137 1.85570 1.88810 - 1.90967 1.91645 1.92437 1.93112 1.93120 1.93207 - 1.93728 1.93807 1.93785 1.93795 1.93774 1.93787 - 1.42811 1.49037 1.55220 1.61395 1.67542 1.73655 - 1.79740 1.85838 1.92013 1.98276 2.04618 2.11035 - 2.17558 2.24148 2.30571 2.36355 2.41025 2.44645 - 2.47286 2.48226 2.49248 2.50205 2.51108 2.51305 - 2.51352 2.51352 2.51376 2.51378 2.51382 2.51381 - 1.80626 1.88169 1.95506 2.02686 2.09684 2.16502 - 2.23157 2.29718 2.36292 2.42869 2.49398 2.55831 - 2.62194 2.68474 2.74510 2.80029 2.84739 2.88555 - 2.91603 2.92962 2.94261 2.95397 2.97173 2.97431 - 2.97020 2.96958 2.97009 2.97020 2.97029 2.97022 - 2.14654 2.23403 2.31633 2.39440 2.46871 2.54003 - 2.60876 2.67575 2.74219 2.80771 2.87120 2.93192 - 2.99087 3.04870 3.10428 3.15575 3.20126 3.24080 - 3.27545 3.29141 3.30665 3.32045 3.34423 3.34724 - 3.34007 3.33902 3.33974 3.33990 3.34004 3.33992 - 2.45425 2.55172 2.64065 2.72254 2.79857 2.87043 - 2.93876 3.00453 3.06914 3.13200 3.19170 3.24735 - 3.30057 3.35267 3.40293 3.45022 3.49356 3.53359 - 3.57132 3.58919 3.60631 3.62193 3.64925 3.65261 - 3.64409 3.64283 3.64366 3.64386 3.64402 3.64388 - 2.98682 3.09937 3.19654 3.28095 3.35531 3.42316 - 3.48562 3.54400 3.60012 3.65341 3.70239 3.74643 - 3.78775 3.82840 3.86830 3.90731 3.94564 3.98474 - 4.02548 4.04564 4.06536 4.08286 4.11068 4.11462 - 4.10797 4.10697 4.10777 4.10795 4.10811 4.10798 - 3.43272 3.55552 3.65631 3.73883 3.80732 3.86716 - 3.91997 3.96741 4.01177 4.05285 4.08967 4.12206 - 4.15227 4.18254 4.21316 4.24461 4.27773 4.31425 - 4.35483 4.37564 4.39655 4.41426 4.43731 4.44165 - 4.44026 4.44002 4.44060 4.44070 4.44079 4.44074 - 4.29793 4.43355 4.53193 4.59988 4.64552 4.67853 - 4.70183 4.71805 4.73069 4.74060 4.74838 4.75485 - 4.76161 4.77042 4.78201 4.79731 4.81755 4.84412 - 4.87724 4.89553 4.91529 4.92996 4.93592 4.94040 - 4.95320 4.95499 4.95487 4.95479 4.95470 4.95484 - 4.93794 5.07589 5.16348 5.21076 5.22963 5.23383 - 5.22757 5.21435 5.19862 5.18199 5.16580 5.15129 - 5.13945 5.13144 5.12803 5.12988 5.13782 5.15258 - 5.17387 5.18672 5.20191 5.21157 5.20325 5.20699 - 5.22868 5.23177 5.23113 5.23090 5.23068 5.23095 - 5.85704 5.98452 6.04070 6.04209 6.00777 5.95863 - 5.90093 5.83935 5.77923 5.72271 5.67084 5.62427 - 5.58375 5.54969 5.52255 5.50206 5.48778 5.47924 - 5.47538 5.47551 5.47844 5.47778 5.45406 5.45538 - 5.48065 5.48434 5.48326 5.48290 5.48262 5.48296 - 6.52499 6.63151 6.65136 6.60712 6.52407 6.42889 - 6.32908 6.22957 6.13573 6.04932 5.97061 5.89930 - 5.83618 5.78122 5.73460 5.69524 5.66187 5.63332 - 5.60804 5.59700 5.58836 5.57928 5.55121 5.55013 - 5.56966 5.57256 5.57149 5.57117 5.57092 5.57121 - 7.05929 7.13951 7.12168 7.03386 6.90672 6.77162 - 6.63655 6.50599 6.38478 6.27402 6.17321 6.08127 - 5.99883 5.92573 5.86189 5.80586 5.75593 5.71072 - 5.66834 5.64828 5.62988 5.61439 5.58805 5.58497 - 5.59470 5.59618 5.59537 5.59516 5.59501 5.59517 - 7.50984 7.56064 7.50498 7.37594 7.20872 7.03846 - 6.87320 6.71639 6.57197 6.44042 6.32048 6.21052 - 6.11090 6.02151 5.94204 5.87093 5.80641 5.74717 - 5.69108 5.66379 5.63730 5.61688 5.59517 5.59043 - 5.58908 5.58896 5.58849 5.58839 5.58834 5.58837 - 8.42434 8.21744 8.00535 7.79901 7.59825 7.40326 - 7.21424 7.03125 6.85495 6.68653 6.52645 6.37508 - 6.23373 6.10424 5.98768 5.88590 5.79979 5.72546 - 5.66134 5.63639 5.61834 5.60326 5.54347 5.51360 - 5.51673 5.52037 5.51713 5.51567 5.51803 5.51669 - 8.78837 8.70808 8.50948 8.23952 7.94415 7.66586 - 7.41084 7.17816 6.96683 6.77491 6.59781 6.43224 - 6.27848 6.13753 6.00864 5.88992 5.77986 5.67824 - 5.58292 5.53556 5.48705 5.45261 5.43900 5.42987 - 5.40197 5.39800 5.39828 5.39848 5.39865 5.39838 - 9.72513 9.47904 9.12901 8.72743 8.32213 7.95432 - 7.62664 7.33466 7.07321 6.83585 6.61351 6.40093 - 6.20093 6.01636 5.84686 5.68873 5.53980 5.40131 - 5.27218 5.20887 5.14541 5.09789 5.06214 5.05008 - 5.02881 5.02585 5.02549 5.02554 5.02559 5.02541 - 10.40166 9.86658 9.35893 8.88847 8.45249 8.04922 - 7.67698 7.33467 7.02175 6.73624 6.47548 6.23611 - 6.01332 5.80405 5.60954 5.42936 5.26171 5.09804 - 4.93204 4.85173 4.77931 4.72809 4.66651 4.64947 - 4.64532 4.64568 4.64404 4.64370 4.64345 4.64359 - 10.94964 10.32529 9.68598 9.06516 8.48979 7.98203 - 7.53761 7.14574 6.79575 6.47765 6.17934 5.89436 - 5.62596 5.37660 5.14493 4.92712 4.71895 4.52217 - 4.33730 4.24828 4.16169 4.09361 4.01889 4.00237 - 3.99636 3.99576 3.99422 3.99394 3.99375 3.99377 - 11.33694 10.50331 9.75273 9.07713 8.46784 7.91849 - 7.42474 6.98035 6.57923 6.21663 5.88746 5.58561 - 5.30281 5.03335 4.77770 4.53725 4.31191 4.09817 - 3.89482 3.79756 3.70138 3.62636 3.55467 3.53647 - 3.52024 3.51825 3.51691 3.51670 3.51661 3.51653 - 11.54040 10.61908 9.80341 9.07460 8.42242 7.83779 - 7.31400 6.84255 6.41507 6.02651 5.67259 5.34840 - 5.04763 4.76545 4.50041 4.25008 4.01269 3.78647 - 3.57193 3.46919 3.36693 3.28659 3.21078 3.19195 - 3.17408 3.17163 3.17009 3.17000 3.16970 3.16975 - 11.67166 10.69039 9.83080 9.06436 8.38078 7.76999 - 7.22348 6.73188 6.28615 5.88085 5.51160 5.17357 - 4.86065 4.56810 4.29408 4.03561 3.79049 3.55688 - 3.33400 3.22653 3.11924 3.03442 2.95328 2.93348 - 2.91648 2.91427 2.91251 2.91231 2.91212 2.91214 - 11.82620 10.76383 9.84836 9.03456 8.31216 7.67001 - 7.09678 6.58174 6.11511 5.69106 5.30484 4.95125 - 4.62395 4.31801 4.03133 3.76074 3.50343 3.25739 - 3.01997 2.90442 2.78946 2.69828 2.60739 2.58517 - 2.56837 2.56633 2.56438 2.56420 2.56393 2.56395 - 11.89851 10.78712 9.84209 9.00494 8.26486 7.60909 - 7.02461 6.49944 6.02309 5.58968 5.19445 4.83226 - 4.49687 4.18327 3.88887 3.60964 3.34208 3.08430 - 2.83407 2.71128 2.58870 2.49100 2.39237 2.36735 - 2.34806 2.34593 2.34400 2.34367 2.34354 2.34340 - 11.94772 10.78367 9.81428 8.95950 8.20873 7.54373 - 6.95148 6.41934 5.93656 5.49701 5.09566 4.72701 - 4.38442 4.06244 3.75786 3.46587 3.18160 2.90079 - 2.61944 2.47656 2.33000 2.21006 2.08981 2.05930 - 2.03449 2.03159 2.02928 2.02896 2.02867 2.02838 - 11.91974 10.75262 9.79270 8.94614 8.20256 7.54123 - 6.95061 6.41910 5.93679 5.49761 5.09653 4.72788 - 4.38488 4.06176 3.75470 3.45779 3.16446 2.86736 - 2.55750 2.39387 2.21897 2.07086 1.92673 1.89259 - 1.86487 1.86131 1.85803 1.85758 1.85729 1.85832 - 11.79645 10.67707 9.76797 8.95970 8.23957 7.59141 - 7.00798 6.48212 6.00766 5.57838 5.18780 4.82840 - 4.49073 4.16750 3.85603 3.55239 3.24891 2.92887 - 2.57184 2.37276 2.15341 1.95899 1.75674 1.71134 - 1.68455 1.68116 1.67418 1.67274 1.67371 1.68317 - 11.71795 10.61510 9.74002 8.96592 8.27416 7.65027 - 7.08659 6.57544 6.11020 5.68594 5.29807 4.94143 - 4.60957 4.29629 3.99586 3.69862 3.39128 3.05332 - 2.65658 2.42419 2.15781 1.91640 1.67355 1.62422 - 1.59217 1.58706 1.57779 1.57603 1.57755 1.59435 - 11.63677 10.56221 9.72449 8.98155 8.31357 7.70858 - 7.16004 6.66137 6.20682 5.79189 5.41224 5.06288 - 4.73749 4.42979 4.13367 3.83854 3.52916 3.18059 - 2.75692 2.50029 2.19720 1.91702 1.62957 1.57090 - 1.53710 1.53178 1.52009 1.51777 1.52020 1.53922 - 11.57030 10.51866 9.71318 8.99624 8.34922 7.76142 - 7.22719 6.74059 6.29653 5.89079 5.51923 5.17702 - 4.85792 4.55561 4.26377 3.97126 3.66141 3.30582 - 2.86178 2.58542 2.25099 1.93594 1.60624 1.53757 - 1.50136 1.49591 1.48221 1.47942 1.48263 1.50142 - 11.46866 10.45263 9.69855 9.02255 8.41010 7.85156 - 7.34241 6.87748 6.45242 6.06349 5.70689 5.37805 - 5.07092 4.77914 4.49619 4.21023 3.90247 3.53895 - 3.06540 2.75832 2.37335 2.00034 1.59643 1.50465 - 1.45481 1.44937 1.43669 1.43423 1.43967 1.45296 - 11.39460 10.40626 9.69089 9.04593 8.46021 7.92483 - 7.43592 6.98894 6.58003 6.20573 5.86247 5.54576 - 5.24955 4.96747 4.69295 4.41391 4.11044 3.74523 - 3.25492 2.92625 2.50134 2.07799 1.60559 1.49379 - 1.43032 1.42380 1.41040 1.40775 1.41271 1.42320 - 11.27464 10.33991 9.68877 9.09621 8.55459 8.05743 - 7.60247 7.18693 6.80854 6.46408 6.14958 5.85989 - 5.58744 5.32476 5.06527 4.79689 4.50137 4.14750 - 3.66243 3.31253 2.81744 2.28500 1.65398 1.50510 - 1.40847 1.39548 1.37480 1.37113 1.37314 1.38237 - 11.21257 10.30759 9.69308 9.13230 8.61857 8.14662 - 7.71466 7.32060 6.96266 6.63798 6.34284 6.07222 - 5.81860 5.57438 5.33290 5.08158 4.80126 4.45911 - 3.97533 3.61480 3.08894 2.49806 1.73664 1.53774 - 1.39783 1.38022 1.35793 1.35405 1.35547 1.36149 - 11.15326 10.28007 9.70722 9.18324 8.70276 8.26160 - 7.85832 7.49129 7.15921 6.85973 6.58984 6.34522 - 6.11916 5.90476 5.69587 5.48007 5.23629 4.92380 - 4.44942 4.07882 3.52147 2.86524 1.92446 1.63444 - 1.39223 1.36312 1.34328 1.34036 1.33565 1.34042 - 11.13346 10.27469 9.72223 9.21677 8.75385 8.32974 - 7.94312 7.59248 7.27665 6.99377 6.74151 6.51643 - 6.31293 6.12430 5.94214 5.74890 5.52066 5.22442 - 4.77796 4.42906 3.89414 3.21108 2.08394 1.71989 - 1.40803 1.36633 1.33379 1.32967 1.32633 1.32965 - 11.12016 10.27390 9.73543 9.24231 8.79069 8.37742 - 8.00139 7.66141 7.35657 7.08529 6.84548 6.63402 - 6.44561 6.27396 6.11125 5.94047 5.73739 5.46602 - 5.04153 4.70334 4.17829 3.48617 2.25410 1.81488 - 1.42154 1.36873 1.32972 1.32396 1.32059 1.32311 - 11.11192 10.27574 9.74660 9.26176 8.81783 8.41203 - 8.04343 7.71105 7.41418 7.15149 6.92103 6.71998 - 6.54332 6.38513 6.23821 6.08626 5.90505 5.65642 - 5.25394 4.92775 4.41602 3.72400 2.41335 1.90835 - 1.43766 1.37350 1.32742 1.32027 1.31665 1.31876 - 11.09962 10.28042 9.76353 9.28937 8.85503 8.45853 - 8.09937 7.77716 7.49176 7.24198 7.02592 6.84058 - 6.68068 6.54045 6.41424 6.28838 6.14130 5.93537 - 5.58438 5.28651 4.79950 4.10613 2.69031 2.09667 - 1.47694 1.38494 1.32399 1.31877 1.30909 1.31331 - 11.11594 10.29328 9.77425 9.30155 8.87175 8.48228 - 8.13183 7.81898 7.54244 7.30097 7.09288 6.91541 - 6.76353 6.63293 6.52198 6.42472 6.32194 6.15574 - 5.82255 5.53613 5.08455 4.42714 2.94304 2.26419 - 1.51434 1.40193 1.32453 1.31555 1.30810 1.31000 - 11.09132 10.29509 9.79079 9.33016 8.91042 8.52972 - 8.18705 7.88145 7.61231 7.37920 7.18160 7.01850 - 6.88750 6.78566 6.70874 6.64392 6.57083 6.45459 - 6.21261 5.98351 5.59188 4.98779 3.46626 2.63138 - 1.61333 1.45387 1.32890 1.31587 1.30000 1.30559 - 11.07333 10.30011 9.80197 9.34591 8.92978 8.55223 - 8.21272 7.91095 7.64696 7.42045 7.23083 7.07687 - 6.95584 6.86505 6.80222 6.75822 6.71633 6.64201 - 6.45926 6.27009 5.92026 5.36103 3.87103 2.95768 - 1.70828 1.50042 1.33704 1.31791 1.30177 1.30341 - 11.03293 10.30545 9.81159 9.35923 8.94680 8.57352 - 8.23886 7.94259 7.68479 7.46526 7.28359 7.13881 - 7.02859 6.95091 6.90464 6.88229 6.87164 6.85012 - 6.75263 6.61797 6.33336 5.84900 4.45934 3.46528 - 1.89207 1.60763 1.35520 1.32683 1.29812 1.30121 - 10.99719 10.30669 9.81528 9.36546 8.95554 8.58467 - 8.25253 7.95927 7.70523 7.48988 7.31217 7.17105 - 7.06517 6.99378 6.95717 6.95037 6.96273 6.96800 - 6.90276 6.80110 6.59486 6.21805 4.86897 3.79518 - 2.07954 1.73365 1.37248 1.32139 1.30269 1.30011 - 10.97029 10.30745 9.81794 9.36950 8.96085 8.59141 - 8.26091 7.96948 7.71747 7.50441 7.32925 7.19105 - 7.08860 7.02137 6.99021 6.99101 7.01505 7.04044 - 7.01079 6.93560 6.76524 6.43764 5.18854 4.11028 - 2.23720 1.83348 1.39466 1.32993 1.30630 1.29946 - 10.95083 10.30818 9.82031 9.37270 8.96470 8.59617 - 8.26676 7.97643 7.72541 7.51342 7.33997 7.20432 - 7.10519 7.04175 7.01445 7.01831 7.04578 7.08384 - 7.09551 7.05239 6.89360 6.55032 5.41019 4.44893 - 2.38206 1.90749 1.41867 1.35354 1.29985 1.29902 - 10.92742 10.30906 9.82264 9.37621 8.96934 8.60212 - 8.27418 7.98545 7.73609 7.52589 7.35453 7.22146 - 7.12542 7.06583 7.04356 7.05448 7.09246 7.14741 - 7.19055 7.17676 7.06882 6.79067 5.76563 4.85829 - 2.66960 2.09219 1.46186 1.37118 1.30339 1.29847 - 10.91282 10.30951 9.82409 9.37838 8.97223 8.60582 - 8.27879 7.99100 7.74255 7.53337 7.36326 7.23180 - 7.13771 7.08051 7.06132 7.07658 7.12108 7.18658 - 7.24912 7.25411 7.18293 6.95548 6.02106 5.16697 - 2.92550 2.26240 1.50470 1.38960 1.30764 1.29813 - 10.89089 10.31030 9.82600 9.38128 8.97614 8.61085 - 8.28502 7.99844 7.75117 7.54330 7.37485 7.24558 - 7.15419 7.10026 7.08530 7.10647 7.15992 7.24024 - 7.32946 7.36054 7.34577 7.20421 6.43890 5.69923 - 3.45503 2.63618 1.60936 1.43882 1.31945 1.29768 - 10.87855 10.31069 9.82688 9.38270 8.97811 8.61336 - 8.28808 8.00210 7.75549 7.54837 7.38081 7.25262 - 7.16256 7.11032 7.09759 7.12185 7.17994 7.26832 - 7.37175 7.41598 7.43084 7.34076 6.69972 6.04807 - 3.86768 2.95106 1.71002 1.49054 1.33164 1.29746 - 10.86559 10.31097 9.82773 9.38410 8.98009 8.61585 - 8.29109 8.00566 7.75976 7.55347 7.38684 7.25972 - 7.17096 7.12043 7.10999 7.13738 7.20020 7.29706 - 7.41564 7.47312 7.51658 7.48368 7.01548 6.48820 - 4.47689 3.45259 1.89805 1.59499 1.35574 1.29723 - 10.85892 10.31121 9.82810 9.38476 8.98104 8.61709 - 8.29261 8.00748 7.76193 7.55604 7.38988 7.26326 - 7.17516 7.12549 7.11620 7.14515 7.21033 7.31127 - 7.43804 7.50289 7.55942 7.55622 7.20235 6.75782 - 4.90772 3.84162 2.07358 1.69787 1.37889 1.29712 - 10.87333 10.31727 9.82714 9.38078 8.97665 8.61357 - 8.29068 8.00741 7.76346 7.55877 7.39320 7.26608 - 7.17523 7.12067 7.10793 7.14300 7.22733 7.34057 - 7.45724 7.51715 7.57829 7.59756 7.32992 6.93861 - 5.22351 4.15748 2.24394 1.79917 1.40000 1.29706 - 10.87014 10.31734 9.82732 9.38109 8.97707 8.61412 - 8.29134 8.00818 7.76438 7.55983 7.39443 7.26752 - 7.17694 7.12274 7.11048 7.14622 7.23151 7.34627 - 7.46590 7.52896 7.59675 7.62908 7.41238 7.07126 - 5.47421 4.41647 2.40215 1.90028 1.42158 1.29702 - 10.84730 10.31131 9.82866 9.38568 8.98235 8.61883 - 8.29481 8.01020 7.76521 7.55996 7.39451 7.26874 - 7.18167 7.13330 7.12568 7.15699 7.22562 7.33216 - 7.47211 7.55014 7.62651 7.66742 7.52121 7.24515 - 5.84033 4.82417 2.68735 2.09729 1.46425 1.29696 - 10.84449 10.31129 9.82882 9.38592 8.98256 8.61903 - 8.29504 8.01051 7.76573 7.56074 7.39551 7.26988 - 7.18297 7.13488 7.12768 7.15950 7.22882 7.33687 - 7.47889 7.55867 7.64176 7.69355 7.58142 7.35258 - 6.09431 5.13269 2.93972 2.27962 1.50426 1.29693 - 0.54346 0.56672 0.59153 0.61796 0.64588 0.67512 - 0.70571 0.73774 0.77140 0.80698 0.84506 0.88618 - 0.93060 0.97803 1.02659 1.07164 1.10781 1.13407 - 1.15345 1.16279 1.17106 1.17565 1.17735 1.17803 - 1.17831 1.17826 1.17826 1.17829 1.17826 1.17827 - 0.77344 0.80855 0.84465 0.88197 0.92051 0.96034 - 1.00152 1.04418 1.08858 1.13487 1.18323 1.23405 - 1.28801 1.34508 1.40286 1.45553 1.49695 1.52773 - 1.54897 1.55601 1.56396 1.56983 1.56945 1.57339 - 1.57569 1.57544 1.57537 1.57559 1.57543 1.57549 - 0.99577 1.04087 1.08667 1.13341 1.18105 1.22958 - 1.27906 1.32967 1.38173 1.43541 1.49076 1.54806 - 1.60792 1.67022 1.73244 1.78883 1.83343 1.86686 - 1.89011 1.89793 1.90676 1.91378 1.91561 1.91972 - 1.92227 1.92211 1.92211 1.92231 1.92216 1.92222 - 1.41063 1.47245 1.53389 1.59527 1.65642 1.71722 - 1.77776 1.83840 1.89973 1.96186 2.02468 2.08819 - 2.15269 2.21790 2.28157 2.33924 2.38643 2.42376 - 2.45190 2.46240 2.47376 2.48421 2.49347 2.49497 - 2.49654 2.49682 2.49700 2.49701 2.49703 2.49704 - 1.78588 1.86083 1.93373 2.00505 2.07463 2.14246 - 2.20869 2.27388 2.33894 2.40404 2.46913 2.53394 - 2.59798 2.66050 2.72012 2.77502 2.82307 2.86293 - 2.89473 2.90883 2.92338 2.93640 2.95130 2.95218 - 2.95170 2.95209 2.95269 2.95271 2.95272 2.95268 - 2.12390 2.21072 2.29249 2.37019 2.44418 2.51517 - 2.58352 2.64990 2.71548 2.78026 2.84401 2.90622 - 2.96654 3.02448 3.07924 3.13038 3.17719 3.21853 - 3.25395 3.27021 3.28727 3.30307 3.32197 3.32223 - 3.32053 3.32101 3.32188 3.32189 3.32191 3.32184 - 2.42980 2.52642 2.61482 2.69642 2.77226 2.84388 - 2.91180 2.97692 3.04056 3.10270 3.16303 3.22093 - 3.27624 3.32874 3.37817 3.42510 3.46996 3.51184 - 3.54988 3.56789 3.58688 3.60459 3.62599 3.62609 - 3.62393 3.62446 3.62547 3.62548 3.62550 3.62542 - 2.95970 3.07120 3.16787 3.25218 3.32662 3.39449 - 3.45678 3.51468 3.56994 3.62268 3.67271 3.71968 - 3.76372 3.80517 3.84441 3.88319 3.92319 3.96398 - 4.00458 4.02475 4.04595 4.06511 4.08762 4.08872 - 4.08763 4.08819 4.08915 4.08918 4.08921 4.08912 - 3.40380 3.52553 3.62586 3.70844 3.77728 3.83750 - 3.89056 3.93796 3.98184 4.02262 4.06056 4.09578 - 4.12869 4.15994 4.19028 4.22174 4.25640 4.29430 - 4.33474 4.35564 4.37732 4.39580 4.41622 4.41923 - 4.42066 4.42120 4.42184 4.42187 4.42190 4.42188 - 4.26629 4.40137 4.49991 4.56853 4.61508 4.64900 - 4.67318 4.69023 4.70372 4.71455 4.72340 4.73115 - 4.73919 4.74912 4.76166 4.77784 4.79890 4.82604 - 4.85942 4.87788 4.89765 4.91137 4.91931 4.93099 - 4.93715 4.93661 4.93691 4.93735 4.93701 4.93718 - 4.91564 5.02978 5.11527 5.17513 5.20971 5.22109 - 5.21365 5.19499 5.17459 5.15521 5.13786 5.12374 - 5.11437 5.11096 5.11292 5.11761 5.12340 5.13465 - 5.15709 5.17262 5.18750 5.19331 5.19201 5.20783 - 5.21615 5.21524 5.21515 5.21584 5.21540 5.21558 - 5.84157 5.93315 5.98631 6.00651 5.99536 5.95665 - 5.89718 5.82761 5.76038 5.69935 5.64545 5.59939 - 5.56214 5.53377 5.51305 5.49549 5.47789 5.46498 - 5.46319 5.46669 5.46934 5.46431 5.45043 5.46667 - 5.47437 5.47298 5.47262 5.47345 5.47288 5.47308 - 6.49461 6.60375 6.62500 6.58157 6.49994 6.40775 - 6.31183 6.21577 6.12351 6.03716 5.95816 5.88710 - 5.82470 5.77077 5.72533 5.68687 5.65381 5.62565 - 5.60158 5.59136 5.58304 5.57260 5.55081 5.56382 - 5.56818 5.56621 5.56607 5.56681 5.56611 5.56640 - 7.03062 7.11421 7.09796 7.01089 6.88513 6.75327 - 6.62255 6.49587 6.37647 6.26577 6.16459 6.07280 - 5.99101 5.91896 5.85635 5.80119 5.75151 5.70679 - 5.66580 5.64646 5.62845 5.61242 5.59041 5.59550 - 5.59614 5.59478 5.59451 5.59491 5.59449 5.59466 - 7.48277 7.53763 7.48368 7.35520 7.18923 7.02240 - 6.86192 6.70942 6.56706 6.43565 6.31529 6.20537 - 6.10633 6.01800 5.93985 5.86967 5.80538 5.74671 - 5.69206 5.66527 5.63917 5.61905 5.59893 5.59564 - 5.59252 5.59191 5.59156 5.59157 5.59147 5.59151 - 8.39946 8.19582 7.98696 7.78366 7.58573 7.39337 - 7.20681 7.02609 6.85184 6.68527 6.52679 6.37683 - 6.23666 6.10807 5.99218 5.89079 5.80493 5.73096 - 5.66766 5.64331 5.62584 5.61044 5.54616 5.51479 - 5.52354 5.52907 5.52647 5.52471 5.52734 5.52571 - 8.76751 8.69192 8.49551 8.22640 7.93236 7.65728 - 7.40662 7.17811 6.96927 6.77838 6.60169 6.43664 - 6.28375 6.14411 6.01669 5.89905 5.78938 5.68868 - 5.59462 5.54708 5.49882 5.46642 5.44752 5.42444 - 5.41223 5.41320 5.41258 5.41172 5.41235 5.41206 - 9.71189 9.46703 9.12074 8.72363 8.32170 7.95484 - 7.62667 7.33440 7.07446 6.84010 6.62115 6.41151 - 6.21379 6.03080 5.86234 5.70514 5.55739 5.42034 - 5.29218 5.22877 5.16549 5.11923 5.08083 5.06104 - 5.04874 5.04858 5.04772 5.04716 5.04747 5.04730 - 10.39757 9.86300 9.35616 8.88665 8.45182 8.04986 - 7.67911 7.33846 7.02732 6.74375 6.48509 6.24794 - 6.02746 5.82050 5.62834 5.45048 5.28501 5.12301 - 4.95763 4.87711 4.80426 4.75328 4.69627 4.68119 - 4.67334 4.67259 4.67105 4.67098 4.67063 4.67079 - 11.01393 10.30554 9.65254 9.05711 8.51336 8.01804 - 7.56870 7.16191 6.79489 6.46418 6.16530 5.89288 - 5.63941 5.39959 5.17380 4.96252 4.76277 4.56631 - 4.36798 4.27236 4.18650 4.12662 4.05835 4.03974 - 4.03037 4.02954 4.02773 4.02766 4.02714 4.02735 - 11.32905 10.50521 9.76116 9.08939 8.48188 7.93299 - 7.43900 6.99440 6.59384 6.23258 5.90541 5.60598 - 5.32567 5.05852 4.80496 4.56629 4.34245 4.13002 - 3.92795 3.83140 3.73612 3.66191 3.58988 3.57082 - 3.55588 3.55425 3.55282 3.55260 3.55248 3.55241 - 11.53805 10.62005 9.80773 9.08224 8.43325 7.85165 - 7.33059 6.86144 6.43574 6.04849 5.69558 5.37227 - 5.07251 4.79162 4.52810 4.27942 4.04366 3.81892 - 3.60561 3.50350 3.40208 3.32237 3.24535 3.22567 - 3.20932 3.20739 3.20590 3.20569 3.20552 3.20547 - 11.67297 10.68985 9.83110 9.06743 8.38799 7.78201 - 7.24036 6.75291 6.30990 5.90604 5.53731 5.19930 - 4.88648 4.59450 4.32151 4.06444 3.82094 3.58884 - 3.36718 3.26024 3.15356 3.06917 2.98741 2.96714 - 2.95070 2.94871 2.94696 2.94671 2.94657 2.94654 - 11.82481 10.75852 9.84332 9.03293 8.31599 7.68026 - 7.11340 6.60352 6.13979 5.71662 5.32991 4.97525 - 4.64732 4.34179 4.05632 3.78719 3.53121 3.28659 - 3.05078 2.93588 2.82099 2.72947 2.63881 2.61652 - 2.59907 2.59699 2.59502 2.59472 2.59461 2.59457 - 11.89528 10.78237 9.83802 9.00343 8.26710 7.61574 - 7.03570 6.51439 6.04073 5.60895 5.21459 4.85281 - 4.51782 4.20490 3.91144 3.63334 3.36705 3.11053 - 2.86138 2.73900 2.61665 2.51889 2.41986 2.39464 - 2.37492 2.37270 2.37074 2.37042 2.37027 2.37019 - 11.93207 10.77548 9.81085 8.95916 8.21024 7.54633 - 6.95481 6.42345 5.94181 5.50377 5.10424 4.73757 - 4.39698 4.07685 3.77401 3.48352 3.20051 2.92074 - 2.64023 2.49765 2.35124 2.23121 2.11036 2.07961 - 2.05474 2.05185 2.04952 2.04918 2.04891 2.04860 - 11.89825 10.74068 9.78627 8.94290 8.20074 7.53976 - 6.94904 6.41757 5.93593 5.49813 5.09891 4.73249 - 4.39186 4.07105 3.76618 3.47122 3.17945 2.88341 - 2.57407 2.41052 2.23574 2.08778 1.94382 1.90972 - 1.88184 1.87823 1.87495 1.87451 1.87420 1.87512 - 11.77351 10.65818 9.75156 8.94544 8.22721 7.58083 - 6.99905 6.47480 6.00190 5.57417 5.18515 4.82738 - 4.49143 4.17005 3.86055 3.55894 3.25752 2.93929 - 2.58348 2.38473 2.16549 1.97091 1.76801 1.72269 - 1.69773 1.69486 1.68809 1.68657 1.68755 1.69680 - 11.69108 10.59085 9.71745 8.94532 8.25575 7.63417 - 7.07278 6.56371 6.10018 5.67735 5.29080 4.93556 - 4.60549 4.29448 3.99670 3.70219 3.39728 3.06090 - 2.66466 2.43246 2.16686 1.92607 1.68089 1.63039 - 1.60289 1.59929 1.59054 1.58855 1.59018 1.60668 - 11.60847 10.53433 9.69693 8.95544 8.28978 7.68763 - 7.14214 6.64626 6.19391 5.78065 5.40235 5.05433 - 4.73061 4.42513 4.13168 3.83937 3.53256 3.18577 - 2.76288 2.50672 2.20483 1.92534 1.63395 1.57346 - 1.54640 1.54331 1.53235 1.52966 1.53230 1.55101 - 11.54054 10.48828 9.68224 8.96636 8.32162 7.73690 - 7.20606 6.72265 6.28109 5.87725 5.50720 5.16640 - 4.84900 4.54894 4.25976 3.97006 3.66282 3.30917 - 2.86625 2.59064 2.25777 1.94344 1.60851 1.53760 - 1.50977 1.50709 1.49427 1.49102 1.49450 1.51298 - 11.43639 10.41887 9.66369 8.98833 8.37791 7.82237 - 7.31668 6.85517 6.43297 6.04632 5.69162 5.36451 - 5.05923 4.76968 4.48925 4.20599 3.90094 3.53990 - 3.06846 2.76245 2.37870 2.00545 1.59616 1.50326 - 1.46154 1.45933 1.44933 1.44656 1.45051 1.46446 - 11.36029 10.37082 9.65408 9.00952 8.42556 7.89292 - 7.40732 6.96368 6.55772 6.18593 5.84486 5.53018 - 5.23603 4.95620 4.68410 4.40762 4.10677 3.74422 - 3.25662 2.92942 2.50602 2.08236 1.60400 1.49115 - 1.43668 1.43368 1.42316 1.42017 1.42356 1.43480 - 11.23796 10.30300 9.65072 9.05835 8.51809 8.02314 - 7.57090 7.15828 6.78259 6.44059 6.12840 5.84095 - 5.57081 5.31060 5.05373 4.78807 4.49511 4.14312 - 3.65959 3.31167 2.82093 2.29140 1.65255 1.49981 - 1.41616 1.40712 1.38697 1.38249 1.38530 1.39424 - 11.17430 10.27089 9.65592 9.09554 8.58291 8.11261 - 7.68271 7.29091 6.93527 6.61290 6.32006 6.05176 - 5.80044 5.55852 5.31935 5.07038 4.79238 4.45224 - 3.97071 3.61253 3.09115 2.50337 1.73606 1.53460 - 1.40631 1.39204 1.37021 1.36566 1.36775 1.37355 - 11.11328 10.24419 9.67233 9.14929 8.66976 8.22962 - 7.82752 7.46189 7.13146 6.83388 6.56603 6.32353 - 6.09944 5.88678 5.67946 5.46523 5.22329 4.91348 - 4.44323 4.07537 3.52101 2.86654 1.92579 1.63702 - 1.40146 1.37433 1.35604 1.35297 1.34762 1.35274 - 11.08675 10.23753 9.68938 9.18658 8.72499 8.30145 - 7.91505 7.56494 7.25049 6.96967 6.71956 6.49590 - 6.29181 6.10034 5.91556 5.72513 5.50858 5.22736 - 4.78763 4.43080 3.87248 3.17892 2.09731 1.73803 - 1.41536 1.37364 1.34723 1.34392 1.33608 1.34215 - 11.08044 10.23966 9.70298 9.21124 8.76075 8.34844 - 7.97326 7.63421 7.33045 7.06041 6.82193 6.61179 - 6.42455 6.25381 6.09192 5.92216 5.72063 5.45157 - 5.03063 4.69507 4.17367 3.48570 2.25830 1.82026 - 1.43257 1.38083 1.34214 1.33644 1.33297 1.33574 - 11.07263 10.24191 9.71463 9.23133 8.78867 8.38396 - 8.01632 7.68485 7.38894 7.12719 6.89770 6.69759 - 6.52176 6.36431 6.21809 6.06697 5.88700 5.64042 - 5.24150 4.91804 4.40995 3.72193 2.41751 1.91539 - 1.44884 1.38541 1.33987 1.33281 1.32916 1.33147 - 11.06101 10.24699 9.73199 9.25950 8.82662 8.43141 - 8.07339 7.75217 7.46760 7.21849 7.00296 6.81808 - 6.65854 6.51868 6.39288 6.26764 6.12157 5.91744 - 5.56967 5.27424 4.79052 4.10138 2.69449 2.10465 - 1.48808 1.39664 1.33646 1.33138 1.32170 1.32614 - 11.07708 10.25987 9.74286 9.27191 8.84364 8.45548 - 8.10615 7.79422 7.51846 7.27759 7.06997 6.89283 - 6.74120 6.61081 6.50008 6.40314 6.30099 6.13631 - 5.80619 5.52204 5.07334 4.42012 2.94643 2.27160 - 1.52517 1.41343 1.33700 1.32819 1.32080 1.32290 - 11.05291 10.26149 9.75885 9.29983 8.88162 8.50233 - 8.16090 7.85640 7.58811 7.35564 7.15847 6.99562 - 6.86474 6.76293 6.68604 6.62137 6.54871 6.43325 - 6.19299 5.96573 5.57729 4.97767 3.46561 2.63562 - 1.62322 1.46484 1.34133 1.32855 1.31274 1.31857 - 11.03522 10.26621 9.76948 9.31492 8.90031 8.52428 - 8.18616 7.88560 7.62250 7.39662 7.20735 7.05358 - 6.93264 6.84194 6.77922 6.73538 6.69372 6.61976 - 6.43792 6.25001 5.90310 5.34869 3.86760 2.95816 - 1.71720 1.51104 1.34943 1.33046 1.31459 1.31642 - 10.99445 10.27167 9.77950 9.32842 8.91715 8.54510 - 8.21169 7.91656 7.65965 7.44076 7.25956 7.11512 - 7.00516 6.92765 6.88146 6.85911 6.84845 6.82695 - 6.72979 6.59576 6.31315 5.83298 4.45242 3.46222 - 1.89957 1.61734 1.36734 1.33933 1.31094 1.31425 - 10.95935 10.27281 9.78324 9.33489 8.92623 8.55644 - 8.22524 7.93282 7.67958 7.46497 7.28790 7.14726 - 7.04174 6.97052 6.93392 6.92705 6.93927 6.94437 - 6.87918 6.77803 6.57330 6.19941 4.85893 3.79132 - 2.08619 1.74261 1.38430 1.33376 1.31539 1.31316 - 10.93277 10.27368 9.78600 9.33913 8.93177 8.56333 - 8.23361 7.94288 7.69163 7.47930 7.30483 7.16718 - 7.06513 6.99809 6.96693 6.96761 6.99147 7.01664 - 6.98688 6.91194 6.74262 6.41750 5.17707 4.10508 - 2.24301 1.84186 1.40622 1.34213 1.31901 1.31251 - 10.91413 10.27441 9.78807 9.34202 8.93538 8.56791 - 8.23940 7.95001 7.70012 7.48919 7.31624 7.18043 - 7.08091 7.01733 6.99021 6.99470 7.02359 7.06481 - 7.07060 7.01635 6.86138 6.55658 5.42931 4.38599 - 2.38796 1.93275 1.43039 1.35398 1.31881 1.31207 - 10.89090 10.27529 9.79050 9.34555 8.93999 8.57386 - 8.24691 7.95920 7.71098 7.50181 7.33084 7.19742 - 7.10102 7.04156 7.01973 7.03093 7.06915 7.12675 - 7.16754 7.14468 7.03444 6.78456 5.78894 4.80415 - 2.66692 2.11277 1.47401 1.37234 1.32495 1.31152 - 10.87587 10.27594 9.79230 9.34805 8.94311 8.57777 - 8.25170 7.96477 7.71710 7.50861 7.33905 7.20797 - 7.11413 7.05705 7.03786 7.05299 7.09726 7.16240 - 7.22457 7.22952 7.15844 6.93184 6.00408 5.15641 - 2.92710 2.26805 1.51541 1.40141 1.32026 1.31119 - 10.85401 10.27674 9.79419 9.35075 8.94673 8.58265 - 8.25805 7.97258 7.72615 7.51885 7.35078 7.22176 - 7.13053 7.07673 7.06177 7.08285 7.13603 7.21596 - 7.30476 7.33566 7.32081 7.17965 6.41864 5.68410 - 3.45374 2.63999 1.61928 1.45006 1.33193 1.31075 - 10.84193 10.27703 9.79505 9.35216 8.94870 8.58516 - 8.26109 7.97619 7.73042 7.52387 7.35671 7.22878 - 7.13890 7.08677 7.07405 7.09820 7.15604 7.24404 - 7.34700 7.39098 7.40565 7.31576 6.67763 6.03016 - 3.86417 2.95322 1.71921 1.50122 1.34403 1.31053 - 10.82914 10.27721 9.79576 9.35358 8.95079 8.58772 - 8.26401 7.97953 7.73443 7.52878 7.36266 7.23588 - 7.14736 7.09693 7.08648 7.11372 7.17628 7.27275 - 7.39083 7.44803 7.49121 7.45825 6.99163 6.46743 - 4.47017 3.45207 1.90592 1.60465 1.36795 1.31032 - 10.82295 10.27725 9.79579 9.35388 8.95146 8.58873 - 8.26542 7.98145 7.73710 7.53211 7.36603 7.23875 - 7.15041 7.10169 7.09378 7.12257 7.18470 7.28263 - 7.41728 7.49041 7.53447 7.49128 7.17562 6.84294 - 4.85848 3.77838 2.08357 1.72916 1.39131 1.31021 - 10.83732 10.28341 9.79495 9.35009 8.94733 8.58547 - 8.26364 7.98130 7.73812 7.53407 7.36900 7.24223 - 7.15162 7.09718 7.08443 7.11934 7.20334 7.31615 - 7.43238 7.49202 7.55280 7.57178 7.30509 6.91608 - 5.21240 4.15266 2.24953 1.80725 1.41189 1.31016 - 10.83416 10.28348 9.79513 9.35041 8.94776 8.58601 - 8.26431 7.98206 7.73903 7.53512 7.37021 7.24366 - 7.15332 7.09923 7.08697 7.12255 7.20753 7.32184 - 7.44100 7.50379 7.57123 7.60330 7.38743 7.04825 - 5.46139 4.40987 2.40668 1.90769 1.43328 1.31012 - 10.81118 10.27775 9.79686 9.35524 8.95304 8.59064 - 8.26771 7.98405 7.73988 7.53525 7.37029 7.24488 - 7.15804 7.10979 7.10218 7.13335 7.20167 7.30777 - 7.44718 7.52493 7.60096 7.64156 7.49564 7.22093 - 5.82493 4.81483 2.69015 2.10345 1.47556 1.31006 - 10.80839 10.27793 9.79730 9.35557 8.95323 8.59073 - 8.26780 7.98429 7.74037 7.53605 7.37132 7.24604 - 7.15934 7.11134 7.10414 7.13582 7.20487 7.31253 - 7.45399 7.53343 7.61620 7.66788 7.55522 7.32627 - 6.07678 5.12126 2.94113 2.28482 1.51515 1.31003 - 0.53489 0.55794 0.58254 0.60877 0.63650 0.66554 - 0.69592 0.72771 0.76102 0.79614 0.83359 0.87388 - 0.91726 0.96347 1.01079 1.05493 1.09098 1.11804 - 1.13830 1.14748 1.15566 1.16072 1.16401 1.16462 - 1.16504 1.16508 1.16512 1.16512 1.16513 1.16514 - 0.76251 0.79729 0.83308 0.87010 0.90836 0.94790 - 0.98877 1.03109 1.07503 1.12075 1.16839 1.21832 - 1.27120 1.32704 1.38363 1.43561 1.47731 1.50904 - 1.53140 1.53894 1.54726 1.55478 1.55944 1.56036 - 1.56131 1.56143 1.56150 1.56153 1.56151 1.56147 - 0.98273 1.02741 1.07282 1.11919 1.16649 1.21468 - 1.26380 1.31402 1.36560 1.41869 1.47332 1.52977 - 1.58865 1.64987 1.71109 1.76700 1.81203 1.84658 - 1.87124 1.87979 1.88929 1.89806 1.90451 1.90593 - 1.90731 1.90747 1.90759 1.90762 1.90761 1.90755 - 1.39404 1.45531 1.51626 1.57720 1.63793 1.69837 - 1.75854 1.81880 1.87971 1.94136 2.00362 2.06650 - 2.13034 2.19489 2.25804 2.31561 2.36340 2.40192 - 2.43169 2.44320 2.45562 2.46677 2.47654 2.47890 - 2.48097 2.48122 2.48142 2.48146 2.48146 2.48142 - 1.76641 1.84076 1.91313 1.98399 2.05316 2.12064 - 2.18656 2.25147 2.31625 2.38104 2.44580 2.51023 - 2.57394 2.63623 2.69580 2.75093 2.79960 2.84053 - 2.87412 2.88941 2.90479 2.91723 2.92998 2.93318 - 2.93571 2.93605 2.93630 2.93633 2.93637 2.93636 - 2.10211 2.18828 2.26952 2.34676 2.42039 2.49111 - 2.55924 2.62548 2.69092 2.75560 2.81923 2.88135 - 2.94165 2.99972 3.05478 3.10637 3.15383 3.19611 - 3.23325 3.25077 3.26844 3.28273 3.29747 3.30121 - 3.30417 3.30457 3.30486 3.30489 3.30493 3.30497 - 2.40610 2.50207 2.58995 2.67113 2.74667 2.81810 - 2.88594 2.95105 3.01473 3.07694 3.13736 3.19541 - 3.25097 3.30388 3.35388 3.40144 3.44696 3.48965 - 3.52927 3.54849 3.56793 3.58360 3.59981 3.60395 - 3.60722 3.60765 3.60797 3.60801 3.60806 3.60812 - 2.93319 3.04406 3.14027 3.22428 3.29859 3.36649 - 3.42895 3.48713 3.54272 3.59585 3.64632 3.69379 - 3.73848 3.78071 3.82084 3.86047 3.90116 3.94259 - 3.98433 4.00544 4.02690 4.04420 4.06206 4.06665 - 4.07026 4.07073 4.07108 4.07113 4.07118 4.07127 - 3.37540 3.49652 3.59651 3.67896 3.74787 3.80835 - 3.86182 3.90974 3.95420 3.99562 4.03423 4.07021 - 4.10397 4.13620 4.16758 4.20001 4.23542 4.27386 - 4.31497 4.33640 4.35835 4.37609 4.39440 4.39908 - 4.40279 4.40328 4.40364 4.40369 4.40373 4.40382 - 4.23544 4.37005 4.46857 4.53754 4.58470 4.61940 - 4.64446 4.66250 4.67700 4.68882 4.69868 4.70744 - 4.71656 4.72763 4.74134 4.75855 4.78033 4.80793 - 4.84155 4.85994 4.87919 4.89508 4.91150 4.91567 - 4.91901 4.91945 4.91977 4.91981 4.91984 4.91988 - 4.88393 4.99810 5.08396 5.14446 5.17996 5.19246 - 5.18631 5.16897 5.14988 5.13171 5.11552 5.10250 - 5.09419 5.09181 5.09479 5.10048 5.10721 5.11907 - 5.14135 5.15630 5.17066 5.18106 5.19388 5.19722 - 5.19965 5.19994 5.20022 5.20024 5.20031 5.20024 - 5.81025 5.90257 5.95685 5.97837 5.96873 5.93168 - 5.87391 5.80601 5.74030 5.68063 5.62791 5.58291 - 5.54659 5.51910 5.49921 5.48260 5.46603 5.45391 - 5.45209 5.45500 5.45713 5.45781 5.46134 5.46232 - 5.46288 5.46295 5.46306 5.46305 5.46309 5.46294 - 6.46491 6.57466 6.59751 6.55629 6.47700 6.38688 - 6.29273 6.19826 6.10752 6.02257 5.94481 5.87479 - 5.81330 5.76025 5.71563 5.67800 5.64577 5.61839 - 5.59499 5.58471 5.57549 5.56930 5.56389 5.56258 - 5.56160 5.56149 5.56141 5.56139 5.56139 5.56126 - 7.00229 7.08701 7.07289 6.98847 6.86537 6.73575 - 6.60685 6.48180 6.36400 6.25484 6.15499 6.06426 - 5.98338 5.91216 5.85035 5.79602 5.74718 5.70322 - 5.66294 5.64384 5.62564 5.61229 5.59981 5.59685 - 5.59450 5.59419 5.59397 5.59394 5.59393 5.59387 - 7.45576 7.51222 7.46084 7.33533 7.17222 7.00771 - 6.84908 6.69827 6.55759 6.42785 6.30894 6.20016 - 6.10210 6.01466 5.93734 5.86797 5.80446 5.74645 - 5.69250 5.66624 5.64068 5.62142 5.60307 5.59873 - 5.59527 5.59481 5.59446 5.59441 5.59439 5.59446 - 8.37539 8.17451 7.96840 7.76774 7.57231 7.38233 - 7.19800 7.01940 6.84715 6.68242 6.52566 6.37725 - 6.23849 6.11116 5.99632 5.89580 5.81059 5.73710 - 5.67405 5.64963 5.63174 5.61538 5.54888 5.51775 - 5.53213 5.53868 5.53530 5.53323 5.53651 5.53481 - 8.74528 8.67291 8.48019 8.21467 7.92376 7.65110 - 7.40234 7.17554 6.96854 6.77956 6.60465 6.44108 - 6.28951 6.15109 6.02477 5.90803 5.79900 5.69873 - 5.60544 5.55909 5.51301 5.47720 5.44238 5.43408 - 5.42743 5.42652 5.42585 5.42576 5.42570 5.42599 - 9.69521 9.45449 9.11233 8.71891 8.32010 7.95576 - 7.62961 7.33907 7.08074 6.84795 6.63051 6.42237 - 6.22620 6.04477 5.87778 5.72175 5.57479 5.43857 - 5.31186 5.24961 5.18793 5.13999 5.09285 5.08122 - 5.07198 5.07078 5.06990 5.06978 5.06970 5.06963 - 10.38558 9.85540 9.35257 8.88654 8.45469 8.05531 - 7.68677 7.34800 7.03848 6.75629 6.49883 6.26282 - 6.04351 5.83786 5.64711 5.47084 5.30705 5.14663 - 4.98265 4.90305 4.83185 4.78292 4.72765 4.71203 - 4.70134 4.70033 4.69919 4.69901 4.69886 4.69833 - 11.00723 10.30363 9.65479 9.06285 8.52201 8.02907 - 7.58171 7.17655 6.81085 6.48125 6.18338 5.91195 - 5.65961 5.42119 5.19705 4.98769 4.79004 4.59557 - 4.39893 4.30433 4.22025 4.16262 4.09649 4.07738 - 4.06459 4.06344 4.06211 4.06193 4.06166 4.06076 - 11.32606 10.50614 9.76556 9.09690 8.49221 7.94582 - 7.45399 7.01118 6.61206 6.25195 5.92576 5.62730 - 5.34811 5.08238 4.83054 4.59391 4.37232 4.16209 - 3.96186 3.86608 3.77142 3.69731 3.62493 3.60684 - 3.59238 3.59069 3.58925 3.58907 3.58892 3.58870 - 11.53721 10.62396 9.81480 9.09135 8.44367 7.86303 - 7.34293 6.87523 6.45180 6.06753 5.71783 5.39742 - 5.09934 4.81861 4.55466 4.30678 4.07402 3.85246 - 3.64041 3.53827 3.43685 3.35690 3.27910 3.26071 - 3.24581 3.24390 3.24226 3.24212 3.24190 3.24311 - 11.66959 10.69065 9.83542 9.07487 8.39822 7.79470 - 7.25525 6.76976 6.32852 5.92625 5.55901 5.22243 - 4.91101 4.62046 4.34896 4.09348 3.85166 3.62125 - 3.40104 3.29456 3.18775 3.10264 3.02051 3.00121 - 2.98602 2.98413 2.98226 2.98195 2.98186 2.98383 - 11.81833 10.75695 9.84555 9.03843 8.32425 7.69092 - 7.12621 6.61828 6.15639 5.73499 5.35000 4.99698 - 4.67063 4.36658 4.08254 3.81477 3.56008 3.31653 - 3.08147 2.96676 2.85183 2.76021 2.67010 2.64806 - 2.63068 2.62861 2.62667 2.62637 2.62625 2.62707 - 11.88507 10.77786 9.83773 9.00654 8.27299 7.62388 - 7.04581 6.52628 6.05438 5.62434 5.23171 4.87164 - 4.53832 4.22698 3.93498 3.65819 3.39294 3.13713 - 2.88832 2.76603 2.64386 2.54653 2.44838 2.42291 - 2.40260 2.40031 2.39845 2.39819 2.39800 2.39629 - 11.91275 10.76374 9.80429 8.95648 8.21038 7.54858 - 6.95869 6.42874 5.94855 5.51202 5.11406 4.74904 - 4.41016 4.09180 3.79068 3.50175 3.21994 2.94098 - 2.66084 2.51838 2.37225 2.25264 2.13213 2.10114 - 2.07592 2.07298 2.07070 2.07041 2.07011 2.06810 - 11.87141 10.72280 9.77431 8.93528 8.19613 7.53731 - 6.94812 6.41789 5.93749 5.50097 5.10312 4.73819 - 4.39922 4.08026 3.77741 3.48445 3.19458 2.90014 - 2.59183 2.42849 2.25361 2.10516 1.96052 1.92698 - 1.89998 1.89646 1.89306 1.89255 1.89230 1.89540 - 11.73654 10.63045 9.73025 8.92914 8.21473 7.57128 - 6.99171 6.46909 5.99735 5.57053 5.18230 4.82539 - 4.49067 4.17109 3.86392 3.56516 3.26690 2.95165 - 2.59798 2.39964 2.17995 1.98421 1.77986 1.73483 - 1.71300 1.71069 1.70349 1.70175 1.70307 1.71484 - 11.62599 10.54946 9.69048 8.92674 8.24125 7.62115 - 7.06023 6.55232 6.09213 5.67425 5.29297 4.94165 - 4.61176 4.29642 3.99229 3.69407 3.39118 3.06019 - 2.67099 2.44369 2.18461 1.94780 1.69174 1.63352 - 1.61612 1.61541 1.60505 1.60220 1.60513 1.62119 - 11.56085 10.49832 9.66841 8.93228 8.27034 7.67071 - 7.12685 6.63204 6.18052 5.76797 5.39041 5.04328 - 4.72086 4.41730 4.12654 3.83801 3.53608 3.19450 - 2.77557 2.51980 2.21577 1.93249 1.63882 1.58109 - 1.56017 1.55779 1.54602 1.54312 1.54626 1.56410 - 11.49057 10.44996 9.65137 8.94083 8.29983 7.71765 - 7.18847 6.70617 6.26546 5.86236 5.49306 5.15314 - 4.83700 4.53878 4.25225 3.96643 3.66439 3.31650 - 2.87813 2.60297 2.26742 1.94843 1.61085 1.54340 - 1.52326 1.52149 1.50765 1.50414 1.50826 1.52580 - 11.38400 10.37806 9.62988 8.95966 8.35293 7.79995 - 7.29599 6.83566 6.41442 6.02860 5.67470 5.34851 - 5.04444 4.75662 4.47873 4.19933 3.89967 3.54492 - 3.07872 2.77318 2.38610 2.00733 1.59540 1.50664 - 1.47416 1.47327 1.46258 1.45959 1.46460 1.47778 - 11.30727 10.32883 9.61874 8.97907 8.39866 7.86854 - 7.38465 6.94228 6.53735 6.16651 5.82633 5.51264 - 5.21967 4.94144 4.67170 4.39888 4.10335 3.74734 - 3.26551 2.93888 2.51176 2.08200 1.60118 1.49315 - 1.44913 1.44764 1.43638 1.43313 1.43769 1.44875 - 11.18607 10.26113 9.61445 9.02629 8.48908 7.99632 - 7.54568 7.13429 6.75979 6.41899 6.10801 5.82177 - 5.55286 5.29397 5.03880 4.77574 4.48690 4.14114 - 3.66504 3.31912 2.82565 2.28887 1.64598 1.50188 - 1.42964 1.42153 1.40007 1.39533 1.39851 1.40857 - 11.12452 10.23013 9.61995 9.06317 8.55323 8.08493 - 7.65653 7.26596 6.91154 6.59036 6.29874 6.03163 - 5.78147 5.54074 5.30303 5.05626 4.78179 4.44723 - 3.97282 3.61694 3.09388 2.50043 1.73104 1.53760 - 1.41956 1.40618 1.38335 1.37858 1.38099 1.38753 - 11.06790 10.20605 9.63762 9.11732 8.63997 8.20157 - 7.80089 7.43645 7.10712 6.81061 6.54380 6.30229 - 6.07919 5.86759 5.66159 5.44930 5.21034 4.90478 - 4.43978 4.07392 3.51960 2.86404 1.92640 1.64196 - 1.41358 1.38756 1.36933 1.36617 1.36130 1.36609 - 11.04423 10.20130 9.65591 9.15531 8.69553 8.27350 - 7.88838 7.53939 7.22598 6.94615 6.69696 6.47420 - 6.27098 6.08042 5.89670 5.70776 5.49343 5.21550 - 4.78026 4.42577 3.86921 3.17702 2.10030 1.74462 - 1.42733 1.38654 1.36051 1.35718 1.34956 1.35535 - 11.04003 10.20494 9.67048 9.18060 8.73166 8.32067 - 7.94666 7.60863 7.30585 7.03676 6.79917 6.58989 - 6.40343 6.23343 6.07234 5.90365 5.70371 5.43713 - 5.02017 4.68746 4.16957 3.48438 2.26163 1.82807 - 1.44472 1.39357 1.35530 1.34968 1.34622 1.34898 - 11.03355 10.20809 9.68271 9.20105 8.75982 8.35638 - 7.98985 7.65940 7.36439 7.10350 6.87480 6.67540 - 6.50024 6.34342 6.19789 6.04764 5.86893 5.62445 - 5.22912 4.90833 4.40385 3.72015 2.42285 1.92319 - 1.46063 1.39800 1.35303 1.34600 1.34241 1.34480 - 11.02348 10.21420 9.70077 9.22965 8.79807 8.40404 - 8.04708 7.72682 7.44308 7.19471 6.97981 6.79548 - 6.63646 6.49710 6.37184 6.24725 6.10207 5.89933 - 5.55421 5.26124 4.78180 4.09851 2.70034 2.11261 - 1.49935 1.40874 1.34956 1.34460 1.33498 1.33960 - 11.03963 10.22728 9.71183 9.24229 8.81528 8.42825 - 8.07992 7.76887 7.49387 7.25366 7.04660 6.86996 - 6.71877 6.58880 6.47849 6.38202 6.28045 6.11666 - 5.78858 5.50680 5.06280 4.41584 2.95068 2.27866 - 1.53609 1.42531 1.35005 1.34131 1.33410 1.33641 - 11.01560 10.22871 9.72753 9.26985 8.85287 8.47473 - 8.13437 7.83079 7.56331 7.33150 7.13490 6.97249 - 6.84192 6.74034 6.66358 6.59906 6.52667 6.41179 - 6.17316 5.94777 5.56268 4.96773 3.46476 2.63949 - 1.63329 1.47614 1.35421 1.34168 1.32594 1.33204 - 10.99771 10.23304 9.73776 9.28459 8.87129 8.49647 - 8.15946 7.85987 7.59760 7.37236 7.18361 7.03020 - 6.90953 6.81901 6.75641 6.71264 6.67108 6.59739 - 6.41660 6.23019 5.88631 5.33522 3.86111 2.95927 - 1.72660 1.52187 1.36216 1.34348 1.32781 1.32982 - 10.95704 10.23800 9.74736 9.29781 8.88798 8.51719 - 8.18485 7.89064 7.63451 7.41625 7.23560 7.09159 - 6.98192 6.90454 6.85837 6.83600 6.82534 6.80382 - 6.70690 6.57376 6.29370 5.81558 4.43983 3.46029 - 1.90771 1.62718 1.37976 1.35229 1.32409 1.32760 - 10.92207 10.23915 9.75115 9.30430 8.89702 8.52843 - 8.19827 7.90678 7.65432 7.44039 7.26387 7.12366 - 7.01844 6.94737 6.91081 6.90379 6.91577 6.92075 - 6.85604 6.75550 6.55164 6.17902 4.84609 3.78660 - 2.09325 1.75193 1.39640 1.34643 1.32851 1.32650 - 10.89571 10.24002 9.75397 9.30857 8.90254 8.53526 - 8.20661 7.91680 7.66635 7.45470 7.28078 7.14356 - 7.04180 6.97491 6.94377 6.94433 6.96796 6.99291 - 6.96322 6.88860 6.71998 6.39634 5.16358 4.09897 - 2.24906 1.85053 1.41809 1.35465 1.33210 1.32586 - 10.87738 10.24085 9.75610 9.31149 8.90614 8.53984 - 8.21237 7.92391 7.67483 7.46457 7.29220 7.15680 - 7.05756 6.99413 6.96703 6.97140 7.00007 7.04103 - 7.04664 6.99246 6.83809 6.53503 5.41567 4.37890 - 2.39295 1.94074 1.44210 1.36643 1.33185 1.32543 - 10.85453 10.24183 9.75862 9.31509 8.91081 8.54584 - 8.21991 7.93312 7.68569 7.47718 7.30676 7.17378 - 7.07765 7.01832 6.99648 7.00757 7.04561 7.10294 - 7.14323 7.12014 7.01032 6.76261 5.77519 4.79525 - 2.67016 2.11973 1.48533 1.38450 1.33796 1.32489 - 10.83977 10.24249 9.76043 9.31759 8.91394 8.54976 - 8.22474 7.93872 7.69185 7.48401 7.31498 7.18430 - 7.09073 7.03380 7.01461 7.02961 7.07360 7.13843 - 7.20034 7.20503 7.13360 6.90892 5.99123 5.14593 - 2.92856 2.27392 1.52638 1.41345 1.33320 1.32457 - 10.81848 10.24339 9.76234 9.32031 8.91759 8.55468 - 8.23112 7.94655 7.70090 7.49423 7.32667 7.19804 - 7.10708 7.05341 7.03846 7.05940 7.11230 7.19190 - 7.28036 7.31092 7.29545 7.15608 6.40453 5.67011 - 3.45218 2.64391 1.62940 1.46147 1.34473 1.32413 - 10.80654 10.24378 9.76322 9.32172 8.91955 8.55718 - 8.23415 7.95018 7.70519 7.49928 7.33261 7.20506 - 7.11543 7.06343 7.05072 7.07473 7.13229 7.21993 - 7.32249 7.36613 7.38023 7.29161 6.66069 6.01356 - 3.86046 2.95547 1.72856 1.51205 1.35669 1.32391 - 10.79381 10.24397 9.76397 9.32315 8.92162 8.55969 - 8.23703 7.95347 7.70916 7.50416 7.33854 7.21212 - 7.12384 7.07354 7.06308 7.09020 7.15250 7.24860 - 7.36618 7.42308 7.46593 7.43316 6.96908 6.44721 - 4.46340 3.45156 1.91391 1.61447 1.38040 1.32368 - 10.78761 10.24391 9.76400 9.32345 8.92228 8.56069 - 8.23842 7.95538 7.71180 7.50745 7.34190 7.21499 - 7.12689 7.07829 7.07037 7.09903 7.16085 7.25840 - 7.39260 7.46549 7.50920 7.46546 7.14972 6.81970 - 4.84945 3.77592 2.09040 1.73805 1.40372 1.32357 - 10.80202 10.25007 9.76311 9.31966 8.91817 8.55744 - 8.23664 7.95518 7.71280 7.50939 7.34484 7.21846 - 7.12811 7.07378 7.06101 7.09572 7.17940 7.29191 - 7.40792 7.46730 7.52724 7.54494 7.27794 6.89152 - 5.20137 4.14805 2.25518 1.81547 1.42395 1.32350 - 10.79901 10.25014 9.76330 9.31997 8.91861 8.55800 - 8.23730 7.95598 7.71371 7.51045 7.34606 7.21990 - 7.12981 7.07585 7.06354 7.09890 7.18355 7.29757 - 7.41655 7.47907 7.54563 7.57629 7.35976 7.02282 - 5.44879 4.40362 2.41130 1.91523 1.44516 1.32346 - 10.77597 10.24420 9.76486 9.32474 8.92393 8.56273 - 8.24080 7.95801 7.71457 7.51056 7.34611 7.22109 - 7.13452 7.08638 7.07874 7.10976 7.17783 7.28352 - 7.42238 7.49988 7.57566 7.61564 7.46851 7.19600 - 5.80970 4.80564 2.69300 2.10968 1.48706 1.32343 - 10.77302 10.24428 9.76516 9.32500 8.92405 8.56280 - 8.24091 7.95828 7.71510 7.51140 7.34717 7.22226 - 7.13582 7.08798 7.08077 7.11230 7.18107 7.28829 - 7.42926 7.50836 7.59056 7.64279 7.53329 7.30192 - 6.05922 5.10987 2.94253 2.29000 1.52621 1.32342 - 0.52647 0.54935 0.57383 0.59998 0.62759 0.65645 - 0.68655 0.71801 0.75098 0.78571 0.82265 0.86222 - 0.90456 0.94933 0.99503 1.03799 1.07399 1.10200 - 1.12343 1.13285 1.14126 1.14666 1.15070 1.15153 - 1.15214 1.15221 1.15226 1.15227 1.15228 1.15229 - 0.75172 0.78630 0.82188 0.85867 0.89667 0.93591 - 0.97645 1.01838 1.06189 1.10708 1.15409 1.20322 - 1.25503 1.30951 1.36465 1.41563 1.45736 1.49009 - 1.51423 1.52284 1.53196 1.53987 1.54523 1.54634 - 1.54742 1.54755 1.54764 1.54766 1.54765 1.54761 - 0.96985 1.01425 1.05937 1.10543 1.15238 1.20021 - 1.24895 1.29875 1.34987 1.40242 1.45644 1.51213 - 1.57003 1.63005 1.69002 1.74510 1.79027 1.82596 - 1.85273 1.86259 1.87317 1.88251 1.88961 1.89119 - 1.89266 1.89284 1.89297 1.89300 1.89299 1.89293 - 1.37757 1.43844 1.49899 1.55954 1.61989 1.67993 - 1.73971 1.79957 1.86007 1.92128 1.98306 2.04539 - 2.10856 2.17231 2.23468 2.29184 2.33998 2.37972 - 2.41168 2.42459 2.43828 2.45020 2.46057 2.46306 - 2.46521 2.46547 2.46568 2.46572 2.46572 2.46568 - 1.74702 1.82091 1.89284 1.96328 2.03208 2.09921 - 2.16481 2.22941 2.29392 2.35844 2.42291 2.48703 - 2.55038 2.61227 2.67151 2.72659 2.77577 2.81789 - 2.85344 2.86994 2.88654 2.89987 2.91322 2.91651 - 2.91914 2.91949 2.91975 2.91978 2.91982 2.91981 - 2.08034 2.16597 2.24676 2.32365 2.39697 2.46743 - 2.53533 2.60138 2.66670 2.73128 2.79485 2.85690 - 2.91712 2.97513 3.03022 3.08205 3.13015 3.17353 - 3.21227 3.23082 3.24959 3.26472 3.28008 3.28393 - 3.28699 3.28741 3.28770 3.28773 3.28777 3.28782 - 2.38238 2.47776 2.56520 2.64611 2.72145 2.79272 - 2.86046 2.92550 2.98920 3.05150 3.11204 3.17024 - 3.22597 3.27911 3.32939 3.37742 3.42368 3.46734 - 3.50823 3.52827 3.54865 3.56511 3.58196 3.58622 - 3.58959 3.59004 3.59038 3.59042 3.59046 3.59053 - 2.90654 3.01678 3.11264 3.19655 3.27089 3.33887 - 3.40146 3.45984 3.51574 3.56926 3.62018 3.66816 - 3.71338 3.75619 3.79696 3.83733 3.87885 3.92107 - 3.96353 3.98511 4.00721 4.02515 4.04366 4.04839 - 4.05213 4.05264 4.05299 4.05303 4.05308 4.05318 - 3.34677 3.46730 3.56706 3.64957 3.71873 3.77952 - 3.83337 3.88173 3.92673 3.96878 4.00809 4.04479 - 4.07931 4.11234 4.14453 4.17783 4.21408 4.25318 - 4.29468 4.31633 4.33869 4.35693 4.37586 4.38072 - 4.38456 4.38508 4.38546 4.38551 4.38556 4.38565 - 4.20431 4.33853 4.43712 4.50653 4.55440 4.58993 - 4.61591 4.63490 4.65033 4.66314 4.67402 4.68387 - 4.69403 4.70604 4.72061 4.73867 4.76133 4.78947 - 4.82309 4.84143 4.86078 4.87697 4.89394 4.89828 - 4.90178 4.90224 4.90258 4.90262 4.90267 4.90269 - 4.85210 4.96637 5.05264 5.11383 5.15023 5.16385 - 5.15895 5.14296 5.12517 5.10826 5.09328 5.08138 - 5.07409 5.07263 5.07642 5.08288 5.09034 5.10274 - 5.12518 5.14008 5.15450 5.16512 5.17843 5.18194 - 5.18452 5.18483 5.18513 5.18514 5.18522 5.18514 - 5.77957 5.87247 5.92764 5.95035 5.94210 5.90661 - 5.85051 5.78426 5.72012 5.66188 5.61046 5.56660 - 5.53125 5.50455 5.48531 5.46926 5.45328 5.44176 - 5.44057 5.44380 5.44623 5.44718 5.45114 5.45226 - 5.45292 5.45301 5.45313 5.45312 5.45316 5.45300 - 6.43784 6.54631 6.56975 6.53046 6.45370 6.36601 - 6.27402 6.18132 6.09195 6.00808 5.93132 5.86241 - 5.80198 5.74980 5.70589 5.66876 5.63694 5.61012 - 5.58772 5.57802 5.56936 5.56355 5.55854 5.55735 - 5.55642 5.55631 5.55625 5.55625 5.55625 5.55610 - 6.97571 7.06134 7.04895 6.96669 6.84586 6.71830 - 6.59126 6.46781 6.35144 6.24362 6.14516 6.05590 - 5.97626 5.90581 5.84438 5.79032 5.74192 5.69864 - 5.65941 5.64099 5.62349 5.61064 5.59854 5.59566 - 5.59338 5.59308 5.59287 5.59284 5.59282 5.59277 - 7.43105 7.48851 7.43925 7.31643 7.15595 6.99355 - 6.83653 6.68710 6.54790 6.41972 6.30241 6.19515 - 6.09832 6.01170 5.93485 5.86580 5.80269 5.74523 - 5.69220 5.66668 5.64188 5.62317 5.60523 5.60096 - 5.59756 5.59711 5.59677 5.59672 5.59669 5.59677 - 8.35311 8.15486 7.95139 7.75320 7.56012 7.37236 - 7.19011 7.01345 6.84302 6.67996 6.52471 6.37766 - 6.24010 6.11378 5.99977 5.89991 5.81518 5.74210 - 5.67952 5.65540 5.63791 5.62208 5.55669 5.52596 - 5.54007 5.54653 5.54323 5.54120 5.54444 5.54276 - 8.72615 8.65530 8.46589 8.20436 7.91693 7.64632 - 7.39862 7.17271 6.96728 6.78041 6.60751 6.44554 - 6.29530 6.15805 6.03273 5.91679 5.80833 5.70828 - 5.61529 5.56955 5.52423 5.48906 5.45471 5.44652 - 5.43996 5.43907 5.43840 5.43830 5.43825 5.43855 - 9.67972 9.44278 9.10440 8.71443 8.31852 7.95652 - 7.63225 7.34335 7.08665 6.85547 6.63960 6.43297 - 6.23830 6.05840 5.89292 5.73834 5.59261 5.45697 - 5.33046 5.26872 5.20773 5.16042 5.11386 5.10237 - 5.09325 5.09208 5.09120 5.09107 5.09099 5.09093 - 10.37267 9.84670 9.34772 8.88508 8.45621 8.05943 - 7.69316 7.35640 7.04861 6.76795 6.51190 6.27724 - 6.05930 5.85512 5.66597 5.49140 5.32938 5.17050 - 5.00756 4.92833 4.85759 4.80921 4.75465 4.73923 - 4.72865 4.72766 4.72654 4.72637 4.72622 4.72567 - 10.99681 10.29824 9.65367 9.06542 8.52775 8.03755 - 7.59253 7.18937 6.82545 6.49741 6.20096 5.93092 - 5.68002 5.44319 5.22081 5.01336 4.81777 4.62535 - 4.43046 4.33661 4.25315 4.19596 4.13054 4.11172 - 4.09906 4.09791 4.09661 4.09643 4.09615 4.09524 - 11.31856 10.50301 9.76633 9.10131 8.49993 7.95654 - 7.46735 7.02682 6.62956 6.27098 5.94609 5.64886 - 5.37102 5.10686 4.85683 4.62219 4.40272 4.19451 - 3.99594 3.90089 3.80698 3.73350 3.66169 3.64372 - 3.62939 3.62771 3.62628 3.62610 3.62595 3.62574 - 11.52645 10.61950 9.81606 9.09780 8.45473 7.87799 - 7.36098 6.89531 6.47275 6.08846 5.73838 5.41791 - 5.12107 4.84325 4.58301 4.33777 4.10559 3.88446 - 3.67457 3.57390 3.47330 3.39338 3.31593 3.29742 - 3.28271 3.28091 3.27921 3.27895 3.27886 3.28006 - 11.65831 10.68909 9.84068 9.08479 8.41116 7.80952 - 7.27125 6.78672 6.34665 5.94583 5.58027 5.24551 - 4.93594 4.64715 4.37734 4.12337 3.88289 3.65370 - 3.43472 3.32890 3.22283 3.13830 3.05626 3.03686 - 3.02164 3.01975 3.01784 3.01753 3.01747 3.01949 - 11.80806 10.75642 9.85134 9.04816 8.33624 7.70401 - 7.13982 6.63248 6.17173 5.75205 5.36918 5.01851 - 4.69439 4.39231 4.10994 3.84357 3.58996 3.34699 - 3.11201 2.99745 2.88332 2.79260 2.70202 2.68006 - 2.66250 2.66028 2.65835 2.65817 2.65794 2.65883 - 11.86967 10.77321 9.84001 9.01339 8.28256 7.63493 - 7.05761 6.53870 6.06778 5.63911 5.24816 4.88996 - 4.55853 4.24900 3.95868 3.68335 3.41927 3.16430 - 2.91602 2.79390 2.67187 2.57462 2.47633 2.45077 - 2.43041 2.42812 2.42627 2.42601 2.42581 2.42407 - 11.89405 10.75226 9.79765 8.95356 8.21022 7.55050 - 6.96226 6.43376 5.95499 5.51992 5.12349 4.76008 - 4.42290 4.10634 3.80705 3.51986 3.23959 2.96177 - 2.68216 2.53968 2.39331 2.27344 2.15301 2.12214 - 2.09697 2.09404 2.09178 2.09149 2.09117 2.08911 - 11.84761 10.70547 9.76138 8.92591 8.18959 7.53306 - 6.94584 6.41731 5.93852 5.50354 5.10723 4.74391 - 4.40668 4.08961 3.78873 3.49769 3.20951 2.91638 - 2.60884 2.44560 2.27061 2.12200 1.97769 1.94437 - 1.91748 1.91395 1.91053 1.91002 1.90980 1.91295 - 11.70492 10.60507 9.70911 8.91157 8.20020 7.55937 - 6.98211 6.46152 5.99162 5.56647 5.17982 4.82448 - 4.49135 4.17347 3.86809 3.57123 3.27494 2.96158 - 2.60946 2.41173 2.19249 1.99705 1.79327 1.74859 - 1.72706 1.72471 1.71732 1.71558 1.71712 1.72913 - 11.60584 10.52791 9.66871 8.90639 8.22333 7.60596 - 7.04725 6.54012 6.07854 5.65788 5.27380 4.92146 - 4.59489 4.28813 3.99535 3.70651 3.40774 3.07751 - 2.68630 2.45540 2.18919 1.94631 1.70043 1.65245 - 1.62978 1.62657 1.61691 1.61474 1.61716 1.63412 - 11.51459 10.46464 9.64236 8.91110 8.25208 7.65400 - 7.11088 6.61664 6.16601 5.75479 5.37891 5.03378 - 4.71358 4.41242 4.12407 3.83772 3.53768 3.19802 - 2.78135 2.52682 2.22403 1.94172 1.64948 1.59246 - 1.57210 1.56956 1.55729 1.55439 1.55814 1.57645 - 11.44144 10.41427 9.62366 8.91818 8.28010 7.69933 - 7.17069 6.68872 6.24880 5.84695 5.47933 5.14145 - 4.82759 4.53179 4.24771 3.96410 3.66399 3.31816 - 2.88237 2.60867 2.27458 1.95675 1.62089 1.55431 - 1.53491 1.53295 1.51847 1.51493 1.51985 1.53793 - 11.33177 10.33988 9.60002 8.93499 8.33116 7.77946 - 7.27584 6.81566 6.39502 6.01038 5.65814 5.33398 - 5.03219 4.74677 4.47132 4.19416 3.89655 3.54408 - 3.08086 2.77706 2.39177 2.01450 1.60483 1.51712 - 1.48554 1.48444 1.47310 1.47015 1.47605 1.48987 - 11.25391 10.28956 9.58763 8.95312 8.37554 7.84664 - 7.36304 6.92074 6.51636 6.14664 5.80806 5.49635 - 5.20561 4.92972 4.66233 4.39175 4.09834 3.74479 - 3.26621 2.94150 2.51640 2.08837 1.61021 1.50343 - 1.46056 1.45886 1.44686 1.44365 1.44924 1.46096 - 11.17025 10.23697 9.58334 8.99147 8.45326 7.96158 - 7.51341 7.10518 6.73377 6.39574 6.08706 5.80238 - 5.53395 5.27483 5.02078 4.76399 4.48751 4.15094 - 3.67099 3.31792 2.81767 2.28861 1.66594 1.50332 - 1.44200 1.43489 1.41046 1.40856 1.40654 1.42107 - 11.11311 10.20698 9.58765 9.02614 8.51504 8.04825 - 7.62309 7.23640 6.88540 6.56693 6.27722 6.01110 - 5.76082 5.51940 5.28263 5.04255 4.78144 4.45627 - 3.97625 3.61245 3.08363 2.50090 1.75161 1.53689 - 1.43200 1.42057 1.39429 1.39154 1.38964 1.40023 - 11.02179 10.16901 9.60512 9.08797 8.61266 8.17552 - 7.77556 7.41166 7.08302 6.78738 6.52164 6.28134 - 6.05953 5.84928 5.64473 5.43411 5.19715 4.89427 - 4.43315 4.06984 3.51855 2.86613 1.93353 1.65116 - 1.42535 1.39958 1.38112 1.37802 1.37394 1.37904 - 11.00139 10.16598 9.62390 9.12577 8.66778 8.24698 - 7.86273 7.51446 7.20179 6.92279 6.67450 6.45270 - 6.25048 6.06094 5.87837 5.69078 5.47820 5.20278 - 4.77131 4.41943 3.86613 3.17749 2.10664 1.75332 - 1.43904 1.39867 1.37275 1.36950 1.36243 1.36845 - 10.99949 10.17082 9.63893 9.15109 8.70369 8.29390 - 7.92080 7.58358 7.28159 7.01332 6.77656 6.56810 - 6.38246 6.21328 6.05306 5.88535 5.68676 5.42241 - 5.00937 4.67946 4.16507 3.48352 2.26676 1.83601 - 1.45652 1.40615 1.36785 1.36187 1.35941 1.36218 - 10.99473 10.17488 9.65152 9.17156 8.73172 8.32945 - 7.96391 7.63433 7.34016 7.08005 6.85209 6.65339 - 6.47888 6.32270 6.17784 6.02839 5.85088 5.60841 - 5.21668 4.89862 4.39778 3.71808 2.42727 1.93059 - 1.47226 1.41049 1.36583 1.35861 1.35564 1.35807 - 10.98643 10.18179 9.66984 9.20010 8.76979 8.37694 - 8.02107 7.70179 7.41891 7.17126 6.95699 6.77317 - 6.61459 6.47562 6.35079 6.22676 6.08248 5.88138 - 5.53933 5.24884 4.77300 4.09410 2.70348 2.11916 - 1.51059 1.42092 1.36271 1.35785 1.34826 1.35297 - 11.00284 10.19508 9.68110 9.21288 8.78708 8.40116 - 8.05382 7.74367 7.46948 7.22996 7.02350 6.84737 - 6.69661 6.56701 6.45701 6.36090 6.25987 6.09725 - 5.77180 5.49234 5.05193 4.40962 2.95262 2.28419 - 1.54696 1.43728 1.36347 1.35500 1.34736 1.34984 - 10.97905 10.19632 9.69638 9.23995 8.82421 8.44724 - 8.10798 7.80541 7.53881 7.30774 7.11172 6.94973 - 6.81945 6.71801 6.64133 6.57690 6.50479 6.39053 - 6.15351 5.92991 5.54809 4.95771 3.46387 2.64324 - 1.64325 1.48761 1.36791 1.35570 1.33932 1.34553 - 10.96096 10.20026 9.70626 9.25440 8.84241 8.46887 - 8.13305 7.83450 7.57311 7.34852 7.16025 7.00717 - 6.88672 6.79639 6.73390 6.69019 6.64867 6.57519 - 6.39535 6.21023 5.86918 5.32257 3.85809 2.96125 - 1.73591 1.53260 1.37562 1.35777 1.34105 1.34335 - 10.92058 10.20473 9.71556 9.26760 8.85931 8.48978 - 8.15846 7.86510 7.60974 7.39217 7.21203 7.06840 - 6.95899 6.88179 6.83567 6.81325 6.80245 6.78084 - 6.68421 6.55179 6.27364 5.79921 4.43344 3.45957 - 1.91566 1.63710 1.39253 1.36564 1.33745 1.34117 - 10.88594 10.20608 9.71957 9.27424 8.86837 8.50099 - 8.17184 7.88119 7.62949 7.41620 7.24021 7.10042 - 6.99548 6.92457 6.88803 6.88092 6.89271 6.89745 - 6.83277 6.73267 6.53010 6.16024 4.83674 3.78379 - 2.10036 1.76115 1.40839 1.35903 1.34173 1.34010 - 10.85998 10.20715 9.72260 9.27864 8.87393 8.50781 - 8.18010 7.89115 7.64144 7.43045 7.25709 7.12030 - 7.01882 6.95208 6.92092 6.92137 6.94481 6.96950 - 6.93965 6.86523 6.69748 6.37610 5.15213 4.09416 - 2.25520 1.85903 1.42959 1.36687 1.34528 1.33947 - 10.84176 10.20809 9.72483 9.28162 8.87757 8.51238 - 8.18587 7.89825 7.64992 7.44034 7.26851 7.13353 - 7.03456 6.97125 6.94413 6.94839 6.97689 7.01759 - 7.02290 6.96872 6.81493 6.51381 5.40270 4.37237 - 2.39809 1.94861 1.45338 1.37850 1.34504 1.33906 - 10.81937 10.20907 9.72730 9.28515 8.88215 8.51831 - 8.19340 7.90746 7.66081 7.45296 7.28307 7.15048 - 7.05461 6.99538 6.97353 6.98449 7.02235 7.07939 - 7.11930 7.09602 6.98648 6.74019 5.75980 4.78573 - 2.67356 2.12671 1.49649 1.39654 1.35118 1.33854 - 10.80479 10.20973 9.72907 9.28759 8.88523 8.52223 - 8.19825 7.91313 7.66701 7.45977 7.29123 7.16095 - 7.06766 7.01085 6.99163 7.00650 7.05027 7.11475 - 7.17628 7.18085 7.10941 6.88550 5.97407 5.13469 - 2.93018 2.27978 1.53756 1.42580 1.34636 1.33823 - 10.78375 10.21053 9.73082 9.29016 8.88880 8.52713 - 8.20466 7.92102 7.67611 7.47001 7.30292 7.17466 - 7.08395 7.03039 7.01545 7.03624 7.08890 7.16813 - 7.25616 7.28655 7.27094 7.13177 6.38431 5.65515 - 3.45071 2.64769 1.64032 1.47401 1.35764 1.33781 - 10.77186 10.21083 9.73168 9.29161 8.89080 8.52965 - 8.20771 7.92463 7.68036 7.47502 7.30882 7.18165 - 7.09230 7.04041 7.02768 7.05154 7.10885 7.19611 - 7.29820 7.34165 7.35555 7.26692 6.63874 5.99616 - 3.85679 2.95756 1.73874 1.52403 1.36948 1.33759 - 10.75928 10.21101 9.73247 9.29312 8.89295 8.53221 - 8.21055 7.92785 7.68426 7.47990 7.31478 7.18873 - 7.10070 7.05053 7.04006 7.06703 7.12905 7.22474 - 7.34182 7.39845 7.44106 7.40816 6.94538 6.42686 - 4.45665 3.45098 1.92223 1.62475 1.39304 1.33736 - 10.75316 10.21115 9.73262 9.29349 8.89364 8.53322 - 8.21191 7.92973 7.68689 7.48317 7.31811 7.19160 - 7.10377 7.05531 7.04735 7.07585 7.13742 7.23455 - 7.36821 7.44081 7.48432 7.44054 7.12531 6.79734 - 4.84039 3.77321 2.09692 1.74674 1.41625 1.33724 - 10.76753 10.21741 9.73194 9.28982 8.88956 8.52994 - 8.21012 7.92953 7.68789 7.48512 7.32107 7.19509 - 7.10500 7.05082 7.03804 7.07258 7.15592 7.26796 - 7.38348 7.44263 7.50245 7.52005 7.25298 6.86841 - 5.19064 4.14360 2.26000 1.82261 1.43633 1.33718 - 10.76455 10.21749 9.73215 9.29016 8.89002 8.53051 - 8.21081 7.93033 7.68881 7.48618 7.32229 7.19652 - 7.10669 7.05287 7.04056 7.07577 7.16008 7.27363 - 7.39211 7.45441 7.52082 7.55133 7.33447 6.99908 - 5.43648 4.39751 2.41488 1.92142 1.45739 1.33714 - 10.74176 10.21145 9.73349 9.29472 8.89521 8.53516 - 8.21426 7.93238 7.68970 7.48633 7.32239 7.19773 - 7.11137 7.06335 7.05569 7.08656 7.15434 7.25966 - 7.39802 7.47521 7.55074 7.59056 7.44329 7.17152 - 5.79444 4.79652 2.69561 2.11561 1.49879 1.33711 - 10.73873 10.21123 9.73356 9.29486 8.89532 8.53526 - 8.21438 7.93260 7.69018 7.48712 7.32340 7.19887 - 7.11267 7.06495 7.05772 7.08909 7.15755 7.26439 - 7.40486 7.48363 7.56554 7.61745 7.50780 7.27739 - 6.04120 5.09774 2.94604 2.29788 1.53730 1.33711 - 0.51850 0.54112 0.56543 0.59144 0.61894 0.64766 - 0.67759 0.70882 0.74147 0.77577 0.81214 0.85092 - 0.89218 0.93561 0.97984 1.02173 1.05761 1.08646 - 1.10888 1.11836 1.12688 1.13266 1.13764 1.13876 - 1.13962 1.13972 1.13980 1.13982 1.13983 1.13941 - 0.74153 0.77580 0.81111 0.84764 0.88540 0.92441 - 0.96469 1.00630 1.04938 1.09400 1.14026 1.18844 - 1.23909 1.29223 1.34601 1.39614 1.43798 1.47164 - 1.49724 1.50671 1.51655 1.52498 1.53154 1.53302 - 1.53439 1.53451 1.53459 1.53469 1.53470 1.52692 - 0.95767 1.00166 1.04642 1.09216 1.13881 1.18635 - 1.23478 1.28422 1.33486 1.38679 1.44002 1.49477 - 1.55155 1.61034 1.66915 1.72357 1.76901 1.80582 - 1.83440 1.84537 1.85694 1.86699 1.87536 1.87731 - 1.87908 1.87925 1.87937 1.87947 1.87948 1.87217 - 1.36194 1.42227 1.48236 1.54247 1.60245 1.66217 - 1.72163 1.78114 1.84121 1.90187 1.96300 2.02456 - 2.08687 2.14974 2.21136 2.26824 2.31691 2.35797 - 2.39196 2.40611 2.42096 2.43371 2.44527 2.44808 - 2.45048 2.45077 2.45100 2.45104 2.45105 2.45144 - 1.72848 1.80183 1.87325 1.94322 2.01160 2.07842 - 2.14377 2.20815 2.27236 2.33650 2.40052 2.46412 - 2.52692 2.58831 2.64720 2.70230 2.75212 2.79564 - 2.83322 2.85081 2.86849 2.88266 2.89697 2.90047 - 2.90331 2.90381 2.90408 2.90394 2.90406 2.91204 - 2.05946 2.14449 2.22475 2.30116 2.37412 2.44433 - 2.51207 2.57802 2.64320 2.70762 2.77097 2.83279 - 2.89279 2.95059 3.00561 3.05769 3.10655 3.15128 - 3.19187 3.21138 3.23108 3.24691 3.26303 3.26699 - 3.27022 3.27085 3.27114 3.27089 3.27107 3.28432 - 2.35955 2.45429 2.54121 2.62168 2.69673 2.76784 - 2.83552 2.90058 2.96432 3.02667 3.08725 3.14547 - 3.20124 3.25442 3.30486 3.35330 3.40039 3.44534 - 3.48785 3.50870 3.52983 3.54685 3.56424 3.56852 - 3.57203 3.57274 3.57305 3.57275 3.57296 3.58877 - 2.88077 2.99034 3.08574 3.16937 3.24359 3.31162 - 3.37439 3.43305 3.48929 3.54321 3.59458 3.64301 - 3.68866 3.73189 3.77310 3.81406 3.85644 3.89976 - 3.94343 3.96555 3.98810 4.00632 4.02504 4.02970 - 4.03349 4.03419 4.03454 4.03428 4.03448 4.04814 - 3.31897 3.43887 3.53828 3.62069 3.68995 3.75099 - 3.80523 3.85411 3.89972 3.94245 3.98249 4.01993 - 4.05516 4.08881 4.12160 4.15555 4.19264 4.23265 - 4.27501 4.29701 4.31961 4.33793 4.35682 4.36159 - 4.36542 4.36602 4.36637 4.36629 4.36640 4.37252 - 4.17377 4.30762 4.40625 4.47599 4.52446 4.56074 - 4.58760 4.60754 4.62395 4.63777 4.64978 4.66085 - 4.67212 4.68498 4.70019 4.71889 4.74233 4.77105 - 4.80493 4.82341 4.84280 4.85884 4.87545 4.87969 - 4.88315 4.88346 4.88371 4.88395 4.88397 4.86978 - 4.82062 4.93506 5.02178 5.08364 5.12092 5.13560 - 5.13190 5.11718 5.10069 5.08507 5.07134 5.06065 - 5.05445 5.05395 5.05855 5.06567 5.07363 5.08640 - 5.10906 5.12403 5.13847 5.14904 5.16196 5.16533 - 5.16792 5.16806 5.16822 5.16847 5.16858 5.14275 - 5.74883 5.84253 5.89878 5.92276 5.91594 5.88199 - 5.82748 5.76278 5.70010 5.64323 5.59305 5.55035 - 5.51608 5.49040 5.47205 5.45665 5.44099 5.42969 - 5.42884 5.43232 5.43506 5.43623 5.44007 5.44112 - 5.44186 5.44180 5.44175 5.44199 5.44208 5.41364 - 6.40908 6.51834 6.54326 6.50585 6.43113 6.34533 - 6.25507 6.16393 6.07599 5.99342 5.91788 5.85011 - 5.79079 5.73969 5.69674 5.66027 5.62869 5.60202 - 5.58009 5.57088 5.56276 5.55737 5.55254 5.55153 - 5.55060 5.55018 5.55014 5.55060 5.55038 5.52952 - 6.94900 7.03552 7.02491 6.94490 6.82640 6.70088 - 6.57560 6.45375 6.33891 6.23250 6.13531 6.04713 - 5.96856 5.89929 5.83898 5.78564 5.73734 5.69408 - 5.65548 5.63767 5.62085 5.60855 5.59689 5.59411 - 5.59196 5.59158 5.59131 5.59143 5.59141 5.58080 - 7.40630 7.46468 7.41740 7.29713 7.13921 6.97892 - 6.82366 6.67579 6.53821 6.41162 6.29568 6.18956 - 6.09384 6.00847 5.93282 5.86452 5.80145 5.74397 - 5.69162 5.66670 5.64264 5.62456 5.60719 5.60308 - 5.59979 5.59934 5.59901 5.59898 5.59896 5.59869 - 8.33055 8.13484 7.93391 7.73815 7.54738 7.36181 - 7.18163 7.00692 6.83830 6.67692 6.52323 6.37761 - 6.24132 6.11610 6.00304 5.90394 5.81980 5.74721 - 5.68509 5.66119 5.64398 5.62854 5.56445 5.53427 - 5.54831 5.55487 5.55159 5.54926 5.55261 5.56551 - 8.70777 8.63793 8.45103 8.19268 7.90825 7.63987 - 7.39382 7.16941 6.96579 6.78087 6.60978 6.44930 - 6.30046 6.16467 6.04075 5.92573 5.81748 5.71755 - 5.62522 5.57999 5.53535 5.50087 5.46733 5.45934 - 5.45283 5.45215 5.45161 5.45124 5.45120 5.47242 - 9.79575 9.39636 9.00784 8.64151 8.29641 7.97166 - 7.66665 7.38146 7.11627 6.87072 6.64386 6.43426 - 6.24007 6.06077 5.89753 5.75031 5.61728 5.48780 - 5.35232 5.28503 5.22380 5.18124 5.13575 5.12391 - 5.11485 5.11398 5.11308 5.11274 5.11281 5.12409 - 10.36171 9.83962 9.34414 8.88458 8.45841 8.06400 - 7.69981 7.36488 7.05869 6.77946 6.52473 6.29133 - 6.07472 5.87199 5.68443 5.51158 5.35137 5.19416 - 5.03248 4.95376 4.88364 4.83590 4.78204 4.76680 - 4.75641 4.75537 4.75422 4.75412 4.75399 4.74764 - 10.98875 10.29507 9.65477 9.07009 8.53543 8.04771 - 7.60472 7.20326 6.84072 6.51386 6.21849 5.94953 - 5.69988 5.46455 5.24399 5.03867 4.84546 4.65536 - 4.46236 4.36927 4.28653 4.22994 4.16518 4.14654 - 4.13406 4.13287 4.13151 4.13140 4.13114 4.12363 - 11.31094 10.49860 9.76626 9.10612 8.50978 7.97112 - 7.48585 7.04775 6.65088 6.29110 5.96434 5.66573 - 5.38878 5.12861 4.88413 4.65347 4.43445 4.22611 - 4.02982 3.93657 3.84374 3.77031 3.69885 3.68125 - 3.66706 3.66540 3.66399 3.66375 3.66362 3.66482 - 11.51889 10.61817 9.81963 9.10525 8.46526 7.89096 - 7.37593 6.91193 6.49089 6.10802 5.75937 5.44037 - 5.14511 4.86903 4.61067 4.36738 4.13712 3.91780 - 3.70954 3.60963 3.50973 3.43034 3.35340 3.33500 - 3.32034 3.31857 3.31692 3.31664 3.31655 3.31937 - 11.65043 10.68726 9.84361 9.09158 8.42106 7.82200 - 7.28586 6.80320 6.36484 5.96566 5.60170 5.26854 - 4.96059 4.67346 4.40534 4.15306 3.91421 3.68655 - 3.46895 3.36377 3.25829 3.17416 3.09252 3.07322 - 3.05797 3.05608 3.05426 3.05399 3.05391 3.05543 - 11.79479 10.75113 9.85199 9.05351 8.34520 7.71578 - 7.15380 6.64828 6.18916 5.77096 5.38950 5.04020 - 4.71749 4.41685 4.13594 3.87091 3.61852 3.37690 - 3.14355 3.02966 2.91558 2.82456 2.73451 2.71235 - 2.69489 2.69280 2.69088 2.69061 2.69049 2.68991 - 11.85870 10.76809 9.83920 9.01608 8.28812 7.64287 - 7.06758 6.55055 6.08146 5.65459 5.26542 4.90897 - 4.57922 4.27124 3.98236 3.70832 3.44532 3.19125 - 2.94367 2.82184 2.70006 2.60294 2.50470 2.47914 - 2.45886 2.45659 2.45469 2.45439 2.45421 2.45353 - 11.87989 10.74322 9.79225 8.95110 8.21011 7.55237 - 6.96584 6.43892 5.96170 5.52821 5.13337 4.77160 - 4.43612 4.12130 3.82375 3.53817 3.25926 2.98240 - 2.70326 2.56085 2.41453 2.29471 2.17435 2.14350 - 2.11843 2.11553 2.11321 2.11286 2.11256 2.11231 - 11.83154 10.69330 9.75193 8.91879 8.18447 7.52975 - 6.94416 6.41715 5.93977 5.50616 5.11125 4.74944 - 4.41393 4.09885 3.80013 3.51125 3.22497 2.93320 - 2.62614 2.46286 2.28781 2.13924 1.99529 1.96211 - 1.93511 1.93154 1.92827 1.92786 1.92760 1.92857 - 11.68385 10.58766 9.69373 8.89799 8.18816 7.54878 - 6.97288 6.45362 5.98505 5.56125 5.17602 4.82224 - 4.49091 4.17507 3.87202 3.57767 3.28397 2.97287 - 2.62220 2.42481 2.20564 2.01017 1.80700 1.76260 - 1.74060 1.73824 1.73150 1.73005 1.73149 1.74120 - 11.56476 10.49834 9.64562 8.88701 8.20589 7.58970 - 7.03226 6.52756 6.07034 5.65533 5.27694 4.92868 - 4.60222 4.29083 3.99117 3.69790 3.40028 3.07429 - 2.68909 2.46328 2.20532 1.96936 1.71534 1.65793 - 1.64002 1.63927 1.62977 1.62735 1.63059 1.64768 - 11.46899 10.42914 9.61292 8.88589 8.23000 7.63453 - 7.09413 6.60336 6.15749 5.75173 5.38098 5.03920 - 4.71857 4.41248 4.11714 3.82626 3.52699 3.19049 - 2.77854 2.52973 2.23854 1.96730 1.66564 1.59500 - 1.58043 1.58128 1.56944 1.56621 1.57115 1.59048 - 11.39200 10.37457 9.59018 8.88949 8.25533 7.67805 - 7.15289 6.67490 6.23973 5.84300 5.47997 5.14492 - 4.83039 4.52991 4.23930 3.95153 3.65204 3.30808 - 2.87495 2.60702 2.28736 1.98443 1.63847 1.55485 - 1.54188 1.54403 1.53026 1.52638 1.53276 1.55175 - 11.26752 10.29019 9.56019 8.90305 8.30553 7.75902 - 7.25981 6.80367 6.38704 6.00617 5.65696 5.33445 - 5.03191 4.74314 4.46335 4.18399 3.88705 3.53154 - 3.06090 2.75986 2.39370 2.04227 1.63541 1.52692 - 1.48035 1.48598 1.49191 1.48897 1.47988 1.50281 - 11.18524 10.23639 9.54531 8.91961 8.34918 7.82610 - 7.34720 6.90880 6.50776 6.14074 5.80410 5.49324 - 5.20187 4.92395 4.65438 4.38380 4.09208 3.73302 - 3.24035 2.91590 2.51197 2.11560 1.64500 1.51444 - 1.45350 1.45924 1.46679 1.46338 1.45102 1.47320 - 11.13661 10.20642 9.55333 8.96214 8.42468 7.93390 - 7.48673 7.07963 6.70946 6.37280 6.06565 5.78265 - 5.51612 5.25915 5.00756 4.75360 4.48040 4.14755 - 3.67147 3.31999 2.82057 2.29261 1.67502 1.51393 - 1.44975 1.44212 1.42168 1.42225 1.41819 1.43303 - 11.07900 10.17594 9.55715 8.99626 8.48587 8.01996 - 7.59582 7.21026 6.86051 6.54341 6.25517 5.99064 - 5.74208 5.50253 5.26782 5.03012 4.77181 4.45014 - 3.97430 3.61248 3.08504 2.50394 1.76013 1.54707 - 1.44056 1.42887 1.40597 1.40529 1.40168 1.41268 - 10.97358 10.12348 9.56203 9.04924 8.57966 8.14883 - 7.75492 7.39577 7.06951 6.77407 6.50696 6.26459 - 6.04144 5.83202 5.63176 5.43094 5.20615 4.89839 - 4.40237 4.02289 3.48204 2.86861 1.97313 1.66966 - 1.42673 1.40557 1.39925 1.39482 1.37503 1.39234 - 10.96964 10.13541 9.59273 9.09484 8.63775 8.21836 - 7.83580 7.48920 7.17797 6.90006 6.65268 6.43159 - 6.23009 6.04139 5.85985 5.67368 5.46306 5.19030 - 4.76256 4.41323 3.86324 3.17826 2.11313 1.76186 - 1.45022 1.41058 1.38570 1.38267 1.37579 1.38202 - 10.96744 10.14052 9.60833 9.12081 8.67431 8.26581 - 7.89426 7.55853 7.25782 6.99053 6.75456 6.54672 - 6.36164 6.19308 6.03360 5.86693 5.66991 5.40797 - 4.99870 4.67149 4.16054 3.48266 2.27197 1.84420 - 1.46847 1.41877 1.38109 1.37526 1.37273 1.37580 - 10.96260 10.14486 9.62133 9.14178 8.70283 8.30178 - 7.93763 7.60943 7.31640 7.05720 6.82992 6.63176 - 6.45772 6.30205 6.15777 6.00915 5.83287 5.59247 - 5.20428 4.88889 4.39168 3.71605 2.43174 1.93809 - 1.48450 1.42366 1.37929 1.37186 1.36913 1.37166 - 10.95448 10.15230 9.64027 9.17097 8.74148 8.34972 - 7.99507 7.67698 7.39510 7.14824 6.93458 6.75121 - 6.59299 6.45437 6.32987 6.20635 6.06291 5.86341 - 5.52439 5.23642 4.76425 4.08969 2.70651 2.12585 - 1.52273 1.43398 1.37620 1.37127 1.36185 1.36651 - 10.97004 10.16579 9.65241 9.18484 8.75971 8.37451 - 8.02790 7.71851 7.44504 7.20627 7.00050 6.82501 - 6.67481 6.54562 6.43594 6.34010 6.23948 6.07786 - 5.75489 5.47774 5.04104 4.40348 2.95450 2.28975 - 1.55842 1.44986 1.37686 1.36835 1.36100 1.36340 - 10.94809 10.16765 9.66759 9.21138 8.79617 8.42000 - 8.08167 7.78010 7.51444 7.28423 7.08894 6.92751 - 6.79754 6.69610 6.61924 6.55475 6.48296 6.36939 - 6.13393 5.91209 5.53346 4.94761 3.46309 2.64709 - 1.65258 1.49825 1.38086 1.36920 1.35290 1.35923 - 10.93088 10.17179 9.67744 9.22571 8.81427 8.44158 - 8.10679 7.80932 7.54883 7.32498 7.13728 6.98459 - 6.86436 6.77409 6.71156 6.66784 6.62640 6.55321 - 6.37425 6.19039 5.85209 5.30975 3.85506 2.96363 - 1.74390 1.54186 1.38822 1.37161 1.35451 1.35717 - 10.89059 10.17717 9.68790 9.23987 8.83171 8.46270 - 8.13219 7.83974 7.58522 7.36837 7.18878 7.04550 - 6.93631 6.85926 6.81320 6.79074 6.77984 6.75810 - 6.66169 6.52992 6.25363 5.78282 4.42696 3.45902 - 1.92288 1.64622 1.40517 1.37919 1.35100 1.35508 - 10.85626 10.17882 9.69260 9.24735 8.84159 8.47451 - 8.14588 7.85583 7.60479 7.39213 7.21671 7.07738 - 6.97278 6.90206 6.86556 6.85836 6.86994 6.87442 - 6.80968 6.70996 6.50864 6.14151 4.82722 3.78084 - 2.10781 1.77089 1.42104 1.37225 1.35527 1.35403 - 10.83050 10.18020 9.69610 9.25238 8.84782 8.48192 - 8.15454 7.86598 7.61677 7.40635 7.23352 7.09719 - 6.99608 6.92954 6.89844 6.89877 6.92198 6.94635 - 6.91628 6.84204 6.67514 6.35587 5.14038 4.08940 - 2.26250 1.86885 1.44222 1.37999 1.35879 1.35341 - 10.81248 10.18124 9.69866 9.25581 8.85196 8.48698 - 8.16071 7.87337 7.62542 7.41631 7.24494 7.11041 - 7.01179 6.94868 6.92160 6.92576 6.95402 6.99438 - 6.99936 6.94517 6.79199 6.49271 5.38938 4.36578 - 2.40467 1.95805 1.46585 1.39151 1.35856 1.35298 - 10.79026 10.18242 9.70155 9.25999 8.85734 8.49376 - 8.16902 7.88328 7.63685 7.42927 7.25969 7.12739 - 7.03176 6.97270 6.95090 6.96179 6.99943 7.05612 - 7.09559 7.07217 6.96287 6.71789 5.74410 4.77614 - 2.67804 2.13479 1.50841 1.40918 1.36470 1.35245 - 10.77594 10.18318 9.70353 9.26281 8.86095 8.49828 - 8.17451 7.88955 7.64362 7.43658 7.26819 7.13802 - 7.04481 6.98809 6.96892 6.98374 7.02728 7.09140 - 7.15253 7.15695 7.08543 6.86223 5.95699 5.12325 - 2.93208 2.28600 1.54889 1.43822 1.35983 1.35213 - 10.75525 10.18409 9.70553 9.26578 8.86513 8.50400 - 8.18195 7.89857 7.65382 7.44778 7.28062 7.15222 - 7.06137 7.00773 6.99270 7.01339 7.06582 7.14468 - 7.23228 7.26249 7.24670 7.10764 6.36414 5.64058 - 3.44778 2.64988 1.65035 1.48599 1.37080 1.35170 - 10.74360 10.18448 9.70649 9.26738 8.86738 8.50691 - 8.18548 7.90279 7.65874 7.45346 7.28719 7.15984 - 7.07024 7.01809 7.00508 7.02866 7.08567 7.17260 - 7.27428 7.31751 7.33121 7.24241 6.61687 5.97937 - 3.85099 2.95734 1.74786 1.53545 1.38248 1.35149 - 10.73108 10.18477 9.70740 9.26902 8.86970 8.50972 - 8.18873 7.90655 7.66334 7.45914 7.29405 7.16793 - 7.07963 7.02903 7.01798 7.04435 7.10589 7.20117 - 7.31783 7.37420 7.41658 7.38342 6.92184 6.40697 - 4.44835 3.44880 1.93012 1.63501 1.40588 1.35128 - 10.72504 10.18491 9.70761 9.26947 8.87047 8.51082 - 8.19024 7.90866 7.66632 7.46294 7.29804 7.17148 - 7.08341 7.03449 7.02590 7.05366 7.11450 7.21099 - 7.34411 7.41647 7.45975 7.41588 7.10110 6.77504 - 4.83164 3.77099 2.10400 1.75593 1.42912 1.35119 - 10.73956 10.19107 9.70679 9.26580 8.86650 8.50774 - 8.18865 7.90869 7.66752 7.46510 7.30124 7.17531 - 7.08510 7.03061 7.01732 7.05110 7.13344 7.24444 - 7.35918 7.41814 7.47798 7.49552 7.22783 6.84534 - 5.18208 4.14131 2.26624 1.83090 1.44900 1.35113 - 10.73661 10.19114 9.70701 9.26614 8.86697 8.50834 - 8.18939 7.90956 7.66858 7.46634 7.30273 7.17704 - 7.08716 7.03308 7.02028 7.05473 7.13799 7.25036 - 7.36780 7.42980 7.49633 7.52698 7.30897 6.97526 - 5.42738 4.39460 2.42025 1.92892 1.46988 1.35110 - 10.71377 10.18531 9.70871 9.27099 8.87233 8.51305 - 8.19288 7.91166 7.66955 7.46663 7.30298 7.17845 - 7.09212 7.04399 7.03604 7.06626 7.13295 7.23684 - 7.37396 7.45078 7.52596 7.56562 7.41842 7.14691 - 5.78080 4.78917 2.69889 2.12189 1.51083 1.35106 - 10.71097 10.18519 9.70879 9.27120 8.87260 8.51339 - 8.19323 7.91203 7.67002 7.46724 7.30377 7.17951 - 7.09348 7.04568 7.03817 7.06910 7.13689 7.24235 - 7.38094 7.45918 7.54081 7.59247 7.48259 7.25373 - 6.01933 5.08099 2.94657 2.30370 1.54858 1.35103 - 0.51077 0.53333 0.55750 0.58332 0.61061 0.63914 - 0.66890 0.69992 0.73228 0.76615 0.80194 0.83995 - 0.88016 0.92219 0.96489 1.00567 1.04149 1.07140 - 1.09490 1.10426 1.11272 1.11884 1.12502 1.12651 - 1.12769 1.12784 1.12795 1.12797 1.12798 1.12766 - 0.73155 0.76561 0.80070 0.83701 0.87453 0.91328 - 0.95327 0.99452 1.03715 1.08119 1.12673 1.17400 - 1.22351 1.27530 1.32773 1.37702 1.41905 1.45373 - 1.48078 1.49103 1.50148 1.51032 1.51802 1.51986 - 1.52148 1.52162 1.52173 1.52183 1.52185 1.51324 - 0.94563 0.98935 1.03383 1.07928 1.12565 1.17287 - 1.22094 1.26995 1.32008 1.37140 1.42387 1.47771 - 1.53342 1.59102 1.64871 1.70251 1.74827 1.78623 - 1.81656 1.82856 1.84105 1.85175 1.86120 1.86346 - 1.86545 1.86564 1.86579 1.86589 1.86591 1.85767 - 1.34636 1.40633 1.46605 1.52582 1.58543 1.64477 - 1.70383 1.76292 1.82249 1.88259 1.94308 2.00393 - 2.06548 2.12758 2.18856 2.24523 2.29442 2.33671 - 2.37258 2.38791 2.40392 2.41754 2.43011 2.43318 - 2.43579 2.43610 2.43635 2.43639 2.43641 2.43647 - 1.71005 1.78289 1.85390 1.92353 1.99159 2.05805 - 2.12302 2.18698 2.25079 2.31455 2.37815 2.44132 - 2.50370 2.56473 2.62342 2.67865 2.72909 2.77380 - 2.81315 2.83181 2.85063 2.86574 2.88101 2.88475 - 2.88779 2.88833 2.88861 2.88846 2.88858 2.89690 - 2.03865 2.12310 2.20295 2.27905 2.35173 2.42164 - 2.48906 2.55469 2.61962 2.68383 2.74701 2.80868 - 2.86858 2.92639 2.98154 3.03399 3.08355 3.12936 - 3.17148 3.19192 3.21264 3.22937 3.24642 3.25059 - 3.25403 3.25469 3.25500 3.25473 3.25493 3.26900 - 2.33679 2.43091 2.51741 2.59763 2.67249 2.74337 - 2.81082 2.87569 2.93930 3.00162 3.06225 3.12060 - 3.17655 3.23003 3.28086 3.32984 3.37766 3.42358 - 3.46735 3.48899 3.51100 3.52882 3.54709 3.55159 - 3.55529 3.55604 3.55636 3.55604 3.55626 3.57314 - 2.85506 2.96395 3.05902 3.14254 3.21678 3.28479 - 3.34753 3.40622 3.46262 3.51683 3.56862 3.61757 - 3.66385 3.70776 3.74972 3.79144 3.83454 3.87858 - 3.92307 3.94569 3.96885 3.98767 4.00713 4.01199 - 4.01595 4.01670 4.01705 4.01677 4.01697 4.03153 - 3.29124 3.41045 3.50962 3.59213 3.66164 3.72291 - 3.77735 3.82646 3.87245 3.91570 3.95642 3.99465 - 4.03075 4.06534 4.09907 4.13387 4.17161 4.21216 - 4.25503 4.27733 4.30031 4.31907 4.33855 4.34349 - 4.34745 4.34807 4.34845 4.34837 4.34847 4.35481 - 4.14341 4.27655 4.37528 4.44571 4.49505 4.53208 - 4.55955 4.58010 4.59730 4.61208 4.62516 4.63730 - 4.64969 4.66372 4.68003 4.69959 4.72346 4.75241 - 4.78649 4.80503 4.82453 4.84075 4.85765 4.86197 - 4.86551 4.86582 4.86609 4.86634 4.86635 4.85088 - 4.78903 4.90379 4.99107 5.05367 5.09187 5.10758 - 5.10502 5.09148 5.07614 5.06166 5.04905 5.03946 - 5.03439 5.03501 5.04066 5.04856 5.05689 5.06981 - 5.09264 5.10770 5.12224 5.13288 5.14596 5.14937 - 5.15200 5.15215 5.15230 5.15257 5.15266 5.12523 - 5.71793 5.81248 5.86989 5.89520 5.88986 5.85748 - 5.80458 5.74146 5.68022 5.62465 5.57564 5.53398 - 5.50070 5.47594 5.45841 5.44359 5.42821 5.41717 - 5.41690 5.42077 5.42381 5.42510 5.42908 5.43017 - 5.43093 5.43086 5.43082 5.43108 5.43117 5.40227 - 6.39958 6.46457 6.48666 6.47312 6.42648 6.35168 - 6.25682 6.15403 6.05718 5.97031 5.89415 5.82857 - 5.77374 5.72854 5.69134 5.65703 5.62187 5.59088 - 5.57070 5.56462 5.55744 5.55046 5.54638 5.54547 - 5.54457 5.54434 5.54417 5.54434 5.54440 5.52413 - 6.92175 7.00903 7.00021 6.92261 6.80666 6.68348 - 6.56022 6.44010 6.32676 6.22168 6.12573 6.03873 - 5.96118 5.89265 5.83283 5.77978 5.73175 5.68914 - 5.65178 5.63462 5.61839 5.60645 5.59504 5.59229 - 5.59017 5.58981 5.58957 5.58967 5.58963 5.58006 - 7.38034 7.44001 7.39484 7.27711 7.12184 6.96400 - 6.81095 6.66501 6.52905 6.40390 6.28930 6.18445 - 6.08981 6.00515 5.92993 5.86191 5.79919 5.74245 - 5.69137 5.66715 5.64370 5.62601 5.60895 5.60489 - 5.60164 5.60122 5.60091 5.60085 5.60081 5.60140 - 8.30609 8.11328 7.91523 7.72218 7.53399 7.35084 - 7.17293 7.00034 6.83368 6.67411 6.52202 6.37783 - 6.24280 6.11862 6.00638 5.90790 5.82419 5.75199 - 5.69043 5.66694 5.65029 5.63553 5.57244 5.54250 - 5.55623 5.56271 5.55951 5.55721 5.56052 5.57346 - 8.68590 8.61950 8.43570 8.18008 7.89821 7.63242 - 7.38891 7.16683 6.96513 6.78186 6.61236 6.45349 - 6.30603 6.17119 6.04785 5.93338 5.82590 5.72695 - 5.63582 5.59124 5.54721 5.51318 5.48002 5.47211 - 5.46568 5.46501 5.46447 5.46410 5.46406 5.48468 - 9.77932 9.38380 8.99885 8.63577 8.29357 7.97141 - 7.66873 7.38559 7.12221 6.87827 6.65284 6.44454 - 6.25161 6.07356 5.91158 5.76565 5.63397 5.50589 - 5.37182 5.30525 5.24473 5.20272 5.15770 5.14591 - 5.13694 5.13608 5.13519 5.13484 5.13492 5.14547 - 10.34975 9.83196 9.34039 8.88418 8.46092 8.06896 - 7.70687 7.37369 7.06898 6.79100 6.53737 6.30502 - 6.08956 5.88817 5.70216 5.53111 5.37291 5.21774 - 5.05788 4.97998 4.91068 4.86358 4.81025 4.79506 - 4.78475 4.78373 4.78258 4.78247 4.78235 4.77595 - 10.98231 10.29343 9.65721 9.07588 8.54398 8.05853 - 7.61739 7.21740 6.85605 6.53019 6.23571 5.96768 - 5.71915 5.48531 5.26660 5.06351 4.87288 4.68534 - 4.49453 4.40239 4.32060 4.26476 4.20053 4.18189 - 4.16947 4.16831 4.16694 4.16681 4.16658 4.15923 - 11.27463 10.52431 9.80383 9.12782 8.51095 7.96452 - 7.48271 7.05428 6.66804 6.31675 5.99323 5.69228 - 5.41202 5.15096 4.90788 4.68013 4.46475 4.26011 - 4.06548 3.97170 3.87959 3.80801 3.73689 3.71913 - 3.70502 3.70323 3.70188 3.70167 3.70156 3.70270 - 11.51375 10.61897 9.82496 9.11401 8.47662 7.90434 - 7.39089 6.92828 6.50863 6.12724 5.78015 5.46280 - 5.16928 4.89502 4.63855 4.39720 4.16889 3.95145 - 3.74494 3.64584 3.54667 3.46776 3.39120 3.37286 - 3.35825 3.35648 3.35483 3.35455 3.35446 3.35721 - 11.64537 10.68727 9.84749 9.09874 8.43095 7.83419 - 7.30009 6.81927 6.38272 5.98533 5.62315 5.29176 - 4.98559 4.70019 4.43378 4.18320 3.94602 3.71994 - 3.50378 3.39924 3.29426 3.21043 3.12909 3.10988 - 3.09469 3.09279 3.09097 3.09070 3.09061 3.09211 - 11.78806 10.74828 9.85249 9.05712 8.35174 7.72503 - 7.16562 6.66247 6.20556 5.78943 5.40990 5.06244 - 4.74144 4.44241 4.16299 3.89938 3.64830 3.40787 - 3.17551 3.06203 2.94825 2.85737 2.76741 2.74528 - 2.72781 2.72572 2.72380 2.72353 2.72341 2.72286 - 11.84936 10.76252 9.83686 9.01687 8.29184 7.64934 - 7.07666 6.56205 6.09515 5.67030 5.28299 4.92828 - 4.60018 4.29377 4.00636 3.73369 3.47191 3.21887 - 2.97210 2.85060 2.72910 2.63215 2.53379 2.50813 - 2.48779 2.48552 2.48362 2.48331 2.48313 2.48249 - 11.86288 10.73243 9.78576 8.94804 8.20975 7.55415 - 6.96943 6.44413 5.96847 5.53650 5.14322 4.78307 - 4.44926 4.13618 3.84040 3.55647 3.27899 3.00326 - 2.72487 2.58274 2.43671 2.31708 2.19652 2.16550 - 2.14035 2.13744 2.13511 2.13475 2.13446 2.13419 - 11.80754 10.67908 9.74383 8.91463 8.18262 7.52912 - 6.94412 6.41757 5.94092 5.50839 5.11488 4.75473 - 4.42110 4.10805 3.81145 3.52461 3.24016 2.94981 - 2.64364 2.48060 2.30574 2.15729 2.01342 1.98025 - 1.95322 1.94965 1.94638 1.94598 1.94571 1.94666 - 11.65955 10.56959 9.67978 8.88716 8.17968 7.54211 - 6.96755 6.44926 5.98145 5.55826 5.17361 4.82056 - 4.49029 4.17600 3.87495 3.58304 3.29208 2.98356 - 2.63478 2.43793 2.21896 2.02345 1.82063 1.77657 - 1.75493 1.75261 1.74588 1.74443 1.74584 1.75589 - 11.54436 10.48691 9.63906 8.88291 8.20230 7.58498 - 7.02501 6.51661 6.05482 5.63517 5.25326 4.90421 - 4.58201 4.28064 3.99408 3.71188 3.41955 3.09445 - 2.70596 2.47552 2.20956 1.96721 1.72396 1.67712 - 1.65377 1.65062 1.64222 1.64052 1.64278 1.66111 - 11.44739 10.41949 9.60908 8.88395 8.22698 7.62827 - 7.08315 6.58690 6.13557 5.72512 5.35138 5.00962 - 4.69399 4.39844 4.11664 3.83739 3.54437 3.21048 - 2.79713 2.54335 2.24110 1.95966 1.67088 1.61528 - 1.59396 1.59153 1.58109 1.57882 1.58240 1.60338 - 11.37005 10.36582 9.58735 8.88800 8.25176 7.67001 - 7.13894 6.65460 6.21374 5.81257 5.44711 5.11271 - 4.80351 4.51341 4.23598 3.95964 3.66685 3.32722 - 2.89527 2.62259 2.28938 1.97275 1.64105 1.57610 - 1.55552 1.55371 1.54154 1.53881 1.54353 1.56442 - 11.25527 10.28695 9.55911 8.90013 8.29795 7.74502 - 7.23867 6.77585 6.35415 5.97021 5.62023 5.29969 - 5.00263 4.72287 4.45395 4.18400 3.89379 3.54786 - 3.08924 2.78717 2.40373 2.02863 1.62352 1.53720 - 1.50544 1.50466 1.49535 1.49324 1.50012 1.51542 - 11.17467 10.23356 9.54331 8.91471 8.33878 7.80868 - 7.32239 6.87751 6.47218 6.10325 5.76702 5.45896 - 5.17290 4.90247 4.64134 4.37767 4.09153 3.74465 - 3.27132 2.94886 2.52627 2.10106 1.62821 1.52299 - 1.48014 1.47887 1.46920 1.46696 1.47362 1.48591 - 11.10048 10.17740 9.52782 8.93920 8.40359 7.91402 - 7.46754 7.06070 6.69048 6.35354 6.04609 5.76300 - 5.49697 5.24139 4.99211 4.74146 4.47239 4.14396 - 3.67175 3.32173 2.82329 2.29642 1.68301 1.52402 - 1.46153 1.45409 1.43393 1.43464 1.43039 1.44602 - 11.04148 10.14517 9.52966 8.97124 8.46271 7.99810 - 7.57480 7.18971 6.84011 6.52296 6.23464 5.97015 - 5.72208 5.48374 5.25103 5.01615 4.76153 4.44398 - 3.97224 3.61227 3.08636 2.50690 1.76777 1.55685 - 1.45257 1.44120 1.41859 1.41803 1.41425 1.42589 - 10.94238 10.10476 9.54743 9.03441 8.56138 8.12523 - 7.72552 7.36181 7.03397 6.73983 6.47615 6.23838 - 6.01936 5.81205 5.61072 5.40387 5.17151 4.87437 - 4.42066 4.06214 3.51679 2.87074 1.94803 1.66914 - 1.44770 1.42314 1.40661 1.40400 1.40045 1.40584 - 10.92400 10.10116 9.56421 9.06972 8.61419 8.19501 - 7.81189 7.46461 7.15319 6.87574 6.62927 6.40947 - 6.20933 6.02195 5.84171 5.65696 5.44810 5.17777 - 4.75371 4.40693 3.86021 3.17880 2.11953 1.77062 - 1.46229 1.42335 1.39909 1.39611 1.38926 1.39570 - 10.92320 10.10592 9.57837 9.09380 8.64889 8.24102 - 7.86947 7.53366 7.23323 6.96664 6.73165 6.52495 - 6.34094 6.17323 6.01448 5.84867 5.65300 5.39335 - 4.98797 4.66353 4.15603 3.48178 2.27720 1.85240 - 1.48066 1.43169 1.39455 1.38879 1.38628 1.38959 - 10.91979 10.11002 9.59026 9.11334 8.67611 8.27609 - 7.91253 7.58474 7.29226 7.03374 6.80729 6.60996 - 6.43670 6.28166 6.13797 5.99004 5.81486 5.57641 - 5.19182 4.87918 4.38562 3.71400 2.43626 1.94573 - 1.49654 1.43654 1.39283 1.38546 1.38281 1.38553 - 10.91282 10.11706 9.60800 9.14106 8.71343 8.32314 - 7.96964 7.65247 7.37139 7.12523 6.91215 6.72928 - 6.57146 6.43321 6.30909 6.18604 6.04340 5.84543 - 5.50942 5.22396 4.75547 4.08534 2.70974 2.13259 - 1.53439 1.44663 1.38981 1.38498 1.37568 1.38047 - 10.92865 10.13029 9.61956 9.15428 8.73112 8.34759 - 8.00238 7.69412 7.42156 7.18346 6.97818 6.80302 - 6.65303 6.52405 6.41458 6.31899 6.21889 6.05843 - 5.73810 5.46328 5.03021 4.39731 2.95647 2.29540 - 1.56975 1.46234 1.39049 1.38207 1.37489 1.37740 - 10.90552 10.13161 9.63472 9.18109 8.76795 8.39339 - 8.05629 7.75566 7.49069 7.26095 7.06599 6.90481 - 6.77506 6.67397 6.59746 6.53317 6.46142 6.34815 - 6.11422 5.89423 5.51888 4.93756 3.46210 2.65099 - 1.66303 1.51004 1.39439 1.38303 1.36683 1.37330 - 10.88741 10.13543 9.64464 9.19566 8.78626 8.41504 - 8.08129 7.78454 7.52466 7.30133 7.11406 6.96173 - 6.84183 6.75184 6.68952 6.64585 6.60436 6.53120 - 6.35306 6.17046 5.83492 5.29708 3.85203 2.96553 - 1.75352 1.55315 1.40166 1.38534 1.36849 1.37127 - 10.84789 10.13999 9.65405 9.20899 8.80320 8.43583 - 8.10635 7.81464 7.56084 7.34465 7.16560 7.02271 - 6.91375 6.83685 6.79086 6.76837 6.75733 6.73546 - 6.63924 6.50805 6.23356 5.76637 4.42051 3.45822 - 1.93104 1.65647 1.41833 1.39289 1.36495 1.36923 - 10.81426 10.14141 9.65801 9.21546 8.81207 8.44686 - 8.11965 7.83070 7.58051 7.36852 7.19359 7.05460 - 6.95021 6.87961 6.84312 6.83584 6.84726 6.85151 - 6.78669 6.68729 6.48715 6.12277 4.81782 3.77780 - 2.11500 1.78049 1.43385 1.38570 1.36909 1.36821 - 10.78899 10.14247 9.66093 9.21972 8.81750 8.45361 - 8.12788 7.84064 7.59246 7.38277 7.21045 7.07445 - 6.97351 6.90707 6.87595 6.87619 6.89924 6.92335 - 6.89303 6.81889 6.65278 6.33577 5.12887 4.08423 - 2.26865 1.87779 1.45476 1.39326 1.37261 1.36761 - 10.77088 10.14198 9.66203 9.22259 8.82218 8.45999 - 8.13563 7.84919 7.60097 7.39112 7.21962 7.08613 - 6.98908 6.92735 6.90098 6.90432 6.92955 6.96586 - 6.97743 6.93417 6.77719 6.44243 5.34453 4.42000 - 2.41016 1.94504 1.47594 1.41842 1.36735 1.36720 - 10.74950 10.14431 9.66550 9.22613 8.82569 8.46412 - 8.14121 7.85703 7.61185 7.40526 7.23638 7.10455 - 7.00920 6.95026 6.92839 6.93915 6.97657 7.03301 - 7.07208 7.04844 6.93929 6.69563 5.72879 4.76650 - 2.68143 2.14206 1.52031 1.42201 1.37849 1.36669 - 10.73524 10.14497 9.66724 9.22855 8.82876 8.46808 - 8.14613 7.86277 7.61812 7.41208 7.24451 7.11497 - 7.02221 6.96567 6.94647 6.96109 7.00438 7.06817 - 7.12895 7.13319 7.06156 6.83904 5.93992 5.11198 - 2.93381 2.29209 1.56039 1.45093 1.37354 1.36639 - 10.71470 10.14577 9.66899 9.23116 8.83240 8.47303 - 8.15259 7.87069 7.62723 7.42232 7.25617 7.12863 - 7.03844 6.98513 6.97016 6.99071 7.04287 7.12137 - 7.20856 7.23858 7.22257 7.08368 6.34410 5.62544 - 3.44661 2.65399 1.66091 1.49799 1.38437 1.36599 - 10.70299 10.14607 9.66984 9.23259 8.83437 8.47552 - 8.15558 7.87422 7.63143 7.42731 7.26209 7.13564 - 7.04675 6.99511 6.98238 7.00597 7.06277 7.14928 - 7.25047 7.29346 7.30694 7.21813 6.59514 5.96182 - 3.84764 2.95977 1.75760 1.54680 1.39589 1.36579 - 10.69062 10.14626 9.67065 9.23406 8.83644 8.47795 - 8.15827 7.87729 7.63523 7.43214 7.26803 7.14272 - 7.05515 7.00521 6.99471 7.02141 7.08294 7.17785 - 7.29393 7.35003 7.39217 7.35888 6.89841 6.38665 - 4.44173 3.44840 1.93845 1.64530 1.41905 1.36558 - 10.68476 10.14640 9.67084 9.23441 8.83704 8.47884 - 8.15956 7.87914 7.63783 7.43540 7.27135 7.14557 - 7.05822 7.00997 7.00197 7.03019 7.09127 7.18764 - 7.32022 7.39222 7.43526 7.39133 7.07705 6.75268 - 4.82242 3.76849 2.11115 1.76528 1.44219 1.36548 - 10.69913 10.15266 9.67019 9.23082 8.83304 8.47565 - 8.15780 7.87896 7.63882 7.43728 7.27424 7.14902 - 7.05945 7.00556 6.99279 7.02702 7.10969 7.22084 - 7.33535 7.39403 7.45351 7.47071 7.20325 6.82265 - 5.17086 4.13653 2.27223 1.83957 1.46174 1.36542 - 10.69611 10.15273 9.67042 9.23118 8.83351 8.47623 - 8.15851 7.87977 7.63975 7.43836 7.27548 7.15045 - 7.06114 7.00760 6.99531 7.03020 7.11384 7.22645 - 7.34390 7.40573 7.47188 7.50205 7.28412 6.95205 - 5.41454 4.38808 2.42515 1.93687 1.48248 1.36538 - 10.67362 10.14680 9.67179 9.23574 8.83871 8.48094 - 8.16208 7.88197 7.64077 7.43860 7.27559 7.15164 - 7.06577 7.01798 7.01031 7.04089 7.10816 7.21267 - 7.34997 7.42656 7.50140 7.54080 7.39357 7.12282 - 5.76533 4.77979 2.70189 2.12842 1.52302 1.36533 - 10.67125 10.14628 9.67131 9.23551 8.83875 8.48111 - 8.16234 7.88251 7.64188 7.44023 7.27709 7.15229 - 7.06597 7.01891 7.01275 7.04444 7.11139 7.21517 - 7.35672 7.44006 7.52054 7.55357 7.43694 7.28089 - 6.00494 5.02659 2.94364 2.33238 1.55333 1.36529 - 0.50326 0.52576 0.54980 0.57544 0.60254 0.63089 - 0.66048 0.69130 0.72338 0.75686 0.79206 0.82924 - 0.86835 0.90905 0.95037 0.99019 1.02595 1.05653 - 1.08085 1.09044 1.09921 1.10579 1.11278 1.11451 - 1.11589 1.11607 1.11621 1.11623 1.11624 1.11602 - 0.72202 0.75588 0.79076 0.82685 0.86415 0.90263 - 0.94231 0.98319 1.02535 1.06880 1.11360 1.15995 - 1.20831 1.25876 1.30984 1.35826 1.40042 1.43605 - 1.46458 1.47575 1.48705 1.49652 1.50520 1.50732 - 1.50914 1.50931 1.50944 1.50955 1.50957 1.50031 - 0.93419 0.97765 1.02187 1.06704 1.11309 1.15998 - 1.20767 1.25624 1.30583 1.35650 1.40821 1.46112 - 1.51575 1.57212 1.62863 1.68174 1.72777 1.76688 - 1.79906 1.81224 1.82584 1.83737 1.84785 1.85038 - 1.85258 1.85279 1.85296 1.85307 1.85310 1.84412 - 1.33157 1.39116 1.45051 1.50990 1.56913 1.62807 - 1.68672 1.74533 1.80438 1.86390 1.92373 1.98385 - 2.04458 2.10585 2.16611 2.22249 2.27215 2.31569 - 2.35360 2.37023 2.38755 2.40215 2.41572 2.41905 - 2.42184 2.42218 2.42245 2.42249 2.42251 2.42230 - 1.69250 1.76480 1.83536 1.90458 1.97227 2.03836 - 2.10294 2.16652 2.22992 2.29322 2.35637 2.41907 - 2.48099 2.54161 2.60001 2.65527 2.70629 2.75221 - 2.79345 2.81330 2.83338 2.84950 2.86566 2.86960 - 2.87281 2.87337 2.87367 2.87351 2.87364 2.88221 - 2.01875 2.10261 2.18196 2.25764 2.32997 2.39955 - 2.46669 2.53206 2.59671 2.66067 2.72362 2.78511 - 2.84488 2.90263 2.95786 3.01060 3.06079 3.10768 - 3.15141 3.17290 3.19476 3.21239 3.23019 3.23453 - 3.23810 3.23880 3.23912 3.23884 3.23903 3.25373 - 2.31490 2.40841 2.49442 2.57423 2.64876 2.71941 - 2.78668 2.85143 2.91494 2.97721 3.03784 3.09625 - 3.15236 3.20608 3.25727 3.30674 3.35520 3.40203 - 3.44714 3.46964 3.49261 3.51121 3.53012 3.53474 - 3.53857 3.53934 3.53968 3.53932 3.53957 3.55727 - 2.83010 2.93848 3.03311 3.11630 3.19033 3.25827 - 3.32109 3.37995 3.43659 3.49111 3.54327 3.59267 - 3.63950 3.68407 3.72674 3.76914 3.81287 3.85756 - 3.90289 3.92608 3.94987 3.96922 3.98907 3.99400 - 3.99804 3.99880 3.99917 3.99888 3.99909 4.01429 - 3.26411 3.38297 3.48186 3.56414 3.63357 3.69496 - 3.74970 3.79925 3.84576 3.88960 3.93097 3.96994 - 4.00685 4.04231 4.07692 4.11248 4.15078 4.19176 - 4.23513 4.25778 4.28115 4.30022 4.31991 4.32489 - 4.32888 4.32950 4.32989 4.32980 4.32992 4.33638 - 4.11323 4.24664 4.34552 4.41605 4.46564 4.50322 - 4.53153 4.55305 4.57121 4.58692 4.60100 4.61427 - 4.62781 4.64292 4.66018 4.68042 4.70464 4.73377 - 4.76802 4.78662 4.80615 4.82236 4.83922 4.84353 - 4.84706 4.84736 4.84762 4.84789 4.84791 4.83140 - 4.75806 4.87319 4.96101 5.02430 5.06330 5.07996 - 5.07841 5.06596 5.05179 5.03852 5.02714 5.01877 - 5.01486 5.01652 5.02303 5.03153 5.04014 5.05318 - 5.07615 5.09127 5.10577 5.11632 5.12931 5.13271 - 5.13533 5.13546 5.13560 5.13588 5.13599 5.10731 - 5.68743 5.78319 5.84192 5.86857 5.86460 5.83360 - 5.78204 5.72023 5.66033 5.60605 5.55831 5.51786 - 5.48565 5.46181 5.44498 5.43064 5.41552 5.40471 - 5.40490 5.40904 5.41224 5.41356 5.41763 5.41876 - 5.41953 5.41946 5.41942 5.41969 5.41977 5.39067 - 6.37034 6.43723 6.46127 6.44958 6.40470 6.33154 - 6.23821 6.13684 6.04137 5.95584 5.88093 5.81652 - 5.76272 5.71838 5.68182 5.64795 5.61303 5.58236 - 5.56289 5.55729 5.55051 5.54376 5.53998 5.53915 - 5.53832 5.53811 5.53794 5.53810 5.53817 5.51858 - 6.89373 6.98352 6.97712 6.90171 6.78777 6.66643 - 6.54490 6.42633 6.31438 6.21060 6.11595 6.03028 - 5.95388 5.88619 5.82692 5.77421 5.72645 5.68429 - 5.64773 5.63106 5.61536 5.60389 5.59296 5.59033 - 5.58831 5.58797 5.58773 5.58782 5.58780 5.57917 - 7.35352 7.41578 7.37341 7.25835 7.10546 6.94963 - 6.79827 6.65386 6.51945 6.39582 6.28268 6.17917 - 6.08568 6.00192 5.92735 5.85975 5.79729 5.74091 - 5.69058 5.66687 5.64406 5.62694 5.61049 5.60658 - 5.60347 5.60307 5.60277 5.60272 5.60269 5.60396 - 8.28154 8.09164 7.89644 7.70613 7.52050 7.33976 - 7.16413 6.99366 6.82897 6.67118 6.52073 6.37798 - 6.24420 6.12107 6.00965 5.91175 5.82840 5.75647 - 5.69526 5.67200 5.65571 5.64151 5.57992 5.55058 - 5.56409 5.57047 5.56736 5.56511 5.56837 5.58121 - 8.66326 8.59948 8.41933 8.16762 7.88915 7.62570 - 7.38381 7.16319 6.96341 6.78232 6.61471 6.45724 - 6.31100 6.17746 6.05541 5.94184 5.83467 5.73584 - 5.64517 5.60111 5.55779 5.52449 5.49215 5.48449 - 5.47824 5.47758 5.47708 5.47672 5.47668 5.49661 - 9.76163 9.37010 8.98887 8.62912 8.28991 7.97044 - 7.67014 7.38913 7.12764 6.88535 6.66141 6.45450 - 6.26288 6.08617 5.92555 5.78098 5.65062 5.52365 - 5.39031 5.32404 5.26401 5.22265 5.17845 5.16689 - 5.15807 5.15723 5.15637 5.15604 5.15612 5.16612 - 10.33708 9.82357 9.33577 8.88287 8.46246 8.07297 - 7.71303 7.38167 7.07855 6.80194 6.54954 6.31839 - 6.10417 5.90423 5.71983 5.55060 5.39436 5.24102 - 5.08254 5.00512 4.93625 4.88954 4.83684 4.82190 - 4.81170 4.81070 4.80956 4.80944 4.80933 4.80324 - 10.97675 10.29210 9.65945 9.08115 8.55179 8.06849 - 7.62913 7.23063 6.87054 6.54578 6.25234 5.98541 - 5.73818 5.50593 5.28915 5.08835 4.90030 4.71535 - 4.52673 4.43540 4.35415 4.29852 4.23475 4.21634 - 4.20397 4.20280 4.20145 4.20131 4.20108 4.19398 - 11.28051 10.51565 9.80018 9.13783 8.53169 7.98517 - 7.49699 7.06321 6.67915 6.33455 6.01534 5.71385 - 5.43310 5.17441 4.93393 4.70843 4.49558 4.29346 - 4.10077 4.00781 3.91691 3.84520 3.77443 3.75693 - 3.74301 3.74112 3.73978 3.73963 3.73944 3.74038 - 11.51349 10.62180 9.83056 9.12215 8.48710 7.91697 - 7.40550 6.94467 6.52664 6.14674 5.80108 5.48520 - 5.19327 4.92082 4.66633 4.42711 4.20099 3.98569 - 3.78110 3.68283 3.58430 3.50576 3.42962 3.41141 - 3.39686 3.39510 3.39346 3.39319 3.39308 3.39563 - 11.64410 10.68930 9.85248 9.10635 8.44099 7.84646 - 7.31444 6.83556 6.40083 6.00518 5.64470 5.31501 - 5.01055 4.72694 4.46236 4.21364 3.97829 3.75394 - 3.53934 3.43549 3.33110 3.24766 3.16674 3.14765 - 3.13251 3.13063 3.12882 3.12856 3.12847 3.12990 - 11.78343 10.74785 9.85531 9.06279 8.35991 7.73545 - 7.17811 6.67694 6.22198 5.80778 5.43018 5.08463 - 4.76549 4.46821 4.19046 3.92841 3.67869 3.43942 - 3.20801 3.09496 2.98161 2.89109 2.80144 2.77937 - 2.76196 2.75988 2.75796 2.75769 2.75757 2.75715 - 11.84083 10.75917 9.83720 9.02025 8.29774 7.65738 - 7.08660 6.57378 6.10871 5.68570 5.30028 4.94746 - 4.62122 4.31660 4.03088 3.75971 3.49916 3.24705 - 3.00088 2.87962 2.75841 2.66174 2.56356 2.53791 - 2.51760 2.51534 2.51343 2.51312 2.51295 2.51242 - 11.84699 10.72257 9.78010 8.94562 8.20979 7.55617 - 6.97309 6.44925 5.97509 5.54467 5.15301 4.79453 - 4.46252 4.15129 3.85737 3.57518 3.29916 3.02447 - 2.74660 2.60456 2.45862 2.33911 2.21868 2.18769 - 2.16256 2.15966 2.15732 2.15697 2.15668 2.15640 - 11.78727 10.66449 9.73302 8.90692 8.17735 7.52585 - 6.94257 6.41754 5.94234 5.51122 5.11913 4.76050 - 4.42854 4.11734 3.82272 3.53789 3.25530 2.96646 - 2.66119 2.49833 2.32352 2.17509 2.03156 1.99857 - 1.97161 1.96803 1.96479 1.96440 1.96411 1.96503 - 11.63349 10.54866 9.66209 8.87218 8.16699 7.53140 - 6.95860 6.44190 5.97553 5.55370 5.17042 4.81876 - 4.49005 4.17752 3.87848 3.58878 3.30018 2.99395 - 2.64709 2.45097 2.23245 2.03714 1.83478 1.79103 - 1.76976 1.76748 1.76079 1.75935 1.76075 1.77084 - 11.50961 10.45431 9.60830 8.85482 8.17775 7.56475 - 7.00985 6.50721 6.05169 5.63821 5.26139 4.91498 - 4.59105 4.28311 3.98785 3.69990 3.40827 3.08819 - 2.70785 2.48380 2.22691 1.99146 1.73906 1.68271 - 1.66599 1.66541 1.65601 1.65360 1.65679 1.67471 - 11.41213 10.38277 9.57231 8.84967 8.19718 7.60441 - 7.06613 6.57706 6.13262 5.72819 5.35886 5.01884 - 4.70072 4.39820 4.10750 3.82229 3.52952 3.19959 - 2.79323 2.54655 2.25685 1.98649 1.68717 1.61792 - 1.60494 1.60604 1.59436 1.59114 1.59602 1.61641 - 11.33484 10.32698 9.54751 8.85050 8.21919 7.64418 - 7.12085 6.64433 6.21045 5.81496 5.45328 5.12000 - 4.80803 4.51116 4.22530 3.94339 3.65069 3.31369 - 2.88666 2.62118 2.30336 2.00169 1.65870 1.57674 - 1.56573 1.56820 1.55463 1.55077 1.55708 1.57723 - 11.21118 10.24182 9.51504 8.86035 8.26478 7.71991 - 7.22211 6.76722 6.35179 5.97216 5.62442 5.30379 - 5.00389 4.71876 4.44371 4.17023 3.88018 3.53196 - 3.06818 2.77023 2.40678 2.05747 1.65429 1.54767 - 1.50369 1.50980 1.51607 1.51318 1.50440 1.52818 - 11.12915 10.18744 9.49852 8.87452 8.30550 7.78367 - 7.30596 6.86870 6.46882 6.10311 5.76800 5.45912 - 5.17042 4.89611 4.63120 4.36639 4.08151 3.72984 - 3.24446 2.92349 2.52285 2.12925 1.66317 1.53476 - 1.47687 1.48323 1.49125 1.48790 1.47578 1.49880 - 11.07921 10.15539 9.50350 8.91331 8.37678 7.88693 - 7.44074 7.03466 6.66564 6.33027 6.02466 5.74363 - 5.47970 5.22616 4.97895 4.73049 4.46403 4.13906 - 3.67141 3.32367 2.82677 2.30108 1.69164 1.53464 - 1.47389 1.46664 1.44690 1.44786 1.44325 1.45922 - 11.01853 10.12202 9.50448 8.94468 8.43536 7.97054 - 7.54752 7.16318 6.81471 6.49902 6.21242 5.94983 - 5.70368 5.46718 5.23630 5.00339 4.75109 4.43682 - 3.96966 3.61215 3.08822 2.51051 1.77590 1.56706 - 1.46507 1.45402 1.43182 1.43148 1.42740 1.43931 - 10.91594 10.07859 9.51975 9.00602 8.53297 8.09736 - 7.69861 7.33611 7.00953 6.71665 6.45425 6.21771 - 5.99987 5.79367 5.59355 5.38825 5.15812 4.86399 - 4.41441 4.05848 3.51610 2.87309 1.95539 1.67860 - 1.46015 1.43623 1.42020 1.41764 1.41416 1.41956 - 10.89313 10.07256 9.53542 9.04111 8.58607 8.16768 - 7.78553 7.43930 7.12897 6.85258 6.60714 6.38834 - 6.18914 6.00263 5.82335 5.63985 5.43278 5.16507 - 4.74489 4.40078 3.85733 3.17948 2.12608 1.77958 - 1.47466 1.43647 1.41287 1.40994 1.40311 1.40960 - 10.88923 10.07555 9.54880 9.06509 8.62102 8.21404 - 7.84343 7.50859 7.20914 6.94355 6.70953 6.50372 - 6.32047 6.15336 5.99518 5.83022 5.63602 5.37877 - 4.97727 4.65557 4.15153 3.48094 2.28251 1.86077 - 1.49313 1.44489 1.40834 1.40271 1.40014 1.40361 - 10.88364 10.07831 9.55999 9.08439 8.64834 8.24943 - 7.88687 7.56004 7.26844 7.01076 6.78505 6.58840 - 6.41576 6.26126 6.11812 5.97089 5.79684 5.56037 - 5.17936 4.86944 4.37953 3.71194 2.44084 1.95350 - 1.50884 1.44970 1.40668 1.39939 1.39675 1.39964 - 10.87453 10.08399 9.57704 9.11190 8.68579 8.29680 - 7.94436 7.62812 7.34784 7.10234 6.88982 6.70742 - 6.55000 6.41211 6.28837 6.16582 6.02399 5.82750 - 5.49446 5.21146 4.74662 4.08092 2.71300 2.13943 - 1.54628 1.45953 1.40369 1.39896 1.38977 1.39470 - 10.89002 10.09692 9.58833 9.12489 8.70335 8.32120 - 7.97716 7.66989 7.39813 7.16067 6.95586 6.78104 - 6.63132 6.50257 6.39333 6.29805 6.19844 6.03912 - 5.72130 5.44876 5.01929 4.39108 2.95847 2.30114 - 1.58129 1.47507 1.40436 1.39605 1.38903 1.39171 - 10.86802 10.09891 9.60384 9.15183 8.74012 8.36679 - 8.03076 7.73104 7.46684 7.23771 7.04322 6.88238 - 6.75292 6.65203 6.57568 6.51153 6.43994 6.32708 - 6.09461 5.87639 5.50426 4.92746 3.46113 2.65497 - 1.67367 1.52204 1.40816 1.39710 1.38102 1.38770 - 10.85119 10.10335 9.61403 9.16641 8.75826 8.38820 - 8.05549 7.75968 7.50059 7.27789 7.09113 6.93917 - 6.81952 6.72969 6.66744 6.62379 6.58237 6.50939 - 6.33201 6.15058 5.81777 5.28442 3.84903 2.96749 - 1.76331 1.56463 1.41534 1.39932 1.38277 1.38571 - 10.81213 10.10848 9.62394 9.17984 8.77492 8.40857 - 8.08020 7.78957 7.53663 7.32111 7.14256 7.00001 - 6.89130 6.81454 6.76858 6.74605 6.73494 6.71298 - 6.61690 6.48627 6.21353 5.74995 4.41406 3.45748 - 1.93934 1.66687 1.43170 1.40685 1.37925 1.38370 - 10.77869 10.10950 9.62757 9.18622 8.78388 8.41973 - 8.09353 7.80554 7.55617 7.34487 7.17046 7.03186 - 6.92772 6.85725 6.82078 6.81343 6.82471 6.82874 - 6.76382 6.66470 6.46571 6.10401 4.80839 3.77482 - 2.12230 1.79020 1.44687 1.39943 1.38330 1.38270 - 10.75360 10.11022 9.63019 9.19036 8.78936 8.42658 - 8.10184 7.81550 7.56810 7.35906 7.18727 7.05166 - 6.95100 6.88469 6.85358 6.85377 6.87665 6.90048 - 6.86989 6.79579 6.63046 6.31565 5.11744 4.07918 - 2.27490 1.88684 1.46752 1.40681 1.38683 1.38210 - 10.73549 10.10961 9.63124 9.19322 8.79406 8.43299 - 8.10965 7.82407 7.57662 7.36739 7.19641 7.06332 - 6.96653 6.90495 6.87860 6.88183 6.90687 6.94291 - 6.95418 6.91089 6.75426 6.42117 5.33171 4.41365 - 2.41509 1.95312 1.48853 1.43201 1.38161 1.38170 - 10.71446 10.11184 9.63457 9.19670 8.79759 8.43721 - 8.11529 7.83194 7.58750 7.38153 7.21315 7.08173 - 6.98664 6.92782 6.90595 6.91658 6.95383 7.00996 - 7.04861 7.02478 6.91577 6.67341 5.71340 4.75676 - 2.68482 2.14937 1.53240 1.43508 1.39263 1.38119 - 10.70096 10.11250 9.63603 9.19877 8.80038 8.44091 - 8.12006 7.83780 7.59433 7.38927 7.22193 7.09186 - 6.99865 6.94241 6.92387 6.93866 6.98145 7.04716 - 7.10773 7.10523 7.02801 6.82394 5.96105 5.06875 - 2.92423 2.30836 1.57378 1.45391 1.39829 1.38089 - 10.68016 10.11355 9.63828 9.20181 8.80429 8.44606 - 8.12664 7.84562 7.60291 7.39860 7.23293 7.10574 - 7.01578 6.96260 6.94764 6.96806 7.01998 7.09809 - 7.18485 7.21472 7.19859 7.05988 6.32401 5.61026 - 3.44547 2.65814 1.67163 1.51019 1.39820 1.38049 - 10.66869 10.11381 9.63910 9.20321 8.80624 8.44853 - 8.12959 7.84913 7.60708 7.40357 7.23884 7.11274 - 7.02409 6.97257 6.95982 6.98328 7.03982 7.12595 - 7.22670 7.26950 7.28281 7.19402 6.57341 5.94423 - 3.84430 2.96222 1.76746 1.55834 1.40962 1.38030 - 10.65646 10.11393 9.63986 9.20468 8.80832 8.45095 - 8.13227 7.85215 7.61084 7.40837 7.24477 7.11983 - 7.03250 6.98267 6.97215 6.99871 7.05995 7.15449 - 7.27010 7.32596 7.36789 7.33449 6.87502 6.36626 - 4.43511 3.44804 1.94686 1.65573 1.43257 1.38011 - 10.65057 10.11411 9.64002 9.20500 8.80891 8.45185 - 8.13356 7.85400 7.61343 7.41161 7.24806 7.12265 - 7.03556 6.98742 6.97940 7.00747 7.06828 7.16428 - 7.29633 7.36805 7.41089 7.36696 7.05304 6.73037 - 4.81330 3.76602 2.11838 1.77477 1.45560 1.38001 - 10.66479 10.12028 9.63937 9.20141 8.80489 8.44863 - 8.13180 7.85383 7.61442 7.41352 7.25095 7.12609 - 7.03677 6.98300 6.97023 7.00429 7.08664 7.19735 - 7.31144 7.36990 7.42913 7.44606 7.17875 6.80000 - 5.15974 4.13178 2.27820 1.84830 1.47477 1.37996 - 10.66181 10.12034 9.63959 9.20176 8.80536 8.44923 - 8.13251 7.85463 7.61535 7.41458 7.25218 7.12751 - 7.03845 6.98502 6.97272 7.00747 7.09079 7.20298 - 7.31995 7.38157 7.44754 7.47752 7.25947 6.92879 - 5.40174 4.38162 2.43010 1.94485 1.49522 1.37992 - 10.63956 10.11455 9.64102 9.20632 8.81052 8.45387 - 8.13603 7.85681 7.61638 7.41484 7.25231 7.12871 - 7.04307 6.99538 6.98768 7.01812 7.08509 7.18922 - 7.32609 7.40240 7.47692 7.51609 7.36890 7.09881 - 5.74995 4.77052 2.70498 2.13506 1.53532 1.37987 - 10.63681 10.11420 9.64097 9.20654 8.81094 8.45431 - 8.13638 7.85713 7.61685 7.41555 7.25327 7.12986 - 7.04443 6.99702 6.98972 7.02063 7.08831 7.19396 - 7.33284 7.41072 7.49179 7.54295 7.43284 7.20473 - 5.98466 5.05787 2.94938 2.31452 1.57216 1.37983 - 0.49597 0.51824 0.54216 0.56776 0.59482 0.62306 - 0.65243 0.68295 0.71470 0.74777 0.78241 0.81882 - 0.85691 0.89636 0.93630 0.97501 1.01042 1.04164 - 1.06698 1.07666 1.08562 1.09268 1.10081 1.10288 - 1.10455 1.10478 1.10494 1.10496 1.10498 1.10524 - 0.71258 0.74624 0.78093 0.81683 0.85393 0.89220 - 0.93162 0.97219 1.01392 1.05682 1.10090 1.14632 - 1.19352 1.24256 1.29220 1.33965 1.38184 1.41842 - 1.44859 1.46073 1.47275 1.48266 1.49264 1.49516 - 1.49721 1.49748 1.49771 1.49769 1.49771 1.50148 - 0.92284 0.96603 1.00997 1.05487 1.10067 1.14728 - 1.19468 1.24288 1.29201 1.34209 1.39305 1.44502 - 1.49849 1.55351 1.60867 1.66097 1.70725 1.74761 - 1.78188 1.79629 1.81086 1.82297 1.83476 1.83770 - 1.84011 1.84043 1.84069 1.84069 1.84070 1.84454 - 1.31690 1.37609 1.43509 1.49412 1.55302 1.61162 - 1.66992 1.72815 1.78675 1.84573 1.90491 1.96425 - 2.02405 2.08428 2.14357 2.19952 2.24975 2.29481 - 2.33504 2.35304 2.37150 2.38682 2.40164 2.40532 - 2.40836 2.40873 2.40904 2.40907 2.40910 2.40965 - 1.67457 1.74654 1.81692 1.88607 1.95368 2.01955 - 2.08379 2.14692 2.20980 2.27249 2.33477 2.39639 - 2.45751 2.51800 2.57680 2.63238 2.68340 2.73062 - 2.77459 2.79511 2.81618 2.83354 2.85061 2.85489 - 2.85840 2.85880 2.85913 2.85921 2.85925 2.85598 - 1.99913 2.08234 2.16122 2.23657 2.30864 2.37795 - 2.44479 2.50985 2.57422 2.63791 2.70062 2.76187 - 2.82139 2.87886 2.93390 2.98683 3.03786 3.08623 - 3.13189 3.15434 3.17712 3.19549 3.21427 3.21906 - 3.22279 3.22319 3.22358 3.22377 3.22375 3.21745 - 2.29341 2.38621 2.47174 2.55127 2.62560 2.69604 - 2.76307 2.82759 2.89095 2.95312 3.01373 3.07217 - 3.12831 3.18205 3.23335 3.28322 3.33260 3.38077 - 3.42744 3.45071 3.47446 3.49368 3.51346 3.51855 - 3.52249 3.52289 3.52330 3.52354 3.52351 3.51526 - 2.80583 2.91338 3.00756 3.09060 3.16461 3.23250 - 3.29525 3.35406 3.41080 3.46555 3.51806 3.56790 - 3.61520 3.66022 3.70339 3.74648 3.79117 3.83692 - 3.88318 3.90676 3.93101 3.95079 3.97134 3.97667 - 3.98080 3.98122 3.98165 3.98190 3.98186 3.97300 - 3.23797 3.35591 3.45442 3.53670 3.60632 3.66785 - 3.72269 3.77241 3.81923 3.86357 3.90559 3.94526 - 3.98292 4.01908 4.05441 4.09077 4.13002 4.17184 - 4.21568 4.23844 4.26200 4.28134 4.30160 4.30686 - 4.31096 4.31140 4.31182 4.31203 4.31201 4.30517 - 4.08466 4.21710 4.31583 4.38679 4.43706 4.47525 - 4.50407 4.52615 4.54506 4.56172 4.57690 4.59130 - 4.60591 4.62189 4.63990 4.66095 4.68612 4.71583 - 4.74986 4.76821 4.78760 4.80391 4.82114 4.82554 - 4.82911 4.82958 4.82993 4.82996 4.82999 4.83039 - 4.72840 4.84343 4.93148 4.99524 5.03492 5.05244 - 5.05194 5.04063 5.02762 5.01553 5.00533 4.99809 - 4.99521 4.99777 5.00507 5.01431 5.02362 5.03709 - 5.05991 5.07476 5.08910 5.09971 5.11299 5.11648 - 5.11904 5.11938 5.11970 5.11967 5.11973 5.12518 - 5.65845 5.75455 5.81402 5.84168 5.83897 5.80939 - 5.75939 5.69916 5.64074 5.58783 5.54133 5.50196 - 5.47065 5.44752 5.43125 5.41741 5.40278 5.39243 - 5.39291 5.39718 5.40059 5.40216 5.40644 5.40763 - 5.40832 5.40845 5.40861 5.40851 5.40856 5.41782 - 6.34285 6.41049 6.43569 6.42545 6.38222 6.31085 - 6.21936 6.11979 6.02596 5.94187 5.86820 5.80484 - 5.75185 5.70811 5.67198 5.63844 5.60389 5.57370 - 5.55492 5.54980 5.54360 5.53730 5.53372 5.53293 - 5.53202 5.53198 5.53196 5.53184 5.53186 5.54211 - 6.86787 6.95854 6.95367 6.88017 6.76828 6.64895 - 6.52934 6.41263 6.30241 6.20021 6.10685 6.02219 - 5.94656 5.87950 5.82070 5.76834 5.72085 5.67899 - 5.64324 5.62737 5.61250 5.60155 5.59086 5.58823 - 5.58615 5.58599 5.58584 5.58566 5.58565 5.59626 - 7.32900 7.39258 7.35210 7.23917 7.08847 6.93472 - 6.78534 6.64286 6.51032 6.38843 6.27669 6.17422 - 6.08153 5.99850 5.92451 5.85731 5.79502 5.73880 - 5.68924 5.66643 5.64454 5.62803 5.61185 5.60793 - 5.60478 5.60446 5.60421 5.60402 5.60401 5.61475 - 8.25849 8.07120 7.87870 7.69094 7.50772 7.32928 - 7.15578 6.98731 6.82446 6.66837 6.51944 6.37805 - 6.24545 6.12328 6.01264 5.91528 5.83228 5.76064 - 5.69980 5.67682 5.66096 5.64734 5.58701 5.55807 - 5.57113 5.57730 5.57426 5.57217 5.57533 5.58262 - 8.64333 8.58203 8.40477 8.15584 7.87986 7.61857 - 7.37860 7.15987 6.96213 6.78307 6.61720 6.46104 - 6.31599 6.18369 6.06281 5.95004 5.84306 5.74414 - 5.65397 5.61073 5.56835 5.53573 5.50383 5.49616 - 5.48999 5.48921 5.48862 5.48848 5.48842 5.49339 - 9.74668 9.35830 8.98024 8.62340 8.28683 7.96975 - 7.67162 7.39260 7.13289 6.89223 6.66979 6.46426 - 6.27403 6.09867 5.93939 5.79615 5.66708 5.54119 - 5.40861 5.34270 5.28337 5.24285 5.19924 5.18770 - 5.17911 5.17810 5.17712 5.17710 5.17715 5.16525 - 10.32558 9.81580 9.33164 8.88188 8.46419 8.07708 - 7.71918 7.38957 7.08794 6.81264 6.56143 6.33143 - 6.11848 5.91997 5.73724 5.56989 5.41570 5.26430 - 5.10732 5.03051 4.96232 4.91624 4.86419 4.84944 - 4.83954 4.83840 4.83718 4.83731 4.83719 4.81253 - 10.96943 10.28918 9.66061 9.08568 8.55915 8.07817 - 7.64070 7.24377 6.88497 6.56129 6.26885 6.00294 - 5.75693 5.52623 5.31137 5.11288 4.92752 4.74539 - 4.55933 4.46911 4.38871 4.33358 4.27056 4.25250 - 4.24049 4.23925 4.23786 4.23786 4.23763 4.22134 - 11.27488 10.51509 9.80398 9.14497 8.54155 7.99736 - 7.51110 7.07888 6.69600 6.35236 6.03414 5.73386 - 5.45477 5.19823 4.95997 4.73667 4.52615 4.32664 - 4.13668 4.04489 3.95496 3.88393 3.81385 3.79658 - 3.78285 3.78095 3.77962 3.77949 3.77929 3.77887 - 11.50896 10.62183 9.83465 9.12957 8.49728 7.92952 - 7.42005 6.96100 6.54459 6.16622 5.82207 5.50773 - 5.21745 4.94677 4.69424 4.45710 4.23317 4.02013 - 3.81779 3.72060 3.62300 3.54506 3.46953 3.45133 - 3.43668 3.43496 3.43336 3.43299 3.43293 3.44021 - 11.63979 10.68924 9.85612 9.11324 8.45067 7.85861 - 7.32876 6.85189 6.41904 6.02518 5.66646 5.33852 - 5.03581 4.75397 4.49121 4.24433 4.01084 3.78832 - 3.57550 3.47249 3.36887 3.28597 3.20555 3.18627 - 3.17084 3.16903 3.16728 3.16685 3.16682 3.17636 - 11.77809 10.74635 9.85735 9.06790 8.36774 7.74573 - 7.19063 6.69158 6.23865 5.82645 5.45080 5.10713 - 4.78980 4.49424 4.21814 3.95760 3.70933 3.47135 - 3.24112 3.12859 3.01569 2.92547 2.83591 2.81364 - 2.79606 2.79405 2.79215 2.79172 2.79167 2.79858 - 11.83371 10.75595 9.83738 9.02335 8.30339 7.66528 - 7.09654 6.58567 6.12249 5.70136 5.31777 4.96679 - 4.64232 4.33938 4.05525 3.78555 3.52633 3.27538 - 3.03019 2.90932 2.78835 2.69167 2.59322 2.56762 - 2.54753 2.54532 2.54337 2.54300 2.54286 2.54468 - 11.83555 10.71505 9.77551 8.94352 8.20981 7.55801 - 6.97657 6.45430 5.98168 5.55282 5.16275 4.80592 - 4.47561 4.16616 3.87400 3.59352 3.31902 3.04561 - 2.76861 2.62682 2.48096 2.36133 2.24080 2.21005 - 2.18525 2.18234 2.17997 2.17966 2.17937 2.17634 - 11.77287 10.65305 9.72399 8.89996 8.17220 7.52238 - 6.94065 6.41712 5.94338 5.51375 5.12319 4.76618 - 4.43602 4.12679 3.83428 3.55150 3.27074 2.98330 - 2.67878 2.51610 2.34150 2.19350 2.05096 2.01781 - 1.99030 1.98667 1.98353 1.98318 1.98284 1.98345 - 11.61422 10.53131 9.64617 8.85762 8.15382 7.51972 - 6.94850 6.43347 5.96882 5.54880 5.16739 4.81766 - 4.49094 4.18040 3.88337 3.59572 3.30915 3.00477 - 2.65945 2.46408 2.24657 2.05250 1.85234 1.80883 - 1.78466 1.78187 1.77564 1.77434 1.77535 1.78730 - 11.48705 10.43322 9.58787 8.83529 8.15933 7.54771 - 6.99437 6.49345 6.03983 5.62837 5.25365 4.90942 - 4.58767 4.28188 3.98875 3.70291 3.41339 3.09529 - 2.71692 2.49410 2.23909 2.00601 1.75738 1.70123 - 1.67924 1.67772 1.66916 1.66703 1.66952 1.68887 - 11.38748 10.35897 9.54886 8.82682 8.17525 7.58377 - 7.04707 6.55982 6.11739 5.71513 5.34808 5.01042 - 4.69460 4.39427 4.10569 3.82257 3.53186 3.20397 - 2.79996 2.55502 2.26810 2.00122 1.70703 1.63789 - 1.61750 1.61727 1.60678 1.60396 1.60787 1.62951 - 11.30845 10.30139 9.52191 8.82526 8.19479 7.62102 - 7.09926 6.62462 6.19287 5.79967 5.44041 5.10960 - 4.80000 4.50533 4.22154 3.94161 3.65087 3.31593 - 2.89159 2.62831 2.31413 2.01694 1.68016 1.59818 - 1.57801 1.57886 1.56676 1.56339 1.56851 1.58996 - 11.19180 10.21897 9.48870 8.83194 8.23558 7.69106 - 7.19455 6.74173 6.32895 5.95240 5.60790 5.29037 - 4.99293 4.70940 4.43528 4.16252 3.87406 3.53072 - 3.07688 2.78502 2.42632 2.07676 1.66289 1.55624 - 1.53202 1.53410 1.51961 1.51545 1.52232 1.54092 - 11.10086 10.15893 9.46892 8.84458 8.27593 7.75515 - 7.27900 6.84379 6.44631 6.08325 5.75093 5.44477 - 5.15847 4.88608 4.62263 4.35900 4.07537 3.72590 - 3.24520 2.92845 2.53435 2.14740 1.68664 1.55743 - 1.49163 1.49546 1.50185 1.49901 1.48872 1.51181 - 11.04217 10.12240 9.47215 8.88343 8.34826 7.85970 - 7.41475 7.00990 6.64214 6.30811 6.00399 5.72470 - 5.46295 5.21210 4.96799 4.72277 4.45899 4.13448 - 3.66576 3.32043 2.83301 2.31937 1.71820 1.55894 - 1.48570 1.47742 1.45982 1.46041 1.45641 1.47272 - 10.98141 10.08900 9.47296 8.91457 8.40655 7.94297 - 7.52114 7.13795 6.79065 6.47619 6.19091 5.92987 - 5.68561 5.45141 5.22321 4.99311 4.74324 4.42967 - 3.96224 3.60740 3.09269 2.52653 1.79973 1.58896 - 1.47722 1.46549 1.44510 1.44447 1.44089 1.45305 - 10.88212 10.04703 9.48834 8.97527 8.50327 8.06902 - 7.67178 7.31079 6.98560 6.69397 6.43274 6.19736 - 5.98078 5.77604 5.57757 5.37402 5.14565 4.85306 - 4.40572 4.05283 3.51726 2.88297 1.97302 1.69501 - 1.47315 1.44900 1.43383 1.43143 1.42737 1.43356 - 10.85878 10.04137 9.50494 9.01152 8.55754 8.14034 - 7.75944 7.41444 7.10521 6.82981 6.58533 6.36742 - 6.16917 5.98369 5.80558 5.62340 5.41790 5.15202 - 4.73473 4.39352 3.85549 3.18440 2.13835 1.79236 - 1.48743 1.44954 1.42679 1.42398 1.41686 1.42377 - 10.85438 10.04471 9.51911 9.03644 8.59344 8.18751 - 7.81792 7.48405 7.18553 6.92083 6.68764 6.48260 - 6.30005 6.13357 5.97607 5.81204 5.61926 5.36429 - 4.96649 4.64734 4.14662 3.48118 2.29142 1.87001 - 1.50565 1.45834 1.42239 1.41676 1.41429 1.41790 - 10.84881 10.04778 9.53077 9.05631 8.62133 8.22342 - 7.86179 7.53583 7.24502 6.98808 6.76304 6.56702 - 6.39491 6.24096 6.09837 5.95186 5.77890 5.54436 - 5.16688 4.85971 4.37353 3.70975 2.44481 1.96121 - 1.52139 1.46311 1.42076 1.41357 1.41100 1.41403 - 10.83897 10.05849 9.55264 9.08532 8.65691 8.26795 - 7.91735 7.60351 7.32479 7.07979 6.86683 6.68363 - 6.52655 6.39098 6.27042 6.14917 6.00532 5.80812 - 5.48157 5.20356 4.73881 4.06783 2.70533 2.14371 - 1.56457 1.47861 1.41634 1.40985 1.39972 1.40921 - 10.85581 10.06694 9.55968 9.09746 8.67700 8.29583 - 7.95265 7.64615 7.37505 7.13816 6.93381 6.75933 - 6.60985 6.48124 6.37209 6.27695 6.17782 6.02000 - 5.70545 5.43511 5.00775 4.38197 2.95703 2.30463 - 1.59307 1.48820 1.41851 1.41037 1.40345 1.40630 - 10.83344 10.06862 9.57506 9.12439 8.71381 8.34151 - 8.00635 7.70737 7.44378 7.21511 7.02100 6.86042 - 6.73115 6.63038 6.55411 6.48999 6.41851 6.30603 - 6.07508 5.85868 5.48970 4.91705 3.45945 2.65867 - 1.68448 1.53427 1.42223 1.41149 1.39553 1.40238 - 10.81669 10.07291 9.58504 9.13873 8.73175 8.36275 - 8.03095 7.73592 7.47747 7.25527 7.06889 6.91721 - 6.79771 6.70793 6.64567 6.60201 6.56060 6.48775 - 6.31100 6.13055 5.80023 5.27287 3.85027 2.97036 - 1.77308 1.57630 1.42936 1.41357 1.39736 1.40044 - 10.77788 10.07794 9.59490 9.15212 8.74836 8.38304 - 8.05558 7.76573 7.51346 7.29847 7.12035 6.97806 - 6.86951 6.79284 6.74684 6.72415 6.71273 6.69063 - 6.59485 6.46454 6.19273 5.73499 4.41568 3.45806 - 1.94742 1.67750 1.44542 1.42105 1.39382 1.39848 - 10.74472 10.07904 9.59870 9.15859 8.75736 8.39420 - 8.06891 7.78171 7.53303 7.32228 7.14830 7.00999 - 6.90600 6.83559 6.79905 6.79157 6.80270 6.80632 - 6.74070 6.64164 6.44444 6.08750 4.80345 3.77401 - 2.12958 1.79996 1.46022 1.41348 1.39762 1.39751 - 10.73811 10.08642 9.60065 9.15837 8.75748 8.39660 - 8.07473 7.79114 7.54533 7.33698 7.16559 7.03004 - 6.92753 6.85698 6.82193 6.82464 6.85991 6.89415 - 6.86308 6.78496 6.59953 6.24741 5.09269 4.15061 - 2.27083 1.87055 1.48334 1.43546 1.39507 1.39693 - 10.70198 10.07912 9.60236 9.16572 8.76774 8.40767 - 8.08517 7.80032 7.55351 7.34484 7.17430 7.04156 - 6.94497 6.88344 6.85699 6.86002 6.88472 6.92035 - 6.93116 6.88772 6.73136 6.40031 5.32023 4.40763 - 2.42002 1.96131 1.50136 1.44584 1.39607 1.39655 - 10.68110 10.07989 9.60443 9.16909 8.77248 8.41388 - 8.09291 7.80964 7.56447 7.35755 7.18899 7.05861 - 6.96502 6.90738 6.88606 6.89597 6.93063 6.98284 - 7.02546 7.01074 6.90155 6.62997 5.66083 4.79554 - 2.69535 2.13873 1.54084 1.46318 1.39812 1.39606 - 10.66785 10.08222 9.60732 9.17133 8.77403 8.41556 - 8.09562 7.81416 7.57137 7.36686 7.19997 7.07020 - 6.97718 6.92102 6.90242 6.91698 6.95934 7.02453 - 7.08472 7.08213 7.00454 6.79986 5.94004 5.05488 - 2.92636 2.31499 1.58561 1.46684 1.41270 1.39577 - 10.64819 10.08315 9.60910 9.17397 8.77773 8.42057 - 8.10207 7.82207 7.58054 7.37724 7.21171 7.08375 - 6.99329 6.94071 6.92681 6.94711 6.99694 7.07470 - 7.16576 7.19532 7.16749 7.02246 6.33234 5.60040 - 3.41985 2.65883 1.68539 1.51774 1.42475 1.39539 - 10.63655 10.08359 9.61026 9.17566 8.77987 8.42323 - 8.10525 7.82559 7.58423 7.38128 7.21697 7.09120 - 7.00274 6.95129 6.93847 6.96177 7.01803 7.10365 - 7.20365 7.24621 7.25959 7.16917 6.54560 5.92547 - 3.84126 2.96468 1.77747 1.57013 1.42358 1.39519 - 10.62426 10.08368 9.61104 9.17717 8.78197 8.42566 - 8.10790 7.82860 7.58796 7.38607 7.22292 7.09831 - 7.01120 6.96145 6.95086 6.97725 7.03822 7.13232 - 7.24725 7.30274 7.34434 7.31013 6.85001 6.34565 - 4.42854 3.44767 1.95543 1.66637 1.44628 1.39499 - 10.61785 10.08368 9.61124 9.17755 8.78258 8.42654 - 8.10916 7.83043 7.59056 7.38934 7.22626 7.10119 - 7.01427 6.96621 6.95815 6.98607 7.04663 7.14219 - 7.27352 7.34476 7.38723 7.34341 7.03054 6.70887 - 4.80412 3.76355 2.12576 1.78444 1.46922 1.39488 - 10.63181 10.08943 9.61019 9.17373 8.77851 8.42341 - 8.10757 7.83044 7.59172 7.39134 7.22920 7.10462 - 7.01548 6.96181 6.94903 6.98295 7.06497 7.17513 - 7.28840 7.34654 7.40587 7.42330 7.15670 6.77922 - 5.14859 4.12697 2.28436 1.85721 1.48808 1.39482 - 10.62867 10.08935 9.61033 9.17405 8.77900 8.42404 - 8.10831 7.83130 7.59270 7.39246 7.23044 7.10605 - 7.01716 6.96384 6.95154 6.98612 7.06913 7.18075 - 7.29692 7.35822 7.42438 7.45503 7.23758 6.90774 - 5.38894 4.37500 2.43514 1.95301 1.50834 1.39478 - 10.60656 10.08408 9.61233 9.17894 8.78421 8.42856 - 8.11164 7.83328 7.59356 7.39259 7.23052 7.10723 - 7.02179 6.97422 6.96650 6.99679 7.06347 7.16717 - 7.30347 7.37938 7.45336 7.49260 7.34661 7.07542 - 5.73444 4.76121 2.70812 2.14180 1.54798 1.39473 - 10.60644 10.08433 9.61191 9.17861 8.78422 8.42876 - 8.11194 7.83379 7.59458 7.39412 7.23192 7.10784 - 7.02199 6.97518 6.96899 7.00036 7.06671 7.16966 - 7.31030 7.39315 7.47282 7.50434 7.38498 7.23093 - 5.97045 5.00331 2.94660 2.34385 1.57711 1.39470 - 0.48887 0.51109 0.53489 0.56032 0.58723 0.61537 - 0.64468 0.67507 0.70648 0.73903 0.77306 0.80878 - 0.84591 0.88398 0.92233 0.95986 0.99520 1.02738 - 1.05382 1.06359 1.07264 1.08003 1.08898 1.09138 - 1.09339 1.09358 1.09367 1.09371 1.09370 1.09388 - 0.70384 0.73701 0.77132 0.80698 0.84396 0.88220 - 0.92164 0.96216 1.00365 1.04604 1.08931 1.13359 - 1.17934 1.22671 1.27472 1.32121 1.36370 1.40146 - 1.43313 1.44609 1.45889 1.46935 1.48022 1.48376 - 1.48764 1.48705 1.48581 1.48639 1.48577 1.49009 - 0.91233 0.95490 0.99836 1.04294 1.08855 1.13508 - 1.18243 1.23055 1.27938 1.32888 1.37896 1.42976 - 1.48180 1.53526 1.58897 1.64052 1.68727 1.72900 - 1.76505 1.78052 1.79621 1.80916 1.82186 1.82582 - 1.83009 1.82953 1.82830 1.82889 1.82826 1.83277 - 1.30296 1.36162 1.42012 1.47874 1.53727 1.59555 - 1.65353 1.71140 1.76953 1.82792 1.88636 1.94485 - 2.00373 2.06303 2.12157 2.17726 2.22803 2.27438 - 2.31658 2.33584 2.35565 2.37204 2.38782 2.39185 - 2.39530 2.39557 2.39568 2.39580 2.39574 2.39661 - 1.65760 1.72924 1.79923 1.86794 1.93503 2.00036 - 2.06398 2.12650 2.18882 2.25099 2.31280 2.37405 - 2.43487 2.49517 2.55392 2.60967 2.66117 2.70942 - 2.75525 2.77704 2.79943 2.81785 2.83588 2.83971 - 2.84198 2.84316 2.84480 2.84437 2.84496 2.84154 - 1.98017 2.06233 2.14070 2.21590 2.28782 2.35664 - 2.42267 2.48675 2.55025 2.61333 2.67590 2.73751 - 2.79757 2.85549 2.91086 2.96411 3.01559 3.06484 - 3.11210 3.13562 3.15962 3.17910 3.19865 3.20217 - 3.20386 3.20512 3.20796 3.20844 3.20792 3.20169 - 2.27260 2.36406 2.44908 2.52861 2.60297 2.67295 - 2.73907 2.80248 2.86489 2.92652 2.98724 3.04654 - 3.10379 3.15847 3.21046 3.26082 3.31059 3.35943 - 3.40744 3.43161 3.45639 3.47663 3.49704 3.50039 - 3.50159 3.50311 3.50671 3.50732 3.50663 3.49839 - 2.78209 2.88807 2.98176 3.06501 3.13932 3.20694 - 3.26890 3.32672 3.38265 3.43711 3.49014 3.54138 - 3.59037 3.63685 3.68113 3.72491 3.76991 3.81601 - 3.86313 3.88729 3.91220 3.93270 3.95361 3.95700 - 3.95808 3.95971 3.96359 3.96425 3.96350 3.95458 - 3.21212 3.32856 3.42664 3.50922 3.57930 3.64084 - 3.69530 3.74446 3.79090 3.83528 3.87803 3.91916 - 3.95854 3.99628 4.03286 4.07004 4.10956 4.15154 - 4.19586 4.21896 4.24289 4.26265 4.28302 4.28671 - 4.28838 4.28977 4.29290 4.29344 4.29286 4.28600 - 4.05585 4.18742 4.28597 4.35727 4.40820 4.44714 - 4.47678 4.49969 4.51943 4.53691 4.55288 4.56812 - 4.58375 4.60102 4.62039 4.64236 4.66767 4.69731 - 4.73151 4.74981 4.76906 4.78521 4.80228 4.80651 - 4.80981 4.81040 4.81093 4.81093 4.81102 4.81149 - 4.69917 4.81341 4.90134 4.96554 5.00625 5.02522 - 5.02643 5.01687 5.00533 4.99438 4.98500 4.97840 - 4.97611 4.97937 4.98743 4.99737 5.00719 5.02089 - 5.04359 5.05822 5.07232 5.08268 5.09569 5.09984 - 5.10384 5.10336 5.10233 5.10283 5.10232 5.10830 - 5.63046 5.72587 5.78556 5.81424 5.81322 5.78586 - 5.73833 5.68048 5.62393 5.57234 5.52662 5.48764 - 5.45652 5.43360 5.41762 5.40425 5.39032 5.38056 - 5.38116 5.38530 5.38863 5.39009 5.39442 5.39677 - 5.39989 5.39875 5.39673 5.39750 5.39662 5.40645 - 6.29505 6.40959 6.44091 6.41029 6.34251 6.26371 - 6.18051 6.09662 6.01604 5.94021 5.86943 5.80412 - 5.74663 5.69811 5.65810 5.62378 5.59294 5.56778 - 5.54933 5.54160 5.53504 5.53082 5.52683 5.52743 - 5.52956 5.52804 5.52560 5.52590 5.52523 5.53577 - 6.84244 6.93367 6.93036 6.85889 6.74918 6.63188 - 6.51434 6.40008 6.29291 6.19353 6.10121 6.01543 - 5.93863 5.87193 5.81460 5.76341 5.71581 5.67409 - 5.63944 5.62380 5.60932 5.59871 5.58805 5.58758 - 5.58936 5.58714 5.58373 5.58418 5.58325 5.59402 - 7.30489 7.36904 7.33037 7.21990 7.07176 6.92024 - 6.77295 6.63283 6.50327 6.38419 6.27369 6.17045 - 6.07687 5.99426 5.92164 5.85552 5.79320 5.73709 - 5.68857 5.66617 5.64492 5.62885 5.61241 5.61126 - 5.61323 5.61013 5.60550 5.60615 5.60489 5.61578 - 8.23455 8.05009 7.86050 7.67548 7.49487 7.31885 - 7.14764 6.98128 6.82039 6.66608 6.51873 6.37874 - 6.24733 6.12613 6.01620 5.91932 5.83653 5.76500 - 5.70436 5.68156 5.66602 5.65297 5.59475 5.56811 - 5.58589 5.59051 5.58136 5.57835 5.58328 5.58908 - 8.62307 8.56257 8.38802 8.14273 7.87031 7.61163 - 7.37358 7.15657 6.96082 6.78388 6.61979 6.46487 - 6.32087 6.18966 6.06984 5.95791 5.85137 5.75262 - 5.66303 5.62066 5.57945 5.54739 5.51462 5.51014 - 5.51000 5.50582 5.49993 5.50081 5.49924 5.50456 - 9.59913 9.37896 9.05898 8.68650 8.30582 7.95584 - 7.64087 7.35915 7.10831 6.88310 6.67529 6.47926 - 6.29521 6.12398 5.96538 5.81663 5.67615 5.54470 - 5.42255 5.36439 5.30733 5.26319 5.21949 5.20785 - 5.19774 5.19739 5.19786 5.19763 5.19791 5.18653 - 10.31566 9.80833 9.32662 8.87907 8.46336 8.07803 - 7.72175 7.39368 7.09348 6.81957 6.56978 6.34132 - 6.13014 5.93371 5.75336 5.58869 5.43722 5.28793 - 5.13176 5.05514 4.98787 4.94333 4.89149 4.87350 - 4.85454 4.85719 4.86492 4.86377 4.86585 4.84147 - 10.96498 10.28778 9.66196 9.08941 8.56490 8.08564 - 7.64966 7.25402 6.89637 6.57382 6.28255 6.01796 - 5.77362 5.54507 5.33285 5.13744 4.95542 4.77610 - 4.59159 4.50180 4.42219 4.36827 4.30597 4.28515 - 4.26409 4.26667 4.27438 4.27309 4.27509 4.25843 - 11.26832 10.51586 9.80977 9.15398 8.55259 8.00980 - 7.52451 7.09299 6.71075 6.36808 6.05162 5.75382 - 5.47705 5.22216 4.98570 4.76489 4.55750 4.36095 - 4.17274 4.08130 3.99183 3.92190 3.85328 3.83444 - 3.81799 3.81735 3.81955 3.81986 3.81893 3.81860 - 11.50480 10.62229 9.83911 9.13742 8.50802 7.94273 - 7.43536 6.97814 6.56335 6.18646 5.84373 5.53083 - 5.24206 4.97309 4.72247 4.48750 4.26593 4.05521 - 3.85488 3.75847 3.66136 3.58369 3.50923 3.49167 - 3.47759 3.47577 3.47381 3.47341 3.47341 3.48000 - 11.63814 10.69071 9.86050 9.12012 8.45986 7.87002 - 7.34239 6.86788 6.43764 6.04652 5.69045 5.36480 - 5.06354 4.78222 4.51977 4.27441 4.04421 3.82464 - 3.61242 3.50921 3.40618 3.32431 3.24427 3.22665 - 3.21380 3.21029 3.20619 3.20705 3.20569 3.21496 - 11.77252 10.74348 9.85756 9.07149 8.37484 7.75631 - 7.20451 6.70842 6.25794 5.84768 5.47362 5.13131 - 4.81522 4.52090 4.24608 3.98696 3.74022 3.50382 - 3.27504 3.16310 3.05048 2.96012 2.87090 2.85013 - 2.83518 2.83234 2.82730 2.82647 2.82710 2.83326 - 11.82547 10.75097 9.83567 9.02491 8.30813 7.67306 - 7.10720 6.59891 6.13794 5.71869 5.33677 4.98729 - 4.66424 4.36274 4.08006 3.81181 3.55396 3.30427 - 3.06015 2.93970 2.81897 2.72224 2.62379 2.59898 - 2.58044 2.57773 2.57386 2.57323 2.57352 2.57515 - 11.82369 10.70688 9.77030 8.94084 8.20929 7.55944 - 6.97976 6.45915 5.98813 5.56087 5.17242 4.81728 - 4.48878 4.18125 3.89108 3.61244 3.33951 3.06726 - 2.79097 2.64937 2.50367 2.38413 2.26357 2.23279 - 2.20800 2.20509 2.20268 2.20236 2.20208 2.19936 - 11.76135 10.64366 9.71607 8.89358 8.16728 7.51893 - 6.93866 6.41658 5.94425 5.51602 5.12694 4.77156 - 4.44321 4.13605 3.84575 3.56519 3.28639 3.00046 - 2.69677 2.53424 2.35969 2.21176 2.06968 2.03683 - 2.00960 2.00592 2.00259 2.00220 2.00191 2.00279 - 11.60305 10.52071 9.63549 8.84711 8.14365 7.51014 - 6.93971 6.42566 5.96218 5.54351 5.16361 4.81558 - 4.49071 4.18223 3.88744 3.60218 3.31807 3.01590 - 2.67219 2.47733 2.26009 2.06621 1.86715 1.82448 - 1.80135 1.79847 1.79164 1.79021 1.79140 1.80494 - 11.49090 10.43319 9.58426 8.82900 8.15094 7.53741 - 6.98198 6.47830 6.02092 5.60547 5.22779 4.88335 - 4.56661 4.27188 3.99304 3.71934 3.43565 3.11779 - 2.73393 2.50539 2.24238 2.00428 1.76852 1.72226 - 1.69469 1.69100 1.68383 1.68236 1.68383 1.70677 - 11.39284 10.36283 9.54918 8.82313 8.16721 7.57113 - 7.02971 6.53768 6.09064 5.68451 5.31534 4.97867 - 4.66898 4.38047 4.10678 3.83650 3.55268 3.22653 - 2.81842 2.56728 2.26960 1.99450 1.71534 1.65945 - 1.63087 1.62814 1.62105 1.61936 1.62131 1.64750 - 11.31457 10.30766 9.52485 8.82325 8.18673 7.60639 - 7.07801 6.59721 6.16035 5.76365 5.40316 5.07438 - 4.77166 4.48902 4.22001 3.95288 3.66949 3.33777 - 2.91147 2.64211 2.31500 2.00669 1.68620 1.61998 - 1.58932 1.58754 1.58094 1.57915 1.58141 1.60785 - 11.19713 10.22748 9.49439 8.83164 8.22717 7.67349 - 7.16782 6.70710 6.28888 5.90966 5.56548 5.25166 - 4.96200 4.69019 4.42975 4.16873 3.88761 3.54996 - 3.09895 2.80210 2.42739 2.06194 1.66554 1.57805 - 1.53996 1.53945 1.53395 1.53208 1.53462 1.55849 - 11.11378 10.17297 9.47743 8.84436 8.26497 7.73268 - 7.24569 6.80181 6.39943 6.03527 5.70531 5.40468 - 5.12666 4.86456 4.61203 4.35711 4.07958 3.74046 - 3.27497 2.95893 2.54788 2.13534 1.67072 1.56194 - 1.51298 1.51278 1.50800 1.50607 1.50866 1.52905 - 11.03894 10.11309 9.45608 8.86211 8.32301 7.83175 - 7.38518 6.97972 6.61220 6.27925 5.97691 5.70006 - 5.44123 5.19372 4.95336 4.71225 4.45268 4.13178 - 3.66554 3.32149 2.83629 2.32569 1.72868 1.56762 - 1.48527 1.48190 1.47582 1.47506 1.47273 1.48945 - 10.97381 10.07658 9.45463 8.89163 8.38018 7.91424 - 7.49101 7.10730 6.76025 6.44678 6.16314 5.90431 - 5.66273 5.43159 5.20685 4.98054 4.73462 4.42450 - 3.95970 3.60642 3.09446 2.53194 1.80966 1.59713 - 1.47732 1.47054 1.46127 1.45930 1.45735 1.46948 - 10.85354 10.02702 9.47072 8.95717 8.48263 8.04461 - 7.64335 7.27919 6.95278 6.66195 6.40309 6.17117 - 5.95830 5.75691 5.56129 5.36003 5.13345 4.84277 - 4.39859 4.04860 3.51773 2.88821 1.98051 1.70090 - 1.47852 1.45719 1.44926 1.44782 1.44127 1.44965 - 10.82716 10.01723 9.48307 8.98991 8.53472 8.11545 - 7.73220 7.38534 7.07554 6.80085 6.55811 6.34265 - 6.14701 5.96390 5.78783 5.60738 5.40338 5.13932 - 4.72530 4.38698 3.85348 3.18725 2.14511 1.79902 - 1.49546 1.45986 1.44227 1.44013 1.43138 1.43966 - 10.82087 10.01776 9.49426 9.01234 8.56907 8.16224 - 7.79155 7.45687 7.15834 6.89441 6.66265 6.45943 - 6.27868 6.11372 5.95742 5.79434 5.60255 5.34954 - 4.95574 4.63948 4.14216 3.48074 2.29812 1.87797 - 1.51497 1.47052 1.43837 1.43163 1.43034 1.43366 - 10.81452 10.01868 9.50340 9.03003 8.59563 8.19799 - 7.83647 7.51064 7.22026 6.96398 6.73985 6.54483 - 6.37374 6.22066 6.07887 5.93310 5.76105 5.52826 - 5.15442 4.85005 4.36753 3.70796 2.45022 1.96919 - 1.53305 1.47662 1.43634 1.42873 1.42679 1.42969 - 10.80484 10.02644 9.52170 9.05644 8.63026 8.24304 - 7.89373 7.58081 7.30283 7.05836 6.84571 6.66261 - 6.50560 6.37018 6.24988 6.12903 5.98589 5.79021 - 5.46684 5.19134 4.72989 4.06288 2.70902 2.15213 - 1.57846 1.49327 1.43161 1.42523 1.41536 1.42476 - 10.81833 10.03480 9.52987 9.06965 8.65089 8.27117 - 7.92921 7.62370 7.35338 7.11705 6.91307 6.73880 - 6.58937 6.46073 6.35147 6.25625 6.15728 6.00047 - 5.68874 5.42083 4.99691 4.37543 2.95913 2.31160 - 1.60792 1.50352 1.43346 1.42568 1.41874 1.42177 - 10.79898 10.03771 9.54537 9.09609 8.68705 8.31630 - 7.98266 7.68501 7.42246 7.19452 7.00081 6.84028 - 6.71071 6.60936 6.53242 6.46802 6.39696 6.28525 - 6.05567 5.84100 5.47519 4.90666 3.45811 2.66405 - 1.69805 1.54857 1.43693 1.42636 1.41088 1.41778 - 10.78350 10.04286 9.55599 9.11087 8.70527 8.33767 - 8.00724 7.71340 7.45581 7.23413 7.04798 6.89627 - 6.77658 6.68652 6.62397 6.58014 6.53885 6.46625 - 6.29009 6.11071 5.78314 5.26022 3.84708 2.97305 - 1.78482 1.58919 1.44378 1.42863 1.41234 1.41580 - 10.76024 10.05348 9.56574 9.12139 8.71816 8.35451 - 8.02936 7.74185 7.49145 7.27769 7.09996 6.95688 - 6.84543 6.76396 6.71461 6.69724 6.70190 6.68522 - 6.56942 6.43326 6.17829 5.73291 4.38256 3.46949 - 1.96048 1.68493 1.45898 1.43551 1.40990 1.41381 - 10.71185 10.04973 9.57078 9.13173 8.73131 8.36891 - 8.04435 7.75780 7.50970 7.29946 7.12599 6.98813 - 6.88450 6.81421 6.77763 6.76996 6.78076 6.78397 - 6.71805 6.61921 6.42320 6.06910 4.79418 3.77058 - 2.13649 1.80968 1.47391 1.42797 1.41244 1.41280 - 10.68731 10.05003 9.57298 9.13577 8.73701 8.37604 - 8.05278 7.76768 7.52139 7.31340 7.14259 7.00790 - 6.90788 6.84184 6.81062 6.81041 6.83270 6.85563 - 6.82384 6.74967 6.58627 6.27727 5.09737 4.06965 - 2.28669 1.90479 1.49392 1.43491 1.41601 1.41221 - 10.66917 10.04937 9.57414 9.13873 8.74173 8.38243 - 8.06057 7.77629 7.53002 7.32189 7.15189 7.01962 - 6.92341 6.86214 6.83577 6.83864 6.86289 6.89794 - 6.90833 6.86481 6.70868 6.37925 5.30769 4.40082 - 2.42396 1.96914 1.51460 1.45995 1.41110 1.41180 - 10.64853 10.04999 9.57604 9.14196 8.74643 8.38871 - 8.06850 7.78590 7.54133 7.33495 7.16688 7.03692 - 6.94362 6.88618 6.86488 6.87461 6.90886 6.96052 - 7.00261 6.98766 6.87836 6.60772 5.64558 4.78613 - 2.69794 2.14563 1.55350 1.47698 1.41300 1.41130 - 10.63503 10.05220 9.57897 9.14441 8.74830 8.39083 - 8.07167 7.79068 7.54803 7.34366 7.17746 7.04900 - 6.95695 6.90070 6.88133 6.89541 6.93778 7.00024 - 7.05936 7.06302 6.99129 6.76916 5.88328 5.07685 - 2.93919 2.31058 1.59607 1.49060 1.41653 1.41099 - 10.61559 10.05324 9.58075 9.14680 8.75158 8.39547 - 8.07804 7.79900 7.55827 7.35556 7.19040 7.06260 - 6.97218 6.91959 6.90563 6.92576 6.97532 7.05265 - 7.14299 7.17212 7.14396 6.99908 6.31215 5.58475 - 3.41963 2.66392 1.69648 1.53013 1.43939 1.41059 - 10.60428 10.05363 9.58169 9.14825 8.75351 8.39791 - 8.08101 7.80254 7.56246 7.36050 7.19622 7.06951 - 6.98050 6.92976 6.91818 6.94134 6.99497 7.07899 - 7.18537 7.23143 7.23057 7.12086 6.55137 5.94708 - 3.80546 2.95021 1.79115 1.58325 1.44919 1.41039 - 10.59204 10.05379 9.58270 9.15003 8.75589 8.40057 - 8.08373 7.80527 7.56533 7.36399 7.20127 7.07700 - 6.99010 6.94043 6.92982 6.95605 7.01673 7.11038 - 7.22469 7.27980 7.32094 7.28631 6.82686 6.32537 - 4.42200 3.44741 1.96411 1.67714 1.46028 1.41018 - 10.58630 10.05378 9.58268 9.15031 8.75654 8.40152 - 8.08503 7.80704 7.56783 7.36714 7.20454 7.07983 - 6.99319 6.94524 6.93713 6.96490 7.02518 7.12034 - 7.25103 7.32185 7.36391 7.31983 7.00693 6.68654 - 4.79458 3.76087 2.13317 1.79420 1.48306 1.41008 - 10.60050 10.05974 9.58182 9.14657 8.75245 8.39835 - 8.08340 7.80703 7.56900 7.36920 7.20752 7.08329 - 6.99440 6.94086 6.92807 6.96183 7.04352 7.15321 - 7.26594 7.32375 7.38267 7.39963 7.13265 6.75668 - 5.13717 4.12210 2.29056 1.86621 1.50156 1.41002 - 10.59749 10.05975 9.58203 9.14692 8.75296 8.39899 - 8.08416 7.80793 7.57001 7.37035 7.20882 7.08478 - 6.99614 6.94294 6.93061 6.96503 7.04767 7.15884 - 7.27449 7.33548 7.40122 7.43134 7.21340 6.88482 - 5.37611 4.36849 2.44026 1.96129 1.52160 1.40998 - 10.57563 10.05422 9.58368 9.15159 8.75813 8.40357 - 8.08759 7.81003 7.57105 7.37073 7.20910 7.08606 - 7.00074 6.95321 6.94548 6.97565 7.04209 7.14539 - 7.28116 7.35676 7.43022 7.46888 7.32241 7.05174 - 5.71917 4.75199 2.71135 2.14865 1.56075 1.40993 - 10.57293 10.05446 9.58424 9.15217 8.75859 8.40392 - 8.08784 7.81025 7.57127 7.37103 7.20964 7.08699 - 7.00210 6.95495 6.94757 6.97819 7.04538 7.15025 - 7.28798 7.36524 7.44570 7.49523 7.38066 7.15538 - 5.95005 5.03460 2.95238 2.32573 1.59661 1.40989 - 0.48215 0.50415 0.52781 0.55315 0.57995 0.60792 - 0.63698 0.66712 0.69829 0.73055 0.76408 0.79896 - 0.83494 0.87166 0.90864 0.94524 0.98054 1.01349 - 1.04066 1.05038 1.05955 1.06742 1.07753 1.08024 - 1.08249 1.08280 1.08301 1.08300 1.08297 1.08306 - 0.69510 0.72807 0.76220 0.79765 0.83440 0.87240 - 0.91155 0.95174 0.99282 1.03468 1.07726 1.12065 - 1.16521 1.21110 1.25760 1.30328 1.34633 1.38562 - 1.41898 1.43255 1.44533 1.45558 1.46823 1.47207 - 1.47610 1.47685 1.47668 1.47591 1.47475 1.47903 - 0.90173 0.94406 0.98729 1.03161 1.07693 1.12315 - 1.17015 1.21786 1.26621 1.31514 1.36450 1.41440 - 1.46528 1.51732 1.56965 1.62053 1.66800 1.71149 - 1.74963 1.76596 1.78190 1.79480 1.80935 1.81363 - 1.81810 1.81890 1.81873 1.81795 1.81673 1.82129 - 1.28904 1.34739 1.40558 1.46388 1.52207 1.57997 - 1.63754 1.69498 1.75261 1.81044 1.86824 1.92598 - 1.98397 2.04227 2.09989 2.15519 2.20656 2.25434 - 2.29852 2.31893 2.33981 2.35702 2.37423 2.37866 - 2.38250 2.38301 2.38326 2.38314 2.38291 2.38399 - 1.64087 1.71215 1.78180 1.85016 1.91689 1.98185 - 2.04510 2.10722 2.16912 2.23083 2.29217 2.35290 - 2.41319 2.47296 2.53127 2.58687 2.63871 2.68780 - 2.73515 2.75816 2.78228 2.80236 2.82123 2.82555 - 2.82834 2.82847 2.82919 2.82985 2.83081 2.82770 - 1.96090 2.04295 2.12103 2.19579 2.26723 2.33567 - 2.40139 2.46523 2.52850 2.59134 2.65363 2.71493 - 2.77471 2.83245 2.88781 2.94125 2.99307 3.04235 - 3.09023 3.11541 3.14166 3.16293 3.18314 3.18725 - 3.18892 3.18899 3.19008 3.19115 3.19335 3.18671 - 2.25127 2.34269 2.42744 2.50655 2.58046 2.65010 - 2.71601 2.77929 2.84161 2.90317 2.96381 3.02304 - 3.08030 3.13512 3.18740 3.23814 3.28818 3.33657 - 3.38461 3.41053 3.43777 3.45995 3.48072 3.48469 - 3.48573 3.48565 3.48698 3.48839 3.49129 3.48242 - 2.75762 2.86366 2.95720 3.04009 3.11405 3.18150 - 3.24346 3.30141 3.35756 3.41226 3.46557 3.51711 - 3.56652 3.61355 3.65847 3.70286 3.74812 3.79344 - 3.84005 3.86574 3.89290 3.91511 3.93605 3.94000 - 3.94083 3.94071 3.94212 3.94365 3.94681 3.93717 - 3.18547 3.30209 3.40013 3.48249 3.55234 3.61389 - 3.66856 3.71811 3.76502 3.80992 3.85322 3.89494 - 3.93499 3.97346 4.01081 4.04869 4.08858 4.13001 - 4.17385 4.19801 4.22350 4.24441 4.26470 4.26882 - 4.27027 4.27028 4.27148 4.27269 4.27517 4.26778 - 4.02632 4.15837 4.25715 4.32854 4.37964 4.41906 - 4.44943 4.47325 4.49389 4.51229 4.52925 4.54554 - 4.56212 4.58016 4.60016 4.62279 4.64885 4.67907 - 4.71344 4.73173 4.75083 4.76674 4.78376 4.78808 - 4.79145 4.79191 4.79231 4.79238 4.79254 4.79318 - 4.66908 4.78358 4.87196 4.93679 4.97825 4.99810 - 5.00033 4.99185 4.98148 4.97173 4.96355 4.95807 - 4.95672 4.96066 4.96924 4.97982 4.99061 5.00536 - 5.02864 5.04308 5.05627 5.06549 5.07874 5.08280 - 5.08668 5.08741 5.08731 5.08657 5.08552 5.09152 - 5.60132 5.69740 5.75802 5.78781 5.78806 5.76208 - 5.71602 5.65966 5.60456 5.55434 5.50988 5.47198 - 5.44167 5.41923 5.40356 5.39068 5.37773 5.36920 - 5.37078 5.37494 5.37736 5.37761 5.38241 5.38459 - 5.38744 5.38820 5.38771 5.38652 5.38487 5.39450 - 6.26772 6.38338 6.41598 6.38674 6.32051 6.24343 - 6.16203 6.07990 6.00085 5.92634 5.85670 5.79240 - 5.73579 5.68796 5.64838 5.61404 5.58317 5.56026 - 5.54454 5.53540 5.52757 5.52335 5.51991 5.52001 - 5.52210 5.52248 5.52181 5.52065 5.51845 5.52865 - 6.81707 6.90950 6.90772 6.83799 6.73012 6.61475 - 6.49911 6.38663 6.28104 6.18303 6.09190 6.00718 - 5.93133 5.86544 5.80860 5.75724 5.70932 5.67062 - 5.63977 5.62196 5.60565 5.59524 5.58556 5.58439 - 5.58601 5.58630 5.58531 5.58387 5.58102 5.59111 - 7.28124 7.34664 7.30972 7.20126 7.05523 6.90573 - 6.76034 6.62201 6.49405 6.37643 6.26723 6.16517 - 6.07274 5.99115 5.91915 5.85264 5.78966 5.73772 - 5.69435 5.66852 5.64448 5.62870 5.61374 5.61166 - 5.61329 5.61357 5.61221 5.61037 5.60663 5.61649 - 8.21406 8.03153 7.84395 7.66088 7.48217 7.30799 - 7.13857 6.97397 6.81479 6.66212 6.51638 6.37795 - 6.24806 6.12832 6.01981 5.92427 5.84275 5.77231 - 5.71241 5.68970 5.67392 5.66031 5.60119 5.57408 - 5.59287 5.60026 5.59570 5.59157 5.58976 5.59595 - 8.60473 8.54570 8.37353 8.13099 7.86122 7.60479 - 7.36859 7.15323 6.95906 6.78371 6.62123 6.46801 - 6.32582 6.19641 6.07782 5.96551 5.85794 5.76505 - 5.68242 5.63465 5.58923 5.55774 5.52732 5.52173 - 5.52123 5.52113 5.51920 5.51710 5.51261 5.51672 - 9.58517 9.36740 9.05037 8.68096 8.30313 7.95559 - 7.64262 7.36248 7.11289 6.88881 6.68240 6.48818 - 6.30615 6.13688 5.98004 5.83261 5.69286 5.56192 - 5.44062 5.38309 5.32695 5.28376 5.24107 5.23011 - 5.22058 5.21916 5.21854 5.21910 5.22009 5.20935 - 10.30498 9.80104 9.32247 8.87774 8.46460 8.08159 - 7.72741 7.40124 7.10277 6.83047 6.58215 6.35508 - 6.14525 5.95014 5.77104 5.60746 5.45675 5.30737 - 5.15041 5.07439 5.01088 4.97185 4.92113 4.90237 - 4.88551 4.88272 4.88364 4.88718 4.89357 4.87181 - 10.95775 10.28471 9.66261 9.09328 8.57155 8.09473 - 7.66084 7.26702 6.91098 6.58986 6.29991 6.03662 - 5.79360 5.56645 5.35566 5.16166 4.98083 4.80190 - 4.61716 4.52844 4.45343 4.40584 4.34439 4.32228 - 4.30336 4.30046 4.30120 4.30466 4.31105 4.29656 - 11.28476 10.50016 9.78972 9.14631 8.56262 8.03349 - 7.55549 7.12350 6.73252 6.37885 6.05867 5.76742 - 5.49897 5.24861 5.01507 4.79585 4.58811 4.39048 - 4.20416 4.11615 4.02973 3.96216 3.89391 3.87564 - 3.85918 3.85699 3.85645 3.85742 3.86018 3.85928 - 11.49653 10.62079 9.84279 9.14504 8.51856 7.95546 - 7.44979 6.99403 6.58073 6.20541 5.86438 5.55329 - 5.26649 4.99960 4.75115 4.51826 4.29858 4.08959 - 3.89098 3.79566 3.70014 3.62409 3.55039 3.53268 - 3.51859 3.51702 3.51555 3.51514 3.51479 3.52084 - 11.62628 10.68642 9.86229 9.12687 8.47061 7.88391 - 7.35870 6.88593 6.45682 6.06649 5.71116 5.38654 - 5.08719 4.80880 4.54963 4.30659 4.07714 3.85865 - 3.64954 3.54809 3.44540 3.36292 3.28422 3.26622 - 3.25290 3.25160 3.24966 3.24856 3.24657 3.25475 - 11.75982 10.73895 9.85884 9.07705 8.38348 7.76719 - 7.21710 6.72258 6.27380 5.86544 5.49343 5.15323 - 4.83921 4.54688 4.27402 4.01693 3.77232 3.53802 - 3.31098 3.19940 3.08620 2.99493 2.90660 2.88584 - 2.87072 2.86932 2.86713 2.86582 2.86324 2.86948 - 11.81009 10.74403 9.83476 9.02833 8.31464 7.68176 - 7.11753 6.61068 6.15126 5.73374 5.35368 5.00613 - 4.68507 4.38551 4.10482 3.83867 3.58306 3.33551 - 3.09294 2.97262 2.85092 2.75286 2.65508 2.63051 - 2.61185 2.60998 2.60784 2.60692 2.60526 2.60733 - 11.80370 10.69515 9.76415 8.93877 8.21008 7.56221 - 6.98398 6.46459 5.99485 5.56897 5.18201 4.82854 - 4.50186 4.19633 3.90827 3.63178 3.36084 3.09023 - 2.81485 2.67332 2.52727 2.40728 2.28691 2.25635 - 2.23167 2.22871 2.22615 2.22580 2.22551 2.22311 - 11.73870 10.62821 9.70556 8.88659 8.16278 7.51623 - 6.93734 6.41646 5.94539 5.51857 5.13102 4.77733 - 4.45090 4.14585 3.85767 3.57893 3.30141 3.01612 - 2.71264 2.55043 2.37708 2.23057 2.08847 2.05539 - 2.02845 2.02483 2.02131 2.02081 2.02032 2.02073 - 11.58295 10.50204 9.61781 8.83069 8.12878 7.49704 - 6.92864 6.41676 5.95554 5.53915 5.16149 4.81551 - 4.49232 4.18502 3.89094 3.60604 3.32207 3.02029 - 2.67782 2.48424 2.26920 2.07776 1.88081 1.83831 - 1.81488 1.81221 1.80590 1.80432 1.80432 1.81653 - 11.46272 10.40986 9.56355 8.81008 8.13329 7.52078 - 6.96637 6.46393 6.00827 5.59494 5.21969 4.87782 - 4.56359 4.27099 3.99345 3.71938 3.43344 3.11322 - 2.72958 2.50346 2.24603 2.01412 1.78053 1.73307 - 1.70537 1.70210 1.69546 1.69387 1.69450 1.71562 - 11.36307 10.33749 9.52589 8.80113 8.14613 7.55084 - 7.01030 6.51954 6.07436 5.67062 5.30421 4.97042 - 4.66343 4.37708 4.10435 3.83285 3.54543 3.21575 - 2.80784 2.55995 2.26967 2.00257 1.72637 1.66917 - 1.64018 1.63751 1.63051 1.62896 1.63111 1.65531 - 11.28367 10.28102 9.49982 8.79919 8.16334 7.58358 - 7.05596 6.57641 6.14153 5.74743 5.38996 5.06434 - 4.76448 4.48395 4.21561 3.94658 3.65848 3.32225 - 2.89612 2.63073 2.31247 2.01362 1.69677 1.62925 - 1.59792 1.59574 1.58862 1.58727 1.59102 1.61542 - 11.16486 10.19905 9.46725 8.80511 8.20096 7.64761 - 7.14253 6.68300 6.26686 5.89049 5.54966 5.23932 - 4.95274 4.68297 4.42276 4.15883 3.87141 3.52781 - 3.07690 2.78502 2.42132 2.06748 1.67579 1.58715 - 1.54804 1.54630 1.53911 1.53818 1.54455 1.56643 - 11.08059 10.14365 9.44918 8.81654 8.23730 7.70519 - 7.21865 6.77589 6.37563 6.01440 5.68793 5.39091 - 5.11606 4.85594 4.60335 4.34490 4.06012 3.71416 - 3.24864 2.93821 2.53959 2.14003 1.68089 1.57115 - 1.52102 1.51902 1.51171 1.51108 1.51917 1.53768 - 10.95241 10.06604 9.43224 8.85010 8.31409 7.81978 - 7.36686 6.95487 6.58375 6.25049 5.95078 5.67902 - 5.42713 5.18706 4.95182 4.70821 4.43528 4.09569 - 3.61833 3.28157 2.82377 2.33935 1.74226 1.58422 - 1.48729 1.48202 1.48014 1.48107 1.48811 1.49953 - 10.88370 10.02841 9.43125 8.88098 8.37283 7.90358 - 7.47338 7.08246 6.73133 6.41727 6.13614 5.88233 - 5.64742 5.42314 5.20280 4.97346 4.71441 4.38823 - 3.91690 3.57081 3.08004 2.53651 1.82139 1.61934 - 1.48009 1.46974 1.46655 1.46734 1.47176 1.48057 - 10.81854 9.99650 9.44141 8.92864 8.45453 8.01688 - 7.61602 7.25262 6.92757 6.63860 6.38197 6.15240 - 5.94159 5.74148 5.54582 5.34219 5.11070 4.81526 - 4.37138 4.02619 3.50621 2.88884 1.98948 1.71092 - 1.48799 1.46524 1.45577 1.45569 1.45490 1.46200 - 10.79934 9.98943 9.45378 8.96006 8.50504 8.08646 - 7.70424 7.35847 7.04957 6.77578 6.53431 6.32113 - 6.12961 5.95227 5.78063 5.59706 5.37889 5.09837 - 4.68264 4.35981 3.86332 3.22134 2.14091 1.79303 - 1.51025 1.47495 1.44984 1.44837 1.44732 1.45271 - 10.78714 9.98738 9.46480 8.98393 8.54178 8.13614 - 7.76659 7.43289 7.13511 6.87173 6.64048 6.43791 - 6.25827 6.09493 5.94019 5.77728 5.58350 5.32797 - 4.93466 4.62225 4.13415 3.48198 2.30290 1.88590 - 1.52711 1.48138 1.44883 1.44455 1.44313 1.44715 - 10.78032 9.98844 9.47441 9.00222 8.56896 8.17241 - 7.81189 7.48694 7.19728 6.94160 6.71797 6.52350 - 6.35313 6.20096 6.06006 5.91463 5.74215 5.50922 - 5.13756 4.83641 4.35997 3.70676 2.45441 1.97662 - 1.54507 1.48861 1.44867 1.44222 1.44020 1.44349 - 10.77029 9.99628 9.49309 9.02918 8.60420 8.21805 - 7.86960 7.55745 7.28015 7.03632 6.82420 6.64154 - 6.48476 6.34940 6.22912 6.10870 5.96691 5.77423 - 5.45516 5.18151 4.72210 4.05798 2.71192 2.15886 - 1.59027 1.50632 1.44610 1.43975 1.42925 1.43895 - 10.78354 10.00457 9.50141 9.04269 8.62520 8.24656 - 7.90544 7.60063 7.33084 7.09489 6.89116 6.71706 - 6.56783 6.43945 6.33062 6.23616 6.13861 5.98454 - 5.67728 5.41162 4.98874 4.36843 2.96044 2.31740 - 1.61953 1.51704 1.44870 1.44030 1.43329 1.43620 - 10.76211 10.00720 9.51760 9.07012 8.66214 8.29194 - 7.95856 7.66121 7.39930 7.17227 6.97950 6.81964 - 6.68988 6.58731 6.50904 6.44535 6.37826 6.27027 - 6.04307 5.82937 5.45921 4.89113 3.46319 2.67157 - 1.70672 1.55797 1.45322 1.44012 1.42952 1.43254 - 10.74930 10.01263 9.52724 9.08344 8.67898 8.31240 - 7.98288 7.68985 7.43300 7.21196 7.02631 6.87490 - 6.75523 6.66492 6.60207 6.55847 6.51836 6.44751 - 6.27302 6.09426 5.76726 5.24668 3.84428 2.97501 - 1.79473 1.60165 1.45860 1.44283 1.42739 1.43073 - 10.72627 10.02309 9.53684 9.09380 8.69176 8.32916 - 8.00491 7.71822 7.46848 7.25527 7.07799 6.93523 - 6.82401 6.74269 6.69339 6.67595 6.68040 6.66341 - 6.54750 6.41182 6.15858 5.71669 4.37584 3.46885 - 1.96910 1.69571 1.47279 1.44980 1.42489 1.42892 - 10.67855 10.01947 9.54186 9.10408 8.70484 8.34350 - 8.01987 7.73412 7.48671 7.27703 7.10400 6.96647 - 6.86310 6.79303 6.75655 6.74872 6.75895 6.76095 - 6.69399 6.59561 6.40139 6.05066 4.78491 3.76771 - 2.14393 1.81952 1.48718 1.44206 1.42735 1.42801 - 10.65437 10.01975 9.54407 9.10815 8.71059 8.35067 - 8.02835 7.74404 7.49840 7.29095 7.12057 6.98621 - 6.88651 6.82072 6.78964 6.78923 6.81072 6.83208 - 6.79892 6.72515 6.56347 6.25760 5.08606 4.06466 - 2.29299 1.91386 1.50686 1.44881 1.43101 1.42748 - 10.63631 10.01914 9.54526 9.11109 8.71527 8.35703 - 8.03612 7.75265 7.50707 7.29948 7.12990 6.99797 - 6.90209 6.84108 6.81484 6.81740 6.84074 6.87443 - 6.88355 6.83999 6.68528 6.35880 5.29482 4.39449 - 2.42910 1.97713 1.52735 1.47419 1.42599 1.42712 - 10.61590 10.01978 9.54721 9.11441 8.72003 8.36337 - 8.04410 7.76232 7.51842 7.31261 7.14497 7.01532 - 6.92231 6.86507 6.84383 6.85332 6.88685 6.93751 - 6.97870 6.96360 6.85487 6.58585 5.63014 4.77710 - 2.70131 2.15259 1.56597 1.49105 1.42784 1.42667 - 10.60315 10.02184 9.54974 9.11647 8.72164 8.36529 - 8.04715 7.76721 7.52570 7.32230 7.15628 7.02721 - 6.93466 6.87870 6.86002 6.87421 6.91588 6.98005 - 7.03893 7.03567 6.95789 6.75479 5.90570 5.03068 - 2.93033 2.32825 1.61003 1.49357 1.44237 1.42640 - 10.58334 10.02303 9.55193 9.11928 8.72522 8.37017 - 8.05369 7.77547 7.53544 7.33331 7.16861 7.04116 - 6.95092 6.89837 6.88427 6.90421 6.95364 7.03123 - 7.12171 7.15013 7.12100 6.97582 6.29219 5.56866 - 3.41871 2.66882 1.70806 1.54301 1.45418 1.42604 - 10.57216 10.02341 9.55289 9.12073 8.72718 8.37262 - 8.05663 7.77898 7.53959 7.33823 7.17441 7.04805 - 6.95924 6.90854 6.89686 6.91982 6.97331 7.05752 - 7.16395 7.20935 7.20757 7.09741 6.52989 5.92863 - 3.80227 2.95339 1.80188 1.59547 1.46388 1.42586 - 10.56004 10.02354 9.55385 9.12250 8.72955 8.37528 - 8.05936 7.78168 7.54243 7.34167 7.17942 7.05548 - 6.96880 6.91925 6.90861 6.93467 6.99507 7.08832 - 7.20214 7.25693 7.29771 7.26272 6.80387 6.30526 - 4.41522 3.44698 1.97316 1.68846 1.47448 1.42568 - 10.55438 10.02353 9.55381 9.12274 8.73017 8.37621 - 8.06063 7.78345 7.54491 7.34482 7.18266 7.05832 - 6.97192 6.92408 6.91596 6.94357 7.00354 7.09810 - 7.22805 7.29865 7.34063 7.29654 6.98357 6.66438 - 4.78523 3.75843 2.14093 1.80435 1.49726 1.42558 - 10.56853 10.02950 9.55299 9.11902 8.72608 8.37302 - 8.05900 7.78345 7.54613 7.34691 7.18569 7.06180 - 6.97314 6.91973 6.90692 6.94051 7.02186 7.13107 - 7.24328 7.30081 7.35947 7.37618 7.10896 6.73440 - 5.12576 4.11718 2.29712 1.87577 1.51529 1.42553 - 10.56555 10.02949 9.55321 9.11942 8.72663 8.37371 - 8.05980 7.78437 7.54715 7.34806 7.18697 7.06328 - 6.97486 6.92179 6.90946 6.94375 7.02610 7.13686 - 7.25205 7.31278 7.37822 7.40796 7.18951 6.86200 - 5.36314 4.36195 2.44571 1.96998 1.53511 1.42548 - 10.54372 10.02398 9.55481 9.12404 8.73176 8.37827 - 8.06324 7.78651 7.54822 7.34845 7.18725 7.06453 - 6.97944 6.93205 6.92433 6.95433 7.02043 7.12360 - 7.25914 7.33414 7.40713 7.44561 7.29858 7.02810 - 5.70379 4.74278 2.71444 2.15533 1.57385 1.42543 - 10.54115 10.02423 9.55539 9.12462 8.73223 8.37861 - 8.06346 7.78665 7.54836 7.34871 7.18778 7.06548 - 6.98080 6.93375 6.92639 6.95689 7.02380 7.12808 - 7.26508 7.34226 7.42254 7.47180 7.35663 7.13122 - 5.93307 5.02322 2.95280 2.33010 1.60925 1.42539 - 0.47336 0.49669 0.52100 0.54643 0.57299 0.60068 - 0.62950 0.65943 0.69043 0.72244 0.75539 0.78923 - 0.82398 0.85953 0.89545 0.93108 0.96555 0.99813 - 1.02705 1.03898 1.04912 1.05596 1.06510 1.06861 - 1.07214 1.07248 1.07246 1.07246 1.07241 1.07242 - 0.69318 0.72446 0.75690 0.79070 0.82589 0.86245 - 0.90036 0.93958 0.98005 1.02168 1.06434 1.10790 - 1.15230 1.19730 1.24228 1.28633 1.32834 1.36761 - 1.40232 1.41682 1.42973 1.43946 1.45436 1.46065 - 1.46707 1.46774 1.46776 1.46769 1.46756 1.46817 - 0.90199 0.94102 0.98122 1.02286 1.06592 1.11034 - 1.15605 1.20294 1.25087 1.29974 1.34931 1.39946 - 1.45018 1.50127 1.55200 1.60138 1.64827 1.69228 - 1.73205 1.74929 1.76526 1.77771 1.79515 1.80184 - 1.80865 1.80941 1.80948 1.80940 1.80926 1.80999 - 1.28723 1.34003 1.39374 1.44874 1.50486 1.56193 - 1.61969 1.67785 1.73606 1.79406 1.85159 1.90854 - 1.96523 2.02186 2.07786 2.13269 2.18551 2.23508 - 2.28061 2.30231 2.32428 2.34216 2.36095 2.36582 - 2.37023 2.37087 2.37121 2.37119 2.37122 2.37153 - 1.62783 1.69705 1.76504 1.83217 1.89812 1.96269 - 2.02589 2.08805 2.14981 2.21118 2.27195 2.33201 - 2.39169 2.45108 2.50920 2.56458 2.61623 2.66647 - 2.71787 2.74383 2.77017 2.79017 2.80659 2.81170 - 2.81346 2.81346 2.81399 2.81406 2.81412 2.81399 - 1.93385 2.01869 2.09946 2.17649 2.24933 2.31788 - 2.38262 2.44486 2.50666 2.56835 2.62973 2.69049 - 2.75058 2.80971 2.86679 2.92038 2.96994 3.01946 - 3.07380 3.10268 3.13172 3.15254 3.16718 3.17256 - 3.17193 3.17144 3.17214 3.17225 3.17239 3.17184 - 2.21196 2.31013 2.40140 2.48601 2.56341 2.63364 - 2.69767 2.75782 2.81748 2.87733 2.93718 2.99660 - 3.05519 3.11240 3.16715 3.21807 3.26499 3.31298 - 3.36824 3.39856 3.42888 3.44999 3.46378 3.46927 - 3.46705 3.46625 3.46708 3.46720 3.46740 3.46657 - 2.70096 2.81848 2.92396 3.01756 3.09866 3.16761 - 3.22627 3.27869 3.33042 3.38274 3.43555 3.48831 - 3.54041 3.59109 3.63944 3.68438 3.72606 3.76994 - 3.82269 3.85242 3.88215 3.90306 3.91805 3.92338 - 3.92049 3.91961 3.92049 3.92061 3.92088 3.91996 - 3.12059 3.24936 3.36179 3.45824 3.53804 3.60193 - 3.65245 3.69492 3.73645 3.77873 3.82181 3.86528 - 3.90863 3.95126 3.99251 4.03153 4.06843 4.10769 - 4.15475 4.18129 4.20813 4.22828 4.24648 4.25138 - 4.24986 4.24933 4.25011 4.25019 4.25045 4.24986 - 3.96470 4.10015 4.21162 4.30029 4.36588 4.40983 - 4.43600 4.45154 4.46579 4.48108 4.49786 4.51637 - 4.53670 4.55902 4.58310 4.60816 4.63360 4.66066 - 4.69086 4.70733 4.72490 4.74183 4.76672 4.77027 - 4.77341 4.77401 4.77442 4.77439 4.77453 4.77539 - 4.61693 4.74252 4.83957 4.91035 4.95509 4.97587 - 4.97731 4.96750 4.95661 4.94741 4.94068 4.93708 - 4.93732 4.94206 4.95115 4.96324 4.97687 4.99167 - 5.00738 5.01586 5.02572 5.03844 5.06387 5.06625 - 5.07179 5.07298 5.07313 5.07303 5.07309 5.07543 - 5.58046 5.69409 5.75119 5.76460 5.74845 5.71835 - 5.67904 5.63417 5.58808 5.54313 5.50126 5.46391 - 5.43194 5.40588 5.38616 5.37240 5.36414 5.36107 - 5.35757 5.35282 5.35152 5.35700 5.37104 5.37404 - 5.37808 5.37902 5.37944 5.37925 5.37920 5.38326 - 6.30872 6.35538 6.36712 6.35058 6.30773 6.24229 - 6.16035 6.07122 5.98559 5.90684 5.83594 5.77332 - 5.72010 5.67620 5.64056 5.60921 5.57881 5.55164 - 5.53102 5.52320 5.51501 5.50998 5.51364 5.51322 - 5.51774 5.51872 5.51846 5.51839 5.51834 5.52205 - 6.87599 6.88465 6.85700 6.80147 6.72062 6.61885 - 6.50289 6.38252 6.26897 6.16550 6.07282 5.99070 - 5.91938 5.85794 5.80496 5.75603 5.70786 5.66436 - 5.63074 5.61735 5.60228 5.58941 5.58279 5.58162 - 5.58622 5.58712 5.58667 5.58665 5.58656 5.58837 - 7.32871 7.33792 7.27877 7.17243 7.03802 6.89553 - 6.75187 6.61268 6.48432 6.36732 6.25955 6.15937 - 6.06859 5.98798 5.91642 5.85028 5.78775 5.73540 - 5.69251 5.66893 5.64617 5.62986 5.61410 5.61205 - 5.61769 5.61863 5.61804 5.61788 5.61796 5.61698 - 8.05000 8.02108 7.90273 7.72622 7.52176 7.31902 - 7.12540 6.94448 6.78028 6.63188 6.49479 6.36612 - 6.24773 6.14094 6.04410 5.95297 5.86557 5.78956 - 5.72607 5.69331 5.65963 5.63220 5.60471 5.60153 - 5.60786 5.60880 5.60790 5.60777 5.60786 5.60194 - 8.59364 8.52773 8.35528 8.11662 7.85178 7.59860 - 7.36411 7.14979 6.95688 6.78310 6.62236 6.47085 - 6.33021 6.20213 6.08475 5.97371 5.86693 5.77178 - 5.69021 5.64948 5.60737 5.57247 5.53734 5.53255 - 5.53676 5.53734 5.53629 5.53619 5.53622 5.52758 - 9.67413 9.30306 8.94074 8.59756 8.27277 7.96568 - 7.67593 7.40376 7.14954 6.91320 6.69417 6.49153 - 6.30427 6.13243 5.97727 5.83882 5.71503 5.59411 - 5.46532 5.40101 5.34371 5.30520 5.26242 5.25022 - 5.24053 5.23937 5.23828 5.23814 5.23802 5.23074 - 10.19571 9.75270 9.31598 8.89644 8.49460 8.11212 - 7.75115 7.41516 7.10823 6.83014 6.57941 6.35431 - 6.15238 5.97056 5.80429 5.64095 5.47251 5.31051 - 5.16801 5.10419 5.04270 4.99548 4.94703 4.93088 - 4.90766 4.90393 4.90305 4.90329 4.90204 4.90120 - 10.89102 10.25095 9.65283 9.09971 8.58780 8.11571 - 7.68289 7.28799 6.93032 6.60760 6.31662 6.05357 - 5.81316 5.59092 5.38450 5.18858 4.99789 4.81501 - 4.64574 4.56828 4.49431 4.43821 4.37960 4.36026 - 4.33424 4.33028 4.32920 4.32922 4.32787 4.33460 - 11.27659 10.50398 9.80058 9.16016 8.57655 8.04560 - 7.56501 7.13092 6.73954 6.38716 6.06955 5.78158 - 5.51629 5.26881 5.03934 4.82813 4.63217 4.43978 - 4.24294 4.14740 4.06239 4.00419 3.93697 3.91616 - 3.89711 3.89490 3.89363 3.89336 3.89277 3.90029 - 11.48686 10.61881 9.84662 9.15309 8.52967 7.96875 - 7.46466 7.01020 6.59821 6.22432 5.88480 5.57539 - 5.29044 5.02555 4.77927 4.54870 4.33147 4.12510 - 3.92935 3.83553 3.74146 3.66628 3.59250 3.57456 - 3.56012 3.55847 3.55709 3.55684 3.55689 3.56210 - 11.62581 10.68886 9.86723 9.13420 8.48020 7.89563 - 7.37247 6.90166 6.47445 6.08600 5.73252 5.40979 - 5.11236 4.83593 4.57881 4.33784 4.11047 3.89411 - 3.68726 3.58706 3.48576 3.40425 3.32534 3.30721 - 3.29492 3.29369 3.29231 3.29215 3.29273 3.29495 - 11.76873 10.74504 9.86370 9.08218 8.38995 7.77576 - 7.22825 6.73639 6.29007 5.88397 5.51405 5.17583 - 4.86372 4.57324 4.30219 4.04684 3.80387 3.57104 - 3.34535 3.23453 3.12230 3.03184 2.94334 2.92265 - 2.90960 2.90844 2.90704 2.90703 2.90809 2.90590 - 11.82103 10.75002 9.83805 9.03106 8.31836 7.68756 - 7.12601 6.62200 6.16514 5.74984 5.37176 5.02603 - 4.70667 4.40882 4.12979 3.86523 3.61112 3.36489 - 3.12343 3.00362 2.88245 2.78473 2.68678 2.66244 - 2.64582 2.64424 2.64272 2.64274 2.64374 2.63955 - 11.80393 10.69305 9.76098 8.93595 8.20859 7.56277 - 6.98691 6.46991 6.00223 5.57812 5.19272 4.84070 - 4.51550 4.21157 3.92521 3.65049 3.38127 3.11215 - 2.83778 2.69646 2.55031 2.43008 2.31011 2.27995 - 2.25593 2.25308 2.25058 2.25023 2.24994 2.24731 - 11.72019 10.61469 9.69539 8.87927 8.15779 7.51324 - 6.93607 6.41672 5.94708 5.52160 5.13542 4.78315 - 4.45831 4.15507 3.86887 3.59226 3.31684 3.03335 - 2.73099 2.56896 2.39541 2.24871 2.10768 2.07494 - 2.04700 2.04318 2.03932 2.03833 2.03641 2.03990 - 11.53700 10.47180 9.59857 8.81939 8.12259 7.49354 - 6.92550 6.41186 5.94694 5.52595 5.14427 4.79688 - 4.47769 4.18069 3.90002 3.62564 3.34497 3.04117 - 2.69337 2.49625 2.27824 2.08652 1.89701 1.85755 - 1.82717 1.82276 1.81586 1.81336 1.80977 1.82957 - 11.38569 10.36217 9.53466 8.79253 8.12141 7.51064 - 6.95558 6.45185 5.99571 5.58293 5.20904 4.86913 - 4.55720 4.26705 3.99211 3.72078 3.43776 3.12086 - 2.74090 2.51647 2.26016 2.02859 1.79486 1.74642 - 1.71359 1.70923 1.70043 1.69687 1.69266 1.72553 - 11.27066 10.28067 9.49203 8.78095 8.13254 7.53894 - 6.99712 6.50428 6.05812 5.65476 5.28977 4.95818 - 4.65375 4.37003 4.10007 3.83142 3.54700 3.22077 - 2.81682 2.57086 2.28204 2.01568 1.73978 1.68142 - 1.64586 1.64174 1.63168 1.62744 1.62320 1.66392 - 11.18143 10.21830 9.46261 8.77714 8.14854 7.57044 - 7.04115 6.55902 6.12283 5.72898 5.37298 5.04970 - 4.75259 4.47488 4.20943 3.94330 3.65822 3.32529 - 2.90284 2.63933 2.32277 2.02516 1.70951 1.64084 - 1.60184 1.59793 1.58700 1.58232 1.57833 1.62359 - 11.05213 10.12994 9.42613 8.78070 8.18450 7.63280 - 7.12562 6.66293 6.24513 5.86887 5.52957 5.22176 - 4.93819 4.67146 4.41428 4.15334 3.86878 3.52787 - 3.07957 2.78921 2.42757 2.07608 1.68756 1.59800 - 1.54998 1.54614 1.53409 1.52896 1.52579 1.57473 - 10.96447 10.07209 9.40630 8.79083 8.21976 7.68929 - 7.20047 6.75434 6.35223 5.99105 5.66614 5.37175 - 5.10000 4.84302 4.59353 4.33803 4.05592 3.71201 - 3.24802 2.93871 2.54245 2.14625 1.69197 1.58162 - 1.52224 1.51801 1.50535 1.50011 1.49786 1.54651 - 10.84034 9.99583 9.38893 8.82302 8.29478 7.80207 - 7.34693 6.93166 6.55875 6.22550 5.92729 5.65812 - 5.40928 5.17224 4.93994 4.69898 4.42809 4.08937 - 3.61203 3.27617 2.82184 2.34264 1.75143 1.59300 - 1.49065 1.48338 1.47481 1.47115 1.46928 1.50969 - 10.78166 9.96322 9.38957 8.85358 8.35236 7.88460 - 7.45252 7.05874 6.70606 6.39207 6.11235 5.86090 - 5.62875 5.40720 5.18945 4.96240 4.70500 4.37930 - 3.90760 3.56238 3.07547 2.53792 1.82978 1.62798 - 1.48516 1.47338 1.46492 1.46202 1.45937 1.49172 - 10.73802 9.94242 9.40382 8.90121 8.43221 7.99588 - 7.59399 7.22880 6.90287 6.61412 6.35866 6.13090 - 5.92219 5.72409 5.53032 5.32836 5.09809 4.80311 - 4.35938 4.01542 3.49957 2.88836 1.99673 1.71941 - 1.49598 1.47279 1.46068 1.45855 1.45384 1.47443 - 10.73618 9.94507 9.42047 8.93348 8.48175 8.06394 - 7.68097 7.33412 7.02501 6.75198 6.51195 6.30047 - 6.11033 5.93368 5.76249 5.58020 5.36456 5.08588 - 4.67014 4.34811 3.85580 3.22011 2.14722 1.80180 - 1.51953 1.48489 1.45925 1.45606 1.45392 1.46589 - 10.73878 9.95028 9.43384 8.95691 8.51696 8.11223 - 7.74277 7.40898 7.11145 6.84877 6.61851 6.41705 - 6.23833 6.07558 5.92132 5.75933 5.56720 5.31344 - 4.92191 4.61131 4.12722 3.48027 2.30816 1.89398 - 1.53788 1.49291 1.46069 1.45585 1.45381 1.46081 - 10.74228 9.95648 9.44509 8.97489 8.54306 8.14752 - 7.78772 7.46335 7.17430 6.91926 6.69630 6.50248 - 6.33270 6.18107 6.04066 5.89588 5.72437 5.49316 - 5.12468 4.82613 4.35348 3.70453 2.45874 1.98410 - 1.55675 1.50114 1.46211 1.45581 1.45348 1.45748 - 10.74491 9.96820 9.46372 9.00101 8.57807 8.19346 - 7.84602 7.53448 7.25764 7.01418 6.80245 6.62019 - 6.46382 6.32883 6.20890 6.08877 5.94749 5.75654 - 5.44169 5.17117 4.71507 4.05416 2.71495 2.16576 - 1.60244 1.51968 1.46122 1.45533 1.44524 1.45337 - 10.75601 9.97914 9.47574 9.01700 8.59966 8.22135 - 7.88070 7.57647 7.30735 7.07214 6.86916 6.69577 - 6.54706 6.41898 6.31026 6.21582 6.11854 5.96590 - 5.66239 5.39960 4.98010 4.36335 2.96214 2.32289 - 1.63194 1.53078 1.46406 1.45622 1.44979 1.45090 - 10.73220 9.97917 9.48957 9.04255 8.63544 8.26636 - 7.93421 7.63802 7.37699 7.15057 6.95817 6.79848 - 6.66881 6.56630 6.48806 6.42431 6.35714 6.24968 - 6.02447 5.81275 5.44565 4.88171 3.46232 2.67515 - 1.71816 1.57114 1.46789 1.45476 1.44522 1.44762 - 10.71406 9.98187 9.49829 9.05602 8.65284 8.28734 - 7.95873 7.66649 7.41035 7.18993 7.00480 6.85378 - 6.73429 6.64394 6.58091 6.53724 6.49725 6.42642 - 6.25189 6.07382 5.74950 5.23389 3.84144 2.97696 - 1.80497 1.61395 1.47260 1.45644 1.44216 1.44601 - 10.68985 9.99107 9.50693 9.06575 8.66531 8.30403 - 7.98092 7.69511 7.44609 7.23339 7.05643 6.91390 - 6.80280 6.72158 6.67230 6.65477 6.65894 6.64129 - 6.52449 6.38891 6.13749 5.69970 4.36932 3.46843 - 1.97759 1.70640 1.48639 1.46368 1.43934 1.44440 - 10.66048 9.99402 9.51146 9.07192 8.67330 8.31415 - 7.99346 7.71048 7.46468 7.25569 7.08302 6.94543 - 6.84011 6.76578 6.72534 6.71997 6.74232 6.75437 - 6.68621 6.58350 6.37100 5.98552 4.76255 3.83955 - 2.13745 1.80221 1.50448 1.47132 1.43940 1.44359 - 10.61916 9.98825 9.51481 9.08097 8.68525 8.32695 - 8.00578 7.72186 7.47567 7.26725 7.09653 6.96302 - 6.86496 6.80096 6.77072 6.76807 6.78390 6.80426 - 6.78779 6.72360 6.54008 6.18125 5.05744 4.14209 - 2.28863 1.89391 1.52224 1.48104 1.44059 1.44311 - 10.60359 9.98906 9.51653 9.08362 8.68891 8.33170 - 8.01169 7.72899 7.48409 7.27708 7.10795 6.97636 - 6.88073 6.81987 6.79366 6.79614 6.81922 6.85251 - 6.86111 6.81731 6.66267 6.33761 5.28206 4.38828 - 2.43399 1.98521 1.54105 1.48950 1.44133 1.44279 - 10.58390 9.98996 9.51857 9.08690 8.69362 8.33799 - 8.01968 7.73872 7.49553 7.29028 7.12306 6.99373 - 6.90093 6.84386 6.82269 6.83203 6.86521 6.91550 - 6.95654 6.94135 6.83244 6.56391 5.61478 4.76812 - 2.70458 2.15968 1.57913 1.50596 1.44323 1.44237 - 10.57149 9.99183 9.52089 9.08891 8.69537 8.34011 - 8.02288 7.74370 7.50284 7.29995 7.13437 7.00564 - 6.91334 6.85753 6.83887 6.85291 6.89425 6.95805 - 7.01675 7.01347 6.93559 6.73288 5.88853 5.01854 - 2.93238 2.33503 1.62261 1.50741 1.45779 1.44212 - 10.55130 9.99294 9.52319 9.09180 8.69893 8.34494 - 8.02939 7.75199 7.51266 7.31109 7.14685 7.01972 - 6.92970 6.87725 6.86313 6.88288 6.93199 7.00921 - 7.09950 7.12795 7.09870 6.95345 6.27217 5.55278 - 3.41807 2.67360 1.71919 1.55555 1.46927 1.44179 - 10.54004 9.99328 9.52415 9.09326 8.70087 8.34735 - 8.03231 7.75548 7.51682 7.31602 7.15269 7.02667 - 6.93806 6.88744 6.87570 6.89849 6.95169 7.03554 - 7.14163 7.18690 7.18494 7.07458 6.50839 5.91054 - 3.79948 2.95641 1.81193 1.60716 1.47881 1.44162 - 10.52806 9.99340 9.52507 9.09498 8.70320 8.34996 - 8.03496 7.75811 7.51959 7.31944 7.15767 7.03409 - 6.94763 6.89815 6.88747 6.91337 6.97352 7.06644 - 7.17970 7.23405 7.27445 7.23922 6.78102 6.28505 - 4.40891 3.44695 1.98171 1.69907 1.48912 1.44145 - 10.52257 9.99337 9.52500 9.09520 8.70382 8.35091 - 8.03628 7.75992 7.52209 7.32258 7.16090 7.03690 - 6.95071 6.90297 6.89481 6.92229 6.98205 7.07623 - 7.20554 7.27570 7.31731 7.27305 6.96021 6.64251 - 4.77629 3.75614 2.14854 1.81439 1.51169 1.44137 - 10.53666 9.99936 9.52428 9.09160 8.69983 8.34780 - 8.03471 7.75998 7.52333 7.32469 7.16391 7.04038 - 6.95195 6.89864 6.88583 6.91927 7.00029 7.10908 - 7.22078 7.27804 7.33639 7.35273 7.08527 6.71225 - 5.11462 4.11251 2.30383 1.88547 1.52924 1.44133 - 10.53361 9.99932 9.52448 9.09198 8.70037 8.34849 - 8.03552 7.76090 7.52437 7.32585 7.16522 7.04186 - 6.95368 6.90071 6.88836 6.92247 7.00448 7.11485 - 7.22964 7.29016 7.35531 7.38463 7.16578 6.83938 - 5.35012 4.35540 2.45158 1.97918 1.54871 1.44131 - 10.51193 9.99379 9.52601 9.09652 8.70545 8.35303 - 8.03896 7.76305 7.52544 7.32621 7.16545 7.04306 - 6.95819 6.91091 6.90318 6.93306 6.99891 7.10165 - 7.23670 7.31157 7.38431 7.42242 7.27488 7.00481 - 5.68830 4.73339 2.71813 2.16278 1.58699 1.44130 - 10.50918 9.99406 9.52664 9.09714 8.70587 8.35328 - 8.03904 7.76304 7.52547 7.32640 7.16597 7.04401 - 6.95958 6.91266 6.90528 6.93563 7.00228 7.10625 - 7.24273 7.31934 7.39917 7.44833 7.33300 7.10744 - 5.91601 5.01176 2.95362 2.33498 1.62217 1.44130 - 0.46680 0.49015 0.51446 0.53984 0.56630 0.59384 - 0.62242 0.65202 0.68260 0.71406 0.74635 0.77944 - 0.81337 0.84811 0.88324 0.91816 0.95209 0.98446 - 1.01375 1.02619 1.03700 1.04449 1.05422 1.05783 - 1.06161 1.06200 1.06199 1.06199 1.06197 1.06198 - 0.68721 0.71635 0.74718 0.77994 0.81468 0.85136 - 0.88985 0.92985 0.97092 1.01277 1.05510 1.09761 - 1.13995 1.18192 1.22382 1.26710 1.31255 1.35636 - 1.39099 1.40298 1.41473 1.42628 1.44481 1.45016 - 1.45587 1.45683 1.45716 1.45706 1.45717 1.45752 - 0.89465 0.93112 0.96940 1.00979 1.05230 1.09685 - 1.14323 1.19103 1.23966 1.28880 1.33805 1.38710 - 1.43564 1.48356 1.53110 1.57980 1.63046 1.67925 - 1.71921 1.73448 1.74986 1.76435 1.78494 1.79069 - 1.79703 1.79810 1.79844 1.79832 1.79844 1.79888 - 1.27265 1.32562 1.37942 1.43442 1.49048 1.54736 - 1.60483 1.66259 1.72034 1.77781 1.83472 1.89098 - 1.94691 2.00268 2.05761 2.11088 2.16201 2.21251 - 2.26344 2.28800 2.31089 2.32768 2.34734 2.35316 - 2.35794 2.35849 2.35886 2.35886 2.35888 2.35914 - 1.61205 1.68071 1.74821 1.81490 1.88046 1.94470 - 2.00757 2.06941 2.13081 2.19174 2.25201 2.31150 - 2.37061 2.42945 2.48709 2.54215 2.59383 2.64471 - 2.69787 2.72530 2.75347 2.77502 2.79226 2.79758 - 2.79968 2.79972 2.80025 2.80034 2.80039 2.80023 - 1.91603 2.00016 2.08033 2.15685 2.22928 2.29751 - 2.36199 2.42402 2.48557 2.54696 2.60803 2.66850 - 2.72837 2.78738 2.84438 2.89767 2.94663 2.99595 - 3.05157 3.08204 3.11351 3.13660 3.15176 3.15727 - 3.15688 3.15640 3.15711 3.15723 3.15737 3.15683 - 2.19240 2.28977 2.38036 2.46443 2.54144 2.61140 - 2.67525 2.73530 2.79484 2.85455 2.91430 2.97365 - 3.03234 3.08980 3.14477 3.19544 3.24137 3.28853 - 3.34463 3.37650 3.40955 3.43332 3.44743 3.45298 - 3.45091 3.45011 3.45094 3.45109 3.45129 3.45050 - 2.67868 2.79533 2.90009 2.99318 3.07396 3.14277 - 3.20146 3.25398 3.30587 3.35837 3.41142 3.46452 - 3.51714 3.56853 3.61751 3.66239 3.70297 3.74560 - 3.79854 3.82945 3.86167 3.88518 3.90032 3.90565 - 3.90283 3.90195 3.90284 3.90298 3.90323 3.90237 - 3.09631 3.22425 3.33606 3.43209 3.51171 3.57562 - 3.62635 3.66914 3.71105 3.75378 3.79738 3.84148 - 3.88559 3.92912 3.97118 4.01042 4.04667 4.08498 - 4.13188 4.15905 4.18754 4.20958 4.22797 4.23286 - 4.23141 4.23090 4.23168 4.23178 4.23202 4.23149 - 3.93740 4.07239 4.18365 4.27231 4.33812 4.38249 - 4.40926 4.42555 4.44063 4.45680 4.47456 4.49406 - 4.51536 4.53859 4.56354 4.58942 4.61564 4.64309 - 4.67292 4.68891 4.70605 4.72287 4.74819 4.75179 - 4.75507 4.75571 4.75612 4.75608 4.75622 4.75710 - 4.58829 4.71394 4.81124 4.88246 4.92782 4.94938 - 4.95174 4.94293 4.93312 4.92506 4.91946 4.91695 - 4.91816 4.92369 4.93353 4.94668 4.96181 4.97783 - 4.99341 5.00105 5.00958 5.02121 5.04710 5.04955 - 5.05523 5.05645 5.05660 5.05650 5.05657 5.05891 - 5.55182 5.66611 5.72422 5.73888 5.72408 5.69531 - 5.65730 5.61372 5.56893 5.52528 5.48461 5.44833 - 5.41720 5.39174 5.37256 5.35971 5.35301 5.35143 - 5.34843 5.34336 5.34111 5.34549 5.35946 5.36263 - 5.36663 5.36755 5.36798 5.36780 5.36771 5.37179 - 6.28094 6.32919 6.34257 6.32771 6.28651 6.22267 - 6.14229 6.05466 5.97044 5.89304 5.82335 5.76178 - 5.70934 5.66594 5.63072 5.60014 5.57117 5.54566 - 5.52618 5.51844 5.50961 5.50358 5.50720 5.50686 - 5.51104 5.51197 5.51173 5.51164 5.51161 5.51536 - 6.84970 6.86037 6.83475 6.78116 6.70218 6.60218 - 6.48790 6.36913 6.25712 6.15509 6.06372 5.98271 - 5.91215 5.85112 5.79846 5.75038 5.70402 5.66265 - 5.63043 5.61711 5.60121 5.58713 5.58054 5.57945 - 5.58346 5.58426 5.58383 5.58379 5.58375 5.58569 - 7.30412 7.31550 7.25850 7.15420 7.02179 6.88124 - 6.73941 6.60190 6.47500 6.35941 6.25329 6.15488 - 6.06511 5.98431 5.91222 5.84733 5.78878 5.73885 - 5.69578 5.67329 5.64946 5.63039 5.61532 5.61331 - 5.61811 5.61897 5.61841 5.61823 5.61835 5.61759 - 8.02999 8.00199 7.88481 7.70990 7.50784 7.30850 - 7.11845 6.94008 6.77635 6.62747 6.49140 6.36595 - 6.25000 6.14292 6.04468 5.95515 5.87425 5.80205 - 5.73639 5.70369 5.66869 5.63874 5.61112 5.60861 - 5.61372 5.61448 5.61377 5.61359 5.61394 5.60813 - 8.57534 8.51125 8.34104 8.10479 7.84235 7.59140 - 7.35891 7.14632 6.95490 6.78269 6.62414 6.47522 - 6.33616 6.20782 6.08972 5.98061 5.87979 5.78829 - 5.70568 5.66532 5.62091 5.58227 5.54879 5.54413 - 5.54765 5.54820 5.54719 5.54706 5.54716 5.53873 - 9.66061 9.29234 8.93268 8.59200 8.26950 7.96460 - 7.67687 7.40661 7.15418 6.91952 6.70207 6.50096 - 6.31513 6.14467 5.99083 5.85364 5.73103 5.61119 - 5.48330 5.41947 5.36284 5.32509 5.28314 5.27132 - 5.26268 5.26170 5.26059 5.26043 5.26031 5.25267 - 10.18518 9.74590 9.31248 8.89581 8.49646 8.11609 - 7.75696 7.42251 7.11691 6.84005 6.59054 6.36687 - 6.16683 5.98730 5.82295 5.65949 5.48824 5.32417 - 5.18363 5.12243 5.06549 5.02284 4.97524 4.95921 - 4.93844 4.93520 4.93427 4.93440 4.93324 4.93135 - 10.91851 10.26218 9.65411 9.09625 8.58381 8.11435 - 7.68612 7.29649 6.94341 6.62423 6.33552 6.07316 - 5.83130 5.60594 5.39770 5.20694 5.02994 4.85484 - 4.67364 4.58741 4.51713 4.47565 4.41996 4.39730 - 4.37357 4.37072 4.36959 4.36929 4.36840 4.37360 - 11.27153 10.50328 9.80347 9.16619 8.58533 8.05685 - 7.57842 7.14626 6.75662 6.40583 6.08972 5.80318 - 5.53929 5.29320 5.06513 4.85538 4.66093 4.47015 - 4.27529 4.18143 4.09951 4.04484 3.97910 3.95767 - 3.93944 3.93746 3.93611 3.93580 3.93517 3.94217 - 11.47946 10.61801 9.85061 9.16078 8.54016 7.98135 - 7.47896 7.02602 6.61559 6.24338 5.90569 5.59822 - 5.31531 5.05254 4.80838 4.57981 4.36436 4.15977 - 3.96614 3.87370 3.78144 3.70795 3.63496 3.61680 - 3.60175 3.59999 3.59864 3.59841 3.59845 3.60402 - 11.61712 10.68726 9.87090 9.14170 8.49051 7.90804 - 7.38652 6.91725 6.49172 6.10517 5.75377 5.43327 - 5.13814 4.86406 4.60925 4.37050 4.14518 3.93076 - 3.72580 3.62653 3.52614 3.44530 3.36667 3.34822 - 3.33464 3.33318 3.33185 3.33174 3.33232 3.33556 - 11.75719 10.74140 9.86565 9.08811 8.39873 7.78660 - 7.24068 6.75030 6.30569 5.90156 5.53382 5.19793 - 4.88826 4.60025 4.33169 4.07886 3.83832 3.60766 - 3.38349 3.27295 3.16035 3.06913 2.98029 2.95934 - 2.94489 2.94344 2.94212 2.94218 2.94326 2.94231 - 11.80731 10.74426 9.83779 9.03480 8.32496 7.69620 - 7.13622 6.63362 6.17828 5.76469 5.38849 5.04483 - 4.72771 4.43226 4.15584 3.89407 3.64282 3.39905 - 3.15894 3.03902 2.91668 2.81733 2.71884 2.69452 - 2.67711 2.67533 2.67387 2.67395 2.67498 2.67148 - 11.78660 10.68268 9.75543 8.93401 8.20933 7.56548 - 6.99118 6.47548 6.00905 5.58620 5.20218 4.85170 - 4.52831 4.22653 3.94265 3.67056 3.40397 3.13694 - 2.86350 2.72201 2.57512 2.45396 2.33379 2.30384 - 2.28010 2.27728 2.27477 2.27442 2.27412 2.27112 - 11.70111 10.60109 9.68555 8.87234 8.15314 7.51043 - 6.93481 6.41686 5.94855 5.52442 5.13965 4.78892 - 4.46580 4.16446 3.88023 3.60528 3.33097 3.04811 - 2.74614 2.58466 2.41264 2.26777 2.12718 2.09428 - 2.06682 2.06313 2.05921 2.05814 2.05615 2.05960 - 11.52879 10.46345 9.58866 8.80780 8.10954 7.47956 - 6.91147 6.39894 5.93658 5.51911 5.14110 4.79641 - 4.47748 4.17815 3.89512 3.62304 3.35058 3.05150 - 2.69770 2.49645 2.27973 2.09463 1.91362 1.87544 - 1.84180 1.83663 1.83092 1.82911 1.82422 1.84788 - 11.39391 10.35285 9.51382 8.76598 8.09372 7.48523 - 6.93469 6.43649 5.98570 5.57752 5.20693 4.86826 - 4.55431 4.25902 3.97865 3.70687 3.43028 3.11807 - 2.73450 2.50779 2.25435 2.03104 1.81013 1.76294 - 1.72602 1.72050 1.71318 1.71083 1.70412 1.74471 - 11.25420 10.26191 9.47087 8.75847 8.10984 7.51694 - 6.97666 6.48608 6.04279 5.64266 5.28098 4.95234 - 4.64993 4.36663 4.09475 3.82070 3.52768 3.19443 - 2.79150 2.55170 2.27552 2.02286 1.75388 1.69394 - 1.65734 1.65346 1.64348 1.63888 1.63431 1.68355 - 11.16744 10.20003 9.44024 8.75236 8.12291 7.54529 - 7.01759 6.53797 6.10505 5.71488 5.36261 5.04262 - 4.74762 4.46999 4.20178 3.92869 3.63280 3.29094 - 2.86940 2.61326 2.31201 2.03088 1.72350 1.65307 - 1.61280 1.60913 1.59831 1.59325 1.58892 1.64335 - 11.04247 10.11274 9.40245 8.75303 8.15505 7.60348 - 7.09799 6.63823 6.22422 5.85224 5.51729 5.21322 - 4.93183 4.66470 4.40353 4.13336 3.83485 3.48224 - 3.03455 2.75335 2.41093 2.07994 1.70163 1.61015 - 1.56067 1.55708 1.54522 1.53971 1.53618 1.59436 - 10.95750 10.05564 9.38187 8.76145 8.18807 7.65757 - 7.17055 6.72757 6.32952 5.97292 5.65260 5.36213 - 5.09257 4.83494 4.58081 4.31499 4.01727 3.65997 - 3.19582 2.89621 2.52092 2.14806 1.70876 1.59649 - 1.53053 1.52649 1.51709 1.51225 1.50971 1.56589 - 10.83463 9.97941 9.36350 8.79196 8.26102 7.76811 - 7.31478 6.90278 6.53408 6.20556 5.91208 5.64686 - 5.40002 5.16179 4.92400 4.67163 4.38411 4.03183 - 3.55609 3.23157 2.79981 2.34384 1.76469 1.60559 - 1.50241 1.49546 1.48742 1.48347 1.48071 1.52845 - 10.78358 9.94829 9.36209 8.81907 8.31530 7.84838 - 7.41926 7.02915 6.67953 6.36809 6.09106 5.84337 - 5.61737 5.40337 5.18797 4.94548 4.65167 4.29862 - 3.84342 3.52768 3.07999 2.55466 1.81548 1.63977 - 1.50679 1.48965 1.47592 1.47538 1.47006 1.51002 - 10.72106 9.91987 9.37578 8.86988 8.39953 7.96349 - 7.56321 7.20061 6.87781 6.59251 6.34038 6.11535 - 5.90791 5.70877 5.51105 5.30146 5.06071 4.75851 - 4.31940 3.98497 3.48511 2.88949 2.00731 1.73089 - 1.50946 1.48702 1.47578 1.47363 1.46869 1.49215 - 10.70399 9.91493 9.39020 8.90342 8.45227 8.03547 - 7.65395 7.30906 7.00241 6.73202 6.49425 6.28378 - 6.09207 5.91077 5.73372 5.54846 5.33639 5.06705 - 4.66040 4.33521 3.82569 3.18591 2.16799 1.82730 - 1.52952 1.49446 1.47636 1.47424 1.46726 1.48328 - 10.69819 9.91648 9.40296 8.92791 8.48911 8.08511 - 7.71636 7.38367 7.08809 6.82791 6.60003 6.39990 - 6.21994 6.05274 5.89270 5.72801 5.54055 5.29967 - 4.92330 4.61066 4.10357 3.43998 2.31928 1.92164 - 1.55165 1.50373 1.47712 1.47458 1.46582 1.47799 - 10.70411 9.92221 9.41234 8.94371 8.51345 8.11947 - 7.76115 7.43812 7.15016 6.89605 6.67391 6.48095 - 6.31228 6.16197 6.02248 5.87686 5.70259 5.47074 - 5.10829 4.81511 4.34766 3.70281 2.46415 1.99316 - 1.57118 1.51667 1.47864 1.47250 1.47028 1.47450 - 10.70070 9.92933 9.42877 8.97028 8.55084 8.16833 - 7.82178 7.51042 7.23349 6.98998 6.77853 6.59694 - 6.44118 6.30668 6.18802 6.07184 5.93708 5.74772 - 5.42361 5.14969 4.70409 4.06792 2.73489 2.16438 - 1.60819 1.53249 1.48083 1.47245 1.46911 1.47021 - 10.70105 9.93527 9.43898 8.98589 8.57288 8.19761 - 7.85874 7.55504 7.28527 7.04862 6.84422 6.67062 - 6.52481 6.40317 6.30091 6.20510 6.09549 5.93755 - 5.65061 5.39714 4.97555 4.35154 2.96585 2.32994 - 1.64507 1.54683 1.48045 1.47442 1.46419 1.46762 - 10.69095 9.94363 9.45664 9.01170 8.60620 8.23839 - 7.90725 7.61198 7.35190 7.12642 6.93485 6.77572 - 6.64611 6.54323 6.46502 6.40357 6.34173 6.23827 - 6.01113 5.79732 5.43112 4.87190 3.46180 2.67932 - 1.73035 1.58514 1.48398 1.47104 1.46179 1.46417 - 10.67718 9.94817 9.46562 9.02450 8.62256 8.25835 - 7.93105 7.64003 7.38502 7.16555 6.98116 6.83060 - 6.71119 6.62062 6.55768 6.51560 6.47915 6.41029 - 6.23285 6.05303 5.73099 5.22169 3.83874 2.97921 - 1.81592 1.62695 1.48820 1.47233 1.45843 1.46247 - 10.65308 9.95749 9.47464 9.03463 8.63530 8.27509 - 7.95295 7.66808 7.41990 7.20797 7.03174 6.88985 - 6.77935 6.69863 6.64977 6.63251 6.63666 6.61846 - 6.50076 6.36545 6.11651 5.68357 4.36301 3.46794 - 1.98668 1.71781 1.50131 1.47927 1.45536 1.46075 - 10.62336 9.95978 9.47856 9.04030 8.64289 8.28490 - 7.96529 7.68331 7.43845 7.23031 7.05836 6.92139 - 6.81653 6.74247 6.70207 6.69653 6.71847 6.73005 - 6.66184 6.55977 6.34926 5.96742 4.75361 3.83675 - 2.14503 1.81250 1.51899 1.48674 1.45537 1.45989 - 10.58029 9.95250 9.48077 9.04852 8.65430 8.29743 - 7.97762 7.69503 7.45017 7.24300 7.07335 6.94053 - 6.84247 6.77771 6.74638 6.74344 6.76004 6.77846 - 6.75543 6.69104 6.52058 6.18959 5.05634 4.09756 - 2.29787 1.91707 1.53897 1.48828 1.45572 1.45938 - 10.56479 9.95359 9.48305 9.05184 8.65863 8.30269 - 7.98377 7.70200 7.45788 7.25151 7.08294 6.95185 - 6.85675 6.79642 6.77047 6.77235 6.79387 6.82633 - 6.83695 6.79492 6.64111 6.31675 5.26934 4.38207 - 2.43920 1.99386 1.55492 1.50457 1.45725 1.45904 - 10.54492 9.95431 9.48501 9.05513 8.66336 8.30900 - 7.99174 7.71169 7.46927 7.26464 7.09798 6.96914 - 6.87683 6.82020 6.79922 6.80803 6.83987 6.88954 - 6.93243 6.91877 6.81032 6.54185 5.59947 4.75906 - 2.70802 2.16717 1.59244 1.52069 1.45901 1.45861 - 10.53266 9.95655 9.48767 9.05724 8.66497 8.31091 - 7.99478 7.71660 7.47659 7.27439 7.10938 6.98110 - 6.88917 6.83364 6.81508 6.82878 6.86934 6.93279 - 6.99245 6.98999 6.91265 6.71066 5.87147 5.00652 - 2.93454 2.34196 1.63543 1.52149 1.47351 1.45835 - 10.51388 9.95794 9.48983 9.05995 8.66845 8.31569 - 8.00127 7.72486 7.48637 7.28552 7.12184 6.99513 - 6.90540 6.85306 6.83896 6.85869 6.90773 6.98479 - 7.07480 7.10324 7.07443 6.93030 6.25243 5.53685 - 3.41732 2.67857 1.73092 1.56873 1.48483 1.45802 - 10.50325 9.95838 9.49075 9.06134 8.67031 8.31805 - 8.00414 7.72831 7.49047 7.29040 7.12760 7.00199 - 6.91364 6.86313 6.85140 6.87423 6.92751 7.01118 - 7.11656 7.16154 7.15998 7.05084 6.48719 5.89236 - 3.79643 2.95959 1.82268 1.61957 1.49422 1.45785 - 10.49129 9.95850 9.49171 9.06307 8.67263 8.32064 - 8.00676 7.73087 7.49314 7.29366 7.13244 7.00930 - 6.92313 6.87376 6.86303 6.88892 6.94917 7.04196 - 7.15443 7.20830 7.24890 7.21461 6.75829 6.26511 - 4.40238 3.44677 1.99078 1.71041 1.50402 1.45768 - 10.48547 9.95837 9.49166 9.06335 8.67329 8.32159 - 8.00804 7.73262 7.49561 7.29677 7.13564 7.01205 - 6.92613 6.87849 6.87034 6.89784 6.95771 7.05179 - 7.18042 7.25017 7.29177 7.24810 6.93686 6.62082 - 4.76717 3.75370 2.15626 1.82463 1.52648 1.45760 - 10.49911 9.96405 9.49077 9.05970 8.66936 8.31860 - 8.00659 7.73278 7.49692 7.29890 7.13863 7.01546 - 6.92731 6.87421 6.86153 6.89499 6.97596 7.08456 - 7.19597 7.25300 7.31108 7.32726 7.06121 6.69045 - 5.10357 4.10782 2.31030 1.89488 1.54358 1.45754 - 10.49599 9.96395 9.49093 9.06008 8.66993 8.31931 - 8.00744 7.73376 7.49800 7.30010 7.13995 7.01693 - 6.92902 6.87625 6.86404 6.89820 6.98020 7.09041 - 7.20495 7.26523 7.32994 7.35892 7.14135 6.81705 - 5.33747 4.34895 2.45690 1.98780 1.56278 1.45751 - 10.47444 9.95867 9.49270 9.06472 8.67494 8.32374 - 8.01076 7.73582 7.49902 7.30046 7.14024 7.01828 - 6.93367 6.88646 6.87863 6.90840 6.97421 7.07671 - 7.21132 7.28600 7.35837 7.39625 7.25014 6.98141 - 5.67304 4.72414 2.72156 2.16997 1.60051 1.45746 - 10.47292 9.95906 9.49309 9.06517 8.67538 8.32401 - 8.01082 7.73575 7.49903 7.30072 7.14073 7.01896 - 6.93473 6.88820 6.88112 6.91104 6.97618 7.07892 - 7.21550 7.29224 7.37246 7.42214 7.30753 7.08315 - 5.89887 5.00032 2.95542 2.34098 1.63514 1.45742 - 0.46008 0.48348 0.50783 0.53321 0.55963 0.58707 - 0.61550 0.64485 0.67508 0.70609 0.73779 0.77015 - 0.80324 0.83703 0.87115 0.90506 0.93819 0.97051 - 1.00100 1.01417 1.02476 1.03145 1.04351 1.04877 - 1.05117 1.05124 1.05169 1.05176 1.05183 1.05235 - 0.67583 0.70717 0.73960 0.77330 0.80826 0.84447 - 0.88185 0.92035 0.95988 1.00034 1.04159 1.08357 - 1.12633 1.16978 1.21339 1.25639 1.29790 1.33757 - 1.37418 1.39040 1.40554 1.41743 1.43440 1.44082 - 1.44635 1.44653 1.44651 1.44691 1.44662 1.42836 - 0.88098 0.91997 0.96006 1.00150 1.04423 1.08819 - 1.13327 1.17934 1.22625 1.27387 1.32201 1.37058 - 1.41970 1.46933 1.51886 1.56746 1.61424 1.65918 - 1.70155 1.72097 1.73970 1.75474 1.77447 1.78121 - 1.78710 1.78735 1.78737 1.78778 1.78749 1.76839 - 1.25924 1.31199 1.36556 1.42031 1.47606 1.53261 - 1.58971 1.64706 1.70434 1.76128 1.81761 1.87325 - 1.92855 1.98371 2.03811 2.09100 2.14209 2.19327 - 2.24614 2.27219 2.29660 2.31452 2.33534 2.34137 - 2.34602 2.34645 2.34679 2.34690 2.34687 2.34301 - 1.59614 1.66464 1.73187 1.79814 1.86320 1.92683 - 1.98907 2.05032 2.11127 2.17191 2.23194 2.29110 - 2.34942 2.40689 2.46310 2.51805 2.57200 2.62593 - 2.68066 2.70811 2.73615 2.75844 2.77812 2.78178 - 2.78579 2.78666 2.78710 2.78682 2.78706 2.79984 - 1.89816 1.98189 2.06164 2.13769 2.20960 2.27730 - 2.34123 2.40273 2.46385 2.52486 2.58553 2.64542 - 2.70429 2.76182 2.81756 2.87152 2.92418 2.97762 - 3.03411 3.06350 3.09376 3.11743 3.13577 3.13797 - 3.14127 3.14237 3.14289 3.14234 3.14280 3.16784 - 2.19042 2.27066 2.34952 2.42765 2.50447 2.57933 - 2.65157 2.72048 2.78542 2.84598 2.90224 2.95479 - 3.00586 3.05742 3.10940 3.16164 3.21429 3.26904 - 3.32768 3.35834 3.38951 3.41338 3.43008 3.43039 - 3.43393 3.43541 3.43582 3.43505 3.43569 3.46733 - 2.65644 2.77246 2.87671 2.96938 3.04982 3.11834 - 3.17675 3.22893 3.28033 3.33223 3.38466 3.43731 - 3.49000 3.54214 3.59231 3.63799 3.67858 3.72241 - 3.77942 3.81195 3.84175 3.86148 3.88015 3.88244 - 3.88452 3.88539 3.88620 3.88580 3.88605 3.91517 - 3.07217 3.19946 3.31078 3.40647 3.48590 3.54970 - 3.60040 3.64317 3.68498 3.72752 3.77096 3.81504 - 3.85955 3.90399 3.94728 3.98737 4.02377 4.06299 - 4.11283 4.14105 4.16749 4.18655 4.20778 4.21033 - 4.21269 4.21347 4.21415 4.21392 4.21418 4.22884 - 3.91047 4.04496 4.15596 4.24462 4.31063 4.35546 - 4.38287 4.39995 4.41592 4.43305 4.45181 4.47232 - 4.49456 4.51860 4.54425 4.57076 4.59754 4.62530 - 4.65493 4.67065 4.68760 4.70453 4.73038 4.73408 - 4.73752 4.73802 4.73832 4.73852 4.73870 4.71504 - 4.56017 4.68564 4.78304 4.85462 4.90061 4.92306 - 4.92658 4.91916 4.91092 4.90457 4.90073 4.89983 - 4.90220 4.90827 4.91821 4.93162 4.94748 4.96351 - 4.97725 4.98404 4.99368 5.00729 5.03226 5.03626 - 5.03999 5.04028 5.04032 5.04074 5.04085 4.99929 - 5.53602 5.62358 5.67912 5.70724 5.70906 5.68748 - 5.64789 5.59892 5.55076 5.50657 5.46699 5.43252 - 5.40373 5.38093 5.36425 5.35275 5.34503 5.33927 - 5.33395 5.33226 5.33287 5.33715 5.34973 5.35463 - 5.35650 5.35599 5.35648 5.35747 5.35674 5.32074 - 6.25571 6.30345 6.31702 6.30300 6.26328 6.20149 - 6.12365 6.03891 5.95777 5.88341 5.81647 5.75690 - 5.70498 5.66028 5.62282 5.59131 5.56421 5.54034 - 5.51915 5.51038 5.50350 5.50062 5.50253 5.50429 - 5.50515 5.50489 5.50505 5.50557 5.50524 5.48503 - 6.81371 6.85114 6.82983 6.76599 6.67384 6.56891 - 6.45796 6.34774 6.24572 6.15284 6.06726 5.98736 - 5.91461 5.84959 5.79257 5.74275 5.69937 5.66223 - 5.62814 5.61099 5.59764 5.59010 5.58008 5.58178 - 5.58179 5.58107 5.58091 5.58123 5.58109 5.57292 - 7.28012 7.29306 7.23736 7.13443 7.00397 6.86636 - 6.72794 6.59335 6.46800 6.35315 6.24833 6.15234 - 6.06482 5.98502 5.91311 5.84864 5.79103 5.73952 - 5.69305 5.67160 5.65121 5.63579 5.62080 5.61930 - 5.61964 5.61922 5.61859 5.61863 5.61878 5.61708 - 8.00631 7.98170 7.86835 7.69695 7.49722 7.29856 - 7.10841 6.93069 6.76972 6.62497 6.49222 6.36826 - 6.25305 6.14703 6.05025 5.96266 5.88330 5.80859 - 5.73804 5.70690 5.67705 5.65141 5.62144 5.62373 - 5.62123 5.61960 5.61925 5.61961 5.61945 5.62283 - 8.55500 8.49370 8.32652 8.09321 7.83343 7.58463 - 7.35388 7.14266 6.95234 6.78131 6.62450 6.47805 - 6.34143 6.21502 6.09864 5.99183 5.89342 5.80005 - 5.71176 5.67207 5.63331 5.60028 5.56345 5.56397 - 5.56001 5.55822 5.55773 5.55802 5.55781 5.56239 - 9.64430 9.28002 8.92387 8.58618 8.26622 7.96344 - 7.67745 7.40859 7.15725 6.92345 6.70675 6.50640 - 6.32157 6.15257 6.00063 5.86582 5.74593 5.62854 - 5.50212 5.43857 5.38208 5.34449 5.30345 5.29231 - 5.28475 5.28409 5.28305 5.28263 5.28256 5.28833 - 10.23483 9.75397 9.29502 8.86654 8.46660 8.09403 - 7.74780 7.42734 7.13261 6.86242 6.61504 6.38841 - 6.17945 5.98648 5.81093 5.65250 5.50857 5.36698 - 5.21768 5.14477 5.08274 5.04367 4.99587 4.97981 - 4.96772 4.96705 4.96625 4.96544 4.96512 4.97289 - 10.90739 10.25753 9.65454 9.10076 8.59146 8.12432 - 7.69770 7.30907 6.95649 6.63744 6.34865 6.08620 - 5.84455 5.62001 5.41331 5.22505 5.05188 4.88241 - 4.70831 4.62458 4.55268 4.50581 4.44658 4.42653 - 4.41275 4.41215 4.41115 4.41020 4.40958 4.41857 - 11.26267 10.50042 9.80561 9.17241 8.59487 8.06905 - 7.59273 7.16218 6.77381 6.42403 6.10876 5.82304 - 5.56016 5.31540 5.08911 4.88167 4.69028 4.50351 - 4.31349 4.22168 4.14012 4.08387 4.01623 3.99548 - 3.98216 3.98135 3.98005 3.97943 3.97894 3.98595 - 11.47059 10.61584 9.85365 9.16791 8.55049 7.99420 - 7.49384 7.04268 6.63398 6.26350 5.92756 5.62186 - 5.34072 5.07973 4.83742 4.61086 4.39769 4.19569 - 4.00498 3.91410 3.82325 3.75064 3.67779 3.65918 - 3.64453 3.64297 3.64171 3.64149 3.64157 3.64507 - 11.60936 10.68701 9.87548 9.14950 8.50033 7.91921 - 7.39887 6.93115 6.50809 6.12472 5.77691 5.45985 - 5.16724 4.89437 4.64024 4.40294 4.18054 3.96846 - 3.76370 3.66467 3.56676 3.48921 3.41060 3.39266 - 3.37622 3.37402 3.37287 3.37300 3.37353 3.37387 - 11.74821 10.73971 9.86870 9.09428 8.40688 7.79605 - 7.25131 6.76253 6.32038 5.91945 5.55533 5.22300 - 4.91613 4.62985 4.36249 4.11133 3.87328 3.64388 - 3.41839 3.30738 3.19692 3.10902 3.02134 3.00251 - 2.98263 2.97969 2.97862 2.97898 2.98007 2.97656 - 11.79676 10.74055 9.83858 9.03864 8.33084 7.70352 - 7.14476 6.64363 6.19038 5.77943 5.40625 5.06568 - 4.75138 4.45825 4.18384 3.92418 3.67502 3.43207 - 3.19060 3.06990 2.94837 2.85088 2.75484 2.73320 - 2.71086 2.70767 2.70638 2.70667 2.70779 2.70307 - 11.76735 10.67138 9.74958 8.93209 8.21018 7.56830 - 6.99546 6.48105 6.01598 5.59466 5.21231 4.86369 - 4.54237 4.24282 3.96126 3.69141 3.42671 3.16099 - 2.88798 2.74640 2.59936 2.47824 2.35916 2.32994 - 2.30576 2.30270 2.30013 2.29983 2.29947 2.29694 - 11.67703 10.58446 9.67409 8.86479 8.14849 7.50798 - 6.93409 6.41762 5.95077 5.52809 5.14477 4.79553 - 4.47392 4.17412 3.89147 3.61814 3.34551 3.06434 - 2.76428 2.60411 2.43400 2.29030 2.14586 2.11083 - 2.08659 2.08405 2.08015 2.07876 2.07696 2.08092 - 11.49758 10.43859 9.56847 8.79145 8.09638 7.46913 - 6.90330 6.39270 5.93195 5.51578 5.13884 4.79500 - 4.47673 4.17789 3.89528 3.62367 3.35205 3.05480 - 2.70551 2.50900 2.30035 2.12072 1.92450 1.87735 - 1.85472 1.85324 1.84699 1.84421 1.83933 1.86653 - 11.32934 10.31322 9.49014 8.75185 8.08428 7.47703 - 6.92560 6.42569 5.97370 5.56515 5.19522 4.85853 - 4.54830 4.25781 3.98037 3.70430 3.41578 3.09840 - 2.73007 2.51814 2.27994 2.06216 1.81622 1.75696 - 1.73422 1.73474 1.72711 1.72213 1.71811 1.76351 - 11.21336 10.22846 9.44212 8.73343 8.08776 7.49724 - 6.95891 6.47000 6.02820 5.62930 5.26843 4.93997 - 4.63675 4.35158 4.07729 3.80135 3.50864 3.18087 - 2.79171 2.56215 2.29719 2.04884 1.75807 1.68650 - 1.66302 1.66479 1.65621 1.65028 1.64633 1.70243 - 11.12426 10.16426 9.40927 8.72506 8.09841 7.52298 - 6.99698 6.51868 6.08684 5.69743 5.34548 5.02512 - 4.72878 4.44880 4.17779 3.90270 3.60752 3.27241 - 2.86695 2.62232 2.33297 2.05619 1.72819 1.64631 - 1.61417 1.61665 1.61168 1.60597 1.60010 1.66217 - 10.99643 10.07460 9.36906 8.72312 8.12766 7.57782 - 7.07343 6.61429 6.20058 5.82852 5.49298 5.18768 - 4.90416 4.63404 4.36965 4.09737 3.80011 3.45621 - 3.02851 2.76113 2.43216 2.10522 1.70451 1.60200 - 1.56009 1.56310 1.55882 1.55285 1.54664 1.61293 - 10.91005 10.01642 9.34739 8.73030 8.15915 7.62996 - 7.14353 6.70061 6.30226 5.94494 5.62340 5.33109 - 5.05888 4.79785 4.54026 4.27224 3.97611 3.62896 - 3.18785 2.90385 2.54301 2.17306 1.70808 1.58622 - 1.53196 1.53453 1.53084 1.52501 1.51877 1.58420 - 10.78705 9.93985 9.32831 8.75975 8.23064 7.73856 - 7.28526 6.87265 6.50283 6.17268 5.87708 5.60921 - 5.35922 5.11759 4.87671 4.62281 4.33767 3.99636 - 3.54450 3.23593 2.81850 2.36526 1.76371 1.59731 - 1.50583 1.50478 1.50180 1.49704 1.49124 1.54634 - 10.72703 9.90649 9.32846 8.78997 8.28796 7.82081 - 7.39043 6.99901 6.64895 6.33748 6.05973 5.80910 - 5.57565 5.34981 5.12434 4.88589 4.61623 4.28921 - 3.84222 3.52253 3.06919 2.55538 1.84199 1.63550 - 1.50366 1.49717 1.49343 1.48978 1.48431 1.52768 - 10.67783 9.88320 9.34231 8.83868 8.36978 7.93447 - 7.53426 7.17112 6.84725 6.56037 6.30627 6.07902 - 5.86931 5.66818 5.46916 5.25970 5.02189 4.72805 - 4.30522 3.98115 3.49003 2.89699 2.00903 1.73217 - 1.51942 1.50005 1.49138 1.48900 1.48308 1.50952 - 10.66303 9.87990 9.35789 8.87312 8.42337 8.00742 - 7.62623 7.28122 6.97404 6.70274 6.46377 6.25191 - 6.05884 5.87646 5.69888 5.51419 5.30469 5.04153 - 4.64628 4.32822 3.82479 3.18790 2.17116 1.83234 - 1.54170 1.50871 1.49240 1.49025 1.48292 1.50048 - 10.65894 9.88265 9.37149 8.89829 8.46085 8.05785 - 7.68969 7.35729 7.06171 6.80129 6.57295 6.37225 - 6.19173 6.02414 5.86411 5.70015 5.51475 5.27820 - 4.90940 4.60153 4.09884 3.43856 2.32347 1.92898 - 1.56506 1.51864 1.49344 1.49099 1.48219 1.49507 - 10.65797 9.88706 9.38276 8.91730 8.48840 8.09454 - 7.73579 7.41260 7.12555 6.87316 6.65285 6.46071 - 6.29009 6.13454 5.98903 5.84245 5.67742 5.46373 - 5.11931 4.82334 4.32846 3.65746 2.46531 2.02088 - 1.58816 1.52879 1.49412 1.49111 1.48108 1.49150 - 10.66111 9.90040 9.40215 8.94256 8.52142 8.13883 - 7.79375 7.48478 7.21047 6.96937 6.75958 6.57876 - 6.42343 6.28928 6.17044 6.05248 5.91508 5.72883 - 5.41871 5.15072 4.69782 4.04298 2.72346 2.18376 - 1.63086 1.55023 1.49453 1.48914 1.47923 1.48709 - 10.67472 9.90886 9.41074 8.95657 8.54316 8.16823 - 7.83043 7.52859 7.26147 7.02791 6.82637 6.65432 - 6.50715 6.38098 6.27463 6.18305 6.08907 5.93980 - 5.63924 5.37777 4.96010 4.34865 2.96824 2.33901 - 1.65952 1.56082 1.49720 1.48982 1.48376 1.48443 - 10.65373 9.91036 9.42490 8.98134 8.57717 8.21069 - 7.88099 7.58736 7.32921 7.10594 6.91674 6.75997 - 6.63239 6.53063 6.45148 6.38486 6.31408 6.20865 - 5.99810 5.79701 5.43542 4.85862 3.43301 2.68951 - 1.75252 1.60111 1.49774 1.48973 1.47137 1.48088 - 10.64081 9.91458 9.43294 8.99298 8.59240 8.22974 - 7.90410 7.61488 7.36171 7.14412 6.96166 6.81303 - 6.69550 6.60631 6.54292 6.49595 6.44982 6.37604 - 6.21123 6.04594 5.73939 5.22227 3.80147 2.97617 - 1.83891 1.64567 1.50179 1.48878 1.46722 1.47913 - 10.61562 9.92379 9.44269 9.00431 8.60642 8.24750 - 7.92652 7.64266 7.39537 7.18420 7.00861 6.86726 - 6.75722 6.67688 6.62829 6.61116 6.61519 6.59647 - 6.47834 6.34406 6.09914 5.67185 4.35637 3.46533 - 1.99556 1.72940 1.51645 1.49505 1.47162 1.47738 - 10.56974 9.92050 9.44778 9.01445 8.61920 8.26146 - 7.94094 7.65787 7.41264 7.20475 7.03315 6.89682 - 6.79440 6.72504 6.68889 6.68089 6.69032 6.69124 - 6.62393 6.52683 6.33740 5.99609 4.75672 3.75806 - 2.16675 1.85063 1.52995 1.48726 1.47401 1.47650 - 10.54402 9.91942 9.44939 9.01859 8.62566 8.26985 - 7.95093 7.66908 7.42478 7.21804 7.04865 6.91602 - 6.81804 6.75333 6.72203 6.71913 6.73587 6.75467 - 6.73246 6.66860 6.49867 6.16916 5.04465 4.09254 - 2.30434 1.92663 1.55333 1.50376 1.47185 1.47598 - 10.52879 9.92060 9.45172 9.02198 8.63005 8.27519 - 7.95716 7.67611 7.43249 7.22646 7.05806 6.92710 - 6.83211 6.77197 6.74618 6.74796 6.76907 6.80178 - 6.81410 6.77280 6.61821 6.29348 5.25637 4.37627 - 2.44451 2.00260 1.56902 1.51989 1.47349 1.47563 - 10.50924 9.92138 9.45372 9.02529 8.63479 8.28150 - 7.96514 7.68584 7.44401 7.23986 7.07354 6.94494 - 6.85281 6.79634 6.77536 6.78389 6.81518 6.86494 - 6.90937 6.89629 6.78663 6.51705 5.58403 4.75101 - 2.71158 2.17469 1.60597 1.53570 1.47511 1.47519 - 10.49652 9.92375 9.45674 9.02772 8.63657 8.28355 - 7.96833 7.69078 7.45107 7.24914 7.08482 6.95775 - 6.86676 6.81131 6.79216 6.80524 6.84518 6.90586 - 6.96668 6.97198 6.89927 6.67665 5.81481 5.03233 - 2.94688 2.33643 1.64685 1.54749 1.47816 1.47492 - 10.47864 9.92484 9.45828 9.02983 8.63962 8.28802 - 7.97463 7.69918 7.46164 7.26170 7.09877 6.97262 - 6.88318 6.83087 6.81653 6.83586 6.88450 6.96122 - 7.05100 7.07938 7.05075 6.90732 6.23267 5.52090 - 3.41658 2.68362 1.74289 1.58218 1.50068 1.47456 - 10.46813 9.92518 9.45906 9.03110 8.64143 8.29036 - 7.97749 7.70261 7.46570 7.26645 7.10438 6.97927 - 6.89122 6.84078 6.82891 6.85149 6.90451 6.98771 - 7.09248 7.13736 7.13628 7.02809 6.46598 5.87388 - 3.79333 2.96281 1.83365 1.63223 1.50992 1.47438 - 10.45630 9.92528 9.46000 9.03286 8.64380 8.29299 - 7.98013 7.70511 7.46812 7.26925 7.10852 6.98576 - 6.89985 6.85063 6.83997 6.86590 6.92617 7.01855 - 7.13012 7.18375 7.22480 7.19132 6.73559 6.24485 - 4.39581 3.44664 2.00001 1.72195 1.51918 1.47419 - 10.45044 9.92521 9.46007 9.03319 8.64445 8.29395 - 7.98141 7.70684 7.47051 7.27221 7.11148 6.98820 - 6.90252 6.85512 6.84717 6.87485 6.93475 7.02839 - 7.15611 7.22554 7.26722 7.22406 6.91374 6.59929 - 4.75820 3.75140 2.16410 1.83500 1.54148 1.47411 - 10.46402 9.93093 9.45925 9.02963 8.64058 8.29097 - 7.97996 7.70702 7.47188 7.27446 7.11465 6.99185 - 6.90398 6.85111 6.83857 6.87207 6.95292 7.06116 - 7.17189 7.22848 7.28624 7.30246 7.03779 6.66914 - 5.09260 4.10315 2.31681 1.90439 1.55815 1.47406 - 10.46103 9.93082 9.45940 9.02999 8.64112 8.29169 - 7.98083 7.70803 7.47303 7.27576 7.11613 6.99352 - 6.90590 6.85336 6.84127 6.87542 6.95723 7.06705 - 7.18087 7.24067 7.30493 7.33383 7.11780 6.79548 - 5.32493 4.34256 2.46232 1.99651 1.57705 1.47403 - 10.43963 9.92562 9.46119 9.03461 8.64608 8.29602 - 7.98405 7.71002 7.47404 7.27620 7.11657 6.99503 - 6.91068 6.86355 6.85567 6.88528 6.95086 7.05289 - 7.18690 7.26141 7.33335 7.37083 7.22597 6.95855 - 5.65775 4.71483 2.72500 2.17721 1.61421 1.47400 - 10.43813 9.92587 9.46142 9.03491 8.64646 8.29628 - 7.98414 7.70994 7.47394 7.27619 7.11666 6.99530 - 6.91137 6.86496 6.85770 6.88689 6.95091 7.05370 - 7.19130 7.26753 7.34730 7.39713 7.28250 7.05776 - 5.88156 4.98894 2.95723 2.34703 1.64830 1.47400 - 0.45431 0.47731 0.50130 0.52637 0.55255 0.57980 - 0.60808 0.63733 0.66745 0.69827 0.72963 0.76133 - 0.79313 0.82494 0.85691 0.89005 0.92501 0.95978 - 0.98975 1.00123 1.01141 1.01973 1.03342 1.03779 - 1.04073 1.04109 1.04145 1.04151 1.04151 1.04229 - 0.67053 0.69930 0.72976 0.76216 0.79653 0.83286 - 0.87102 0.91070 0.95147 0.99299 1.03488 1.07668 - 1.11780 1.15784 1.19728 1.23828 1.28243 1.32624 - 1.36226 1.37557 1.38973 1.40395 1.42443 1.43094 - 1.43571 1.43583 1.43599 1.43645 1.43627 1.41692 - 0.87428 0.91031 0.94814 0.98807 1.03011 1.07420 - 1.12014 1.16752 1.21581 1.26462 1.31350 1.36196 - 1.40946 1.45566 1.50099 1.54758 1.59700 1.64597 - 1.68798 1.70512 1.72358 1.74124 1.76379 1.77074 - 1.77609 1.77626 1.77641 1.77688 1.77669 1.75624 - 1.24600 1.29842 1.35167 1.40609 1.46151 1.51772 - 1.57447 1.63146 1.68836 1.74491 1.80083 1.85602 - 1.91083 1.96545 2.01929 2.07168 2.12250 2.17412 - 2.22878 2.25623 2.28198 2.30078 2.32256 2.32889 - 2.33386 2.33430 2.33465 2.33478 2.33473 2.33023 - 1.58128 1.64816 1.71449 1.78049 1.84564 1.90942 - 1.97166 2.03251 2.09236 2.15150 2.21045 2.26931 - 2.32739 2.38423 2.44023 2.49560 2.55019 2.60437 - 2.66092 2.69165 2.72226 2.74415 2.76345 2.76813 - 2.77223 2.77309 2.77365 2.77341 2.77355 2.78655 - 1.88046 1.96337 2.04252 2.11821 2.18994 2.25755 - 2.32136 2.38251 2.44272 2.50233 2.56127 2.61950 - 2.67753 2.73560 2.79278 2.84755 2.89946 2.95335 - 3.01487 3.04783 3.07941 3.10153 3.11988 3.12346 - 3.12636 3.12729 3.12826 3.12787 3.12809 3.15398 - 2.15352 2.24938 2.33878 2.42196 2.49832 2.56779 - 2.63115 2.69042 2.74859 2.80632 2.86363 2.92046 - 2.97726 3.03414 3.09004 3.14305 3.19270 3.24508 - 3.30742 3.34153 3.37361 3.39534 3.41309 3.41576 - 3.41795 3.41901 3.42014 3.41961 3.41992 3.45281 - 2.63460 2.74944 2.85289 2.94510 3.02542 3.09406 - 3.15265 3.20483 3.25573 3.30658 3.35751 3.40847 - 3.45973 3.51126 3.56199 3.60997 3.65463 3.70242 - 3.76086 3.79327 3.82355 3.84433 3.86315 3.86516 - 3.86696 3.86803 3.86914 3.86862 3.86899 3.89915 - 3.04836 3.17454 3.28514 3.38046 3.45985 3.52389 - 3.57494 3.61795 3.65962 3.70164 3.74420 3.78728 - 3.83101 3.87530 3.91934 3.96148 4.00121 4.04350 - 4.09420 4.12212 4.14877 4.16861 4.19003 4.19239 - 4.19465 4.19554 4.19634 4.19605 4.19635 4.21141 - 3.88345 4.01749 4.12827 4.21691 4.28312 4.32835 - 4.35635 4.37420 4.39106 4.40921 4.42908 4.45072 - 4.47401 4.49893 4.52526 4.55232 4.57952 4.60746 - 4.63686 4.65236 4.66919 4.68621 4.71245 4.71649 - 4.72062 4.72078 4.72050 4.72093 4.72087 4.69608 - 4.53156 4.65741 4.75519 4.82717 4.87358 4.89657 - 4.90082 4.89451 4.88791 4.88370 4.88235 4.88405 - 4.88862 4.89604 4.90634 4.91901 4.93320 4.94752 - 4.96067 4.96753 4.97706 4.99037 5.01575 5.02061 - 5.02588 5.02535 5.02407 5.02503 5.02457 4.98156 - 5.49522 5.60978 5.67027 5.68840 5.67680 5.64985 - 5.61299 5.57147 5.53133 5.49436 5.46061 5.42999 - 5.40270 5.37881 5.35866 5.34231 5.33113 5.33035 - 5.32832 5.31709 5.31559 5.32748 5.33930 5.34314 - 5.34872 5.34721 5.34503 5.34606 5.34525 5.30904 - 6.21803 6.29015 6.30862 6.28640 6.23529 6.16857 - 6.09258 6.01416 5.94090 5.87450 5.81412 5.75865 - 5.70824 5.66254 5.62182 5.58576 5.55495 5.53299 - 5.51425 5.50089 5.49371 5.49517 5.49520 5.49823 - 5.50198 5.50033 5.49820 5.49900 5.49828 5.47928 - 6.78756 6.82643 6.80722 6.74575 6.65577 6.55244 - 6.44271 6.33378 6.23362 6.14336 6.06127 5.98540 - 5.91603 5.85275 5.79556 5.74351 5.69634 5.65651 - 5.62313 5.60699 5.59429 5.58679 5.57706 5.57942 - 5.58079 5.57938 5.57804 5.57857 5.57812 5.57172 - 7.25442 7.26927 7.21706 7.11798 6.99023 6.85307 - 6.71390 6.57931 6.45667 6.34647 6.24603 6.15284 - 6.06733 5.98934 5.91845 5.85294 5.79172 5.73685 - 5.69020 5.66981 5.65137 5.63673 5.61929 5.62113 - 5.62004 5.61908 5.61893 5.61918 5.61910 5.61920 - 7.98384 7.96150 7.85095 7.68244 7.48528 7.28853 - 7.09987 6.92355 6.76428 6.62141 6.49051 6.36846 - 6.25601 6.15383 6.06057 5.97304 5.88877 5.81003 - 5.74091 5.71086 5.68161 5.65647 5.62835 5.62860 - 5.62321 5.62323 5.62529 5.62514 5.62572 5.62989 - 8.53472 8.47605 8.31190 8.08164 7.82456 7.57789 - 7.34879 7.13901 6.95016 6.78043 6.62443 6.47863 - 6.34407 6.22195 6.11043 6.00518 5.90291 5.80618 - 5.71943 5.68058 5.64232 5.61008 5.57556 5.57319 - 5.56464 5.56547 5.56891 5.56841 5.56937 5.57362 - 9.55395 9.25140 8.93585 8.62000 8.30601 7.99677 - 7.69619 7.41005 7.14456 6.90153 6.68139 6.48473 - 6.31270 6.16473 6.03401 5.90319 5.76121 5.62556 - 5.51194 5.46007 5.40769 5.36548 5.32430 5.31238 - 5.30116 5.30181 5.30557 5.30585 5.30454 5.30905 - 10.21559 9.74318 9.29103 8.86773 8.47147 8.10121 - 7.75611 7.43574 7.14021 6.86854 6.61938 6.39106 - 6.18129 5.98896 5.81569 5.66130 5.52314 5.38824 - 5.24515 5.17432 5.11230 5.07164 5.02478 5.00960 - 4.99550 4.99590 4.99789 4.99674 4.99706 5.00155 - 10.89209 10.25110 9.65527 9.10685 8.60142 8.13687 - 7.71168 7.32353 6.97063 6.65071 6.36077 6.09728 - 5.85531 5.63164 5.42718 5.24266 5.07479 4.91186 - 4.74457 4.66342 4.59179 4.54322 4.48507 4.46709 - 4.45485 4.45386 4.45215 4.45136 4.45051 4.45691 - 11.25274 10.49716 9.80781 9.17901 8.60500 8.08193 - 7.60772 7.17874 6.79150 6.44256 6.12796 5.84295 - 5.58103 5.33776 5.11351 4.90878 4.72084 4.53818 - 4.35257 4.26263 4.18182 4.12522 4.05871 4.03975 - 4.02934 4.02741 4.02356 4.02331 4.02217 4.02856 - 11.46136 10.61378 9.85697 9.17531 8.56096 8.00702 - 7.50851 7.05900 6.65199 6.28334 5.94931 5.64560 - 5.36643 5.10736 4.86701 4.64252 4.43161 4.23212 - 4.04415 3.95460 3.86474 3.79259 3.72081 3.70372 - 3.69171 3.68924 3.68464 3.68394 3.68479 3.68911 - 11.59724 10.68267 9.87731 9.15631 8.51109 7.93308 - 7.41514 6.94921 6.52749 6.14521 5.79850 5.48288 - 5.19252 4.92285 4.67209 4.43691 4.21471 4.00328 - 3.80179 3.70480 3.60750 3.52960 3.45289 3.43515 - 3.42150 3.41858 3.41395 3.41354 3.41488 3.41743 - 11.73326 10.73403 9.86964 9.10022 8.41645 7.80823 - 7.26536 6.77802 6.33716 5.93754 5.57493 5.24454 - 4.94032 4.65740 4.39336 4.14403 3.90570 3.67631 - 3.45323 3.34378 3.23368 3.14564 3.05981 3.03973 - 3.02219 3.01891 3.01527 3.01534 3.01689 3.01586 - 11.77916 10.73287 9.83779 9.04283 8.33845 7.71340 - 7.15623 6.65633 6.20434 5.79481 5.42327 5.08470 - 4.77287 4.48262 4.21102 3.95315 3.70441 3.46187 - 3.22204 3.10230 2.98102 2.88355 2.78854 2.76556 - 2.74458 2.74135 2.73904 2.73936 2.74049 2.73678 - 11.74786 10.66010 9.74383 8.93030 8.21109 7.57109 - 6.99969 6.48659 6.02303 5.60346 5.22307 4.87656 - 4.55744 4.26006 3.98057 3.71252 3.44920 3.18442 - 2.91197 2.77061 2.62394 2.50325 2.38423 2.35438 - 2.32895 2.32639 2.32561 2.32558 2.32481 2.32142 - 11.65261 10.56797 9.66289 8.85751 8.14402 7.50560 - 6.93338 6.41847 5.95330 5.53247 5.15110 4.80378 - 4.48394 4.18570 3.90448 3.63258 3.36147 3.08180 - 2.78306 2.62344 2.45374 2.31034 2.16633 2.13088 - 2.10540 2.10330 2.10104 2.09984 2.09752 2.10175 - 11.46714 10.41456 9.54883 8.77552 8.08358 7.45898 - 6.89542 6.38675 5.92764 5.51292 5.13721 4.79447 - 4.47721 4.17936 3.89780 3.62744 3.35752 3.06294 - 2.71735 2.52253 2.31452 2.13463 1.93981 1.89519 - 1.87780 1.87400 1.86230 1.86010 1.85365 1.88552 - 11.29525 10.28413 9.46474 8.73000 8.06581 7.46163 - 6.91289 6.41510 5.96452 5.55673 5.18701 4.85011 - 4.53941 4.24849 3.97128 3.69720 3.41305 3.10120 - 2.73792 2.52758 2.28938 2.07138 1.83226 1.77875 - 1.75995 1.75749 1.74102 1.73445 1.73289 1.78241 - 11.17819 10.19634 9.41283 8.70749 8.06545 7.47848 - 6.94322 6.45637 6.01521 5.61569 5.25328 4.92277 - 4.61761 4.33126 4.05736 3.78470 3.49878 3.17935 - 2.79735 2.56969 2.30399 2.05453 1.77345 1.71079 - 1.69234 1.68982 1.66925 1.66123 1.66032 1.72127 - 11.08918 10.13046 9.37723 8.69610 8.07331 7.50185 - 6.97922 6.50288 6.07086 5.67937 5.32404 4.99978 - 4.70006 4.41829 4.14795 3.87741 3.59122 3.26698 - 2.87084 2.62892 2.33934 2.06120 1.74097 1.66888 - 1.64874 1.64625 1.62333 1.61447 1.61400 1.68090 - 10.96248 10.03888 9.33351 8.69025 8.09897 7.55375 - 7.05319 6.59575 6.18029 5.80353 5.46132 5.14877 - 4.85938 4.58654 4.32359 4.05845 3.77435 3.44566 - 3.03014 2.76599 2.43651 2.10779 1.71666 1.62567 - 1.59789 1.59519 1.57022 1.56066 1.56074 1.63145 - 10.87720 9.97995 9.30998 8.69525 8.12844 7.60426 - 7.12190 6.68041 6.27918 5.91523 5.58465 5.28263 - 5.00274 4.73835 4.48279 4.22379 3.94382 3.61494 - 3.18798 2.90756 2.54606 2.17416 1.71982 1.61028 - 1.57102 1.56769 1.54244 1.53291 1.53327 1.60253 - 10.75556 9.90327 9.28976 8.72307 8.19822 7.71123 - 7.26202 6.85038 6.47643 6.13765 5.83047 5.55034 - 5.29073 5.04503 4.80680 4.56385 4.29782 3.97786 - 3.54216 3.23758 2.81951 2.36451 1.77469 1.62064 - 1.54391 1.53746 1.51443 1.50625 1.50676 1.56435 - 10.69567 9.87052 9.29054 8.75375 8.25565 7.79321 - 7.36657 6.97590 6.62163 6.30153 6.01225 5.74934 - 5.50626 5.27639 5.05359 4.82595 4.57511 4.26914 - 3.83815 3.52252 3.06890 2.55385 1.85230 1.65723 - 1.53877 1.52781 1.50710 1.50056 1.50061 1.54548 - 10.64540 9.84849 9.30654 8.80447 8.33874 7.90715 - 7.50990 7.14738 6.82026 6.52662 6.26342 6.02640 - 5.80901 5.60469 5.40782 5.20707 4.98443 4.70780 - 4.29851 3.97831 3.48787 2.89495 2.01811 1.75043 - 1.54823 1.52618 1.50655 1.50232 1.50022 1.52708 - 10.62917 9.84611 9.32401 8.84080 8.39360 7.98050 - 7.60162 7.25730 6.94816 6.67251 6.42751 6.20915 - 6.01093 5.82644 5.65044 5.47185 5.27304 5.02227 - 4.63743 4.32287 3.82107 3.18565 2.17910 1.84749 - 1.56524 1.53099 1.50844 1.50524 1.50031 1.51789 - 10.63218 9.85155 9.33744 8.86433 8.42907 8.02934 - 7.66441 7.33370 7.03689 6.77275 6.53950 6.33453 - 6.15345 5.99062 5.83803 5.67817 5.48886 5.24448 - 4.87529 4.58030 4.11148 3.47708 2.32458 1.92104 - 1.58760 1.54328 1.50863 1.50602 1.50220 1.51238 - 10.62943 9.85620 9.34994 8.88472 8.45760 8.06641 - 7.71036 7.38889 7.10157 6.84725 6.62427 6.43010 - 6.26038 6.10971 5.97095 5.82794 5.65886 5.43502 - 5.08338 4.79627 4.33449 3.69590 2.47376 2.01127 - 1.60275 1.54938 1.51143 1.50632 1.50358 1.50874 - 10.62362 9.86374 9.36811 8.91316 8.49627 8.11568 - 7.77085 7.46156 7.18762 6.94786 6.74042 6.56240 - 6.40862 6.27369 6.15272 6.03378 5.89816 5.71348 - 5.40210 5.13461 4.68879 4.04642 2.73416 2.19060 - 1.63759 1.55931 1.51282 1.50949 1.50123 1.50424 - 10.64178 9.87768 9.37958 8.92592 8.51352 8.13999 - 7.80399 7.50425 7.23950 7.00848 6.80953 6.63993 - 6.49470 6.36968 6.26357 6.17128 6.07566 5.92446 - 5.62307 5.36274 4.94899 4.34354 2.97130 2.34455 - 1.66970 1.57381 1.51431 1.50678 1.50150 1.50151 - 10.62080 9.87866 9.39318 8.95048 8.54783 8.18330 - 7.85571 7.56404 7.30736 7.08513 6.89680 6.74111 - 6.61539 6.51669 6.44146 6.37864 6.30978 6.20074 - 5.97372 5.76198 5.40716 4.85927 3.45584 2.68527 - 1.75433 1.61412 1.51536 1.50656 1.49097 1.49789 - 10.60324 9.88214 9.40279 8.96452 8.56518 8.20342 - 7.87851 7.59003 7.33778 7.12131 6.94006 6.79257 - 6.67590 6.58738 6.52551 6.48302 6.44426 6.37171 - 6.19144 6.01331 5.69961 5.20291 3.83418 2.98212 - 1.83599 1.65234 1.52021 1.50449 1.49186 1.49610 - 10.57954 9.89105 9.41139 8.97435 8.57771 8.21998 - 7.90012 7.61728 7.37093 7.16060 6.98579 6.84508 - 6.73556 6.65561 6.60725 6.59014 6.59400 6.57493 - 6.45668 6.32288 6.07977 5.65603 4.34993 3.46500 - 2.00496 1.74117 1.53183 1.51114 1.48821 1.49430 - 10.53400 9.88781 9.41653 8.98458 8.59066 8.23418 - 7.91481 7.63264 7.38800 7.18035 7.00876 6.87225 - 6.76964 6.70022 6.66421 6.65671 6.66702 6.66882 - 6.60200 6.50522 6.31670 5.97761 4.74737 3.75586 - 2.17569 1.86204 1.54484 1.50298 1.49051 1.49341 - 10.50922 9.88691 9.41808 8.98860 8.59700 8.24250 - 7.92473 7.64376 7.39994 7.19328 7.02368 6.89058 - 6.79219 6.72725 6.69602 6.69364 6.71137 6.73140 - 6.71025 6.64682 6.47741 6.14931 5.03331 4.08850 - 2.31223 1.93721 1.56796 1.51943 1.48834 1.49288 - 10.49405 9.88807 9.42049 8.99209 8.60149 8.24792 - 7.93101 7.65082 7.40770 7.20181 7.03323 6.90178 - 6.80615 6.74540 6.71928 6.72166 6.74464 6.77922 - 6.79189 6.75035 6.59604 6.27294 5.24345 4.37048 - 2.45134 2.01220 1.58324 1.53566 1.48988 1.49253 - 10.47472 9.88893 9.42255 8.99541 8.60621 8.25416 - 7.93891 7.66051 7.41931 7.21550 7.04926 6.92051 - 6.82808 6.77123 6.75002 6.75885 6.79121 6.84210 - 6.88674 6.87349 6.76394 6.49540 5.56875 4.74232 - 2.71601 2.18277 1.61965 1.55108 1.49143 1.49209 - 10.46223 9.89114 9.42538 8.99779 8.60803 8.25624 - 7.94206 7.66539 7.42641 7.22504 7.06116 6.93437 - 6.84352 6.78804 6.76878 6.78185 6.82201 6.88281 - 6.94356 6.94892 6.87632 6.65437 5.79796 5.02107 - 2.94899 2.34319 1.66010 1.56238 1.49439 1.49182 - 10.44406 9.89219 9.42714 9.00018 8.61132 8.26086 - 7.94834 7.67357 7.43654 7.23722 7.07545 6.95096 - 6.86278 6.81064 6.79564 6.81437 6.86292 6.93847 - 7.02398 7.05223 7.03511 6.89574 6.17738 5.50274 - 3.43849 2.68929 1.75210 1.60229 1.50344 1.49146 - 10.43336 9.89249 9.42798 9.00152 8.61316 8.26318 - 7.95117 7.67693 7.44050 7.24188 7.08098 6.95756 - 6.87067 6.82011 6.80729 6.82936 6.88319 6.96681 - 7.06483 7.10517 7.11768 7.02865 6.41737 5.82032 - 3.82186 2.98120 1.84119 1.64495 1.51367 1.49128 - 10.42166 9.89257 9.42878 9.00302 8.61521 8.26558 - 7.95375 7.67963 7.44341 7.24515 7.08491 6.96249 - 6.87682 6.82771 6.81705 6.84289 6.90294 6.99501 - 7.10611 7.15956 7.20062 7.16741 6.71318 6.22524 - 4.38938 3.44649 2.00931 1.73365 1.53463 1.49109 - 10.41566 9.89265 9.42918 9.00375 8.61624 8.26681 - 7.95511 7.68113 7.44509 7.24708 7.08722 6.96533 - 6.88027 6.83189 6.82232 6.85003 6.91313 7.00926 - 7.12787 7.18887 7.24243 7.23774 6.89194 6.47656 - 4.79004 3.80694 2.16838 1.82359 1.55488 1.49101 - 10.42979 9.89847 9.42825 8.99998 8.61213 8.26360 - 7.95355 7.68145 7.44702 7.25020 7.09086 6.96841 - 6.88080 6.82808 6.81555 6.84894 6.92951 7.03739 - 7.14773 7.20417 7.26186 7.27817 7.01434 6.64766 - 5.08200 4.09873 2.32343 1.91405 1.57297 1.49096 - 10.42712 9.89860 9.42850 9.00033 8.61263 8.26423 - 7.95435 7.68244 7.44822 7.25164 7.09257 6.97042 - 6.88313 6.83079 6.81872 6.85270 6.93413 7.04341 - 7.15668 7.21624 7.28037 7.30932 7.09410 6.77335 - 5.31228 4.33611 2.46777 2.00536 1.59162 1.49093 - 10.40616 9.89306 9.42984 9.00466 8.61754 8.26866 - 7.95767 7.68450 7.44930 7.25216 7.09313 6.97208 - 6.88811 6.84124 6.83342 6.86278 6.92776 7.02915 - 7.16272 7.23697 7.30866 7.34609 7.20201 6.93538 - 5.64228 4.70550 2.72855 2.18458 1.62823 1.49090 - 10.40348 9.89293 9.43000 9.00492 8.61780 8.26882 - 7.95771 7.68440 7.44912 7.25194 7.09287 6.97180 - 6.88801 6.84157 6.83416 6.86326 6.92735 7.03002 - 7.16706 7.24293 7.32243 7.37219 7.25786 7.03396 - 5.86491 4.97776 2.95911 2.35322 1.66175 1.49090 - 0.44803 0.47088 0.49473 0.51968 0.54573 0.57285 - 0.60099 0.63004 0.65987 0.69030 0.72112 0.75208 - 0.78290 0.81347 0.84413 0.87635 0.91126 0.94667 - 0.97729 0.98882 0.99909 1.00767 1.02234 1.02731 - 1.03089 1.03113 1.03110 1.03110 1.03117 1.03214 - 0.66216 0.69081 0.72114 0.75338 0.78758 0.82369 - 0.86157 0.90092 0.94126 0.98224 1.02347 1.06447 - 1.10462 1.14358 1.18186 1.22179 1.26529 1.30961 - 1.34976 1.36724 1.38431 1.39894 1.41695 1.41742 - 1.41371 1.41685 1.42580 1.42733 1.42540 1.40544 - 0.86409 0.89997 0.93762 0.97735 1.01916 1.06296 - 1.10855 1.15553 1.20332 1.25154 1.29973 1.34739 - 1.39399 1.43922 1.48354 1.52918 1.57803 1.62767 - 1.67433 1.69611 1.71794 1.73626 1.75633 1.75675 - 1.75293 1.75631 1.76583 1.76745 1.76541 1.74417 - 1.23272 1.28488 1.33786 1.39197 1.44707 1.50292 - 1.55925 1.61578 1.67216 1.72815 1.78344 1.83796 - 1.89208 1.94603 1.99926 2.05123 2.10206 2.15468 - 2.21206 2.24153 2.26917 2.28907 2.31104 2.31634 - 2.31877 2.32012 2.32270 2.32256 2.32310 2.31756 - 1.56461 1.63209 1.69847 1.76405 1.82850 1.89159 - 1.95327 2.01378 2.07368 2.13289 2.19124 2.24866 - 2.30560 2.36242 2.41876 2.47436 2.52930 2.58488 - 2.64231 2.67152 2.70132 2.72480 2.74767 2.75627 - 2.76698 2.76428 2.75926 2.76141 2.75903 2.77337 - 1.86254 1.94501 2.02375 2.09900 2.17031 2.23751 - 2.30094 2.36176 2.42174 2.48116 2.53995 2.59797 - 2.65557 2.71299 2.76974 2.82535 2.87978 2.93493 - 2.99287 3.02280 3.05338 3.07713 3.10005 3.11155 - 3.12839 3.12232 3.11163 3.11592 3.11106 3.14021 - 2.13385 2.22921 2.31813 2.40085 2.47680 2.54591 - 2.60896 2.66802 2.72610 2.78383 2.84119 2.89802 - 2.95456 3.01091 3.06654 3.12079 3.17353 3.22709 - 3.28414 3.31390 3.34428 3.36765 3.39044 3.40346 - 3.42358 3.41567 3.40191 3.40735 3.40116 3.43835 - 2.61230 2.72650 2.82941 2.92119 3.00117 3.06960 - 3.12810 3.18033 3.23141 3.28255 3.33386 3.38513 - 3.43651 3.48793 3.53878 3.58815 3.63576 3.68447 - 3.73763 3.76578 3.79429 3.81615 3.83850 3.85086 - 3.86953 3.86228 3.84966 3.85467 3.84899 3.88316 - 3.02421 3.14967 3.25972 3.35467 3.43388 3.49791 - 3.54913 3.59245 3.63454 3.67705 3.72017 3.76381 - 3.80802 3.85271 3.89725 3.94049 3.98199 4.02493 - 4.07302 4.09885 4.12471 4.14472 4.16649 4.17539 - 4.18671 4.18335 4.17731 4.17982 4.17704 4.19400 - 3.85673 3.99005 4.10044 4.18900 4.25545 4.30120 - 4.32992 4.34861 4.36630 4.38525 4.40594 4.42851 - 4.45297 4.47927 4.50677 4.53381 4.55952 4.58753 - 4.62215 4.64165 4.66057 4.67582 4.69522 4.69466 - 4.68648 4.69341 4.70480 4.70066 4.70558 4.67709 - 4.50371 4.62911 4.72686 4.79916 4.84622 4.87013 - 4.87550 4.87036 4.86482 4.86159 4.86121 4.86401 - 4.87003 4.87924 4.89092 4.90292 4.91397 4.92812 - 4.95033 4.96414 4.97712 4.98793 5.00374 4.99825 - 4.98083 4.99237 5.01163 5.00447 5.01288 4.96378 - 5.46709 5.58179 5.64313 5.66259 5.65255 5.62707 - 5.59159 5.55129 5.51226 5.47638 5.44400 5.41500 - 5.38903 5.36578 5.34593 5.33040 5.32011 5.31535 - 5.31595 5.31808 5.32116 5.32569 5.33365 5.32661 - 5.31188 5.32094 5.33537 5.33316 5.33723 5.29731 - 6.19056 6.26384 6.28387 6.26344 6.21416 6.14917 - 6.07477 5.99775 5.92569 5.86043 5.80140 5.74752 - 5.69842 5.65337 5.61288 5.57725 5.54699 5.52296 - 5.50593 5.50001 5.49541 5.49348 5.49347 5.48901 - 5.48100 5.48545 5.49257 5.49145 5.49349 5.47351 - 6.76116 6.80186 6.78470 6.72534 6.63741 6.53595 - 6.42792 6.32045 6.22153 6.13243 6.05166 5.97731 - 5.90924 5.84673 5.78986 5.73805 5.69112 5.65065 - 5.61824 5.60507 5.59343 5.58573 5.57929 5.57645 - 5.57292 5.57397 5.57581 5.57548 5.57603 5.57054 - 7.22920 7.24630 7.19650 7.09977 6.97425 6.83906 - 6.70162 6.56851 6.44712 6.33810 6.23894 6.14718 - 6.06297 5.98589 5.91553 5.85027 5.78912 5.73434 - 5.68825 5.66841 5.65018 5.63724 5.62566 5.62308 - 5.62124 5.62050 5.61960 5.61967 5.61949 5.62136 - 7.96101 7.94134 7.83362 7.66787 7.47318 7.27853 - 7.09159 6.91672 6.75871 6.61703 6.48739 6.36669 - 6.25564 6.15468 6.06240 5.97535 5.89110 5.81294 - 5.74410 5.71286 5.68322 5.66144 5.64177 5.63797 - 5.63571 5.63378 5.63121 5.63146 5.63085 5.63704 - 8.51403 8.45831 8.29732 8.07008 7.81566 7.57113 - 7.34376 7.13539 6.94782 6.77933 6.62457 6.48011 - 6.34700 6.22641 6.11628 6.01187 5.90979 5.81381 - 5.72734 5.68710 5.64849 5.61979 5.59355 5.58804 - 5.58412 5.58213 5.57965 5.57983 5.57928 5.58494 - 9.51311 9.24432 8.94726 8.63690 8.31831 7.99812 - 7.68479 7.38993 7.12558 6.89279 6.68848 6.50788 - 6.34349 6.18972 6.04541 5.90709 5.77291 5.64588 - 5.53089 5.47846 5.42600 5.38420 5.34556 5.33701 - 5.33061 5.32902 5.32719 5.32751 5.32697 5.32980 - 10.20210 9.73413 9.28587 8.86597 8.47269 8.10505 - 7.76221 7.44381 7.14998 6.87982 6.63202 6.40503 - 6.19669 6.00599 5.83458 5.68229 5.54647 5.41387 - 5.27243 5.20172 5.13868 5.09627 5.04953 5.03732 - 5.03109 5.03008 5.02798 5.02792 5.02769 5.03016 - 10.88193 10.24625 9.65493 9.11035 8.60820 8.14639 - 7.72355 7.33737 6.98617 6.66772 6.37914 6.11702 - 5.87658 5.65477 5.45249 5.27056 5.10565 4.94578 - 4.78097 4.70019 4.62731 4.57637 4.51780 4.50214 - 4.49583 4.49468 4.49173 4.49178 4.49116 4.49516 - 11.24384 10.49419 9.80961 9.18483 8.61418 8.09391 - 7.62202 7.19498 6.80938 6.46186 6.14859 5.86494 - 5.60461 5.36325 5.14130 4.93928 4.75440 4.57477 - 4.39149 4.30210 4.22092 4.16337 4.09746 4.07980 - 4.07157 4.06997 4.06651 4.06656 4.06580 4.07112 - 11.45245 10.61172 9.86018 9.18260 8.57136 8.01983 - 7.52321 7.07524 6.66969 6.30246 5.96993 5.66783 - 5.39050 5.13356 4.89562 4.67379 4.46568 4.26875 - 4.08271 3.99384 3.90450 3.83275 3.76207 3.74547 - 3.73362 3.73154 3.72794 3.72730 3.72773 3.73314 - 11.58814 10.68052 9.88038 9.16340 8.52125 7.94558 - 7.42946 6.96507 6.54479 6.16398 5.81877 5.50479 - 5.21628 4.94868 4.70026 4.46760 4.24798 4.03888 - 3.83915 3.74288 3.64642 3.56964 3.49489 3.47668 - 3.46210 3.45967 3.45621 3.45562 3.45590 3.46103 - 11.72274 10.73054 9.87135 9.10583 8.42500 7.81899 - 7.27785 6.79199 6.35259 5.95447 5.59343 5.26474 - 4.96238 4.68148 4.41962 4.17255 3.93641 3.70892 - 3.48729 3.37856 3.26953 3.18322 3.09987 3.07841 - 3.05906 3.05634 3.05397 3.05365 3.05348 3.05519 - 11.76658 10.72747 9.83752 9.04641 8.34486 7.72193 - 7.16642 6.66796 6.21742 5.80945 5.43954 5.10274 - 4.79278 4.50451 4.23498 3.97917 3.73234 3.49142 - 3.25285 3.13375 3.01350 2.91771 2.82487 2.80035 - 2.77747 2.77478 2.77370 2.77366 2.77307 2.77049 - 11.72860 10.64890 9.73800 8.92839 8.21195 7.57393 - 7.00400 6.49224 6.03015 5.61219 5.23357 4.88895 - 4.57176 4.27632 3.99876 3.73250 3.47079 3.20749 - 2.93642 2.79572 2.64967 2.52943 2.41046 2.38021 - 2.35429 2.35167 2.35092 2.35093 2.35021 2.34584 - 11.62652 10.55094 9.65181 8.85062 8.13993 7.50341 - 6.93255 6.41886 5.95510 5.53592 5.15637 4.81101 - 4.49318 4.19690 3.91757 3.64743 3.37790 3.09985 - 2.80280 2.64383 2.47424 2.32996 2.18425 2.15008 - 2.12593 2.12295 2.11898 2.11827 2.11843 2.12250 - 11.41585 10.37849 9.52374 8.75853 8.07234 7.45168 - 6.89063 6.38343 5.92514 5.51097 5.13602 4.79489 - 4.48090 4.18778 3.90992 3.63773 3.35971 3.06156 - 2.72524 2.53665 2.32886 2.14380 1.94802 1.90685 - 1.89109 1.88677 1.87119 1.86778 1.87221 1.90447 - 11.24841 10.25009 9.43906 8.70993 8.04926 7.44717 - 6.89956 6.40259 5.95301 5.54650 5.17837 4.84332 - 4.53477 4.24629 3.97170 3.70026 3.41837 3.10765 - 2.74349 2.53184 2.29191 2.07284 1.83691 1.78706 - 1.77009 1.76525 1.74492 1.73993 1.74756 1.80129 - 11.12348 10.15667 9.38292 8.68402 8.04590 7.46106 - 6.92678 6.44050 6.00012 5.60173 5.24079 4.91211 - 4.60915 4.32535 4.05425 3.78444 3.50092 3.18247 - 2.79906 2.56985 2.30257 2.05274 1.77658 1.71805 - 1.70106 1.69571 1.67074 1.66451 1.67391 1.74012 - 11.02804 10.08645 9.34427 8.67038 8.05186 7.48253 - 6.96070 6.48467 6.05323 5.66276 5.30885 4.98640 - 4.68889 4.40973 4.14224 3.87462 3.59090 3.26764 - 2.87003 2.62666 2.33589 2.05807 1.74390 1.67607 - 1.65696 1.65135 1.62372 1.61674 1.62706 1.69966 - 10.89208 9.98892 9.29666 8.66184 8.07534 7.53224 - 7.03215 6.57458 6.15940 5.78346 5.44259 5.13184 - 4.84466 4.57438 4.31423 4.05194 3.77033 3.44279 - 3.02638 2.76135 2.43162 2.10437 1.72044 1.63359 - 1.60622 1.60023 1.57037 1.56266 1.57346 1.65001 - 10.80140 9.92658 9.27101 8.66545 8.10373 7.58162 - 7.09948 6.65753 6.25634 5.89311 5.56381 5.26358 - 4.98587 4.72390 4.47097 4.21466 3.93708 3.60965 - 3.18272 2.90215 2.54126 2.17158 1.72471 1.61898 - 1.57998 1.57355 1.54365 1.53578 1.54605 1.62093 - 10.67593 9.84751 9.24919 8.69214 8.17246 7.68739 - 7.23803 6.82555 6.45139 6.11320 5.80726 5.52884 - 5.27122 5.02755 4.79141 4.55057 4.28669 3.96895 - 3.53576 3.23273 2.81680 2.36461 1.78113 1.63014 - 1.55470 1.54641 1.52020 1.51302 1.52013 1.58245 - 10.61848 9.81605 9.25044 8.72272 8.22951 7.76883 - 7.34199 6.95044 6.59595 6.27643 5.98838 5.72711 - 5.48580 5.25759 5.03640 4.81038 4.56140 4.25825 - 3.83172 3.51894 3.06831 2.55595 1.85920 1.66670 - 1.55103 1.53956 1.51727 1.51116 1.51465 1.56341 - 10.57822 9.79943 9.26861 8.77370 8.31195 7.88193 - 7.48475 7.12178 6.79470 6.50173 6.23966 6.00406 - 5.78807 5.58491 5.38907 5.18933 4.96821 4.69479 - 4.29163 3.97542 3.48875 2.89842 2.02497 1.75959 - 1.56224 1.54133 1.52225 1.51781 1.51542 1.54482 - 10.57317 9.80285 9.28824 8.81005 8.36587 7.95430 - 7.57595 7.23182 6.92312 6.64825 6.40430 6.18712 - 5.99000 5.80642 5.63120 5.45345 5.25596 5.00803 - 4.62875 4.31799 3.82011 3.18779 2.18553 1.85652 - 1.57991 1.54735 1.52624 1.52272 1.51634 1.53553 - 10.58558 9.81306 9.30337 8.83346 8.40045 8.00224 - 7.63831 7.30835 7.01231 6.74899 6.51664 6.31265 - 6.13261 5.97083 5.81920 5.65994 5.47107 5.22849 - 4.86429 4.57299 4.10810 3.47693 2.32999 1.93007 - 1.60235 1.56020 1.52714 1.52356 1.51928 1.52995 - 10.58935 9.82108 9.31707 8.85380 8.42838 8.03867 - 7.68392 7.36360 7.07734 6.82400 6.60190 6.40855 - 6.23956 6.08959 5.95155 5.80931 5.64129 5.41913 - 5.07055 4.78589 4.32767 3.69341 2.47890 2.02000 - 1.61740 1.56616 1.52989 1.52403 1.52102 1.52627 - 10.59200 9.83504 9.33849 8.88216 8.46467 8.08512 - 7.74245 7.43553 7.16320 6.92420 6.71688 6.53882 - 6.38580 6.25307 6.13528 6.01922 5.88494 5.69976 - 5.38217 5.11033 4.67207 4.05077 2.74945 2.18865 - 1.64881 1.57878 1.53152 1.52464 1.52104 1.52170 - 10.59480 9.83930 9.34629 8.89666 8.48728 8.11587 - 7.78106 7.48164 7.21640 6.98446 6.78484 6.61585 - 6.47414 6.35575 6.25550 6.15992 6.04859 5.88853 - 5.60229 5.35233 4.93938 4.33012 2.97549 2.35234 - 1.68322 1.58973 1.53080 1.52604 1.51602 1.51894 - 10.57753 9.84672 9.36460 8.92173 8.51775 8.15273 - 7.82575 7.53575 7.28165 7.06218 6.87573 6.72041 - 6.59421 6.49478 6.41900 6.35665 6.28965 6.18219 - 5.95535 5.74421 5.39203 4.84898 3.45563 2.69060 - 1.76680 1.62774 1.53067 1.52259 1.50840 1.51525 - 10.56102 9.84544 9.36887 8.93282 8.53528 8.17494 - 7.85117 7.56363 7.31224 7.09659 6.91608 6.76929 - 6.65326 6.56528 6.50383 6.46154 6.42279 6.35060 - 6.17206 5.99570 5.68490 5.19200 3.83141 2.98492 - 1.84754 1.66480 1.53473 1.52049 1.50873 1.51343 - 10.53810 9.85394 9.37662 8.94166 8.54687 8.19075 - 7.87229 7.59066 7.34531 7.13580 6.96162 6.82137 - 6.71216 6.63240 6.58413 6.56707 6.57108 6.55274 - 6.43650 6.30436 6.06341 5.64241 4.34372 3.46451 - 2.01442 1.75259 1.54666 1.52710 1.50502 1.51160 - 10.50999 9.85722 9.38167 8.94838 8.55530 8.20102 - 7.88455 7.60518 7.36240 7.15583 6.98502 6.84882 - 6.74449 6.67085 6.63080 6.62559 6.64804 6.66082 - 6.59560 6.49630 6.29049 5.91619 4.72590 3.82761 - 2.16918 1.84481 1.56397 1.53462 1.50498 1.51069 - 10.47035 9.85143 9.38452 8.95669 8.56654 8.21328 - 7.89660 7.61657 7.37358 7.16766 6.99867 6.86611 - 6.76811 6.70343 6.67232 6.66996 6.68775 6.70813 - 6.68805 6.62552 6.45734 6.13111 5.02217 4.08347 - 2.31896 1.94742 1.58346 1.53597 1.50504 1.51015 - 10.45635 9.85309 9.38708 8.96015 8.57090 8.21856 - 7.90278 7.62360 7.38133 7.17615 7.00815 6.87717 - 6.78191 6.72145 6.69550 6.69792 6.72080 6.75552 - 6.76903 6.72817 6.57461 6.25289 5.23087 4.36409 - 2.45657 2.02177 1.59874 1.55192 1.50685 1.50979 - 10.43742 9.85401 9.38917 8.96346 8.57558 8.22477 - 7.91064 7.63325 7.39291 7.18984 7.02419 6.89588 - 6.80375 6.74710 6.72598 6.73486 6.76730 6.81824 - 6.86294 6.84974 6.74052 6.47331 5.55385 4.73319 - 2.71941 2.19099 1.63435 1.56691 1.50827 1.50933 - 10.42466 9.85593 9.39183 8.96577 8.57745 8.22693 - 7.91385 7.63815 7.39999 7.19931 7.03599 6.90967 - 6.81916 6.76391 6.74474 6.75772 6.79773 6.85884 - 6.91959 6.92412 6.85151 6.63132 5.78146 5.00981 - 2.95097 2.35015 1.67385 1.57769 1.51101 1.50905 - 10.40539 9.85664 9.39360 8.96822 8.58068 8.23141 - 7.92002 7.64626 7.41010 7.21150 7.05030 6.92622 - 6.83834 6.78639 6.77147 6.79009 6.83843 6.91413 - 6.99938 7.02666 7.00957 6.87185 6.15808 5.48795 - 3.43763 2.69373 1.76405 1.61632 1.51976 1.50868 - 10.39461 9.85690 9.39443 8.96955 8.58249 8.23369 - 7.92280 7.64956 7.41401 7.21612 7.05578 6.93276 - 6.84614 6.79574 6.78297 6.80497 6.85863 6.94204 - 7.03983 7.08002 7.09287 7.00480 6.39646 5.80334 - 3.81880 2.98385 1.85209 1.65811 1.52978 1.50849 - 10.38353 9.85713 9.39524 8.97101 8.58451 8.23606 - 7.92530 7.65217 7.41679 7.21926 7.05958 6.93756 - 6.85215 6.80316 6.79251 6.81833 6.87826 6.96973 - 7.08068 7.13509 7.17680 7.14353 6.69061 6.20575 - 4.38297 3.44646 2.01881 1.74554 1.55040 1.50830 - 10.37790 9.85735 9.39570 8.97176 8.58556 8.23729 - 7.92670 7.65367 7.41846 7.22114 7.06182 6.94034 - 6.85554 6.80730 6.79772 6.82537 6.88834 6.98394 - 7.10228 7.16388 7.21783 7.21311 6.86871 6.45576 - 4.78100 3.80448 2.17654 1.83437 1.57036 1.50821 - 10.39226 9.86310 9.39464 8.96792 8.58148 8.23420 - 7.92525 7.65409 7.42045 7.22430 7.06549 6.94342 - 6.85607 6.80352 6.79103 6.82431 6.90462 7.01208 - 7.12191 7.17813 7.23572 7.25229 6.99053 6.62626 - 5.07103 4.09409 2.33013 1.92381 1.58810 1.50815 - 10.38963 9.86315 9.39485 8.96829 8.58200 8.23488 - 7.92610 7.65513 7.42171 7.22576 7.06720 6.94543 - 6.85841 6.80626 6.79425 6.82816 6.90932 7.01805 - 7.13040 7.18944 7.25330 7.28256 7.06982 6.75149 - 5.29977 4.32962 2.47314 2.01421 1.60641 1.50813 - 10.36819 9.85769 9.39639 8.97270 8.58685 8.23914 - 7.92925 7.65706 7.42269 7.22623 7.06774 6.94708 - 6.86338 6.81666 6.80886 6.83804 6.90269 7.00406 - 7.13697 7.20980 7.28075 7.31901 7.17760 6.91226 - 5.62723 4.69619 2.73188 2.19191 1.64245 1.50810 - 10.36534 9.85726 9.39629 8.97285 8.58711 8.23934 - 7.92930 7.65691 7.42245 7.22594 7.06739 6.94671 - 6.86316 6.81683 6.80944 6.83849 6.90237 7.00428 - 7.14101 7.21782 7.29761 7.34665 7.23244 7.00982 - 5.84801 4.96672 2.96135 2.35964 1.67543 1.50810 - 0.44177 0.46446 0.48818 0.51300 0.53892 0.56591 - 0.59389 0.62274 0.65229 0.68233 0.71260 0.74283 - 0.77267 0.80200 0.83136 0.86266 0.89750 0.93353 - 0.96488 0.97660 0.98702 0.99587 1.01145 1.01680 - 1.02067 1.02092 1.02085 1.02084 1.02092 1.02210 - 0.65376 0.68229 0.71249 0.74459 0.77861 0.81452 - 0.85215 0.89117 0.93110 0.97156 1.01213 1.05228 - 1.09140 1.12913 1.16617 1.20527 1.24881 1.29405 - 1.33564 1.35379 1.37152 1.38676 1.40585 1.40645 - 1.40261 1.40590 1.41529 1.41691 1.41487 1.39396 - 0.85031 0.88864 0.92808 0.96885 1.01090 1.05414 - 1.09844 1.14367 1.18964 1.23616 1.28298 1.32993 - 1.37696 1.42393 1.47028 1.51548 1.55965 1.60563 - 1.65638 1.68252 1.70670 1.72386 1.74344 1.74633 - 1.74110 1.74526 1.75517 1.75426 1.75652 1.73202 - 1.21929 1.27125 1.32401 1.37788 1.43268 1.48817 - 1.54411 1.60017 1.65604 1.71142 1.76606 1.81987 - 1.87328 1.92657 1.97924 2.03087 2.08176 2.13523 - 2.19479 2.22579 2.25476 2.27540 2.29832 2.30387 - 2.30623 2.30768 2.31055 2.31038 2.31099 2.30479 - 1.54874 1.61586 1.68189 1.74710 1.81118 1.87390 - 1.93518 1.99531 2.05479 2.11359 2.17149 2.22844 - 2.28489 2.34123 2.39717 2.45269 2.50810 2.56482 - 2.62421 2.65470 2.68571 2.71003 2.73379 2.74265 - 2.75360 2.75088 2.74581 2.74798 2.74559 2.76009 - 1.84463 1.92660 2.00489 2.07972 2.15065 2.21749 - 2.28060 2.34111 2.40080 2.45995 2.51847 2.57624 - 2.63362 2.69086 2.74753 2.80329 2.85825 2.91446 - 2.97415 3.00519 3.03688 3.06138 3.08504 3.09687 - 3.11421 3.10795 3.09695 3.10137 3.09637 3.12638 - 2.11423 2.20899 2.29741 2.37967 2.45524 2.52404 - 2.58685 2.64571 2.70364 2.76125 2.81853 2.87531 - 2.93186 2.98830 3.04410 3.09868 3.15200 3.20652 - 3.26504 3.29574 3.32706 3.35110 3.37447 3.38787 - 3.40862 3.40043 3.38619 3.39183 3.38543 3.42387 - 2.59004 2.70354 2.80587 2.89721 2.97689 3.04515 - 3.10361 3.15589 3.20710 3.25842 3.30996 3.36155 - 3.41331 3.46518 3.51655 3.56649 3.61471 3.66415 - 3.71826 3.74700 3.77615 3.79849 3.82121 3.83387 - 3.85311 3.84561 3.83255 3.83773 3.83185 3.86718 - 3.00005 3.12478 3.23430 3.32889 3.40791 3.47194 - 3.52333 3.56693 3.60939 3.65234 3.69599 3.74021 - 3.78506 3.83043 3.87567 3.91959 3.96171 4.00520 - 4.05383 4.07995 4.10618 4.12654 4.14856 4.15761 - 4.16917 4.16572 4.15953 4.16210 4.15924 4.17664 - 3.82973 3.96256 4.07271 4.16125 4.22791 4.27407 - 4.30342 4.32285 4.34138 4.36123 4.38288 4.40644 - 4.43188 4.45911 4.48745 4.51519 4.54143 4.56971 - 4.60430 4.62368 4.64255 4.65791 4.67750 4.67675 - 4.66806 4.67531 4.68723 4.68289 4.68803 4.65818 - 4.47548 4.60083 4.69875 4.77142 4.81908 4.84376 - 4.85007 4.84597 4.84155 4.83948 4.84028 4.84426 - 4.85137 4.86154 4.87401 4.88662 4.89808 4.91238 - 4.93438 4.94797 4.96080 4.97166 4.98770 4.98194 - 4.96380 4.97577 4.99576 4.98833 4.99705 4.94607 - 5.43892 5.55383 5.61606 5.63685 5.62831 5.60430 - 5.57013 5.53105 5.49310 5.45833 5.42731 5.39995 - 5.37538 5.35292 5.33337 5.31805 5.30818 5.30367 - 5.30413 5.30617 5.30927 5.31396 5.32227 5.31522 - 5.30036 5.30956 5.32421 5.32197 5.32609 5.28557 - 6.16307 6.23754 6.25914 6.24048 6.19302 6.12978 - 6.05693 5.98129 5.91043 5.84632 5.78866 5.73635 - 5.68860 5.64429 5.60404 5.56850 5.53852 5.51476 - 5.49787 5.49206 5.48771 5.48611 5.48652 5.48239 - 5.47484 5.47912 5.48596 5.48489 5.48681 5.46769 - 6.73479 6.77731 6.76220 6.70496 6.61908 6.51950 - 6.41313 6.30711 6.20943 6.12151 6.04207 5.96923 - 5.90247 5.84072 5.78415 5.73246 5.68573 5.64549 - 5.61341 5.60051 5.58929 5.58204 5.57605 5.57372 - 5.57102 5.57174 5.57298 5.57274 5.57313 5.56930 - 7.20412 7.22338 7.17595 7.08160 6.95831 6.82510 - 6.68935 6.55768 6.43756 6.32971 6.23185 6.14157 - 6.05867 5.98247 5.91259 5.84755 5.78653 5.73190 - 5.68622 5.66676 5.64906 5.63665 5.62557 5.62354 - 5.62261 5.62150 5.61996 5.62011 5.61974 5.62347 - 7.93845 7.92127 7.81633 7.65330 7.46113 7.26856 - 7.08334 6.90989 6.75318 6.61269 6.48432 6.36501 - 6.25530 6.15552 6.06417 5.97769 5.89358 5.81550 - 5.74714 5.71637 5.68740 5.66626 5.64719 5.64384 - 5.64226 5.64007 5.63704 5.63737 5.63663 5.64415 - 8.49376 8.44071 8.28274 8.05851 7.80678 7.56442 - 7.33875 7.13179 6.94550 6.77825 6.62479 6.48168 - 6.35002 6.23087 6.12209 6.01860 5.91683 5.82099 - 5.73511 5.69546 5.65758 5.62958 5.60406 5.59878 - 5.59520 5.59314 5.59054 5.59075 5.59016 5.59623 - 9.49672 9.23206 8.93867 8.63145 8.31553 7.99755 - 7.68607 7.39280 7.12985 6.89839 6.69539 6.51618 - 6.35340 6.20151 6.05917 5.92254 5.78950 5.66338 - 5.54947 5.49772 5.44614 5.40525 5.36756 5.35894 - 5.35195 5.35077 5.34964 5.34973 5.34947 5.35054 - 10.18917 9.72541 9.28093 8.86433 8.47396 8.10889 - 7.76827 7.45181 7.15969 6.89103 6.64462 6.41898 - 6.21208 6.02302 5.85346 5.70328 5.56975 5.43935 - 5.29970 5.22976 5.16763 5.12613 5.08047 5.06818 - 5.06093 5.06038 5.05944 5.05928 5.05931 5.05879 - 10.87224 10.24174 9.65474 9.11391 8.61497 8.15588 - 7.73534 7.35114 7.00164 6.68468 6.39747 6.13674 - 5.89786 5.67788 5.47780 5.29842 5.13642 4.97951 - 4.81733 4.73770 4.66585 4.61571 4.55823 4.54261 - 4.53533 4.53460 4.53277 4.53271 4.53237 4.53343 - 11.23553 10.49136 9.81151 9.19064 8.62328 8.10580 - 7.63622 7.21112 6.82717 6.48112 6.16920 5.88695 - 5.62819 5.38872 5.16903 4.96966 4.78778 4.61126 - 4.43079 4.34260 4.26240 4.20550 4.14056 4.12314 - 4.11463 4.11319 4.11018 4.11019 4.10956 4.11372 - 11.44334 10.60959 9.86340 9.18992 8.58181 8.03264 - 7.53786 7.09142 6.68734 6.32157 5.99056 5.69010 - 5.41460 5.15973 4.92412 4.70486 4.49950 4.30533 - 4.12186 4.03413 3.94573 3.87454 3.80464 3.78847 - 3.77713 3.77498 3.77099 3.77026 3.77079 3.77719 - 11.57845 10.67811 9.88344 9.17057 8.53151 7.95814 - 7.44379 6.98087 6.56203 6.18269 5.83903 5.52673 - 5.24005 4.97450 4.72832 4.49810 4.28103 4.07446 - 3.87707 3.78182 3.68616 3.60981 3.53568 3.51805 - 3.50447 3.50184 3.49741 3.49664 3.49716 3.50464 - 11.71115 10.72660 9.87295 9.11157 8.43374 7.82992 - 7.29043 6.80598 6.36799 5.97138 5.61194 5.28496 - 4.98446 4.70554 4.44579 4.20091 3.96696 3.74155 - 3.52178 3.41382 3.30540 3.21938 3.13642 3.11547 - 3.09712 3.09419 3.09078 3.09025 3.09035 3.09453 - 11.75263 10.72142 9.83711 9.05009 8.35150 7.73067 - 7.17672 6.67961 6.23048 5.82404 5.45579 5.12076 - 4.81268 4.52637 4.25887 4.00509 3.76019 3.52101 - 3.28390 3.16540 3.04564 2.95012 2.85752 2.83320 - 2.81076 2.80799 2.80650 2.80638 2.80590 2.80420 - 11.70889 10.63737 9.73203 8.92646 8.21285 7.57682 - 7.00839 6.49793 6.03725 5.62090 5.24402 4.90126 - 4.58602 4.29257 4.01697 3.75259 3.49254 3.23062 - 2.96054 2.82021 2.67452 2.55457 2.43580 2.40543 - 2.37921 2.37667 2.37632 2.37640 2.37559 2.37027 - 11.60189 10.53449 9.64079 8.84355 8.13561 7.50105 - 6.93166 6.41928 5.95696 5.53939 5.16162 4.81816 - 4.50231 4.20807 3.93077 3.66253 3.39467 3.11796 - 2.82186 2.66324 2.49399 2.35003 2.20476 2.17075 - 2.14653 2.14353 2.13962 2.13894 2.13908 2.14330 - 11.38421 10.35471 9.50514 8.74366 8.06010 7.44134 - 6.88175 6.37586 5.91905 5.50649 5.13332 4.79411 - 4.48216 4.19116 3.91544 3.64530 3.36911 3.07254 - 2.73749 2.54940 2.34207 2.15745 1.96284 1.92256 - 1.90777 1.90317 1.88644 1.88279 1.88759 1.92362 - 11.21243 10.22155 9.41541 8.68978 8.03167 7.43146 - 6.88536 6.38975 5.94163 5.53673 5.17032 4.83715 - 4.53062 4.24427 3.97189 3.70262 3.42277 3.11390 - 2.75137 2.54045 2.30120 2.08282 1.84883 1.80040 - 1.78501 1.77973 1.75755 1.75215 1.76055 1.82051 - 11.08513 10.12535 9.35603 8.66044 8.02476 7.44182 - 6.90906 6.42417 5.98525 5.58844 5.22919 4.90232 - 4.60133 4.31964 4.05077 3.78318 3.50184 3.18546 - 2.80403 2.57576 2.30940 2.06049 1.78682 1.73009 - 1.71517 1.70932 1.68210 1.67537 1.68571 1.75939 - 10.98808 10.05323 9.31522 8.64443 8.02829 7.46084 - 6.94056 6.46594 6.03594 5.64701 5.29474 4.97405 - 4.67846 4.40135 4.13607 3.87069 3.58921 3.26821 - 2.87289 2.63065 2.34103 2.06437 1.75311 1.68734 - 1.67068 1.66455 1.63449 1.62696 1.63832 1.71891 - 10.85056 9.95362 9.26500 8.63299 8.04876 7.50751 - 7.00898 6.55283 6.13906 5.76459 5.42525 5.11613 - 4.83073 4.56239 4.30434 4.04429 3.76499 3.43995 - 3.02630 2.76274 2.43457 2.10889 1.72854 1.64407 - 1.61966 1.61323 1.58087 1.57260 1.58448 1.66914 - 10.75928 9.89030 9.23800 8.63508 8.07549 7.55518 - 7.07459 6.63406 6.23425 5.87240 5.54453 5.24584 - 4.96975 4.70960 4.45867 4.20451 3.92927 3.60449 - 3.18066 2.90182 2.54284 2.17508 1.73228 1.62913 - 1.59345 1.58669 1.55442 1.54601 1.55735 1.63991 - 10.63409 9.81089 9.21526 8.66047 8.14272 7.65931 - 7.21142 6.80029 6.42739 6.09042 5.78572 5.50857 - 5.25232 5.01019 4.77576 4.53685 4.27521 3.96025 - 3.53067 3.22985 2.81642 2.36680 1.78825 1.64008 - 1.56857 1.56028 1.53231 1.52470 1.53270 1.60115 - 10.57747 9.77996 9.21677 8.69111 8.19967 7.74054 - 7.31506 6.92476 6.57144 6.25304 5.96606 5.70590 - 5.46577 5.23886 5.01915 4.79486 4.54799 4.24758 - 3.82488 3.51455 3.06683 2.55750 1.86625 1.67668 - 1.56532 1.55415 1.53074 1.52430 1.52850 1.58190 - 10.53874 9.76464 9.23596 8.74290 8.28273 7.85414 - 7.45820 7.09636 6.77031 6.47830 6.21715 5.98245 - 5.76737 5.56522 5.37051 5.17214 4.95281 4.68194 - 4.28267 3.96914 3.48580 2.89908 2.03194 1.76964 - 1.57706 1.55689 1.53771 1.53312 1.53113 1.56305 - 10.53475 9.76903 9.25644 8.77999 8.33731 7.92708 - 7.54990 7.20682 6.89909 6.62511 6.38199 6.16558 - 5.96925 5.78648 5.61218 5.43554 5.23957 4.99394 - 4.61835 4.31028 3.81590 3.18752 2.19221 1.86644 - 1.59490 1.56335 1.54283 1.53928 1.53310 1.55361 - 10.54786 9.77982 9.27203 8.80384 8.37231 7.97543 - 7.61266 7.28374 6.98863 6.72615 6.49456 6.29129 - 6.11197 5.95094 5.80013 5.64171 5.45389 5.21321 - 4.85274 4.56431 4.10308 3.47587 2.33572 1.93946 - 1.61772 1.57660 1.54420 1.54085 1.53649 1.54794 - 10.55195 9.78821 9.28612 8.82451 8.40056 8.01214 - 7.65854 7.33924 7.05391 6.80139 6.58003 6.38737 - 6.21903 6.06970 5.93231 5.79079 5.62369 5.40324 - 5.05804 4.77606 4.32152 3.69144 2.48417 2.02901 - 1.63257 1.58259 1.54735 1.54166 1.53868 1.54419 - 10.55505 9.80267 9.30798 8.85322 8.43711 8.05881 - 7.71728 7.41140 7.14000 6.90182 6.69524 6.51781 - 6.36535 6.23311 6.11578 6.00025 5.86674 5.68290 - 5.36796 5.09848 4.66385 4.04703 2.75356 2.19681 - 1.66347 1.59496 1.54926 1.54252 1.53910 1.53953 - 10.55810 9.80690 9.31565 8.86762 8.45967 8.08953 - 7.75588 7.45750 7.19318 6.96206 6.76313 6.59474 - 6.45354 6.33556 6.23569 6.14054 6.02980 5.87076 - 5.58672 5.33884 4.92930 4.32450 2.97835 2.35971 - 1.69729 1.60538 1.54844 1.54398 1.53406 1.53672 - 10.54604 9.81168 9.32933 8.88959 8.48976 8.12789 - 7.80280 7.51340 7.25877 7.03834 6.85153 6.69711 - 6.57237 6.47435 6.39966 6.33751 6.26969 6.16193 - 5.93695 5.72763 5.37846 4.83959 3.45542 2.69559 - 1.77947 1.64224 1.54775 1.54012 1.52609 1.53297 - 10.52438 9.81259 9.33759 8.90302 8.50684 8.14778 - 7.82517 7.53869 7.28823 7.07335 6.89350 6.74723 - 6.63158 6.54389 6.48262 6.44051 6.40201 6.33014 - 6.15223 5.97688 5.66862 5.18004 3.82886 2.98752 - 1.85894 1.67841 1.55135 1.53750 1.52622 1.53112 - 10.50174 9.82106 9.34533 8.91181 8.51834 8.16341 - 7.84600 7.56532 7.32082 7.11202 6.93844 6.79869 - 6.68987 6.61042 6.56232 6.54532 6.54932 6.53097 - 6.41510 6.28366 6.04447 5.62674 4.33726 3.46417 - 2.02392 1.76460 1.56262 1.54385 1.52233 1.52926 - 10.47415 9.82449 9.35046 8.91855 8.52675 8.17361 - 7.85818 7.57972 7.33772 7.13185 6.96160 6.82586 - 6.72190 6.64853 6.60862 6.60343 6.62582 6.63855 - 6.57357 6.47476 6.27014 5.89835 4.71682 3.82490 - 2.17714 1.85567 1.57954 1.55123 1.52226 1.52833 - 10.43524 9.81891 9.35337 8.92686 8.53793 8.18581 - 7.87018 7.59108 7.34890 7.14363 6.97518 6.84301 - 6.74532 6.68084 6.64984 6.64753 6.66531 6.68567 - 6.66572 6.60348 6.43612 6.11187 5.01108 4.07873 - 2.32574 1.95745 1.59869 1.55242 1.52220 1.52778 - 10.42140 9.82056 9.35592 8.93029 8.54228 8.19108 - 7.87636 7.59810 7.35664 7.15211 6.98462 6.85403 - 6.75906 6.69879 6.67294 6.67536 6.69815 6.73283 - 6.74654 6.70591 6.55280 6.23258 5.21840 4.35786 - 2.46211 2.03099 1.61368 1.56819 1.52410 1.52741 - 10.40267 9.82155 9.35804 8.93361 8.54695 8.19727 - 7.88420 7.60773 7.36820 7.16577 7.00063 6.87271 - 6.78087 6.72438 6.70331 6.71217 6.74448 6.79533 - 6.84009 6.82702 6.71805 6.45188 5.53897 4.72427 - 2.72307 2.19891 1.64863 1.58280 1.52534 1.52694 - 10.39084 9.82327 9.36022 8.93553 8.54862 8.19932 - 7.88734 7.61273 7.37576 7.17612 7.01315 6.88643 - 6.79549 6.74036 6.72164 6.73488 6.77503 6.83864 - 6.89863 6.89568 6.81836 6.62008 5.80423 4.95934 - 2.94385 2.37081 1.68914 1.58065 1.53953 1.52666 - 10.37107 9.82406 9.36233 8.93827 8.55202 8.20394 - 7.89360 7.62077 7.38539 7.18745 7.02676 6.90310 - 6.81549 6.76370 6.74877 6.76728 6.81541 6.89085 - 6.97587 7.00311 6.98618 6.84905 6.13891 5.47326 - 3.43674 2.69844 1.77650 1.63074 1.53633 1.52628 - 10.36040 9.82431 9.36315 8.93958 8.55380 8.20618 - 7.89634 7.62404 7.38926 7.19198 7.03218 6.90958 - 6.82323 6.77297 6.76018 6.78205 6.83550 6.91865 - 7.01609 7.05615 7.06913 6.98152 6.37581 5.78645 - 3.81565 2.98670 1.86345 1.67166 1.54617 1.52609 - 10.34944 9.82446 9.36387 8.94098 8.55580 8.20852 - 7.89883 7.62659 7.39198 7.19505 7.03586 6.91425 - 6.82909 6.78025 6.76960 6.79530 6.85503 6.94615 - 7.05667 7.11090 7.15265 7.11971 6.66844 6.18639 - 4.37659 3.44641 2.02840 1.75764 1.56651 1.52590 - 10.34397 9.82459 9.36423 8.94173 8.55691 8.20986 - 7.90027 7.62809 7.39360 7.19690 7.03810 6.91700 - 6.83246 6.78434 6.77476 6.80229 6.86504 6.96029 - 7.07816 7.13959 7.19345 7.18889 6.84582 6.43513 - 4.77216 3.80201 2.18469 1.84532 1.58615 1.52581 - 10.34057 9.82474 9.36445 8.94212 8.55754 8.21072 - 7.90139 7.62949 7.39529 7.19889 7.04041 6.91964 - 6.83552 6.78795 6.77907 6.80748 6.87153 6.96925 - 7.09230 7.15783 7.21752 7.22970 6.96519 6.60515 - 5.06417 4.08713 2.33655 1.93275 1.60482 1.52576 - 10.35506 9.83046 9.36364 8.93846 8.55342 8.20742 - 7.89964 7.62955 7.39687 7.20156 7.04351 6.92212 - 6.83538 6.78337 6.77137 6.80511 6.88596 6.99427 - 7.10622 7.16506 7.22875 7.25800 7.04622 6.72962 - 5.28730 4.32327 2.47875 2.02332 1.62151 1.52573 - 10.33427 9.82491 9.36491 8.94270 8.55826 8.21177 - 7.90287 7.63152 7.39789 7.20207 7.04406 6.92379 - 6.84034 6.79374 6.78592 6.81494 6.87931 6.98028 - 7.11277 7.18539 7.25611 7.29426 7.15363 6.88939 - 5.61218 4.68699 2.73550 2.19950 1.65696 1.52571 - 10.33144 9.82485 9.36513 8.94290 8.55829 8.21164 - 7.90265 7.63122 7.39756 7.20171 7.04367 6.92337 - 6.84005 6.79383 6.78641 6.81531 6.87897 6.98048 - 7.11671 7.19335 7.27293 7.32180 7.20801 6.98614 - 5.83122 4.95555 2.96343 2.36604 1.68928 1.52570 - 0.43541 0.45798 0.48159 0.50632 0.53216 0.55907 - 0.58695 0.61564 0.64494 0.67459 0.70429 0.73370 - 0.76243 0.79038 0.81835 0.84896 0.88428 0.92072 - 0.95209 0.96447 0.97510 0.98383 1.00080 1.00611 - 1.01039 1.01053 1.01043 1.01064 1.01051 1.01193 - 0.64284 0.67333 0.70485 0.73755 0.77140 0.80635 - 0.84231 0.87921 0.91691 0.95529 0.99419 1.03350 - 1.07328 1.11347 1.15366 1.19343 1.23274 1.27343 - 1.31724 1.33941 1.36005 1.37513 1.39346 1.39646 - 1.39135 1.39538 1.40507 1.40418 1.40641 1.38250 - 0.84091 0.87869 0.91753 0.95764 0.99896 1.04140 - 1.08485 1.12917 1.17417 1.21970 1.26554 1.31157 - 1.35789 1.40446 1.45080 1.49645 1.54149 1.58832 - 1.63954 1.66619 1.69203 1.71159 1.73237 1.73472 - 1.72944 1.73394 1.74430 1.74333 1.74572 1.71994 - 1.20618 1.25779 1.31017 1.36362 1.41796 1.47296 - 1.52833 1.58379 1.63900 1.69369 1.74760 1.80070 - 1.85345 1.90623 1.95859 2.01018 2.06143 2.11580 - 2.17703 2.20929 2.23983 2.26191 2.28588 2.29140 - 2.29379 2.29540 2.29853 2.29834 2.29900 2.29213 - 1.53522 1.59864 1.66226 1.72645 1.79087 1.85512 - 1.91877 1.98133 2.04232 2.10138 2.15830 2.21325 - 2.26726 2.32129 2.37506 2.42841 2.48213 2.54022 - 2.60679 2.64170 2.67313 2.69420 2.71982 2.72936 - 2.73981 2.73802 2.73311 2.73378 2.73255 2.74692 - 1.83385 1.90690 1.97941 2.05183 2.12368 2.19441 - 2.26341 2.33007 2.39378 2.45410 2.51097 2.56479 - 2.61724 2.66988 2.72267 2.77565 2.82985 2.88943 - 2.95833 2.99410 3.02469 3.04362 3.06992 3.08274 - 3.09897 3.09457 3.08371 3.08503 3.08241 3.11261 - 2.10674 2.18729 2.26650 2.34490 2.42189 2.49677 - 2.56882 2.63730 2.70154 2.76108 2.81600 2.86695 - 2.91627 2.96613 3.01667 3.06815 3.12174 3.18144 - 3.25064 3.28614 3.31517 3.33181 3.35816 3.37306 - 3.39225 3.38636 3.37227 3.37393 3.37061 3.40942 - 2.58933 2.67914 2.76603 2.85071 2.93236 3.01014 - 3.08314 3.15050 3.21150 3.26576 3.31364 3.35637 - 3.39738 3.43986 3.48432 3.53135 3.58216 3.63970 - 3.70574 3.73881 3.76430 3.77748 3.80273 3.81815 - 3.83546 3.82984 3.81698 3.81849 3.81559 3.85119 - 2.97703 3.09963 3.20779 3.30188 3.38126 3.44642 - 3.49953 3.54516 3.58953 3.63406 3.67879 3.72334 - 3.76737 3.81066 3.85341 3.89655 3.94122 3.98826 - 4.03812 4.06357 4.08847 4.10777 4.13067 4.13984 - 4.15157 4.14805 4.14169 4.14431 4.14140 4.15923 - 3.80092 3.93554 4.04669 4.13541 4.20148 4.24645 - 4.27432 4.29248 4.31055 4.33090 4.35398 4.37976 - 4.40791 4.43795 4.46879 4.49792 4.52387 4.55138 - 4.58614 4.60587 4.62476 4.63986 4.65971 4.65876 - 4.64954 4.65709 4.66953 4.66500 4.67039 4.63919 - 4.44348 4.57347 4.67415 4.74760 4.79418 4.81628 - 4.81913 4.81174 4.80534 4.80298 4.80525 4.81243 - 4.82432 4.84032 4.85848 4.87383 4.88320 4.89408 - 4.91582 4.93057 4.94436 4.95549 4.97151 4.96550 - 4.94666 4.95905 4.97976 4.97204 4.98109 4.92827 - 5.41439 5.51339 5.57762 5.61144 5.61619 5.59536 - 5.55529 5.50609 5.45971 5.41977 5.38691 5.36150 - 5.34368 5.33261 5.32574 5.31630 5.29993 5.28616 - 5.28712 5.29320 5.29841 5.30216 5.30999 5.30422 - 5.28858 5.29828 5.31453 5.30845 5.31557 5.27376 - 6.13864 6.19940 6.22343 6.21706 6.18237 6.12349 - 6.04724 5.96399 5.88572 5.81599 5.75548 5.70417 - 5.66217 5.62821 5.59965 5.56958 5.53354 5.50117 - 5.48493 5.48320 5.48103 5.47856 5.47908 5.47597 - 5.46859 5.47283 5.47998 5.47728 5.48044 5.46184 - 6.71466 6.73876 6.72510 6.68172 6.61125 6.51838 - 6.41034 6.29768 6.19256 6.09839 6.01565 5.94377 - 5.88235 5.82954 5.78276 5.73541 5.68327 5.63544 - 5.60389 5.59486 5.58601 5.57836 5.57269 5.57111 - 5.56915 5.56952 5.57026 5.56993 5.57031 5.56807 - 7.17983 7.20102 7.15496 7.06192 6.94061 6.81055 - 6.67825 6.54881 6.42820 6.31828 6.21937 6.13051 - 6.05042 5.97726 5.91009 5.84636 5.78440 5.72739 - 5.68070 5.66276 5.64746 5.63694 5.62577 5.62401 - 5.62376 5.62283 5.62046 5.62005 5.62053 5.62562 - 7.94189 7.87198 7.76282 7.62613 7.46592 7.28836 - 7.10196 6.91826 6.75035 6.60144 6.47052 6.35534 - 6.25242 6.15843 6.07089 5.98475 5.89689 5.81387 - 5.74510 5.71742 5.69171 5.67215 5.65283 5.64966 - 5.64893 5.64639 5.64263 5.64383 5.64233 5.65133 - 8.51171 8.38444 8.21923 8.02929 7.81926 7.59580 - 7.36782 7.14732 6.94734 6.77082 6.61584 6.47915 - 6.35556 6.24097 6.13318 6.02826 5.92378 5.82456 - 5.73804 5.70107 5.66653 5.64060 5.61476 5.60949 - 5.60636 5.60422 5.60128 5.60209 5.60100 5.60760 - 9.48353 9.21885 8.92713 8.62290 8.31103 7.99776 - 7.69126 7.40265 7.14349 6.91482 6.71354 6.53489 - 6.37135 6.21748 6.07283 5.93552 5.80463 5.68109 - 5.56765 5.51579 5.46537 5.42655 5.38958 5.38083 - 5.37333 5.37257 5.37214 5.37197 5.37202 5.37130 - 10.17470 9.71586 9.27588 8.86334 8.47660 8.11476 - 7.77705 7.46316 7.17328 6.90657 6.66185 6.43765 - 6.23195 6.04388 5.87517 5.72579 5.59326 5.46470 - 5.32810 5.25954 5.19725 5.15447 5.11043 5.09951 - 5.09087 5.09054 5.09086 5.09060 5.09093 5.08739 - 10.86374 10.23766 9.65459 9.11706 8.62096 8.16434 - 7.74589 7.36350 7.01557 6.70006 6.41428 6.15504 - 5.91793 5.70014 5.50273 5.32653 5.16822 5.01519 - 4.85623 4.77730 4.70453 4.65269 4.59743 4.58367 - 4.57491 4.57432 4.57374 4.57360 4.57357 4.57166 - 11.22882 10.48947 9.81346 9.19587 8.63123 8.11599 - 7.64825 7.22470 6.84208 6.49724 6.18657 5.90575 - 5.64883 5.41183 5.19526 4.99968 4.82213 4.64981 - 4.47235 4.38476 4.30398 4.24602 4.18283 4.16691 - 4.15774 4.15628 4.15382 4.15380 4.15331 4.15630 - 11.43393 10.60761 9.86705 9.19767 8.59252 8.04544 - 7.55214 7.10692 6.70402 6.33957 6.01001 5.71123 - 5.43769 5.18516 4.95229 4.73622 4.53447 4.34403 - 4.16382 4.07701 3.98819 3.91579 3.84684 3.83160 - 3.82070 3.81839 3.81402 3.81326 3.81383 3.82126 - 11.57087 10.67545 9.88514 9.17635 8.54099 7.97101 - 7.45963 6.99924 6.58240 6.20463 5.86223 5.55101 - 5.26543 5.00116 4.75664 4.52881 4.31502 4.11226 - 3.91846 3.82433 3.72821 3.65029 3.57631 3.55954 - 3.54689 3.54400 3.53861 3.53767 3.53840 3.54828 - 11.70358 10.72201 9.87184 9.11444 8.44089 7.84136 - 7.30593 6.82498 6.38964 5.99489 5.63668 5.31047 - 5.01046 4.73198 4.47291 4.22936 3.99773 3.77525 - 3.55855 3.45186 3.34384 3.25721 3.17331 3.15249 - 3.13517 3.13207 3.12761 3.12686 3.12724 3.13390 - 11.74141 10.71514 9.83503 9.05200 8.35709 7.73965 - 7.18875 6.69432 6.24746 5.84287 5.47617 5.14244 - 4.83547 4.55015 4.28364 4.03098 3.78747 3.54982 - 3.31442 3.19711 3.07905 2.98487 2.89093 2.86583 - 2.84395 2.84125 2.83932 2.83907 2.83878 2.83793 - 11.68803 10.62651 9.72757 8.92595 8.21447 7.57940 - 7.01136 6.50130 6.04158 5.62677 5.25194 4.91159 - 4.59898 4.30817 4.03505 3.77254 3.51347 3.25182 - 2.98182 2.84201 2.69813 2.58041 2.46158 2.43051 - 2.40406 2.40171 2.40173 2.40186 2.40101 2.39471 - 11.57582 10.51892 9.63172 8.83835 8.13235 7.49846 - 6.92909 6.41671 5.95493 5.53854 5.16249 4.82128 - 4.50814 4.21694 3.94283 3.67749 3.41188 3.13675 - 2.84128 2.68231 2.51192 2.36707 2.22436 2.19171 - 2.16727 2.16408 2.16026 2.15964 2.15966 2.16409 - 11.36286 10.32832 9.47695 8.71684 8.03708 7.42391 - 6.87101 6.37217 5.92200 5.51519 5.14610 4.80833 - 4.49370 4.19589 3.91242 3.63945 3.36895 3.08199 - 2.75503 2.56881 2.35965 2.17090 1.97392 1.93413 - 1.92487 1.92066 1.90178 1.89762 1.90285 1.94264 - 11.17994 10.18161 9.37413 8.65272 8.00273 7.41309 - 6.87836 6.39324 5.95308 5.55326 5.18889 4.85433 - 4.54238 4.24717 3.96571 3.69306 3.41886 3.11905 - 2.76311 2.55387 2.31479 2.09623 1.86285 1.81101 - 1.79215 1.78999 1.77514 1.76925 1.77019 1.83951 - 11.04328 10.07610 9.30692 8.61802 7.99367 7.42464 - 6.90629 6.43395 6.00360 5.61113 5.25228 4.92201 - 4.61387 4.32239 4.04420 3.77358 3.49837 3.19041 - 2.81292 2.58491 2.31862 2.07160 1.80202 1.73980 - 1.71901 1.71738 1.70023 1.69266 1.69205 1.77841 - 10.93860 9.99738 9.26112 8.59916 7.99672 7.44557 - 6.94172 6.48102 6.05989 5.67469 5.32158 4.99603 - 4.69218 4.40485 4.13039 3.86247 3.58752 3.27395 - 2.87945 2.63586 2.34620 2.07353 1.76982 1.69684 - 1.67227 1.67122 1.65338 1.64474 1.64230 1.73790 - 10.79023 9.88953 9.20549 8.58540 8.01799 7.49596 - 7.01630 6.57556 6.17085 5.79914 5.45727 5.14141 - 4.84653 4.56787 4.30151 4.04014 3.76807 3.44832 - 3.02910 2.76089 2.43247 2.11489 1.74838 1.65405 - 1.61863 1.61842 1.60131 1.59151 1.58546 1.68803 - 10.69296 9.82223 9.17628 8.58701 8.04590 7.54630 - 7.08574 6.66126 6.27041 5.91061 5.57912 5.27259 - 4.98654 4.71653 4.45842 4.20438 3.93716 3.61572 - 3.18038 2.89385 2.53446 2.17854 1.75500 1.64005 - 1.59123 1.59136 1.57615 1.56593 1.55666 1.65871 - 10.56544 9.74175 9.15335 8.61293 8.11430 7.65214 - 7.22464 6.82949 6.46487 6.12880 5.81912 5.53313 - 5.26705 5.01689 4.77845 4.54327 4.29196 3.97717 - 3.52446 3.20978 2.79572 2.36548 1.81666 1.65375 - 1.56636 1.56546 1.55594 1.54615 1.53068 1.61978 - 10.56515 9.73993 9.16389 8.63896 8.15844 7.71681 - 7.31140 6.93893 6.59656 6.28194 5.99259 5.72522 - 5.47498 5.23746 5.00967 4.78563 4.55054 4.26598 - 3.85047 3.53362 3.06528 2.53766 1.86205 1.68515 - 1.58222 1.57014 1.54337 1.53672 1.54346 1.60042 - 10.52015 9.72764 9.19018 8.69786 8.24571 7.82989 - 7.44870 7.10018 6.78269 6.49411 6.23190 5.99245 - 5.77013 5.55989 5.35861 5.15984 4.94917 4.69082 - 4.29876 3.98153 3.48364 2.88390 2.03073 1.77862 - 1.59370 1.57347 1.55269 1.54803 1.54768 1.58144 - 10.51034 9.73452 9.21690 8.74140 8.30422 7.90252 - 7.53517 7.20104 6.89924 6.62793 6.38457 6.16545 - 5.96463 5.77661 5.59790 5.42086 5.23069 4.99400 - 4.62495 4.31586 3.81360 3.17809 2.19394 1.87574 - 1.61102 1.58003 1.55923 1.55572 1.55046 1.57191 - 10.51025 9.74505 9.23895 8.77341 8.34538 7.95256 - 7.59424 7.26983 6.97895 6.71992 6.49032 6.28649 - 6.10243 5.93239 5.77247 5.61390 5.44120 5.22284 - 4.87484 4.57690 4.08179 3.43019 2.34651 1.96957 - 1.62987 1.58728 1.56284 1.55986 1.55133 1.56618 - 10.51206 9.75494 9.25628 8.79732 8.37549 7.98886 - 7.63697 7.31965 7.03678 6.78690 6.56769 6.37564 - 6.20479 6.04932 5.90504 5.76216 5.60468 5.40238 - 5.07375 4.78794 4.30536 3.64894 2.48783 2.05885 - 1.64920 1.59486 1.56462 1.56177 1.55111 1.56239 - 10.52111 9.77058 9.27790 8.82622 8.41281 8.03568 - 7.69401 7.38721 7.11475 6.87569 6.66868 6.49165 - 6.34065 6.21105 6.09697 5.98399 5.85053 5.66255 - 5.34566 5.08280 4.66086 4.05376 2.75704 2.20564 - 1.67855 1.61096 1.56805 1.55966 1.55775 1.55768 - 10.51910 9.77708 9.29009 8.84406 8.43632 8.06506 - 7.72953 7.42923 7.16363 6.93204 6.73347 6.56625 - 6.42705 6.31187 6.21527 6.12303 6.01327 5.85011 - 5.55932 5.31383 4.91811 4.33451 2.98993 2.36097 - 1.70984 1.62240 1.56811 1.55830 1.55590 1.55483 - 10.50704 9.78159 9.30340 8.86565 8.46606 8.10317 - 7.77630 7.48508 7.22924 7.00839 6.82193 6.66865 - 6.54589 6.45057 6.37885 6.31887 6.25087 6.13886 - 5.91046 5.70399 5.35795 4.82782 3.46222 2.70226 - 1.78967 1.65450 1.56671 1.55506 1.54900 1.55104 - 10.48983 9.78231 9.30905 8.87578 8.48048 8.12193 - 7.79953 7.51297 7.26224 7.04702 6.86695 6.72097 - 6.60667 6.52152 6.46302 6.42157 6.38022 6.30571 - 6.12943 5.95546 5.64635 5.15857 3.82483 2.99079 - 1.87055 1.69214 1.56821 1.55473 1.54408 1.54916 - 10.46786 9.79035 9.31601 8.88376 8.49146 8.13760 - 7.82117 7.54133 7.29758 7.08944 6.91637 6.77703 - 6.66852 6.58923 6.54118 6.52415 6.52814 6.51018 - 6.39494 6.26293 6.02107 5.60212 4.32799 3.46497 - 2.03372 1.77665 1.57881 1.56089 1.53997 1.54727 - 10.43988 9.79345 9.32113 8.89078 8.50036 8.14849 - 7.83418 7.55669 7.31554 7.11037 6.94066 6.80531 - 6.70156 6.62823 6.58815 6.58267 6.60477 6.61773 - 6.55374 6.45516 6.24947 5.87733 4.70652 3.82279 - 2.18529 1.86664 1.59536 1.56813 1.53987 1.54633 - 10.42020 9.79581 9.32454 8.89519 8.50586 8.15518 - 7.84220 7.56623 7.32680 7.12359 6.95613 6.82338 - 6.72268 6.65306 6.61796 6.61971 6.65347 6.68709 - 6.65892 6.58476 6.40721 6.07283 4.99274 4.10845 - 2.32847 1.95609 1.61309 1.57537 1.54056 1.54577 - 10.38812 9.78963 9.32631 8.90204 8.51540 8.16560 - 7.85224 7.57532 7.33512 7.13171 6.96508 6.83491 - 6.73964 6.67824 6.65097 6.65292 6.67712 6.71324 - 6.72653 6.68574 6.53455 6.21753 5.20684 4.35119 - 2.46763 2.04031 1.62886 1.58476 1.54165 1.54539 - 10.36949 9.79068 9.32861 8.90555 8.52018 8.17173 - 7.85982 7.58446 7.34594 7.14442 6.98000 6.85248 - 6.76053 6.70340 6.68149 6.69011 6.72330 6.77474 - 6.81861 6.80549 6.69908 6.43655 5.52514 4.71491 - 2.72675 2.20696 1.66315 1.59899 1.54276 1.54492 - 10.35759 9.79247 9.33095 8.90760 8.52186 8.17364 - 7.86265 7.58892 7.35276 7.15379 6.99135 6.86495 - 6.77416 6.71900 6.70016 6.71327 6.75339 6.81676 - 6.87615 6.87330 6.79772 6.60209 5.78854 4.94730 - 2.94616 2.37820 1.70309 1.59608 1.55692 1.54464 - 10.33851 9.79301 9.33259 8.91001 8.52515 8.17819 - 7.86875 7.59662 7.36186 7.16430 7.00363 6.87968 - 6.79218 6.74132 6.72767 6.74653 6.79322 6.86720 - 6.95468 6.98263 6.95497 6.81530 6.15548 5.45816 - 3.41288 2.70342 1.79207 1.63802 1.56737 1.54426 - 10.32794 9.79327 9.33341 8.91125 8.52681 8.18036 - 7.87148 7.59998 7.36590 7.16907 7.00919 6.88617 - 6.79992 6.75078 6.73950 6.76155 6.81263 6.89320 - 6.99595 7.04044 7.03938 6.93310 6.38251 5.80253 - 3.78066 2.97541 1.87861 1.68469 1.57591 1.54407 - 10.31670 9.79363 9.33453 8.91298 8.52900 8.18280 - 7.87405 7.60267 7.36881 7.17253 7.01385 6.89253 - 6.80754 6.75878 6.74812 6.77370 6.83317 6.92385 - 7.03425 7.08845 7.12833 7.09308 6.64602 6.16731 - 4.37028 3.44644 2.03812 1.76988 1.58287 1.54388 - 10.31159 9.79385 9.33475 8.91341 8.52972 8.18380 - 7.87540 7.60450 7.37133 7.17563 7.01686 6.89487 - 6.80992 6.76273 6.75455 6.78175 6.84114 6.93407 - 7.06054 7.12909 7.16983 7.12679 6.82193 6.51464 - 4.72316 3.74288 2.19663 1.87814 1.60442 1.54378 - 10.32523 9.79965 9.33418 8.91018 8.52619 8.18112 - 7.87412 7.60467 7.37251 7.17756 7.01971 6.89838 - 6.81152 6.75923 6.74674 6.77971 6.85941 6.96610 - 7.07518 7.13095 7.18793 7.20398 6.94403 6.58378 - 5.04943 4.08507 2.34381 1.94382 1.61917 1.54373 - 10.32265 9.79975 9.33440 8.91054 8.52668 8.18174 - 7.87489 7.60559 7.37361 7.17886 7.02124 6.90019 - 6.81368 6.76179 6.74983 6.78347 6.86403 6.97191 - 7.08329 7.14191 7.20566 7.23514 7.02331 6.70772 - 5.27488 4.31709 2.48447 2.03250 1.63685 1.54368 - 10.30209 9.79410 9.33537 8.91445 8.53125 8.18585 - 7.87799 7.60762 7.37498 7.17988 7.02196 6.90108 - 6.81737 6.77147 6.76488 6.79443 6.85741 6.95550 - 7.08945 7.16728 7.23824 7.25649 7.10619 6.93136 - 5.59711 4.62690 2.73481 2.23442 1.66397 1.54363 - 10.29898 9.79382 9.33555 8.91474 8.53144 8.18589 - 7.87782 7.60726 7.37450 7.17947 7.02199 6.90187 - 6.81859 6.77236 6.76486 6.79356 6.85691 6.95840 - 7.09437 7.17031 7.25009 7.29979 7.18457 6.96273 - 5.81458 4.94440 2.96541 2.37243 1.70334 1.54359 - 0.42913 0.45155 0.47502 0.49963 0.52535 0.55214 - 0.57988 0.60839 0.63740 0.66664 0.69579 0.72444 - 0.75217 0.77887 0.80555 0.83530 0.87060 0.90762 - 0.93963 0.95228 0.96308 0.97200 0.98993 0.99561 - 1.00022 1.00032 1.00012 1.00043 1.00092 1.00188 - 0.63427 0.66476 0.69624 0.72886 0.76257 0.79730 - 0.83298 0.86948 0.90669 0.94445 0.98259 1.02105 - 1.05990 1.09914 1.13842 1.17740 1.21626 1.25726 - 1.30266 1.32604 1.34753 1.36290 1.38221 1.38556 - 1.37998 1.38458 1.39517 1.39325 1.38962 1.37103 - 0.83053 0.86825 0.90699 0.94696 0.98808 1.03026 - 1.07336 1.11722 1.16168 1.20655 1.25162 1.29680 - 1.34220 1.38788 1.43340 1.47842 1.52321 1.57060 - 1.62376 1.65183 1.67880 1.69892 1.72076 1.72331 - 1.71743 1.72262 1.73408 1.73188 1.72730 1.70778 - 1.19275 1.24416 1.29632 1.34952 1.40356 1.45821 - 1.51318 1.56817 1.62284 1.67691 1.73015 1.78254 - 1.83458 1.88670 1.93853 1.98981 2.04114 2.09637 - 2.15971 2.19348 2.22534 2.24821 2.27318 2.27890 - 2.28107 2.28304 2.28671 2.28595 2.28336 2.27935 - 1.51930 1.58240 1.64570 1.70955 1.77360 1.83748 - 1.90072 1.96286 2.02339 2.08197 2.13840 2.19286 - 2.24643 2.30008 2.35361 2.40693 2.46097 2.52003 - 2.58858 2.62486 2.65757 2.67946 2.70593 2.71574 - 2.72651 2.72457 2.71946 2.72048 2.72117 2.73364 - 1.81586 1.88850 1.96061 2.03264 2.10410 2.17445 - 2.24308 2.30938 2.37275 2.43277 2.48937 2.54294 - 2.59521 2.64775 2.70055 2.75373 2.80840 2.86896 - 2.93959 2.97651 3.00824 3.02792 3.05490 3.06807 - 3.08506 3.08009 3.06841 3.07084 3.07455 3.09876 - 2.08702 2.16710 2.24586 2.32385 2.40045 2.47498 - 2.54673 2.61494 2.67899 2.73838 2.79323 2.84417 - 2.89356 2.94355 2.99431 3.04616 3.10032 3.16094 - 3.23158 3.26801 3.29799 3.31531 3.34218 3.35747 - 3.37769 3.37095 3.35566 3.35895 3.36490 3.39493 - 2.56692 2.65622 2.74266 2.82694 2.90828 2.98582 - 3.05866 3.12598 3.18705 3.24147 3.28964 3.33275 - 3.37420 3.41717 3.46217 3.50978 3.56125 3.61955 - 3.68647 3.72007 3.74618 3.75986 3.78544 3.80118 - 3.81953 3.81298 3.79883 3.80217 3.80988 3.83523 - 2.95294 3.07477 3.18238 3.27610 3.35530 3.42047 - 3.47377 3.51971 3.56446 3.60944 3.65467 3.69979 - 3.74444 3.78840 3.83184 3.87566 3.92095 3.96857 - 4.01900 4.04475 4.06999 4.08959 4.11274 4.12203 - 4.13433 4.13041 4.12322 4.12686 4.13240 4.14188 - 3.77402 3.90808 4.01896 4.10765 4.17393 4.21935 - 4.24786 4.26680 4.28570 4.30695 4.33096 4.35771 - 4.38682 4.41779 4.44949 4.47933 4.50574 4.53347 - 4.56821 4.58786 4.60673 4.62195 4.64198 4.64083 - 4.63108 4.63898 4.65200 4.64717 4.65205 4.62029 - 4.41534 4.54521 4.64602 4.71984 4.76700 4.78989 - 4.79370 4.78736 4.78208 4.78084 4.78427 4.79259 - 4.80558 4.82257 4.84158 4.85756 4.86725 4.87817 - 4.89972 4.91428 4.92797 4.93917 4.95543 4.94917 - 4.92937 4.94241 4.96433 4.95564 4.95875 4.91053 - 5.38587 5.48571 5.55095 5.58587 5.59183 5.57225 - 5.53347 5.48559 5.44054 5.40192 5.37035 5.34618 - 5.32948 5.31937 5.31323 5.30423 5.28798 5.27416 - 5.27510 5.28118 5.28646 5.29034 5.29854 5.29279 - 5.27670 5.28682 5.30392 5.29689 5.29652 5.26192 - 6.11087 6.17328 6.19900 6.19428 6.16120 6.10386 - 6.02908 5.94726 5.87040 5.80205 5.74285 5.69277 - 5.65186 5.61876 5.59083 5.56109 5.52510 5.49273 - 5.47674 5.47524 5.47332 5.47110 5.47207 5.46929 - 5.46214 5.46642 5.47371 5.47047 5.46766 5.45589 - 6.68808 6.71435 6.70286 6.66148 6.59290 6.50176 - 6.39532 6.28418 6.18052 6.08775 6.00633 5.93566 - 5.87528 5.82328 5.77706 5.72999 5.67793 5.63020 - 5.59907 5.59040 5.58193 5.57457 5.56946 5.56836 - 5.56705 5.56721 5.56766 5.56706 5.56279 5.56673 - 7.15477 7.17809 7.13440 7.04374 6.92464 6.79653 - 6.66592 6.53800 6.41885 6.31035 6.21280 6.12519 - 6.04615 5.97378 5.90710 5.84364 5.78182 5.72507 - 5.67893 5.66131 5.64641 5.63632 5.62579 5.62435 - 5.62484 5.62417 5.62122 5.61980 5.61713 5.62769 - 7.91906 7.85206 7.74571 7.61159 7.45372 7.27824 - 7.09373 6.91174 6.74540 6.59797 6.46839 6.35445 - 6.25258 6.15947 6.07260 5.98695 5.89943 5.81678 - 5.74861 5.72134 5.69610 5.67698 5.65836 5.65561 - 5.65544 5.65276 5.64874 5.64968 5.64434 5.65850 - 8.49111 8.36708 8.20490 8.01774 7.81019 7.58893 - 7.36290 7.14414 6.94577 6.77073 6.61710 6.48169 - 6.35926 6.24575 6.13890 6.03475 5.93085 5.83217 - 5.74634 5.70981 5.67581 5.65044 5.62538 5.62038 - 5.61740 5.61533 5.61251 5.61291 5.60786 5.61899 - 9.46709 9.20653 8.91849 8.61743 8.30825 7.99727 - 7.69266 7.40566 7.14795 6.92060 6.72061 6.54332 - 6.38135 6.22931 6.08660 5.95096 5.82120 5.69853 - 5.58612 5.53495 5.48550 5.44770 5.41163 5.40281 - 5.39460 5.39438 5.39494 5.39410 5.39058 5.39209 - 10.16202 9.70722 9.27092 8.86162 8.47770 8.11834 - 7.78277 7.47073 7.18246 6.91720 6.67380 6.45093 - 6.24669 6.06033 5.89359 5.74644 5.61633 5.48993 - 5.35481 5.28690 5.22573 5.18438 5.14148 5.13023 - 5.12052 5.12088 5.12261 5.12182 5.11950 5.11599 - 10.85452 10.23338 9.65442 9.12046 8.62737 8.17330 - 7.75700 7.37643 7.03006 6.71593 6.43145 6.17357 - 5.93807 5.72227 5.52727 5.35391 5.19877 5.04869 - 4.89194 4.81395 4.74245 4.69202 4.63792 4.62394 - 4.61423 4.61418 4.61488 4.61457 4.61392 4.60985 - 11.22079 10.48679 9.81537 9.20157 8.64011 8.12753 - 7.66202 7.24033 6.85931 6.51588 6.20653 5.92710 - 5.67179 5.43675 5.22256 5.02980 4.85544 4.68625 - 4.51139 4.42488 4.34518 4.28811 4.22589 4.21015 - 4.20086 4.19935 4.19718 4.19769 4.20030 4.19883 - 11.42501 10.60553 9.87025 9.20498 8.60298 8.05833 - 7.56692 7.12327 6.72189 6.35890 6.03087 5.73370 - 5.46196 5.21144 4.98083 4.76731 4.56833 4.38074 - 4.20319 4.11753 4.02950 3.95743 3.88929 3.87486 - 3.86450 3.86117 3.85612 3.85722 3.86527 3.86529 - 11.56198 10.67300 9.88780 9.18309 8.55104 7.98372 - 7.47451 7.01597 6.60081 6.22460 5.88373 5.57403 - 5.29003 5.02749 4.78493 4.55933 4.34812 4.14810 - 3.95696 3.86391 3.76830 3.69026 3.61692 3.60134 - 3.58971 3.58532 3.57849 3.57997 3.59098 3.59190 - 11.69319 10.71803 9.87280 9.11948 8.44924 7.85244 - 7.31928 6.84031 6.40675 6.01364 5.65697 5.33225 - 5.03374 4.75681 4.49940 4.25776 4.02832 3.80820 - 3.59374 3.48791 3.38017 3.29325 3.20971 3.18987 - 3.17361 3.16932 3.16338 3.16432 3.17229 3.17326 - 11.72839 10.70916 9.83424 9.05525 8.36348 7.74846 - 7.19953 6.70681 6.26157 5.85860 5.49353 5.16144 - 4.85613 4.57250 4.30774 4.05694 3.81536 3.57959 - 3.34585 3.22918 3.11147 3.01731 2.92355 2.89869 - 2.87728 2.87446 2.87196 2.87161 2.87155 2.87166 - 11.66836 10.61526 9.72193 8.92430 8.21552 7.58229 - 7.01553 6.50663 6.04824 5.63499 5.26191 4.92351 - 4.61293 4.32423 4.05321 3.79264 3.53522 3.27483 - 3.00571 2.86627 2.72286 2.60565 2.48701 2.45552 - 2.42875 2.42720 2.42783 2.42655 2.42000 2.41917 - 11.55105 10.50266 9.62111 8.83169 8.12828 7.49611 - 6.92795 6.41665 5.95616 5.54131 5.16704 4.82781 - 4.51679 4.22780 3.95590 3.69257 3.42861 3.15473 - 2.86009 2.70142 2.53144 2.38703 2.24488 2.21247 - 2.18794 2.18459 2.18097 2.18083 2.18226 2.18495 - 11.33351 10.30454 9.45715 8.70040 8.02353 7.41290 - 6.86221 6.36536 5.91700 5.51184 5.14434 4.80813 - 4.49513 4.19905 3.91743 3.64644 3.37796 3.09285 - 2.76727 2.58151 2.37263 2.18420 1.98894 1.95062 - 1.94215 1.93538 1.91544 1.91643 1.94096 1.96187 - 11.14415 10.15218 9.34922 8.63151 7.98467 7.39770 - 6.86527 6.38213 5.94371 5.54544 5.18250 4.84935 - 4.53890 4.24537 3.96575 3.69510 3.42296 3.12498 - 2.77044 2.56185 2.32372 2.10678 1.87789 1.82703 - 1.80207 1.79728 1.78923 1.79307 1.81946 1.85884 - 11.00373 10.04333 9.27882 8.59378 7.97265 7.40635 - 6.89030 6.41993 5.99123 5.60025 5.24272 4.91376 - 4.60705 4.31720 4.04086 3.77226 3.49919 3.19315 - 2.81719 2.58998 2.32498 2.08015 1.81638 1.75534 - 1.72664 1.72166 1.71347 1.71854 1.75090 1.79783 - 10.89664 9.96241 9.23092 8.57287 7.97370 7.42529 - 6.92374 6.46496 6.04544 5.66164 5.30980 4.98547 - 4.68297 4.39722 4.12460 3.85872 3.58593 3.27435 - 2.88152 2.63886 2.35078 2.08081 1.78388 1.71220 - 1.67848 1.67360 1.66634 1.67241 1.70820 1.75734 - 10.74562 9.85213 9.17283 8.55665 7.99249 7.47319 - 6.99578 6.55689 6.15369 5.78327 5.44254 5.12776 - 4.83412 4.55696 4.29234 4.03300 3.76313 3.44545 - 3.02810 2.76111 2.43477 2.12062 1.76219 1.66930 - 1.62343 1.61897 1.61444 1.62173 1.65979 1.70741 - 10.64725 9.78374 9.14241 8.55697 8.01904 7.52210 - 7.06371 6.64100 6.25159 5.89299 5.56253 5.25701 - 4.97208 4.70347 4.44705 4.19498 3.92992 3.61061 - 3.17735 2.89225 2.53535 2.18337 1.76866 1.65522 - 1.59573 1.59157 1.58977 1.59744 1.63403 1.67801 - 10.52002 9.70314 9.11884 8.58186 8.08610 7.62633 - 7.20080 6.80726 6.44394 6.10892 5.80012 5.51497 - 5.24986 5.00090 4.76395 4.53055 4.28130 3.96870 - 3.51850 3.20565 2.79470 2.36909 1.82959 1.66834 - 1.57222 1.56787 1.57099 1.57741 1.60276 1.63889 - 10.52496 9.70356 9.12954 8.60679 8.12853 7.68918 - 7.28592 6.91539 6.57459 6.26118 5.97276 5.70612 - 5.45656 5.21981 4.99308 4.77067 4.53809 4.25678 - 3.84501 3.52987 3.06284 2.53744 1.87150 1.69940 - 1.59461 1.57805 1.55578 1.56213 1.60860 1.61940 - 10.48129 9.69277 9.15718 8.66678 8.21654 7.80260 - 7.42319 7.07627 6.76009 6.47259 6.21121 5.97244 - 5.75072 5.54111 5.34066 5.14318 4.93454 4.67909 - 4.29086 3.97584 3.48021 2.88351 2.03924 1.79130 - 1.60763 1.58549 1.56798 1.57088 1.59304 1.60024 - 10.47246 9.70073 9.18495 8.71121 8.27575 7.87569 - 7.50985 7.17708 6.87645 6.60611 6.36354 6.14509 - 5.94484 5.75741 5.57940 5.40340 5.21488 4.98070 - 4.61532 4.30864 3.80922 3.17727 2.20156 1.88725 - 1.62578 1.59441 1.57596 1.57652 1.58316 1.59060 - 10.47307 9.71202 9.20775 8.74390 8.31745 7.92610 - 7.56911 7.24591 6.95607 6.69795 6.46912 6.26596 - 6.08247 5.91298 5.75370 5.59599 5.42466 5.20844 - 4.86387 4.56837 4.07642 3.42875 2.35327 1.98015 - 1.64503 1.60297 1.58029 1.57921 1.57606 1.58481 - 10.47529 9.72238 9.22552 8.76824 8.34788 7.96262 - 7.61196 7.29574 7.01384 6.76483 6.54638 6.35499 - 6.18470 6.02979 5.88606 5.74395 5.58759 5.38713 - 5.06164 4.77825 4.29900 3.64673 2.49377 2.06863 - 1.66450 1.61129 1.58246 1.58015 1.57080 1.58097 - 10.48479 9.73848 9.24758 8.79750 8.38549 8.00961 - 7.66906 7.36327 7.09170 6.85345 6.64715 6.47075 - 6.32035 6.19132 6.07779 5.96536 5.83260 5.64588 - 5.33160 5.07107 4.65277 4.05019 2.76133 2.21393 - 1.69357 1.62784 1.58630 1.57719 1.57285 1.57621 - 10.48283 9.74501 9.25980 8.81531 8.40894 8.03892 - 7.70449 7.40515 7.14041 6.90960 6.71169 6.54508 - 6.40647 6.29184 6.19575 6.10401 5.99475 5.83249 - 5.54377 5.30033 4.90814 4.32920 2.99301 2.36828 - 1.72418 1.63879 1.58654 1.57611 1.57016 1.57333 - 10.47057 9.74915 9.27267 8.83645 8.43824 8.07658 - 7.75082 7.46058 7.20561 6.98549 6.79968 6.64698 - 6.52470 6.42984 6.35852 6.29887 6.23117 6.11959 - 5.89236 5.68734 5.34429 4.81866 3.46226 2.70718 - 1.80257 1.66944 1.58501 1.57390 1.56571 1.56949 - 10.45330 9.74956 9.27797 8.84621 8.45230 8.09501 - 7.77373 7.48816 7.23830 7.02382 6.84438 6.69892 - 6.58504 6.50028 6.44208 6.40085 6.35969 6.28543 - 6.10984 5.93692 5.63022 5.14652 3.82228 2.99365 - 1.88225 1.70590 1.58609 1.57397 1.56312 1.56759 - 10.43150 9.75742 9.28477 8.85404 8.46310 8.11046 - 7.79511 7.51624 7.27332 7.06588 6.89340 6.75454 - 6.64639 6.56739 6.51953 6.50258 6.50659 6.48870 - 6.37389 6.24259 6.00236 5.58652 4.32158 3.46477 - 2.04347 1.78887 1.59571 1.57925 1.55982 1.56567 - 10.40382 9.76059 9.28993 8.86106 8.47199 8.12131 - 7.80806 7.53150 7.29116 7.08665 6.91750 6.78258 - 6.67916 6.60605 6.56613 6.56070 6.58277 6.59574 - 6.53206 6.43396 6.22947 5.85977 4.69750 3.82015 - 2.19354 1.87780 1.61137 1.58539 1.55887 1.56470 - 10.38447 9.76306 9.29340 8.86554 8.47753 8.12803 - 7.81609 7.54102 7.30237 7.09979 6.93286 6.80052 - 6.70013 6.63073 6.59573 6.59751 6.63120 6.66479 - 6.63687 6.56309 6.38643 6.05402 4.98182 4.10387 - 2.33546 1.96641 1.62846 1.59184 1.55872 1.56413 - 10.35263 9.75695 9.29525 8.87245 8.48711 8.13845 - 7.82609 7.55004 7.31061 7.10785 6.94177 6.81202 - 6.71704 6.65580 6.62858 6.63054 6.65471 6.69082 - 6.70431 6.66376 6.51316 6.19772 5.19455 4.34493 - 2.47334 2.04997 1.64388 1.60066 1.55933 1.56374 - 10.33420 9.75800 9.29756 8.87598 8.49189 8.14460 - 7.83369 7.55919 7.32142 7.12054 6.95662 6.82950 - 6.73784 6.68087 6.65901 6.66757 6.70068 6.75205 - 6.79599 6.78304 6.67700 6.41563 5.51049 4.70599 - 2.73058 2.21529 1.67760 1.61470 1.56008 1.56326 - 10.32232 9.75983 9.29995 8.87800 8.49352 8.14642 - 7.83644 7.56362 7.32821 7.12988 6.96797 6.84196 - 6.75145 6.69645 6.67764 6.69070 6.73070 6.79392 - 6.85322 6.85041 6.77523 6.58081 5.77218 4.93557 - 2.94865 2.38571 1.71711 1.61156 1.57423 1.56297 - 10.30393 9.75865 9.30001 8.88021 8.49807 8.15287 - 7.84426 7.57221 7.33712 7.13921 6.97876 6.85580 - 6.76934 6.71898 6.70549 6.72462 6.77157 6.84329 - 6.92765 6.95852 6.93914 6.79821 6.10894 5.43828 - 3.43722 2.70754 1.79820 1.66623 1.56850 1.56259 - 10.29297 9.76061 9.30237 8.88160 8.49840 8.15305 - 7.84519 7.57461 7.34131 7.14514 6.98577 6.86313 - 6.77713 6.72813 6.71688 6.73883 6.78970 6.86997 - 6.97232 7.01670 7.01586 6.91040 6.36232 5.78488 - 3.77761 2.97902 1.89089 1.69891 1.59339 1.56240 - 10.28184 9.76095 9.30349 8.88333 8.50059 8.15550 - 7.84775 7.57725 7.34417 7.14856 6.99038 6.86942 - 6.78467 6.73603 6.72538 6.75084 6.81010 6.90049 - 7.01046 7.06449 7.10435 7.06940 6.62417 6.14836 - 4.36385 3.44637 2.04837 1.78288 1.59947 1.56221 - 10.27680 9.76119 9.30371 8.88376 8.50131 8.15652 - 7.84911 7.57911 7.34669 7.15161 6.99333 6.87173 - 6.78702 6.73995 6.73176 6.75886 6.81805 6.91065 - 7.03663 7.10493 7.14563 7.10298 6.79948 6.49374 - 4.71432 3.74070 2.20498 1.88929 1.62090 1.56212 - 10.29057 9.76696 9.30307 8.88051 8.49782 8.15390 - 7.84791 7.57934 7.34791 7.15359 6.99622 6.87523 - 6.78863 6.73647 6.72400 6.75683 6.83623 6.94253 - 7.05117 7.10676 7.16370 7.17990 6.92097 6.56265 - 5.03882 4.08067 2.35036 1.95352 1.63533 1.56206 - 10.28802 9.76703 9.30330 8.88086 8.49830 8.15451 - 7.84867 7.58026 7.34903 7.15489 6.99775 6.87705 - 6.79079 6.73903 6.72707 6.76056 6.84083 6.94830 - 7.05926 7.11768 7.18133 7.21084 6.99990 6.68601 - 5.26270 4.31092 2.48957 2.04105 1.65276 1.56202 - 10.26750 9.76146 9.30436 8.88484 8.50286 8.15859 - 7.85173 7.58225 7.35036 7.15589 6.99844 6.87794 - 6.79445 6.74869 6.74210 6.77151 6.83421 6.93190 - 7.06539 7.14298 7.21373 7.23197 7.08252 6.90881 - 5.58237 4.61771 2.73817 2.24206 1.67907 1.56196 - 10.26430 9.76113 9.30448 8.88507 8.50300 8.15856 - 7.85149 7.58183 7.34985 7.15547 6.99848 6.87869 - 6.79560 6.74948 6.74199 6.77057 6.83366 6.93473 - 7.07024 7.14598 7.22563 7.27527 7.16037 6.93950 - 5.79774 4.93312 2.96842 2.38000 1.71740 1.56192 - 0.42023 0.44390 0.46839 0.49370 0.51977 0.54649 - 0.57375 0.60139 0.62927 0.65720 0.68506 0.71285 - 0.74082 0.76919 0.79777 0.82647 0.85568 0.88764 - 0.92401 0.94178 0.95448 0.96039 0.97696 0.98605 - 0.98961 0.98936 0.99015 0.99063 0.99072 0.99174 - 0.62974 0.65942 0.69009 0.72188 0.75476 0.78869 - 0.82358 0.85932 0.89582 0.93291 0.97044 1.00831 - 1.04654 1.08507 1.12358 1.16179 1.20007 1.24118 - 1.28803 1.31257 1.33486 1.35036 1.37066 1.37690 - 1.37941 1.38100 1.38121 1.37861 1.37823 1.35962 - 0.82614 0.86260 0.90009 0.93881 0.97872 1.01974 - 1.06177 1.10465 1.14826 1.19241 1.23691 1.28161 - 1.32656 1.37169 1.41661 1.46101 1.50536 1.55302 - 1.60787 1.63728 1.66540 1.68600 1.70886 1.71427 - 1.71697 1.71904 1.71912 1.71592 1.71544 1.69573 - 1.18444 1.23462 1.28556 1.33754 1.39041 1.44396 - 1.49792 1.55199 1.60587 1.65931 1.71205 1.76405 - 1.81576 1.86752 1.91898 1.96995 2.02122 2.07703 - 2.14224 2.17747 2.21081 2.23468 2.26052 2.26690 - 2.27114 2.27251 2.27286 2.27129 2.27108 2.26669 - 1.50487 1.56734 1.63001 1.69323 1.75667 1.81994 - 1.88260 1.94418 2.00420 2.06231 2.11832 2.17241 - 2.22565 2.27902 2.33235 2.38564 2.43993 2.49983 - 2.57025 2.60792 2.64212 2.66521 2.69237 2.70065 - 2.70645 2.70661 2.70736 2.70817 2.70836 2.72046 - 1.79498 1.86777 1.94003 2.01218 2.08374 2.15413 - 2.22274 2.28894 2.35213 2.41187 2.46812 2.52131 - 2.57323 2.62553 2.67826 2.73160 2.78679 2.84837 - 2.92079 2.95895 2.99202 3.01289 3.04042 3.05055 - 3.05748 3.05651 3.05760 3.06048 3.06104 3.08499 - 2.05141 2.14263 2.22895 2.31062 2.38705 2.45797 - 2.52375 2.58565 2.64569 2.70418 2.76099 2.81607 - 2.87000 2.92343 2.97664 3.03081 3.08738 3.14736 - 3.21128 3.24411 3.27649 3.30140 3.32852 3.33726 - 3.34520 3.34544 3.34589 3.34736 3.35227 3.38047 - 2.51390 2.62433 2.72533 2.81710 2.89889 2.97066 - 3.03352 3.09021 3.14474 3.19794 3.24986 3.30046 - 3.35022 3.39972 3.44917 3.49948 3.55172 3.60663 - 3.66445 3.69386 3.72282 3.74530 3.77099 3.77976 - 3.78776 3.78780 3.78821 3.79007 3.79561 3.81923 - 2.91326 3.03766 3.14791 3.24421 3.32583 3.39316 - 3.44823 3.49546 3.54094 3.58614 3.63119 3.67597 - 3.72064 3.76538 3.81015 3.85518 3.90098 3.94885 - 3.99987 4.02600 4.05154 4.07143 4.09523 4.10331 - 4.11141 4.10867 4.10943 4.11552 4.11454 4.12448 - 3.73285 3.86947 3.98303 4.07441 4.14327 4.19105 - 4.22160 4.24216 4.26220 4.28412 4.30845 4.33538 - 4.36494 4.39695 4.43008 4.46109 4.48793 4.51559 - 4.55022 4.56989 4.58897 4.60370 4.62251 4.62728 - 4.63082 4.63143 4.63169 4.63139 4.63162 4.60131 - 4.37962 4.51104 4.61360 4.68923 4.73823 4.76291 - 4.76838 4.76351 4.75947 4.75925 4.76349 4.77255 - 4.78638 4.80445 4.82461 4.84150 4.85151 4.86231 - 4.88351 4.89801 4.91193 4.92242 4.93677 4.93921 - 4.93975 4.94237 4.94232 4.93818 4.93911 4.89272 - 5.36575 5.46453 5.52898 5.56342 5.56921 5.54982 - 5.51155 5.46450 5.42061 5.38339 5.35342 5.33087 - 5.31555 5.30638 5.30076 5.29204 5.27601 5.26225 - 5.26304 5.26912 5.27470 5.27829 5.28533 5.28568 - 5.28430 5.28733 5.28717 5.28199 5.28304 5.25005 - 6.10257 6.16203 6.18524 6.17848 6.14392 6.08570 - 6.01068 5.92928 5.85347 5.78672 5.72951 5.68151 - 5.64223 5.60994 5.58211 5.55229 5.51647 5.48438 - 5.46856 5.46719 5.46561 5.46361 5.46458 5.46379 - 5.46188 5.46409 5.46396 5.46002 5.46076 5.44998 - 6.81899 6.74355 6.66197 6.58095 6.50049 6.42062 - 6.34144 6.26305 6.18559 6.10952 6.03540 5.96317 - 5.89374 5.82741 5.76504 5.70787 5.65741 5.61495 - 5.58505 5.57891 5.58226 5.58979 5.57187 5.55709 - 5.56052 5.56377 5.56323 5.56164 5.56139 5.56546 - 7.29306 7.18639 7.07364 6.96240 6.85262 6.74443 - 6.63796 6.53327 6.43074 6.33099 6.23458 6.14159 - 6.05312 5.96984 5.89272 5.82322 5.76270 5.71109 - 5.67132 5.65976 5.65700 5.65826 5.62957 5.61164 - 5.61780 5.62183 5.62061 5.61876 5.61935 5.62981 - 8.03247 7.87000 7.70224 7.53810 7.37745 7.22048 - 7.06741 6.91829 6.77367 6.63458 6.50140 6.37449 - 6.25502 6.14442 6.04373 5.95461 5.87809 5.81175 - 5.75555 5.73466 5.72110 5.71122 5.66468 5.64179 - 5.65199 5.65716 5.65481 5.65256 5.65378 5.66569 - 8.47018 8.34945 8.19037 8.00602 7.80100 7.58198 - 7.35794 7.14094 6.94419 6.77061 6.61834 6.48419 - 6.36296 6.25054 6.14468 6.04131 5.93796 5.83977 - 5.75460 5.71850 5.68501 5.66044 5.63661 5.62976 - 5.62306 5.62356 5.62308 5.62089 5.62123 5.63037 - 9.43241 9.18075 8.90048 8.60600 8.30221 7.99551 - 7.69417 7.40957 7.15354 6.92732 6.72812 6.55160 - 6.39084 6.24073 6.10036 5.96668 5.83793 5.71591 - 5.60451 5.55410 5.50564 5.46885 5.43359 5.42443 - 5.41562 5.41654 5.41573 5.41234 5.41283 5.41285 - 10.00590 9.71382 9.33683 8.91805 8.49738 8.11000 - 7.76019 7.44688 7.16878 6.91917 6.68765 6.46894 - 6.26749 6.08669 5.92527 5.77618 5.63410 5.50077 - 5.37648 5.31655 5.25860 5.21461 5.17134 5.16116 - 5.15209 5.15272 5.15149 5.14868 5.14822 5.14457 - 10.83175 10.21910 9.64742 9.11944 8.63129 8.18121 - 7.76809 7.38997 7.04546 6.73273 6.44934 6.19247 - 5.95823 5.74417 5.55145 5.38092 5.22906 5.08217 - 4.92787 4.85087 4.78047 4.73109 4.67802 4.66438 - 4.65560 4.65561 4.65422 4.65248 4.65214 4.64806 - 11.20750 10.48039 9.81459 9.20552 8.64799 8.13863 - 7.67574 7.25615 6.87683 6.53481 6.22673 5.94856 - 5.69474 5.46160 5.24974 5.05979 4.88866 4.72272 - 4.55059 4.46518 4.38643 4.33005 4.26892 4.25361 - 4.24461 4.24308 4.24188 4.24292 4.24285 4.24141 - 11.41624 10.60344 9.87333 9.21213 8.61329 8.07109 - 7.58163 7.13961 6.73973 6.37824 6.05173 5.75619 - 5.48622 5.23772 5.00941 4.79843 4.60223 4.41749 - 4.24260 4.15806 4.07086 3.99925 3.93215 3.91785 - 3.90731 3.90508 3.90368 3.90541 3.90971 3.90934 - 11.55593 10.67473 9.89437 9.19254 8.56195 7.99533 - 7.48666 7.02923 6.61639 6.24347 5.90625 5.59979 - 5.31739 5.05440 4.81094 4.58719 4.38206 4.18750 - 3.99638 3.90197 3.80671 3.73104 3.65888 3.64218 - 3.63235 3.62549 3.62432 3.63363 3.63184 3.63552 - 11.68865 10.71794 9.87624 9.12593 8.45829 7.86375 - 7.33263 6.85549 6.42367 6.03220 5.67714 5.35399 - 5.05704 4.78169 4.52596 4.28622 4.05897 3.84115 - 3.62885 3.52387 3.41652 3.32970 3.24700 3.22693 - 3.20996 3.20683 3.20518 3.20704 3.21163 3.21260 - 11.72131 10.70727 9.83601 9.05998 8.37058 7.75753 - 7.21028 6.71914 6.27548 5.87414 5.51076 5.18038 - 4.87680 4.59490 4.33189 4.08292 3.84325 3.60931 - 3.37720 3.26120 3.14393 3.05005 2.95676 2.93163 - 2.90972 2.90701 2.90519 2.90511 2.90523 2.90533 - 11.65064 10.60519 9.71709 8.92309 8.21677 7.58522 - 7.01968 6.51190 6.05483 5.64315 5.27184 4.93539 - 4.62687 4.34029 4.07133 3.81269 3.55688 3.29779 - 3.02961 2.89057 2.74763 2.63077 2.51214 2.48087 - 2.45460 2.45216 2.44976 2.44799 2.44439 2.44356 - 11.52264 10.48388 9.60889 8.82403 8.12367 7.49353 - 6.92677 6.41664 5.95749 5.54418 5.17167 4.83435 - 4.52541 4.23858 3.96886 3.70755 3.44526 3.17269 - 2.87898 2.72064 2.55097 2.40670 2.26459 2.23264 - 2.20859 2.20545 2.20232 2.20218 2.20276 2.20577 - 11.29212 10.27224 9.43150 8.68028 8.00793 7.40101 - 6.85338 6.35900 5.91268 5.50920 5.14316 4.80827 - 4.49664 4.20210 3.92219 3.65308 3.38660 3.10344 - 2.77953 2.59443 2.38609 2.19796 2.00233 1.96227 - 1.95029 1.94807 1.94206 1.94470 1.95864 1.98114 - 11.09693 10.11387 9.31747 8.60521 7.96286 7.37967 - 6.85036 6.36981 5.93353 5.53704 5.17563 4.84386 - 4.53479 4.24278 3.96490 3.69638 3.42701 3.13291 - 2.78296 2.57572 2.33618 2.11440 1.87529 1.82476 - 1.82017 1.81894 1.81094 1.81571 1.84025 1.87827 - 10.94905 9.99882 9.24189 8.56312 7.94721 7.38522 - 6.87274 6.40527 5.97893 5.58983 5.23384 4.90618 - 4.60068 4.31209 4.03714 3.77014 3.49904 3.19571 - 2.82331 2.59802 2.33447 2.08934 1.81949 1.75509 - 1.73075 1.73375 1.74297 1.75014 1.77511 1.81740 - 10.83906 9.91525 9.19138 8.53969 7.94581 7.40182 - 6.90390 6.44809 6.03096 5.64904 5.29873 4.97566 - 4.67432 4.38975 4.11842 3.85405 3.58324 3.27453 - 2.88574 2.64534 2.35907 2.08891 1.78552 1.71036 - 1.68203 1.68619 1.69838 1.70669 1.73378 1.77693 - 10.68598 9.80270 9.13079 8.52080 7.96185 7.44691 - 6.97310 6.53716 6.13633 5.76779 5.42854 5.11498 - 4.82239 4.54629 4.28283 4.02488 3.75693 3.44232 - 3.02965 2.76540 2.44143 2.12744 1.76272 1.66666 - 1.62778 1.63336 1.64995 1.65947 1.68721 1.72696 - 10.58782 9.73403 9.09965 8.52008 7.98712 7.49434 - 7.03944 6.61958 6.23247 5.87571 5.54669 5.24231 - 4.95839 4.69076 4.43537 4.18459 3.92140 3.60525 - 3.17702 2.89500 2.54089 2.18948 1.76919 1.65311 - 1.60158 1.60763 1.62693 1.63668 1.66232 1.69749 - 10.46417 9.65580 9.07723 8.54516 8.05361 7.59742 - 7.17491 6.78387 6.42260 6.08924 5.78177 5.49767 - 5.23344 4.98533 4.74925 4.51695 4.26941 3.95992 - 3.51507 3.20573 2.79836 2.37436 1.83171 1.66914 - 1.58141 1.58606 1.60726 1.61523 1.63049 1.65822 - 10.45355 9.67390 9.11251 8.58484 8.09442 7.64477 - 7.23688 6.87082 6.54587 6.25257 5.97624 5.70800 - 5.44964 5.20254 4.96557 4.73580 4.50441 4.24432 - 3.85924 3.54208 3.06835 2.53499 1.86679 1.70727 - 1.60774 1.59507 1.59093 1.59905 1.62957 1.63863 - 10.43661 9.65338 9.12087 8.63342 8.18597 7.77463 - 7.39755 7.05261 6.73796 6.45157 6.19098 5.95278 - 5.73159 5.52262 5.32303 5.12673 4.91973 4.66652 - 4.28184 3.96990 3.47928 2.88790 2.04756 1.79926 - 1.61970 1.60311 1.59694 1.60038 1.61387 1.61935 - 10.43185 9.66471 9.15129 8.67984 8.24653 7.84847 - 7.48447 7.15329 6.85395 6.58460 6.34281 6.12496 - 5.92528 5.73845 5.56117 5.38617 5.19906 4.96692 - 4.60495 4.30119 3.80644 3.17982 2.20992 1.89683 - 1.63991 1.61206 1.60019 1.60107 1.60307 1.60964 - 10.43476 9.67803 9.17578 8.71383 8.28913 7.89944 - 7.54395 7.22207 6.93336 6.67616 6.44809 6.24556 - 6.06265 5.89376 5.73513 5.57828 5.40818 5.19381 - 4.85244 4.55967 4.07196 3.42939 2.36099 1.99023 - 1.66010 1.62040 1.60154 1.60070 1.59538 1.60379 - 10.43840 9.68969 9.19465 8.73903 8.32020 7.93634 - 7.58696 7.27187 6.99098 6.74284 6.52514 6.33441 - 6.16472 6.01038 5.86727 5.72590 5.57062 5.37185 - 5.04937 4.76847 4.29305 3.64555 2.50053 2.07867 - 1.67997 1.62842 1.60179 1.59969 1.58972 1.59992 - 10.44935 9.70700 9.21772 8.76908 8.35835 7.98363 - 7.64412 7.33927 7.06859 6.83115 6.62562 6.44991 - 6.30015 6.17168 6.05869 5.94683 5.81478 5.62931 - 5.31760 5.05939 4.64477 4.04661 2.76524 2.22214 - 1.70933 1.64547 1.60369 1.59341 1.59200 1.59509 - 10.44753 9.71367 9.23003 8.78695 8.38183 8.01291 - 7.67946 7.38102 7.11713 6.88708 6.68989 6.52394 - 6.38596 6.27190 6.17635 6.08506 5.97631 5.81493 - 5.52829 5.28696 4.89840 4.32345 2.99412 2.37510 - 1.73949 1.65616 1.60338 1.59135 1.58941 1.59217 - 10.43447 9.71700 9.24218 8.80743 8.41055 8.05008 - 7.72538 7.43607 7.18194 6.96257 6.77741 6.62527 - 6.50353 6.40916 6.33829 6.27897 6.21152 6.10034 - 5.87438 5.67099 5.33109 4.80855 3.45831 2.71114 - 1.81617 1.68520 1.60204 1.59028 1.58459 1.58827 - 10.43114 9.72216 9.24622 8.81256 8.41879 8.06321 - 7.74472 7.46241 7.21554 7.00347 6.82544 6.67976 - 6.56298 6.47280 6.40990 6.37187 6.34490 6.27919 - 6.09127 5.91319 5.62095 5.14383 3.79182 3.00561 - 1.89766 1.71841 1.60211 1.59316 1.58098 1.58634 - 10.39499 9.72443 9.25346 8.82426 8.43470 8.08331 - 7.76906 7.49117 7.24909 7.04237 6.87049 6.73210 - 6.62433 6.54560 6.49793 6.48108 6.48511 6.46731 - 6.35302 6.22243 5.98376 5.57087 4.31507 3.46440 - 2.05307 1.80123 1.61318 1.59795 1.57814 1.58439 - 10.36802 9.72785 9.25882 8.83144 8.44368 8.09419 - 7.78198 7.50635 7.26678 7.06293 6.89432 6.75983 - 6.65676 6.58394 6.54421 6.53886 6.56092 6.57374 - 6.51010 6.41255 6.20985 5.84366 4.69067 3.81897 - 2.20152 1.88888 1.62839 1.60383 1.57719 1.58342 - 10.34918 9.73057 9.26250 8.83605 8.44931 8.10095 - 7.79002 7.51583 7.27792 7.07598 6.90955 6.77762 - 6.67756 6.60844 6.57362 6.57548 6.60911 6.64246 - 6.61436 6.54100 6.36614 6.03735 4.97422 4.10160 - 2.34218 1.97655 1.64494 1.60981 1.57704 1.58285 - 10.31800 9.72473 9.26441 8.84289 8.45877 8.11125 - 7.79993 7.52481 7.28617 7.08408 6.91853 6.78917 - 6.69445 6.63336 6.60619 6.60814 6.63232 6.66854 - 6.68218 6.64172 6.49148 6.17912 5.18730 4.34011 - 2.47890 2.05949 1.65985 1.61820 1.57760 1.58246 - 10.29986 9.72584 9.26674 8.84641 8.46356 8.11737 - 7.80749 7.53391 7.29693 7.09669 6.93330 6.80657 - 6.71518 6.65836 6.63653 6.64508 6.67810 6.72942 - 6.77346 6.76062 6.65489 6.39516 5.49762 4.69770 - 2.73437 2.22352 1.69264 1.63147 1.57820 1.58198 - 10.28810 9.72749 9.26896 8.84838 8.46520 8.11926 - 7.81029 7.53834 7.30368 7.10598 6.94456 6.81898 - 6.72874 6.67392 6.65516 6.66814 6.70798 6.77106 - 6.83039 6.82772 6.75283 6.55900 5.75439 4.92329 - 2.95132 2.39337 1.73139 1.62741 1.59224 1.58168 - 10.26920 9.72782 9.27042 8.85065 8.46840 8.12377 - 7.81638 7.54603 7.31276 7.11643 6.95677 6.83361 - 6.74670 6.69617 6.68260 6.70127 6.74751 6.82090 - 6.90808 6.93620 6.90886 6.76944 6.11349 5.42537 - 3.41190 2.71432 1.81807 1.66757 1.60278 1.58129 - 10.25884 9.72799 9.27116 8.85184 8.47001 8.12587 - 7.81904 7.54932 7.31674 7.12116 6.96232 6.84007 - 6.75436 6.70552 6.69429 6.71611 6.76677 6.84672 - 6.94879 6.99314 6.99241 6.88706 6.34035 5.76673 - 3.77498 2.98257 1.90252 1.71258 1.61097 1.58109 - 10.24783 9.72836 9.27227 8.85357 8.47219 8.12827 - 7.82150 7.55186 7.31955 7.12459 6.96694 6.84635 - 6.76183 6.71330 6.70263 6.72798 6.78702 6.87713 - 6.98676 7.04050 7.08002 7.04643 6.60695 6.13029 - 4.35751 3.44660 2.05822 1.79528 1.61647 1.58089 - 10.24294 9.72874 9.27262 8.85404 8.47289 8.12926 - 7.82287 7.55373 7.32208 7.12766 6.96990 6.84866 - 6.76417 6.71717 6.70894 6.73592 6.79497 6.88730 - 7.01268 7.08060 7.12135 7.07983 6.77931 6.47423 - 4.70563 3.73859 2.21344 1.90062 1.63770 1.58079 - 10.25665 9.73469 9.27219 8.85094 8.46944 8.12659 - 7.82158 7.55387 7.32321 7.12953 6.97269 6.85211 - 6.76578 6.71376 6.70126 6.73391 6.81299 6.91901 - 7.02752 7.08292 7.13920 7.15447 6.89601 6.54019 - 5.02832 4.07650 2.35750 1.96396 1.65163 1.58073 - 10.25422 9.73487 9.27247 8.85129 8.46990 8.12717 - 7.82231 7.55478 7.32431 7.13083 6.97425 6.85397 - 6.76797 6.71633 6.70430 6.73757 6.81750 6.92483 - 7.03595 7.09418 7.15643 7.18366 6.97192 6.66074 - 5.25058 4.30511 2.49550 2.05064 1.66871 1.58070 - 10.23373 9.72905 9.27328 8.85514 8.47446 8.13134 - 7.82548 7.55688 7.32572 7.13185 6.97490 6.85478 - 6.77157 6.72594 6.71934 6.74857 6.81093 6.90822 - 7.04155 7.11915 7.18938 7.20599 7.05431 6.88386 - 5.56793 4.60900 2.74207 2.25018 1.69431 1.58065 - 10.23076 9.72836 9.27281 8.85478 8.47416 8.13105 - 7.82522 7.55669 7.32572 7.13208 6.97529 6.85516 - 6.77184 6.72605 6.71926 6.74831 6.81078 6.90925 - 7.04561 7.12641 7.20533 7.23899 7.12520 6.97361 - 5.78320 4.87624 2.96605 2.41311 1.72369 1.58063 - 0.41375 0.43744 0.46191 0.48717 0.51316 0.53974 - 0.56678 0.59413 0.62160 0.64902 0.67624 0.70328 - 0.73041 0.75789 0.78556 0.81340 0.84196 0.87385 - 0.91122 0.92976 0.94277 0.94853 0.96615 0.97605 - 0.97976 0.97965 0.98043 0.98059 0.98063 0.98164 - 0.62106 0.65076 0.68141 0.71314 0.74590 0.77963 - 0.81424 0.84960 0.88561 0.92208 0.95886 0.99586 - 1.03316 1.07075 1.10835 1.14577 1.18357 1.22490 - 1.27326 1.29909 1.32267 1.33868 1.35718 1.36242 - 1.36530 1.36555 1.36629 1.36657 1.36665 1.34823 - 0.81562 0.85204 0.88946 0.92807 0.96780 1.00858 - 1.05027 1.09273 1.13580 1.17930 1.22303 1.26687 - 1.31090 1.35514 1.39923 1.44298 1.48704 1.53517 - 1.59184 1.62280 1.65259 1.67402 1.69458 1.69858 - 1.70166 1.70213 1.70282 1.70308 1.70317 1.68371 - 1.17091 1.22090 1.27163 1.32338 1.37597 1.42918 - 1.48274 1.53637 1.58972 1.64256 1.69464 1.74594 - 1.79694 1.84803 1.89894 1.94957 2.00086 2.05748 - 2.12478 2.16161 2.19658 2.22139 2.24658 2.25233 - 2.25680 2.25740 2.25805 2.25815 2.25823 2.25401 - 1.48897 1.55110 1.61344 1.67630 1.73938 1.80227 - 1.86453 1.92568 1.98526 2.04291 2.09845 2.15207 - 2.20487 2.25786 2.31093 2.36414 2.41870 2.47957 - 2.55206 2.59114 2.62655 2.65042 2.67919 2.68809 - 2.69393 2.69448 2.69510 2.69506 2.69512 2.70724 - 1.77713 1.84946 1.92129 1.99302 2.06416 2.13415 - 2.20238 2.26823 2.33109 2.39054 2.44654 2.49951 - 2.55126 2.60345 2.65616 2.70965 2.76529 2.82789 - 2.90220 2.94150 2.97531 2.99674 3.02779 3.03961 - 3.04641 3.04684 3.04744 3.04731 3.04738 3.07115 - 2.03204 2.12258 2.20832 2.28950 2.36552 2.43612 - 2.50165 2.56338 2.62326 2.68163 2.73836 2.79340 - 2.84733 2.90082 2.95420 3.00870 3.06587 3.12686 - 3.19235 3.22606 3.25906 3.28460 3.31563 3.32698 - 3.33557 3.33645 3.33658 3.33606 3.33630 3.36594 - 2.49202 2.60165 2.70200 2.79326 2.87469 2.94626 - 3.00906 3.06582 3.12046 3.17386 3.22605 3.27695 - 3.32710 3.37701 3.42693 3.47779 3.53070 3.58647 - 3.64533 3.67523 3.70440 3.72727 3.75718 3.76891 - 3.77761 3.77836 3.77842 3.77800 3.77820 3.80318 - 2.88958 3.01314 3.12273 3.21857 3.29996 3.36725 - 3.42247 3.46999 3.51586 3.56151 3.60708 3.65245 - 3.69777 3.74317 3.78862 3.83429 3.88065 3.92912 - 3.98085 4.00731 4.03298 4.05271 4.07927 4.09128 - 4.09769 4.09778 4.09829 4.09844 4.09845 4.10704 - 3.70634 3.84234 3.95554 4.04681 4.11583 4.16399 - 4.19514 4.21645 4.23731 4.26014 4.28542 4.31334 - 4.34388 4.37681 4.41078 4.44250 4.46984 4.49774 - 4.53226 4.55180 4.57086 4.58576 4.60441 4.60880 - 4.61252 4.61286 4.61314 4.61343 4.61358 4.58238 - 4.35171 4.48298 4.58563 4.66158 4.71113 4.73655 - 4.74294 4.73911 4.73616 4.73707 4.74249 4.75271 - 4.76764 4.78670 4.80771 4.82524 4.83565 4.84647 - 4.86728 4.88152 4.89548 4.90641 4.91900 4.91857 - 4.92039 4.92088 4.92102 4.92133 4.92153 4.87498 - 5.33708 5.43676 5.50225 5.53783 5.54482 5.52668 - 5.48971 5.44397 5.40139 5.36550 5.33681 5.31551 - 5.30132 5.29309 5.28820 5.27999 5.26414 5.25031 - 5.25088 5.25689 5.26270 5.26687 5.27205 5.26917 - 5.26929 5.26975 5.26982 5.26995 5.27013 5.23826 - 6.07440 6.13562 6.16060 6.15558 6.12268 6.06603 - 5.99251 5.91254 5.83813 5.77275 5.71685 5.67008 - 5.63187 5.60044 5.57326 5.54379 5.50807 5.47597 - 5.46026 5.45907 5.45788 5.45644 5.45638 5.45346 - 5.45275 5.45306 5.45310 5.45306 5.45317 5.44413 - 6.79193 6.71863 6.63914 6.56014 6.48164 6.40364 - 6.32626 6.24957 6.17370 6.09910 6.02631 5.95527 - 5.88686 5.82135 5.75959 5.70278 5.65244 5.61002 - 5.58020 5.57415 5.57765 5.58536 5.56773 5.55300 - 5.55596 5.55884 5.55853 5.55771 5.55943 5.56423 - 7.26748 7.16315 7.05271 6.94368 6.83601 6.72983 - 6.62526 6.52237 6.42151 6.32329 6.22827 6.13651 - 6.04908 5.96663 5.89014 5.82100 5.76061 5.70905 - 5.66940 5.65797 5.65544 5.65702 5.62898 5.61131 - 5.61738 5.62118 5.62012 5.61884 5.62092 5.63199 - 8.00975 7.84988 7.68467 7.52295 7.36461 7.20982 - 7.05877 6.91156 6.76872 6.63125 6.49954 6.37392 - 6.25557 6.14589 6.04591 5.95725 5.88101 5.81486 - 5.75896 5.73829 5.72504 5.71555 5.66967 5.64711 - 5.65770 5.66277 5.66058 5.65882 5.66131 5.67294 - 8.44940 8.33200 8.17602 7.99448 7.79194 7.57512 - 7.35302 7.13774 6.94258 6.77049 6.61960 6.48674 - 6.36670 6.25535 6.15043 6.04782 5.94507 5.84743 - 5.76290 5.72722 5.69436 5.67055 5.64661 5.63872 - 5.63375 5.63352 5.63316 5.63296 5.63292 5.64181 - 9.41611 9.16861 8.89201 8.60069 8.29957 7.99507 - 7.69559 7.41255 7.15794 6.93306 6.73521 6.56009 - 6.40091 6.25262 6.11415 5.98213 5.85456 5.73341 - 5.62291 5.57313 5.52577 5.49034 5.45430 5.44254 - 5.43492 5.43443 5.43376 5.43360 5.43357 5.43364 - 9.99260 9.70534 9.33252 8.91721 8.49942 8.11448 - 7.76659 7.45465 7.17729 6.92824 6.69783 6.48114 - 6.28210 6.10375 5.94473 5.79796 5.65788 5.52558 - 5.40220 5.34372 5.28736 5.24480 5.20074 5.18685 - 5.17763 5.17688 5.17606 5.17585 5.17588 5.17316 - 10.82266 10.21485 9.64733 9.12289 8.63774 8.19021 - 7.77924 7.40294 7.05997 6.74861 6.46651 6.21100 - 5.97834 5.76628 5.57598 5.40831 5.25962 5.11565 - 4.96345 4.88739 4.81849 4.77061 4.71719 4.70241 - 4.69203 4.69102 4.68988 4.68970 4.68972 4.68629 - 11.19961 10.47784 9.81654 9.21124 8.65687 8.15018 - 7.68950 7.27179 6.89406 6.55346 6.24670 5.96989 - 5.71768 5.48650 5.27701 5.08988 4.92194 4.75920 - 4.58976 4.50538 4.42739 4.37173 4.31326 4.29899 - 4.28901 4.28777 4.28634 4.28626 4.28604 4.28399 - 11.40726 10.60141 9.87658 9.21949 8.62381 8.08404 - 7.59645 7.15599 6.75760 6.39758 6.07258 5.77867 - 5.51050 5.26399 5.03793 4.82950 4.63610 4.45427 - 4.28211 4.19862 4.11182 4.04053 3.97803 3.96699 - 3.95723 3.95551 3.95378 3.95364 3.95340 3.95341 - 11.54649 10.67222 9.89722 9.19954 8.57219 8.00810 - 7.50149 7.04584 6.63469 6.26347 5.92793 5.62312 - 5.34224 5.08070 4.83886 4.61731 4.41515 4.22378 - 4.03525 3.94166 3.84650 3.77025 3.70310 3.69363 - 3.68191 3.67949 3.67800 3.67809 3.67779 3.67918 - 11.67843 10.71601 9.87966 9.13271 8.46702 7.87362 - 7.34342 6.86769 6.43830 6.05008 5.69852 5.37840 - 5.08283 4.80694 4.55029 4.31215 4.09039 3.87747 - 3.66504 3.55863 3.45100 3.36555 3.28700 3.27041 - 3.25475 3.25239 3.25067 3.25056 3.25033 3.25198 - 11.70825 10.70125 9.83521 9.06326 8.37698 7.76636 - 7.22107 6.73163 6.28959 5.88987 5.52810 5.19938 - 4.89746 4.61725 4.35601 4.10887 3.87112 3.63907 - 3.40862 3.29326 3.17636 3.08251 2.98939 2.96454 - 2.94356 2.94115 2.93942 2.93917 2.93893 2.93909 - 11.63116 10.59400 9.71148 8.92146 8.21785 7.58810 - 7.02387 6.51723 6.06149 5.65136 5.28183 4.94730 - 4.64085 4.35637 4.08953 3.83281 3.57860 3.32073 - 3.05337 2.91478 2.77262 2.65628 2.53503 2.50162 - 2.47490 2.47207 2.46994 2.46960 2.46940 2.46803 - 11.49797 10.46768 9.59833 8.81742 8.11967 7.49126 - 6.92570 6.41665 5.95879 5.54702 5.17628 4.84094 - 4.53410 4.24948 3.98194 3.72263 3.46200 3.19070 - 2.89783 2.73978 2.57044 2.42665 2.28590 2.25463 - 2.23033 2.22715 2.22384 2.22333 2.22311 2.22654 - 11.26158 10.24782 9.41153 8.66405 7.99480 7.39053 - 6.84517 6.35277 5.90818 5.50627 5.14170 4.80829 - 4.49825 4.20546 3.92747 3.66040 3.39593 3.11430 - 2.79106 2.60613 2.39835 2.21240 2.02662 1.99175 - 1.98240 1.98172 1.97433 1.97219 1.97387 2.00009 - 11.05977 10.08382 9.29245 8.58429 7.94534 7.36495 - 6.83799 6.35938 5.92474 5.52967 5.16957 4.83912 - 4.53155 4.24131 3.96547 3.69915 3.43193 3.13929 - 2.78969 2.58251 2.34386 2.12581 1.90302 1.86107 - 1.86179 1.86348 1.85316 1.84965 1.85305 1.89723 - 10.91204 9.96776 9.21488 8.53944 7.92636 7.36680 - 6.85639 6.39071 5.96595 5.57827 5.22363 4.89733 - 4.59335 4.30655 4.03367 3.76911 3.50090 3.20085 - 2.83154 2.60693 2.34246 2.09688 1.83821 1.78739 - 1.79482 1.79850 1.78591 1.78142 1.78619 1.83644 - 10.80123 9.88282 9.16253 8.51388 7.92266 7.38099 - 6.88513 6.43116 6.01568 5.63530 5.28640 4.96474 - 4.66485 4.38188 4.11236 3.85016 3.58206 3.27695 - 2.89235 2.65344 2.36705 2.09670 1.80353 1.74296 - 1.75420 1.75945 1.74509 1.73989 1.74576 1.79603 - 10.64182 9.76548 9.09822 8.49212 7.93645 7.42430 - 6.95286 6.51891 6.11978 5.75270 5.41475 5.10244 - 4.81119 4.53660 4.27482 4.01868 3.75251 3.43928 - 3.02767 2.76460 2.44380 2.13651 1.79345 1.71106 - 1.69392 1.70347 1.70872 1.70459 1.69701 1.74612 - 10.54247 9.69571 9.06584 8.49009 7.96037 7.47033 - 7.01774 6.59983 6.21436 5.85899 5.53120 5.22798 - 4.94531 4.67909 4.42531 4.17626 3.91480 3.59998 - 3.17292 2.89228 2.54178 2.19782 1.80057 1.69868 - 1.67001 1.68043 1.68819 1.68367 1.67227 1.71668 - 10.41900 9.61718 9.04274 8.51417 8.02559 7.57191 - 7.15151 6.76226 6.40246 6.07034 5.76393 5.48084 - 5.21767 4.97080 4.73612 4.50538 4.25944 3.95134 - 3.50801 3.20044 2.79726 2.38131 1.86141 1.71186 - 1.64503 1.65386 1.66507 1.66018 1.64198 1.67743 - 10.41242 9.63761 9.07872 8.55323 8.06481 7.61710 - 7.21120 6.84733 6.52480 6.23377 5.95888 5.69107 - 5.43263 5.18546 4.94878 4.72032 4.49181 4.23611 - 3.85506 3.53835 3.06468 2.53604 1.89320 1.74659 - 1.66124 1.65236 1.64246 1.64024 1.64142 1.65784 - 10.39811 9.61834 9.08760 8.60212 8.15679 7.74763 - 7.37264 7.02955 6.71635 6.43105 6.17123 5.93358 - 5.71289 5.50452 5.30577 5.11085 4.90595 4.65523 - 4.27329 3.96312 3.47530 2.88976 2.06731 1.82741 - 1.65765 1.64361 1.63474 1.63233 1.62916 1.63854 - 10.39422 9.63087 9.11924 8.64960 8.21813 7.82189 - 7.45958 7.12992 6.83183 6.56347 6.32244 6.10518 - 5.90603 5.71977 5.54320 5.36930 5.18389 4.95399 - 4.59500 4.29335 3.80171 3.18037 2.22438 1.91743 - 1.66770 1.64169 1.62902 1.62693 1.62027 1.62881 - 10.39773 9.64503 9.14457 8.68434 8.26128 7.87316 - 7.51912 7.19854 6.91094 6.65466 6.42735 6.22545 - 6.04309 5.87475 5.71677 5.56084 5.39212 5.17975 - 4.84138 4.55086 4.06646 3.42869 2.37136 2.00541 - 1.68123 1.64303 1.62471 1.62272 1.61367 1.62295 - 10.40189 9.65730 9.16403 8.71006 8.29275 7.91028 - 7.56216 7.24821 6.96832 6.72106 6.50413 6.31404 - 6.14494 5.99115 5.84864 5.70804 5.55389 5.35690 - 5.03736 4.75878 4.28672 3.64370 2.50774 2.08989 - 1.69668 1.64652 1.62139 1.61928 1.60865 1.61906 - 10.41338 9.67518 9.18763 8.74053 8.33119 7.95772 - 7.61930 7.31545 7.04563 6.80898 6.60416 6.42910 - 6.27994 6.15209 6.03972 5.92851 5.79725 5.61297 - 5.30362 5.04764 4.63691 4.04368 2.76807 2.22717 - 1.72248 1.65890 1.61929 1.61214 1.61028 1.61422 - 10.41191 9.68198 9.20003 8.75843 8.35462 7.98690 - 7.65450 7.35701 7.09394 6.86463 6.66811 6.50277 - 6.36536 6.25191 6.15699 6.06633 5.95823 5.79769 - 5.51276 5.27335 4.88868 4.31916 2.99501 2.37715 - 1.75162 1.66871 1.61831 1.60985 1.60757 1.61128 - 10.39875 9.68504 9.21178 8.77848 8.38289 8.02362 - 7.69997 7.41161 7.15831 6.93964 6.75511 6.60352 - 6.48232 6.38848 6.31812 6.25925 6.19217 6.08140 - 5.85640 5.65438 5.31768 4.80030 3.45702 2.71206 - 1.82884 1.70000 1.61919 1.60851 1.60342 1.60736 - 10.39506 9.68976 9.21545 8.78325 8.39083 8.03644 - 7.71903 7.43767 7.19165 6.98033 6.80292 6.65776 - 6.54146 6.45168 6.38911 6.35135 6.32459 6.25907 - 6.07177 5.89484 5.60546 5.13260 3.78849 3.00776 - 1.91115 1.73476 1.62095 1.61156 1.60029 1.60543 - 10.35896 9.69179 9.22247 8.79475 8.40652 8.05632 - 7.74315 7.46620 7.22495 7.01894 6.84763 6.70973 - 6.60235 6.52392 6.47646 6.45971 6.46380 6.44612 - 6.33231 6.20241 5.96531 5.55552 4.30971 3.46565 - 2.06505 1.81644 1.63200 1.61642 1.59737 1.60348 - 10.33228 9.69520 9.22782 8.80191 8.41550 8.06721 - 7.75608 7.48136 7.24261 7.03944 6.87139 6.73734 - 6.63460 6.56200 6.52240 6.51707 6.53910 6.55200 - 6.48884 6.39177 6.18998 5.82607 4.68305 3.81809 - 2.21078 1.90141 1.64593 1.62204 1.59607 1.60251 - 10.31355 9.69791 9.23150 8.80655 8.42115 8.07397 - 7.76410 7.49084 7.25372 7.05243 6.88655 6.75503 - 6.65527 6.58634 6.55160 6.55343 6.58701 6.62041 - 6.59273 6.51976 6.34546 6.01840 4.96451 4.09840 - 2.34902 1.98677 1.66131 1.62769 1.59561 1.60193 - 10.28262 9.69209 9.23346 8.81343 8.43064 8.08429 - 7.77399 7.49977 7.26192 7.06049 6.89550 6.76654 - 6.67209 6.61112 6.58394 6.58585 6.61004 6.64635 - 6.66026 6.62009 6.47040 6.15939 5.17546 4.33522 - 2.48400 2.06801 1.67535 1.63585 1.59601 1.60155 - 10.26466 9.69322 9.23580 8.81697 8.43540 8.09039 - 7.78152 7.50882 7.27261 7.07303 6.91016 6.78384 - 6.69272 6.63604 6.61422 6.62269 6.65563 6.70693 - 6.75110 6.73844 6.63311 6.37439 5.48322 4.68964 - 2.73747 2.23055 1.70726 1.64862 1.59643 1.60106 - 10.25292 9.69497 9.23810 8.81895 8.43700 8.09218 - 7.78423 7.51319 7.27933 7.08229 6.92140 6.79619 - 6.70621 6.65151 6.63279 6.64573 6.68546 6.74843 - 6.80769 6.80507 6.73057 6.53791 5.73839 4.91181 - 2.95334 2.40045 1.74563 1.64343 1.61064 1.60077 - 10.23470 9.69361 9.23800 8.82098 8.44137 8.09848 - 7.79191 7.52169 7.28812 7.09149 6.93205 6.80986 - 6.72395 6.67394 6.66056 6.67953 6.72605 6.79721 - 6.88116 6.91217 6.89347 6.75241 6.06591 5.40819 - 3.43681 2.71811 1.82424 1.69658 1.60415 1.60038 - 10.22395 9.69542 9.24021 8.82229 8.44171 8.09870 - 7.79288 7.52405 7.29223 7.09729 6.93894 6.81710 - 6.73166 6.68298 6.67179 6.69355 6.74402 6.82367 - 6.92531 6.96954 6.96908 6.86450 6.32020 5.74974 - 3.77335 2.98707 1.91482 1.72680 1.62899 1.60018 - 10.21304 9.69583 9.24135 8.82402 8.44386 8.10105 - 7.79534 7.52660 7.29503 7.10069 6.94353 6.82334 - 6.73909 6.69070 6.68002 6.70525 6.76413 6.85394 - 6.96312 7.01665 7.05616 7.02297 6.58552 6.11141 - 4.35191 3.44735 2.06839 1.80800 1.63387 1.59998 - 10.20821 9.69619 9.24170 8.82453 8.44461 8.10208 - 7.79669 7.52843 7.29754 7.10373 6.94650 6.82565 - 6.74141 6.69452 6.68626 6.71314 6.77200 6.86404 - 6.98893 7.05657 7.09728 7.05616 6.75699 6.45322 - 4.69612 3.73588 2.22183 1.91202 1.65479 1.59988 - 10.22206 9.70207 9.24118 8.82137 8.44116 8.09947 - 7.79548 7.52866 7.29875 7.10568 6.94933 6.82911 - 6.74302 6.69113 6.67863 6.71114 6.78994 6.89559 - 7.00372 7.05893 7.11500 7.13021 6.87298 6.51869 - 5.01522 4.06988 2.36428 1.97465 1.66803 1.59982 - 10.21976 9.70225 9.24145 8.82172 8.44162 8.10006 - 7.79621 7.52955 7.29983 7.10698 6.95087 6.83095 - 6.74520 6.69369 6.68168 6.71479 6.79444 6.90140 - 7.01214 7.07015 7.13216 7.15930 6.94850 6.63837 - 5.23511 4.29612 2.50108 2.06054 1.68470 1.59978 - 10.19910 9.69653 9.24241 8.82564 8.44617 8.10416 - 7.79932 7.53161 7.30121 7.10795 6.95149 6.83174 - 6.74878 6.70328 6.69667 6.72577 6.78789 6.88481 - 7.01765 7.09501 7.16504 7.18165 7.03071 6.86103 - 5.55222 4.59929 2.74588 2.25836 1.70969 1.59973 - 10.19575 9.69581 9.24216 8.82563 8.44620 8.10409 - 7.79906 7.53113 7.30063 7.10745 6.95141 6.83235 - 6.74976 6.70392 6.69644 6.72474 6.78725 6.88758 - 7.02242 7.09756 7.17593 7.22798 7.12514 6.89695 - 5.76966 4.91683 2.97362 2.39261 1.74711 1.59969 - 0.40837 0.43094 0.45453 0.47918 0.50486 0.53146 - 0.55883 0.58675 0.61489 0.64289 0.67033 0.69673 - 0.72155 0.74472 0.76762 0.79437 0.82875 0.86790 - 0.90310 0.91566 0.92673 0.93679 0.95719 0.96440 - 0.96927 0.96978 0.97028 0.97036 0.97034 0.97155 - 0.61346 0.64286 0.67318 0.70453 0.73686 0.77011 - 0.80416 0.83891 0.87421 0.90992 0.94588 0.98203 - 1.01849 1.05532 1.09229 1.12933 1.16710 1.20900 - 1.25880 1.28563 1.31001 1.32641 1.34574 1.35138 - 1.35438 1.35463 1.35541 1.35571 1.35580 1.33673 - 0.80740 0.84316 0.87989 0.91777 0.95676 0.99676 - 1.03766 1.07933 1.12160 1.16431 1.20727 1.25039 - 1.29376 1.33742 1.38109 1.42464 1.46886 1.51776 - 1.57611 1.60826 1.63917 1.66134 1.68274 1.68698 - 1.69018 1.69065 1.69139 1.69166 1.69175 1.67157 - 1.16051 1.20951 1.25924 1.31001 1.36165 1.41395 - 1.46665 1.51949 1.57215 1.62441 1.67601 1.72692 - 1.77759 1.82836 1.87897 1.92941 1.98078 2.03811 - 2.10733 2.14559 2.18199 2.20777 2.23377 2.23963 - 2.24424 2.24488 2.24556 2.24567 2.24572 2.24124 - 1.47579 1.53692 1.59829 1.66024 1.72246 1.78456 - 1.84615 1.90674 1.96590 2.02326 2.07864 2.13218 - 2.18489 2.23770 2.29049 2.34339 2.39778 2.45914 - 2.53354 2.57413 2.61100 2.63580 2.66532 2.67433 - 2.68034 2.68092 2.68157 2.68153 2.68157 2.69396 - 1.76105 1.83254 1.90359 1.97460 2.04512 2.11458 - 2.18242 2.24798 2.31072 2.37017 2.42627 2.47940 - 2.53123 2.58334 2.63577 2.68882 2.74406 2.80694 - 2.88304 2.92381 2.95897 2.98118 3.01290 3.02488 - 3.03188 3.03233 3.03295 3.03283 3.03286 3.05730 - 2.01424 2.10314 2.18765 2.26805 2.34375 2.41447 - 2.48046 2.54280 2.60323 2.66196 2.71885 2.77382 - 2.82745 2.88041 2.93313 2.98711 3.04422 3.10591 - 3.17317 3.20812 3.24214 3.26814 3.29979 3.31143 - 3.32021 3.32109 3.32123 3.32070 3.32094 3.35145 - 2.46891 2.57797 2.67799 2.76919 2.85079 2.92278 - 2.98617 3.04361 3.09894 3.15294 3.20564 3.25689 - 3.30713 3.35685 3.40636 3.45681 3.50960 3.56579 - 3.62593 3.65672 3.68657 3.70968 3.74006 3.75205 - 3.76093 3.76168 3.76175 3.76132 3.76151 3.78720 - 2.86386 2.98666 3.09592 3.19184 3.27370 3.34180 - 3.39808 3.44672 3.49357 3.53999 3.58611 3.63177 - 3.67716 3.72247 3.76780 3.81370 3.86085 3.91003 - 3.96164 3.98794 4.01410 4.03517 4.06230 4.07255 - 4.08016 4.08071 4.08086 4.08078 4.08083 4.08968 - 3.67255 3.81139 3.92687 4.01978 4.08975 4.13829 - 4.16938 4.19055 4.21158 4.23498 4.26122 4.29038 - 4.32229 4.35650 4.39158 4.42412 4.45186 4.47987 - 4.51435 4.53384 4.55289 4.56785 4.58661 4.59096 - 4.59469 4.59503 4.59531 4.59562 4.59576 4.56348 - 4.31599 4.45104 4.55667 4.63470 4.68537 4.71111 - 4.71723 4.71296 4.70990 4.71118 4.71744 4.72902 - 4.74574 4.76692 4.79009 4.80919 4.82003 4.83061 - 4.85111 4.86521 4.87912 4.89009 4.90272 4.90214 - 4.90394 4.90444 4.90458 4.90491 4.90511 4.85722 - 5.30451 5.40740 5.47547 5.51286 5.52095 5.50325 - 5.46627 5.42035 5.37780 5.34223 5.31428 5.29422 - 5.28193 5.27628 5.27421 5.26803 5.25260 5.23836 - 5.23872 5.24476 5.25069 5.25504 5.26044 5.25750 - 5.25765 5.25813 5.25820 5.25833 5.25851 5.22636 - 6.04815 6.11063 6.13682 6.13286 6.10088 6.04504 - 5.97218 5.89279 5.81892 5.75413 5.69895 5.65320 - 5.61659 5.58746 5.56285 5.53527 5.49997 5.46759 - 5.45195 5.45097 5.45008 5.44896 5.44936 5.44662 - 5.44604 5.44636 5.44641 5.44637 5.44648 5.43813 - 6.63846 6.66248 6.64987 6.60842 6.54077 6.45154 - 6.34782 6.24000 6.14008 6.05132 5.97411 5.90767 - 5.85119 5.80246 5.75877 5.71331 5.66193 5.61464 - 5.58454 5.57674 5.56949 5.56364 5.55959 5.55697 - 5.55577 5.55596 5.55598 5.55581 5.55587 5.56289 - 7.24861 7.14524 7.03580 6.92778 6.82111 6.71593 - 6.61236 6.51048 6.41064 6.31345 6.21946 6.12874 - 6.04236 5.96097 5.88554 5.81746 5.75810 5.70744 - 5.66840 5.65709 5.65450 5.65605 5.62903 5.61212 - 5.61869 5.62249 5.62138 5.62010 5.62216 5.63408 - 7.88077 7.81005 7.70278 7.57020 7.41602 7.24596 - 7.06793 6.89263 6.73232 6.59000 6.46467 6.35410 - 6.25481 6.16349 6.07780 5.99317 5.90689 5.82570 - 5.75925 5.73304 5.70920 5.69197 5.67576 5.67093 - 5.66773 5.66757 5.66736 5.66719 5.66715 5.68017 - 8.41778 8.36040 8.20718 7.99428 7.75748 7.53078 - 7.32020 7.12648 6.95030 6.79039 6.64278 6.50468 - 6.37655 6.25915 6.15114 6.04945 5.95140 5.85758 - 5.77205 5.73536 5.70295 5.68077 5.65750 5.65064 - 5.64594 5.64567 5.64536 5.64511 5.64521 5.65326 - 9.37571 9.20301 8.93482 8.61208 8.27355 7.95472 - 7.66276 7.40060 7.17031 6.96507 6.77223 6.58564 - 6.41260 6.25913 6.12304 5.99625 5.87209 5.75175 - 5.64100 5.59226 5.54602 5.51145 5.47627 5.46392 - 5.45636 5.45596 5.45533 5.45509 5.45515 5.45444 - 9.98077 9.69731 9.32811 8.91611 8.50132 8.11903 - 7.77328 7.46271 7.18583 6.93713 6.70837 6.49493 - 6.29905 6.12260 5.96463 5.81927 5.68150 5.55060 - 5.42787 5.37094 5.31616 5.27477 5.23114 5.21539 - 5.20575 5.20524 5.20444 5.20414 5.20422 5.20170 - 10.79827 10.19980 9.64006 9.12191 8.64178 8.19810 - 7.78999 7.41568 7.07402 6.76344 6.48182 6.22686 - 5.99526 5.78515 5.59779 5.43399 5.28981 5.14979 - 4.99968 4.92420 4.85645 4.81001 4.75655 4.74089 - 4.72980 4.72884 4.72780 4.72753 4.72766 4.72443 - 11.16591 10.45779 9.80743 9.21086 8.66325 8.16160 - 7.70447 7.28902 6.91255 6.57241 6.26569 5.98887 - 5.73723 5.50768 5.30098 5.11775 4.95456 4.79626 - 4.62958 4.54593 4.46862 4.41362 4.35596 4.34186 - 4.33175 4.33050 4.32912 4.32901 4.32887 4.32652 - 11.37578 10.59007 9.87858 9.22941 8.63749 8.09853 - 7.61008 7.16851 6.77004 6.41113 6.08809 5.79649 - 5.53044 5.28585 5.06311 4.86240 4.68118 4.50560 - 4.32393 4.23292 4.14644 4.08294 4.02244 4.01066 - 4.00121 3.99958 3.99797 3.99800 3.99763 3.99747 - 11.50195 10.65861 9.90352 9.21700 8.59414 8.02975 - 7.52005 7.06070 6.64727 6.27555 5.94121 5.63916 - 5.36250 5.10649 4.87118 4.65644 4.45991 4.26935 - 4.07393 3.97604 3.88158 3.81096 3.74645 3.73531 - 3.72531 3.72336 3.72164 3.72172 3.72122 3.72283 - 11.63671 10.69369 9.87212 9.13644 8.47907 7.89150 - 7.36509 6.89150 6.46301 6.07485 5.72298 5.40285 - 5.10849 4.83525 4.58148 4.34413 4.12015 3.90656 - 3.69909 3.59607 3.48898 3.40146 3.32387 3.30835 - 3.29412 3.29185 3.28988 3.28968 3.28937 3.29136 - 11.67741 10.68612 9.83121 9.06692 8.38569 7.77820 - 7.23483 6.74681 6.30636 5.90843 5.54856 5.22169 - 4.92134 4.64228 4.38189 4.13564 3.89899 3.66842 - 3.43984 3.32538 3.20887 3.11491 3.02226 2.99792 - 2.97730 2.97487 2.97311 2.97286 2.97261 2.97279 - 11.63280 10.59351 9.70969 8.91940 8.21629 7.58768 - 7.02499 6.52011 6.06614 5.65780 5.29012 4.95758 - 4.65331 4.37121 4.10685 3.85250 3.60028 3.34385 - 3.07733 2.93903 2.79734 2.68151 2.56017 2.52638 - 2.49942 2.49660 2.49450 2.49415 2.49395 2.49245 - 11.53832 10.49028 9.60720 8.81671 8.11280 7.48110 - 6.91462 6.40652 5.95104 5.54257 5.17544 4.84320 - 4.53784 4.25314 3.98668 3.73446 3.48744 3.22325 - 2.92027 2.75446 2.58469 2.44675 2.30694 2.27573 - 2.25070 2.24730 2.24426 2.24401 2.24358 2.24741 - 11.29687 10.26871 9.42072 8.66446 7.98902 7.38081 - 6.83345 6.34065 5.89701 5.49712 5.13535 4.80521 - 4.49839 4.20847 3.93299 3.66808 3.40545 3.12531 - 2.80320 2.61872 2.41141 2.22608 2.04205 2.00816 - 1.99965 1.99905 1.99163 1.98945 1.99121 2.01951 - 11.09484 10.10430 9.30088 8.58366 7.93831 7.35383 - 6.82473 6.34567 5.91195 5.51889 5.16159 4.83430 - 4.52976 4.24202 3.96818 3.70338 3.43733 3.14573 - 2.79725 2.59076 2.35299 2.13608 1.91608 1.87566 - 1.87801 1.87988 1.86948 1.86590 1.86946 1.91692 - 10.93747 9.98153 9.21882 8.53606 7.91790 7.35524 - 6.84342 6.37774 5.95415 5.56855 5.21659 4.89319 - 4.59183 4.30696 4.03539 3.77157 3.50372 3.20414 - 2.83593 2.61223 2.34907 2.10513 1.85004 1.80111 - 1.81076 1.81470 1.80200 1.79743 1.80244 1.85635 - 10.81385 9.88773 9.16066 8.50710 7.91269 7.36932 - 6.87307 6.41975 6.00581 5.62760 5.28126 4.96219 - 4.66445 4.38284 4.11392 3.85167 3.58313 3.27792 - 2.89438 2.65660 2.37190 2.10364 1.81465 1.75623 - 1.77016 1.77575 1.76126 1.75597 1.76213 1.81603 - 10.62979 9.75317 9.08504 8.47881 7.92370 7.41270 - 6.94290 6.51097 6.11411 5.74942 5.41379 5.10347 - 4.81350 4.53920 4.27678 4.01920 3.75121 3.43691 - 3.02633 2.76484 2.44646 2.14202 1.80389 1.72388 - 1.71000 1.72011 1.72548 1.72125 1.71387 1.76619 - 10.51065 9.66949 9.04350 8.47147 7.94531 7.45874 - 7.00944 6.59464 6.21202 5.85918 5.53350 5.23177 - 4.94969 4.68299 4.42767 4.17619 3.91194 3.59535 - 3.16929 2.89052 2.54296 2.20240 1.81071 1.71139 - 1.68637 1.69748 1.70551 1.70090 1.68960 1.73673 - 10.39657 9.62754 9.04552 8.48968 7.97446 7.51090 - 7.09696 6.72704 6.39494 6.09054 5.80017 5.51526 - 5.23646 4.96523 4.70370 4.45543 4.21598 3.95413 - 3.56977 3.25950 2.81571 2.34564 1.82647 1.72768 - 1.68619 1.68115 1.67034 1.66800 1.67261 1.69742 - 10.33219 9.58814 9.04681 8.52976 8.04303 7.59331 - 7.18643 6.82866 6.52372 6.25278 5.98419 5.70468 - 5.43432 5.18628 4.95249 4.71487 4.46311 4.21279 - 3.85806 3.53536 3.07312 2.54968 1.87696 1.76290 - 1.68846 1.67226 1.65913 1.66007 1.65505 1.67776 - 10.29819 9.58101 9.07469 8.58908 8.13158 7.70992 - 7.32847 6.99150 6.70174 6.44583 6.20104 5.95615 - 5.72152 5.50380 5.29719 5.08822 4.86494 4.62393 - 4.27585 3.96988 3.49321 2.90444 2.04610 1.83557 - 1.68773 1.66718 1.65079 1.64975 1.64605 1.65835 - 10.31400 9.59534 9.10062 8.63070 8.19096 7.78695 - 7.42124 7.09628 6.81362 6.56445 6.33376 6.11301 - 5.90613 5.71493 5.53416 5.35159 5.15295 4.92286 - 4.58069 4.28817 3.81858 3.20636 2.21192 1.91664 - 1.69325 1.66606 1.64610 1.64359 1.64081 1.64855 - 10.33836 9.61241 9.12131 8.66042 8.23253 7.84059 - 7.48567 7.16874 6.89035 6.64505 6.42377 6.22046 - 6.03482 5.86539 5.70687 5.54708 5.36959 5.15138 - 4.81575 4.53391 4.07900 3.46354 2.36794 1.99847 - 1.70196 1.66692 1.64285 1.63924 1.63697 1.64264 - 10.35923 9.62786 9.13750 8.68170 8.26174 7.87898 - 7.53284 7.22239 6.94667 6.70330 6.48887 6.29961 - 6.13116 5.97869 5.83695 5.69387 5.53305 5.33161 - 5.01682 4.74612 4.28979 3.65707 2.50913 2.09476 - 1.71392 1.66592 1.64057 1.63815 1.62844 1.63872 - 10.38267 9.64592 9.15838 8.71173 8.30319 7.93076 - 7.59344 7.29057 7.02146 6.78522 6.58066 6.40591 - 6.25742 6.13076 6.01996 5.91017 5.77988 5.59676 - 5.28985 5.03612 4.62899 4.04032 2.77244 2.23552 - 1.73818 1.67634 1.63842 1.63145 1.62979 1.63383 - 10.37774 9.65374 9.17374 8.73261 8.32826 7.95946 - 7.62605 7.32832 7.06653 6.83975 6.64631 6.48352 - 6.34637 6.22978 6.12928 6.03344 5.92540 5.77885 - 5.52384 5.29206 4.88387 4.27132 2.96996 2.40255 - 1.78076 1.68809 1.63269 1.62927 1.61686 1.63088 - 10.36827 9.65561 9.18214 8.74912 8.35422 7.99581 - 7.67306 7.38537 7.13226 6.91342 6.72852 6.57678 - 6.45620 6.36410 6.29620 6.23943 6.17314 6.06264 - 5.83869 5.63810 5.30435 4.79155 3.45718 2.71672 - 1.84226 1.71572 1.63781 1.62746 1.62284 1.62693 - 10.35881 9.65724 9.18456 8.75378 8.36255 8.00918 - 7.69260 7.41189 7.16639 6.95547 6.77838 6.63351 - 6.51758 6.42836 6.36655 6.32975 6.30407 6.23950 - 6.05298 5.87687 5.58977 5.12094 3.78591 3.01064 - 1.92338 1.74940 1.63918 1.63040 1.61965 1.62498 - 10.32095 9.65780 9.19064 8.76483 8.37826 8.02950 - 7.71754 7.44160 7.20115 6.99576 6.82493 6.68736 - 6.58024 6.50204 6.45476 6.43819 6.44244 6.42499 - 6.31174 6.18254 5.94710 5.54038 4.30350 3.46556 - 2.07524 1.82945 1.64965 1.63502 1.61664 1.62299 - 10.29526 9.66174 9.19634 8.77223 8.38742 8.04055 - 7.73066 7.45705 7.21922 7.01680 6.84936 6.71574 - 6.61329 6.54083 6.50118 6.49565 6.51736 6.53012 - 6.46740 6.37097 6.17043 5.80890 4.67435 3.81571 - 2.21934 1.91316 1.66309 1.64042 1.61525 1.62199 - 10.27785 9.66511 9.20043 8.77709 8.39318 8.04735 - 7.73869 7.46652 7.23037 7.02990 6.86469 6.73369 - 6.63425 6.56541 6.53054 6.53200 6.56503 6.59810 - 6.57080 6.49841 6.32509 5.99995 4.95391 4.09409 - 2.35622 1.99750 1.67803 1.64584 1.61471 1.62140 - 10.24756 9.65966 9.20261 8.78404 8.40260 8.05749 - 7.74838 7.47527 7.23848 7.03802 6.87386 6.74553 - 6.65131 6.59010 6.56232 6.56368 6.58772 6.62412 - 6.63833 6.59844 6.44935 6.13991 5.16341 4.32940 - 2.48995 2.07787 1.69166 1.65374 1.61504 1.62100 - 10.23009 9.66098 9.20501 8.78755 8.40727 8.06343 - 7.75569 7.48403 7.24876 7.05003 6.88788 6.76207 - 6.67118 6.61441 6.59223 6.60034 6.63314 6.68444 - 6.72870 6.71621 6.61129 6.35377 5.46887 4.68116 - 2.74144 2.23897 1.72278 1.66604 1.61527 1.62049 - 10.21786 9.66267 9.20756 8.78983 8.40910 8.06538 - 7.75837 7.48802 7.25455 7.05786 6.89771 6.77366 - 6.68464 6.63014 6.61100 6.62339 6.66247 6.72307 - 6.78331 6.78744 6.71833 6.50573 5.68237 4.94386 - 2.96406 2.39227 1.75899 1.67414 1.61714 1.62019 - 10.19952 9.66090 9.20701 8.79148 8.41317 8.07137 - 7.76571 7.49623 7.26328 7.06712 6.90806 6.78617 - 6.70057 6.65093 6.63788 6.65704 6.70345 6.77432 - 6.85800 6.88899 6.87054 6.73019 6.04736 5.39408 - 3.43613 2.72301 1.83757 1.71239 1.62248 1.61981 - 10.18907 9.66085 9.20761 8.79264 8.41483 8.07354 - 7.76840 7.49949 7.26721 7.07182 6.91366 6.79279 - 6.70833 6.66003 6.64896 6.67150 6.72342 6.80155 - 6.89704 6.94105 6.95118 6.85913 6.28167 5.69440 - 3.80311 3.00481 1.91972 1.74800 1.63054 1.61962 - 10.17787 9.66318 9.21049 8.79456 8.41558 8.07388 - 7.76918 7.50135 7.27056 7.07684 6.92019 6.80043 - 6.71647 6.66818 6.65745 6.68255 6.74121 6.83073 - 6.93953 6.99293 7.03250 6.99968 6.56416 6.09276 - 4.34573 3.44750 2.07860 1.82101 1.65157 1.61945 - 10.17339 9.66371 9.21104 8.79541 8.41673 8.07522 - 7.77063 7.50296 7.27249 7.07923 6.92307 6.80372 - 6.72018 6.67238 6.66247 6.68919 6.75086 6.84492 - 6.96122 7.02120 7.07291 7.06840 6.73667 6.33452 - 4.72778 3.78962 2.22671 1.90223 1.66931 1.61937 - 10.17077 9.66425 9.21150 8.79595 8.41748 8.07619 - 7.77180 7.50428 7.27390 7.08072 6.92477 6.80583 - 6.72285 6.67577 6.66673 6.69446 6.75736 6.85353 - 6.97451 7.03881 7.09745 7.10874 6.84745 6.49877 - 5.00887 4.06303 2.37118 1.98430 1.68624 1.61933 - 10.18590 9.67009 9.21072 8.79229 8.41338 8.07289 - 7.77000 7.50418 7.27519 7.08294 6.92734 6.80780 - 6.72233 6.67098 6.65900 6.69200 6.77139 6.87800 - 6.98837 7.04620 7.10808 7.13525 6.92558 6.61722 - 5.22316 4.29020 2.50712 2.07026 1.70121 1.61929 - 10.16497 9.66412 9.21150 8.79613 8.41793 8.07702 - 7.77314 7.50624 7.27655 7.08387 6.92786 6.80842 - 6.72572 6.68043 6.67395 6.70302 6.76489 6.86142 - 6.99379 7.07089 7.14075 7.15747 7.00752 6.83887 - 5.53772 4.59051 2.74987 2.26664 1.72538 1.61923 - 10.15964 9.66297 9.21141 8.79623 8.41784 8.07681 - 7.77288 7.50594 7.27618 7.08360 6.92809 6.80952 - 6.72726 6.68145 6.67379 6.70184 6.76413 6.86420 - 6.99847 7.07326 7.15144 7.20361 7.10145 6.87405 - 5.75349 4.90604 2.97594 2.39944 1.76217 1.61918 - \ No newline at end of file diff --git a/openmc/data/__init__.py b/openmc/data/__init__.py deleted file mode 100644 index 277c14ca8..000000000 --- a/openmc/data/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# Version of HDF5 nuclear data format -HDF5_VERSION_MAJOR = 3 -HDF5_VERSION_MINOR = 0 -HDF5_VERSION = (HDF5_VERSION_MAJOR, HDF5_VERSION_MINOR) - -# Version of WMP nuclear data format -WMP_VERSION_MAJOR = 1 -WMP_VERSION_MINOR = 1 -WMP_VERSION = (WMP_VERSION_MAJOR, WMP_VERSION_MINOR) - - -from .data import * -from .neutron import * -from .photon import * -from .decay import * -from .reaction import * -from . import ace -from .angle_distribution import * -from . import endf -from .energy_distribution import * -from .product import * -from .angle_energy import * -from .uncorrelated import * -from .correlated import * -from .kalbach_mann import * -from .nbody import * -from .thermal import * -from .urr import * -from .library import * -from .fission_energy import * -from .resonance import * -from .resonance_covariance import * -from .multipole import * -from .grid import * -from .function import * diff --git a/openmc/data/_endf.pyx b/openmc/data/_endf.pyx deleted file mode 100644 index 991ee015b..000000000 --- a/openmc/data/_endf.pyx +++ /dev/null @@ -1,8 +0,0 @@ -# cython: c_string_type=str, c_string_encoding=ascii - -cdef extern from "endf.c": - double cfloat_endf(const char* buffer, int n) - -def float_endf(s): - cdef const char* c_string = s - return cfloat_endf(c_string, len(s)) diff --git a/openmc/data/ace.py b/openmc/data/ace.py deleted file mode 100644 index ee194560b..000000000 --- a/openmc/data/ace.py +++ /dev/null @@ -1,460 +0,0 @@ -"""This module is for reading ACE-format cross sections. ACE stands for "A -Compact ENDF" format and originated from work on MCNP_. It is used in a number -of other Monte Carlo particle transport codes. - -ACE-format cross sections are typically generated from ENDF_ files through a -cross section processing program like NJOY_. The ENDF data consists of tabulated -thermal data, ENDF/B resonance parameters, distribution parameters in the -unresolved resonance region, and tabulated data in the fast region. After the -ENDF data has been reconstructed and Doppler-broadened, the ACER module -generates ACE-format cross sections. - -.. _MCNP: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/ -.. _NJOY: http://t2.lanl.gov/codes.shtml -.. _ENDF: http://www.nndc.bnl.gov/endf - -""" - -from pathlib import PurePath -import struct -import sys - -import numpy as np - -from openmc.mixin import EqualityMixin -import openmc.checkvalue as cv -from .data import ATOMIC_SYMBOL, gnd_name -from .endf import ENDF_FLOAT_RE - - -def get_metadata(zaid, metastable_scheme='nndc'): - """Return basic identifying data for a nuclide with a given ZAID. - - Parameters - ---------- - zaid : int - ZAID (1000*Z + A) obtained from a library - metastable_scheme : {'nndc', 'mcnp'} - Determine how ZAID identifiers are to be interpreted in the case of - a metastable nuclide. Because the normal ZAID (=1000*Z + A) does not - encode metastable information, different conventions are used among - different libraries. In MCNP libraries, the convention is to add 400 - for a metastable nuclide except for Am242m, for which 95242 is - metastable and 95642 (or 1095242 in newer libraries) is the ground - state. For NNDC libraries, ZAID is given as 1000*Z + A + 100*m. - - Returns - ------- - name : str - Name of the table - element : str - The atomic symbol of the isotope in the table; e.g., Zr. - Z : int - Number of protons in the nucleus - mass_number : int - Number of nucleons in the nucleus - metastable : int - Metastable state of the nucleus. A value of zero indicates ground state. - - """ - - cv.check_type('zaid', zaid, int) - cv.check_value('metastable_scheme', metastable_scheme, ['nndc', 'mcnp']) - - Z = zaid // 1000 - mass_number = zaid % 1000 - - if metastable_scheme == 'mcnp': - if zaid > 1000000: - # New SZA format - Z = Z % 1000 - if zaid == 1095242: - metastable = 0 - else: - metastable = zaid // 1000000 - else: - if zaid == 95242: - metastable = 1 - elif zaid == 95642: - metastable = 0 - else: - metastable = 1 if mass_number > 300 else 0 - elif metastable_scheme == 'nndc': - metastable = 1 if mass_number > 300 else 0 - - while mass_number > 3 * Z: - mass_number -= 100 - - # Determine name - element = ATOMIC_SYMBOL[Z] - name = gnd_name(Z, mass_number, metastable) - - return (name, element, Z, mass_number, metastable) - - -def ascii_to_binary(ascii_file, binary_file): - """Convert an ACE file in ASCII format (type 1) to binary format (type 2). - - Parameters - ---------- - ascii_file : str - Filename of ASCII ACE file - binary_file : str - Filename of binary ACE file to be written - - """ - - # Open ASCII file - ascii = open(str(ascii_file), 'r') - - # Set default record length - record_length = 4096 - - # Read data from ASCII file - lines = ascii.readlines() - ascii.close() - - # Open binary file - binary = open(str(binary_file), 'wb') - - idx = 0 - - while idx < len(lines): - # check if it's a > 2.0.0 version header - if lines[idx].split()[0][1] == '.': - if lines[idx + 1].split()[3] == '3': - idx = idx + 3 - else: - raise NotImplementedError('Only backwards compatible ACE' - 'headers currently supported') - # Read/write header block - hz = lines[idx][:10].encode('UTF-8') - aw0 = float(lines[idx][10:22]) - tz = float(lines[idx][22:34]) - hd = lines[idx][35:45].encode('UTF-8') - hk = lines[idx + 1][:70].encode('UTF-8') - hm = lines[idx + 1][70:80].encode('UTF-8') - binary.write(struct.pack(str('=10sdd10s70s10s'), hz, aw0, tz, hd, hk, hm)) - - # Read/write IZ/AW pairs - data = ' '.join(lines[idx + 2:idx + 6]).split() - iz = list(map(int, data[::2])) - aw = list(map(float, data[1::2])) - izaw = [item for sublist in zip(iz, aw) for item in sublist] - binary.write(struct.pack(str('=' + 16*'id'), *izaw)) - - # Read/write NXS and JXS arrays. Null bytes are added at the end so - # that XSS will start at the second record - nxs = list(map(int, ' '.join(lines[idx + 6:idx + 8]).split())) - jxs = list(map(int, ' '.join(lines[idx + 8:idx + 12]).split())) - binary.write(struct.pack(str('=16i32i{0}x'.format(record_length - 500)), - *(nxs + jxs))) - - # Read/write XSS array. Null bytes are added to form a complete record - # at the end of the file - n_lines = (nxs[0] + 3)//4 - xss = list(map(float, ' '.join(lines[ - idx + 12:idx + 12 + n_lines]).split())) - extra_bytes = record_length - ((len(xss)*8 - 1) % record_length + 1) - binary.write(struct.pack(str('={0}d{1}x'.format(nxs[0], extra_bytes)), - *xss)) - - # Advance to next table in file - idx += 12 + n_lines - - # Close binary file - binary.close() - - -def get_table(filename, name=None): - """Read a single table from an ACE file - - Parameters - ---------- - filename : str - Path of the ACE library to load table from - name : str, optional - Name of table to load, e.g. '92235.71c' - - Returns - ------- - openmc.data.ace.Table - ACE table with specified name. If no name is specified, the first table - in the file is returned. - - """ - - if name is None: - return Library(filename).tables[0] - else: - lib = Library(filename, name) - if lib.tables: - return lib.tables[0] - else: - raise ValueError('Could not find ACE table with name: {}' - .format(name)) - - -class Library(EqualityMixin): - """A Library objects represents an ACE-formatted file which may contain - multiple tables with data. - - Parameters - ---------- - filename : str - Path of the ACE library file to load. - table_names : None, str, or iterable, optional - Tables from the file to read in. If None, reads in all of the - tables. If str, reads in only the single table of a matching name. - verbose : bool, optional - Determines whether output is printed to the stdout when reading a - Library - - Attributes - ---------- - tables : list - List of :class:`Table` instances - - """ - - def __init__(self, filename, table_names=None, verbose=False): - if isinstance(table_names, str): - table_names = [table_names] - if table_names is not None: - table_names = set(table_names) - - self.tables = [] - - # Determine whether file is ASCII or binary - filename = str(filename) - try: - fh = open(filename, 'rb') - # Grab 10 lines of the library - sb = b''.join([fh.readline() for i in range(10)]) - - # Try to decode it with ascii - sb.decode('ascii') - - # No exception so proceed with ASCII - reopen in non-binary - fh.close() - with open(filename, 'r') as fh: - self._read_ascii(fh, table_names, verbose) - except UnicodeDecodeError: - fh.close() - with open(filename, 'rb') as fh: - self._read_binary(fh, table_names, verbose) - - def _read_binary(self, ace_file, table_names, verbose=False, - recl_length=4096, entries=512): - """Read a binary (Type 2) ACE table. - - Parameters - ---------- - ace_file : file - Open ACE file - table_names : None, str, or iterable - Tables from the file to read in. If None, reads in all of the - tables. If str, reads in only the single table of a matching name. - verbose : str, optional - Whether to display what tables are being read. Defaults to False. - recl_length : int, optional - Fortran record length in binary file. Default value is 4096 bytes. - entries : int, optional - Number of entries per record. The default is 512 corresponding to a - record length of 4096 bytes with double precision data. - - """ - - while True: - start_position = ace_file.tell() - - # Check for end-of-file - if len(ace_file.read(1)) == 0: - return - ace_file.seek(start_position) - - # Read name, atomic mass ratio, temperature, date, comment, and - # material - name, atomic_weight_ratio, temperature, date, comment, mat = \ - struct.unpack(str('=10sdd10s70s10s'), ace_file.read(116)) - name = name.decode().strip() - - # Read ZAID/awr combinations - data = struct.unpack(str('=' + 16*'id'), ace_file.read(192)) - pairs = list(zip(data[::2], data[1::2])) - - # Read NXS - nxs = list(struct.unpack(str('=16i'), ace_file.read(64))) - - # Determine length of XSS and number of records - length = nxs[0] - n_records = (length + entries - 1)//entries - - # verify that we are supposed to read this table in - if (table_names is not None) and (name not in table_names): - ace_file.seek(start_position + recl_length*(n_records + 1)) - continue - - if verbose: - kelvin = round(temperature * 1e6 / 8.617342e-5) - print("Loading nuclide {0} at {1} K".format(name, kelvin)) - - # Read JXS - jxs = list(struct.unpack(str('=32i'), ace_file.read(128))) - - # Read XSS - ace_file.seek(start_position + recl_length) - xss = list(struct.unpack(str('={0}d'.format(length)), - ace_file.read(length*8))) - - # Insert zeros at beginning of NXS, JXS, and XSS arrays so that the - # indexing will be the same as Fortran. This makes it easier to - # follow the ACE format specification. - nxs.insert(0, 0) - nxs = np.array(nxs, dtype=int) - - jxs.insert(0, 0) - jxs = np.array(jxs, dtype=int) - - xss.insert(0, 0.0) - xss = np.array(xss) - - # Create ACE table with data read in - table = Table(name, atomic_weight_ratio, temperature, pairs, - nxs, jxs, xss) - self.tables.append(table) - - # Advance to next record - ace_file.seek(start_position + recl_length*(n_records + 1)) - - def _read_ascii(self, ace_file, table_names, verbose=False): - """Read an ASCII (Type 1) ACE table. - - Parameters - ---------- - ace_file : file - Open ACE file - table_names : None, str, or iterable - Tables from the file to read in. If None, reads in all of the - tables. If str, reads in only the single table of a matching name. - verbose : str, optional - Whether to display what tables are being read. Defaults to False. - - """ - - tables_seen = set() - - lines = [ace_file.readline() for i in range(13)] - - while len(lines) != 0 and lines[0].strip() != '': - # Read name of table, atomic mass ratio, and temperature. If first - # line is empty, we are at end of file - - # check if it's a 2.0 style header - if lines[0].split()[0][1] == '.': - words = lines[0].split() - name = words[1] - words = lines[1].split() - atomic_weight_ratio = float(words[0]) - temperature = float(words[1]) - commentlines = int(words[3]) - for i in range(commentlines): - lines.pop(0) - lines.append(ace_file.readline()) - else: - words = lines[0].split() - name = words[0] - atomic_weight_ratio = float(words[1]) - temperature = float(words[2]) - - datastr = ' '.join(lines[2:6]).split() - pairs = list(zip(map(int, datastr[::2]), - map(float, datastr[1::2]))) - - datastr = '0 ' + ' '.join(lines[6:8]) - nxs = np.fromstring(datastr, sep=' ', dtype=int) - - n_lines = (nxs[1] + 3)//4 - - # Ensure that we have more tables to read in - if (table_names is not None) and (table_names <= tables_seen): - break - tables_seen.add(name) - - # verify that we are supposed to read this table in - if (table_names is not None) and (name not in table_names): - for i in range(n_lines - 1): - ace_file.readline() - lines = [ace_file.readline() for i in range(13)] - continue - - # Read lines corresponding to this table - lines += [ace_file.readline() for i in range(n_lines - 1)] - - if verbose: - kelvin = round(temperature * 1e6 / 8.617342e-5) - print("Loading nuclide {0} at {1} K".format(name, kelvin)) - - # Insert zeros at beginning of NXS, JXS, and XSS arrays so that the - # indexing will be the same as Fortran. This makes it easier to - # follow the ACE format specification. - datastr = '0 ' + ' '.join(lines[8:12]) - jxs = np.fromstring(datastr, dtype=int, sep=' ') - - datastr = '0.0 ' + ''.join(lines[12:12+n_lines]) - xss = np.fromstring(datastr, sep=' ') - - # When NJOY writes an ACE file, any values less than 1e-100 actually - # get written without the 'e'. Thus, what we do here is check - # whether the xss array is of the right size (if a number like - # 1.0-120 is encountered, np.fromstring won't capture any numbers - # after it). If it's too short, then we apply the ENDF float regular - # expression. We don't do this by default because it's expensive! - if xss.size != nxs[1] + 1: - datastr = ENDF_FLOAT_RE.sub(r'\1e\2\3', datastr) - xss = np.fromstring(datastr, sep=' ') - assert xss.size == nxs[1] + 1 - - table = Table(name, atomic_weight_ratio, temperature, pairs, - nxs, jxs, xss) - self.tables.append(table) - - # Read all data blocks - lines = [ace_file.readline() for i in range(13)] - - -class Table(EqualityMixin): - """ACE cross section table - - Parameters - ---------- - name : str - ZAID identifier of the table, e.g. '92235.70c'. - atomic_weight_ratio : float - Atomic mass ratio of the target nuclide. - temperature : float - Temperature of the target nuclide in MeV. - pairs : list of tuple - 16 pairs of ZAIDs and atomic weight ratios. Used for thermal scattering - tables to indicate what isotopes scattering is applied to. - nxs : numpy.ndarray - Array that defines various lengths with in the table - jxs : numpy.ndarray - Array that gives locations in the ``xss`` array for various blocks of - data - xss : numpy.ndarray - Raw data for the ACE table - - """ - def __init__(self, name, atomic_weight_ratio, temperature, pairs, - nxs, jxs, xss): - self.name = name - self.atomic_weight_ratio = atomic_weight_ratio - self.temperature = temperature - self.pairs = pairs - self.nxs = nxs - self.jxs = jxs - self.xss = xss - - def __repr__(self): - return "".format(self.name) diff --git a/openmc/data/angle_distribution.py b/openmc/data/angle_distribution.py deleted file mode 100644 index 638590cff..000000000 --- a/openmc/data/angle_distribution.py +++ /dev/null @@ -1,310 +0,0 @@ -from collections.abc import Iterable -from io import StringIO -from numbers import Real -from warnings import warn - -import numpy as np - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from openmc.stats import Univariate, Tabular, Uniform, Legendre -from .function import INTERPOLATION_SCHEME -from .data import EV_PER_MEV -from .endf import get_head_record, get_cont_record, get_tab1_record, \ - get_list_record, get_tab2_record - - -class AngleDistribution(EqualityMixin): - """Angle distribution as a function of incoming energy - - Parameters - ---------- - energy : Iterable of float - Incoming energies in eV at which distributions exist - mu : Iterable of openmc.stats.Univariate - Distribution of scattering cosines corresponding to each incoming energy - - Attributes - ---------- - energy : Iterable of float - Incoming energies in eV at which distributions exist - mu : Iterable of openmc.stats.Univariate - Distribution of scattering cosines corresponding to each incoming energy - - """ - - def __init__(self, energy, mu): - super().__init__() - self.energy = energy - self.mu = mu - - @property - def energy(self): - return self._energy - - @property - def mu(self): - return self._mu - - @energy.setter - def energy(self, energy): - cv.check_type('angle distribution incoming energy', energy, - Iterable, Real) - self._energy = energy - - @mu.setter - def mu(self, mu): - cv.check_type('angle distribution scattering cosines', mu, - Iterable, Univariate) - self._mu = mu - - def to_hdf5(self, group): - """Write angle distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - dset = group.create_dataset('energy', data=self.energy) - - # Make sure all data is tabular - mu_tabular = [mu_i if isinstance(mu_i, Tabular) else - mu_i.to_tabular() for mu_i in self.mu] - - # Determine total number of (mu,p) pairs and create array - n_pairs = sum([len(mu_i.x) for mu_i in mu_tabular]) - pairs = np.empty((3, n_pairs)) - - # Create array for offsets - offsets = np.empty(len(mu_tabular), dtype=int) - interpolation = np.empty(len(mu_tabular), dtype=int) - j = 0 - - # Populate offsets and pairs array - for i, mu_i in enumerate(mu_tabular): - n = len(mu_i.x) - offsets[i] = j - interpolation[i] = 1 if mu_i.interpolation == 'histogram' else 2 - pairs[0, j:j+n] = mu_i.x - pairs[1, j:j+n] = mu_i.p - pairs[2, j:j+n] = mu_i.c - j += n - - # Create dataset for distributions - dset = group.create_dataset('mu', data=pairs) - - # Write interpolation as attribute - dset.attrs['offsets'] = offsets - dset.attrs['interpolation'] = interpolation - - @classmethod - def from_hdf5(cls, group): - """Generate angular distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.AngleDistribution - Angular distribution - - """ - energy = group['energy'][()] - data = group['mu'] - offsets = data.attrs['offsets'] - interpolation = data.attrs['interpolation'] - - mu = [] - n_energy = len(energy) - for i in range(n_energy): - # Determine length of outgoing energy distribution and number of - # discrete lines - j = offsets[i] - if i < n_energy - 1: - n = offsets[i+1] - j - else: - n = data.shape[1] - j - - interp = INTERPOLATION_SCHEME[interpolation[i]] - mu_i = Tabular(data[0, j:j+n], data[1, j:j+n], interp) - mu_i.c = data[2, j:j+n] - - mu.append(mu_i) - - return cls(energy, mu) - - @classmethod - def from_ace(cls, ace, location_dist, location_start): - """Generate an angular distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - location_dist : int - Index in the XSS array corresponding to the start of a block, - e.g. JXS(9). - location_start : int - Index in the XSS array corresponding to the start of an angle - distribution array - - Returns - ------- - openmc.data.AngleDistribution - Angular distribution - - """ - # Set starting index for angle distribution - idx = location_dist + location_start - 1 - - # Number of energies at which angular distributions are tabulated - n_energies = int(ace.xss[idx]) - idx += 1 - - # Incoming energy grid - energy = ace.xss[idx:idx + n_energies]*EV_PER_MEV - idx += n_energies - - # Read locations for angular distributions - lc = ace.xss[idx:idx + n_energies].astype(int) - idx += n_energies - - mu = [] - for i in range(n_energies): - if lc[i] > 0: - # Equiprobable 32 bin distribution - idx = location_dist + abs(lc[i]) - 1 - cos = ace.xss[idx:idx + 33] - pdf = np.zeros(33) - pdf[:32] = 1.0/(32.0*np.diff(cos)) - cdf = np.linspace(0.0, 1.0, 33) - - mu_i = Tabular(cos, pdf, 'histogram', ignore_negative=True) - mu_i.c = cdf - elif lc[i] < 0: - # Tabular angular distribution - idx = location_dist + abs(lc[i]) - 1 - intt = int(ace.xss[idx]) - n_points = int(ace.xss[idx + 1]) - data = ace.xss[idx + 2:idx + 2 + 3*n_points] - data.shape = (3, n_points) - - mu_i = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) - mu_i.c = data[2] - else: - # Isotropic angular distribution - mu_i = Uniform(-1., 1.) - - mu.append(mu_i) - - return cls(energy, mu) - - @classmethod - def from_endf(cls, ev, mt): - """Generate an angular distribution from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - mt : int - The MT value of the reaction to get angular distributions for - - Returns - ------- - openmc.data.AngleDistribution - Angular distribution - - """ - file_obj = StringIO(ev.section[4, mt]) - - # Read HEAD record - items = get_head_record(file_obj) - lvt = items[2] - ltt = items[3] - - # Read CONT record - items = get_cont_record(file_obj) - li = items[2] - nk = items[4] - center_of_mass = (items[3] == 2) - - # Check for obsolete energy transformation matrix. If present, just skip - # it and keep reading - if lvt > 0: - warn('Obsolete energy transformation matrix in MF=4 angular ' - 'distribution.') - for _ in range((nk + 5)//6): - file_obj.readline() - - if ltt == 0 and li == 1: - # Purely isotropic - energy = np.array([0., ev.info['energy_max']]) - mu = [Uniform(-1., 1.), Uniform(-1., 1.)] - - elif ltt == 1 and li == 0: - # Legendre polynomial coefficients - params, tab2 = get_tab2_record(file_obj) - n_energy = params[5] - - energy = np.zeros(n_energy) - mu = [] - for i in range(n_energy): - items, al = get_list_record(file_obj) - temperature = items[0] - energy[i] = items[1] - coefficients = np.asarray([1.0] + al) - mu.append(Legendre(coefficients)) - - elif ltt == 2 and li == 0: - # Tabulated probability distribution - params, tab2 = get_tab2_record(file_obj) - n_energy = params[5] - - energy = np.zeros(n_energy) - mu = [] - for i in range(n_energy): - params, f = get_tab1_record(file_obj) - temperature = params[0] - energy[i] = params[1] - if f.n_regions > 1: - raise NotImplementedError('Angular distribution with multiple ' - 'interpolation regions not supported.') - mu.append(Tabular(f.x, f.y, INTERPOLATION_SCHEME[f.interpolation[0]])) - - elif ltt == 3 and li == 0: - # Legendre for low energies / tabulated for high energies - params, tab2 = get_tab2_record(file_obj) - n_energy_legendre = params[5] - - energy_legendre = np.zeros(n_energy_legendre) - mu = [] - for i in range(n_energy_legendre): - items, al = get_list_record(file_obj) - temperature = items[0] - energy_legendre[i] = items[1] - coefficients = np.asarray([1.0] + al) - mu.append(Legendre(coefficients)) - - params, tab2 = get_tab2_record(file_obj) - n_energy_tabulated = params[5] - - energy_tabulated = np.zeros(n_energy_tabulated) - for i in range(n_energy_tabulated): - params, f = get_tab1_record(file_obj) - temperature = params[0] - energy_tabulated[i] = params[1] - if f.n_regions > 1: - raise NotImplementedError('Angular distribution with multiple ' - 'interpolation regions not supported.') - mu.append(Tabular(f.x, f.y, INTERPOLATION_SCHEME[f.interpolation[0]])) - - energy = np.concatenate((energy_legendre, energy_tabulated)) - - return AngleDistribution(energy, mu) diff --git a/openmc/data/angle_energy.py b/openmc/data/angle_energy.py deleted file mode 100644 index 8cf9bcf5e..000000000 --- a/openmc/data/angle_energy.py +++ /dev/null @@ -1,117 +0,0 @@ -from abc import ABCMeta, abstractmethod -from io import StringIO - -import openmc.data -from openmc.mixin import EqualityMixin - - -class AngleEnergy(EqualityMixin, metaclass=ABCMeta): - """Distribution in angle and energy of a secondary particle.""" - @abstractmethod - def to_hdf5(self, group): - pass - - @staticmethod - def from_hdf5(group): - """Generate angle-energy distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.AngleEnergy - Angle-energy distribution - - """ - dist_type = group.attrs['type'].decode() - if dist_type == 'uncorrelated': - return openmc.data.UncorrelatedAngleEnergy.from_hdf5(group) - elif dist_type == 'correlated': - return openmc.data.CorrelatedAngleEnergy.from_hdf5(group) - elif dist_type == 'kalbach-mann': - return openmc.data.KalbachMann.from_hdf5(group) - elif dist_type == 'nbody': - return openmc.data.NBodyPhaseSpace.from_hdf5(group) - elif dist_type == 'coherent_elastic': - return openmc.data.CoherentElasticAE.from_hdf5(group) - elif dist_type == 'incoherent_elastic': - return openmc.data.IncoherentElasticAE.from_hdf5(group) - elif dist_type == 'incoherent_elastic_discrete': - return openmc.data.IncoherentElasticAEDiscrete.from_hdf5(group) - elif dist_type == 'incoherent_inelastic_discrete': - return openmc.data.IncoherentInelasticAEDiscrete.from_hdf5(group) - elif dist_type == 'incoherent_inelastic': - return openmc.data.IncoherentInelasticAE.from_hdf5(group) - - @staticmethod - def from_ace(ace, location_dist, location_start, rx=None): - """Generate an angle-energy distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - location_dist : int - Index in the XSS array corresponding to the start of a block, - e.g. JXS(11) for the the DLW block. - location_start : int - Index in the XSS array corresponding to the start of an energy - distribution array - rx : Reaction - Reaction this energy distribution will be associated with - - Returns - ------- - distribution : openmc.data.AngleEnergy - Secondary angle-energy distribution - - """ - # Set starting index for energy distribution - idx = location_dist + location_start - 1 - - law = int(ace.xss[idx + 1]) - location_data = int(ace.xss[idx + 2]) - - # Position index for reading law data - idx = location_dist + location_data - 1 - - # Parse energy distribution data - if law == 2: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.DiscretePhoton.from_ace(ace, idx) - elif law in (3, 33): - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.LevelInelastic.from_ace(ace, idx) - elif law == 4: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.ContinuousTabular.from_ace( - ace, idx, location_dist) - elif law == 5: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.GeneralEvaporation.from_ace(ace, idx) - elif law == 7: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.MaxwellEnergy.from_ace(ace, idx) - elif law == 9: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.Evaporation.from_ace(ace, idx) - elif law == 11: - distribution = openmc.data.UncorrelatedAngleEnergy() - distribution.energy = openmc.data.WattEnergy.from_ace(ace, idx) - elif law == 44: - distribution = openmc.data.KalbachMann.from_ace( - ace, idx, location_dist) - elif law == 61: - distribution = openmc.data.CorrelatedAngleEnergy.from_ace( - ace, idx, location_dist) - elif law == 66: - distribution = openmc.data.NBodyPhaseSpace.from_ace( - ace, idx, rx.q_value) - else: - raise ValueError("Unsupported ACE secondary energy " - "distribution law {}".format(law)) - - return distribution diff --git a/openmc/data/compton_profiles.h5 b/openmc/data/compton_profiles.h5 deleted file mode 100644 index 298ed0340..000000000 Binary files a/openmc/data/compton_profiles.h5 and /dev/null differ diff --git a/openmc/data/correlated.py b/openmc/data/correlated.py deleted file mode 100644 index 567d23abd..000000000 --- a/openmc/data/correlated.py +++ /dev/null @@ -1,462 +0,0 @@ -from collections.abc import Iterable -from numbers import Real, Integral -from warnings import warn - -import numpy as np - -import openmc.checkvalue as cv -from openmc.stats import Tabular, Univariate, Discrete, Mixture, \ - Uniform, Legendre -from .function import INTERPOLATION_SCHEME -from .angle_energy import AngleEnergy -from .data import EV_PER_MEV -from .endf import get_list_record, get_tab2_record - - -class CorrelatedAngleEnergy(AngleEnergy): - """Correlated angle-energy distribution - - Parameters - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - mu : Iterable of Iterable of openmc.stats.Univariate - Distribution of scattering cosine for each incoming/outgoing energy - - Attributes - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - mu : Iterable of Iterable of openmc.stats.Univariate - Distribution of scattering cosine for each incoming/outgoing energy - - """ - - _name = 'correlated' - - def __init__(self, breakpoints, interpolation, energy, energy_out, mu): - super().__init__() - self.breakpoints = breakpoints - self.interpolation = interpolation - self.energy = energy - self.energy_out = energy_out - self.mu = mu - - @property - def breakpoints(self): - return self._breakpoints - - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - - @property - def mu(self): - return self._mu - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('correlated angle-energy breakpoints', breakpoints, - Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('correlated angle-energy interpolation', interpolation, - Iterable, Integral) - self._interpolation = interpolation - - @energy.setter - def energy(self, energy): - cv.check_type('correlated angle-energy incoming energy', energy, - Iterable, Real) - self._energy = energy - - @energy_out.setter - def energy_out(self, energy_out): - cv.check_type('correlated angle-energy outgoing energy', energy_out, - Iterable, Univariate) - self._energy_out = energy_out - - @mu.setter - def mu(self, mu): - cv.check_iterable_type('correlated angle-energy outgoing cosine', - mu, Univariate, 2, 2) - self._mu = mu - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_(self._name) - - dset = group.create_dataset('energy', data=self.energy) - dset.attrs['interpolation'] = np.vstack((self.breakpoints, - self.interpolation)) - - # Determine total number of (E,p) pairs and create array - n_tuple = sum(len(d.x) for d in self.energy_out) - eout = np.empty((5, n_tuple)) - - # Make sure all mu data is tabular - mu_tabular = [] - for i, mu_i in enumerate(self.mu): - mu_tabular.append([mu_ij if isinstance(mu_ij, (Tabular, Discrete)) else - mu_ij.to_tabular() for mu_ij in mu_i]) - - # Determine total number of (mu,p) points and create array - n_tuple = sum(sum(len(mu_ij.x) for mu_ij in mu_i) - for mu_i in mu_tabular) - mu = np.empty((3, n_tuple)) - - # Create array for offsets - offsets = np.empty(len(self.energy_out), dtype=int) - interpolation = np.empty(len(self.energy_out), dtype=int) - n_discrete_lines = np.empty(len(self.energy_out), dtype=int) - offset_e = 0 - offset_mu = 0 - - # Populate offsets and eout array - for i, d in enumerate(self.energy_out): - n = len(d) - offsets[i] = offset_e - - if isinstance(d, Mixture): - discrete, continuous = d.distribution - n_discrete_lines[i] = m = len(discrete) - interpolation[i] = 1 if continuous.interpolation == 'histogram' else 2 - eout[0, offset_e:offset_e+m] = discrete.x - eout[1, offset_e:offset_e+m] = discrete.p - eout[2, offset_e:offset_e+m] = discrete.c - eout[0, offset_e+m:offset_e+n] = continuous.x - eout[1, offset_e+m:offset_e+n] = continuous.p - eout[2, offset_e+m:offset_e+n] = continuous.c - else: - if isinstance(d, Tabular): - n_discrete_lines[i] = 0 - interpolation[i] = 1 if d.interpolation == 'histogram' else 2 - elif isinstance(d, Discrete): - n_discrete_lines[i] = n - interpolation[i] = 1 - eout[0, offset_e:offset_e+n] = d.x - eout[1, offset_e:offset_e+n] = d.p - eout[2, offset_e:offset_e+n] = d.c - - for j, mu_ij in enumerate(mu_tabular[i]): - if isinstance(mu_ij, Discrete): - eout[3, offset_e+j] = 0 - else: - eout[3, offset_e+j] = 1 if mu_ij.interpolation == 'histogram' else 2 - eout[4, offset_e+j] = offset_mu - - n_mu = len(mu_ij) - mu[0, offset_mu:offset_mu+n_mu] = mu_ij.x - mu[1, offset_mu:offset_mu+n_mu] = mu_ij.p - mu[2, offset_mu:offset_mu+n_mu] = mu_ij.c - - offset_mu += n_mu - - offset_e += n - - # Create dataset for outgoing energy distributions - dset = group.create_dataset('energy_out', data=eout) - - # Write interpolation on outgoing energy as attribute - dset.attrs['offsets'] = offsets - dset.attrs['interpolation'] = interpolation - dset.attrs['n_discrete_lines'] = n_discrete_lines - - # Create dataset for outgoing angle distributions - group.create_dataset('mu', data=mu) - - @classmethod - def from_hdf5(cls, group): - """Generate correlated angle-energy distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.CorrelatedAngleEnergy - Correlated angle-energy distribution - - """ - interp_data = group['energy'].attrs['interpolation'] - energy_breakpoints = interp_data[0, :] - energy_interpolation = interp_data[1, :] - energy = group['energy'][()] - - offsets = group['energy_out'].attrs['offsets'] - interpolation = group['energy_out'].attrs['interpolation'] - n_discrete_lines = group['energy_out'].attrs['n_discrete_lines'] - dset_eout = group['energy_out'][()] - energy_out = [] - - dset_mu = group['mu'][()] - mu = [] - - n_energy = len(energy) - for i in range(n_energy): - # Determine length of outgoing energy distribution and number of - # discrete lines - offset_e = offsets[i] - if i < n_energy - 1: - n = offsets[i+1] - offset_e - else: - n = dset_eout.shape[1] - offset_e - m = n_discrete_lines[i] - - # Create discrete distribution if lines are present - if m > 0: - x = dset_eout[0, offset_e:offset_e+m] - p = dset_eout[1, offset_e:offset_e+m] - eout_discrete = Discrete(x, p) - eout_discrete.c = dset_eout[2, offset_e:offset_e+m] - p_discrete = eout_discrete.c[-1] - - # Create continuous distribution - if m < n: - interp = INTERPOLATION_SCHEME[interpolation[i]] - - x = dset_eout[0, offset_e+m:offset_e+n] - p = dset_eout[1, offset_e+m:offset_e+n] - eout_continuous = Tabular(x, p, interp, ignore_negative=True) - eout_continuous.c = dset_eout[2, offset_e+m:offset_e+n] - - # If both continuous and discrete are present, create a mixture - # distribution - if m == 0: - eout_i = eout_continuous - elif m == n: - eout_i = eout_discrete - else: - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - - # Read angular distributions - mu_i = [] - for j in range(n): - # Determine interpolation scheme - interp_code = int(dset_eout[3, offsets[i] + j]) - - # Determine offset and length - offset_mu = int(dset_eout[4, offsets[i] + j]) - if offsets[i] + j < dset_eout.shape[1] - 1: - n_mu = int(dset_eout[4, offsets[i] + j + 1]) - offset_mu - else: - n_mu = dset_mu.shape[1] - offset_mu - - # Get data - x = dset_mu[0, offset_mu:offset_mu+n_mu] - p = dset_mu[1, offset_mu:offset_mu+n_mu] - c = dset_mu[2, offset_mu:offset_mu+n_mu] - - if interp_code == 0: - mu_ij = Discrete(x, p) - else: - mu_ij = Tabular(x, p, INTERPOLATION_SCHEME[interp_code], - ignore_negative=True) - mu_ij.c = c - mu_i.append(mu_ij) - - offset_mu += n_mu - - energy_out.append(eout_i) - mu.append(mu_i) - - return cls(energy_breakpoints, energy_interpolation, - energy, energy_out, mu) - - @classmethod - def from_ace(cls, ace, idx, ldis): - """Generate correlated angle-energy distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - idx : int - Index in XSS array of the start of the energy distribution data - (LDIS + LOCC - 1) - ldis : int - Index in XSS array of the start of the energy distribution block - (e.g. JXS[11]) - - Returns - ------- - openmc.data.CorrelatedAngleEnergy - Correlated angle-energy distribution - - """ - # Read number of interpolation regions and incoming energies - n_regions = int(ace.xss[idx]) - n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) - - # Get interpolation information - idx += 1 - if n_regions > 0: - breakpoints = ace.xss[idx:idx + n_regions].astype(int) - interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) - else: - breakpoints = np.array([n_energy_in]) - interpolation = np.array([2]) - - # Incoming energies at which distributions exist - idx += 2*n_regions + 1 - energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV - - # Location of distributions - idx += n_energy_in - loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) - - # Initialize list of distributions - energy_out = [] - mu = [] - - # Read each outgoing energy distribution - for i in range(n_energy_in): - idx = ldis + loc_dist[i] - 1 - - # intt = interpolation scheme (1=hist, 2=lin-lin) - INTTp = int(ace.xss[idx]) - intt = INTTp % 10 - n_discrete_lines = (INTTp - intt)//10 - if intt not in (1, 2): - warn("Interpolation scheme for continuous tabular distribution " - "is not histogram or linear-linear.") - intt = 2 - - # Secondary energy distribution - n_energy_out = int(ace.xss[idx + 1]) - data = ace.xss[idx + 2:idx + 2 + 4*n_energy_out].copy() - data.shape = (4, n_energy_out) - data[0,:] *= EV_PER_MEV - - # Create continuous distribution - eout_continuous = Tabular(data[0][n_discrete_lines:], - data[1][n_discrete_lines:]/EV_PER_MEV, - INTERPOLATION_SCHEME[intt], - ignore_negative=True) - eout_continuous.c = data[2][n_discrete_lines:] - if np.any(data[1][n_discrete_lines:] < 0.0): - warn("Correlated angle-energy distribution has negative " - "probabilities.") - - # If discrete lines are present, create a mixture distribution - if n_discrete_lines > 0: - eout_discrete = Discrete(data[0][:n_discrete_lines], - data[1][:n_discrete_lines]) - eout_discrete.c = data[2][:n_discrete_lines] - if n_discrete_lines == n_energy_out: - eout_i = eout_discrete - else: - p_discrete = min(sum(eout_discrete.p), 1.0) - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - else: - eout_i = eout_continuous - - energy_out.append(eout_i) - - lc = data[3].astype(int) - - # Secondary angular distributions - mu_i = [] - for j in range(n_energy_out): - if lc[j] > 0: - idx = ldis + abs(lc[j]) - 1 - - intt = int(ace.xss[idx]) - n_cosine = int(ace.xss[idx + 1]) - data = ace.xss[idx + 2:idx + 2 + 3*n_cosine] - data.shape = (3, n_cosine) - - mu_ij = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) - mu_ij.c = data[2] - else: - # Isotropic distribution - mu_ij = Uniform(-1., 1.) - - mu_i.append(mu_ij) - - # Add cosine distributions for this incoming energy to list - mu.append(mu_i) - - return cls(breakpoints, interpolation, energy, energy_out, mu) - - @classmethod - def from_endf(cls, file_obj): - """Generate correlated angle-energy distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for a correlated - angle-energy distribution - - Returns - ------- - openmc.data.CorrelatedAngleEnergy - Correlated angle-energy distribution - - """ - params, tab2 = get_tab2_record(file_obj) - lep = params[3] - ne = params[5] - energy = np.zeros(ne) - n_discrete_energies = np.zeros(ne, dtype=int) - energy_out = [] - mu = [] - for i in range(ne): - items, values = get_list_record(file_obj) - energy[i] = items[1] - n_discrete_energies[i] = items[2] - # TODO: separate out discrete lines - n_angle = items[3] - n_energy_out = items[5] - values = np.asarray(values) - values.shape = (n_energy_out, n_angle + 2) - - # Outgoing energy distribution at the i-th incoming energy - eout_i = values[:,0] - eout_p_i = values[:,1] - energy_out_i = Tabular(eout_i, eout_p_i, INTERPOLATION_SCHEME[lep], - ignore_negative=True) - energy_out.append(energy_out_i) - - # Legendre coefficients used for angular distributions - mu_i = [] - for j in range(n_energy_out): - mu_i.append(Legendre(values[j,1:])) - mu.append(mu_i) - - return cls(tab2.breakpoints, tab2.interpolation, energy, - energy_out, mu) diff --git a/openmc/data/data.py b/openmc/data/data.py deleted file mode 100644 index e813209f0..000000000 --- a/openmc/data/data.py +++ /dev/null @@ -1,385 +0,0 @@ -import itertools -from math import sqrt -import os -import re -from warnings import warn - - -# Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions -# of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), -# pp. 293-306 (2013). The "representative isotopic abundance" values from -# column 9 are used except where an interval is given, in which case the -# "best measurement" is used. -NATURAL_ABUNDANCE = { - 'H1': 0.99984426, 'H2': 0.00015574, 'He3': 0.000002, - 'He4': 0.999998, 'Li6': 0.07589, 'Li7': 0.92411, - 'Be9': 1.0, 'B10': 0.1982, 'B11': 0.8018, - 'C12': 0.988922, 'C13': 0.011078, 'N14': 0.996337, - 'N15': 0.003663, 'O16': 0.9976206, 'O17': 0.000379, - 'O18': 0.0020004, 'F19': 1.0, 'Ne20': 0.9048, - 'Ne21': 0.0027, 'Ne22': 0.0925, 'Na23': 1.0, - 'Mg24': 0.78951, 'Mg25': 0.1002, 'Mg26': 0.11029, - 'Al27': 1.0, 'Si28': 0.9222968, 'Si29': 0.0468316, - 'Si30': 0.0308716, 'P31': 1.0, 'S32': 0.9504074, - 'S33': 0.0074869, 'S34': 0.0419599, 'S36': 0.0001458, - 'Cl35': 0.757647, 'Cl37': 0.242353, 'Ar36': 0.003336, - 'Ar38': 0.000629, 'Ar40': 0.996035, 'K39': 0.932581, - 'K40': 0.000117, 'K41': 0.067302, 'Ca40': 0.96941, - 'Ca42': 0.00647, 'Ca43': 0.00135, 'Ca44': 0.02086, - 'Ca46': 0.00004, 'Ca48': 0.00187, 'Sc45': 1.0, - 'Ti46': 0.0825, 'Ti47': 0.0744, 'Ti48': 0.7372, - 'Ti49': 0.0541, 'Ti50': 0.0518, 'V50': 0.0025, - 'V51': 0.9975, 'Cr50': 0.04345, 'Cr52': 0.83789, - 'Cr53': 0.09501, 'Cr54': 0.02365, 'Mn55': 1.0, - 'Fe54': 0.05845, 'Fe56': 0.91754, 'Fe57': 0.02119, - 'Fe58': 0.00282, 'Co59': 1.0, 'Ni58': 0.680769, - 'Ni60': 0.262231, 'Ni61': 0.011399, 'Ni62': 0.036345, - 'Ni64': 0.009256, 'Cu63': 0.6915, 'Cu65': 0.3085, - 'Zn64': 0.4917, 'Zn66': 0.2773, 'Zn67': 0.0404, - 'Zn68': 0.1845, 'Zn70': 0.0061, 'Ga69': 0.60108, - 'Ga71': 0.39892, 'Ge70': 0.2052, 'Ge72': 0.2745, - 'Ge73': 0.0776, 'Ge74': 0.3652, 'Ge76': 0.0775, - 'As75': 1.0, 'Se74': 0.0086, 'Se76': 0.0923, - 'Se77': 0.076, 'Se78': 0.2369, 'Se80': 0.498, - 'Se82': 0.0882, 'Br79': 0.50686, 'Br81': 0.49314, - 'Kr78': 0.00355, 'Kr80': 0.02286, 'Kr82': 0.11593, - 'Kr83': 0.115, 'Kr84': 0.56987, 'Kr86': 0.17279, - 'Rb85': 0.7217, 'Rb87': 0.2783, 'Sr84': 0.0056, - 'Sr86': 0.0986, 'Sr87': 0.07, 'Sr88': 0.8258, - 'Y89': 1.0, 'Zr90': 0.5145, 'Zr91': 0.1122, - 'Zr92': 0.1715, 'Zr94': 0.1738, 'Zr96': 0.028, - 'Nb93': 1.0, 'Mo92': 0.14649, 'Mo94': 0.09187, - 'Mo95': 0.15873, 'Mo96': 0.16673, 'Mo97': 0.09582, - 'Mo98': 0.24292, 'Mo100': 0.09744, 'Ru96': 0.0554, - 'Ru98': 0.0187, 'Ru99': 0.1276, 'Ru100': 0.126, - 'Ru101': 0.1706, 'Ru102': 0.3155, 'Ru104': 0.1862, - 'Rh103': 1.0, 'Pd102': 0.0102, 'Pd104': 0.1114, - 'Pd105': 0.2233, 'Pd106': 0.2733, 'Pd108': 0.2646, - 'Pd110': 0.1172, 'Ag107': 0.51839, 'Ag109': 0.48161, - 'Cd106': 0.01245, 'Cd108': 0.00888, 'Cd110': 0.1247, - 'Cd111': 0.12795, 'Cd112': 0.24109, 'Cd113': 0.12227, - 'Cd114': 0.28754, 'Cd116': 0.07512, 'In113': 0.04281, - 'In115': 0.95719, 'Sn112': 0.0097, 'Sn114': 0.0066, - 'Sn115': 0.0034, 'Sn116': 0.1454, 'Sn117': 0.0768, - 'Sn118': 0.2422, 'Sn119': 0.0859, 'Sn120': 0.3258, - 'Sn122': 0.0463, 'Sn124': 0.0579, 'Sb121': 0.5721, - 'Sb123': 0.4279, 'Te120': 0.0009, 'Te122': 0.0255, - 'Te123': 0.0089, 'Te124': 0.0474, 'Te125': 0.0707, - 'Te126': 0.1884, 'Te128': 0.3174, 'Te130': 0.3408, - 'I127': 1.0, 'Xe124': 0.00095, 'Xe126': 0.00089, - 'Xe128': 0.0191, 'Xe129': 0.26401, 'Xe130': 0.04071, - 'Xe131': 0.21232, 'Xe132': 0.26909, 'Xe134': 0.10436, - 'Xe136': 0.08857, 'Cs133': 1.0, 'Ba130': 0.0011, - 'Ba132': 0.001, 'Ba134': 0.0242, 'Ba135': 0.0659, - 'Ba136': 0.0785, 'Ba137': 0.1123, 'Ba138': 0.717, - 'La138': 0.0008881, 'La139': 0.9991119, 'Ce136': 0.00186, - 'Ce138': 0.00251, 'Ce140': 0.88449, 'Ce142': 0.11114, - 'Pr141': 1.0, 'Nd142': 0.27153, 'Nd143': 0.12173, - 'Nd144': 0.23798, 'Nd145': 0.08293, 'Nd146': 0.17189, - 'Nd148': 0.05756, 'Nd150': 0.05638, 'Sm144': 0.0308, - 'Sm147': 0.15, 'Sm148': 0.1125, 'Sm149': 0.1382, - 'Sm150': 0.0737, 'Sm152': 0.2674, 'Sm154': 0.2274, - 'Eu151': 0.4781, 'Eu153': 0.5219, 'Gd152': 0.002, - 'Gd154': 0.0218, 'Gd155': 0.148, 'Gd156': 0.2047, - 'Gd157': 0.1565, 'Gd158': 0.2484, 'Gd160': 0.2186, - 'Tb159': 1.0, 'Dy156': 0.00056, 'Dy158': 0.00095, - 'Dy160': 0.02329, 'Dy161': 0.18889, 'Dy162': 0.25475, - 'Dy163': 0.24896, 'Dy164': 0.2826, 'Ho165': 1.0, - 'Er162': 0.00139, 'Er164': 0.01601, 'Er166': 0.33503, - 'Er167': 0.22869, 'Er168': 0.26978, 'Er170': 0.1491, - 'Tm169': 1.0, 'Yb168': 0.00123, 'Yb170': 0.02982, - 'Yb171': 0.14086, 'Yb172': 0.21686, 'Yb173': 0.16103, - 'Yb174': 0.32025, 'Yb176': 0.12995, 'Lu175': 0.97401, - 'Lu176': 0.02599, 'Hf174': 0.0016, 'Hf176': 0.0526, - 'Hf177': 0.186, 'Hf178': 0.2728, 'Hf179': 0.1362, - 'Hf180': 0.3508, 'Ta180': 0.0001201, 'Ta181': 0.9998799, - 'W180': 0.0012, 'W182': 0.265, 'W183': 0.1431, - 'W184': 0.3064, 'W186': 0.2843, 'Re185': 0.374, - 'Re187': 0.626, 'Os184': 0.0002, 'Os186': 0.0159, - 'Os187': 0.0196, 'Os188': 0.1324, 'Os189': 0.1615, - 'Os190': 0.2626, 'Os192': 0.4078, 'Ir191': 0.373, - 'Ir193': 0.627, 'Pt190': 0.00012, 'Pt192': 0.00782, - 'Pt194': 0.32864, 'Pt195': 0.33775, 'Pt196': 0.25211, - 'Pt198': 0.07356, 'Au197': 1.0, 'Hg196': 0.0015, - 'Hg198': 0.1004, 'Hg199': 0.1694, 'Hg200': 0.2314, - 'Hg201': 0.1317, 'Hg202': 0.2974, 'Hg204': 0.0682, - 'Tl203': 0.29524, 'Tl205': 0.70476, 'Pb204': 0.014, - 'Pb206': 0.241, 'Pb207': 0.221, 'Pb208': 0.524, - 'Bi209': 1.0, 'Th230': 0.0002, 'Th232': 0.9998, - 'Pa231': 1.0, 'U234': 0.000054, 'U235': 0.007204, - 'U238': 0.992742 -} - -ATOMIC_SYMBOL = {0: 'n', 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', - 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', 12: 'Mg', 13: 'Al', - 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', - 20: 'Ca', 21: 'Sc', 22: 'Ti', 23: 'V', 24: 'Cr', 25: 'Mn', - 26: 'Fe', 27: 'Co', 28: 'Ni', 29: 'Cu', 30: 'Zn', 31: 'Ga', - 32: 'Ge', 33: 'As', 34: 'Se', 35: 'Br', 36: 'Kr', 37: 'Rb', - 38: 'Sr', 39: 'Y', 40: 'Zr', 41: 'Nb', 42: 'Mo', 43: 'Tc', - 44: 'Ru', 45: 'Rh', 46: 'Pd', 47: 'Ag', 48: 'Cd', 49: 'In', - 50: 'Sn', 51: 'Sb', 52: 'Te', 53: 'I', 54: 'Xe', 55: 'Cs', - 56: 'Ba', 57: 'La', 58: 'Ce', 59: 'Pr', 60: 'Nd', 61: 'Pm', - 62: 'Sm', 63: 'Eu', 64: 'Gd', 65: 'Tb', 66: 'Dy', 67: 'Ho', - 68: 'Er', 69: 'Tm', 70: 'Yb', 71: 'Lu', 72: 'Hf', 73: 'Ta', - 74: 'W', 75: 'Re', 76: 'Os', 77: 'Ir', 78: 'Pt', 79: 'Au', - 80: 'Hg', 81: 'Tl', 82: 'Pb', 83: 'Bi', 84: 'Po', 85: 'At', - 86: 'Rn', 87: 'Fr', 88: 'Ra', 89: 'Ac', 90: 'Th', 91: 'Pa', - 92: 'U', 93: 'Np', 94: 'Pu', 95: 'Am', 96: 'Cm', 97: 'Bk', - 98: 'Cf', 99: 'Es', 100: 'Fm', 101: 'Md', 102: 'No', - 103: 'Lr', 104: 'Rf', 105: 'Db', 106: 'Sg', 107: 'Bh', - 108: 'Hs', 109: 'Mt', 110: 'Ds', 111: 'Rg', 112: 'Cn', - 113: 'Nh', 114: 'Fl', 115: 'Mc', 116: 'Lv', 117: 'Ts', - 118: 'Og'} -ATOMIC_NUMBER = {value: key for key, value in ATOMIC_SYMBOL.items()} - -_ATOMIC_MASS = {} - -_GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') - - -def atomic_mass(isotope): - """Return atomic mass of isotope in atomic mass units. - - Atomic mass data comes from the `Atomic Mass Evaluation 2016 - `_. - - Parameters - ---------- - isotope : str - Name of isotope, e.g., 'Pu239' - - Returns - ------- - float - Atomic mass of isotope in [amu] - - """ - if not _ATOMIC_MASS: - - # Load data from AME2016 file - mass_file = os.path.join(os.path.dirname(__file__), 'mass16.txt') - with open(mass_file, 'r') as ame: - # Read lines in file starting at line 40 - for line in itertools.islice(ame, 39, None): - name = '{}{}'.format(line[20:22].strip(), int(line[16:19])) - mass = float(line[96:99]) + 1e-6*float( - line[100:106] + '.' + line[107:112]) - _ATOMIC_MASS[name.lower()] = mass - - # For isotopes found in some libraries that represent all natural - # isotopes of their element (e.g. C0), calculate the atomic mass as - # the sum of the atomic mass times the natural abudance of the isotopes - # that make up the element. - for element in ['C', 'Zn', 'Pt', 'Os', 'Tl']: - isotope_zero = element.lower() + '0' - _ATOMIC_MASS[isotope_zero] = 0. - for iso, abundance in NATURAL_ABUNDANCE.items(): - if re.match(r'{}\d+'.format(element), iso): - _ATOMIC_MASS[isotope_zero] += abundance * \ - _ATOMIC_MASS[iso.lower()] - - # Get rid of metastable information - if '_' in isotope: - isotope = isotope[:isotope.find('_')] - - return _ATOMIC_MASS[isotope.lower()] - - -def atomic_weight(element): - """Return atomic weight of an element in atomic mass units. - - Computes an average of the atomic mass of each of element's naturally - occurring isotopes weighted by their relative abundance. - - Parameters - ---------- - element : str - Name of element, e.g. 'H', 'U' - - Returns - ------- - float - Atomic weight of element in [amu] - - """ - weight = 0. - for nuclide, abundance in NATURAL_ABUNDANCE.items(): - if re.match(r'{}\d+'.format(element), nuclide): - weight += atomic_mass(nuclide) * abundance - if weight > 0.: - return weight - else: - raise ValueError("No naturally-occurring isotopes for element '{}'." - .format(element)) - - -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 = _GND_NAME_RE.match(name).groups() - except AttributeError: - raise ValueError("'{}' does not appear to be a nuclide name in GND " - "format".format(name)) - - if symbol not in ATOMIC_NUMBER: - raise ValueError("'{}' is not a recognized element symbol" - .format(symbol)) - - 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 - -# Unit conversions -EV_PER_MEV = 1.0e6 -JOULE_PER_EV = 1.6021766208e-19 - -# Avogadro's constant -AVOGADRO = 6.022140857e23 - -# Neutron mass in units of amu -NEUTRON_MASS = 1.00866491588 diff --git a/openmc/data/decay.py b/openmc/data/decay.py deleted file mode 100644 index 6a8ad39f0..000000000 --- a/openmc/data/decay.py +++ /dev/null @@ -1,484 +0,0 @@ -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 - -import numpy as np -from uncertainties import ufloat, unumpy, UFloat - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER -from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record - - -# Gives name and (change in A, change in Z) resulting from decay -_DECAY_MODES = { - 0: ('gamma', (0, 0)), - 1: ('beta-', (0, 1)), - 2: ('ec/beta+', (0, -1)), - 3: ('IT', (0, 0)), - 4: ('alpha', (-4, -2)), - 5: ('n', (-1, 0)), - 6: ('sf', None), - 7: ('p', (-1, -1)), - 8: ('e-', (0, 0)), - 9: ('xray', (0, 0)), - 10: ('unknown', None) -} - -_RADIATION_TYPES = { - 0: 'gamma', - 1: 'beta-', - 2: 'ec/beta+', - 4: 'alpha', - 5: 'n', - 6: 'sf', - 7: 'p', - 8: 'e-', - 9: 'xray', - 10: 'anti-neutrino', - 11: 'neutrino' -} - - -def get_decay_modes(value): - """Return sequence of decay modes given an ENDF RTYP value. - - Parameters - ---------- - value : float - ENDF definition of sequence of decay modes - - Returns - ------- - list of str - List of successive decays, e.g. ('beta-', 'neutron') - - """ - return [_DECAY_MODES[int(x)][0] for x in - str(value).strip('0').replace('.', '')] - - -class FissionProductYields(EqualityMixin): - """Independent and cumulative fission product yields. - - Parameters - ---------- - ev_or_filename : str of openmc.data.endf.Evaluation - ENDF fission product yield evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Attributes - ---------- - cumulative : list of dict - Cumulative yields for each tabulated energy. Each item in the list is a - dictionary whose keys are nuclide names and values are cumulative - yields. The i-th dictionary corresponds to the i-th incident neutron - energy. - energies : Iterable of float or None - Energies at which fission product yields are tabulated. - independent : list of dict - Independent yields for each tabulated energy. Each item in the list is a - dictionary whose keys are nuclide names and values are independent - yields. The i-th dictionary corresponds to the i-th incident neutron - energy. - nuclide : dict - Properties of the fissioning nuclide. - - Notes - ----- - Neutron fission yields are typically not measured with a monoenergetic - source of neutrons. As such, if the fission yields are given at, e.g., - 0.0253 eV, one should interpret this as meaning that they are derived from a - typical thermal reactor flux spectrum as opposed to a monoenergetic source - at 0.0253 eV. - - """ - def __init__(self, ev_or_filename): - # Define function that can be used to read both independent and - # cumulative yields - def get_yields(file_obj): - # Determine number of energies - n_energy = get_head_record(file_obj)[2] - energies = np.zeros(n_energy) - - data = [] - for i in range(n_energy): - # Determine i-th energy and number of products - items, values = get_list_record(file_obj) - energies[i] = items[0] - n_products = items[5] - - # Get yields for i-th energy - yields = {} - for j in range(n_products): - Z, A = divmod(int(values[4*j]), 1000) - isomeric_state = int(values[4*j + 1]) - name = ATOMIC_SYMBOL[Z] + str(A) - if isomeric_state > 0: - name += '_m{}'.format(isomeric_state) - yield_j = ufloat(values[4*j + 2], values[4*j + 3]) - yields[name] = yield_j - - data.append(yields) - - return energies, data - - # Get evaluation if str is passed - if isinstance(ev_or_filename, Evaluation): - ev = ev_or_filename - else: - ev = Evaluation(ev_or_filename) - - # Assign basic nuclide properties - self.nuclide = { - 'name': ev.gnd_name, - 'atomic_number': ev.target['atomic_number'], - 'mass_number': ev.target['mass_number'], - 'isomeric_state': ev.target['isomeric_state'] - } - - # Read independent yields - if (8, 454) in ev.section: - file_obj = StringIO(ev.section[8, 454]) - self.energies, self.independent = get_yields(file_obj) - - # Read cumulative yields - if (8, 459) in ev.section: - file_obj = StringIO(ev.section[8, 459]) - energies, self.cumulative = get_yields(file_obj) - assert np.all(energies == self.energies) - - @classmethod - def from_endf(cls, ev_or_filename): - """Generate fission product yield data from an ENDF evaluation - - Parameters - ---------- - ev_or_filename : str or openmc.data.endf.Evaluation - ENDF fission product yield evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Returns - ------- - openmc.data.FissionProductYields - Fission product yield data - - """ - return cls(ev_or_filename) - - -class DecayMode(EqualityMixin): - """Radioactive decay mode. - - Parameters - ---------- - parent : str - Parent decaying nuclide - modes : list of str - Successive decay modes - daughter_state : int - Metastable state of the daughter nuclide - energy : uncertainties.UFloat - Total decay energy in eV available in the decay process. - branching_ratio : uncertainties.UFloat - Fraction of the decay of the parent nuclide which proceeds by this mode. - - Attributes - ---------- - branching_ratio : uncertainties.UFloat - Fraction of the decay of the parent nuclide which proceeds by this mode. - daughter : str - Name of daughter nuclide produced from decay - energy : uncertainties.UFloat - Total decay energy in eV available in the decay process. - modes : list of str - Successive decay modes - parent : str - Parent decaying nuclide - - """ - - def __init__(self, parent, modes, daughter_state, energy, - branching_ratio): - self._daughter_state = daughter_state - self.parent = parent - self.modes = modes - self.energy = energy - self.branching_ratio = branching_ratio - - def __repr__(self): - return (' {}, {}>'.format( - ','.join(self.modes), self.parent, self.daughter, - self.branching_ratio)) - - @property - def branching_ratio(self): - return self._branching_ratio - - @property - def daughter(self): - # Determine atomic number and mass number of parent - symbol, A = re.match(r'([A-Zn][a-z]*)(\d+)', self.parent).groups() - A = int(A) - Z = ATOMIC_NUMBER[symbol] - - # Process changes - for mode in self.modes: - for name, changes in _DECAY_MODES.values(): - if name == mode: - if changes is not None: - delta_A, delta_Z = changes - A += delta_A - Z += delta_Z - - if self._daughter_state > 0: - return '{}{}_m{}'.format(ATOMIC_SYMBOL[Z], A, self._daughter_state) - else: - return '{}{}'.format(ATOMIC_SYMBOL[Z], A) - - @property - def energy(self): - return self._energy - - @property - def modes(self): - return self._modes - - @property - def parent(self): - return self._parent - - @branching_ratio.setter - def branching_ratio(self, branching_ratio): - cv.check_type('branching ratio', branching_ratio, UFloat) - cv.check_greater_than('branching ratio', - branching_ratio.nominal_value, 0.0, True) - if branching_ratio.nominal_value == 0.0: - warn('Decay mode {} of parent {} has a zero branching ratio.' - .format(self.modes, self.parent)) - cv.check_greater_than('branching ratio uncertainty', - branching_ratio.std_dev, 0.0, True) - self._branching_ratio = branching_ratio - - @energy.setter - def energy(self, energy): - cv.check_type('decay energy', energy, UFloat) - cv.check_greater_than('decay energy', energy.nominal_value, 0.0, True) - cv.check_greater_than('decay energy uncertainty', - energy.std_dev, 0.0, True) - self._energy = energy - - @modes.setter - def modes(self, modes): - cv.check_type('decay modes', modes, Iterable, str) - self._modes = modes - - @parent.setter - def parent(self, parent): - cv.check_type('parent nuclide', parent, str) - self._parent = parent - - -class Decay(EqualityMixin): - """Radioactive decay data. - - Parameters - ---------- - ev_or_filename : str of openmc.data.endf.Evaluation - ENDF radioactive decay data evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Attributes - ---------- - average_energies : dict - Average decay energies in eV of each type of radiation for decay heat - applications. - decay_constant : uncertainties.UFloat - Decay constant in inverse seconds. - half_life : uncertainties.UFloat - Half-life of the decay in seconds. - modes : list - Decay mode information for each mode of decay. - nuclide : dict - Dictionary describing decaying nuclide with keys 'name', - 'excited_state', 'mass', 'stable', 'spin', and 'parity'. - spectra : dict - Resulting radiation spectra for each radiation type. - - """ - def __init__(self, ev_or_filename): - # Get evaluation if str is passed - if isinstance(ev_or_filename, Evaluation): - ev = ev_or_filename - else: - ev = Evaluation(ev_or_filename) - - file_obj = StringIO(ev.section[8, 457]) - - self.nuclide = {} - self.modes = [] - self.spectra = {} - self.average_energies = {} - - # Get head record - items = get_head_record(file_obj) - Z, A = divmod(items[0], 1000) - metastable = items[3] - self.nuclide['atomic_number'] = Z - self.nuclide['mass_number'] = A - self.nuclide['isomeric_state'] = metastable - if metastable > 0: - self.nuclide['name'] = '{}{}_m{}'.format(ATOMIC_SYMBOL[Z], A, - metastable) - else: - self.nuclide['name'] = '{}{}'.format(ATOMIC_SYMBOL[Z], A) - self.nuclide['mass'] = items[1] # AWR - self.nuclide['excited_state'] = items[2] # State of the original nuclide - self.nuclide['stable'] = (items[4] == 1) # Nucleus stability flag - - # Determine if radioactive/stable - if not self.nuclide['stable']: - NSP = items[5] # Number of radiation types - - # Half-life and decay energies - items, values = get_list_record(file_obj) - self.half_life = ufloat(items[0], items[1]) - NC = items[4]//2 - pairs = [x for x in zip(values[::2], values[1::2])] - ex = self.average_energies - ex['light'] = ufloat(*pairs[0]) - ex['electromagnetic'] = ufloat(*pairs[1]) - ex['heavy'] = ufloat(*pairs[2]) - if NC == 17: - ex['beta-'] = ufloat(*pairs[3]) - ex['beta+'] = ufloat(*pairs[4]) - ex['auger'] = ufloat(*pairs[5]) - ex['conversion'] = ufloat(*pairs[6]) - ex['gamma'] = ufloat(*pairs[7]) - ex['xray'] = ufloat(*pairs[8]) - ex['Bremsstrahlung'] = ufloat(*pairs[9]) - ex['annihilation'] = ufloat(*pairs[10]) - ex['alpha'] = ufloat(*pairs[11]) - ex['recoil'] = ufloat(*pairs[12]) - ex['SF'] = ufloat(*pairs[13]) - ex['neutron'] = ufloat(*pairs[14]) - ex['proton'] = ufloat(*pairs[15]) - ex['neutrino'] = ufloat(*pairs[16]) - - items, values = get_list_record(file_obj) - spin = items[0] - if spin == -77.777: - self.nuclide['spin'] = None - else: - self.nuclide['spin'] = spin - self.nuclide['parity'] = items[1] # Parity of the nuclide - - # Decay mode information - n_modes = items[5] # Number of decay modes - for i in range(n_modes): - decay_type = get_decay_modes(values[6*i]) - isomeric_state = int(values[6*i + 1]) - energy = ufloat(*values[6*i + 2:6*i + 4]) - branching_ratio = ufloat(*values[6*i + 4:6*(i + 1)]) - - mode = DecayMode(self.nuclide['name'], decay_type, isomeric_state, - energy, branching_ratio) - self.modes.append(mode) - - discrete_type = {0.0: None, 1.0: 'allowed', 2.0: 'first-forbidden', - 3.0: 'second-forbidden', 4.0: 'third-forbidden', - 5.0: 'fourth-forbidden', 6.0: 'fifth-forbidden'} - - # Read spectra - for i in range(NSP): - spectrum = {} - - items, values = get_list_record(file_obj) - # Decay radiation type - spectrum['type'] = _RADIATION_TYPES[items[1]] - # Continuous spectrum flag - spectrum['continuous_flag'] = {0: 'discrete', 1: 'continuous', - 2: 'both'}[items[2]] - spectrum['discrete_normalization'] = ufloat(*values[0:2]) - spectrum['energy_average'] = ufloat(*values[2:4]) - spectrum['continuous_normalization'] = ufloat(*values[4:6]) - - NER = items[5] # Number of tabulated discrete energies - - if not spectrum['continuous_flag'] == 'continuous': - # Information about discrete spectrum - spectrum['discrete'] = [] - for j in range(NER): - items, values = get_list_record(file_obj) - di = {} - di['energy'] = ufloat(*items[0:2]) - di['from_mode'] = get_decay_modes(values[0]) - di['type'] = discrete_type[values[1]] - di['intensity'] = ufloat(*values[2:4]) - if spectrum['type'] == 'ec/beta+': - di['positron_intensity'] = ufloat(*values[4:6]) - elif spectrum['type'] == 'gamma': - if len(values) >= 6: - di['internal_pair'] = ufloat(*values[4:6]) - if len(values) >= 8: - di['total_internal_conversion'] = ufloat(*values[6:8]) - if len(values) == 12: - di['k_shell_conversion'] = ufloat(*values[8:10]) - di['l_shell_conversion'] = ufloat(*values[10:12]) - spectrum['discrete'].append(di) - - if not spectrum['continuous_flag'] == 'discrete': - # Read continuous spectrum - ci = {} - params, ci['probability'] = get_tab1_record(file_obj) - ci['type'] = get_decay_modes(params[0]) - - # Read covariance (Ek, Fk) table - LCOV = params[3] - if LCOV != 0: - items, values = get_list_record(file_obj) - ci['covariance_lb'] = items[3] - ci['covariance'] = zip(values[0::2], values[1::2]) - - spectrum['continuous'] = ci - - # Add spectrum to dictionary - self.spectra[spectrum['type']] = spectrum - - else: - items, values = get_list_record(file_obj) - 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): - if hasattr(self.half_life, 'n'): - return log(2.)/self.half_life - else: - mu, sigma = self.half_life - return ufloat(log(2.)/mu, log(2.)/mu**2*sigma) - - @classmethod - def from_endf(cls, ev_or_filename): - """Generate radioactive decay data from an ENDF evaluation - - Parameters - ---------- - ev_or_filename : str or openmc.data.endf.Evaluation - ENDF radioactive decay data evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Returns - ------- - openmc.data.Decay - Radioactive decay data - - """ - return cls(ev_or_filename) diff --git a/openmc/data/density_effect.h5 b/openmc/data/density_effect.h5 deleted file mode 100644 index 77d973517..000000000 Binary files a/openmc/data/density_effect.h5 and /dev/null differ diff --git a/openmc/data/endf.c b/openmc/data/endf.c deleted file mode 100644 index fee6af179..000000000 --- a/openmc/data/endf.c +++ /dev/null @@ -1,39 +0,0 @@ -#include - -double cfloat_endf(const char* buffer, int n) -{ - char arr[12]; // 11 characters plus a null terminator - int j = 0; // current position in arr - int found_significand = 0; - int found_exponent = 0; - for (int i = 0; i < n; ++i) { - // Skip whitespace characters - char c = buffer[i]; - if (c == ' ') continue; - - if (found_significand) { - if (!found_exponent) { - if (c == '+' || c == '-') { - // In the case that we encounter +/- and we haven't yet encountered - // e/E, we manually add it - arr[j++] = 'e'; - found_exponent = 1; - - } else if (c == 'e' || c == 'E' || c == 'd' || c == 'D') { - arr[j++] = 'e'; - found_exponent = 1; - continue; - } - } - } else if (c == '.' || (c >= '0' && c <= '9')) { - found_significand = 1; - } - - // Copy character - arr[j++] = c; - } - - // Done copying. Add null terminator and convert to double - arr[j] = '\0'; - return atof(arr); -} diff --git a/openmc/data/endf.py b/openmc/data/endf.py deleted file mode 100644 index 92a558e21..000000000 --- a/openmc/data/endf.py +++ /dev/null @@ -1,550 +0,0 @@ -"""Module for parsing and manipulating data from ENDF evaluations. - -All the classes and functions in this module are based on document -ENDF-102 titled "Data Formats and Procedures for the Evaluated Nuclear -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 - -""" -import io -import re -import os -from math import pi -from pathlib import PurePath -from collections import OrderedDict -from collections.abc import Iterable - -import numpy as np -from numpy.polynomial.polynomial import Polynomial - -from .data import ATOMIC_SYMBOL, gnd_name -from .function import Tabulated1D, INTERPOLATION_SCHEME -from openmc.stats.univariate import Uniform, Tabular, Legendre -try: - from ._endf import float_endf - _CYTHON = True -except ImportError: - _CYTHON = False - - -_LIBRARY = {0: 'ENDF/B', 1: 'ENDF/A', 2: 'JEFF', 3: 'EFF', - 4: 'ENDF/B High Energy', 5: 'CENDL', 6: 'JENDL', - 17: 'TENDL', 18: 'ROSFOND', 21: 'SG-21', 31: 'INDL/V', - 32: 'INDL/A', 33: 'FENDL', 34: 'IRDF', 35: 'BROND', - 36: 'INGDB-90', 37: 'FENDL/A', 41: 'BROND'} - -_SUBLIBRARY = { - 0: 'Photo-nuclear data', - 1: 'Photo-induced fission product yields', - 3: 'Photo-atomic data', - 4: 'Radioactive decay data', - 5: 'Spontaneous fission product yields', - 6: 'Atomic relaxation data', - 10: 'Incident-neutron data', - 11: 'Neutron-induced fission product yields', - 12: 'Thermal neutron scattering data', - 19: 'Neutron standards', - 113: 'Electro-atomic data', - 10010: 'Incident-proton data', - 10011: 'Proton-induced fission product yields', - 10020: 'Incident-deuteron data', - 10030: 'Incident-triton data', - 20030: 'Incident-helion (3He) data', - 20040: 'Incident-alpha data' -} - -SUM_RULES = {1: [2, 3], - 3: [4, 5, 11, 16, 17, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, - 36, 37, 41, 42, 44, 45, 152, 153, 154, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, 181, 183, 184, 185, - 186, 187, 188, 189, 190, 194, 195, 196, 198, 199, 200], - 4: list(range(50, 92)), - 16: list(range(875, 892)), - 18: [19, 20, 21, 38], - 27: [18, 101], - 101: [102, 103, 104, 105, 106, 107, 108, 109, 111, 112, 113, 114, - 115, 116, 117, 155, 182, 191, 192, 193, 197], - 103: list(range(600, 650)), - 104: list(range(650, 700)), - 105: list(range(700, 750)), - 106: list(range(750, 800)), - 107: list(range(800, 850))} - -ENDF_FLOAT_RE = re.compile(r'([\s\-\+]?\d*\.\d+)([\+\-]) ?(\d+)') - - -def py_float_endf(s): - """Convert string of floating point number in ENDF to float. - - The ENDF-6 format uses an 'e-less' floating point number format, - e.g. -1.23481+10. Trying to convert using the float built-in won't work - because of the lack of an 'e'. This function allows such strings to be - converted while still allowing numbers that are not in exponential notation - to be converted as well. - - Parameters - ---------- - s : str - Floating-point number from an ENDF file - - Returns - ------- - float - The number - - """ - return float(ENDF_FLOAT_RE.sub(r'\1e\2\3', s)) - - -if not _CYTHON: - float_endf = py_float_endf - - -def int_endf(s): - """Convert string of integer number in ENDF to int. - - The ENDF-6 format technically allows integers to be represented by a field - of all blanks. This function acts like int(s) except when s is a string of - all whitespace, in which case zero is returned. - - Parameters - ---------- - s : str - Integer or spaces - - Returns - ------- - integer - The number or 0 - """ - return 0 if s.isspace() else int(s) - - -def get_text_record(file_obj): - """Return data from a TEXT record in an ENDF-6 file. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - - Returns - ------- - str - Text within the TEXT record - - """ - return file_obj.readline()[:66] - - -def get_cont_record(file_obj, skip_c=False): - """Return data from a CONT record in an ENDF-6 file. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - skip_c : bool - Determine whether to skip the first two quantities (C1, C2) of the CONT - record. - - Returns - ------- - tuple - The six items within the CONT record - - """ - line = file_obj.readline() - if skip_c: - C1 = None - C2 = None - else: - C1 = float_endf(line[:11]) - C2 = float_endf(line[11:22]) - L1 = int_endf(line[22:33]) - L2 = int_endf(line[33:44]) - N1 = int_endf(line[44:55]) - N2 = int_endf(line[55:66]) - return (C1, C2, L1, L2, N1, N2) - - -def get_head_record(file_obj): - """Return data from a HEAD record in an ENDF-6 file. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - - Returns - ------- - tuple - The six items within the HEAD record - - """ - line = file_obj.readline() - ZA = int(float_endf(line[:11])) - AWR = float_endf(line[11:22]) - L1 = int_endf(line[22:33]) - L2 = int_endf(line[33:44]) - N1 = int_endf(line[44:55]) - N2 = int_endf(line[55:66]) - return (ZA, AWR, L1, L2, N1, N2) - - -def get_list_record(file_obj): - """Return data from a LIST record in an ENDF-6 file. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - - Returns - ------- - list - The six items within the header - list - The values within the list - - """ - # determine how many items are in list - items = get_cont_record(file_obj) - NPL = items[4] - - # read items - b = [] - for i in range((NPL - 1)//6 + 1): - line = file_obj.readline() - n = min(6, NPL - 6*i) - for j in range(n): - b.append(float_endf(line[11*j:11*(j + 1)])) - - return (items, b) - - -def get_tab1_record(file_obj): - """Return data from a TAB1 record in an ENDF-6 file. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - - Returns - ------- - list - The six items within the header - openmc.data.Tabulated1D - The tabulated function - - """ - # Determine how many interpolation regions and total points there are - line = file_obj.readline() - C1 = float_endf(line[:11]) - C2 = float_endf(line[11:22]) - L1 = int_endf(line[22:33]) - L2 = int_endf(line[33:44]) - n_regions = int_endf(line[44:55]) - n_pairs = int_endf(line[55:66]) - params = [C1, C2, L1, L2] - - # Read the interpolation region data, namely NBT and INT - breakpoints = np.zeros(n_regions, dtype=int) - interpolation = np.zeros(n_regions, dtype=int) - m = 0 - for i in range((n_regions - 1)//3 + 1): - line = file_obj.readline() - to_read = min(3, n_regions - m) - for j in range(to_read): - breakpoints[m] = int_endf(line[0:11]) - interpolation[m] = int_endf(line[11:22]) - line = line[22:] - m += 1 - - # Read tabulated pairs x(n) and y(n) - x = np.zeros(n_pairs) - y = np.zeros(n_pairs) - m = 0 - for i in range((n_pairs - 1)//3 + 1): - line = file_obj.readline() - to_read = min(3, n_pairs - m) - for j in range(to_read): - x[m] = float_endf(line[:11]) - y[m] = float_endf(line[11:22]) - line = line[22:] - m += 1 - - return params, Tabulated1D(x, y, breakpoints, interpolation) - - -def get_tab2_record(file_obj): - # Determine how many interpolation regions and total points there are - params = get_cont_record(file_obj) - n_regions = params[4] - - # Read the interpolation region data, namely NBT and INT - breakpoints = np.zeros(n_regions, dtype=int) - interpolation = np.zeros(n_regions, dtype=int) - m = 0 - for i in range((n_regions - 1)//3 + 1): - line = file_obj.readline() - to_read = min(3, n_regions - m) - for j in range(to_read): - breakpoints[m] = int(line[0:11]) - interpolation[m] = int(line[11:22]) - line = line[22:] - m += 1 - - return params, Tabulated2D(breakpoints, interpolation) - - -def get_intg_record(file_obj): - """ - Return data from an INTG record in an ENDF-6 file. Used to store the - covariance matrix in a compact format. - - Parameters - ---------- - file_obj : file-like object - ENDF-6 file to read from - - Returns - ------- - numpy.ndarray - The correlation matrix described in the INTG record - """ - # determine how many items are in list and NDIGIT - items = get_cont_record(file_obj) - ndigit = items[2] - npar = items[3] # Number of parameters - nlines = items[4] # Lines to read - NROW_RULES = {2: 18, 3: 12, 4: 11, 5: 9, 6: 8} - nrow = NROW_RULES[ndigit] - - # read lines and build correlation matrix - corr = np.identity(npar) - for i in range(nlines): - line = file_obj.readline() - ii = int_endf(line[:5]) - 1 # -1 to account for 0 indexing - jj = int_endf(line[5:10]) - 1 - factor = 10**ndigit - for j in range(nrow): - if jj+j >= ii: - break - element = int_endf(line[11+(ndigit+1)*j:11+(ndigit+1)*(j+1)]) - if element > 0: - corr[ii, jj] = (element+0.5)/factor - elif element < 0: - corr[ii, jj] = (element-0.5)/factor - - # Symmetrize the correlation matrix - corr = corr + corr.T - np.diag(corr.diagonal()) - return corr - - -def get_evaluations(filename): - """Return a list of all evaluations within an ENDF file. - - Parameters - ---------- - filename : str - Path to ENDF-6 formatted file - - Returns - ------- - list - A list of :class:`openmc.data.endf.Evaluation` instances. - - """ - evaluations = [] - with open(str(filename), 'r') as fh: - while True: - pos = fh.tell() - line = fh.readline() - if line[66:70] == ' -1': - break - fh.seek(pos) - evaluations.append(Evaluation(fh)) - return evaluations - - -class Evaluation(object): - """ENDF material evaluation with multiple files/sections - - Parameters - ---------- - filename_or_obj : str or file-like - Path to ENDF file to read or an open file positioned at the start of an - ENDF material - - Attributes - ---------- - info : dict - Miscellaneous information about the evaluation. - target : dict - Information about the target material, such as its mass, isomeric state, - whether it's stable, and whether it's fissionable. - projectile : dict - Information about the projectile such as its mass. - reaction_list : list of 4-tuples - List of sections in the evaluation. The entries of the tuples are the - file (MF), section (MT), number of records (NC), and modification - indicator (MOD). - - """ - def __init__(self, filename_or_obj): - if isinstance(filename_or_obj, (str, PurePath)): - fh = open(str(filename_or_obj), 'r') - else: - fh = filename_or_obj - self.section = {} - self.info = {} - self.target = {} - self.projectile = {} - self.reaction_list = [] - - # Skip TPID record. Evaluators sometimes put in TPID records that are - # ill-formated because they lack MF/MT values or put them in the wrong - # columns. - if fh.tell() == 0: - fh.readline() - MF = 0 - - # Determine MAT number for this evaluation - while MF == 0: - position = fh.tell() - line = fh.readline() - MF = int(line[70:72]) - self.material = int(line[66:70]) - fh.seek(position) - - while True: - # Find next section - while True: - position = fh.tell() - line = fh.readline() - MAT = int(line[66:70]) - MF = int(line[70:72]) - MT = int(line[72:75]) - if MT > 0 or MAT == 0: - fh.seek(position) - break - - # If end of material reached, exit loop - if MAT == 0: - fh.readline() - break - - section_data = '' - while True: - line = fh.readline() - if line[72:75] == ' 0': - break - else: - section_data += line - self.section[MF, MT] = section_data - - self._read_header() - - def __repr__(self): - if 'zsymam' in self.target: - name = self.target['zsymam'].replace(' ', '') - else: - name = 'Unknown' - return '<{} for {} {}>'.format(self.info['sublibrary'], name, - self.info['library']) - - def _read_header(self): - file_obj = io.StringIO(self.section[1, 451]) - - # Information about target/projectile - items = get_head_record(file_obj) - Z, A = divmod(items[0], 1000) - self.target['atomic_number'] = Z - self.target['mass_number'] = A - self.target['mass'] = items[1] - self._LRP = items[2] - self.target['fissionable'] = (items[3] == 1) - try: - library = _LIBRARY[items[4]] - except KeyError: - library = 'Unknown' - self.info['modification'] = items[5] - - # Control record 1 - items = get_cont_record(file_obj) - self.target['excitation_energy'] = items[0] - self.target['stable'] = (int(items[1]) == 0) - self.target['state'] = items[2] - self.target['isomeric_state'] = m = items[3] - self.info['format'] = items[5] - assert self.info['format'] == 6 - - # Set correct excited state for Am242_m1, which is wrong in ENDF/B-VII.1 - if Z == 95 and A == 242 and m == 1: - self.target['state'] = 2 - - # Control record 2 - items = get_cont_record(file_obj) - self.projectile['mass'] = items[0] - self.info['energy_max'] = items[1] - library_release = items[2] - self.info['sublibrary'] = _SUBLIBRARY[items[4]] - library_version = items[5] - self.info['library'] = (library, library_version, library_release) - - # Control record 3 - items = get_cont_record(file_obj) - self.target['temperature'] = items[0] - self.info['derived'] = (items[2] > 0) - NWD = items[4] - NXC = items[5] - - # Text records - text = [get_text_record(file_obj) for i in range(NWD)] - if len(text) >= 5: - self.target['zsymam'] = text[0][0:11] - self.info['laboratory'] = text[0][11:22] - self.info['date'] = text[0][22:32] - self.info['author'] = text[0][32:66] - self.info['reference'] = text[1][1:22] - self.info['date_distribution'] = text[1][22:32] - self.info['date_release'] = text[1][33:43] - self.info['date_entry'] = text[1][55:63] - self.info['identifier'] = text[2:5] - self.info['description'] = text[5:] - - # File numbers, reaction designations, and number of records - for i in range(NXC): - _, _, mf, mt, nc, mod = get_cont_record(file_obj, skip_c=True) - self.reaction_list.append((mf, mt, nc, mod)) - - @property - def gnd_name(self): - return gnd_name(self.target['atomic_number'], - self.target['mass_number'], - self.target['isomeric_state']) - - -class Tabulated2D(object): - """Metadata for a two-dimensional function. - - This is a dummy class that is not really used other than to store the - interpolation information for a two-dimensional function. Once we refactor - to adopt GND-like data containers, this will probably be removed or - extended. - - Parameters - ---------- - breakpoints : Iterable of int - Breakpoints for interpolation regions - interpolation : Iterable of int - Interpolation scheme identification number, e.g., 3 means y is linear in - ln(x). - - """ - def __init__(self, breakpoints, interpolation): - self.breakpoints = breakpoints - self.interpolation = interpolation diff --git a/openmc/data/energy_distribution.py b/openmc/data/energy_distribution.py deleted file mode 100644 index bff97bf81..000000000 --- a/openmc/data/energy_distribution.py +++ /dev/null @@ -1,1277 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections.abc import Iterable -from numbers import Integral, Real -from warnings import warn - -import numpy as np - -from .function import Tabulated1D, INTERPOLATION_SCHEME -from openmc.stats.univariate import Univariate, Tabular, Discrete, Mixture -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from .data import EV_PER_MEV -from .endf import get_tab1_record, get_tab2_record - - -class EnergyDistribution(EqualityMixin, metaclass=ABCMeta): - """Abstract superclass for all energy distributions.""" - def __init__(self): - pass - - @abstractmethod - def to_hdf5(self, group): - pass - - @staticmethod - def from_hdf5(group): - """Generate energy distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.EnergyDistribution - Energy distribution - - """ - energy_type = group.attrs['type'].decode() - if energy_type == 'maxwell': - return MaxwellEnergy.from_hdf5(group) - elif energy_type == 'evaporation': - return Evaporation.from_hdf5(group) - elif energy_type == 'watt': - return WattEnergy.from_hdf5(group) - elif energy_type == 'madland-nix': - return MadlandNix.from_hdf5(group) - elif energy_type == 'discrete_photon': - return DiscretePhoton.from_hdf5(group) - elif energy_type == 'level': - return LevelInelastic.from_hdf5(group) - elif energy_type == 'continuous': - return ContinuousTabular.from_hdf5(group) - else: - raise ValueError("Unknown energy distribution type: {}" - .format(energy_type)) - - @staticmethod - def from_endf(file_obj, params): - """Generate energy distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.EnergyDistribution - A sub-class of :class:`openmc.data.EnergyDistribution` - - """ - lf = params[3] - if lf == 1: - return ArbitraryTabulated.from_endf(file_obj, params) - elif lf == 5: - return GeneralEvaporation.from_endf(file_obj, params) - elif lf == 7: - return MaxwellEnergy.from_endf(file_obj, params) - elif lf == 9: - return Evaporation.from_endf(file_obj, params) - elif lf == 11: - return WattEnergy.from_endf(file_obj, params) - elif lf == 12: - return MadlandNix.from_endf(file_obj, params) - - -class ArbitraryTabulated(EnergyDistribution): - r"""Arbitrary tabulated function given in ENDF MF=5, LF=1 represented as - - .. math:: - f(E \rightarrow E') = g(E \rightarrow E') - - Parameters - ---------- - energy : numpy.ndarray - Array of incident neutron energies - pdf : list of openmc.data.Tabulated1D - Tabulated outgoing energy distribution probability density functions - - Attributes - ---------- - energy : numpy.ndarray - Array of incident neutron energies - pdf : list of openmc.data.Tabulated1D - Tabulated outgoing energy distribution probability density functions - - """ - - def __init__(self, energy, pdf): - super().__init__() - self.energy = energy - self.pdf = pdf - - def to_hdf5(self, group): - raise NotImplementedError - - @classmethod - def from_endf(cls, file_obj, params): - """Generate arbitrary tabulated distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.ArbitraryTabulated - Arbitrary tabulated distribution - - """ - params, tab2 = get_tab2_record(file_obj) - n_energies = params[5] - - energy = np.zeros(n_energies) - pdf = [] - for j in range(n_energies): - params, func = get_tab1_record(file_obj) - energy[j] = params[1] - pdf.append(func) - return cls(energy, pdf) - - -class GeneralEvaporation(EnergyDistribution): - r"""General evaporation spectrum given in ENDF MF=5, LF=5 represented as - - .. math:: - f(E \rightarrow E') = g(E'/\theta(E)) - - Parameters - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy :math:`E` - g : openmc.data.Tabulated1D - Tabulated function of :math:`x = E'/\theta(E)` - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - Attributes - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy :math:`E` - g : openmc.data.Tabulated1D - Tabulated function of :math:`x = E'/\theta(E)` - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - """ - - def __init__(self, theta, g, u): - super().__init__() - self.theta = theta - self.g = g - self.u = u - - def to_hdf5(self, group): - raise NotImplementedError - - @classmethod - def from_ace(cls, ace, idx=0): - raise NotImplementedError - - @classmethod - def from_endf(cls, file_obj, params): - """Generate general evaporation spectrum from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.GeneralEvaporation - General evaporation spectrum - - """ - u = params[0] - params, theta = get_tab1_record(file_obj) - params, g = get_tab1_record(file_obj) - return cls(theta, g, u) - - -class MaxwellEnergy(EnergyDistribution): - r"""Simple Maxwellian fission spectrum represented as - - .. math:: - f(E \rightarrow E') = \frac{\sqrt{E'}}{I} e^{-E'/\theta(E)} - - Parameters - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - Attributes - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - """ - - def __init__(self, theta, u): - super().__init__() - self.theta = theta - self.u = u - - @property - def theta(self): - return self._theta - - @property - def u(self): - return self._u - - @theta.setter - def theta(self, theta): - cv.check_type('Maxwell theta', theta, Tabulated1D) - self._theta = theta - - @u.setter - def u(self, u): - cv.check_type('Maxwell restriction energy', u, Real) - self._u = u - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('maxwell') - group.attrs['u'] = self.u - self.theta.to_hdf5(group, 'theta') - - @classmethod - def from_hdf5(cls, group): - """Generate Maxwell distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.MaxwellEnergy - Maxwell distribution - - """ - theta = Tabulated1D.from_hdf5(group['theta']) - u = group.attrs['u'] - return cls(theta, u) - - @classmethod - def from_ace(cls, ace, idx=0): - """Create a Maxwell distribution from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - - Returns - ------- - openmc.data.MaxwellEnergy - Maxwell distribution - - """ - # Read nuclear temperature -- since units are MeV, convert to eV - theta = Tabulated1D.from_ace(ace, idx) - theta.y *= EV_PER_MEV - - # Restriction energy - nr = int(ace.xss[idx]) - ne = int(ace.xss[idx + 1 + 2*nr]) - u = ace.xss[idx + 2 + 2*nr + 2*ne]*EV_PER_MEV - - return cls(theta, u) - - @classmethod - def from_endf(cls, file_obj, params): - """Generate Maxwell distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.MaxwellEnergy - Maxwell distribution - - """ - u = params[0] - params, theta = get_tab1_record(file_obj) - return cls(theta, u) - - -class Evaporation(EnergyDistribution): - r"""Evaporation spectrum represented as - - .. math:: - f(E \rightarrow E') = \frac{E'}{I} e^{-E'/\theta(E)} - - Parameters - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - Attributes - ---------- - theta : openmc.data.Tabulated1D - Tabulated function of incident neutron energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - """ - - def __init__(self, theta, u): - super().__init__() - self.theta = theta - self.u = u - - @property - def theta(self): - return self._theta - - @property - def u(self): - return self._u - - @theta.setter - def theta(self, theta): - cv.check_type('Evaporation theta', theta, Tabulated1D) - self._theta = theta - - @u.setter - def u(self, u): - cv.check_type('Evaporation restriction energy', u, Real) - self._u = u - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('evaporation') - group.attrs['u'] = self.u - self.theta.to_hdf5(group, 'theta') - - @classmethod - def from_hdf5(cls, group): - """Generate evaporation spectrum from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.Evaporation - Evaporation spectrum - - """ - theta = Tabulated1D.from_hdf5(group['theta']) - u = group.attrs['u'] - return cls(theta, u) - - @classmethod - def from_ace(cls, ace, idx=0): - """Create an evaporation spectrum from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - - Returns - ------- - openmc.data.Evaporation - Evaporation spectrum - - """ - # Read nuclear temperature -- since units are MeV, convert to eV - theta = Tabulated1D.from_ace(ace, idx) - theta.y *= EV_PER_MEV - - # Restriction energy - nr = int(ace.xss[idx]) - ne = int(ace.xss[idx + 1 + 2*nr]) - u = ace.xss[idx + 2 + 2*nr + 2*ne]*EV_PER_MEV - - return cls(theta, u) - - @classmethod - def from_endf(cls, file_obj, params): - """Generate evaporation spectrum from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.Evaporation - Evaporation spectrum - - """ - u = params[0] - params, theta = get_tab1_record(file_obj) - return cls(theta, u) - - -class WattEnergy(EnergyDistribution): - r"""Energy-dependent Watt spectrum represented as - - .. math:: - f(E \rightarrow E') = \frac{e^{-E'/a}}{I} \sinh \left ( \sqrt{bE'} - \right ) - - Parameters - ---------- - a, b : openmc.data.Tabulated1D - Energy-dependent parameters tabulated as function of incident neutron - energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - Attributes - ---------- - a, b : openmc.data.Tabulated1D - Energy-dependent parameters tabulated as function of incident neutron - energy - u : float - Constant introduced to define the proper upper limit for the final - particle energy such that :math:`0 \le E' \le E - U` - - """ - - def __init__(self, a, b, u): - super().__init__() - self.a = a - self.b = b - self.u = u - - @property - def a(self): - return self._a - - @property - def b(self): - return self._b - - @property - def u(self): - return self._u - - @a.setter - def a(self, a): - cv.check_type('Watt a', a, Tabulated1D) - self._a = a - - @b.setter - def b(self, b): - cv.check_type('Watt b', b, Tabulated1D) - self._b = b - - @u.setter - def u(self, u): - cv.check_type('Watt restriction energy', u, Real) - self._u = u - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('watt') - group.attrs['u'] = self.u - self.a.to_hdf5(group, 'a') - self.b.to_hdf5(group, 'b') - - @classmethod - def from_hdf5(cls, group): - """Generate Watt fission spectrum from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.WattEnergy - Watt fission spectrum - - """ - a = Tabulated1D.from_hdf5(group['a']) - b = Tabulated1D.from_hdf5(group['b']) - u = group.attrs['u'] - return cls(a, b, u) - - @classmethod - def from_ace(cls, ace, idx): - """Create a Watt fission spectrum from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - - Returns - ------- - openmc.data.WattEnergy - Watt fission spectrum - - """ - # Energy-dependent a parameter -- units are MeV, convert to eV - a = Tabulated1D.from_ace(ace, idx) - a.y *= EV_PER_MEV - - # Advance index - nr = int(ace.xss[idx]) - ne = int(ace.xss[idx + 1 + 2*nr]) - idx += 2 + 2*nr + 2*ne - - # Energy-dependent b parameter -- units are MeV^-1 - b = Tabulated1D.from_ace(ace, idx) - b.y /= EV_PER_MEV - - # Advance index - nr = int(ace.xss[idx]) - ne = int(ace.xss[idx + 1 + 2*nr]) - idx += 2 + 2*nr + 2*ne - - # Restriction energy - u = ace.xss[idx]*EV_PER_MEV - - return cls(a, b, u) - - @classmethod - def from_endf(cls, file_obj, params): - """Generate Watt fission spectrum from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.WattEnergy - Watt fission spectrum - - """ - u = params[0] - params, a = get_tab1_record(file_obj) - params, b = get_tab1_record(file_obj) - return cls(a, b, u) - - -class MadlandNix(EnergyDistribution): - r"""Energy-dependent fission neutron spectrum (Madland and Nix) given in - ENDF MF=5, LF=12 represented as - - .. math:: - f(E \rightarrow E') = \frac{1}{2} [ g(E', E_F(L)) + g(E', E_F(H))] - - where - - .. math:: - g(E',E_F) = \frac{1}{3\sqrt{E_F T_M}} \left [ u_2^{3/2} E_1 (u_2) - - u_1^{3/2} E_1 (u_1) + \gamma \left ( \frac{3}{2}, u_2 \right ) - \gamma - \left ( \frac{3}{2}, u_1 \right ) \right ] \\ u_1 = \left ( \sqrt{E'} - - \sqrt{E_F} \right )^2 / T_M \\ u_2 = \left ( \sqrt{E'} + \sqrt{E_F} - \right )^2 / T_M. - - Parameters - ---------- - efl, efh : float - Constants which represent the average kinetic energy per nucleon of the - fission fragment (efl = light, efh = heavy) - tm : openmc.data.Tabulated1D - Parameter tabulated as a function of incident neutron energy - - Attributes - ---------- - efl, efh : float - Constants which represent the average kinetic energy per nucleon of the - fission fragment (efl = light, efh = heavy) - tm : openmc.data.Tabulated1D - Parameter tabulated as a function of incident neutron energy - - """ - - def __init__(self, efl, efh, tm): - super().__init__() - self.efl = efl - self.efh = efh - self.tm = tm - - @property - def efl(self): - return self._efl - - @property - def efh(self): - return self._efh - - @property - def tm(self): - return self._tm - - @efl.setter - def efl(self, efl): - name = 'Madland-Nix light fragment energy' - cv.check_type(name, efl, Real) - cv.check_greater_than(name, efl, 0.) - self._efl = efl - - @efh.setter - def efh(self, efh): - name = 'Madland-Nix heavy fragment energy' - cv.check_type(name, efh, Real) - cv.check_greater_than(name, efh, 0.) - self._efh = efh - - @tm.setter - def tm(self, tm): - cv.check_type('Madland-Nix maximum temperature', tm, Tabulated1D) - self._tm = tm - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('madland-nix') - group.attrs['efl'] = self.efl - group.attrs['efh'] = self.efh - self.tm.to_hdf5(group) - - @classmethod - def from_hdf5(cls, group): - """Generate Madland-Nix fission spectrum from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.MadlandNix - Madland-Nix fission spectrum - - """ - efl = group.attrs['efl'] - efh = group.attrs['efh'] - tm = Tabulated1D.from_hdf5(group['tm']) - return cls(efl, efh, tm) - - @classmethod - def from_endf(cls, file_obj, params): - """Generate Madland-Nix fission spectrum from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for an energy - distribution. - params : list - List of parameters at the start of the energy distribution that - includes the LF value indicating what type of energy distribution is - present. - - Returns - ------- - openmc.data.MadlandNix - Madland-Nix fission spectrum - - """ - params, tm = get_tab1_record(file_obj) - efl, efh = params[0:2] - return cls(efl, efh, tm) - - - -class DiscretePhoton(EnergyDistribution): - """Discrete photon energy distribution - - Parameters - ---------- - primary_flag : int - Indicator of whether the photon is a primary or non-primary photon. - energy : float - Photon energy (if lp==0 or lp==1) or binding energy (if lp==2). - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide responsible for the emitted - particle - - Attributes - ---------- - primary_flag : int - Indicator of whether the photon is a primary or non-primary photon. - energy : float - Photon energy (if lp==0 or lp==1) or binding energy (if lp==2). - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide responsible for the emitted - particle - - """ - - def __init__(self, primary_flag, energy, atomic_weight_ratio): - super().__init__() - self.primary_flag = primary_flag - self.energy = energy - self.atomic_weight_ratio = atomic_weight_ratio - - @property - def primary_flag(self): - return self._primary_flag - - @property - def energy(self): - return self._energy - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @primary_flag.setter - def primary_flag(self, primary_flag): - cv.check_type('discrete photon primary_flag', primary_flag, Integral) - self._primary_flag = primary_flag - - @energy.setter - def energy(self, energy): - cv.check_type('discrete photon energy', energy, Real) - self._energy = energy - - @atomic_weight_ratio.setter - def atomic_weight_ratio(self, atomic_weight_ratio): - cv.check_type('atomic weight ratio', atomic_weight_ratio, Real) - self._atomic_weight_ratio = atomic_weight_ratio - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('discrete_photon') - group.attrs['primary_flag'] = self.primary_flag - group.attrs['energy'] = self.energy - group.attrs['atomic_weight_ratio'] = self.atomic_weight_ratio - - @classmethod - def from_hdf5(cls, group): - """Generate discrete photon energy distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.DiscretePhoton - Discrete photon energy distribution - - """ - primary_flag = group.attrs['primary_flag'] - energy = group.attrs['energy'] - awr = group.attrs['atomic_weight_ratio'] - return cls(primary_flag, energy, awr) - - @classmethod - def from_ace(cls, ace, idx): - """Generate discrete photon energy distribution from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - - Returns - ------- - openmc.data.DiscretePhoton - Discrete photon energy distribution - - """ - primary_flag = int(ace.xss[idx]) - energy = ace.xss[idx + 1]*EV_PER_MEV - return cls(primary_flag, energy, ace.atomic_weight_ratio) - - -class LevelInelastic(EnergyDistribution): - r"""Level inelastic scattering - - Parameters - ---------- - threshold : float - Energy threshold in the laboratory system, :math:`(A + 1)/A * |Q|` - mass_ratio : float - :math:`(A/(A + 1))^2` - - Attributes - ---------- - threshold : float - Energy threshold in the laboratory system, :math:`(A + 1)/A * |Q|` - mass_ratio : float - :math:`(A/(A + 1))^2` - - """ - - def __init__(self, threshold, mass_ratio): - super().__init__() - self.threshold = threshold - self.mass_ratio = mass_ratio - - @property - def threshold(self): - return self._threshold - - @property - def mass_ratio(self): - return self._mass_ratio - - @threshold.setter - def threshold(self, threshold): - cv.check_type('level inelastic threhsold', threshold, Real) - self._threshold = threshold - - @mass_ratio.setter - def mass_ratio(self, mass_ratio): - cv.check_type('level inelastic mass ratio', mass_ratio, Real) - self._mass_ratio = mass_ratio - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('level') - group.attrs['threshold'] = self.threshold - group.attrs['mass_ratio'] = self.mass_ratio - - @classmethod - def from_hdf5(cls, group): - """Generate level inelastic distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.LevelInelastic - Level inelastic scattering distribution - - """ - threshold = group.attrs['threshold'] - mass_ratio = group.attrs['mass_ratio'] - return cls(threshold, mass_ratio) - - @classmethod - def from_ace(cls, ace, idx): - """Generate level inelastic distribution from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - - Returns - ------- - openmc.data.LevelInelastic - Level inelastic scattering distribution - - """ - threshold = ace.xss[idx]*EV_PER_MEV - mass_ratio = ace.xss[idx + 1] - return cls(threshold, mass_ratio) - - -class ContinuousTabular(EnergyDistribution): - """Continuous tabular distribution - - Parameters - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - - Attributes - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - - """ - - def __init__(self, breakpoints, interpolation, energy, energy_out): - super().__init__() - self.breakpoints = breakpoints - self.interpolation = interpolation - self.energy = energy - self.energy_out = energy_out - - @property - def breakpoints(self): - return self._breakpoints - - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('continuous tabular breakpoints', breakpoints, - Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('continuous tabular interpolation', interpolation, - Iterable, Integral) - self._interpolation = interpolation - - @energy.setter - def energy(self, energy): - cv.check_type('continuous tabular incoming energy', energy, - Iterable, Real) - self._energy = energy - - @energy_out.setter - def energy_out(self, energy_out): - cv.check_type('continuous tabular outgoing energy', energy_out, - Iterable, Univariate) - self._energy_out = energy_out - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['type'] = np.string_('continuous') - - dset = group.create_dataset('energy', data=self.energy) - dset.attrs['interpolation'] = np.vstack((self.breakpoints, - self.interpolation)) - - # Determine total number of (E,p) pairs and create array - n_pairs = sum(len(d) for d in self.energy_out) - pairs = np.empty((3, n_pairs)) - - # Create array for offsets - offsets = np.empty(len(self.energy_out), dtype=int) - interpolation = np.empty(len(self.energy_out), dtype=int) - n_discrete_lines = np.empty(len(self.energy_out), dtype=int) - j = 0 - - # Populate offsets and pairs array - for i, eout in enumerate(self.energy_out): - n = len(eout) - offsets[i] = j - - if isinstance(eout, Mixture): - discrete, continuous = eout.distribution - n_discrete_lines[i] = m = len(discrete) - interpolation[i] = 1 if continuous.interpolation == 'histogram' else 2 - pairs[0, j:j+m] = discrete.x - pairs[1, j:j+m] = discrete.p - pairs[2, j:j+m] = discrete.c - pairs[0, j+m:j+n] = continuous.x - pairs[1, j+m:j+n] = continuous.p - pairs[2, j+m:j+n] = continuous.c - else: - if isinstance(eout, Tabular): - n_discrete_lines[i] = 0 - interpolation[i] = 1 if eout.interpolation == 'histogram' else 2 - elif isinstance(eout, Discrete): - n_discrete_lines[i] = n - interpolation[i] = 1 - pairs[0, j:j+n] = eout.x - pairs[1, j:j+n] = eout.p - pairs[2, j:j+n] = eout.c - j += n - - # Create dataset for distributions - dset = group.create_dataset('distribution', data=pairs) - - # Write interpolation as attribute - dset.attrs['offsets'] = offsets - dset.attrs['interpolation'] = interpolation - dset.attrs['n_discrete_lines'] = n_discrete_lines - - @classmethod - def from_hdf5(cls, group): - """Generate continuous tabular distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.ContinuousTabular - Continuous tabular energy distribution - - """ - interp_data = group['energy'].attrs['interpolation'] - energy_breakpoints = interp_data[0, :] - energy_interpolation = interp_data[1, :] - energy = group['energy'][()] - - data = group['distribution'] - offsets = data.attrs['offsets'] - interpolation = data.attrs['interpolation'] - n_discrete_lines = data.attrs['n_discrete_lines'] - - energy_out = [] - n_energy = len(energy) - for i in range(n_energy): - # Determine length of outgoing energy distribution and number of - # discrete lines - j = offsets[i] - if i < n_energy - 1: - n = offsets[i+1] - j - else: - n = data.shape[1] - j - m = n_discrete_lines[i] - - # Create discrete distribution if lines are present - if m > 0: - eout_discrete = Discrete(data[0, j:j+m], data[1, j:j+m]) - eout_discrete.c = data[2, j:j+m] - p_discrete = eout_discrete.c[-1] - - # Create continuous distribution - if m < n: - interp = INTERPOLATION_SCHEME[interpolation[i]] - eout_continuous = Tabular(data[0, j+m:j+n], data[1, j+m:j+n], interp) - eout_continuous.c = data[2, j+m:j+n] - - # If both continuous and discrete are present, create a mixture - # distribution - if m == 0: - eout_i = eout_continuous - elif m == n: - eout_i = eout_discrete - else: - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - energy_out.append(eout_i) - - return cls(energy_breakpoints, energy_interpolation, - energy, energy_out) - - @classmethod - def from_ace(cls, ace, idx, ldis): - """Generate continuous tabular energy distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - idx : int - Index in XSS array of the start of the energy distribution data - (LDIS + LOCC - 1) - ldis : int - Index in XSS array of the start of the energy distribution block - (e.g. JXS[11]) - - Returns - ------- - openmc.data.ContinuousTabular - Continuous tabular energy distribution - - """ - # Read number of interpolation regions and incoming energies - n_regions = int(ace.xss[idx]) - n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) - - # Get interpolation information - idx += 1 - if n_regions > 0: - breakpoints = ace.xss[idx:idx + n_regions].astype(int) - interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) - else: - breakpoints = np.array([n_energy_in]) - interpolation = np.array([2]) - - # Incoming energies at which distributions exist - idx += 2*n_regions + 1 - energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV - - # Location of distributions - idx += n_energy_in - loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) - - # Initialize variables - energy_out = [] - - # Read each outgoing energy distribution - for i in range(n_energy_in): - idx = ldis + loc_dist[i] - 1 - - # intt = interpolation scheme (1=hist, 2=lin-lin) - INTTp = int(ace.xss[idx]) - intt = INTTp % 10 - n_discrete_lines = (INTTp - intt)//10 - if intt not in (1, 2): - warn("Interpolation scheme for continuous tabular distribution " - "is not histogram or linear-linear.") - intt = 2 - - n_energy_out = int(ace.xss[idx + 1]) - data = ace.xss[idx + 2:idx + 2 + 3*n_energy_out].copy() - data.shape = (3, n_energy_out) - data[0,:] *= EV_PER_MEV - - # Create continuous distribution - eout_continuous = Tabular(data[0][n_discrete_lines:], - data[1][n_discrete_lines:]/EV_PER_MEV, - INTERPOLATION_SCHEME[intt]) - eout_continuous.c = data[2][n_discrete_lines:] - - # If discrete lines are present, create a mixture distribution - if n_discrete_lines > 0: - eout_discrete = Discrete(data[0][:n_discrete_lines], - data[1][:n_discrete_lines]) - eout_discrete.c = data[2][:n_discrete_lines] - if n_discrete_lines == n_energy_out: - eout_i = eout_discrete - else: - p_discrete = min(sum(eout_discrete.p), 1.0) - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - else: - eout_i = eout_continuous - - energy_out.append(eout_i) - - return cls(breakpoints, interpolation, energy, energy_out) diff --git a/openmc/data/fission_energy.py b/openmc/data/fission_energy.py deleted file mode 100644 index 95915650b..000000000 --- a/openmc/data/fission_energy.py +++ /dev/null @@ -1,380 +0,0 @@ -from collections.abc import Callable -from copy import deepcopy -from io import StringIO -import sys - -import h5py -import numpy as np - -from .data import EV_PER_MEV -from .endf import get_cont_record, get_list_record, get_tab1_record, Evaluation -from .function import Function1D, Tabulated1D, Polynomial, sum_functions -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin - - -_NAMES = ( - 'fragments', 'prompt_neutrons', 'delayed_neutrons', - 'prompt_photons', 'delayed_photons', 'betas', - 'neutrinos', 'recoverable', 'total' -) - - -class FissionEnergyRelease(EqualityMixin): - """Energy relased by fission reactions. - - Energy is carried away from fission reactions by many different particles. - The attributes of this class specify how much energy is released in the form - of fission fragments, neutrons, photons, etc. Each component is also (in - general) a function of the incident neutron energy. - - Following a fission reaction, most of the energy release is carried by the - daughter nuclei fragments. These fragments accelerate apart from the - Coulomb force on the time scale of ~10^-20 s [1]. Those fragments emit - prompt neutrons between ~10^-18 and ~10^-13 s after scission (although some - prompt neutrons may come directly from the scission point) [1]. Prompt - photons follow with a time scale of ~10^-14 to ~10^-7 s [1]. The fission - products then emit delayed neutrons with half lives between 0.1 and 100 s. - The remaining fission energy comes from beta decays of the fission products - which release beta particles, photons, and neutrinos (that escape the - reactor and do not produce usable heat). - - Use the class methods to instantiate this class from an HDF5 or ENDF - dataset. The :meth:`FissionEnergyRelease.from_hdf5` method builds this - class from the usual OpenMC HDF5 data files. - :meth:`FissionEnergyRelease.from_endf` uses ENDF-formatted data. - - References - ---------- - [1] D. G. Madland, "Total prompt energy release in the neutron-induced - fission of ^235U, ^238U, and ^239Pu", Nuclear Physics A 772:113--137 (2006). - - - Attributes - ---------- - fragments : Callable - Function that accepts incident neutron energy value(s) and returns the - kinetic energy of the fission daughter nuclides (after prompt neutron - emission). - prompt_neutrons : Callable - Function of energy that returns the kinetic energy of prompt fission - neutrons. - delayed_neutrons : Callable - Function of energy that returns the kinetic energy of delayed neutrons - emitted from fission products. - prompt_photons : Callable - Function of energy that returns the kinetic energy of prompt fission - photons. - delayed_photons : Callable - Function of energy that returns the kinetic energy of delayed photons. - betas : Callable - Function of energy that returns the kinetic energy of delayed beta - particles. - neutrinos : Callable - Function of energy that returns the kinetic energy of neutrinos. - recoverable : Callable - Function of energy that returns the kinetic energy of all products that - can be absorbed in the reactor (all of the energy except for the - neutrinos). - total : Callable - Function of energy that returns the kinetic energy of all products. - q_prompt : Callable - Function of energy that returns the prompt fission Q-value (fragments + - prompt neutrons + prompt photons - incident neutron energy). - q_recoverable : Callable - Function of energy that returns the recoverable fission Q-value - (total release - neutrinos - incident neutron energy). This value is - sometimes referred to as the pseudo-Q-value. - q_total : Callable - Function of energy that returns the total fission Q-value (total release - - incident neutron energy). - - """ - def __init__(self, fragments, prompt_neutrons, delayed_neutrons, - prompt_photons, delayed_photons, betas, neutrinos): - self.fragments = fragments - self.prompt_neutrons = prompt_neutrons - self.delayed_neutrons = delayed_neutrons - self.prompt_photons = prompt_photons - self.delayed_photons = delayed_photons - self.betas = betas - self.neutrinos = neutrinos - - @property - def fragments(self): - return self._fragments - - @property - def prompt_neutrons(self): - return self._prompt_neutrons - - @property - def delayed_neutrons(self): - return self._delayed_neutrons - - @property - def prompt_photons(self): - return self._prompt_photons - - @property - def delayed_photons(self): - return self._delayed_photons - - @property - def betas(self): - return self._betas - - @property - def neutrinos(self): - return self._neutrinos - - @property - def recoverable(self): - components = ['fragments', 'prompt_neutrons', 'delayed_neutrons', - 'prompt_photons', 'delayed_photons', 'betas'] - return sum_functions(getattr(self, c) for c in components) - - @property - def total(self): - components = ['fragments', 'prompt_neutrons', 'delayed_neutrons', - 'prompt_photons', 'delayed_photons', 'betas', - 'neutrinos'] - return sum_functions(getattr(self, c) for c in components) - - @property - def q_prompt(self): - # Use a polynomial to subtract incident energy. - funcs = [self.fragments, self.prompt_neutrons, self.prompt_photons, - Polynomial((0.0, -1.0))] - return sum_functions(funcs) - - @property - def q_recoverable(self): - # Use a polynomial to subtract incident energy. - return sum_functions([self.recoverable, Polynomial((0.0, -1.0))]) - - @property - def q_total(self): - # Use a polynomial to subtract incident energy. - return sum_functions([self.total, Polynomial((0.0, -1.0))]) - - @fragments.setter - def fragments(self, energy_release): - cv.check_type('fragments', energy_release, Callable) - self._fragments = energy_release - - @prompt_neutrons.setter - def prompt_neutrons(self, energy_release): - cv.check_type('prompt_neutrons', energy_release, Callable) - self._prompt_neutrons = energy_release - - @delayed_neutrons.setter - def delayed_neutrons(self, energy_release): - cv.check_type('delayed_neutrons', energy_release, Callable) - self._delayed_neutrons = energy_release - - @prompt_photons.setter - def prompt_photons(self, energy_release): - cv.check_type('prompt_photons', energy_release, Callable) - self._prompt_photons = energy_release - - @delayed_photons.setter - def delayed_photons(self, energy_release): - cv.check_type('delayed_photons', energy_release, Callable) - self._delayed_photons = energy_release - - @betas.setter - def betas(self, energy_release): - cv.check_type('betas', energy_release, Callable) - self._betas = energy_release - - @neutrinos.setter - def neutrinos(self, energy_release): - cv.check_type('neutrinos', energy_release, Callable) - self._neutrinos = energy_release - - @classmethod - def from_endf(cls, ev, incident_neutron): - """Generate fission energy release data from an ENDF file. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - incident_neutron : openmc.data.IncidentNeutron - Corresponding incident neutron dataset - - Returns - ------- - openmc.data.FissionEnergyRelease - Fission energy release data - - """ - cv.check_type('evaluation', ev, Evaluation) - - # Check to make sure this ENDF file matches the expected isomer. - if ev.target['atomic_number'] != incident_neutron.atomic_number: - raise ValueError('The atomic number of the ENDF evaluation does ' - 'not match the given IncidentNeutron.') - if ev.target['mass_number'] != incident_neutron.mass_number: - raise ValueError('The atomic mass of the ENDF evaluation does ' - 'not match the given IncidentNeutron.') - if ev.target['isomeric_state'] != incident_neutron.metastable: - raise ValueError('The metastable state of the ENDF evaluation ' - 'does not match the given IncidentNeutron.') - if not ev.target['fissionable']: - raise ValueError('The ENDF evaluation is not fissionable.') - - if (1, 458) not in ev.section: - raise ValueError('ENDF evaluation does not have MF=1, MT=458.') - - file_obj = StringIO(ev.section[1, 458]) - - # Read first record and check whether any components appear as - # tabulated functions - items = get_cont_record(file_obj) - lfc = items[3] - nfc = items[5] - - # Parse the ENDF LIST into an array. - items, data = get_list_record(file_obj) - npoly = items[3] - - # Associate each set of values and uncertainties with its label. - functions = {} - for i, name in enumerate(_NAMES): - coeffs = data[2*i::18] - - # Ignore recoverable and total since we recalculate those directly - if name in ('recoverable', 'total'): - continue - - # In ENDF/B-VII.1, data for 2nd-order coefficients were mistakenly - # not converted from MeV to eV. Check for this error and fix it if - # present. - if npoly == 2: # Only check 2nd-order data. - # If a 5 MeV neutron causes a change of more than 100 MeV, we - # know something is wrong. - second_order = coeffs[2] - if abs(second_order) * (5e6)**2 > 1e8: - # If we found the error, reduce 2nd-order coeff by 10**6. - coeffs[2] /= EV_PER_MEV - - # If multiple coefficients were given, we can create the polynomial - # and move on to the next component - if npoly > 0: - functions[name] = Polynomial(coeffs) - continue - - # If a single coefficient was given, we need to use the Sher-Beck - # formula for energy dependence - zeroth_order = coeffs[0] - if name in ('delayed_photons', 'betas'): - func = Polynomial((zeroth_order, -0.075)) - elif name == 'neutrinos': - func = Polynomial((zeroth_order, -0.105)) - elif name == 'prompt_neutrons': - # Prompt neutrons require nu-data. It is not clear from - # ENDF-102 whether prompt or total nu value should be used, but - # the delayed neutron fraction is so small that the difference - # is negligible. MT=18 (n, fission) might not be available so - # try MT=19 (n, f) as well. - if 18 in incident_neutron and not incident_neutron[18].redundant: - nu = [p.yield_ for p in incident_neutron[18].products - if p.particle == 'neutron' - and p.emission_mode in ('prompt', 'total')] - elif 19 in incident_neutron: - nu = [p.yield_ for p in incident_neutron[19].products - if p.particle == 'neutron' - and p.emission_mode in ('prompt', 'total')] - else: - raise ValueError('IncidentNeutron data has no fission ' - 'reaction.') - if len(nu) == 0: - raise ValueError( - 'Nu data is needed to compute fission energy ' - 'release with the Sher-Beck format.' - ) - if len(nu) > 1: - raise ValueError('Ambiguous prompt/total nu value.') - - nu = nu[0] - if isinstance(nu, Tabulated1D): - # Evaluate Sher-Beck polynomial form at each tabulated value - func = deepcopy(nu) - func.y = (zeroth_order + 1.307*nu.x - 8.07e6*(nu.y - nu.y[0])) - elif isinstance(nu, Polynomial): - # Combine polynomials - if len(nu) == 1: - func = Polynomial([zeroth_order, 1.307]) - else: - func = Polynomial( - [zeroth_order, 1.307 - 8.07e6*nu.coef[1]] - + [-8.07e6*c for c in nu.coef[2:]]) - else: - func = Polynomial(coeffs) - - functions[name] = func - - # Check for tabulated data - if lfc == 1: - for _ in range(nfc): - # Get tabulated function - items, eifc = get_tab1_record(file_obj) - - # Determine which component it is - ifc = items[3] - name = _NAMES[ifc - 1] - - # Replace value in dictionary - functions[name] = eifc - - # Build the object - return cls(**functions) - - @classmethod - def from_hdf5(cls, group): - """Generate fission energy release data from an HDF5 group. - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.FissionEnergyRelease - Fission energy release data - - """ - - fragments = Function1D.from_hdf5(group['fragments']) - prompt_neutrons = Function1D.from_hdf5(group['prompt_neutrons']) - delayed_neutrons = Function1D.from_hdf5(group['delayed_neutrons']) - prompt_photons = Function1D.from_hdf5(group['prompt_photons']) - delayed_photons = Function1D.from_hdf5(group['delayed_photons']) - betas = Function1D.from_hdf5(group['betas']) - neutrinos = Function1D.from_hdf5(group['neutrinos']) - - return cls(fragments, prompt_neutrons, delayed_neutrons, prompt_photons, - delayed_photons, betas, neutrinos) - - def to_hdf5(self, group): - """Write energy release data to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - self.fragments.to_hdf5(group, 'fragments') - self.prompt_neutrons.to_hdf5(group, 'prompt_neutrons') - self.delayed_neutrons.to_hdf5(group, 'delayed_neutrons') - self.prompt_photons.to_hdf5(group, 'prompt_photons') - self.delayed_photons.to_hdf5(group, 'delayed_photons') - self.betas.to_hdf5(group, 'betas') - self.neutrinos.to_hdf5(group, 'neutrinos') - self.q_prompt.to_hdf5(group, 'q_prompt') - self.q_recoverable.to_hdf5(group, 'q_recoverable') diff --git a/openmc/data/function.py b/openmc/data/function.py deleted file mode 100644 index 9175e5e3b..000000000 --- a/openmc/data/function.py +++ /dev/null @@ -1,716 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections.abc import Iterable, Callable -from functools import reduce -from itertools import zip_longest -from numbers import Real, Integral -from math import exp, log - -import numpy as np - -import openmc.data -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from .data import EV_PER_MEV - -INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log', - 4: 'log-linear', 5: 'log-log'} - - -def sum_functions(funcs): - """Add tabulated/polynomials functions together - - Parameters - ---------- - funcs : list of Function1D - Functions to add - - Returns - ------- - Function1D - Sum of polynomial/tabulated functions - - """ - # Copy so we can iterate multiple times - funcs = list(funcs) - - # Get x values for all tabulated components - xs = [] - for f in funcs: - if isinstance(f, Tabulated1D): - xs.append(f.x) - if not np.all(f.interpolation == 2): - raise ValueError('Only linear-linear tabulated functions ' - 'can be combined') - - if xs: - # Take the union of all energies (sorted) - x = reduce(np.union1d, xs) - - # Evaluate each function and add together - y = sum(f(x) for f in funcs) - return Tabulated1D(x, y) - else: - # If no tabulated functions are present, we need to combine the - # polynomials by adding their coefficients - coeffs = [sum(x) for x in zip_longest(*funcs, fillvalue=0.0)] - return Polynomial(coeffs) - - -class Function1D(EqualityMixin, metaclass=ABCMeta): - """A function of one independent variable with HDF5 support.""" - @abstractmethod - def __call__(self): pass - - @abstractmethod - def to_hdf5(self, group, name='xy'): - """Write function to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : str - Name of the dataset to create - - """ - pass - - @classmethod - def from_hdf5(cls, dataset): - """Generate function from an HDF5 dataset - - Parameters - ---------- - dataset : h5py.Dataset - Dataset to read from - - Returns - ------- - openmc.data.Function1D - Function read from dataset - - """ - for subclass in cls.__subclasses__(): - if dataset.attrs['type'].decode() == subclass.__name__: - return subclass.from_hdf5(dataset) - raise ValueError("Unrecognized Function1D class: '" - + dataset.attrs['type'].decode() + "'") - - -class Tabulated1D(Function1D): - """A one-dimensional tabulated function. - - This class mirrors the TAB1 type from the ENDF-6 format. A tabulated - function is specified by tabulated (x,y) pairs along with interpolation - rules that determine the values between tabulated pairs. - - Once an object has been created, it can be used as though it were an actual - function, e.g.: - - >>> f = Tabulated1D([0, 10], [4, 5]) - >>> [f(xi) for xi in numpy.linspace(0, 10, 5)] - [4.0, 4.25, 4.5, 4.75, 5.0] - - Parameters - ---------- - x : Iterable of float - Independent variable - y : Iterable of float - Dependent variable - breakpoints : Iterable of int - Breakpoints for interpolation regions - interpolation : Iterable of int - Interpolation scheme identification number, e.g., 3 means y is linear in - ln(x). - - Attributes - ---------- - x : Iterable of float - Independent variable - y : Iterable of float - Dependent variable - breakpoints : Iterable of int - Breakpoints for interpolation regions - interpolation : Iterable of int - Interpolation scheme identification number, e.g., 3 means y is linear in - ln(x). - n_regions : int - Number of interpolation regions - n_pairs : int - Number of tabulated (x,y) pairs - - """ - - def __init__(self, x, y, breakpoints=None, interpolation=None): - if breakpoints is None or interpolation is None: - # Single linear-linear interpolation region by default - self.breakpoints = np.array([len(x)]) - self.interpolation = np.array([2]) - else: - self.breakpoints = np.asarray(breakpoints, dtype=int) - self.interpolation = np.asarray(interpolation, dtype=int) - - self.x = np.asarray(x) - self.y = np.asarray(y) - - def __call__(self, x): - # Check if input is scalar - if not isinstance(x, Iterable): - return self._interpolate_scalar(x) - - x = np.array(x) - - # Create output array - y = np.zeros_like(x) - - # Get indices for interpolation - idx = np.searchsorted(self.x, x, side='right') - 1 - - # Loop over interpolation regions - for k in range(len(self.breakpoints)): - # Get indices for the begining and ending of this region - i_begin = self.breakpoints[k-1] - 1 if k > 0 else 0 - i_end = self.breakpoints[k] - 1 - - # Figure out which idx values lie within this region - contained = (idx >= i_begin) & (idx < i_end) - - xk = x[contained] # x values in this region - xi = self.x[idx[contained]] # low edge of corresponding bins - xi1 = self.x[idx[contained] + 1] # high edge of corresponding bins - yi = self.y[idx[contained]] - yi1 = self.y[idx[contained] + 1] - - if self.interpolation[k] == 1: - # Histogram - y[contained] = yi - - elif self.interpolation[k] == 2: - # Linear-linear - y[contained] = yi + (xk - xi)/(xi1 - xi)*(yi1 - yi) - - elif self.interpolation[k] == 3: - # Linear-log - y[contained] = yi + np.log(xk/xi)/np.log(xi1/xi)*(yi1 - yi) - - elif self.interpolation[k] == 4: - # Log-linear - y[contained] = yi*np.exp((xk - xi)/(xi1 - xi)*np.log(yi1/yi)) - - elif self.interpolation[k] == 5: - # Log-log - y[contained] = (yi*np.exp(np.log(xk/xi)/np.log(xi1/xi) - *np.log(yi1/yi))) - - # In some cases, x values might be outside the tabulated region due only - # to precision, so we check if they're close and set them equal if so. - y[np.isclose(x, self.x[0], atol=1e-14)] = self.y[0] - y[np.isclose(x, self.x[-1], atol=1e-14)] = self.y[-1] - - return y - - def _interpolate_scalar(self, x): - if x <= self._x[0]: - return self._y[0] - elif x >= self._x[-1]: - return self._y[-1] - - # Get the index for interpolation - idx = np.searchsorted(self._x, x, side='right') - 1 - - # Loop over interpolation regions - for b, p in zip(self.breakpoints, self.interpolation): - if idx < b - 1: - break - - xi = self._x[idx] # low edge of the corresponding bin - xi1 = self._x[idx + 1] # high edge of the corresponding bin - yi = self._y[idx] - yi1 = self._y[idx + 1] - - if p == 1: - # Histogram - return yi - - elif p == 2: - # Linear-linear - return yi + (x - xi)/(xi1 - xi)*(yi1 - yi) - - elif p == 3: - # Linear-log - return yi + log(x/xi)/log(xi1/xi)*(yi1 - yi) - - elif p == 4: - # Log-linear - return yi*exp((x - xi)/(xi1 - xi)*log(yi1/yi)) - - elif p == 5: - # Log-log - return yi*exp(log(x/xi)/log(xi1/xi)*log(yi1/yi)) - - def __len__(self): - return len(self.x) - - @property - def x(self): - return self._x - - @property - def y(self): - return self._y - - @property - def breakpoints(self): - return self._breakpoints - - @property - def interpolation(self): - return self._interpolation - - @property - def n_pairs(self): - return len(self.x) - - @property - def n_regions(self): - return len(self.breakpoints) - - @x.setter - def x(self, x): - cv.check_type('x values', x, Iterable, Real) - self._x = x - - @y.setter - def y(self, y): - cv.check_type('y values', y, Iterable, Real) - self._y = y - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('breakpoints', breakpoints, Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('interpolation', interpolation, Iterable, Integral) - self._interpolation = interpolation - - def integral(self): - """Integral of the tabulated function over its tabulated range. - - Returns - ------- - numpy.ndarray - Array of same length as the tabulated data that represents partial - integrals from the bottom of the range to each tabulated point. - - """ - - # Create output array - partial_sum = np.zeros(len(self.x) - 1) - - i_low = 0 - for k in range(len(self.breakpoints)): - # Determine which x values are within this interpolation range - i_high = self.breakpoints[k] - 1 - - # Get x values and bounding (x,y) pairs - x0 = self.x[i_low:i_high] - x1 = self.x[i_low + 1:i_high + 1] - y0 = self.y[i_low:i_high] - y1 = self.y[i_low + 1:i_high + 1] - - if self.interpolation[k] == 1: - # Histogram - partial_sum[i_low:i_high] = y0*(x1 - x0) - - elif self.interpolation[k] == 2: - # Linear-linear - m = (y1 - y0)/(x1 - x0) - partial_sum[i_low:i_high] = (y0 - m*x0)*(x1 - x0) + \ - m*(x1**2 - x0**2)/2 - - elif self.interpolation[k] == 3: - # Linear-log - logx = np.log(x1/x0) - m = (y1 - y0)/logx - partial_sum[i_low:i_high] = y0 + m*(x1*(logx - 1) + x0) - - elif self.interpolation[k] == 4: - # Log-linear - m = np.log(y1/y0)/(x1 - x0) - partial_sum[i_low:i_high] = y0/m*(np.exp(m*(x1 - x0)) - 1) - - elif self.interpolation[k] == 5: - # Log-log - m = np.log(y1/y0)/np.log(x1/x0) - partial_sum[i_low:i_high] = y0/((m + 1)*x0**m)*( - x1**(m + 1) - x0**(m + 1)) - - i_low = i_high - - return np.concatenate(([0.], np.cumsum(partial_sum))) - - def to_hdf5(self, group, name='xy'): - """Write tabulated function to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : str - Name of the dataset to create - - """ - dataset = group.create_dataset(name, data=np.vstack( - [self.x, self.y])) - dataset.attrs['type'] = np.string_(type(self).__name__) - dataset.attrs['breakpoints'] = self.breakpoints - dataset.attrs['interpolation'] = self.interpolation - - @classmethod - def from_hdf5(cls, dataset): - """Generate tabulated function from an HDF5 dataset - - Parameters - ---------- - dataset : h5py.Dataset - Dataset to read from - - Returns - ------- - openmc.data.Tabulated1D - Function read from dataset - - """ - if dataset.attrs['type'].decode() != cls.__name__: - raise ValueError("Expected an HDF5 attribute 'type' equal to '" - + cls.__name__ + "'") - - x = dataset[0, :] - y = dataset[1, :] - breakpoints = dataset.attrs['breakpoints'] - interpolation = dataset.attrs['interpolation'] - return cls(x, y, breakpoints, interpolation) - - @classmethod - def from_ace(cls, ace, idx=0, convert_units=True): - """Create a Tabulated1D object from an ACE table. - - Parameters - ---------- - ace : openmc.data.ace.Table - An ACE table - idx : int - Offset to read from in XSS array (default of zero) - convert_units : bool - If the abscissa represents energy, indicate whether to convert MeV - to eV. - - Returns - ------- - openmc.data.Tabulated1D - Tabulated data object - - """ - - # Get number of regions and pairs - n_regions = int(ace.xss[idx]) - n_pairs = int(ace.xss[idx + 1 + 2*n_regions]) - - # Get interpolation information - idx += 1 - if n_regions > 0: - breakpoints = ace.xss[idx:idx + n_regions].astype(int) - interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) - else: - # 0 regions implies linear-linear interpolation by default - breakpoints = np.array([n_pairs]) - interpolation = np.array([2]) - - # Get (x,y) pairs - idx += 2*n_regions + 1 - x = ace.xss[idx:idx + n_pairs].copy() - y = ace.xss[idx + n_pairs:idx + 2*n_pairs].copy() - - if convert_units: - x *= EV_PER_MEV - - return Tabulated1D(x, y, breakpoints, interpolation) - - -class Polynomial(np.polynomial.Polynomial, Function1D): - """A power series class. - - Parameters - ---------- - coef : Iterable of float - Polynomial coefficients in order of increasing degree - - """ - def to_hdf5(self, group, name='xy'): - """Write polynomial function to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : str - Name of the dataset to create - - """ - dataset = group.create_dataset(name, data=self.coef) - dataset.attrs['type'] = np.string_(type(self).__name__) - - @classmethod - def from_hdf5(cls, dataset): - """Generate function from an HDF5 dataset - - Parameters - ---------- - dataset : h5py.Dataset - Dataset to read from - - Returns - ------- - openmc.data.Function1D - Function read from dataset - - """ - if dataset.attrs['type'].decode() != cls.__name__: - raise ValueError("Expected an HDF5 attribute 'type' equal to '" - + cls.__name__ + "'") - return cls(dataset[()]) - - -class Combination(EqualityMixin): - """Combination of multiple functions with a user-defined operator - - This class allows you to create a callable object which represents the - combination of other callable objects by way of a series of user-defined - operators connecting each of the callable objects. - - Parameters - ---------- - functions : Iterable of Callable - Functions to combine according to operations - operations : Iterable of numpy.ufunc - Operations to perform between functions; note that the standard order - of operations will not be followed, but can be simulated by - combinations of Combination objects. The operations parameter must have - a length one less than the number of functions. - - - Attributes - ---------- - functions : Iterable of Callable - Functions to combine according to operations - operations : Iterable of numpy.ufunc - Operations to perform between functions; note that the standard order - of operations will not be followed, but can be simulated by - combinations of Combination objects. The operations parameter must have - a length one less than the number of functions. - - """ - - def __init__(self, functions, operations): - self.functions = functions - self.operations = operations - - def __call__(self, x): - ans = self.functions[0](x) - for i, operation in enumerate(self.operations): - ans = operation(ans, self.functions[i + 1](x)) - return ans - - @property - def functions(self): - return self._functions - - @functions.setter - def functions(self, functions): - cv.check_type('functions', functions, Iterable, Callable) - self._functions = functions - - @property - def operations(self): - return self._operations - - @operations.setter - def operations(self, operations): - cv.check_type('operations', operations, Iterable, np.ufunc) - length = len(self.functions) - 1 - cv.check_length('operations', operations, length, length_max=length) - self._operations = operations - - -class Sum(EqualityMixin): - """Sum of multiple functions. - - This class allows you to create a callable object which represents the sum - of other callable objects. This is used for redundant reactions whereby the - cross section is defined as the sum of other cross sections. - - Parameters - ---------- - functions : Iterable of Callable - Functions which are to be added together - - Attributes - ---------- - functions : Iterable of Callable - Functions which are to be added together - - """ - - def __init__(self, functions): - self.functions = list(functions) - - def __call__(self, x): - return sum(f(x) for f in self.functions) - - @property - def functions(self): - return self._functions - - @functions.setter - def functions(self, functions): - cv.check_type('functions', functions, Iterable, Callable) - self._functions = functions - - -class Regions1D(EqualityMixin): - """Piecewise composition of multiple functions. - - This class allows you to create a callable object which is composed - of multiple other callable objects, each applying to a specific interval - - Parameters - ---------- - functions : Iterable of Callable - Functions which are to be combined in a piecewise fashion - breakpoints : Iterable of float - The values of the dependent variable that define the domain of - each function. The `i`\ th and `(i+1)`\ th values are the limits of the - domain of the `i`\ th function. Values must be monotonically increasing. - - Attributes - ---------- - functions : Iterable of Callable - Functions which are to be combined in a piecewise fashion - breakpoints : Iterable of float - The breakpoints between each function - - """ - - def __init__(self, functions, breakpoints): - self.functions = functions - self.breakpoints = breakpoints - - def __call__(self, x): - i = np.searchsorted(self.breakpoints, x) - if isinstance(x, Iterable): - ans = np.empty_like(x) - for j in range(len(i)): - ans[j] = self.functions[i[j]](x[j]) - return ans - else: - return self.functions[i](x) - - @property - def functions(self): - return self._functions - - @property - def breakpoints(self): - return self._breakpoints - - @functions.setter - def functions(self, functions): - cv.check_type('functions', functions, Iterable, Callable) - self._functions = functions - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_iterable_type('breakpoints', breakpoints, Real) - self._breakpoints = breakpoints - - -class ResonancesWithBackground(EqualityMixin): - """Cross section in resolved resonance region. - - Parameters - ---------- - resonances : openmc.data.Resonances - Resolved resonance parameter data - background : Callable - Background cross section as a function of energy - mt : int - MT value of the reaction - - Attributes - ---------- - resonances : openmc.data.Resonances - Resolved resonance parameter data - background : Callable - Background cross section as a function of energy - mt : int - MT value of the reaction - - """ - - - def __init__(self, resonances, background, mt): - self.resonances = resonances - self.background = background - self.mt = mt - - def __call__(self, x): - # Get background cross section - xs = self.background(x) - - for r in self.resonances: - if not isinstance(r, openmc.data.resonance._RESOLVED): - continue - - if isinstance(x, Iterable): - # Determine which energies are within resolved resonance range - within = (r.energy_min <= x) & (x <= r.energy_max) - - # Get resonance cross sections and add to background - resonant_xs = r.reconstruct(x[within]) - xs[within] += resonant_xs[self.mt] - else: - if r.energy_min <= x <= r.energy_max: - resonant_xs = r.reconstruct(x) - xs += resonant_xs[self.mt] - - return xs - - @property - def background(self): - return self._background - - @property - def mt(self): - return self._mt - - @property - def resonances(self): - return self._resonances - - @background.setter - def background(self, background): - cv.check_type('background cross section', background, Callable) - self._background = background - - @mt.setter - def mt(self, mt): - cv.check_type('MT value', mt, Integral) - self._mt = mt - - @resonances.setter - def resonances(self, resonances): - cv.check_type('resolved resonance parameters', resonances, - openmc.data.Resonances) - self._resonances = resonances diff --git a/openmc/data/grid.py b/openmc/data/grid.py deleted file mode 100644 index e63919ac2..000000000 --- a/openmc/data/grid.py +++ /dev/null @@ -1,114 +0,0 @@ -import numpy as np - - -def linearize(x, f, tolerance=0.001): - """Return a tabulated representation of a function of one variable. - - Parameters - ---------- - x : Iterable of float - Initial x values at which the function should be evaluated - f : Callable - Function of a single variable - tolerance : float - Tolerance on the interpolation error - - Returns - ------- - numpy.ndarray - Tabulated values of the independent variable - numpy.ndarray - Tabulated values of the dependent variable - - """ - # Make sure x is a numpy array - x = np.asarray(x) - - # Initialize output arrays - x_out = [] - y_out = [] - - # Initialize stack - x_stack = [x[0]] - y_stack = [f(x[0])] - - for i in range(x.shape[0] - 1): - x_stack.insert(0, x[i + 1]) - y_stack.insert(0, f(x[i + 1])) - - while True: - x_high, x_low = x_stack[-2:] - y_high, y_low = y_stack[-2:] - x_mid = 0.5*(x_low + x_high) - y_mid = f(x_mid) - - y_interp = y_low + (y_high - y_low)/(x_high - x_low)*(x_mid - x_low) - error = abs((y_interp - y_mid)/y_mid) - if error > tolerance: - x_stack.insert(-1, x_mid) - y_stack.insert(-1, y_mid) - else: - x_out.append(x_stack.pop()) - y_out.append(y_stack.pop()) - if len(x_stack) == 1: - break - - x_out.append(x_stack.pop()) - y_out.append(y_stack.pop()) - - return np.array(x_out), np.array(y_out) - -def thin(x, y, tolerance=0.001): - """Check for (x,y) points that can be removed. - - Parameters - ---------- - x : numpy.ndarray - Independent variable - y : numpy.ndarray - Dependent variable - tolerance : float - Tolerance on interpolation error - - Returns - ------- - numpy.ndarray - Tabulated values of the independent variable - numpy.ndarray - Tabulated values of the dependent variable - - """ - # Initialize output arrays - x_out = x.copy() - y_out = y.copy() - - N = x.shape[0] - i_left = 0 - i_right = 2 - - while i_left < N - 2 and i_right < N: - m = (y[i_right] - y[i_left])/(x[i_right] - x[i_left]) - - for i in range(i_left + 1, i_right): - # Determine error in interpolated point - y_interp = y[i_left] + m*(x[i] - x[i_left]) - if abs(y[i]) > 0.: - error = abs((y_interp - y[i])/y[i]) - else: - error = 2*tolerance - - if error > tolerance: - for i_remove in range(i_left + 1, i_right - 1): - x_out[i_remove] = np.nan - y_out[i_remove] = np.nan - i_left = i_right - 1 - i_right = i_left + 1 - break - - i_right += 1 - - for i_remove in range(i_left + 1, i_right - 1): - x_out[i_remove] = np.nan - y_out[i_remove] = np.nan - - return x_out[np.isfinite(x_out)], y_out[np.isfinite(y_out)] diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py deleted file mode 100644 index c7df015a7..000000000 --- a/openmc/data/kalbach_mann.py +++ /dev/null @@ -1,402 +0,0 @@ -from collections.abc import Iterable -from numbers import Real, Integral -from warnings import warn - -import numpy as np - -import openmc.checkvalue as cv -from openmc.stats import Tabular, Univariate, Discrete, Mixture -from .function import Tabulated1D, INTERPOLATION_SCHEME -from .angle_energy import AngleEnergy -from .data import EV_PER_MEV -from .endf import get_list_record, get_tab2_record - - -class KalbachMann(AngleEnergy): - """Kalbach-Mann distribution - - Parameters - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - precompound : Iterable of openmc.data.Tabulated1D - Precompound factor 'r' as a function of outgoing energy for each - incoming energy - slope : Iterable of openmc.data.Tabulated1D - Kalbach-Chadwick angular distribution slope value 'a' as a function of - outgoing energy for each incoming energy - - Attributes - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - energy_out : Iterable of openmc.stats.Univariate - Distribution of outgoing energies corresponding to each incoming energy - precompound : Iterable of openmc.data.Tabulated1D - Precompound factor 'r' as a function of outgoing energy for each - incoming energy - slope : Iterable of openmc.data.Tabulated1D - Kalbach-Chadwick angular distribution slope value 'a' as a function of - outgoing energy for each incoming energy - - """ - - def __init__(self, breakpoints, interpolation, energy, energy_out, - precompound, slope): - super().__init__() - self.breakpoints = breakpoints - self.interpolation = interpolation - self.energy = energy - self.energy_out = energy_out - self.precompound = precompound - self.slope = slope - - @property - def breakpoints(self): - return self._breakpoints - - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - - @property - def precompound(self): - return self._precompound - - @property - def slope(self): - return self._slope - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('Kalbach-Mann breakpoints', breakpoints, - Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('Kalbach-Mann interpolation', interpolation, - Iterable, Integral) - self._interpolation = interpolation - - @energy.setter - def energy(self, energy): - cv.check_type('Kalbach-Mann incoming energy', energy, - Iterable, Real) - self._energy = energy - - @energy_out.setter - def energy_out(self, energy_out): - cv.check_type('Kalbach-Mann distributions', energy_out, - Iterable, Univariate) - self._energy_out = energy_out - - @precompound.setter - def precompound(self, precompound): - cv.check_type('Kalbach-Mann precompound factor', precompound, - Iterable, Tabulated1D) - self._precompound = precompound - - @slope.setter - def slope(self, slope): - cv.check_type('Kalbach-Mann slope', slope, Iterable, Tabulated1D) - self._slope = slope - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('kalbach-mann') - - dset = group.create_dataset('energy', data=self.energy) - dset.attrs['interpolation'] = np.vstack((self.breakpoints, - self.interpolation)) - - # Determine total number of (E,p,r,a) tuples and create array - n_tuple = sum(len(d) for d in self.energy_out) - distribution = np.empty((5, n_tuple)) - - # Create array for offsets - offsets = np.empty(len(self.energy_out), dtype=int) - interpolation = np.empty(len(self.energy_out), dtype=int) - n_discrete_lines = np.empty(len(self.energy_out), dtype=int) - j = 0 - - # Populate offsets and distribution array - for i, (eout, km_r, km_a) in enumerate(zip( - self.energy_out, self.precompound, self.slope)): - n = len(eout) - offsets[i] = j - - if isinstance(eout, Mixture): - discrete, continuous = eout.distribution - n_discrete_lines[i] = m = len(discrete) - interpolation[i] = 1 if continuous.interpolation == 'histogram' else 2 - distribution[0, j:j+m] = discrete.x - distribution[1, j:j+m] = discrete.p - distribution[2, j:j+m] = discrete.c - distribution[0, j+m:j+n] = continuous.x - distribution[1, j+m:j+n] = continuous.p - distribution[2, j+m:j+n] = continuous.c - else: - if isinstance(eout, Tabular): - n_discrete_lines[i] = 0 - interpolation[i] = 1 if eout.interpolation == 'histogram' else 2 - elif isinstance(eout, Discrete): - n_discrete_lines[i] = n - interpolation[i] = 1 - distribution[0, j:j+n] = eout.x - distribution[1, j:j+n] = eout.p - distribution[2, j:j+n] = eout.c - - distribution[3, j:j+n] = km_r.y - distribution[4, j:j+n] = km_a.y - j += n - - # Create dataset for distributions - dset = group.create_dataset('distribution', data=distribution) - - # Write interpolation as attribute - dset.attrs['offsets'] = offsets - dset.attrs['interpolation'] = interpolation - dset.attrs['n_discrete_lines'] = n_discrete_lines - - @classmethod - def from_hdf5(cls, group): - """Generate Kalbach-Mann distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.KalbachMann - Kalbach-Mann energy distribution - - """ - interp_data = group['energy'].attrs['interpolation'] - energy_breakpoints = interp_data[0, :] - energy_interpolation = interp_data[1, :] - energy = group['energy'][()] - - data = group['distribution'] - offsets = data.attrs['offsets'] - interpolation = data.attrs['interpolation'] - n_discrete_lines = data.attrs['n_discrete_lines'] - - energy_out = [] - precompound = [] - slope = [] - n_energy = len(energy) - for i in range(n_energy): - # Determine length of outgoing energy distribution and number of - # discrete lines - j = offsets[i] - if i < n_energy - 1: - n = offsets[i+1] - j - else: - n = data.shape[1] - j - m = n_discrete_lines[i] - - # Create discrete distribution if lines are present - if m > 0: - eout_discrete = Discrete(data[0, j:j+m], data[1, j:j+m]) - eout_discrete.c = data[2, j:j+m] - p_discrete = eout_discrete.c[-1] - - # Create continuous distribution - if m < n: - interp = INTERPOLATION_SCHEME[interpolation[i]] - eout_continuous = Tabular(data[0, j+m:j+n], data[1, j+m:j+n], interp) - eout_continuous.c = data[2, j+m:j+n] - - # If both continuous and discrete are present, create a mixture - # distribution - if m == 0: - eout_i = eout_continuous - elif m == n: - eout_i = eout_discrete - else: - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - - km_r = Tabulated1D(data[0, j:j+n], data[3, j:j+n]) - km_a = Tabulated1D(data[0, j:j+n], data[4, j:j+n]) - - energy_out.append(eout_i) - precompound.append(km_r) - slope.append(km_a) - - return cls(energy_breakpoints, energy_interpolation, - energy, energy_out, precompound, slope) - - @classmethod - def from_ace(cls, ace, idx, ldis): - """Generate Kalbach-Mann energy-angle distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - idx : int - Index in XSS array of the start of the energy distribution data - (LDIS + LOCC - 1) - ldis : int - Index in XSS array of the start of the energy distribution block - (e.g. JXS[11]) - - Returns - ------- - openmc.data.KalbachMann - Kalbach-Mann energy-angle distribution - - """ - # Read number of interpolation regions and incoming energies - n_regions = int(ace.xss[idx]) - n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) - - # Get interpolation information - idx += 1 - if n_regions > 0: - breakpoints = ace.xss[idx:idx + n_regions].astype(int) - interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) - else: - breakpoints = np.array([n_energy_in]) - interpolation = np.array([2]) - - # Incoming energies at which distributions exist - idx += 2*n_regions + 1 - energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV - - # Location of distributions - idx += n_energy_in - loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) - - # Initialize variables - energy_out = [] - km_r = [] - km_a = [] - - # Read each outgoing energy distribution - for i in range(n_energy_in): - idx = ldis + loc_dist[i] - 1 - - # intt = interpolation scheme (1=hist, 2=lin-lin) - INTTp = int(ace.xss[idx]) - intt = INTTp % 10 - n_discrete_lines = (INTTp - intt)//10 - if intt not in (1, 2): - warn("Interpolation scheme for continuous tabular distribution " - "is not histogram or linear-linear.") - intt = 2 - - n_energy_out = int(ace.xss[idx + 1]) - data = ace.xss[idx + 2:idx + 2 + 5*n_energy_out].copy() - data.shape = (5, n_energy_out) - data[0,:] *= EV_PER_MEV - - # Create continuous distribution - eout_continuous = Tabular(data[0][n_discrete_lines:], - data[1][n_discrete_lines:]/EV_PER_MEV, - INTERPOLATION_SCHEME[intt], - ignore_negative=True) - eout_continuous.c = data[2][n_discrete_lines:] - if np.any(data[1][n_discrete_lines:] < 0.0): - warn("Kalbach-Mann energy distribution has negative " - "probabilities.") - - # If discrete lines are present, create a mixture distribution - if n_discrete_lines > 0: - eout_discrete = Discrete(data[0][:n_discrete_lines], - data[1][:n_discrete_lines]) - eout_discrete.c = data[2][:n_discrete_lines] - if n_discrete_lines == n_energy_out: - eout_i = eout_discrete - else: - p_discrete = min(sum(eout_discrete.p), 1.0) - eout_i = Mixture([p_discrete, 1. - p_discrete], - [eout_discrete, eout_continuous]) - else: - eout_i = eout_continuous - - energy_out.append(eout_i) - km_r.append(Tabulated1D(data[0], data[3])) - km_a.append(Tabulated1D(data[0], data[4])) - - return cls(breakpoints, interpolation, energy, energy_out, km_r, km_a) - - @classmethod - def from_endf(cls, file_obj): - """Generate Kalbach-Mann distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of the Kalbach-Mann distribution - - Returns - ------- - openmc.data.KalbachMann - Kalbach-Mann energy-angle distribution - - """ - params, tab2 = get_tab2_record(file_obj) - lep = params[3] - ne = params[5] - energy = np.zeros(ne) - n_discrete_energies = np.zeros(ne, dtype=int) - energy_out = [] - precompound = [] - slope = [] - for i in range(ne): - items, values = get_list_record(file_obj) - energy[i] = items[1] - n_discrete_energies[i] = items[2] - # TODO: split out discrete energies - n_angle = items[3] - n_energy_out = items[5] - values = np.asarray(values) - values.shape = (n_energy_out, n_angle + 2) - - # Outgoing energy distribution at the i-th incoming energy - eout_i = values[:,0] - eout_p_i = values[:,1] - energy_out_i = Tabular(eout_i, eout_p_i, INTERPOLATION_SCHEME[lep]) - energy_out.append(energy_out_i) - - # Precompound and slope factors for Kalbach-Mann - r_i = values[:,2] - if n_angle == 2: - a_i = values[:,3] - else: - a_i = np.zeros_like(r_i) - precompound.append(Tabulated1D(eout_i, r_i)) - slope.append(Tabulated1D(eout_i, a_i)) - - return cls(tab2.breakpoints, tab2.interpolation, energy, - energy_out, precompound, slope) diff --git a/openmc/data/laboratory.py b/openmc/data/laboratory.py deleted file mode 100644 index cfedb292b..000000000 --- a/openmc/data/laboratory.py +++ /dev/null @@ -1,142 +0,0 @@ -from collections.abc import Iterable -from numbers import Real, Integral - -import numpy as np - -import openmc.checkvalue as cv -from openmc.stats import Tabular, Univariate, Discrete, Mixture -from .angle_energy import AngleEnergy -from .function import INTERPOLATION_SCHEME -from .endf import get_tab2_record, get_tab1_record - - -class LaboratoryAngleEnergy(AngleEnergy): - """Laboratory angle-energy distribution - - Parameters - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - mu : Iterable of openmc.stats.Univariate - Distribution of scattering cosines for each incoming energy - energy_out : Iterable of Iterable of openmc.stats.Univariate - Distribution of outgoing energies for each incoming energy/scattering - cosine - - Attributes - ---------- - breakpoints : Iterable of int - Breakpoints defining interpolation regions - interpolation : Iterable of int - Interpolation codes - energy : Iterable of float - Incoming energies at which distributions exist - mu : Iterable of openmc.stats.Univariate - Distribution of scattering cosines for each incoming energy - energy_out : Iterable of Iterable of openmc.stats.Univariate - Distribution of outgoing energies for each incoming energy/scattering - cosine - - """ - - def __init__(self, breakpoints, interpolation, energy, mu, energy_out): - super().__init__() - self.breakpoints = breakpoints - self.interpolation = interpolation - self.energy = energy - self.mu = mu - self.energy_out = energy_out - - @property - def breakpoints(self): - return self._breakpoints - - @property - def interpolation(self): - return self._interpolation - @property - def energy(self): - return self._energy - - @property - def mu(self): - return self._mu - - @property - def energy_out(self): - return self._energy_out - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('laboratory angle-energy breakpoints', breakpoints, - Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('laboratory angle-energy interpolation', interpolation, - Iterable, Integral) - self._interpolation = interpolation - - @energy.setter - def energy(self, energy): - cv.check_type('laboratory angle-energy incoming energy', energy, - Iterable, Real) - self._energy = energy - - @mu.setter - def mu(self, mu): - cv.check_type('laboratory angle-energy outgoing cosine', mu, - Iterable, Univariate) - self._mu = mu - - @energy_out.setter - def energy_out(self, energy_out): - cv.check_iterable_type('laboratory angle-energy outgoing energy', - energy_out, Univariate, 2, 2) - self._energy_out = energy_out - - @classmethod - def from_endf(cls, file_obj): - """Generate laboratory angle-energy distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the start of a section for a correlated - angle-energy distribution - - Returns - ------- - openmc.data.LaboratoryAngleEnergy - Laboratory angle-energy distribution - - """ - params, tab2 = get_tab2_record(file_obj) - ne = params[5] - energy = np.zeros(ne) - mu = [] - energy_out = [] - for i in range(ne): - params, tab2mu = get_tab2_record(file_obj) - energy[i] = params[1] - n_mu = params[5] - mu_i = np.zeros(n_mu) - p_mu_i = np.zeros(n_mu) - energy_out_i = [] - for j in range(n_mu): - params, f = get_tab1_record(file_obj) - mu_i[j] = params[1] - p_mu_i[j] = sum(f.y) - energy_out_i.append(Tabular(f.x, f.y)) - mu.append(Tabular(mu_i, p_mu_i)) - energy_out.append(energy_out_i) - - return cls(tab2.breakpoints, tab2.interpolation, energy, mu, energy_out) - - def to_hdf5(self, group): - raise NotImplementedError diff --git a/openmc/data/library.py b/openmc/data/library.py deleted file mode 100644 index d5f18aa17..000000000 --- a/openmc/data/library.py +++ /dev/null @@ -1,173 +0,0 @@ -import os -import xml.etree.ElementTree as ET -import pathlib - -import h5py - -from openmc.mixin import EqualityMixin -from openmc._xml import clean_indentation -from openmc.checkvalue import check_type - - -class DataLibrary(EqualityMixin): - """Collection of cross section data libraries. - - Attributes - ---------- - libraries : list of dict - List in which each item is a dictionary summarizing cross section data - from a single file. The dictionary has keys 'path', 'type', and - 'materials'. - - """ - - def __init__(self): - self.libraries = [] - - def get_by_material(self, name): - """Return the library dictionary containing a given material. - - Parameters - ---------- - name : str - Name of material, e.g. 'Am241' - - Returns - ------- - library : dict or None - Dictionary summarizing cross section data from a single file; - the dictionary has keys 'path', 'type', and 'materials'. - - """ - for library in self.libraries: - if name in library['materials']: - return library - return None - - def register_file(self, filename): - """Register a file with the data library. - - Parameters - ---------- - filename : str or Path - Path to the file to be registered. - If an ``xml`` file, treat as the depletion chain file without - materials. - - """ - if not isinstance(filename, pathlib.Path): - path = pathlib.Path(filename) - else: - path = filename - - if path.suffix == '.xml': - filetype = 'depletion_chain' - materials = [] - elif path.suffix == '.h5': - with h5py.File(path, 'r') as h5file: - filetype = h5file.attrs['filetype'].decode()[5:] - materials = list(h5file) - else: - raise ValueError( - "File type {} not supported by {}" - .format(path.name, self.__class__.__name__)) - - library = {'path': str(path), 'type': filetype, 'materials': materials} - self.libraries.append(library) - - def export_to_xml(self, path='cross_sections.xml'): - """Export cross section data library to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'cross_sections.xml'. - - """ - root = ET.Element('cross_sections') - - # Determine common directory for library paths - common_dir = os.path.dirname(os.path.commonprefix( - [lib['path'] for lib in self.libraries])) - if common_dir == '': - common_dir = '.' - - if os.path.relpath(common_dir, os.path.dirname(str(path))) != '.': - dir_element = ET.SubElement(root, "directory") - dir_element.text = os.path.realpath(common_dir) - - for library in self.libraries: - if library['type'] == "depletion_chain": - lib_element = ET.SubElement(root, "depletion_chain") - else: - lib_element = ET.SubElement(root, "library") - lib_element.set('materials', ' '.join(library['materials'])) - lib_element.set('path', os.path.relpath(library['path'], common_dir)) - lib_element.set('type', library['type']) - - # Clean the indentation to be user-readable - clean_indentation(root) - - # Write XML file - tree = ET.ElementTree(root) - tree.write(str(path), xml_declaration=True, encoding='utf-8', - method='xml') - - @classmethod - def from_xml(cls, path=None): - """Read cross section data library from an XML file. - - Parameters - ---------- - path : str, optional - Path to XML file to read. If not provided, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used. - - Returns - ------- - data : openmc.data.DataLibrary - Data library object initialized from the provided XML - - """ - - data = cls() - - # If path is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable - if path is None: - path = os.environ.get('OPENMC_CROSS_SECTIONS') - - # Check to make sure there was an environmental variable. - if path is None: - raise ValueError("Either path or OPENMC_CROSS_SECTIONS " - "environmental variable must be set") - - # Convert to string to support pathlib - # TODO: Remove when support is Python 3.6+ only - path = str(path) - - tree = ET.parse(path) - root = tree.getroot() - if root.find('directory') is not None: - directory = root.find('directory').text - else: - directory = os.path.dirname(path) - - for lib_element in root.findall('library'): - filename = os.path.join(directory, lib_element.attrib['path']) - filetype = lib_element.attrib['type'] - materials = lib_element.attrib['materials'].split() - library = {'path': filename, 'type': filetype, - 'materials': materials} - data.libraries.append(library) - - # get depletion chain data - - dep_node = root.find("depletion_chain") - if dep_node is not None: - filename = os.path.join(directory, dep_node.attrib['path']) - library = {'path': filename, 'type': 'depletion_chain', - 'materials': []} - data.libraries.append(library) - - return data diff --git a/openmc/data/mass16.txt b/openmc/data/mass16.txt deleted file mode 100644 index 4b479be45..000000000 --- a/openmc/data/mass16.txt +++ /dev/null @@ -1,3475 +0,0 @@ -1 a0boogfu A T O M I C M A S S A D J U S T M E N T -0 DATE 1 Mar 2017 TIME 17:26 -0 ********************* A= 0 TO 295 - * file : mass16.txt * - ********************* - - This is one file out of a series of 3 files published in: - "The Ame2016 atomic mass evaluation (I)" by W.J.Huang, G.Audi, M.Wang, F.G.Kondev, S.Naimi and X.Xu - Chinese Physics C41 030002, March 2017. - "The Ame2016 atomic mass evaluation (II)" by M.Wang, G.Audi, F.G.Kondev, W.J.Huang, S.Naimi and X.Xu - Chinese Physics C41 030003, March 2017. - for files : mass16.txt : atomic masses - rct1-16.txt : react and sep energies, part 1 - rct2-16.txt : react and sep energies, part 2 - A fourth file is the "Rounded" version of the atomic mass table (the first file) - mass16round.txt : atomic masses "Rounded" version - - All files are 3436 lines long with 124 character per line. - Headers are 39 lines long. - Values in files 1, 2 and 3 are unrounded copy of the published ones - Values in file 4 are exact copy of the published ones - - col 1 : Fortran character control: 1 = page feed 0 = line feed - format : a1,i3,i5,i5,i5,1x,a3,a4,1x,f13.5,f11.5,f11.3,f9.3,1x,a2,f11.3,f9.3,1x,i3,1x,f12.5,f11.5 - cc NZ N Z A el o mass unc binding unc B beta unc atomic_mass unc - Warnings : this format is identical to the ones used in Ame2003 and Ame2012 - in particular "Mass Excess" and "Atomic Mass" values are given now, when necessary, - with 5 digits after decimal point. - decimal point is replaced by # for (non-experimental) estimated values. - * in place of value : not calculable - -....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10....+...11....+...12.... - - - MASS LIST - for analysis - -1N-Z N Z A EL O MASS EXCESS BINDING ENERGY/A BETA-DECAY ENERGY ATOMIC MASS - (keV) (keV) (keV) (micro-u) -0 1 1 0 1 n 8071.31713 0.00046 0.0 0.0 B- 782.347 0.000 1 008664.91582 0.00049 - -1 0 1 1 H 7288.97061 0.00009 0.0 0.0 B- * 1 007825.03224 0.00009 -0 0 1 1 2 H 13135.72176 0.00011 1112.283 0.000 B- * 2 014101.77811 0.00012 -0 1 2 1 3 H 14949.80993 0.00022 2827.265 0.000 B- 18.592 0.000 3 016049.28199 0.00023 - -1 1 2 3 He 14931.21793 0.00021 2572.680 0.000 B- -13736# 2000# 3 016029.32265 0.00022 - -3 0 3 3 Li -pp 28667# 2000# -2267# 667# B- * 3 030775# 2147# -0 2 3 1 4 H -n 24621.127 100.000 1720.449 25.000 B- 22196.211 100.000 4 026431.868 107.354 - 0 2 2 4 He 2424.91561 0.00006 7073.915 0.000 B- -22898.273 212.132 4 002603.25413 0.00006 - -2 1 3 4 Li -p 25323.189 212.132 1153.760 53.033 B- * 4 027185.562 227.733 -0 3 4 1 5 H -nn 32892.444 89.443 1336.359 17.889 B- 21661.211 91.652 5 035311.493 96.020 - 1 3 2 5 He -n 11231.233 20.000 5512.132 4.000 B- -447.654 53.852 5 012057.224 21.470 - -1 2 3 5 Li -p 11678.886 50.000 5266.132 10.000 B- -25460# 2003# 5 012537.800 53.677 - -3 1 4 5 Be x 37139# 2003# 18# 401# B- * 5 039870# 2150# -0 4 5 1 6 H -3n 41875.721 254.127 961.639 42.354 B- 24283.626 254.127 6 044955.437 272.816 - 2 4 2 6 He 17592.095 0.053 4878.519 0.009 B- 3505.216 0.053 6 018885.891 0.057 - 0 3 3 6 Li 14086.87895 0.00144 5332.331 0.000 B- -4288.154 5.448 6 015122.88742 0.00155 - -2 2 4 6 Be - 18375.033 5.448 4487.247 0.908 B- -28945# 2003# 6 019726.409 5.848 - -4 1 5 6 B x 47320# 2003# -467# 334# B- * 6 050800# 2150# -0 5 6 1 7 H -nn 49135# 1004# 940# 143# B- 23062# 1004# 7 052749# 1078# - 3 5 2 7 He -n 26073.126 7.559 4123.057 1.080 B- 11166.021 7.559 7 027990.654 8.115 - 1 4 3 7 Li 14907.10529 0.00423 5606.439 0.001 B- -861.893 0.071 7 016003.43666 0.00454 - -1 3 4 7 Be 15768.999 0.071 5371.548 0.010 B- -11907.551 25.150 7 016928.717 0.076 - -3 2 5 7 B p4n 27676.550 25.150 3558.705 3.593 B- * 7 029712.000 27.000 -0 4 6 2 8 He 31609.681 0.089 3924.520 0.011 B- 10663.878 0.100 8 033934.390 0.095 - 2 5 3 8 Li 20945.804 0.047 5159.712 0.006 B- 16004.133 0.059 8 022486.246 0.050 - 0 4 4 8 Be -a 4941.671 0.035 7062.435 0.004 B- -17979.896 1.000 8 005305.102 0.037 - -2 3 5 8 B 22921.567 1.000 4717.155 0.125 B- -12142.701 18.270 8 024607.316 1.073 - -4 2 6 8 C 35064.268 18.243 3101.524 2.280 B- * 8 037643.042 19.584 -0 5 7 2 9 He 40935.826 46.816 3349.037 5.202 B- 15980.924 46.817 9 043946.419 50.259 - 3 6 3 9 Li -3n 24954.902 0.186 5037.768 0.021 B- 13606.449 0.201 9 026790.191 0.200 - 1 5 4 9 Be 11348.453 0.077 6462.668 0.009 B- -1068.035 0.899 9 012183.066 0.082 - -1 4 5 9 B - 12416.488 0.903 6257.070 0.100 B- -16494.484 2.319 9 013329.649 0.969 - -3 3 6 9 C -pp 28910.972 2.137 4337.423 0.237 B- * 9 031037.207 2.293 -0 6 8 2 10 He -nn 49197.143 92.848 2995.134 9.285 B- 16144.519 93.715 10 052815.308 99.676 - 4 7 3 10 Li -n 33052.624 12.721 4531.351 1.272 B- 20445.136 12.722 10 035483.453 13.656 - 2 6 4 10 Be 12607.488 0.081 6497.630 0.008 B- 556.878 0.082 10 013534.695 0.086 - 0 5 5 10 B 12050.609 0.015 6475.083 0.002 B- -3648.062 0.069 10 012936.862 0.016 - -2 4 6 10 C 15698.672 0.070 6032.042 0.007 B- -23101.355 400.000 10 016853.218 0.075 - -4 3 7 10 N -- 38800.026 400.000 3643.672 40.000 B- * 10 041653.543 429.417 -0 5 8 3 11 Li x 40728.254 0.615 4155.381 0.056 B- 20551.087 0.659 11 043723.581 0.660 - 3 7 4 11 Be 20177.167 0.238 5952.540 0.022 B- 11509.460 0.238 11 021661.081 0.255 - 1 6 5 11 B 8667.707 0.012 6927.732 0.001 B- -1981.689 0.061 11 009305.166 0.013 - -1 5 6 11 C 10649.396 0.060 6676.456 0.005 B- -13654.163 46.154 11 011432.597 0.064 - -3 4 7 11 N -p 24303.559 46.154 5364.046 4.196 B- * 11 026090.945 49.548 -0 6 9 3 12 Li -n 49009.571 30.006 3791.600 2.501 B- 23931.812 30.067 12 052613.941 32.213 - 4 8 4 12 Be 25077.760 1.909 5720.722 0.159 B- 11708.363 2.321 12 026922.083 2.048 - 2 7 5 12 B 13369.397 1.321 6631.223 0.110 B- 13369.397 1.321 12 014352.638 1.418 - 0 6 6 12 C 0.0 0.0 7680.144 0.000 B- -17338.068 1.000 12 000000.0 0.0 - -2 5 7 12 N 17338.068 1.000 6170.109 0.083 B- -14576.544 24.021 12 018613.182 1.073 - -4 4 8 12 O -pp 31914.613 24.000 4890.202 2.000 B- * 12 034261.747 25.765 -0 7 10 3 13 Li -nn 56980.888 70.003 3507.630 5.385 B- 23321.812 70.739 13 061171.503 75.150 - 5 9 4 13 Be -n 33659.077 10.180 5241.435 0.783 B- 17097.130 10.230 13 036134.507 10.929 - 3 8 5 13 B -nn 16561.947 1.000 6496.419 0.077 B- 13436.938 1.000 13 017779.981 1.073 - 1 7 6 13 C 3125.00888 0.00021 7469.849 0.000 B- -2220.472 0.270 13 003354.83521 0.00023 - -1 6 7 13 N 5345.481 0.270 7238.863 0.021 B- -17769.951 9.530 13 005738.609 0.289 - -3 5 8 13 O +3n 23115.432 9.526 5811.763 0.733 B- * 13 024815.437 10.226 -0 6 10 4 14 Be x 39954.498 132.245 4993.897 9.446 B- 16290.813 133.936 14 042892.920 141.970 - 4 9 5 14 B 23663.685 21.213 6101.644 1.515 B- 20643.792 21.213 14 025404.012 22.773 - 2 8 6 14 C 3019.89278 0.00376 7520.319 0.000 B- 156.476 0.004 14 003241.98843 0.00403 - 0 7 7 14 N 2863.41672 0.00019 7475.614 0.000 B- -5144.364 0.025 14 003074.00446 0.00021 - -2 6 8 14 O 8007.781 0.025 7052.278 0.002 B- -23956.622 41.119 14 008596.706 0.027 - -4 5 9 14 F -p 31964.402 41.119 5285.208 2.937 B- * 14 034315.199 44.142 -0 7 11 4 15 Be -n 49825.815 165.797 4540.970 11.053 B- 20867.573 167.126 15 053490.215 177.990 - 5 10 5 15 B 28958.242 21.032 5879.985 1.402 B- 19085.098 21.047 15 031087.953 22.578 - 3 9 6 15 C -n 9873.144 0.800 7100.169 0.053 B- 9771.705 0.800 15 010599.256 0.858 - 1 8 7 15 N 101.43871 0.00060 7699.460 0.000 B- -2754.166 0.491 15 000108.89894 0.00065 - -1 7 8 15 O 2855.605 0.491 7463.692 0.033 B- -13711.146 14.009 15 003065.618 0.526 - -3 6 9 15 F -p 16566.751 14.000 6497.459 0.933 B- -23648.622 68.138 15 017785.139 15.029 - -5 5 10 15 Ne -pp 40215.373 66.684 4868.728 4.446 B- * 15 043172.980 71.588 -0 8 12 4 16 Be -nn 57447.132 165.797 4285.285 10.362 B- 20334.623 167.608 16 061672.036 177.990 - 6 11 5 16 B 37112.510 24.569 5507.302 1.536 B- 23418.378 24.828 16 039841.920 26.375 - 4 10 6 16 C -nn 13694.132 3.578 6922.054 0.224 B- 8010.225 4.254 16 014701.256 3.840 - 2 9 7 16 N -n 5683.907 2.301 7373.796 0.144 B- 10420.908 2.301 16 006101.925 2.470 - 0 8 8 16 O -4737.00135 0.00016 7976.206 0.000 B- -15417.254 8.321 15 994914.61960 0.00017 - -2 7 9 16 F - 10680.253 8.321 6963.731 0.520 B- -13306.523 22.106 16 011465.723 8.932 - -4 6 10 16 Ne -- 23986.776 20.480 6083.177 1.280 B- * 16 025750.864 21.986 -0 7 12 5 17 B x 43716.317 204.104 5269.667 12.006 B- 22684.419 204.841 17 046931.399 219.114 - 5 11 6 17 C 2p-n 21031.898 17.365 6558.024 1.021 B- 13161.820 22.946 17 022578.672 18.641 - 3 10 7 17 N +p 7870.079 15.000 7286.229 0.882 B- 8678.842 15.000 17 008448.877 16.103 - 1 9 8 17 O -808.76348 0.00066 7750.728 0.000 B- -2760.465 0.248 16 999131.75664 0.00070 - -1 8 9 17 F 1951.702 0.248 7542.328 0.015 B- -14548.746 0.432 17 002095.238 0.266 - -3 7 10 17 Ne 16500.447 0.354 6640.499 0.021 B- -18672.766 1001.356 17 017713.959 0.380 - -5 6 11 17 Na x 35173.214 1001.356 5496.080 58.903 B- * 17 037760.000 1075.000 -0 8 13 5 18 B -n 51792.634 204.165 4976.630 11.342 B- 26873.370 206.357 18 055601.682 219.180 - 6 12 6 18 C ++ 24919.264 30.000 6426.131 1.667 B- 11806.096 35.282 18 026751.932 32.206 - 4 11 7 18 N + 13113.168 18.570 7038.562 1.032 B- 13895.984 18.570 18 014077.565 19.935 - 2 10 8 18 O -782.81560 0.00071 7767.097 0.000 B- -1655.929 0.463 17 999159.61284 0.00076 - 0 9 9 18 F 873.113 0.463 7631.638 0.026 B- -4444.501 0.589 18 000937.325 0.497 - -2 8 10 18 Ne 5317.614 0.363 7341.257 0.020 B- -19720.374 93.882 18 005708.693 0.390 - -4 7 11 18 Na 25037.988 93.881 6202.217 5.216 B- * 18 026879.386 100.785 -0 9 14 5 19 B x 59770.244 525.363 4719.634 27.651 B- 27356.492 534.496 19 064166.000 564.000 - 7 13 6 19 C -n 32413.752 98.389 6118.273 5.178 B- 16557.471 99.748 19 034797.596 105.625 - 5 12 7 19 N p-2n 15856.282 16.404 6948.543 0.863 B- 12523.424 16.614 19 017022.419 17.610 - 3 11 8 19 O -n 3332.858 2.637 7566.495 0.139 B- 4820.302 2.637 19 003577.970 2.830 - 1 10 9 19 F -1487.44420 0.00086 7779.018 0.000 B- -3239.494 0.160 18 998403.16288 0.00093 - -1 9 10 19 Ne +3n 1752.050 0.160 7567.343 0.008 B- -11177.340 10.536 19 001880.903 0.171 - -3 8 11 19 Na 12929.390 10.535 6937.885 0.554 B- -18898.998 51.099 19 013880.272 11.309 - -5 7 12 19 Mg -pp 31828.389 50.001 5902.025 2.632 B- * 19 034169.182 53.678 -0 10 15 5 20 B x 68450# 800# 4453# 40# B- 30946# 833# 20 073484# 859# - 8 14 6 20 C x 37503.563 230.625 5961.435 11.531 B- 15737.067 243.746 20 040261.732 247.585 - 6 13 7 20 N x 21766.496 78.894 6709.171 3.945 B- 17970.324 78.899 20 023367.295 84.696 - 4 12 8 20 O -nn 3796.172 0.885 7568.570 0.044 B- 3813.635 0.885 20 004075.358 0.950 - 2 11 9 20 F -n -17.463 0.030 7720.134 0.002 B- 7024.467 0.030 19 999981.252 0.031 - 0 10 10 20 Ne -7041.93055 0.00157 8032.240 0.000 B- -13892.535 1.114 19 992440.17619 0.00168 - -2 9 11 20 Na 6850.604 1.114 7298.496 0.056 B- -10627.088 2.171 20 007354.426 1.195 - -4 8 12 20 Mg +t 17477.692 1.863 6728.025 0.093 B- * 20 018763.075 2.000 -0 11 16 5 21 B x 77330# 900# 4203# 43# B- 31687# 1079# 21 083017# 966# - 9 15 6 21 C x 45643# 596# 5674# 28# B- 20411# 611# 21 049000# 640# - 7 14 7 21 N x 25231.913 134.048 6609.015 6.383 B- 17169.878 134.584 21 027087.573 143.906 - 5 13 8 21 O -3n 8062.035 12.000 7389.374 0.571 B- 8109.640 12.134 21 008654.950 12.882 - 3 12 9 21 F -nn -47.605 1.800 7738.293 0.086 B- 5684.171 1.800 20 999948.894 1.932 - 1 11 10 21 Ne -5731.776 0.038 7971.713 0.002 B- -3547.145 0.090 20 993846.685 0.041 - -1 10 11 21 Na -2184.631 0.098 7765.547 0.005 B- -13088.480 0.761 20 997654.702 0.105 - -3 9 12 21 Mg x 10903.850 0.755 7105.031 0.036 B- -16086# 596# 21 011705.764 0.810 - -5 8 13 21 Al x 26990# 596# 6302# 28# B- * 21 028975# 640# -0 10 16 6 22 C -nn 53611.197 231.490 5421.077 10.522 B- 21846.396 311.063 22 057553.990 248.515 - 8 15 7 22 N x 31764.801 207.779 6378.534 9.445 B- 22481.768 215.435 22 034100.918 223.060 - 6 14 8 22 O -4n 9283.033 56.921 7364.871 2.587 B- 6489.660 58.256 22 009965.746 61.107 - 4 13 9 22 F + 2793.373 12.399 7624.295 0.564 B- 10818.092 12.399 22 002998.809 13.310 - 2 12 10 22 Ne -8024.719 0.018 8080.465 0.001 B- -2843.207 0.171 21 991385.109 0.018 - 0 11 11 22 Na -5181.511 0.171 7915.667 0.008 B- -4781.578 0.321 21 994437.418 0.183 - -2 10 12 22 Mg -399.933 0.313 7662.761 0.014 B- -18601# 401# 21 999570.654 0.335 - -4 9 13 22 Al x 18201# 401# 6782# 18# B- -15137# 643# 22 019540# 430# - -6 8 14 22 Si x 33338# 503# 6058# 23# B- * 22 035790# 540# -0 11 17 6 23 C x 64171# 997# 5077# 43# B- 27450# 1082# 23 068890# 1070# - 9 16 7 23 N x 36720.425 420.570 6236.671 18.286 B- 22099.056 437.827 23 039421.000 451.500 - 7 15 8 23 O x 14621.369 121.712 7163.485 5.292 B- 11336.106 126.190 23 015696.686 130.663 - 5 14 9 23 F 3285.263 33.320 7622.344 1.449 B- 8439.312 33.321 23 003526.874 35.770 - 3 13 10 23 Ne -n -5154.049 0.104 7955.256 0.005 B- 4375.804 0.104 22 994466.900 0.112 - 1 12 11 23 Na -9529.85248 0.00181 8111.493 0.000 B- -4056.340 0.158 22 989769.28199 0.00194 - -1 11 12 23 Mg - -5473.513 0.158 7901.115 0.007 B- -12221.583 0.379 22 994123.941 0.170 - -3 10 13 23 Al -- 6748.070 0.345 7335.727 0.015 B- -16949# 503# 23 007244.351 0.370 - -5 9 14 23 Si x 23697# 503# 6565# 22# B- * 23 025440# 540# -0 10 17 7 24 N x 46938# 401# 5887# 17# B- 28438# 433# 24 050390# 430# - 8 16 8 24 O x 18500.402 164.874 7039.685 6.870 B- 10955.887 191.633 24 019861.000 177.000 - 6 15 9 24 F x 7544.515 97.670 7463.582 4.070 B- 13496.161 97.672 24 008099.370 104.853 - 4 14 10 24 Ne -nn -5951.646 0.513 7993.325 0.021 B- 2466.255 0.513 23 993610.645 0.550 - 2 13 11 24 Na -n -8417.901 0.017 8063.488 0.001 B- 5515.669 0.021 23 990963.011 0.017 - 0 12 12 24 Mg -13933.569 0.013 8260.709 0.001 B- -13884.704 0.233 23 985041.697 0.014 - -2 11 13 24 Al ep -48.865 0.233 7649.582 0.010 B- -10794.060 19.473 23 999947.541 0.250 - -4 10 14 24 Si -- 10745.195 19.472 7167.232 0.811 B- -22574# 503# 24 011535.441 20.904 - -6 9 15 24 P x 33320# 503# 6194# 21# B- * 24 035770# 540# -0 11 18 7 25 N x 55983# 503# 5613# 20# B- 28654# 529# 25 060100# 540# - 9 17 8 25 O -n 27329.027 165.084 6727.805 6.603 B- 15994.862 191.191 25 029338.919 177.225 - 7 16 9 25 F x 11334.166 96.442 7336.306 3.858 B- 13369.667 100.721 25 012167.727 103.535 - 5 15 10 25 Ne -2035.502 29.045 7839.799 1.162 B- 7322.312 29.070 24 997814.799 31.181 - 3 14 11 25 Na -nn -9357.813 1.200 8101.397 0.048 B- 3834.969 1.201 24 989953.973 1.288 - 1 13 12 25 Mg -13192.783 0.047 8223.502 0.002 B- -4276.808 0.045 24 985836.964 0.050 - -1 12 13 25 Al -8915.975 0.065 8021.136 0.003 B- -12743.299 10.000 24 990428.306 0.069 - -3 11 14 25 Si +3n 3827.324 10.000 7480.110 0.400 B- -15911# 401# 25 004108.801 10.735 - -5 10 15 25 P x 19738# 401# 6812# 16# B- * 25 021190# 430# -0 10 18 8 26 O -nn 34661.037 164.950 6497.478 6.344 B- 16012.161 198.932 26 037210.155 177.081 - 8 17 9 26 F x 18648.875 111.199 7083.240 4.277 B- 18167.762 112.716 26 020020.392 119.377 - 6 16 10 26 Ne x 481.114 18.429 7751.910 0.709 B- 7341.893 18.758 26 000516.496 19.784 - 4 15 11 26 Na x -6860.780 3.502 8004.201 0.135 B- 9353.763 3.502 25 992634.649 3.759 - 2 14 12 26 Mg -16214.542 0.030 8333.870 0.001 B- -4004.391 0.063 25 982592.971 0.032 - 0 13 13 26 Al -12210.151 0.067 8149.765 0.003 B- -5069.136 0.085 25 986891.863 0.071 - -2 12 14 26 Si - -7141.015 0.108 7924.708 0.004 B- -18114# 196# 25 992333.804 0.115 - -4 11 15 26 P x 10973# 196# 7198# 8# B- -16106# 627# 26 011780# 210# - -6 10 16 26 S x 27079# 596# 6548# 23# B- * 26 029070# 640# -0 11 19 8 27 O x 44670# 500# 6185# 19# B- 19220# 634# 27 047955# 537# - 9 18 9 27 F x 25450.279 389.830 6867.932 14.438 B- 18399.370 400.258 27 027322.000 418.500 - 7 17 10 27 Ne x 7050.909 90.770 7520.414 3.362 B- 12568.699 90.847 27 007569.462 97.445 - 5 16 11 27 Na ++ -5517.790 3.726 7956.946 0.138 B- 9068.821 3.727 26 994076.408 4.000 - 3 15 12 27 Mg -n -14586.611 0.050 8263.852 0.002 B- 2610.251 0.069 26 984340.628 0.053 - 1 14 13 27 Al -17196.861 0.047 8331.553 0.002 B- -4812.359 0.096 26 981538.408 0.050 - -1 13 14 27 Si - -12384.503 0.107 8124.341 0.004 B- -11662.044 26.340 26 986704.688 0.115 - -3 12 15 27 P p4n -722.458 26.340 7663.438 0.976 B- -17750# 400# 26 999224.409 28.277 - -5 11 16 27 S - 17028# 401# 6977# 15# B- * 27 018280# 430# -0 12 20 8 28 O x 52080# 699# 5988# 25# B- 18338# 802# 28 055910# 750# - 10 19 9 28 F -n 33741.596 393.024 6614.792 14.037 B- 22441.859 412.748 28 036223.095 421.928 - 8 18 10 28 Ne x 11299.737 126.068 7388.346 4.502 B- 12288.052 126.483 28 012130.767 135.339 - 6 17 11 28 Na x -988.315 10.246 7799.264 0.366 B- 14030.529 10.440 27 998939.000 11.000 - 4 16 12 28 Mg + -15018.845 2.001 8272.413 0.071 B- 1831.800 2.000 27 983876.606 2.148 - 2 15 13 28 Al -n -16850.645 0.077 8309.894 0.003 B- 4642.150 0.077 27 981910.087 0.083 - 0 14 14 28 Si -21492.79430 0.00049 8447.744 0.000 B- -14345.055 1.152 27 976926.53499 0.00052 - -2 13 15 28 P -7147.740 1.152 7907.479 0.041 B- -11220.945 160.004 27 992326.585 1.236 - -4 12 16 28 S -- 4073.206 160.000 7478.790 5.714 B- -23443# 617# 28 004372.766 171.767 - -6 11 17 28 Cl x 27516# 596# 6614# 21# B- * 28 029540# 640# -0 11 20 9 29 F x 40150.186 525.363 6444.031 18.116 B- 21750.385 546.221 29 043103.000 564.000 - 9 19 10 29 Ne x 18399.801 149.505 7167.067 5.155 B- 15719.807 149.685 29 019753.000 160.500 - 7 18 11 29 Na 2679.994 7.337 7682.151 0.253 B- 13282.824 13.557 29 002877.092 7.876 - 5 17 12 29 Mg x -10602.829 11.400 8113.202 0.393 B- 7604.931 11.405 28 988617.393 12.238 - 3 16 13 29 Al x -18207.760 0.345 8348.464 0.012 B- 3687.318 0.345 28 980453.164 0.370 - 1 15 14 29 Si -21895.07838 0.00056 8448.635 0.000 B- -4942.230 0.359 28 976494.66525 0.00060 - -1 14 15 29 P -16952.848 0.359 8251.236 0.012 B- -13796.432 50.001 28 981800.368 0.385 - -3 13 16 29 S +3n -3156.416 50.000 7748.520 1.724 B- -16318.592 195.192 28 996611.448 53.677 - -5 12 17 29 Cl -p 13162.176 188.680 7158.832 6.506 B- * 29 014130.178 202.555 -0 12 21 9 30 F x 48112# 596# 6233# 20# B- 24832# 648# 30 051650# 640# - 10 20 10 30 Ne 23280.117 253.250 7034.531 8.442 B- 14805.448 253.295 30 024992.235 271.875 - 8 19 11 30 Na 8474.670 4.727 7501.968 0.158 B- 17358.490 5.850 30 009097.932 5.074 - 6 18 12 30 Mg x -8883.820 3.447 8054.506 0.115 B- 6981.024 4.496 29 990462.826 3.700 - 4 17 13 30 Al x -15864.844 2.888 8261.128 0.096 B- 8568.116 2.888 29 982968.388 3.100 - 2 16 14 30 Si -n -24432.960 0.022 8520.654 0.001 B- -4232.106 0.061 29 973770.136 0.023 - 0 15 15 30 P - -20200.854 0.065 8353.506 0.002 B- -6141.601 0.196 29 978313.489 0.069 - -2 14 16 30 S - -14059.253 0.206 8122.707 0.007 B- -18502# 196# 29 984906.769 0.221 - -4 13 17 30 Cl x 4443# 196# 7480# 7# B- -16488# 284# 30 004770# 210# - -6 12 18 30 Ar -pp 20931.147 206.155 6904.204 6.872 B- * 30 022470.511 221.316 -0 13 22 9 31 F -nn 56143# 546# 6033# 18# B- 24961# 608# 31 060272# 587# - 11 21 10 31 Ne 31181.591 266.195 6813.090 8.587 B- 18935.559 266.562 31 033474.816 285.772 - 9 20 11 31 Na x 12246.031 13.972 7398.677 0.451 B- 15368.182 14.307 31 013146.656 15.000 - 7 19 12 31 Mg x -3122.151 3.074 7869.188 0.099 B- 11828.555 3.801 30 996648.232 3.300 - 5 18 13 31 Al x -14950.706 2.236 8225.517 0.072 B- 7998.330 2.236 30 983949.756 2.400 - 3 17 14 31 Si -n -22949.036 0.043 8458.291 0.001 B- 1491.505 0.043 30 975363.194 0.046 - 1 16 15 31 P -24440.54095 0.00067 8481.167 0.000 B- -5398.016 0.229 30 973761.99863 0.00072 - -1 15 16 31 S -19042.525 0.229 8281.800 0.007 B- -12007.974 3.454 30 979557.007 0.246 - -3 14 17 31 Cl -- -7034.551 3.447 7869.209 0.111 B- -18360# 200# 30 992448.098 3.700 - -5 13 18 31 Ar - 11325# 200# 7252# 6# B- * 31 012158# 215# -0 12 22 10 32 Ne x 36999# 503# 6671# 16# B- 18359# 504# 32 039720# 540# - 10 21 11 32 Na x 18640.151 37.260 7219.881 1.164 B- 19469.051 37.402 32 020011.026 40.000 - 8 20 12 32 Mg x -828.900 3.260 7803.840 0.102 B- 10270.467 7.879 31 999110.139 3.500 - 6 19 13 32 Al x -11099.367 7.173 8100.344 0.224 B- 12978.319 7.179 31 988084.339 7.700 - 4 18 14 32 Si x -24077.686 0.298 8481.468 0.009 B- 227.188 0.301 31 974151.539 0.320 - 2 17 15 32 P -n -24304.874 0.040 8464.120 0.001 B- 1710.660 0.040 31 973907.643 0.042 - 0 16 16 32 S -26015.53355 0.00132 8493.129 0.000 B- -12680.860 0.562 31 972071.17443 0.00141 - -2 15 17 32 Cl -13334.674 0.562 8072.404 0.018 B- -11134.323 1.857 31 985684.637 0.603 - -4 14 18 32 Ar x -2200.351 1.770 7700.008 0.055 B- -23299# 401# 31 997637.826 1.900 - -6 13 19 32 K x 21098# 401# 6947# 13# B- * 32 022650# 430# -0 13 23 10 33 Ne x 45997# 596# 6440# 18# B- 22217# 747# 33 049380# 640# - 11 22 11 33 Na x 23780.110 449.912 7089.926 13.634 B- 18817.813 449.921 33 025529.000 483.000 - 9 21 12 33 Mg x 4962.297 2.888 7636.455 0.088 B- 13459.677 7.559 33 005327.245 3.100 - 7 20 13 33 Al x -8497.380 6.986 8020.616 0.212 B- 12016.945 7.021 32 990877.687 7.500 - 5 19 14 33 Si x -20514.325 0.699 8361.059 0.021 B- 5823.021 1.295 32 977976.964 0.750 - 3 18 15 33 P + -26337.346 1.090 8513.806 0.033 B- 248.508 1.090 32 971725.694 1.170 - 1 17 16 33 S -26585.85434 0.00135 8497.630 0.000 B- -5582.517 0.391 32 971458.90985 0.00145 - -1 16 17 33 Cl -21003.337 0.391 8304.755 0.012 B- -11619.044 0.560 32 977451.989 0.419 - -3 15 18 33 Ar x -9384.292 0.401 7928.955 0.012 B- -16426# 196# 32 989925.547 0.430 - -5 14 19 33 K x 7042# 196# 7407# 6# B- * 33 007560# 210# -0 14 24 10 34 Ne -nn 52842# 513# 6287# 15# B- 21161# 789# 34 056728# 551# - 12 23 11 34 Na x 31680.111 599.416 6886.437 17.630 B- 23356.764 600.112 34 034010.000 643.500 - 10 22 12 34 Mg x 8323.348 28.876 7550.390 0.849 B- 11323.637 29.039 34 008935.481 31.000 - 8 21 13 34 Al x -3000.289 3.074 7860.428 0.090 B- 16956.563 14.448 33 996779.057 3.300 - 6 20 14 34 Si +pp -19956.852 14.118 8336.141 0.415 B- 4591.847 14.141 33 978575.437 15.155 - 4 19 15 34 P x -24548.698 0.810 8448.185 0.024 B- 5382.987 0.812 33 973645.887 0.870 - 2 18 16 34 S -29931.685 0.045 8583.498 0.001 B- -5491.603 0.038 33 967867.012 0.047 - 0 17 17 34 Cl -24440.082 0.049 8398.970 0.001 B- -6061.792 0.063 33 973762.491 0.052 - -2 16 18 34 Ar -18378.290 0.078 8197.672 0.002 B- -17158# 196# 33 980270.093 0.083 - -4 15 19 34 K x -1220# 196# 7670# 6# B- -15072# 357# 33 998690# 210# - -6 14 20 34 Ca x 13851# 298# 7204# 9# B- * 34 014870# 320# -0 13 24 11 35 Na -n 38231# 670# 6733# 19# B- 22592# 723# 35 041043# 720# - 11 23 12 35 Mg x 15639.784 269.668 7356.233 7.705 B- 15863.512 269.768 35 016790.000 289.500 - 9 22 13 35 Al x -223.728 7.359 7787.124 0.210 B- 14167.729 36.605 34 999759.817 7.900 - 7 21 14 35 Si 2p-n -14391.457 35.857 8169.563 1.024 B- 10466.342 35.905 34 984550.134 38.494 - 5 20 15 35 P +p -24857.799 1.866 8446.249 0.053 B- 3988.407 1.867 34 973314.053 2.003 - 3 19 16 35 S -28846.206 0.040 8537.850 0.001 B- 167.322 0.026 34 969032.322 0.043 - 1 18 17 35 Cl -29013.528 0.035 8520.278 0.001 B- -5966.243 0.679 34 968852.694 0.038 - -1 17 18 35 Ar - -23047.284 0.680 8327.461 0.019 B- -11874.394 0.852 34 975257.721 0.730 - -3 16 19 35 K 4n -11172.891 0.512 7965.840 0.015 B- -15961# 196# 34 988005.407 0.550 - -5 15 20 35 Ca x 4788# 196# 7487# 6# B- * 35 005140# 210# -0 14 25 11 36 Na -n 46303# 678# 6546# 19# B- 25923# 967# 36 049708# 728# - 12 24 12 36 Mg x 20380.157 690.237 7244.419 19.173 B- 14429.774 706.243 36 021879.000 741.000 - 10 23 13 36 Al x 5950.384 149.505 7623.515 4.153 B- 18386.508 165.851 36 006388.000 160.500 - 8 22 14 36 Si x -12436.124 71.797 8112.519 1.994 B- 7814.911 72.985 35 986649.271 77.077 - 6 21 15 36 P + -20251.034 13.114 8307.868 0.364 B- 10413.096 13.112 35 978259.619 14.078 - 4 20 16 36 S -30664.131 0.188 8575.389 0.005 B- -1142.126 0.189 35 967080.699 0.201 - 2 19 17 36 Cl -29522.005 0.036 8521.931 0.001 B- 709.535 0.045 35 968306.822 0.038 - 0 18 18 36 Ar -30231.540 0.027 8519.909 0.001 B- -12814.475 0.342 35 967545.105 0.028 - -2 17 19 36 K -17417.065 0.341 8142.219 0.009 B- -10965.916 40.001 35 981302.010 0.366 - -4 16 20 36 Ca 4n -6451.149 40.000 7815.879 1.111 B- -21802# 301# 35 993074.406 42.941 - -6 15 21 36 Sc x 15351# 298# 7189# 8# B- * 36 016480# 320# -0 15 26 11 37 Na -nn 53534# 687# 6392# 19# B- 25323# 980# 37 057471# 737# - 13 25 12 37 Mg -n 28211.474 698.947 7055.111 18.890 B- 18401.911 721.814 37 030286.265 750.350 - 11 24 13 37 Al x 9809.563 180.244 7531.315 4.871 B- 16381.075 213.168 37 010531.000 193.500 - 9 23 14 37 Si x -6571.511 113.809 7952.903 3.076 B- 12424.486 119.969 36 992945.191 122.179 - 7 22 15 37 P p-2n -18995.998 37.948 8267.555 1.026 B- 7900.419 37.947 36 979606.956 40.738 - 5 21 16 37 S -n -26896.417 0.198 8459.935 0.005 B- 4865.121 0.196 36 971125.507 0.212 - 3 20 17 37 Cl -31761.538 0.052 8570.281 0.001 B- -813.873 0.200 36 965902.584 0.055 - 1 19 18 37 Ar - -30947.664 0.207 8527.139 0.006 B- -6147.465 0.227 36 966776.314 0.221 - -1 18 19 37 K -p -24800.199 0.094 8339.847 0.003 B- -11664.133 0.641 36 973375.889 0.100 - -3 17 20 37 Ca x -13136.066 0.634 8003.456 0.017 B- -16656# 300# 36 985897.852 0.680 - -5 16 21 37 Sc x 3520# 300# 7532# 8# B- * 37 003779# 322# -0 14 26 12 38 Mg x 34074# 503# 6928# 13# B- 17864# 627# 38 036580# 540# - 12 25 13 38 Al x 16209.859 374.461 7377.097 9.854 B- 20380.157 388.847 38 017402.000 402.000 - 10 24 14 38 Si x -4170.299 104.793 7892.829 2.758 B- 10451.265 127.474 37 995523.000 112.500 - 8 23 15 38 P x -14621.563 72.581 8147.274 1.910 B- 12239.640 72.934 37 984303.105 77.918 - 6 22 16 38 S + -26861.203 7.172 8448.782 0.189 B- 2936.900 7.171 37 971163.310 7.699 - 4 21 17 38 Cl -n -29798.103 0.098 8505.481 0.003 B- 4916.718 0.218 37 968010.418 0.105 - 2 20 18 38 Ar -34714.821 0.195 8614.280 0.005 B- -5914.066 0.045 37 962732.104 0.209 - 0 19 19 38 K -28800.755 0.195 8438.058 0.005 B- -6742.256 0.063 37 969081.116 0.209 - -2 18 20 38 Ca -22058.499 0.194 8240.043 0.005 B- -17809# 200# 37 976319.226 0.208 - -4 17 21 38 Sc x -4249# 200# 7751# 5# B- -15119# 361# 37 995438# 215# - -6 16 22 38 Ti x 10870# 300# 7332# 8# B- * 38 011669# 322# -0 15 27 12 39 Mg -n 42275# 513# 6747# 13# B- 21625# 650# 39 045384# 551# - 13 26 13 39 Al x 20650# 400# 7281# 10# B- 18330# 422# 39 022169# 429# - 11 25 14 39 Si x 2320.352 135.532 7730.979 3.475 B- 15094.986 176.232 39 002491.000 145.500 - 9 24 15 39 P x -12774.634 112.645 8097.969 2.888 B- 10388.033 123.243 38 986285.865 120.929 - 7 23 16 39 S 2p-n -23162.667 50.000 8344.269 1.282 B- 6637.538 50.030 38 975133.852 53.677 - 5 22 17 39 Cl -nn -29800.205 1.732 8494.402 0.044 B- 3441.985 5.292 38 968008.162 1.859 - 3 21 18 39 Ar + -33242.190 5.000 8562.598 0.128 B- 565.000 5.000 38 964313.039 5.367 - 1 20 19 39 K -33807.19010 0.00458 8557.025 0.000 B- -6524.488 0.596 38 963706.48661 0.00492 - -1 19 20 39 Ca -27282.702 0.596 8369.670 0.015 B- -13109.993 24.007 38 970710.813 0.640 - -3 18 21 39 Sc 2n-p -14172.709 24.000 8013.456 0.615 B- -16373# 202# 38 984784.970 25.765 - -5 17 22 39 Ti x 2200# 200# 7574# 5# B- * 39 002362# 215# -0 16 28 12 40 Mg x 48350# 500# 6628# 13# B- 20760# 640# 40 051906# 537# - 14 27 13 40 Al x 27590# 400# 7127# 10# B- 22160# 528# 40 029619# 429# - 12 26 14 40 Si x 5429.679 345.119 7661.754 8.628 B- 13544.049 377.749 40 005829.000 370.500 - 10 25 15 40 P x -8114.370 153.582 7980.796 3.840 B- 14723.476 153.633 39 991288.865 164.876 - 8 24 16 40 S -22837.846 3.982 8329.325 0.100 B- 4719.967 32.312 39 975482.562 4.274 - 6 23 17 40 Cl + -27557.813 32.066 8427.765 0.802 B- 7482.082 32.066 39 970415.469 34.423 - 4 22 18 40 Ar -35039.89464 0.00224 8595.259 0.000 B- -1504.403 0.056 39 962383.12378 0.00240 - 2 21 19 40 K -33535.492 0.056 8538.090 0.001 B- 1310.893 0.060 39 963998.166 0.060 - 0 20 20 40 Ca -34846.384 0.021 8551.303 0.001 B- -14323.050 2.828 39 962590.865 0.022 - -2 19 21 40 Sc - -20523.335 2.828 8173.669 0.071 B- -11672.950 160.025 39 977967.292 3.036 - -4 18 22 40 Ti -- -8850.384 160.000 7862.286 4.000 B- -21020# 340# 39 990498.721 171.767 - -6 17 23 40 V x 12170# 300# 7317# 7# B- * 40 013065# 322# -0 15 28 13 41 Al x 33420# 500# 7008# 12# B- 21300# 747# 41 035878# 537# - 13 27 14 41 Si x 12119.668 554.705 7508.573 13.529 B- 17099.435 567.571 41 013011.000 595.500 - 11 26 15 41 P x -4979.767 120.163 7906.551 2.931 B- 14028.810 120.233 40 994654.000 129.000 - 9 25 16 41 S x -19008.577 4.099 8229.635 0.100 B- 8298.611 68.846 40 979593.451 4.400 - 7 24 17 41 Cl x -27307.189 68.723 8412.959 1.676 B- 5760.317 68.724 40 970684.525 73.777 - 5 23 18 41 Ar -n -33067.505 0.347 8534.372 0.008 B- 2492.038 0.347 40 964500.571 0.372 - 3 22 19 41 K -35559.54331 0.00380 8576.072 0.000 B- -421.653 0.138 40 961825.25796 0.00408 - 1 21 20 41 Ca -35137.890 0.138 8546.706 0.003 B- -6495.478 0.158 40 962277.921 0.147 - -1 20 21 41 Sc -28642.412 0.083 8369.198 0.002 B- -12944.875 27.945 40 969251.104 0.088 - -3 19 22 41 Ti x -15697.537 27.945 8034.388 0.682 B- -16018# 202# 40 983148.000 30.000 - -5 18 23 41 V x 320# 200# 7625# 5# B- * 41 000344# 215# -0 16 29 13 42 Al x 40100# 600# 6874# 14# B- 23630# 781# 42 043049# 644# - 14 28 14 42 Si x 16470# 500# 7418# 12# B- 15460# 591# 42 017681# 537# - 12 27 15 42 P x 1009.740 314.379 7767.866 7.485 B- 18647.485 314.392 42 001084.000 337.500 - 10 26 16 42 S x -17637.746 2.794 8193.227 0.067 B- 7194.021 59.681 41 981065.100 3.000 - 8 25 17 42 Cl x -24831.767 59.616 8345.886 1.419 B- 9590.908 59.895 41 973342.000 64.000 - 6 24 18 42 Ar x -34422.675 5.775 8555.613 0.138 B- 599.351 5.776 41 963045.736 6.200 - 4 23 19 42 K -n -35022.026 0.106 8551.256 0.003 B- 3525.219 0.183 41 962402.306 0.113 - 2 22 20 42 Ca -38547.245 0.149 8616.563 0.004 B- -6426.092 0.097 41 958617.828 0.159 - 0 21 21 42 Sc -32121.153 0.169 8444.933 0.004 B- -7016.479 0.224 41 965516.522 0.181 - -2 20 22 42 Ti -25104.674 0.277 8259.247 0.007 B- -17485# 196# 41 973049.022 0.297 - -4 19 23 42 V x -7620# 196# 7824# 5# B- -14350# 445# 41 991820# 210# - -6 18 24 42 Cr x 6730# 400# 7464# 10# B- * 42 007225# 429# -0 17 30 13 43 Al x 47020# 800# 6741# 19# B- 23919# 998# 43 050478# 859# - 15 29 14 43 Si x 23101# 596# 7279# 14# B- 18421# 814# 43 024800# 640# - 13 28 15 43 P x 4679.826 554.705 7689.572 12.900 B- 16875.285 554.727 43 005024.000 595.500 - 11 27 16 43 S x -12195.459 4.970 8063.827 0.116 B- 11964.049 62.058 42 986907.635 5.335 - 9 26 17 43 Cl x -24159.508 61.858 8323.866 1.439 B- 7850.300 62.086 42 974063.700 66.407 - 7 25 18 43 Ar x -32009.808 5.310 8488.237 0.123 B- 4565.581 5.325 42 965636.055 5.700 - 5 24 19 43 K -4n -36575.389 0.410 8576.220 0.010 B- 1833.434 0.469 42 960734.703 0.440 - 3 23 20 43 Ca -38408.822 0.228 8600.663 0.005 B- -2220.720 1.865 42 958766.430 0.244 - 1 22 21 43 Sc -p -36188.102 1.863 8530.825 0.043 B- -6867.020 7.481 42 961150.472 1.999 - -1 21 22 43 Ti -n2p -29321.082 7.245 8352.932 0.168 B- -11404.726 43.457 42 968522.521 7.777 - -3 20 23 43 V x -17916.356 42.849 8069.512 0.996 B- -15946# 402# 42 980766.000 46.000 - -5 19 24 43 Cr x -1970# 400# 7680# 9# B- * 42 997885# 429# -0 16 30 14 44 Si x 28513# 596# 7174# 14# B- 18063# 778# 44 030610# 640# - 14 29 15 44 P x 10450# 500# 7567# 11# B- 19655# 500# 44 011219# 537# - 12 28 16 44 S x -9204.233 5.216 7996.015 0.119 B- 11180.290 136.421 43 990118.848 5.600 - 10 27 17 44 Cl x -20384.523 136.321 8232.332 3.098 B- 12288.731 136.330 43 978116.312 146.346 - 8 26 18 44 Ar x -32673.255 1.584 8493.840 0.036 B- 3108.237 1.638 43 964923.816 1.700 - 6 25 19 44 K x -35781.492 0.419 8546.701 0.010 B- 5687.183 0.530 43 961586.986 0.450 - 4 24 20 44 Ca -41468.675 0.325 8658.175 0.007 B- -3652.690 1.757 43 955481.543 0.348 - 2 23 21 44 Sc -p -37815.985 1.756 8557.379 0.040 B- -267.416 1.890 43 959402.867 1.884 - 0 22 22 44 Ti -a -37548.569 0.700 8533.520 0.016 B- -13432.189 181.643 43 959689.951 0.751 - -2 21 23 44 V x -24116.380 181.641 8210.463 4.128 B- -10756# 351# 43 974110.000 195.000 - -4 20 24 44 Cr x -13360# 300# 7948# 7# B- -20390# 583# 43 985657# 322# - -6 19 25 44 Mn x 7030# 500# 7467# 11# B- * 44 007547# 537# -0 17 31 14 45 Si x 37490# 700# 6995# 16# B- 21890# 860# 45 040247# 751# - 15 30 15 45 P x 15600# 500# 7464# 11# B- 19589# 1150# 45 016747# 537# - 13 29 16 45 S x -3989.589 1035.356 7881.807 23.008 B- 14272.954 1044.271 44 995717.000 1111.500 - 11 28 17 45 Cl x -18262.543 136.163 8181.598 3.026 B- 11508.254 136.164 44 980394.353 146.177 - 9 27 18 45 Ar x -29770.796 0.512 8419.952 0.011 B- 6844.841 0.731 44 968039.733 0.550 - 7 26 19 45 K x -36615.638 0.522 8554.674 0.012 B- 4196.536 0.637 44 960691.493 0.560 - 5 25 20 45 Ca -40812.174 0.366 8630.545 0.008 B- 259.722 0.747 44 956186.326 0.392 - 3 24 21 45 Sc -41071.896 0.675 8618.931 0.015 B- -2062.056 0.509 44 955907.503 0.724 - 1 23 22 45 Ti -39009.840 0.845 8555.722 0.019 B- -7123.824 0.214 44 958121.211 0.907 - -1 22 23 45 V -31886.016 0.872 8380.029 0.019 B- -12371.217 35.408 44 965768.951 0.935 - -3 21 24 45 Cr x -19514.799 35.397 8087.728 0.787 B- -14265# 401# 44 979050.000 38.000 - -5 20 25 45 Mn x -5250# 400# 7753# 9# B- -19012# 565# 44 994364# 429# - -7 19 26 45 Fe -pp 13762# 400# 7313# 9# B- * 45 014774# 429# -0 16 31 15 46 P x 22970# 700# 7317# 15# B- 22630# 860# 46 024659# 751# - 14 30 16 46 S x 340# 500# 7792# 11# B- 14199# 542# 46 000365# 537# - 12 29 17 46 Cl x -13859.398 208.661 8083.480 4.536 B- 15913.528 208.664 45 985121.323 224.006 - 10 28 18 46 Ar x -29772.926 1.118 8412.419 0.024 B- 5640.997 1.333 45 968037.446 1.200 - 8 27 19 46 K x -35413.924 0.727 8518.042 0.016 B- 7725.438 2.350 45 961981.586 0.780 - 6 26 20 46 Ca -43139.361 2.235 8668.979 0.049 B- -1378.143 2.333 45 953687.988 2.399 - 4 25 21 46 Sc -n -41761.219 0.683 8622.012 0.015 B- 2366.581 0.667 45 955167.485 0.732 - 2 24 22 46 Ti -44127.799 0.165 8656.451 0.004 B- -7052.449 0.093 45 952626.856 0.176 - 0 23 23 46 V -37075.351 0.202 8486.130 0.004 B- -7603.784 11.455 45 960197.971 0.216 - -2 22 24 46 Cr -29471.567 11.453 8303.823 0.249 B- -16902# 400# 45 968360.970 12.295 - -4 21 25 46 Mn x -12570# 400# 7919# 9# B- -13480# 640# 45 986506# 429# - -6 20 26 46 Fe x 910# 500# 7609# 11# B- * 46 000977# 537# -0 17 32 15 47 P x 29710# 800# 7190# 17# B- 22340# 944# 47 031895# 859# - 15 31 16 47 S x 7370# 500# 7648# 11# B- 17150# 640# 47 007912# 537# - 13 30 17 47 Cl x -9780# 400# 7996# 9# B- 15587# 400# 46 989501# 429# - 11 29 18 47 Ar x -25366.338 1.118 8311.404 0.024 B- 10345.638 1.789 46 972768.114 1.200 - 9 28 19 47 K x -35711.976 1.397 8514.879 0.030 B- 6632.442 2.625 46 961661.614 1.500 - 7 27 20 47 Ca -42344.418 2.222 8639.349 0.047 B- 1992.177 1.185 46 954541.394 2.385 - 5 26 21 47 Sc -44336.595 1.933 8665.090 0.041 B- 600.769 1.929 46 952402.704 2.074 - 3 25 22 47 Ti -44937.364 0.115 8661.227 0.002 B- -2930.746 0.138 46 951757.752 0.123 - 1 24 23 47 V -42006.618 0.169 8582.225 0.004 B- -7444.040 6.032 46 954904.038 0.181 - -1 23 24 47 Cr -34562.578 6.030 8407.195 0.128 B- -11996.204 32.240 46 962895.544 6.473 - -3 22 25 47 Mn x -22566.374 31.671 8135.311 0.674 B- -15697# 501# 46 975774.000 34.000 - -5 21 26 47 Fe x -6870# 500# 7785# 11# B- -17240# 781# 46 992625# 537# - -7 20 27 47 Co x 10370# 600# 7401# 13# B- * 47 011133# 644# -0 16 32 16 48 S x 12761# 596# 7545# 12# B- 17042# 778# 48 013700# 640# - 14 31 17 48 Cl x -4280# 500# 7883# 10# B- 18001# 587# 47 995405# 537# - 12 30 18 48 Ar x -22281.337 307.393 8242.132 6.404 B- 10003.140 307.394 47 976080.000 330.000 - 10 29 19 48 K x -32284.477 0.773 8434.232 0.016 B- 11940.153 0.779 47 965341.186 0.830 - 8 28 20 48 Ca -44224.629 0.096 8666.686 0.002 B- 279.213 4.950 47 952522.904 0.103 - 6 27 21 48 Sc -44503.842 4.951 8656.204 0.103 B- 3988.866 4.950 47 952223.157 5.314 - 4 26 22 48 Ti -48492.709 0.109 8723.006 0.002 B- -4015.015 0.969 47 947940.932 0.117 - 2 25 23 48 V -44477.694 0.975 8623.061 0.020 B- -1655.673 7.388 47 952251.229 1.046 - 0 24 24 48 Cr +nn -42822.020 7.324 8572.269 0.153 B- -13525.682 10.087 47 954028.667 7.862 - -2 23 25 48 Mn -29296.338 6.939 8274.185 0.145 B- -11296# 400# 47 968549.085 7.449 - -4 22 26 48 Fe x -18000# 400# 8023# 8# B- -19500# 640# 47 980676# 429# - -6 21 27 48 Co x 1500# 500# 7600# 10# B- -15293# 708# 48 001610# 537# - -8 20 28 48 Ni -pp 16793# 502# 7265# 10# B- * 48 018028# 538# -0 17 33 16 49 S -n 21093# 667# 7385# 14# B- 20153# 897# 49 022644# 716# - 15 32 17 49 Cl x 940# 600# 7781# 12# B- 18130# 721# 49 001009# 644# - 13 31 18 49 Ar x -17190# 400# 8135# 8# B- 12422# 400# 48 981546# 429# - 11 30 19 49 K x -29611.490 0.801 8372.274 0.016 B- 11688.275 0.826 48 968210.755 0.860 - 9 29 20 49 Ca -n -41299.765 0.201 8594.844 0.004 B- 5261.500 2.702 48 955662.875 0.216 - 7 28 21 49 Sc -46561.265 2.698 8686.256 0.055 B- 2002.522 2.697 48 950014.423 2.896 - 5 27 22 49 Ti -48563.787 0.114 8711.157 0.002 B- -601.856 0.820 48 947864.627 0.122 - 3 26 23 49 V - -47961.931 0.828 8682.908 0.017 B- -2628.871 2.391 48 948510.746 0.889 - 1 25 24 49 Cr -45333.060 2.243 8613.291 0.046 B- -7712.426 0.233 48 951332.955 2.407 - -1 24 25 49 Mn -37620.634 2.255 8439.929 0.046 B- -12869.907 24.324 48 959612.585 2.420 - -3 23 26 49 Fe x -24750.727 24.219 8161.311 0.494 B- -14870# 501# 48 973429.000 26.000 - -5 22 27 49 Co x -9880# 500# 7842# 10# B- -18080# 781# 48 989393# 537# - -7 21 28 49 Ni x 8200# 600# 7457# 12# B- * 49 008803# 644# -0 16 33 17 50 Cl x 7740# 600# 7651# 12# B- 21069# 781# 50 008309# 644# - 14 32 18 50 Ar x -13330# 500# 8056# 10# B- 12398# 500# 49 985690# 537# - 12 31 19 50 K x -25727.848 7.731 8288.582 0.155 B- 13861.376 7.892 49 972380.017 8.300 - 10 30 20 50 Ca x -39589.224 1.584 8550.163 0.032 B- 4958.158 15.084 49 957499.217 1.700 - 8 29 21 50 Sc -pn -44547.382 15.000 8633.679 0.300 B- 6884.278 15.000 49 952176.415 16.103 - 6 28 22 50 Ti -51431.660 0.121 8755.718 0.002 B- -2207.647 0.426 49 944785.839 0.129 - 4 27 23 50 V +n -49224.013 0.409 8695.918 0.008 B- 1038.059 0.299 49 947155.845 0.438 - 2 26 24 50 Cr -50262.072 0.437 8701.032 0.009 B- -7634.477 0.067 49 946041.443 0.468 - 0 25 25 50 Mn -42627.595 0.442 8532.696 0.009 B- -8151.139 8.395 49 954237.391 0.474 - -2 24 26 50 Fe x -34476.456 8.383 8354.026 0.168 B- -16846# 400# 49 962988.000 9.000 - -4 23 27 50 Co x -17630# 400# 8001# 8# B- -13510# 640# 49 981073# 429# - -6 22 28 50 Ni x -4120# 500# 7716# 10# B- * 49 995577# 537# -0 17 34 17 51 Cl x 14290# 700# 7530# 14# B- 20980# 922# 51 015341# 751# - 15 33 18 51 Ar x -6690# 600# 7926# 12# B- 15826# 600# 50 992818# 644# - 13 32 19 51 K x -22516.196 13.047 8221.349 0.256 B- 13816.107 13.057 50 975827.867 14.006 - 11 31 20 51 Ca x -36332.304 0.522 8476.913 0.010 B- 6896.381 20.007 50 960995.665 0.560 - 9 30 21 51 Sc -p2n -43228.684 20.000 8596.796 0.392 B- 6504.153 20.006 50 953592.095 21.471 - 7 29 22 51 Ti -n -49732.837 0.505 8708.988 0.010 B- 2471.005 0.644 50 946609.600 0.541 - 5 28 23 51 V -52203.842 0.401 8742.099 0.008 B- -752.447 0.213 50 943956.867 0.430 - 3 27 24 51 Cr -51451.395 0.400 8712.005 0.008 B- -3207.518 0.346 50 944764.652 0.429 - 1 26 25 51 Mn -48243.877 0.502 8633.772 0.010 B- -8041.321 8.977 50 948208.065 0.539 - -1 25 26 51 Fe -40202.555 8.964 8460.759 0.176 B- -12860.412 49.260 50 956840.779 9.623 - -3 24 27 51 Co x -27342.143 48.438 8193.254 0.950 B- -15442# 503# 50 970647.000 52.000 - -5 23 28 51 Ni x -11900# 500# 7875# 10# B- * 50 987225# 537# -0 16 34 18 52 Ar x -1280# 600# 7825# 12# B- 15858# 601# 51 998626# 644# - 14 33 19 52 K x -17137.627 33.534 8115.029 0.645 B- 17128.639 33.540 51 981602.000 36.000 - 12 32 20 52 Ca x -34266.266 0.671 8429.381 0.013 B- 6177.013 81.855 51 963213.648 0.720 - 10 31 21 52 Sc x -40443.279 81.852 8533.125 1.574 B- 9026.541 82.157 51 956582.351 87.871 - 8 30 22 52 Ti -nn -49469.820 7.072 8691.667 0.136 B- 1973.948 7.085 51 946891.960 7.592 - 6 29 23 52 V -n -51443.769 0.420 8714.582 0.008 B- 3975.473 0.531 51 944772.839 0.450 - 4 28 24 52 Cr -55419.242 0.340 8775.989 0.007 B- -4711.958 1.851 51 940504.992 0.364 - 2 27 25 52 Mn -50707.284 1.845 8670.329 0.035 B- -2376.920 5.017 51 945563.488 1.980 - 0 26 26 52 Fe -48330.363 5.117 8609.574 0.098 B- -13969.413 9.822 51 948115.217 5.493 - -2 25 27 52 Co x -34360.951 8.383 8325.886 0.161 B- -12031# 400# 51 963112.000 9.000 - -4 24 28 52 Ni x -22330# 400# 8079# 8# B- -20049# 721# 51 976028# 429# - -6 23 29 52 Cu x -2280# 600# 7679# 12# B- * 51 997552# 644# -0 17 35 18 53 Ar x 6791# 699# 7677# 13# B- 19086# 708# 53 007290# 750# - 15 34 19 53 K x -12295.721 111.779 8022.848 2.109 B- 17091.983 120.047 52 986800.000 120.000 - 13 33 20 53 Ca x -29387.704 43.780 8330.577 0.826 B- 9519.104 103.774 52 968451.000 47.000 - 11 32 21 53 Sc x -38906.808 94.087 8495.421 1.775 B- 7924.253 137.339 52 958231.821 101.006 - 9 31 22 53 Ti + -46831.061 100.049 8630.174 1.888 B- 5020.000 100.000 52 949724.785 107.406 - 7 30 23 53 V +p -51851.061 3.120 8710.130 0.059 B- 3435.938 3.102 52 944335.593 3.349 - 5 29 24 53 Cr -55286.999 0.348 8760.198 0.007 B- -596.884 0.356 52 940646.961 0.373 - 3 28 25 53 Mn -54690.116 0.450 8734.175 0.009 B- -3742.586 1.686 52 941287.742 0.483 - 1 27 26 53 Fe -50947.530 1.656 8648.799 0.031 B- -8288.101 0.443 52 945305.574 1.777 - -1 26 27 53 Co -42659.428 1.713 8477.658 0.032 B- -13028.604 25.209 52 954203.217 1.839 - -3 25 28 53 Ni x -29630.824 25.150 8217.074 0.475 B- -16361# 501# 52 968190.000 27.000 - -5 24 29 53 Cu x -13270# 500# 7894# 9# B- * 52 985754# 537# -0 16 35 19 54 K x -5002# 596# 7889# 11# B- 20158# 598# 53 994630# 640# - 14 34 20 54 Ca x -25160.585 48.438 8247.496 0.897 B- 8730.315 277.066 53 972989.000 52.000 - 12 33 21 54 Sc x -33890.900 272.800 8394.681 5.052 B- 11731.081 284.990 53 963616.620 292.862 - 10 32 22 54 Ti x -45621.981 82.461 8597.435 1.527 B- 4271.192 83.815 53 951022.786 88.526 - 8 31 23 54 V + -49893.173 15.004 8662.043 0.278 B- 7041.592 15.000 53 946437.472 16.107 - 6 30 24 54 Cr -56934.765 0.353 8777.955 0.007 B- -1377.136 1.008 53 938878.012 0.378 - 4 29 25 54 Mn -p -55557.629 1.059 8737.965 0.020 B- 696.872 1.076 53 940356.429 1.136 - 2 28 26 54 Fe -56254.500 0.372 8736.382 0.007 B- -8244.547 0.089 53 939608.306 0.399 - 0 27 27 54 Co -48009.953 0.383 8569.217 0.007 B- -8731.646 4.673 53 948459.192 0.411 - -2 26 28 54 Ni x -39278.308 4.657 8393.032 0.086 B- -17868# 400# 53 957833.000 5.000 - -4 25 29 54 Cu x -21410# 400# 8048# 7# B- -15139# 565# 53 977015# 429# - -6 24 30 54 Zn -pp -6272# 400# 7753# 7# B- * 53 993267# 430# -0 17 36 19 55 K x 708# 699# 7788# 13# B- 19058# 760# 55 000760# 750# - 15 35 20 55 Ca x -18350# 300# 8120# 5# B- 11809# 544# 54 980300# 322# - 13 34 21 55 Sc x -30159.352 454.342 8320.955 8.261 B- 11508.735 482.226 54 967622.601 487.756 - 11 33 22 55 Ti -41668.088 161.602 8515.980 2.938 B- 7476.498 157.206 54 955267.465 173.486 - 9 32 23 55 V -49144.586 95.104 8637.692 1.729 B- 5965.125 95.103 54 947241.114 102.098 - 7 31 24 55 Cr -55109.710 0.399 8731.924 0.007 B- 2602.703 0.368 54 940837.289 0.428 - 5 30 25 55 Mn -57712.413 0.303 8765.022 0.006 B- -231.114 0.179 54 938043.172 0.325 - 3 29 26 55 Fe -57481.300 0.342 8746.595 0.006 B- -3451.417 0.324 54 938291.283 0.367 - 1 28 27 55 Co -54029.883 0.428 8669.618 0.008 B- -8694.034 0.578 54 941996.531 0.459 - -1 27 28 55 Ni - -45335.849 0.719 8497.320 0.013 B- -13700.449 155.561 54 951329.961 0.771 - -3 26 29 55 Cu x -31635.399 155.559 8233.996 2.828 B- -17065# 429# 54 966038.000 167.000 - -5 25 30 55 Zn x -14570# 400# 7909# 7# B- * 54 984358# 429# -0 18 37 19 56 K x 7927# 801# 7664# 14# B- 21825# 895# 56 008510# 860# - 16 36 20 56 Ca x -13898# 400# 8040# 7# B- 10954# 710# 55 985080# 429# - 14 35 21 56 Sc x -24852.260 586.841 8221.728 10.479 B- 14467.788 599.236 55 973320.000 630.000 - 12 34 22 56 Ti -39320.048 121.247 8466.110 2.165 B- 6834.833 194.550 55 957788.190 130.164 - 10 33 23 56 V -46154.881 176.898 8574.191 3.159 B- 9130.120 176.899 55 950450.694 189.907 - 8 32 24 56 Cr ++ -55285.001 0.603 8723.258 0.011 B- 1626.538 0.561 55 940649.107 0.647 - 6 31 25 56 Mn -n -56911.538 0.331 8738.333 0.006 B- 3695.544 0.207 55 938902.947 0.355 - 4 30 26 56 Fe -60607.082 0.302 8790.354 0.005 B- -4566.680 0.411 55 934935.617 0.324 - 2 29 27 56 Co -56040.402 0.493 8694.836 0.009 B- -2132.863 0.374 55 939838.150 0.529 - 0 28 28 56 Ni -53907.539 0.422 8642.779 0.008 B- -15264.511 14.910 55 942127.872 0.452 - -2 27 29 56 Cu x -38643.029 14.904 8356.227 0.266 B- -13253# 400# 55 958515.000 16.000 - -4 26 30 56 Zn x -25390# 400# 8106# 7# B- -22000# 640# 55 972743# 429# - -6 25 31 56 Ga x -3390# 500# 7699# 9# B- * 55 996361# 537# -0 17 37 20 57 Ca x -6874# 400# 7917# 7# B- 14121# 1364# 56 992620# 429# - 15 36 21 57 Sc x -20995.875 1304.092 8151.433 22.879 B- 12919.758 1329.062 56 977460.000 1400.000 - 13 35 22 57 Ti x -33915.633 256.417 8364.370 4.499 B- 10497.818 268.750 56 963590.068 275.274 - 11 34 23 57 V x -44413.450 80.479 8534.817 1.412 B- 8111.252 80.486 56 952320.197 86.397 - 9 33 24 57 Cr x -52524.702 1.068 8663.394 0.019 B- 4961.548 1.846 56 943612.409 1.146 - 7 32 25 57 Mn -57486.251 1.505 8736.713 0.026 B- 2695.589 1.526 56 938285.968 1.615 - 5 31 26 57 Fe -60181.839 0.304 8770.279 0.005 B- -836.276 0.451 56 935392.134 0.326 - 3 30 27 57 Co -59345.564 0.533 8741.882 0.009 B- -3261.731 0.642 56 936289.913 0.572 - 1 29 28 57 Ni -56083.833 0.582 8670.933 0.010 B- -8774.947 0.439 56 939791.525 0.624 - -1 28 29 57 Cu -47308.886 0.519 8503.262 0.009 B- -14759# 200# 56 949211.819 0.557 - -3 27 30 57 Zn x -32550# 200# 8231# 4# B- -17540# 447# 56 965056# 215# - -5 26 31 57 Ga x -15010# 400# 7909# 7# B- * 56 983886# 429# -0 18 38 20 58 Ca x -1919# 500# 7835# 9# B- 12957# 640# 57 997940# 537# - 16 37 21 58 Sc x -14876# 400# 8045# 7# B- 16234# 447# 57 984030# 429# - 14 36 22 58 Ti x -31110# 200# 8311# 3# B- 9292# 219# 57 966602# 215# - 12 35 23 58 V x -40401.753 89.374 8457.658 1.541 B- 11590.049 89.386 57 956626.932 95.947 - 10 34 24 58 Cr x -51991.801 1.490 8643.998 0.026 B- 3835.759 3.085 57 944184.502 1.600 - 8 33 25 58 Mn x -55827.560 2.701 8696.643 0.047 B- 6327.553 2.723 57 940066.646 2.900 - 6 32 26 58 Fe -62155.113 0.343 8792.250 0.006 B- -2307.955 1.139 57 933273.738 0.368 - 4 31 27 58 Co -59847.158 1.160 8738.969 0.020 B- 381.586 1.107 57 935751.429 1.245 - 2 30 28 58 Ni -60228.744 0.373 8732.059 0.006 B- -8561.019 0.443 57 935341.780 0.400 - 0 29 29 58 Cu -51667.725 0.578 8570.967 0.010 B- -9368.981 50.002 57 944532.413 0.621 - -2 28 30 58 Zn -- -42298.744 50.001 8395.944 0.862 B- -18759# 304# 57 954590.428 53.678 - -4 27 31 58 Ga x -23540# 300# 8059# 5# B- -16459# 583# 57 974729# 322# - -6 26 32 58 Ge x -7080# 500# 7762# 9# B- * 57 992399# 537# -0 17 38 21 59 Sc x -10302# 400# 7967# 7# B- 15208# 447# 58 988940# 429# - 15 37 22 59 Ti x -25510# 200# 8212# 3# B- 12322# 258# 58 972614# 215# - 13 36 23 59 V x -37832.015 161.874 8407.555 2.744 B- 10253.745 270.218 58 959385.659 173.778 - 11 35 24 59 Cr x -48085.760 216.367 8568.087 3.667 B- 7439.560 216.380 58 948377.810 232.279 - 9 34 25 59 Mn x -55525.320 2.329 8680.921 0.039 B- 5139.485 2.356 58 940391.113 2.500 - 7 33 26 59 Fe -60664.805 0.355 8754.771 0.006 B- 1564.903 0.369 58 934873.649 0.380 - 5 32 27 59 Co -62229.709 0.418 8768.035 0.007 B- -1073.002 0.194 58 933193.656 0.448 - 3 31 28 59 Ni -61156.707 0.374 8736.588 0.006 B- -4798.380 0.397 58 934345.571 0.402 - 1 30 29 59 Cu -56358.327 0.544 8642.000 0.009 B- -9142.775 0.602 58 939496.844 0.584 - -1 29 30 59 Zn -47215.551 0.771 8473.777 0.013 B- -13455# 170# 58 949312.017 0.827 - -3 28 31 59 Ga x -33760# 170# 8232# 3# B- -17890# 434# 58 963757# 183# - -5 27 32 59 Ge x -15870# 400# 7916# 7# B- * 58 982963# 429# -0 18 39 21 60 Sc x -4052# 500# 7865# 8# B- 18278# 583# 59 995650# 537# - 16 38 22 60 Ti x -22330# 300# 8157# 5# B- 10912# 372# 59 976028# 322# - 14 37 23 60 V x -33241.956 220.159 8325.450 3.669 B- 13427.621 293.169 59 964313.290 236.350 - 12 36 24 60 Cr x -46669.576 193.593 8536.205 3.227 B- 6298.361 193.607 59 949898.146 207.830 - 10 35 25 60 Mn x -52967.938 2.329 8628.138 0.039 B- 8445.079 4.128 59 943136.576 2.500 - 8 34 26 60 Fe -nn -61413.017 3.409 8755.851 0.057 B- 237.293 3.411 59 934070.411 3.659 - 6 33 27 60 Co -n -61650.309 0.424 8746.766 0.007 B- 2822.809 0.212 59 933815.667 0.455 - 4 32 28 60 Ni -64473.118 0.376 8780.774 0.006 B- -6127.982 1.573 59 930785.256 0.403 - 2 31 29 60 Cu - -58345.137 1.618 8665.602 0.027 B- -4170.797 1.629 59 937363.916 1.736 - 0 30 30 60 Zn -54174.340 0.564 8583.050 0.009 B- -14584# 200# 59 941841.450 0.605 - -2 29 31 60 Ga x -39590# 200# 8327# 3# B- -12501# 361# 59 957498# 215# - -4 28 32 60 Ge x -27090# 300# 8106# 5# B- -21620# 500# 59 970918# 322# - -6 27 33 60 As x -5470# 400# 7732# 7# B- * 59 994128# 429# -0 19 40 21 61 Sc x 931# 600# 7787# 10# B- 17281# 721# 61 001000# 644# - 17 39 22 61 Ti x -16350# 400# 8057# 7# B- 14157# 979# 60 982448# 429# - 15 38 23 61 V x -30506.429 894.234 8276.439 14.660 B- 11968.800 899.958 60 967250.000 960.000 - 13 37 24 61 Cr x -42475.229 101.341 8459.824 1.661 B- 9266.893 101.367 60 954400.963 108.793 - 11 36 25 61 Mn x -51742.122 2.329 8598.915 0.038 B- 7178.372 3.497 60 944452.544 2.500 - 9 35 26 61 Fe x -58920.494 2.608 8703.768 0.043 B- 3977.572 2.742 60 936746.244 2.800 - 7 34 27 61 Co p2n -62898.066 0.846 8756.148 0.014 B- 1323.839 0.790 60 932476.145 0.908 - 5 33 28 61 Ni -64221.905 0.378 8765.025 0.006 B- -2237.845 0.966 60 931054.945 0.405 - 3 32 29 61 Cu p2n -61984.059 0.953 8715.514 0.016 B- -5635.156 15.903 60 933457.371 1.023 - 1 31 30 61 Zn -56348.903 15.899 8610.309 0.261 B- -9214.245 37.679 60 939506.960 17.068 - -1 30 31 61 Ga -47134.659 37.994 8446.431 0.623 B- -13775# 302# 60 949398.859 40.787 - -3 29 32 61 Ge x -33360# 300# 8208# 5# B- -16459# 424# 60 964187# 322# - -5 28 33 61 As x -16900# 300# 7925# 5# B- * 60 981857# 322# -0 18 40 22 62 Ti x -12500# 400# 7995# 6# B- 12977# 499# 61 986581# 429# - 16 39 23 62 V x -25476# 298# 8192# 5# B- 15419# 333# 61 972650# 320# - 14 38 24 62 Cr x -40894.961 148.099 8428.069 2.389 B- 7628.996 148.244 61 956097.451 158.991 - 12 37 25 62 Mn IT -48523.957 6.542 8538.499 0.106 B- 10354.091 7.114 61 947907.386 7.023 - 10 36 26 62 Fe x -58878.048 2.794 8692.882 0.045 B- 2546.235 18.784 61 936791.812 3.000 - 8 35 27 62 Co + -61424.282 18.575 8721.332 0.300 B- 5322.040 18.570 61 934058.317 19.940 - 6 34 28 62 Ni -66746.323 0.439 8794.553 0.007 B- -3958.896 0.475 61 928344.871 0.470 - 4 33 29 62 Cu - -62787.426 0.647 8718.081 0.010 B- -1619.455 0.651 61 932594.921 0.694 - 2 32 30 62 Zn -61167.972 0.625 8679.343 0.010 B- -9181.066 0.376 61 934333.477 0.670 - 0 31 31 62 Ga -51986.906 0.647 8518.642 0.010 B- -10247# 140# 61 944189.757 0.694 - -2 30 32 62 Ge x -41740# 140# 8341# 2# B- -17420# 331# 61 955190# 150# - -4 29 33 62 As x -24320# 300# 8047# 5# B- * 61 973891# 322# -0 19 41 22 63 Ti x -5750# 500# 7889# 8# B- 16140# 640# 62 993827# 537# - 17 40 23 63 V x -21890# 400# 8133# 6# B- 14117# 537# 62 976500# 429# - 15 39 24 63 Cr x -36007.474 358.073 8344.828 5.684 B- 10879.579 358.092 62 961344.384 384.407 - 13 38 25 63 Mn x -46887.053 3.726 8505.101 0.059 B- 8748.568 5.692 62 949664.675 4.000 - 11 37 26 63 Fe -55635.621 4.302 8631.549 0.068 B- 6215.819 19.067 62 940272.700 4.618 - 9 36 27 63 Co -61851.440 18.575 8717.795 0.295 B- 3661.335 18.570 62 933599.744 19.941 - 7 35 28 63 Ni -65512.775 0.440 8763.493 0.007 B- 66.977 0.015 62 929669.139 0.472 - 5 34 29 63 Cu -65579.752 0.440 8752.138 0.007 B- -3366.355 1.546 62 929597.236 0.472 - 3 33 30 63 Zn -62213.397 1.561 8686.285 0.025 B- -5666.304 2.034 62 933211.167 1.676 - 1 32 31 63 Ga x -56547.093 1.304 8583.926 0.021 B- -9625.877 37.283 62 939294.195 1.400 - -1 31 32 63 Ge x -46921.216 37.260 8418.716 0.591 B- -13421# 204# 62 949628.000 40.000 - -3 30 33 63 As x -33500# 200# 8193# 3# B- * 62 964036# 215# -0 20 42 22 64 Ti x -1025# 600# 7818# 9# B- 15295# 721# 63 998900# 644# - 18 41 23 64 V x -16320# 400# 8045# 6# B- 17160# 594# 63 982480# 429# - 16 40 24 64 Cr x -33479.757 439.665 8301.058 6.870 B- 9509.277 439.679 63 964058.000 472.000 - 14 39 25 64 Mn x -42989.035 3.540 8437.417 0.055 B- 11980.510 6.140 63 953849.370 3.800 - 12 38 26 64 Fe x -54969.544 5.017 8612.388 0.078 B- 4822.785 20.625 63 940987.763 5.386 - 10 37 27 64 Co + -59792.329 20.006 8675.520 0.313 B- 7306.592 20.000 63 935810.291 21.476 - 8 36 28 64 Ni -67098.921 0.475 8777.461 0.007 B- -1674.376 0.225 63 927966.341 0.510 - 6 35 29 64 Cu -65424.545 0.448 8739.075 0.007 B- 579.469 0.650 63 929763.857 0.481 - 4 34 30 64 Zn -66004.014 0.647 8735.905 0.010 B- -7171.194 1.483 63 929141.772 0.694 - 2 33 31 64 Ga -58832.821 1.429 8611.631 0.022 B- -4517.325 3.991 63 936840.365 1.533 - 0 32 32 64 Ge x -54315.496 3.726 8528.823 0.058 B- -14783# 203# 63 941689.913 4.000 - -2 31 33 64 As -p -39532# 203# 8286# 3# B- -12832# 543# 63 957560# 218# - -4 30 34 64 Se x -26700# 503# 8073# 8# B- * 63 971336# 540# -0 19 42 23 65 V x -11780# 500# 7976# 8# B- 16440# 583# 64 987354# 537# - 17 41 24 65 Cr x -28220# 300# 8217# 5# B- 12748# 300# 64 969705# 322# - 15 40 25 65 Mn x -40967.339 3.726 8400.681 0.057 B- 10250.557 6.326 64 956019.750 4.000 - 13 39 26 65 Fe x -51217.895 5.112 8546.346 0.079 B- 7967.303 5.520 64 945015.324 5.487 - 11 38 27 65 Co x -59185.198 2.083 8656.884 0.032 B- 5940.487 2.141 64 936462.073 2.235 - 9 37 28 65 Ni -n -65125.685 0.495 8736.240 0.008 B- 2137.975 0.706 64 930084.697 0.531 - 7 36 29 65 Cu -67263.660 0.650 8757.096 0.010 B- -1351.640 0.360 64 927789.487 0.697 - 5 35 30 65 Zn -65912.019 0.650 8724.265 0.010 B- -3254.513 0.662 64 929240.532 0.697 - 3 34 31 65 Ga -62657.507 0.815 8662.160 0.013 B- -6179.291 2.313 64 932734.395 0.874 - 1 33 32 65 Ge -56478.216 2.165 8555.058 0.033 B- -9541.165 84.794 64 939368.137 2.323 - -1 32 33 65 As x -46937.051 84.766 8396.234 1.304 B- -13917# 312# 64 949611.000 91.000 - -3 31 34 65 Se x -33020# 300# 8170# 5# B- * 64 964552# 322# -0 20 43 23 66 V x -5610# 500# 7884# 8# B- 19110# 640# 65 993977# 537# - 18 42 24 66 Cr x -24720# 400# 8161# 6# B- 12030# 400# 65 973462# 429# - 16 41 25 66 Mn x -36750.387 11.178 8331.798 0.169 B- 13317.452 11.906 65 960546.834 12.000 - 14 40 26 66 Fe x -50067.839 4.099 8521.724 0.062 B- 6340.694 14.561 65 946249.960 4.400 - 12 39 27 66 Co x -56408.533 13.972 8605.941 0.212 B- 9597.752 14.042 65 939442.945 15.000 - 10 38 28 66 Ni x -66006.285 1.397 8739.508 0.021 B- 251.987 1.543 65 929139.334 1.500 - 8 37 29 66 Cu -66258.272 0.655 8731.472 0.010 B- 2640.888 0.931 65 928868.814 0.703 - 6 36 30 66 Zn -68899.160 0.749 8759.632 0.011 B- -5175.500 0.800 65 926033.704 0.804 - 4 35 31 66 Ga - -63723.660 1.096 8669.361 0.017 B- -2116.628 2.639 65 931589.832 1.176 - 2 34 32 66 Ge x -61607.032 2.401 8625.437 0.036 B- -9581.955 6.168 65 933862.126 2.577 - 0 33 33 66 As x -52025.077 5.682 8468.403 0.086 B- -10365# 200# 65 944148.779 6.100 - -2 32 34 66 Se x -41660# 200# 8300# 3# B- * 65 955276# 215# -0 21 44 23 67 V x -650# 600# 7812# 9# B- 18030# 721# 66 999302# 644# - 19 43 24 67 Cr x -18680# 400# 8070# 6# B- 14780# 500# 66 979946# 429# - 17 42 25 67 Mn x -33460# 300# 8279# 4# B- 12150# 404# 66 964079# 322# - 15 41 26 67 Fe x -45610.155 270.285 8448.469 4.034 B- 9711.620 270.362 66 951035.482 290.163 - 13 40 27 67 Co x -55321.775 6.443 8581.741 0.096 B- 8420.905 7.061 66 940609.628 6.917 - 11 39 28 67 Ni x -63742.680 2.888 8695.750 0.043 B- 3576.832 3.023 66 931569.414 3.100 - 9 38 29 67 Cu -67319.513 0.894 8737.458 0.013 B- 560.800 0.830 66 927729.526 0.959 - 7 37 30 67 Zn -67880.313 0.760 8734.152 0.011 B- -1001.265 1.122 66 927127.482 0.815 - 5 36 31 67 Ga -66879.048 1.181 8707.531 0.018 B- -4220.819 4.799 66 928202.384 1.268 - 3 35 32 67 Ge -n2p -62658.230 4.661 8632.857 0.070 B- -6071.005 4.682 66 932733.620 5.003 - 1 34 33 67 As -56587.225 0.443 8530.568 0.007 B- -10006.936 67.069 66 939251.111 0.475 - -1 33 34 67 Se x -46580.289 67.068 8369.534 1.001 B- -13790# 405# 66 949994.000 72.000 - -3 32 35 67 Br x -32790# 400# 8152# 6# B- * 66 964798# 429# -0 20 44 24 68 Cr x -14800# 500# 8013# 7# B- 13580# 640# 67 984112# 537# - 18 43 25 68 Mn x -28380# 400# 8201# 6# B- 15107# 541# 67 969533# 429# - 16 42 26 68 Fe x -43486.914 365.259 8411.698 5.371 B- 8443.751 411.489 67 953314.875 392.121 - 14 41 27 68 Co x -51930.665 189.497 8524.366 2.787 B- 11533.150 189.520 67 944250.135 203.433 - 12 40 28 68 Ni x -63463.814 2.981 8682.466 0.044 B- 2103.220 3.375 67 931868.789 3.200 - 10 39 29 68 Cu x -65567.035 1.584 8701.890 0.023 B- 4440.057 1.767 67 929610.889 1.700 - 8 38 30 68 Zn -70007.092 0.784 8755.680 0.012 B- -2921.100 1.200 67 924844.291 0.841 - 6 37 31 68 Ga - -67085.992 1.433 8701.218 0.021 B- -107.203 2.361 67 927980.221 1.538 - 4 36 32 68 Ge x -66978.789 1.876 8688.136 0.028 B- -8084.270 2.632 67 928095.308 2.014 - 2 35 33 68 As -58894.519 1.846 8557.745 0.027 B- -4705.078 1.911 67 936774.130 1.981 - 0 34 34 68 Se x -54189.441 0.496 8477.047 0.007 B- -15398# 259# 67 941825.239 0.532 - -2 33 35 68 Br -p -38791# 259# 8239# 4# B- * 67 958356# 278# -0 21 45 24 69 Cr x -8580# 500# 7924# 7# B- 16190# 640# 68 990789# 537# - 19 44 25 69 Mn x -24770# 400# 8147# 6# B- 14259# 565# 68 973408# 429# - 17 43 26 69 Fe x -39030# 400# 8342# 6# B- 11250# 424# 68 958100# 429# - 15 42 27 69 Co x -50279.157 140.506 8493.865 2.036 B- 9699.492 140.556 68 946023.102 150.839 - 13 41 28 69 Ni x -59978.648 3.726 8623.099 0.054 B- 5757.564 3.979 68 935610.268 4.000 - 11 40 29 69 Cu x -65736.213 1.397 8695.204 0.020 B- 2681.632 1.610 68 929429.268 1.500 - 9 39 30 69 Zn -n -68417.845 0.800 8722.729 0.012 B- 909.964 1.426 68 926550.418 0.858 - 7 38 31 69 Ga -69327.809 1.197 8724.579 0.017 B- -2227.146 0.550 68 925573.531 1.285 - 5 37 32 69 Ge -67100.663 1.318 8680.963 0.019 B- -3988.492 31.982 68 927964.471 1.414 - 3 36 33 69 As -63112.171 31.999 8611.821 0.464 B- -6677.465 32.021 68 932246.294 34.352 - 1 35 34 69 Se -56434.706 1.490 8503.707 0.022 B- -10175.236 42.029 68 939414.847 1.599 - -1 34 35 69 Br -p -46259.470 42.003 8344.902 0.609 B- -13825# 403# 68 950338.413 45.092 - -3 33 36 69 Kr x -32435# 401# 8133# 6# B- * 68 965180# 430# -0 22 46 24 70 Cr x -4480# 600# 7867# 9# B- 15020# 781# 69 995191# 644# - 20 45 25 70 Mn x -19500# 500# 8070# 7# B- 17010# 640# 69 979066# 537# - 18 44 26 70 Fe x -36510# 400# 8302# 6# B- 10120# 500# 69 960805# 429# - 16 43 27 70 Co x -46630# 300# 8436# 4# B- 12584# 300# 69 949941# 322# - 14 42 28 70 Ni x -59213.860 2.144 8604.291 0.031 B- 3762.513 2.401 69 936431.303 2.301 - 12 41 29 70 Cu x -62976.373 1.082 8646.865 0.015 B- 6588.362 2.202 69 932392.079 1.161 - 10 40 30 70 Zn -69564.735 1.918 8729.808 0.027 B- -654.595 1.574 69 925319.181 2.058 - 8 39 31 70 Ga -68910.140 1.201 8709.280 0.017 B- 1651.736 1.462 69 926021.917 1.289 - 6 38 32 70 Ge -70561.876 0.838 8721.700 0.012 B- -6220.000 50.000 69 924248.706 0.900 - 4 37 33 70 As - -64341.876 50.007 8621.666 0.714 B- -2411.985 50.032 69 930926.151 53.684 - 2 36 34 70 Se x -61929.891 1.584 8576.033 0.023 B- -10504.272 14.988 69 933515.523 1.700 - 0 35 35 70 Br x -51425.619 14.904 8414.796 0.213 B- -10325# 201# 69 944792.323 16.000 - -2 34 36 70 Kr x -41100# 200# 8256# 3# B- * 69 955877# 215# -0 21 46 25 71 Mn x -15570# 500# 8015# 7# B- 15860# 640# 70 983285# 537# - 19 45 26 71 Fe x -31430# 400# 8227# 6# B- 12940# 613# 70 966259# 429# - 17 44 27 71 Co x -44369.926 465.030 8398.734 6.550 B- 11036.302 465.035 70 952366.923 499.230 - 15 43 28 71 Ni x -55406.228 2.237 8543.156 0.032 B- 7304.899 2.688 70 940518.964 2.401 - 13 42 29 71 Cu x -62711.127 1.490 8635.022 0.021 B- 4617.651 3.044 70 932676.832 1.600 - 11 41 30 71 Zn -67328.777 2.654 8689.041 0.037 B- 2810.358 2.775 70 927719.580 2.849 - 9 40 31 71 Ga -70139.135 0.812 8717.604 0.011 B- -232.638 0.223 70 924702.536 0.871 - 7 39 32 71 Ge -69906.497 0.834 8703.309 0.012 B- -2013.400 4.082 70 924952.284 0.894 - 5 38 33 71 As - -67893.097 4.167 8663.932 0.059 B- -4746.590 5.017 70 927113.758 4.473 - 3 37 34 71 Se x -63146.507 2.794 8586.060 0.039 B- -6644.089 6.082 70 932209.432 3.000 - 1 36 35 71 Br -56502.418 5.402 8481.462 0.076 B- -10175.212 128.845 70 939342.156 5.799 - -1 35 36 71 Kr -46327.205 128.769 8327.130 1.814 B- -14267# 420# 70 950265.696 138.238 - -3 34 37 71 Rb x -32060# 400# 8115# 6# B- * 70 965582# 429# -0 22 47 25 72 Mn x -9900# 600# 7937# 8# B- 18530# 781# 71 989372# 644# - 20 46 26 72 Fe x -28430# 500# 8184# 7# B- 11769# 640# 71 969479# 537# - 18 45 27 72 Co x -40200# 400# 8336# 6# B- 14027# 400# 71 956844# 429# - 16 44 28 72 Ni x -54226.060 2.237 8520.211 0.031 B- 5556.938 2.637 71 941785.926 2.401 - 14 43 29 72 Cu x -59782.999 1.397 8586.525 0.019 B- 8362.487 2.558 71 935820.307 1.500 - 12 42 30 72 Zn x -68145.486 2.142 8691.805 0.030 B- 442.807 2.294 71 926842.807 2.300 - 10 41 31 72 Ga -68588.293 0.819 8687.089 0.011 B- 3997.607 0.822 71 926367.434 0.878 - 8 40 32 72 Ge -72585.900 0.076 8731.745 0.001 B- -4356.102 4.082 71 922075.826 0.081 - 6 39 33 72 As - -68229.798 4.083 8660.378 0.057 B- -361.618 4.528 71 926752.295 4.383 - 4 38 34 72 Se x -67868.180 1.956 8644.489 0.027 B- -8806.437 2.208 71 927140.507 2.100 - 2 37 35 72 Br x -59061.743 1.025 8511.312 0.014 B- -5121.168 8.076 71 936594.607 1.100 - 0 36 36 72 Kr x -53940.575 8.011 8429.319 0.111 B- -15611# 500# 71 942092.407 8.600 - -2 35 37 72 Rb x -38330# 500# 8202# 7# B- * 71 958851# 537# -0 21 47 26 73 Fe x -22900# 500# 8106# 7# B- 14518# 640# 72 975416# 537# - 19 46 27 73 Co x -37418# 400# 8295# 5# B- 12690# 400# 72 959830# 429# - 17 45 28 73 Ni x -50108.152 2.423 8457.652 0.033 B- 8879.285 3.104 72 946206.683 2.601 - 15 44 29 73 Cu -58987.437 1.942 8568.569 0.027 B- 6605.966 2.691 72 936674.378 2.084 - 13 43 30 73 Zn x -65593.402 1.863 8648.345 0.026 B- 4105.932 2.506 72 929582.582 2.000 - 11 42 31 73 Ga x -69699.335 1.677 8693.873 0.023 B- 1598.188 1.678 72 925174.682 1.800 - 9 41 32 73 Ge -71297.523 0.057 8705.049 0.001 B- -344.776 3.853 72 923458.956 0.061 - 7 40 33 73 As -70952.747 3.853 8689.609 0.053 B- -2725.360 7.399 72 923829.089 4.136 - 5 39 34 73 Se -68227.387 7.424 8641.558 0.102 B- -4579.912 10.388 72 926754.883 7.969 - 3 38 35 73 Br x -63647.475 7.266 8568.103 0.100 B- -7095.725 9.801 72 931671.621 7.800 - 1 37 36 73 Kr x -56551.751 6.578 8460.184 0.090 B- -10470# 200# 72 939289.195 7.061 - -1 36 37 73 Rb -p -46082# 200# 8306# 3# B- -14131# 448# 72 950529# 215# - -3 35 38 73 Sr x -31950# 401# 8102# 5# B- * 72 965700# 430# -0 22 48 26 74 Fe x -19590# 600# 8061# 8# B- 13230# 781# 73 978969# 644# - 20 47 27 74 Co x -32820# 500# 8229# 7# B- 15636# 537# 73 964766# 537# - 18 46 28 74 Ni x -48456# 196# 8430# 3# B- 7550# 196# 73 947980# 210# - 16 45 29 74 Cu x -56006.205 6.148 8521.562 0.083 B- 9750.507 6.642 73 939874.862 6.600 - 14 44 30 74 Zn x -65756.712 2.515 8642.754 0.034 B- 2292.905 3.910 73 929407.262 2.700 - 12 43 31 74 Ga x -68049.617 2.994 8663.167 0.040 B- 5372.824 2.994 73 926945.726 3.214 - 10 42 32 74 Ge -73422.442 0.013 8725.200 0.000 B- -2562.387 1.693 73 921177.762 0.013 - 8 41 33 74 As -70860.054 1.693 8680.001 0.023 B- 1353.147 1.693 73 923928.598 1.817 - 6 40 34 74 Se -72213.201 0.015 8687.715 0.000 B- -6925.049 5.835 73 922475.935 0.015 - 4 39 35 74 Br -65288.153 5.835 8583.561 0.079 B- -2956.317 6.173 73 929910.281 6.264 - 2 38 36 74 Kr -62331.836 2.013 8533.038 0.027 B- -10415.827 3.424 73 933084.017 2.161 - 0 37 37 74 Rb -51916.009 3.027 8381.712 0.041 B- -11089# 100# 73 944265.868 3.249 - -2 36 38 74 Sr x -40827# 100# 8221# 1# B- * 73 956170# 107# -0 23 49 26 75 Fe x -13640# 600# 7982# 8# B- 16010# 781# 74 985357# 644# - 21 48 27 75 Co x -29649# 500# 8185# 7# B- 14380# 583# 74 968170# 537# - 19 47 28 75 Ni x -44030# 300# 8366# 4# B- 10441# 300# 74 952732# 322# - 17 46 29 75 Cu x -54471.341 2.330 8495.094 0.031 B- 8087.567 3.042 74 941522.606 2.501 - 15 45 30 75 Zn x -62558.908 1.956 8592.497 0.026 B- 5905.672 3.113 74 932840.246 2.100 - 13 44 31 75 Ga x -68464.580 2.422 8660.808 0.032 B- 3392.384 2.422 74 926500.246 2.600 - 11 43 32 75 Ge -n -71856.965 0.052 8695.609 0.001 B- 1177.231 0.885 74 922858.371 0.055 - 9 42 33 75 As -73034.195 0.884 8700.874 0.012 B- -864.714 0.882 74 921594.562 0.948 - 7 41 34 75 Se -72169.481 0.073 8678.913 0.001 B- -3062.472 4.285 74 922522.871 0.078 - 5 40 35 75 Br x -69107.009 4.285 8627.649 0.057 B- -4783.385 9.167 74 925810.570 4.600 - 3 39 36 75 Kr x -64323.624 8.104 8553.439 0.108 B- -7104.929 8.189 74 930945.746 8.700 - 1 38 37 75 Rb x -57218.694 1.180 8448.275 0.016 B- -10600.000 220.000 74 938573.201 1.266 - -1 37 38 75 Sr - -46618.694 220.003 8296.511 2.933 B- -14799# 372# 74 949952.770 236.183 - -3 36 39 75 Y x -31820# 300# 8089# 4# B- * 74 965840# 322# -0 22 49 27 76 Co x -24510# 600# 8116# 8# B- 17120# 721# 75 973687# 644# - 20 48 28 76 Ni x -41630# 400# 8331# 5# B- 9346# 400# 75 955308# 429# - 18 47 29 76 Cu x -50975.985 6.707 8443.527 0.088 B- 11327.031 6.863 75 945275.025 7.200 - 16 46 30 76 Zn -62303.016 1.456 8582.273 0.019 B- 3993.624 2.438 75 933114.957 1.562 - 14 45 31 76 Ga x -66296.640 1.956 8624.526 0.026 B- 6916.249 1.956 75 928827.625 2.100 - 12 44 32 76 Ge -73212.889 0.018 8705.236 0.000 B- -921.512 0.886 75 921402.726 0.019 - 10 43 33 76 As -n -72291.377 0.886 8682.816 0.012 B- 2960.573 0.886 75 922392.010 0.951 - 8 42 34 76 Se -75251.950 0.016 8711.477 0.000 B- -4962.881 9.322 75 919213.704 0.017 - 6 41 35 76 Br - -70289.068 9.322 8635.882 0.123 B- -1275.355 10.149 75 924541.577 10.007 - 4 40 36 76 Kr -69013.714 4.013 8608.807 0.053 B- -8534.633 4.121 75 925910.726 4.308 - 2 39 37 76 Rb x -60479.081 0.938 8486.215 0.012 B- -6231.442 34.478 75 935073.032 1.006 - 0 38 38 76 Sr x -54247.639 34.465 8393.929 0.453 B- -15768# 302# 75 941762.761 37.000 - -2 37 39 76 Y x -38480# 300# 8176# 4# B- * 75 958690# 322# -0 23 50 27 77 Co x -21015# 600# 8070# 8# B- 15785# 781# 76 977440# 644# - 21 49 28 77 Ni x -36800# 500# 8265# 6# B- 11824# 522# 76 960494# 537# - 19 48 29 77 Cu x -48624# 149# 8408# 2# B- 10165# 149# 76 947800# 160# - 17 47 30 77 Zn -58789.195 1.973 8530.003 0.026 B- 7203.149 3.124 76 936887.199 2.117 - 15 46 31 77 Ga x -65992.344 2.422 8613.390 0.031 B- 5220.518 2.422 76 929154.300 2.600 - 13 45 32 77 Ge -n -71212.862 0.053 8671.028 0.001 B- 2703.456 1.694 76 923549.844 0.056 - 11 44 33 77 As -73916.318 1.693 8695.978 0.022 B- 683.170 1.693 76 920647.564 1.817 - 9 43 34 77 Se -74599.488 0.062 8694.690 0.001 B- -1364.680 2.810 76 919914.150 0.067 - 7 42 35 77 Br - -73234.809 2.811 8666.806 0.037 B- -3065.366 3.424 76 921379.194 3.017 - 5 41 36 77 Kr x -70169.443 1.956 8616.836 0.025 B- -5338.951 2.351 76 924670.000 2.100 - 3 40 37 77 Rb x -64830.492 1.304 8537.339 0.017 B- -7027.055 8.024 76 930401.600 1.400 - 1 39 38 77 Sr x -57803.436 7.918 8435.918 0.103 B- -11365# 203# 76 937945.455 8.500 - -1 38 39 77 Y -p -46439# 203# 8278# 3# B- -14399# 448# 76 950146# 218# - -3 37 40 77 Zr x -32040# 400# 8081# 5# B- * 76 965604# 429# -0 22 50 28 78 Ni x -33890# 600# 8225# 8# B- 10608# 783# 77 963618# 644# - 20 49 29 78 Cu x -44497.469 503.007 8350.925 6.449 B- 12985.766 503.011 77 952230.000 540.000 - 18 48 30 78 Zn -57483.235 1.944 8507.379 0.025 B- 6222.716 2.719 77 938289.205 2.086 - 16 47 31 78 Ga -63705.950 1.903 8577.127 0.024 B- 8156.099 4.015 77 931608.845 2.043 - 14 46 32 78 Ge -nn -71862.050 3.536 8671.663 0.045 B- 954.890 10.400 77 922852.912 3.795 - 12 45 33 78 As +pn -72816.940 9.781 8673.875 0.125 B- 4209.004 9.782 77 921827.795 10.500 - 10 44 34 78 Se -77025.944 0.179 8717.806 0.002 B- -3573.784 3.575 77 917309.243 0.191 - 8 43 35 78 Br - -73452.160 3.580 8661.959 0.046 B- 726.116 3.584 77 921145.859 3.842 - 6 42 36 78 Kr -74178.275 0.307 8661.238 0.004 B- -7242.857 3.252 77 920366.341 0.329 - 4 41 37 78 Rb x -66935.419 3.237 8558.350 0.042 B- -3761.477 8.125 77 928141.868 3.475 - 2 40 38 78 Sr x -63173.941 7.452 8500.096 0.096 B- -11001# 298# 77 932179.980 8.000 - 0 39 39 78 Y x -52173# 298# 8349# 4# B- -11323# 499# 77 943990# 320# - -2 38 40 78 Zr x -40850# 400# 8194# 5# B- * 77 956146# 429# -0 23 51 28 79 Ni x -27570# 600# 8143# 8# B- 14170# 671# 78 970402# 644# - 21 50 29 79 Cu x -41740# 300# 8312# 4# B- 11692# 300# 78 955190# 322# - 19 49 30 79 Zn -53432.295 2.225 8450.582 0.028 B- 9115.384 2.901 78 942638.068 2.388 - 17 48 31 79 Ga -62547.679 1.868 8556.063 0.024 B- 6978.913 37.147 78 932852.301 2.005 - 15 47 32 79 Ge -69526.592 37.181 8634.501 0.471 B- 4109.457 37.456 78 925360.129 39.915 - 13 46 33 79 As -73636.049 5.328 8676.616 0.067 B- 2281.410 5.331 78 920948.445 5.719 - 11 45 34 79 Se -n -75917.459 0.223 8695.592 0.003 B- 150.576 1.038 78 918499.251 0.238 - 9 44 35 79 Br +n -76068.035 1.021 8687.594 0.013 B- -1625.778 3.333 78 918337.601 1.095 - 7 43 36 79 Kr - -74442.257 3.486 8657.112 0.044 B- -3639.271 4.092 78 920082.945 3.742 - 5 42 37 79 Rb x -70802.985 2.142 8601.142 0.027 B- -5326.096 8.653 78 923989.864 2.300 - 3 41 38 79 Sr x -65476.889 8.383 8523.820 0.106 B- -7659.056 79.620 78 929707.664 9.000 - 1 40 39 79 Y x -57817.833 79.177 8416.967 1.002 B- -11048# 310# 78 937930.000 85.000 - -1 39 40 79 Zr x -46770# 300# 8267# 4# B- -15120# 583# 78 949790# 322# - -3 38 41 79 Nb x -31650# 500# 8066# 6# B- * 78 966022# 537# -0 24 52 28 80 Ni x -22630# 700# 8080# 9# B- 13570# 806# 79 975706# 751# - 22 51 29 80 Cu x -36200# 400# 8240# 5# B- 15449# 400# 79 961138# 429# - 20 50 30 80 Zn -51648.612 2.585 8423.545 0.032 B- 7575.055 3.877 79 944552.930 2.774 - 18 49 31 80 Ga x -59223.667 2.891 8508.454 0.036 B- 10311.639 3.541 79 936420.774 3.103 - 16 48 32 80 Ge x -69535.306 2.054 8627.570 0.026 B- 2679.187 3.915 79 925350.774 2.205 - 14 47 33 80 As x -72214.493 3.333 8651.280 0.042 B- 5544.964 3.445 79 922474.548 3.577 - 12 46 34 80 Se -77759.457 0.963 8710.813 0.012 B- -1870.464 0.310 79 916521.785 1.034 - 10 45 35 80 Br - -75888.993 1.012 8677.653 0.013 B- 2004.353 1.154 79 918529.810 1.086 - 8 44 36 80 Kr -77893.346 0.691 8692.928 0.009 B- -5717.879 1.987 79 916378.048 0.742 - 6 43 37 80 Rb x -72175.467 1.863 8611.675 0.023 B- -1864.009 3.933 79 922516.444 2.000 - 4 42 38 80 Sr x -70311.459 3.464 8578.596 0.043 B- -9163.307 7.139 79 924517.540 3.718 - 2 41 39 80 Y x -61148.152 6.242 8454.275 0.078 B- -6788# 300# 79 934354.755 6.701 - 0 40 40 80 Zr x -54360# 300# 8360# 4# B- -15940# 500# 79 941642# 322# - -2 39 41 80 Nb x -38420# 400# 8151# 5# B- * 79 958754# 429# -0 23 52 29 81 Cu x -31420# 500# 8179# 6# B- 14779# 500# 80 966269# 537# - 21 51 30 81 Zn x -46199.663 5.030 8351.925 0.062 B- 11428.292 5.996 80 950402.619 5.400 - 19 50 31 81 Ga x -57627.954 3.264 8483.357 0.040 B- 8663.733 3.851 80 938133.842 3.503 - 17 49 32 81 Ge x -66291.687 2.055 8580.658 0.025 B- 6241.617 3.344 80 928832.942 2.205 - 15 48 33 81 As -72533.304 2.644 8648.056 0.033 B- 3855.684 2.812 80 922132.290 2.838 - 13 47 34 81 Se -76388.988 0.992 8685.999 0.012 B- 1588.046 1.389 80 917993.044 1.065 - 11 46 35 81 Br -77977.034 0.978 8695.946 0.012 B- -280.853 0.471 80 916288.206 1.049 - 9 45 36 81 Kr -77696.181 1.074 8682.820 0.013 B- -2239.511 5.019 80 916589.714 1.152 - 7 44 37 81 Rb -75456.670 4.904 8645.513 0.061 B- -3928.545 5.817 80 918993.927 5.264 - 5 43 38 81 Sr x -71528.125 3.128 8587.354 0.039 B- -5815.214 6.245 80 923211.394 3.358 - 3 42 39 81 Y x -65712.912 5.405 8505.902 0.067 B- -8252.773 94.236 80 929454.283 5.802 - 1 41 40 81 Zr x -57460.139 94.081 8394.358 1.161 B- -11100# 411# 80 938314.000 101.000 - -1 40 41 81 Nb x -46360# 400# 8248# 5# B- -14610# 640# 80 950230# 429# - -3 39 42 81 Mo x -31750# 500# 8058# 6# B- * 80 965915# 537# -0 24 53 29 82 Cu x -25320# 600# 8103# 7# B- 16994# 600# 81 972818# 644# - 22 52 30 82 Zn x -42313.954 3.074 8301.117 0.037 B- 10616.764 3.916 81 954574.099 3.300 - 20 51 31 82 Ga x -52930.719 2.426 8421.049 0.030 B- 12484.348 3.296 81 943176.533 2.604 - 18 50 32 82 Ge x -65415.067 2.241 8563.756 0.027 B- 4690.352 4.345 81 929774.033 2.405 - 16 49 33 82 As x -70105.419 3.729 8611.414 0.045 B- 7488.463 3.758 81 924738.733 4.003 - 14 48 34 82 Se -77593.882 0.467 8693.196 0.006 B- -95.221 1.077 81 916699.537 0.500 - 12 47 35 82 Br -77498.661 0.971 8682.494 0.012 B- 3093.124 0.971 81 916801.760 1.042 - 10 46 36 82 Kr -80591.78515 0.00549 8710.675 0.000 B- -4403.982 3.009 81 913481.15520 0.00589 - 8 45 37 82 Rb IT -76187.803 3.009 8647.427 0.037 B- -177.751 6.705 81 918209.024 3.230 - 6 44 38 82 Sr -76010.053 5.992 8635.718 0.073 B- -7945.961 8.132 81 918399.847 6.432 - 4 43 39 82 Y x -68064.091 5.499 8529.275 0.067 B- -4432.804 12.457 81 926930.188 5.902 - 2 42 40 82 Zr x -63631.287 11.178 8465.676 0.136 B- -11541# 300# 81 931689.000 12.000 - 0 41 41 82 Nb x -52090# 300# 8315# 4# B- -11720# 500# 81 944079# 322# - -2 40 42 82 Mo x -40370# 400# 8163# 5# B- * 81 956661# 429# -0 23 53 30 83 Zn x -36290# 300# 8226# 4# B- 12967# 300# 82 961041# 322# - 21 52 31 83 Ga x -49257.122 2.613 8372.575 0.031 B- 11719.312 3.559 82 947120.301 2.804 - 19 51 32 83 Ge x -60976.435 2.427 8504.345 0.029 B- 8692.888 3.698 82 934539.101 2.605 - 17 50 33 83 As x -69669.323 2.799 8599.653 0.034 B- 5671.207 4.129 82 925206.901 3.004 - 15 49 34 83 Se -n -75340.530 3.036 8658.555 0.037 B- 3673.179 4.839 82 919118.609 3.259 - 13 48 35 83 Br -79013.709 3.795 8693.384 0.046 B- 976.924 3.795 82 915175.289 4.073 - 11 47 36 83 Kr -79990.633 0.009 8695.729 0.000 B- -920.004 2.329 82 914126.518 0.009 - 9 46 37 83 Rb -79070.630 2.329 8675.218 0.028 B- -2273.024 6.424 82 915114.182 2.500 - 7 45 38 83 Sr -76797.606 6.834 8638.407 0.082 B- -4591.941 19.844 82 917554.374 7.336 - 5 44 39 83 Y x -72205.665 18.631 8573.656 0.224 B- -6294.012 19.707 82 922484.025 20.000 - 3 43 40 83 Zr x -65911.654 6.430 8488.399 0.077 B- -8355.571 151.039 82 929240.925 6.902 - 1 42 41 83 Nb x -57556.083 150.902 8378.304 1.818 B- -11216# 428# 82 938211.000 162.000 - -1 41 42 83 Mo x -46340# 401# 8234# 5# B- -15020# 641# 82 950252# 430# - -3 40 43 83 Tc x -31320# 500# 8043# 6# B- * 82 966377# 537# -0 24 54 30 84 Zn x -31930# 400# 8172# 5# B- 12158# 447# 83 965722# 429# - 22 53 31 84 Ga x -44088# 200# 8307# 2# B- 14061# 200# 83 952670# 215# - 20 52 32 84 Ge x -58148.428 3.171 8465.524 0.038 B- 7705.132 4.479 83 937575.091 3.403 - 18 51 33 84 As x -65853.560 3.171 8547.938 0.038 B- 10094.161 3.722 83 929303.291 3.403 - 16 50 34 84 Se -75947.721 1.961 8658.793 0.023 B- 1835.363 25.765 83 918466.762 2.105 - 14 49 35 84 Br -77783.084 25.730 8671.329 0.306 B- 4656.251 25.730 83 916496.419 27.622 - 12 48 36 84 Kr -82439.33510 0.00379 8717.446 0.000 B- -2680.371 2.194 83 911497.72863 0.00407 - 10 47 37 84 Rb -79758.964 2.194 8676.224 0.026 B- 890.606 2.336 83 914375.225 2.355 - 8 46 38 84 Sr -80649.570 1.243 8677.512 0.015 B- -6755.139 4.411 83 913419.120 1.334 - 6 45 39 84 Y -73894.431 4.299 8587.780 0.051 B- -2472.745 6.977 83 920671.061 4.615 - 4 44 40 84 Zr x -71421.686 5.499 8549.029 0.065 B- -10202.968 14.153 83 923325.662 5.903 - 2 43 41 84 Nb x -61218.717 13.041 8418.252 0.155 B- -7049# 298# 83 934279.000 14.000 - 0 42 42 84 Mo x -54170# 298# 8325# 4# B- -16470# 499# 83 941846# 320# - -2 41 43 84 Tc x -37700# 400# 8120# 5# B- * 83 959527# 429# -0 25 55 30 85 Zn x -25230# 500# 8092# 6# B- 14619# 582# 84 972914# 537# - 23 54 31 85 Ga x -39849# 298# 8255# 4# B- 13274# 298# 84 957220# 320# - 21 53 32 85 Ge x -53123.420 3.729 8401.768 0.044 B- 10065.724 4.830 84 942969.659 4.003 - 19 52 33 85 As x -63189.144 3.078 8510.984 0.036 B- 9224.492 4.031 84 932163.659 3.304 - 17 51 34 85 Se +3p -72413.636 2.613 8610.304 0.031 B- 6161.833 4.031 84 922260.759 2.804 - 15 50 35 85 Br +n2p -78575.469 3.078 8673.592 0.036 B- 2904.861 3.671 84 915645.759 3.304 - 13 49 36 85 Kr + -81480.331 2.000 8698.562 0.024 B- 687.000 2.000 84 912527.262 2.147 - 11 48 37 85 Rb -82167.33050 0.00498 8697.441 0.000 B- -1064.051 2.813 84 911789.73760 0.00534 - 9 47 38 85 Sr -81103.280 2.813 8675.718 0.033 B- -3261.157 19.173 84 912932.043 3.020 - 7 46 39 85 Y x -77842.123 18.965 8628.148 0.223 B- -4666.934 20.026 84 916433.039 20.360 - 5 45 40 85 Zr x -73175.189 6.430 8564.039 0.076 B- -6895.514 7.625 84 921443.198 6.902 - 3 44 41 85 Nb x -66279.676 4.099 8473.711 0.048 B- -8769.923 16.357 84 928845.837 4.400 - 1 43 42 85 Mo x -57509.753 15.835 8361.331 0.186 B- -11660# 400# 84 938260.737 17.000 - -1 42 43 85 Tc x -45850# 400# 8215# 5# B- -14900# 640# 84 950778# 429# - -3 41 44 85 Ru x -30950# 500# 8030# 6# B- * 84 966774# 537# -0 24 55 31 86 Ga x -34080# 400# 8186# 5# B- 15320# 593# 85 963414# 429# - 22 54 32 86 Ge x -49399.922 437.802 8354.629 5.091 B- 9562.221 437.816 85 946967.000 470.000 - 20 53 33 86 As x -58962.142 3.450 8456.721 0.040 B- 11541.024 4.267 85 936701.533 3.703 - 18 52 34 86 Se x -70503.167 2.520 8581.822 0.029 B- 5129.085 3.972 85 924311.733 2.705 - 16 51 35 86 Br +pp -75632.252 3.078 8632.365 0.036 B- 7633.414 3.078 85 918805.433 3.304 - 14 50 36 86 Kr -83265.66564 0.00369 8712.029 0.000 B- -518.672 0.200 85 910610.62627 0.00396 - 12 49 37 86 Rb -n -82746.993 0.200 8696.901 0.002 B- 1776.096 0.200 85 911167.443 0.214 - 10 48 38 86 Sr -84523.08935 0.00522 8708.456 0.000 B- -5240.000 14.142 85 909260.72631 0.00561 - 8 47 39 86 Y - -79283.089 14.142 8638.428 0.164 B- -1314.075 14.585 85 914886.098 15.182 - 6 46 40 86 Zr -77969.014 3.566 8614.051 0.041 B- -8834.960 6.552 85 916296.815 3.827 - 4 45 41 86 Nb x -69134.054 5.499 8502.222 0.064 B- -5023.810 6.642 85 925781.535 5.903 - 2 44 42 86 Mo x -64110.245 3.726 8434.709 0.043 B- -12540# 300# 85 931174.817 4.000 - 0 43 43 86 Tc x -51570# 300# 8280# 3# B- -11800# 500# 85 944637# 322# - -2 42 44 86 Ru x -39770# 400# 8133# 5# B- * 85 957305# 429# -0 25 56 31 87 Ga x -29250# 500# 8129# 6# B- 14828# 583# 86 968599# 537# - 23 55 32 87 Ge x -44078# 300# 8290# 3# B- 11540# 300# 86 952680# 322# - 21 54 33 87 As x -55617.907 2.985 8413.851 0.034 B- 10808.218 3.726 86 940291.718 3.204 - 19 53 34 87 Se x -66426.125 2.241 8529.091 0.026 B- 7465.552 3.877 86 928688.618 2.405 - 17 52 35 87 Br 2p-n -73891.676 3.171 8605.910 0.036 B- 6817.845 3.181 86 920674.018 3.404 - 15 51 36 87 Kr -n -80709.522 0.246 8675.283 0.003 B- 3888.269 0.246 86 913354.759 0.264 - 13 50 37 87 Rb -84597.791 0.006 8710.983 0.000 B- 282.275 0.006 86 909180.531 0.006 - 11 49 38 87 Sr -84880.06595 0.00510 8705.236 0.000 B- -1861.690 1.128 86 908877.49615 0.00548 - 9 48 39 87 Y - -83018.376 1.128 8674.844 0.013 B- -3671.239 4.296 86 910876.102 1.210 - 7 47 40 87 Zr -79347.137 4.146 8623.654 0.048 B- -5472.651 7.963 86 914817.339 4.450 - 5 46 41 87 Nb x -73874.486 6.802 8551.757 0.078 B- -6989.678 7.378 86 920692.472 7.302 - 3 45 42 87 Mo -66884.808 2.857 8462.424 0.033 B- -9194.764 5.073 86 928196.201 3.067 - 1 44 43 87 Tc x -57690.044 4.192 8347.744 0.048 B- -12170# 400# 86 938067.187 4.500 - -1 43 44 87 Ru x -45520# 400# 8199# 5# B- * 86 951132# 429# -0 24 56 32 88 Ge x -40138# 400# 8243# 5# B- 10582# 445# 87 956910# 429# - 22 55 33 88 As x -50720# 196# 8354# 2# B- 13164# 196# 87 945550# 210# - 20 54 34 88 Se x -63884.195 3.357 8495.004 0.038 B- 6831.763 4.613 87 931417.491 3.604 - 18 53 35 88 Br ++ -70715.959 3.171 8563.747 0.036 B- 8975.327 4.106 87 924083.291 3.404 - 16 52 36 88 Kr x -79691.286 2.608 8656.849 0.030 B- 2917.709 2.613 87 914447.881 2.800 - 14 51 37 88 Rb -82608.995 0.159 8681.115 0.002 B- 5312.623 0.159 87 911315.591 0.171 - 12 50 38 88 Sr -87921.61793 0.00558 8732.595 0.000 B- -3622.600 1.500 87 905612.25561 0.00599 - 10 49 39 88 Y - -84299.018 1.500 8682.539 0.017 B- -670.147 5.608 87 909501.276 1.610 - 8 48 40 88 Zr -83628.871 5.403 8666.033 0.061 B- -7455.284 58.886 87 910220.709 5.800 - 6 47 41 88 Nb -76173.586 58.810 8572.424 0.668 B- -3487.042 58.933 87 918224.287 63.134 - 4 46 42 88 Mo x -72686.544 3.819 8523.908 0.043 B- -11005.229 149.088 87 921967.781 4.100 - 2 45 43 88 Tc x -61681.315 149.039 8389.958 1.694 B- -7342# 335# 87 933782.381 160.000 - 0 44 44 88 Ru x -54340# 300# 8298# 3# B- -17479# 500# 87 941664# 322# - -2 43 45 88 Rh x -36860# 400# 8090# 5# B- * 87 960429# 429# -0 25 57 32 89 Ge x -33729# 400# 8169# 4# B- 13069# 499# 88 963790# 429# - 23 56 33 89 As x -46798# 298# 8307# 3# B- 12194# 298# 88 949760# 320# - 21 55 34 89 Se x -58992.391 3.729 8435.279 0.042 B- 9281.872 4.951 88 936669.059 4.003 - 19 54 35 89 Br x -68274.263 3.264 8530.779 0.037 B- 8261.522 3.904 88 926704.559 3.504 - 17 53 36 89 Kr x -76535.785 2.142 8614.815 0.024 B- 5176.604 5.834 88 917835.450 2.300 - 15 52 37 89 Rb -81712.388 5.427 8664.189 0.061 B- 4496.628 5.427 88 912278.137 5.825 - 13 51 38 89 Sr -86209.017 0.092 8705.922 0.001 B- 1499.336 1.615 88 907450.808 0.098 - 11 50 39 89 Y -87708.352 1.612 8713.978 0.018 B- -2832.792 2.776 88 905841.205 1.730 - 9 49 40 89 Zr -84875.561 3.083 8673.359 0.035 B- -4250.351 23.743 88 908882.332 3.310 - 7 48 41 89 Nb -80625.209 23.631 8616.812 0.266 B- -5610.275 23.953 88 913445.272 25.369 - 5 47 42 89 Mo x -75014.935 3.912 8544.984 0.044 B- -7620.087 5.467 88 919468.150 4.200 - 3 46 43 89 Tc x -67394.848 3.819 8450.575 0.043 B- -9135# 298# 88 927648.650 4.100 - 1 45 44 89 Ru x -58260# 298# 8339# 3# B- -12400# 468# 88 937455# 320# - -1 44 45 89 Rh -p -45861# 361# 8191# 4# B- * 88 950767# 387# -0 26 58 32 90 Ge x -29221# 500# 8118# 6# B- 12109# 640# 89 968630# 537# - 24 57 33 90 As x -41330# 400# 8244# 4# B- 14470# 518# 89 955630# 429# - 22 56 34 90 Se x -55800.217 329.749 8395.766 3.664 B- 8200.081 329.766 89 940096.000 354.000 - 20 55 35 90 Br x -64000.298 3.357 8478.186 0.037 B- 10958.952 3.840 89 931292.850 3.604 - 18 54 36 90 Kr x -74959.250 1.863 8591.259 0.021 B- 4405.154 6.746 89 919527.930 2.000 - 16 53 37 90 Rb -79364.404 6.484 8631.512 0.072 B- 6583.723 6.544 89 914798.803 6.960 - 14 52 38 90 Sr -85948.127 2.124 8695.972 0.024 B- 545.934 1.406 89 907730.885 2.280 - 12 51 39 90 Y -86494.062 1.611 8693.345 0.018 B- 2278.474 1.609 89 907144.800 1.729 - 10 50 40 90 Zr -88772.535 0.118 8709.969 0.001 B- -6111.016 3.316 89 904698.758 0.126 - 8 49 41 90 Nb -82661.519 3.317 8633.376 0.037 B- -2489.016 3.316 89 911259.204 3.561 - 6 48 42 90 Mo -80172.503 3.463 8597.028 0.038 B- -9447.816 3.611 89 913931.272 3.717 - 4 47 43 90 Tc x -70724.687 1.025 8483.359 0.011 B- -5840.895 3.869 89 924073.921 1.100 - 2 46 44 90 Ru -64883.792 3.730 8409.768 0.041 B- -13184# 300# 89 930344.379 4.004 - 0 45 45 90 Rh x -51700# 300# 8255# 3# B- -11990# 500# 89 944498# 322# - -2 44 46 90 Pd x -39710# 400# 8113# 4# B- * 89 957370# 429# -0 25 58 33 91 As x -36896# 400# 8193# 4# B- 13684# 589# 90 960390# 429# - 23 57 34 91 Se x -50580.124 433.145 8334.837 4.760 B- 10527.169 433.159 90 945700.000 465.000 - 21 56 35 91 Br -n2p -61107.294 3.544 8441.923 0.039 B- 9866.671 4.190 90 934398.618 3.804 - 19 55 36 91 Kr x -70973.965 2.236 8541.751 0.025 B- 6771.072 8.115 90 923806.310 2.400 - 17 54 37 91 Rb -77745.037 7.801 8607.561 0.086 B- 5906.890 8.873 90 916537.265 8.375 - 15 53 38 91 Sr -83651.927 5.453 8663.875 0.060 B- 2699.369 5.247 90 910195.958 5.853 - 13 52 39 91 Y -86351.295 1.843 8684.941 0.020 B- 1544.271 1.840 90 907298.066 1.978 - 11 51 40 91 Zr -87895.566 0.105 8693.314 0.001 B- -1257.565 2.924 90 905640.223 0.112 - 9 50 41 91 Nb -86638.001 2.926 8670.897 0.032 B- -4429.180 6.744 90 906990.274 3.141 - 7 49 42 91 Mo -82208.821 6.238 8613.628 0.069 B- -6222.175 6.671 90 911745.195 6.696 - 5 48 43 91 Tc -75986.646 2.363 8536.655 0.026 B- -7746.824 3.242 90 918424.975 2.536 - 3 47 44 91 Ru -68239.823 2.221 8442.928 0.024 B- -9670# 298# 90 926741.532 2.384 - 1 46 45 91 Rh x -58570# 298# 8328# 3# B- -12639# 499# 90 937123# 320# - -1 45 46 91 Pd x -45930# 401# 8181# 4# B- * 90 950692# 430# -0 26 59 33 92 As x -30981# 500# 8127# 5# B- 15742# 640# 91 966740# 537# - 24 58 34 92 Se x -46724# 400# 8290# 4# B- 9509# 400# 91 949840# 429# - 22 57 35 92 Br x -56232.805 6.709 8384.911 0.073 B- 12536.514 7.232 91 939631.597 7.202 - 20 56 36 92 Kr x -68769.320 2.701 8512.674 0.029 B- 6003.118 6.692 91 926173.094 2.900 - 18 55 37 92 Rb -74772.438 6.123 8569.422 0.067 B- 8094.923 6.419 91 919728.481 6.573 - 16 54 38 92 Sr -82867.361 3.423 8648.906 0.037 B- 1949.132 9.384 91 911038.224 3.675 - 14 53 39 92 Y -84816.492 9.127 8661.589 0.099 B- 3642.535 9.127 91 908945.745 9.798 - 12 52 40 92 Zr -88459.028 0.102 8692.678 0.001 B- -2005.736 1.782 91 905035.322 0.109 - 10 51 41 92 Nb -86453.292 1.785 8662.372 0.019 B- 355.284 1.791 91 907188.568 1.915 - 8 50 42 92 Mo -86808.576 0.157 8657.730 0.002 B- -7882.884 3.106 91 906807.155 0.168 - 6 49 43 92 Tc -78925.693 3.102 8563.543 0.034 B- -4624.492 4.125 91 915269.779 3.330 - 4 48 44 92 Ru -74301.201 2.718 8504.773 0.030 B- -11302.114 5.153 91 920234.375 2.917 - 2 47 45 92 Rh x -62999.087 4.378 8373.420 0.048 B- -8419# 300# 91 932367.694 4.700 - 0 46 46 92 Pd x -54580# 300# 8273# 3# B- -17450# 583# 91 941406# 322# - -2 45 47 92 Ag x -37130# 500# 8075# 5# B- * 91 960139# 537# -0 25 59 34 93 Se x -40716# 400# 8223# 4# B- 12175# 588# 92 956290# 429# - 23 58 35 93 Br x -52890.230 430.816 8345.598 4.632 B- 11245.765 430.823 92 943220.000 462.500 - 21 57 36 93 Kr x -64135.994 2.515 8458.108 0.027 B- 8483.907 8.224 92 931147.174 2.700 - 19 56 37 93 Rb -72619.901 7.830 8540.920 0.084 B- 7465.938 8.876 92 922039.325 8.406 - 17 55 38 93 Sr -80085.838 7.554 8612.787 0.081 B- 4141.319 11.697 92 914024.311 8.109 - 15 54 39 93 Y -84227.157 10.488 8648.905 0.113 B- 2894.875 10.483 92 909578.422 11.259 - 13 53 40 93 Zr -87122.032 0.457 8671.620 0.005 B- 90.806 1.484 92 906470.646 0.490 - 11 52 41 93 Nb -87212.838 1.491 8664.184 0.016 B- -405.769 1.501 92 906373.161 1.600 - 9 51 42 93 Mo -n -86807.069 0.181 8651.409 0.002 B- -3200.963 1.004 92 906808.773 0.193 - 7 50 43 93 Tc -p -83606.106 1.012 8608.577 0.011 B- -6389.393 2.299 92 910245.149 1.086 - 5 49 44 93 Ru -77216.713 2.065 8531.462 0.022 B- -8204.913 3.343 92 917104.444 2.216 - 3 48 45 93 Rh -69011.800 2.629 8434.825 0.028 B- -10011# 301# 92 925912.781 2.821 - 1 47 46 93 Pd +p -59001# 300# 8319# 3# B- -12734# 501# 92 936660# 323# - -1 46 47 93 Ag x -46267# 401# 8173# 4# B- * 92 950330# 430# -0 26 60 34 94 Se x -36803# 500# 8180# 5# B- 10597# 583# 93 960490# 537# - 24 59 35 94 Br x -47400# 300# 8284# 3# B- 13948# 300# 93 949114# 322# - 22 58 36 94 Kr x -61347.772 12.109 8424.331 0.129 B- 7215.013 12.278 93 934140.454 13.000 - 20 57 37 94 Rb -68562.785 2.029 8492.764 0.022 B- 10282.926 2.623 93 926394.818 2.177 - 18 56 38 94 Sr -78845.711 1.663 8593.834 0.018 B- 3505.752 6.422 93 915355.643 1.785 - 16 55 39 94 Y -82351.463 6.380 8622.806 0.068 B- 4917.859 6.380 93 911592.063 6.849 - 14 54 40 94 Zr -87269.322 0.164 8666.801 0.002 B- -900.260 1.500 93 906312.524 0.175 - 12 53 41 94 Nb -86369.062 1.491 8648.901 0.016 B- 2045.002 1.494 93 907278.992 1.601 - 10 52 42 94 Mo -88414.065 0.141 8662.333 0.002 B- -4255.748 4.069 93 905083.592 0.151 - 8 51 43 94 Tc - -84158.317 4.071 8608.736 0.043 B- -1574.726 5.143 93 909652.325 4.370 - 6 50 44 94 Ru -82583.591 3.143 8583.661 0.033 B- -9675.978 4.615 93 911342.863 3.374 - 4 49 45 94 Rh -72907.613 3.379 8472.402 0.036 B- -6805.345 5.459 93 921730.453 3.627 - 2 48 46 94 Pd x -66102.268 4.287 8391.682 0.046 B- -13693# 400# 93 929036.292 4.602 - 0 47 47 94 Ag x -52410# 400# 8238# 4# B- -12270# 640# 93 943736# 429# - -2 46 48 94 Cd x -40140# 500# 8099# 5# B- * 93 956908# 537# -0 27 61 34 95 Se x -30460# 500# 8112# 5# B- 13311# 582# 94 967300# 537# - 25 60 35 95 Br x -43771# 298# 8244# 3# B- 12388# 299# 94 953010# 320# - 23 59 36 95 Kr x -56158.913 18.630 8365.995 0.196 B- 9732.580 27.513 94 939710.923 20.000 - 21 58 37 95 Rb -65891.493 20.245 8460.208 0.213 B- 9228.058 20.204 94 929262.568 21.734 - 19 57 38 95 Sr -75119.551 5.812 8549.111 0.061 B- 6089.296 7.240 94 919355.840 6.239 - 17 56 39 95 Y -81208.848 6.779 8604.973 0.071 B- 4451.092 6.772 94 912818.711 7.277 - 15 55 40 95 Zr -85659.940 0.869 8643.592 0.009 B- 1126.318 0.985 94 908040.267 0.933 - 13 54 41 95 Nb -86786.258 0.508 8647.212 0.005 B- 925.601 0.494 94 906831.115 0.545 - 11 53 42 95 Mo -87711.858 0.123 8648.720 0.001 B- -1690.518 5.078 94 905837.442 0.132 - 9 52 43 95 Tc -86021.341 5.080 8622.690 0.053 B- -2563.596 10.531 94 907652.287 5.453 - 7 51 44 95 Ru -83457.745 9.502 8587.470 0.100 B- -5117.138 10.266 94 910404.420 10.200 - 5 50 45 95 Rh -78340.606 3.886 8525.370 0.041 B- -8374.706 4.928 94 915897.895 4.171 - 3 49 46 95 Pd x -69965.900 3.031 8428.980 0.032 B- -10369# 298# 94 924888.512 3.253 - 1 48 47 95 Ag x -59597# 298# 8312# 3# B- -12966# 499# 94 936020# 320# - -1 47 48 95 Cd x -46631# 401# 8167# 4# B- * 94 949940# 430# -0 26 61 35 96 Br x -38163# 298# 8184# 3# B- 14916# 299# 95 959030# 320# - 24 60 36 96 Kr x -53079.678 20.493 8330.851 0.213 B- 8274.671 20.765 95 943016.618 22.000 - 22 59 37 96 Rb -61354.349 3.353 8408.896 0.035 B- 11569.808 9.115 95 934133.393 3.599 - 20 58 38 96 Sr -72924.157 8.475 8521.265 0.088 B- 5411.738 9.726 95 921712.692 9.098 - 18 57 39 96 Y -78335.895 6.088 8569.488 0.063 B- 7102.951 6.087 95 915902.953 6.535 - 16 56 40 96 Zr -85438.846 0.114 8635.327 0.001 B- 163.971 0.100 95 908277.621 0.122 - 14 55 41 96 Nb -85602.816 0.147 8628.886 0.002 B- 3192.059 0.107 95 908101.591 0.157 - 12 54 42 96 Mo -88794.876 0.120 8653.987 0.001 B- -2973.242 5.145 95 904674.774 0.128 - 10 53 43 96 Tc - -85821.634 5.146 8614.866 0.054 B- 258.738 5.146 95 907866.681 5.524 - 8 52 44 96 Ru -86080.372 0.170 8609.412 0.002 B- -6392.654 10.000 95 907588.914 0.182 - 6 51 45 96 Rh - -79687.718 10.001 8534.673 0.104 B- -3504.312 10.844 95 914451.710 10.737 - 4 50 46 96 Pd x -76183.406 4.194 8490.020 0.044 B- -11671.771 90.181 95 918213.744 4.502 - 2 49 47 96 Ag ep -64511.636 90.084 8360.290 0.938 B- -8939# 411# 95 930743.906 96.708 - 0 48 48 96 Cd x -55573# 401# 8259# 4# B- -17683# 641# 95 940340# 430# - -2 47 49 96 In x -37890# 500# 8067# 5# B- * 95 959323# 537# -0 27 62 35 97 Br x -34055# 401# 8140# 4# B- 13368# 421# 96 963440# 430# - 25 61 36 97 Kr x -47423.492 130.409 8269.864 1.344 B- 11095.645 130.423 96 949088.784 140.000 - 23 60 37 97 Rb -58519.137 1.912 8376.186 0.020 B- 10062.317 3.888 96 937177.118 2.052 - 21 59 38 97 Sr -68581.454 3.385 8471.856 0.035 B- 7539.969 7.521 96 926374.776 3.633 - 19 58 39 97 Y + -76121.424 6.719 8541.522 0.069 B- 6821.237 6.707 96 918280.286 7.213 - 17 57 40 97 Zr -82942.661 0.414 8603.779 0.004 B- 2663.115 4.248 96 910957.386 0.444 - 15 56 41 97 Nb -85605.776 4.249 8623.168 0.044 B- 1938.915 4.248 96 908098.414 4.561 - 13 55 42 97 Mo -87544.691 0.165 8635.092 0.002 B- -320.266 4.117 96 906016.903 0.176 - 11 54 43 97 Tc -87224.424 4.118 8623.725 0.042 B- -1103.873 4.956 96 906360.723 4.420 - 9 53 44 97 Ru -n -86120.552 2.763 8604.279 0.028 B- -3523.000 35.355 96 907545.779 2.965 - 7 52 45 97 Rh - -82597.552 35.463 8559.894 0.366 B- -4791.709 35.792 96 911327.876 38.071 - 5 51 46 97 Pd x -77805.843 4.844 8502.430 0.050 B- -6980.000 110.000 96 916471.987 5.200 - 3 50 47 97 Ag - -70825.843 110.107 8422.405 1.135 B- -10372# 318# 96 923965.326 118.204 - 1 49 48 97 Cd x -60454# 298# 8307# 3# B- -13264# 499# 96 935100# 320# - -1 48 49 97 In x -47189# 401# 8163# 4# B- * 96 949340# 430# -0 28 63 35 98 Br x -28250# 400# 8080# 4# B- 16061# 499# 97 969672# 429# - 26 62 36 98 Kr x -44311# 298# 8236# 3# B- 10058# 299# 97 952430# 320# - 24 61 37 98 Rb -54369.146 16.083 8330.729 0.164 B- 12053.958 16.403 97 941632.317 17.265 - 22 60 38 98 Sr -66423.104 3.226 8445.745 0.033 B- 5871.673 8.558 97 928691.860 3.463 - 20 59 39 98 Y p-2n -72294.777 7.929 8497.677 0.081 B- 8991.932 11.576 97 922388.360 8.511 - 18 58 40 98 Zr -81286.709 8.451 8581.448 0.086 B- 2237.890 9.819 97 912735.124 9.072 - 16 57 41 98 Nb -pn -83524.598 5.001 8596.301 0.051 B- 4591.373 5.003 97 910332.650 5.369 - 14 56 42 98 Mo -88115.972 0.174 8635.168 0.002 B- -1683.766 3.377 97 905403.608 0.186 - 12 55 43 98 Tc -86432.205 3.380 8610.004 0.034 B- 1792.653 7.157 97 907211.205 3.628 - 10 54 44 98 Ru -88224.858 6.463 8620.313 0.066 B- -5049.653 10.000 97 905286.713 6.937 - 8 53 45 98 Rh - -83175.205 11.906 8560.803 0.121 B- -1854.229 12.816 97 910707.740 12.782 - 6 52 46 98 Pd -81320.975 4.742 8533.899 0.048 B- -8254.560 33.098 97 912698.337 5.090 - 4 51 47 98 Ag -73066.415 32.907 8441.686 0.336 B- -5430.000 40.000 97 921559.972 35.327 - 2 50 48 98 Cd - -67636.415 51.797 8378.295 0.529 B- -13740# 303# 97 927389.317 55.605 - 0 49 49 98 In x -53896# 298# 8230# 3# B- * 97 942140# 320# -0 27 63 36 99 Kr x -38759# 401# 8178# 4# B- 12362# 401# 98 958390# 430# - 25 62 37 99 Rb x -51121.143 4.031 8295.300 0.041 B- 11400.258 6.223 98 945119.192 4.327 - 23 61 38 99 Sr -62521.401 4.741 8402.552 0.048 B- 8128.424 8.138 98 932880.511 5.089 - 21 60 39 99 Y x -70649.825 6.627 8476.755 0.067 B- 6970.792 12.409 98 924154.288 7.114 - 19 59 40 99 Zr -77620.617 10.502 8539.264 0.106 B- 4714.724 15.950 98 916670.835 11.274 - 17 58 41 99 Nb +p -82335.341 12.004 8578.985 0.121 B- 3634.758 12.006 98 911609.371 12.886 - 15 57 42 99 Mo -85970.098 0.229 8607.797 0.002 B- 1357.764 0.890 98 907707.298 0.245 - 13 56 43 99 Tc -87327.862 0.908 8613.610 0.009 B- 297.519 0.946 98 906249.678 0.974 - 11 55 44 99 Ru -87625.381 0.344 8608.712 0.003 B- -2044.081 6.690 98 905930.278 0.369 - 9 54 45 99 Rh -85581.300 6.697 8580.163 0.068 B- -3398.649 8.008 98 908124.690 7.189 - 7 53 46 99 Pd -82182.651 4.981 8537.930 0.050 B- -5470.178 8.004 98 911773.290 5.347 - 5 52 47 99 Ag x -76712.473 6.265 8474.774 0.063 B- -6781.350 6.462 98 917645.768 6.725 - 3 51 48 99 Cd x -69931.123 1.584 8398.373 0.016 B- -8555# 298# 98 924925.847 1.700 - 1 50 49 99 In x -61376# 298# 8304# 3# B- -13432# 585# 98 934110# 320# - -1 49 50 99 Sn x -47944# 503# 8160# 5# B- * 98 948530# 540# -0 28 64 36 100 Kr x -35052# 401# 8140# 4# B- 11195# 401# 99 962370# 430# - 26 63 37 100 Rb x -46247.064 19.561 8244.320 0.196 B- 13573.838 20.831 99 950351.731 21.000 - 24 62 38 100 Sr -59820.903 7.160 8372.234 0.072 B- 7506.493 13.273 99 935779.615 7.686 - 22 61 39 100 Y x -67327.396 11.186 8439.476 0.112 B- 9050.041 13.830 99 927721.063 12.008 - 20 60 40 100 Zr -76377.437 8.149 8522.153 0.081 B- 3419.963 11.398 99 918005.444 8.748 - 18 59 41 100 Nb IT -79797.399 7.986 8548.529 0.080 B- 6395.626 7.992 99 914333.963 8.573 - 16 58 42 100 Mo -86193.025 0.302 8604.662 0.003 B- -172.080 1.371 99 907467.976 0.323 - 14 57 43 100 Tc -n -86020.945 1.351 8595.118 0.014 B- 3206.444 1.376 99 907652.711 1.450 - 12 56 44 100 Ru -89227.389 0.343 8619.359 0.003 B- -3636.262 18.123 99 904210.452 0.368 - 10 55 45 100 Rh -85591.126 18.125 8575.172 0.181 B- -378.348 25.289 99 908114.141 19.458 - 8 54 46 100 Pd -85212.778 17.638 8563.566 0.176 B- -7074.819 18.333 99 908520.315 18.935 - 6 53 47 100 Ag x -78137.959 5.000 8484.994 0.050 B- -3943.363 5.273 99 916115.445 5.367 - 4 52 48 100 Cd -74194.596 1.677 8437.737 0.017 B- -9881.624 182.517 99 920348.820 1.799 - 2 51 49 100 In -64312.972 182.519 8331.097 1.825 B- -7030.000 240.000 99 930957.180 195.942 - 0 50 50 100 Sn - -57282.972 301.518 8252.974 3.015 B- * 99 938504.196 323.693 -0 29 65 36 101 Kr x -29128# 503# 8081# 5# B- 13717# 541# 100 968730# 540# - 27 64 37 101 Rb + -42845# 200# 8209# 2# B- 12480# 200# 100 954004# 215# - 25 63 38 101 Sr x -55324.907 8.480 8324.740 0.084 B- 9736.095 11.055 100 940606.266 9.103 - 23 62 39 101 Y x -65061.002 7.092 8413.391 0.070 B- 8104.955 10.933 100 930154.138 7.614 - 21 61 40 101 Zr -73165.957 8.339 8485.892 0.083 B- 5725.534 9.143 100 921453.110 8.951 - 19 60 41 101 Nb x -78891.491 3.749 8534.835 0.037 B- 4628.458 3.738 100 915306.496 4.024 - 17 59 42 101 Mo -n -83519.949 0.309 8572.915 0.003 B- 2824.645 24.002 100 910337.641 0.331 - 15 58 43 101 Tc + -86344.594 24.004 8593.136 0.238 B- 1613.520 24.000 100 907305.260 25.768 - 13 57 44 101 Ru -87958.114 0.415 8601.365 0.004 B- -545.697 5.852 100 905573.075 0.445 - 11 56 45 101 Rh -87412.416 5.841 8588.216 0.058 B- -1980.284 3.903 100 906158.905 6.270 - 9 55 46 101 Pd -85432.132 4.588 8560.864 0.045 B- -4097.759 6.668 100 908284.828 4.925 - 7 54 47 101 Ag x -81334.374 4.838 8512.546 0.048 B- -5497.918 5.063 100 912683.953 5.193 - 5 53 48 101 Cd x -75836.456 1.490 8450.365 0.015 B- -7223# 196# 100 918586.211 1.600 - 3 52 49 101 In x -68614# 196# 8371# 2# B- -8308# 358# 100 926340# 210# - 1 51 50 101 Sn ep -60305.626 300.005 8281.102 2.970 B- * 100 935259.244 322.068 -0 28 65 37 102 Rb x -37707# 298# 8157# 3# B- 14452# 306# 101 959520# 320# - 26 64 38 102 Sr x -52159.304 67.068 8291.220 0.658 B- 9013.873 67.191 101 944004.680 72.000 - 24 63 39 102 Y x -61173.177 4.077 8371.922 0.040 B- 10414.530 9.669 101 934327.889 4.377 - 22 62 40 102 Zr -71587.707 8.767 8466.355 0.086 B- 4716.837 9.053 101 923147.431 9.412 - 20 61 41 102 Nb -76304.544 2.545 8504.928 0.025 B- 7261.517 8.675 101 918083.697 2.732 - 18 60 42 102 Mo -83566.061 8.312 8568.450 0.081 B- 1006.817 12.373 101 910288.138 8.923 - 16 59 43 102 Tc -84572.878 9.166 8570.650 0.090 B- 4533.558 9.165 101 909207.275 9.840 - 14 58 44 102 Ru -89106.437 0.418 8607.427 0.004 B- -2323.119 6.396 101 904340.300 0.448 - 12 57 45 102 Rh - -86783.318 6.410 8576.981 0.063 B- 1119.853 6.406 101 906834.270 6.881 - 10 56 46 102 Pd -87903.171 0.554 8580.290 0.005 B- -5656.480 8.190 101 905632.058 0.594 - 8 55 47 102 Ag + -82246.691 8.171 8517.164 0.080 B- -2587.000 8.000 101 911704.540 8.771 - 6 54 48 102 Cd -79659.691 1.662 8484.131 0.016 B- -8964.807 4.865 101 914481.799 1.784 - 4 53 49 102 In -70694.884 4.573 8388.571 0.045 B- -5760.000 100.000 101 924105.916 4.909 - 2 52 50 102 Sn - -64934.884 100.105 8324.430 0.981 B- * 101 930289.530 107.466 -0 29 66 37 103 Rb x -33608# 401# 8117# 4# B- 13814# 446# 102 963920# 430# - 27 65 38 103 Sr x -47422# 196# 8243# 2# B- 11035# 196# 102 949090# 210# - 25 64 39 103 Y x -58457.575 11.204 8342.638 0.109 B- 9357.759 14.518 102 937243.208 12.028 - 23 63 40 103 Zr x -67815.334 9.232 8425.895 0.090 B- 7213.337 10.036 102 927197.240 9.911 - 21 62 41 103 Nb x -75028.671 3.935 8488.331 0.038 B- 5931.999 10.036 102 919453.403 4.224 - 19 61 42 103 Mo x -80960.670 9.232 8538.328 0.090 B- 3643.197 13.471 102 913085.140 9.911 - 17 60 43 103 Tc +p -84603.867 9.810 8566.103 0.095 B- 2663.304 9.808 102 909174.008 10.531 - 15 59 44 103 Ru -87267.171 0.443 8584.365 0.004 B- 764.538 2.260 102 906314.833 0.475 - 13 58 45 103 Rh -88031.708 2.301 8584.192 0.022 B- -574.519 2.420 102 905494.068 2.470 - 11 57 46 103 Pd -n -87457.189 0.950 8571.019 0.009 B- -2654.498 4.207 102 906110.840 1.019 - 9 56 47 103 Ag x -84802.692 4.099 8537.651 0.040 B- -4151.075 4.481 102 908960.560 4.400 - 7 55 48 103 Cd -80651.616 1.811 8489.754 0.018 B- -6019.026 9.754 102 913416.923 1.943 - 5 54 49 103 In -74632.591 9.625 8423.721 0.093 B- -7660.000 70.000 102 919878.613 10.332 - 3 53 50 103 Sn - -66972.591 70.659 8341.757 0.686 B- -10794# 306# 102 928101.962 75.855 - 1 52 51 103 Sb x -56178# 298# 8229# 3# B- * 102 939690# 320# -0 28 66 38 104 Sr x -44106# 298# 8210# 3# B- 9958# 499# 103 952650# 320# - 26 65 39 104 Y x -54064# 401# 8298# 4# B- 11660# 401# 103 941960# 430# - 24 64 40 104 Zr x -65724.060 9.325 8402.377 0.090 B- 6094.952 9.699 103 929442.315 10.011 - 22 63 41 104 Nb x -71819.012 2.737 8453.459 0.026 B- 8530.957 9.311 103 922899.115 2.938 - 20 62 42 104 Mo -80349.968 8.921 8527.965 0.086 B- 2153.476 24.167 103 913740.756 9.576 - 18 61 43 104 Tc -82503.444 24.888 8541.149 0.239 B- 5592.266 24.939 103 911428.905 26.718 - 16 60 44 104 Ru -88095.710 2.498 8587.399 0.024 B- -1136.362 3.364 103 905425.360 2.681 - 14 59 45 104 Rh -n -86959.348 2.303 8568.949 0.022 B- 2435.758 2.660 103 906645.295 2.472 - 12 58 46 104 Pd +n -89395.105 1.336 8584.848 0.013 B- -4278.654 4.000 103 904030.401 1.434 - 10 57 47 104 Ag - -85116.452 4.217 8536.184 0.041 B- -1148.072 4.537 103 908623.725 4.527 - 8 56 48 104 Cd -83968.380 1.673 8517.622 0.016 B- -7785.716 6.013 103 909856.230 1.795 - 6 55 49 104 In x -76182.665 5.775 8435.237 0.056 B- -4555.617 8.146 103 918214.540 6.200 - 4 54 50 104 Sn -71627.047 5.745 8383.911 0.055 B- -12453.427 122.579 103 923105.197 6.167 - 2 53 51 104 Sb -p -59173.620 122.444 8256.644 1.177 B- * 103 936474.502 131.449 -0 29 67 38 105 Sr x -38610# 503# 8156# 5# B- 12660# 1428# 104 958550# 540# - 27 66 39 105 Y x -51270.361 1336.694 8269.020 12.730 B- 10194.373 1336.749 104 944959.000 1435.000 - 25 65 40 105 Zr x -61464.734 12.118 8358.659 0.115 B- 8450.817 12.770 104 934014.890 13.008 - 23 64 41 105 Nb x -69915.551 4.028 8431.692 0.038 B- 7421.590 9.920 104 924942.564 4.324 - 21 63 42 105 Mo -77337.141 9.065 8494.923 0.086 B- 4952.947 35.031 104 916975.159 9.731 - 19 62 43 105 Tc -82290.088 35.264 8534.643 0.336 B- 3644.402 35.280 104 911657.952 37.857 - 17 61 44 105 Ru -85934.490 2.499 8561.900 0.024 B- 1916.752 2.851 104 907745.525 2.682 - 15 60 45 105 Rh -87851.243 2.502 8572.704 0.024 B- 566.646 2.346 104 905687.806 2.685 - 13 59 46 105 Pd -88417.888 1.138 8570.650 0.011 B- -1347.052 4.670 104 905079.487 1.222 - 11 58 47 105 Ag -87070.836 4.544 8550.370 0.043 B- -2736.997 4.362 104 906525.607 4.877 - 9 57 48 105 Cd -84333.839 1.392 8516.852 0.013 B- -4693.267 10.341 104 909463.895 1.494 - 7 56 49 105 In x -79640.572 10.246 8464.704 0.098 B- -6302.580 10.989 104 914502.324 11.000 - 5 55 50 105 Sn -73337.992 3.971 8397.228 0.038 B- -9322.510 22.185 104 921268.423 4.263 - 3 54 51 105 Sb +a -64015.482 21.827 8300.992 0.208 B- -11203.972 300.813 104 931276.549 23.431 - 1 53 52 105 Te -a -52811.510 300.020 8186.836 2.857 B- * 104 943304.508 322.084 -0 30 68 38 106 Sr x -34790# 600# 8119# 6# B- 11263# 783# 105 962651# 644# - 28 67 39 106 Y x -46053# 503# 8218# 5# B- 12497# 664# 105 950560# 540# - 26 66 40 106 Zr x -58549.987 433.145 8328.450 4.086 B- 7653.370 433.164 105 937144.000 465.000 - 24 65 41 106 Nb x -66203.357 4.122 8393.271 0.039 B- 9931.170 10.026 105 928927.768 4.424 - 22 64 42 106 Mo x -76134.528 9.140 8479.581 0.086 B- 3641.695 15.284 105 918266.218 9.812 - 20 63 43 106 Tc + -79776.223 12.250 8506.556 0.116 B- 6547.000 11.000 105 914356.697 13.150 - 18 62 44 106 Ru -86323.223 5.391 8560.940 0.051 B- 39.404 0.212 105 907328.203 5.787 - 16 61 45 106 Rh -86362.627 5.390 8553.931 0.051 B- 3544.901 5.335 105 907285.901 5.785 - 14 60 46 106 Pd -89907.527 1.106 8579.992 0.010 B- -2965.145 2.817 105 903480.293 1.186 - 12 59 47 106 Ag -86942.383 3.016 8544.639 0.028 B- 189.755 2.819 105 906663.507 3.237 - 10 58 48 106 Cd -87132.138 1.104 8539.048 0.010 B- -6524.004 12.176 105 906459.797 1.184 - 8 57 49 106 In - -80608.134 12.226 8470.120 0.115 B- -3254.447 13.244 105 913463.603 13.125 - 6 56 50 106 Sn -77353.687 5.091 8432.038 0.048 B- -10880.396 9.025 105 916957.396 5.465 - 4 55 51 106 Sb x -66473.292 7.452 8322.012 0.070 B- -8253.544 100.816 105 928637.982 8.000 - 2 54 52 106 Te -a -58219.748 100.541 8236.767 0.948 B- * 105 937498.526 107.934 -0 31 69 38 107 Sr x -28900# 700# 8064# 7# B- 13465# 862# 106 968975# 751# - 29 68 39 107 Y x -42364# 503# 8182# 5# B- 12015# 1230# 106 954520# 540# - 27 67 40 107 Zr x -54379.688 1122.450 8287.073 10.490 B- 9344.122 1122.479 106 941621.000 1205.000 - 25 66 41 107 Nb x -63723.810 8.023 8367.089 0.075 B- 8827.750 12.232 106 931589.672 8.612 - 23 65 42 107 Mo x -72551.560 9.233 8442.280 0.086 B- 6198.355 12.667 106 922112.692 9.912 - 21 64 43 107 Tc x -78749.914 8.673 8492.897 0.081 B- 5112.598 11.724 106 915458.485 9.310 - 19 63 44 107 Ru -nn -83862.512 8.673 8533.366 0.081 B- 3001.191 14.847 106 909969.885 9.310 - 17 62 45 107 Rh +p -86863.703 12.051 8554.103 0.113 B- 1508.936 12.111 106 906747.974 12.937 - 15 61 46 107 Pd -88372.639 1.201 8560.894 0.011 B- 34.031 2.318 106 905128.064 1.289 - 13 60 47 107 Ag -88406.670 2.382 8553.900 0.022 B- -1416.409 2.567 106 905091.531 2.557 - 11 59 48 107 Cd -86990.261 1.665 8533.351 0.016 B- -3426.000 11.000 106 906612.108 1.787 - 9 58 49 107 In - -83564.261 11.125 8494.021 0.104 B- -5052.033 12.327 106 910290.071 11.943 - 7 57 50 107 Sn x -78512.228 5.310 8439.494 0.050 B- -7858.989 6.738 106 915713.651 5.700 - 5 56 51 107 Sb -70653.239 4.148 8358.734 0.039 B- -10113.913 70.952 106 924150.624 4.452 - 3 55 52 107 Te -a -60539.326 70.830 8256.899 0.662 B- -11110# 308# 106 935008.356 76.039 - 1 54 53 107 I x -49430# 300# 8146# 3# B- * 106 946935# 322# -0 30 69 39 108 Y x -37297# 596# 8134# 6# B- 14056# 718# 107 959960# 640# - 28 68 40 108 Zr x -51353# 401# 8257# 4# B- 8193# 401# 107 944870# 430# - 26 67 41 108 Nb x -59545.765 8.237 8325.665 0.076 B- 11210.177 12.373 107 936074.988 8.842 - 24 66 42 108 Mo x -70755.942 9.233 8422.219 0.085 B- 5166.835 12.734 107 924040.367 9.912 - 22 65 43 108 Tc x -75922.778 8.769 8462.816 0.081 B- 7738.573 11.790 107 918493.541 9.413 - 20 64 44 108 Ru -3n -83661.350 8.680 8527.225 0.080 B- 1370.370 16.469 107 910185.841 9.318 - 18 63 45 108 Rh x -85031.721 13.996 8532.670 0.130 B- 4492.486 14.039 107 908714.688 15.024 - 16 62 46 108 Pd -89524.206 1.108 8567.023 0.010 B- -1917.444 2.633 107 903891.805 1.189 - 14 61 47 108 Ag -n -87606.763 2.388 8542.025 0.022 B- 1645.651 2.639 107 905950.266 2.563 - 12 60 48 108 Cd -89252.414 1.123 8550.019 0.010 B- -5132.595 8.584 107 904183.587 1.205 - 10 59 49 108 In -84119.819 8.641 8495.251 0.080 B- -2049.881 9.836 107 909693.655 9.276 - 8 58 50 108 Sn -82069.938 5.382 8469.027 0.050 B- -9624.607 7.692 107 911894.292 5.778 - 6 57 51 108 Sb x -72445.331 5.496 8372.666 0.051 B- -6663.664 7.712 107 922226.734 5.900 - 4 56 52 108 Te -65781.667 5.411 8303.721 0.050 B- -13132.062 132.370 107 929380.471 5.808 - 2 55 53 108 I -a -52649.605 132.260 8174.884 1.225 B- * 107 943478.321 141.986 -0 31 70 39 109 Y x -33200# 700# 8096# 6# B- 12992# 862# 108 964358# 751# - 29 69 40 109 Zr x -46193# 503# 8208# 5# B- 10497# 566# 108 950410# 540# - 27 68 41 109 Nb x -56689.794 258.490 8297.130 2.371 B- 9976.202 258.732 108 939141.000 277.500 - 25 67 42 109 Mo x -66665.996 11.188 8381.477 0.103 B- 7616.780 14.787 108 928431.106 12.010 - 23 66 43 109 Tc x -74282.775 9.669 8444.178 0.089 B- 6455.626 12.657 108 920254.156 10.380 - 21 65 44 109 Ru -4n -80738.401 8.954 8496.227 0.082 B- 4261.054 9.822 108 913323.756 9.612 - 19 64 45 109 Rh -84999.455 4.039 8528.142 0.037 B- 2607.021 4.187 108 908749.326 4.336 - 17 63 46 109 Pd -87606.476 1.114 8544.882 0.010 B- 1112.950 1.402 108 905950.574 1.195 - 15 62 47 109 Ag -88719.426 1.287 8547.915 0.012 B- -215.105 1.780 108 904755.773 1.381 - 13 61 48 109 Cd -88504.321 1.536 8538.764 0.014 B- -2014.809 4.066 108 904986.698 1.649 - 11 60 49 109 In -86489.511 3.969 8513.102 0.036 B- -3859.327 8.887 108 907149.685 4.261 - 9 59 50 109 Sn -82630.184 7.949 8470.518 0.073 B- -6379.206 8.807 108 911292.843 8.533 - 7 58 51 109 Sb -76250.977 5.265 8404.815 0.048 B- -8535.587 6.850 108 918141.204 5.652 - 5 57 52 109 Te -67715.390 4.382 8319.330 0.040 B- -10042.894 8.030 108 927304.534 4.704 - 3 56 53 109 I -p -57672.496 6.729 8220.016 0.062 B- -11502.948 300.183 108 938086.025 7.223 - 1 55 54 109 Xe -a -46169.548 300.108 8107.306 2.753 B- * 108 950434.948 322.178 -0 30 70 40 110 Zr x -42886# 596# 8177# 5# B- 9424# 1029# 109 953960# 640# - 28 69 41 110 Nb x -52309.909 838.345 8255.260 7.621 B- 12232.677 838.694 109 943843.000 900.000 - 26 68 42 110 Mo x -64542.585 24.223 8359.354 0.220 B- 6491.925 26.018 109 930710.680 26.004 - 24 67 43 110 Tc x -71034.510 9.497 8411.259 0.086 B- 9038.066 12.509 109 923741.312 10.195 - 22 66 44 110 Ru -80072.576 8.924 8486.311 0.081 B- 2756.110 19.404 109 914038.548 9.580 - 20 65 45 110 Rh -82828.686 17.805 8504.254 0.162 B- 5502.218 17.797 109 911079.742 19.114 - 18 64 46 110 Pd -88330.905 0.612 8547.162 0.006 B- -873.603 1.378 109 905172.868 0.657 - 16 63 47 110 Ag -87457.302 1.286 8532.108 0.012 B- 2890.667 1.277 109 906110.719 1.380 - 14 62 48 110 Cd -90347.969 0.380 8551.275 0.003 B- -3878.000 11.547 109 903007.460 0.407 - 12 61 49 110 In - -86469.969 11.553 8508.908 0.105 B- -627.985 17.980 109 907170.665 12.402 - 10 60 50 110 Sn x -85841.983 13.777 8496.087 0.125 B- -8392.250 15.012 109 907844.835 14.790 - 8 59 51 110 Sb x -77449.734 5.962 8412.681 0.054 B- -5219.923 8.875 109 916854.286 6.400 - 6 58 52 110 Te -72229.811 6.575 8358.115 0.060 B- -11765.635 50.978 109 922458.104 7.058 - 4 57 53 110 I -a -60464.176 50.552 8244.043 0.460 B- -8541.551 112.934 109 935089.033 54.270 - 2 56 54 110 Xe -a -51922.625 100.988 8159.280 0.918 B- * 109 944258.765 108.415 -0 31 71 40 111 Zr x -37560# 700# 8128# 6# B- 11316# 760# 110 959678# 751# - 29 70 41 111 Nb x -48875# 298# 8223# 3# B- 11064# 298# 110 947530# 320# - 27 69 42 111 Mo + -59939.761 12.578 8315.292 0.113 B- 9084.861 6.800 110 935652.016 13.502 - 25 68 43 111 Tc x -69024.622 10.581 8390.089 0.095 B- 7760.649 13.848 110 925899.016 11.359 - 23 67 44 111 Ru x -76785.271 9.682 8452.957 0.087 B- 5519.181 11.860 110 917567.616 10.394 - 21 66 45 111 Rh -82304.452 6.850 8495.631 0.062 B- 3681.435 6.887 110 911642.531 7.354 - 19 65 46 111 Pd -n -85985.888 0.731 8521.749 0.007 B- 2229.560 1.572 110 907690.347 0.785 - 17 64 47 111 Ag + -88215.447 1.459 8534.787 0.013 B- 1036.800 1.414 110 905296.816 1.565 - 15 63 48 111 Cd -89252.247 0.357 8537.079 0.003 B- -860.204 3.417 110 904183.766 0.383 - 13 62 49 111 In -88392.043 3.424 8522.282 0.031 B- -2453.456 6.337 110 905107.233 3.675 - 11 61 50 111 Sn +n -85938.587 5.336 8493.130 0.048 B- -5101.851 10.334 110 907741.126 5.728 - 9 60 51 111 Sb x -80836.736 8.849 8440.120 0.080 B- -7249.259 10.937 110 913218.189 9.500 - 7 59 52 111 Te x -73587.477 6.427 8367.763 0.058 B- -8633.692 7.994 110 921000.589 6.900 - 5 58 53 111 I -64953.785 4.754 8282.934 0.043 B- -10558.252 86.830 110 930269.239 5.103 - 3 57 54 111 Xe -a -54395.534 86.700 8180.766 0.781 B- -11575# 214# 110 941603.989 93.076 - 1 56 55 111 Cs x -42821# 196# 8069# 2# B- * 110 954030# 210# -0 32 72 40 112 Zr x -33810# 700# 8094# 6# B- 10463# 760# 111 963703# 751# - 30 71 41 112 Nb x -44274# 298# 8180# 3# B- 13190# 357# 111 952470# 320# - 28 70 42 112 Mo x -57464# 196# 8291# 2# B- 7795# 196# 111 938310# 210# - 26 69 43 112 Tc x -65258.938 5.515 8353.621 0.049 B- 10371.881 11.060 111 929941.644 5.920 - 24 68 44 112 Ru x -75630.818 9.599 8439.242 0.086 B- 4100.685 45.118 111 918806.972 10.305 - 22 67 45 112 Rh -79731.503 44.085 8468.870 0.394 B- 6590.059 43.927 111 914404.705 47.327 - 20 66 46 112 Pd -86321.562 6.544 8520.724 0.058 B- 262.156 6.978 111 907329.986 7.025 - 18 65 47 112 Ag x -86583.718 2.422 8516.080 0.022 B- 3991.141 2.435 111 907048.550 2.600 - 16 64 48 112 Cd -90574.859 0.250 8544.730 0.002 B- -2584.728 4.243 111 902763.883 0.268 - 14 63 49 112 In -87990.131 4.251 8514.667 0.038 B- 664.925 4.243 111 905538.704 4.563 - 12 62 50 112 Sn -88655.056 0.294 8513.618 0.003 B- -7056.091 17.832 111 904824.877 0.315 - 10 61 51 112 Sb x -81598.965 17.829 8443.632 0.159 B- -4031.457 19.702 111 912399.903 19.140 - 8 60 52 112 Te x -77567.508 8.383 8400.652 0.075 B- -10504.178 13.239 111 916727.850 9.000 - 6 59 53 112 I x -67063.330 10.246 8299.879 0.091 B- -7036.991 13.175 111 928004.550 11.000 - 4 58 54 112 Xe -a -60026.338 8.283 8230.064 0.074 B- -13736.062 87.190 111 935559.071 8.891 - 2 57 55 112 Cs -p -46290.277 86.796 8100.435 0.775 B- * 111 950305.341 93.178 -0 31 72 41 113 Nb x -40511# 401# 8146# 4# B- 11979# 500# 112 956510# 430# - 29 71 42 113 Mo x -52490# 300# 8245# 3# B- 10322# 300# 112 943650# 322# - 27 70 43 113 Tc x -62811.541 3.353 8329.464 0.030 B- 9056.578 37.028 112 932569.033 3.600 - 25 69 44 113 Ru -71868.119 36.875 8402.688 0.326 B- 6899.417 37.558 112 922846.396 39.587 - 23 68 45 113 Rh x -78767.536 7.130 8456.821 0.063 B- 4823.555 9.881 112 915439.567 7.653 - 21 67 46 113 Pd x -83591.092 6.945 8492.584 0.061 B- 3435.731 18.033 112 910261.267 7.455 - 19 66 47 113 Ag + -87026.822 16.643 8516.065 0.147 B- 2016.462 16.641 112 906572.858 17.866 - 17 65 48 113 Cd -89043.284 0.244 8526.987 0.002 B- 323.833 0.265 112 904408.097 0.262 - 15 64 49 113 In -89367.117 0.188 8522.929 0.002 B- -1038.985 1.573 112 904060.448 0.202 - 13 63 50 113 Sn -88328.132 1.575 8506.811 0.014 B- -3911.164 17.121 112 905175.845 1.690 - 11 62 51 113 Sb - -84416.968 17.193 8465.275 0.152 B- -6069.939 32.810 112 909374.652 18.457 - 9 61 52 113 Te x -78347.029 27.945 8404.636 0.247 B- -7227.522 29.070 112 915891.000 30.000 - 7 60 53 113 I x -71119.507 8.011 8333.752 0.071 B- -8915.889 10.533 112 923650.064 8.600 - 5 59 54 113 Xe -62203.618 6.840 8247.927 0.061 B- -10439.088 10.970 112 933221.666 7.342 - 3 58 55 113 Cs -p -51764.530 8.577 8148.622 0.076 B- -11980# 298# 112 944428.488 9.207 - 1 57 56 113 Ba x -39784# 298# 8036# 3# B- * 112 957290# 320# -0 32 73 41 114 Nb x -35387# 503# 8100# 4# B- 14420# 585# 113 962010# 540# - 30 72 42 114 Mo x -49807# 298# 8220# 3# B- 8793# 526# 113 946530# 320# - 28 71 43 114 Tc x -58600.288 433.145 8290.259 3.800 B- 11621.524 433.159 113 937090.000 465.000 - 26 70 44 114 Ru x -70221.811 3.550 8385.340 0.031 B- 5488.813 71.643 113 924613.780 3.811 - 24 69 45 114 Rh -75710.625 71.561 8426.624 0.628 B- 7780.319 71.891 113 918721.296 76.824 - 22 68 46 114 Pd x -83490.943 6.945 8488.010 0.061 B- 1439.856 8.311 113 910368.780 7.456 - 20 67 47 114 Ag x -84930.800 4.564 8493.778 0.040 B- 5084.133 4.573 113 908823.031 4.900 - 18 66 48 114 Cd -90014.932 0.276 8531.513 0.002 B- -1445.132 0.382 113 903364.990 0.296 - 16 65 49 114 In -88569.801 0.301 8511.973 0.003 B- 1989.923 0.302 113 904916.402 0.323 - 14 64 50 114 Sn -90559.723 0.029 8522.566 0.000 B- -6063.149 21.838 113 902780.132 0.031 - 12 63 51 114 Sb -84496.574 21.838 8462.518 0.192 B- -2608.005 35.466 113 909289.191 23.444 - 10 62 52 114 Te x -81888.569 27.945 8432.778 0.245 B- -9092# 152# 113 912089.000 30.000 - 8 61 53 114 I x -72796# 149# 8346# 1# B- -5710# 149# 113 921850# 160# - 6 60 54 114 Xe x -67085.890 11.178 8289.205 0.098 B- -12403.629 71.976 113 927980.331 12.000 - 4 59 55 114 Cs -a -54682.261 71.102 8173.538 0.624 B- -8776.835 124.892 113 941296.175 76.331 - 2 58 56 114 Ba -a -45905.426 102.676 8089.686 0.901 B- * 113 950718.495 110.227 -0 33 74 41 115 Nb x -31354# 503# 8065# 4# B- 13395# 643# 114 966340# 540# - 31 73 42 115 Mo x -44749# 401# 8175# 3# B- 11571# 885# 114 951960# 430# - 29 72 43 115 Tc x -56319.990 789.441 8268.527 6.865 B- 9869.744 794.386 114 939538.000 847.500 - 27 71 44 115 Ru x -66189.734 88.496 8347.547 0.770 B- 8040.097 88.790 114 928942.393 95.004 - 25 70 45 115 Rh x -74229.831 7.316 8410.658 0.064 B- 6196.554 15.350 114 920310.993 7.854 - 23 69 46 115 Pd -80426.386 13.546 8457.738 0.118 B- 4556.268 21.649 114 913658.718 14.541 - 21 68 47 115 Ag -84982.654 18.268 8490.555 0.159 B- 3101.825 18.274 114 908767.363 19.611 - 19 67 48 115 Cd -88084.479 0.651 8510.724 0.006 B- 1451.867 0.651 114 905437.417 0.699 - 17 66 49 115 In -89536.346 0.012 8516.546 0.000 B- 497.489 0.010 114 903878.773 0.012 - 15 65 50 115 Sn -90033.835 0.015 8514.069 0.000 B- -3030.432 16.025 114 903344.697 0.016 - 13 64 51 115 Sb x -87003.403 16.025 8480.915 0.139 B- -4940.644 32.214 114 906598.000 17.203 - 11 63 52 115 Te x -82062.759 27.945 8431.150 0.243 B- -5724.962 40.184 114 911902.000 30.000 - 9 62 53 115 I x -76337.797 28.876 8374.564 0.251 B- -7681.049 31.313 114 918048.000 31.000 - 7 61 54 115 Xe x -68656.748 12.109 8300.970 0.105 B- -8957# 103# 114 926293.945 13.000 - 5 60 55 115 Cs x -59699# 102# 8216# 1# B- -10680# 225# 114 935910# 110# - 3 59 56 115 Ba x -49020# 200# 8117# 2# B- * 114 947375# 215# -0 32 74 42 116 Mo x -41500# 500# 8146# 4# B- 9956# 582# 115 955448# 537# - 30 73 43 116 Tc x -51456# 298# 8225# 3# B- 12613# 298# 115 944760# 320# - 28 72 44 116 Ru x -64068.909 3.726 8326.883 0.032 B- 6667.213 73.926 115 931219.193 4.000 - 26 71 45 116 Rh -70736.122 73.832 8377.615 0.636 B- 9095.512 74.169 115 924061.645 79.261 - 24 70 46 116 Pd x -79831.635 7.132 8449.280 0.061 B- 2711.019 7.842 115 914297.210 7.656 - 22 69 47 116 Ag x -82542.653 3.260 8465.907 0.028 B- 6169.827 3.264 115 911386.812 3.500 - 20 68 48 116 Cd -88712.480 0.160 8512.350 0.001 B- -462.731 0.272 115 904763.230 0.172 - 18 67 49 116 In -n -88249.749 0.220 8501.617 0.002 B- 3276.221 0.240 115 905259.992 0.236 - 16 66 50 116 Sn -91525.970 0.096 8523.116 0.001 B- -4703.820 5.160 115 901742.824 0.103 - 14 65 51 116 Sb -86822.150 5.160 8475.821 0.044 B- -1553.189 28.417 115 906792.583 5.539 - 12 64 52 116 Te x -85268.961 27.945 8455.687 0.241 B- -7776.725 100.553 115 908460.000 30.000 - 10 63 53 116 I + -77492.236 96.592 8381.902 0.833 B- -4445.512 95.707 115 916808.658 103.695 - 8 62 54 116 Xe x -73046.724 13.041 8336.834 0.112 B- -11004# 101# 115 921581.112 14.000 - 6 61 55 116 Cs ea -62043# 100# 8235# 1# B- -7463# 224# 115 933395# 108# - 4 60 56 116 Ba x -54580# 200# 8164# 2# B- -13935# 371# 115 941406# 215# - 2 59 57 116 La -a -40645# 312# 8037# 3# B- * 115 956365# 335# -0 33 75 42 117 Mo x -36170# 500# 8100# 4# B- 12212# 641# 116 961170# 537# - 31 74 43 117 Tc x -48382# 401# 8197# 3# B- 11108# 590# 116 948060# 430# - 29 73 44 117 Ru x -59489.865 433.145 8285.562 3.702 B- 9407.508 433.236 116 936135.000 465.000 - 27 72 45 117 Rh x -68897.373 8.892 8359.281 0.076 B- 7527.104 11.411 116 926035.623 9.546 - 25 71 46 117 Pd -76424.477 7.252 8416.929 0.062 B- 5757.537 14.766 116 917954.944 7.785 - 23 70 47 117 Ag -82182.014 13.572 8459.452 0.116 B- 4236.375 13.610 116 911773.974 14.570 - 21 69 48 117 Cd -n -86418.389 1.013 8488.973 0.009 B- 2524.653 4.983 116 907226.038 1.087 - 19 68 49 117 In -88943.042 4.881 8503.865 0.042 B- 1454.709 4.857 116 904515.712 5.239 - 17 67 50 117 Sn -90397.751 0.483 8509.611 0.004 B- -1758.212 8.445 116 902954.017 0.518 - 15 66 51 117 Sb -88639.539 8.437 8487.897 0.072 B- -3544.128 13.079 116 904841.535 9.057 - 13 65 52 117 Te -85095.411 13.456 8450.919 0.115 B- -4659.334 28.673 116 908646.313 14.446 - 11 64 53 117 I -80436.077 26.196 8404.409 0.224 B- -6250.740 28.177 116 913648.314 28.123 - 9 63 54 117 Xe x -74185.337 10.378 8344.297 0.089 B- -7692.245 63.267 116 920358.760 11.141 - 7 62 55 117 Cs x -66493.092 62.410 8271.864 0.533 B- -9035.338 258.002 116 928616.726 67.000 - 5 61 56 117 Ba ep -57457.753 250.340 8187.953 2.140 B- -10987# 321# 116 938316.561 268.750 - 3 60 57 117 La -p -46471# 200# 8087# 2# B- * 116 950111# 215# -0 34 76 42 118 Mo x -32630# 500# 8069# 4# B- 11159# 641# 117 964970# 537# - 32 75 43 118 Tc x -43790# 401# 8157# 3# B- 13470# 448# 117 952990# 430# - 30 74 44 118 Ru x -57260# 200# 8265# 2# B- 7628# 202# 117 938529# 215# - 28 73 45 118 Rh x -64887.460 24.235 8322.858 0.205 B- 10501.286 24.342 117 930340.443 26.017 - 26 72 46 118 Pd -75388.746 2.491 8405.222 0.021 B- 4165.046 3.539 117 919066.847 2.673 - 24 71 47 118 Ag x -79553.792 2.515 8433.889 0.021 B- 7147.849 20.158 117 914595.487 2.700 - 22 70 48 118 Cd -nn -86701.641 20.001 8487.834 0.169 B- 526.570 21.450 117 906921.955 21.471 - 20 69 49 118 In -87228.211 7.752 8485.667 0.066 B- 4424.643 7.740 117 906356.659 8.322 - 18 68 50 118 Sn -91652.853 0.499 8516.533 0.004 B- -3656.640 2.975 117 901606.609 0.536 - 16 67 51 118 Sb - -87996.213 3.016 8478.915 0.026 B- -299.630 18.726 117 905532.174 3.238 - 14 66 52 118 Te +nn -87696.584 18.481 8469.746 0.157 B- -6725.536 27.056 117 905853.839 19.840 - 12 65 53 118 I x -80971.048 19.760 8406.120 0.167 B- -2891.991 22.320 117 913074.000 21.213 - 10 64 54 118 Xe x -78079.057 10.378 8374.981 0.088 B- -9669.689 16.442 117 916178.680 11.141 - 8 63 55 118 Cs IT -68409.367 12.753 8286.404 0.108 B- -6055# 196# 117 926559.519 13.690 - 6 62 56 118 Ba x -62354# 196# 8228# 2# B- -12794# 358# 117 933060# 210# - 4 61 57 118 La x -49560# 300# 8113# 3# B- * 117 946795# 322# -0 33 76 43 119 Tc x -40371# 503# 8128# 4# B- 12193# 585# 118 956660# 540# - 31 75 44 119 Ru x -52564# 298# 8224# 3# B- 10259# 298# 118 943570# 320# - 29 74 45 119 Rh x -62822.794 9.315 8303.394 0.078 B- 8585.108 12.440 118 932556.952 10.000 - 27 73 46 119 Pd x -71407.902 8.245 8368.964 0.069 B- 7237.863 16.855 118 923340.459 8.851 - 25 72 47 119 Ag -78645.765 14.703 8423.212 0.124 B- 5331.303 35.926 118 915570.293 15.783 - 23 71 48 119 Cd -83977.068 37.695 8461.438 0.317 B- 3722.212 38.088 118 909846.903 40.467 - 21 70 49 119 In -87699.281 7.307 8486.143 0.061 B- 2365.742 7.336 118 905850.944 7.844 - 19 69 50 119 Sn -90065.022 0.725 8499.449 0.006 B- -590.843 7.689 118 903311.216 0.778 - 17 68 51 119 Sb -89474.180 7.701 8487.910 0.065 B- -2293.000 2.000 118 903945.512 8.267 - 15 67 52 119 Te - -87181.180 7.957 8462.066 0.067 B- -3415.650 29.055 118 906407.148 8.541 - 13 66 53 119 I x -83765.530 27.945 8426.789 0.235 B- -4971.117 29.810 118 910074.000 30.000 - 11 65 54 119 Xe x -78794.413 10.378 8378.441 0.087 B- -6489.361 17.379 118 915410.713 11.141 - 9 64 55 119 Cs IT -72305.051 13.940 8317.334 0.117 B- -7714.965 200.754 118 922377.330 14.965 - 7 63 56 119 Ba ep -64590.086 200.269 8245.928 1.683 B- -9801# 361# 118 930659.686 214.997 - 5 62 57 119 La x -54790# 300# 8157# 3# B- -10849# 583# 118 941181# 322# - 3 61 58 119 Ce x -43940# 500# 8059# 4# B- * 118 952828# 537# -0 34 77 43 120 Tc x -35518# 503# 8087# 4# B- 14494# 643# 119 961870# 540# - 32 76 44 120 Ru x -50012# 401# 8201# 3# B- 8803# 446# 119 946310# 430# - 30 75 45 120 Rh x -58815# 196# 8268# 2# B- 11466# 196# 119 936860# 210# - 28 74 46 120 Pd -70280.050 2.291 8357.085 0.019 B- 5371.451 5.024 119 924551.258 2.459 - 26 73 47 120 Ag x -75651.502 4.471 8395.327 0.037 B- 8305.853 5.820 119 918784.767 4.800 - 24 72 48 120 Cd x -83957.354 3.726 8458.023 0.031 B- 1771.015 40.183 119 909868.067 4.000 - 22 71 49 120 In + -85728.369 40.010 8466.262 0.333 B- 5370.000 40.000 119 907966.805 42.952 - 20 70 50 120 Sn -91098.369 0.896 8504.492 0.007 B- -2680.608 7.140 119 902201.873 0.962 - 18 69 51 120 Sb - -88417.761 7.196 8475.635 0.060 B- 950.226 7.811 119 905079.624 7.725 - 16 68 52 120 Te -89367.987 3.085 8477.034 0.026 B- -5615.000 15.000 119 904059.514 3.311 - 14 67 53 120 I - -83752.987 15.314 8423.722 0.128 B- -1580.563 19.343 119 910087.465 16.440 - 12 66 54 120 Xe x -82172.423 11.817 8404.031 0.098 B- -8283.785 15.461 119 911784.270 12.686 - 10 65 55 120 Cs IT -73888.639 9.970 8328.480 0.083 B- -5000.000 300.000 119 920677.279 10.702 - 8 64 56 120 Ba - -68888.639 300.166 8280.294 2.501 B- -11319# 424# 119 926045.000 322.241 - 6 63 57 120 La x -57570# 300# 8179# 2# B- -7970# 583# 119 938196# 322# - 4 62 58 120 Ce x -49600# 500# 8107# 4# B- * 119 946752# 537# -0 35 78 43 121 Tc x -31780# 500# 8056# 4# B- 13267# 641# 120 965883# 537# - 33 77 44 121 Ru x -45047# 401# 8159# 3# B- 11203# 738# 120 951640# 430# - 31 76 45 121 Rh x -56250.128 619.444 8245.239 5.119 B- 9932.201 619.453 120 939613.000 665.000 - 29 75 46 121 Pd x -66182.329 3.353 8320.858 0.028 B- 8220.492 12.565 120 928950.343 3.600 - 27 74 47 121 Ag x -74402.821 12.109 8382.330 0.100 B- 6671.005 12.264 120 920125.282 13.000 - 25 73 48 121 Cd x -81073.826 1.942 8430.996 0.016 B- 4762.148 27.483 120 912963.663 2.085 - 23 72 49 121 In +p -85835.974 27.414 8463.887 0.227 B- 3361.291 27.408 120 907851.286 29.430 - 21 71 50 121 Sn -89197.265 0.955 8485.201 0.008 B- 403.057 2.690 120 904242.792 1.025 - 19 70 51 121 Sb -89600.321 2.582 8482.066 0.021 B- -1054.819 25.767 120 903810.093 2.771 - 17 69 52 121 Te -88545.502 25.850 8466.883 0.214 B- -2294.053 26.047 120 904942.488 27.751 - 15 68 53 121 I -86251.449 5.356 8441.458 0.044 B- -3770.463 11.558 120 907405.255 5.749 - 13 67 54 121 Xe -82480.986 10.243 8403.832 0.085 B- -5378.654 13.979 120 911453.014 10.995 - 11 66 55 121 Cs -77102.331 14.290 8352.914 0.118 B- -6357.495 141.176 120 917227.238 15.340 - 9 65 56 121 Ba - -70744.837 141.898 8293.907 1.173 B- -8555# 332# 120 924052.289 152.333 - 7 64 57 121 La x -62190# 300# 8217# 2# B- -9500# 500# 120 933236# 322# - 5 63 58 121 Ce x -52690# 401# 8132# 3# B- -11268# 641# 120 943435# 430# - 3 62 59 121 Pr -p -41422# 500# 8032# 4# B- * 120 955532# 537# -0 34 78 44 122 Ru x -42150# 500# 8135# 4# B- 9930# 583# 121 954750# 537# - 32 77 45 122 Rh x -52080# 300# 8210# 2# B- 12536# 301# 121 944090# 322# - 30 76 46 122 Pd x -64616.161 19.561 8305.975 0.160 B- 6489.948 42.909 121 930631.694 21.000 - 28 75 47 122 Ag x -71106.108 38.191 8352.758 0.313 B- 9506.265 38.260 121 923664.448 41.000 - 26 74 48 122 Cd -80612.374 2.299 8424.266 0.019 B- 2960.368 50.110 121 913459.052 2.468 - 24 73 49 122 In + -83572.741 50.057 8442.118 0.410 B- 6368.592 50.000 121 910280.966 53.738 - 22 72 50 122 Sn -89941.333 2.395 8487.907 0.020 B- -1605.963 3.384 121 903444.001 2.570 - 20 71 51 122 Sb -88335.370 2.578 8468.331 0.021 B- 1979.089 2.127 121 905168.074 2.768 - 18 70 52 122 Te -90314.460 1.507 8478.140 0.012 B- -4234.000 5.000 121 903043.434 1.617 - 16 69 53 122 I - -86080.460 5.222 8437.023 0.043 B- -725.483 12.277 121 907588.820 5.606 - 14 68 54 122 Xe x -85354.977 11.111 8424.664 0.091 B- -7210.218 35.472 121 908367.658 11.928 - 12 67 55 122 Cs -78144.759 33.687 8359.151 0.276 B- -3535.815 43.769 121 916108.145 36.164 - 10 66 56 122 Ba x -74608.944 27.945 8323.756 0.229 B- -10066# 299# 121 919904.000 30.000 - 8 65 57 122 La x -64543# 298# 8235# 2# B- -6669# 499# 121 930710# 320# - 6 64 58 122 Ce x -57874# 401# 8174# 3# B- -13094# 641# 121 937870# 430# - 4 63 59 122 Pr x -44780# 500# 8060# 4# B- * 121 951927# 537# -0 35 79 44 123 Ru x -37080# 500# 8093# 4# B- 12280# 640# 122 960193# 537# - 33 78 45 123 Rh x -49360# 400# 8186# 3# B- 11070# 885# 122 947010# 429# - 31 77 46 123 Pd x -60429.742 789.441 8270.031 6.418 B- 9118.336 790.039 122 935126.000 847.500 - 29 76 47 123 Ag x -69548.078 30.739 8337.803 0.250 B- 7866.103 30.857 122 925337.062 33.000 - 27 75 48 123 Cd -77414.181 2.696 8395.395 0.022 B- 6016.172 19.893 122 916892.453 2.894 - 25 74 49 123 In -83430.353 19.827 8437.946 0.161 B- 4385.828 19.839 122 910433.826 21.285 - 23 73 50 123 Sn -87816.181 2.416 8467.243 0.020 B- 1407.888 2.662 122 905725.446 2.594 - 21 72 51 123 Sb -89224.069 1.506 8472.328 0.012 B- -51.913 0.066 122 904214.016 1.616 - 19 71 52 123 Te -89172.156 1.505 8465.546 0.012 B- -1228.429 3.445 122 904269.747 1.615 - 17 70 53 123 I -87943.727 3.740 8449.198 0.030 B- -2695.027 9.690 122 905588.520 4.014 - 15 69 54 123 Xe -85248.701 9.537 8420.927 0.078 B- -4205.055 15.414 122 908481.750 10.238 - 13 68 55 123 Cs x -81043.646 12.109 8380.379 0.098 B- -5388.693 17.125 122 912996.062 13.000 - 11 67 56 123 Ba x -75654.953 12.109 8330.208 0.098 B- -7004# 196# 122 918781.062 13.000 - 9 66 57 123 La x -68651# 196# 8267# 2# B- -8365# 357# 122 926300# 210# - 7 65 58 123 Ce x -60286# 298# 8193# 2# B- -10056# 499# 122 935280# 320# - 5 64 59 123 Pr x -50230# 400# 8104# 3# B- * 122 946076# 429# -0 36 80 44 124 Ru x -33960# 600# 8068# 5# B- 10929# 721# 123 963542# 644# - 34 79 45 124 Rh x -44890# 400# 8149# 3# B- 13500# 499# 123 951809# 429# - 32 78 46 124 Pd x -58390# 298# 8252# 2# B- 7810# 390# 123 937316# 320# - 30 77 47 124 Ag x -66200.134 251.503 8308.655 2.028 B- 10501.538 251.521 123 928931.229 270.000 - 28 76 48 124 Cd -76701.672 2.995 8387.035 0.024 B- 4168.529 30.539 123 917657.363 3.215 - 26 75 49 124 In -80870.201 30.572 8414.343 0.247 B- 7363.992 30.576 123 913182.263 32.820 - 24 74 50 124 Sn -88234.193 1.014 8467.421 0.008 B- -613.944 1.513 123 905276.692 1.088 - 22 73 51 124 Sb -n -87620.248 1.507 8456.160 0.012 B- 2905.073 0.132 123 905935.789 1.618 - 20 72 52 124 Te -90525.321 1.502 8473.279 0.012 B- -3159.587 1.859 123 902817.064 1.612 - 18 71 53 124 I - -87365.734 2.390 8441.489 0.019 B- 295.686 2.846 123 906209.021 2.566 - 16 70 54 124 Xe -87661.421 1.793 8437.565 0.014 B- -5930.086 8.495 123 905891.588 1.924 - 14 69 55 124 Cs x -81731.334 8.304 8383.432 0.067 B- -2641.559 15.004 123 912257.798 8.914 - 12 68 56 124 Ba x -79089.775 12.497 8355.820 0.101 B- -8831.165 58.030 123 915093.629 13.416 - 10 67 57 124 La x -70258.610 56.669 8278.292 0.457 B- -5343# 303# 123 924574.275 60.836 - 8 66 58 124 Ce x -64916# 298# 8229# 2# B- -11765# 499# 123 930310# 320# - 6 65 59 124 Pr x -53151# 401# 8128# 3# B- -8626# 643# 123 942940# 430# - 4 64 60 124 Nd x -44525# 503# 8052# 4# B- * 123 952200# 540# -0 35 80 45 125 Rh x -42000# 500# 8126# 4# B- 12120# 640# 124 954911# 537# - 33 79 46 125 Pd x -54120# 400# 8216# 3# B- 10400# 589# 124 941900# 429# - 31 78 47 125 Ag x -64519.932 433.145 8293.314 3.465 B- 8828.163 433.154 124 930735.000 465.000 - 29 77 48 125 Cd -73348.095 2.885 8357.681 0.023 B- 7128.710 27.119 124 921257.577 3.097 - 27 76 49 125 In -80476.805 27.023 8408.452 0.216 B- 5419.571 27.011 124 913604.591 29.010 - 25 75 50 125 Sn -85896.376 1.033 8445.550 0.008 B- 2359.899 2.610 124 907786.442 1.109 - 23 74 51 125 Sb + -88256.274 2.599 8458.170 0.021 B- 766.700 2.121 124 905252.987 2.790 - 21 73 52 125 Te -89022.974 1.502 8458.045 0.012 B- -185.770 0.060 124 904429.900 1.612 - 19 72 53 125 I - -88837.204 1.504 8450.300 0.012 B- -1643.824 2.192 124 904629.333 1.614 - 17 71 54 125 Xe -87193.381 1.836 8430.890 0.015 B- -3105.430 7.831 124 906394.050 1.971 - 15 70 55 125 Cs -84087.950 7.744 8399.788 0.062 B- -4418.985 13.446 124 909727.867 8.313 - 13 69 56 125 Ba -79668.965 10.992 8358.178 0.088 B- -5909.481 27.631 124 914471.843 11.800 - 11 68 57 125 La -73759.484 25.997 8304.643 0.208 B- -7102# 197# 124 920815.932 27.909 - 9 67 58 125 Ce x -66658# 196# 8242# 2# B- -8718# 358# 124 928440# 210# - 7 66 59 125 Pr x -57940# 300# 8166# 2# B- -10341# 500# 124 937799# 322# - 5 65 60 125 Nd x -47599# 401# 8077# 3# B- * 124 948900# 430# -0 36 81 45 126 Rh x -37300# 500# 8088# 4# B- 14560# 640# 125 959957# 537# - 34 80 46 126 Pd x -51860# 400# 8197# 3# B- 8820# 447# 125 944326# 429# - 32 79 47 126 Ag x -60680# 200# 8261# 2# B- 11576# 200# 125 934857# 215# - 30 78 48 126 Cd -72256.802 2.476 8346.747 0.020 B- 5516.106 26.908 125 922429.127 2.658 - 28 77 49 126 In -77772.908 26.921 8384.317 0.214 B- 8242.332 27.078 125 916507.344 28.901 - 26 76 50 126 Sn -86015.240 10.447 8443.523 0.083 B- 378.000 30.000 125 907658.836 11.215 - 24 75 51 126 Sb - -86393.240 31.767 8440.314 0.252 B- 3672.108 31.787 125 907253.036 34.103 - 22 74 52 126 Te -90065.348 1.504 8463.248 0.012 B- -2154.031 3.677 125 903310.866 1.614 - 20 73 53 126 I -87911.318 3.809 8439.944 0.030 B- 1235.644 5.173 125 905623.313 4.089 - 18 72 54 126 Xe -89146.962 3.500 8443.541 0.028 B- -4796.133 10.671 125 904296.794 3.757 - 16 71 55 126 Cs -84350.829 10.401 8399.268 0.083 B- -1680.927 16.259 125 909445.655 11.166 - 14 70 56 126 Ba x -82669.902 12.497 8379.718 0.099 B- -7696.435 91.366 125 911250.204 13.416 - 12 69 57 126 La x -74973.468 90.508 8312.426 0.718 B- -4152.910 94.723 125 919512.667 97.163 - 10 68 58 126 Ce x -70820.558 27.945 8273.257 0.222 B- -10497# 198# 125 923971.000 30.000 - 8 67 59 126 Pr x -60324# 196# 8184# 2# B- -7331# 357# 125 935240# 210# - 6 66 60 126 Nd x -52993# 298# 8119# 2# B- -13643# 582# 125 943110# 320# - 4 65 61 126 Pm x -39350# 500# 8005# 4# B- * 125 957756# 537# -0 37 82 45 127 Rh x -34030# 600# 8062# 5# B- 13150# 781# 126 963467# 644# - 35 81 46 127 Pd x -47180# 500# 8159# 4# B- 11260# 539# 126 949350# 537# - 33 80 47 127 Ag x -58440# 200# 8242# 2# B- 10307# 201# 126 937262# 215# - 31 79 48 127 Cd x -68747.402 12.109 8316.945 0.095 B- 8148.782 24.378 126 926196.624 13.000 - 29 78 49 127 In -76896.184 21.157 8374.949 0.167 B- 6574.619 19.098 126 917448.546 22.713 - 27 77 50 127 Sn -83470.803 10.057 8420.557 0.079 B- 3228.674 10.875 126 910390.401 10.796 - 25 76 51 127 Sb -86699.477 5.126 8439.820 0.040 B- 1582.201 4.913 126 906924.277 5.502 - 23 75 52 127 Te -88281.678 1.514 8446.118 0.012 B- 702.231 3.575 126 905225.714 1.625 - 21 74 53 127 I -88983.909 3.647 8445.487 0.029 B- -662.349 2.044 126 904471.838 3.915 - 19 73 54 127 Xe -88321.560 4.110 8434.111 0.032 B- -2081.406 6.421 126 905182.899 4.412 - 17 72 55 127 Cs -86240.154 5.578 8411.562 0.044 B- -3422.210 12.653 126 907417.381 5.988 - 15 71 56 127 Ba -82817.944 11.357 8378.455 0.089 B- -4921.836 27.740 126 911091.275 12.192 - 13 70 57 127 La -77896.108 26.000 8333.540 0.205 B- -5916.772 38.857 126 916375.084 27.912 - 11 69 58 127 Ce x -71979.336 28.876 8280.791 0.227 B- -7436# 198# 126 922727.000 31.000 - 9 68 59 127 Pr x -64543# 196# 8216# 2# B- -9008# 357# 126 930710# 210# - 7 67 60 127 Nd x -55536# 298# 8139# 2# B- -10749# 499# 126 940380# 320# - 5 66 61 127 Pm x -44786# 401# 8048# 3# B- * 126 951920# 430# -0 36 82 46 128 Pd x -44490# 500# 8138# 4# B- 10130# 583# 127 952238# 537# - 34 81 47 128 Ag x -54620# 300# 8211# 2# B- 12622# 300# 127 941363# 322# - 32 80 48 128 Cd -67241.890 7.244 8303.264 0.057 B- 6904.051 153.554 127 927812.857 7.776 - 30 79 49 128 In -74145.941 153.479 8351.090 1.199 B- 9216.067 153.027 127 920401.053 164.766 - 28 78 50 128 Sn -83362.008 17.660 8416.979 0.138 B- 1268.278 13.796 127 910507.197 18.958 - 26 77 51 128 Sb IT -84630.286 19.119 8420.775 0.149 B- 4363.429 19.117 127 909145.645 20.525 - 24 76 52 128 Te -88993.716 0.866 8448.752 0.007 B- -1254.992 3.714 127 904461.311 0.929 - 22 75 53 128 I -87738.724 3.647 8432.836 0.028 B- 2121.575 3.748 127 905808.600 3.915 - 20 74 54 128 Xe -89860.298 1.061 8443.298 0.008 B- -3928.717 5.380 127 903530.996 1.138 - 18 73 55 128 Cs -85931.581 5.443 8406.493 0.043 B- -553.084 7.525 127 907748.648 5.843 - 16 72 56 128 Ba -85378.497 5.195 8396.060 0.041 B- -6753.066 54.695 127 908342.408 5.577 - 14 71 57 128 La x -78625.431 54.448 8337.190 0.425 B- -3091.513 61.200 127 915592.123 58.452 - 12 70 58 128 Ce x -75533.917 27.945 8306.925 0.218 B- -9203.161 40.859 127 918911.000 30.000 - 10 69 59 128 Pr x -66330.757 29.808 8228.913 0.233 B- -6017# 198# 127 928791.000 32.000 - 8 68 60 128 Nd x -60314# 196# 8176# 2# B- -12529# 357# 127 935250# 210# - 6 67 61 128 Pm x -47786# 298# 8072# 2# B- -9116# 582# 127 948700# 320# - 4 66 62 128 Sm x -38670# 500# 7994# 4# B- * 127 958486# 537# -0 37 83 46 129 Pd x -37610# 600# 8084# 5# B- 14370# 721# 128 959624# 644# - 35 82 47 129 Ag x -51980# 400# 8189# 3# B- 11078# 400# 128 944197# 429# - 33 81 48 129 Cd x -63058.046 16.767 8269.034 0.130 B- 9779.674 16.982 128 932304.399 18.000 - 31 80 49 129 In -72837.720 2.693 8338.780 0.021 B- 7753.183 17.302 128 921805.486 2.891 - 29 79 50 129 Sn -80590.903 17.277 8392.818 0.134 B- 4038.404 27.372 128 913482.102 18.547 - 27 78 51 129 Sb + -84629.307 21.231 8418.058 0.165 B- 2375.500 21.213 128 909146.696 22.792 - 25 77 52 129 Te -87004.807 0.869 8430.409 0.007 B- 1502.318 3.142 128 906596.492 0.933 - 23 76 53 129 I -88507.125 3.168 8435.990 0.025 B- 188.934 3.168 128 904983.687 3.401 - 21 75 54 129 Xe -88696.05896 0.00537 8431.390 0.000 B- -1196.813 4.555 128 904780.85892 0.00576 - 19 74 55 129 Cs -87499.246 4.555 8416.047 0.035 B- -2436.048 10.623 128 906065.690 4.889 - 17 73 56 129 Ba -85063.198 10.577 8391.098 0.082 B- -3738.625 21.639 128 908680.896 11.354 - 15 72 57 129 La -81324.573 21.351 8356.052 0.166 B- -5037.077 35.168 128 912694.475 22.920 - 13 71 58 129 Ce x -76287.496 27.945 8310.940 0.217 B- -6513.938 40.859 128 918102.000 30.000 - 11 70 59 129 Pr x -69773.558 29.808 8254.380 0.231 B- -7459# 204# 128 925095.000 32.000 - 9 69 60 129 Nd ep -62315# 202# 8190# 2# B- -9434# 360# 128 933102# 217# - 7 68 61 129 Pm x -52881# 298# 8111# 2# B- -10881# 582# 128 943230# 320# - 5 67 62 129 Sm x -42000# 500# 8021# 4# B- * 128 954911# 537# -0 36 83 47 130 Ag -nn -45697# 500# 8140# 4# B- 15420# 500# 129 950942# 537# - 34 82 48 130 Cd x -61117.589 22.356 8252.586 0.172 B- 8765.617 44.128 129 934387.566 24.000 - 32 81 49 130 In + -69883.206 38.046 8313.996 0.293 B- 10249.000 38.000 129 924977.288 40.844 - 30 80 50 130 Sn -80132.206 1.873 8386.816 0.014 B- 2153.470 14.113 129 913974.533 2.010 - 28 79 51 130 Sb -82285.676 14.212 8397.363 0.109 B- 5067.273 14.212 129 911662.688 15.257 - 26 78 52 130 Te -87352.949 0.011 8430.324 0.000 B- -416.811 3.168 129 906222.747 0.012 - 24 77 53 130 I -n -86936.138 3.168 8421.100 0.024 B- 2944.325 3.168 129 906670.211 3.401 - 22 76 54 130 Xe -89880.463 0.009 8437.731 0.000 B- -2980.720 8.357 129 903509.349 0.010 - 20 75 55 130 Cs -86899.743 8.357 8408.784 0.064 B- 361.801 8.738 129 906709.283 8.971 - 18 74 56 130 Ba -87261.544 2.553 8405.549 0.020 B- -5634.178 26.071 129 906320.874 2.741 - 16 73 57 130 La x -81627.366 25.946 8356.191 0.200 B- -2204.461 38.133 129 912369.413 27.854 - 14 72 58 130 Ce x -79422.905 27.945 8333.216 0.215 B- -8247.448 70.085 129 914736.000 30.000 - 12 71 59 130 Pr x -71175.457 64.273 8263.756 0.494 B- -4579.225 70.085 129 923590.000 69.000 - 10 70 60 130 Nd x -66596.232 27.945 8222.513 0.215 B- -11200# 198# 129 928506.000 30.000 - 8 69 61 130 Pm x -55396# 196# 8130# 2# B- -7890# 446# 129 940530# 210# - 6 68 62 130 Sm x -47506# 401# 8064# 3# B- -13823# 641# 129 949000# 430# - 4 67 63 130 Eu -p -33683# 500# 7951# 4# B- * 129 963840# 537# -0 37 84 47 131 Ag x -40380# 500# 8099# 4# B- 14839# 511# 130 956650# 537# - 35 83 48 131 Cd x -55218.965 102.464 8206.175 0.782 B- 12806.066 102.500 130 940720.000 110.000 - 33 82 49 131 In x -68025.030 2.701 8297.959 0.021 B- 9239.541 4.518 130 926972.122 2.900 - 31 81 50 131 Sn -77264.571 3.621 8362.517 0.028 B- 4716.830 3.962 130 917053.066 3.887 - 29 80 51 131 Sb -81981.401 2.084 8392.552 0.016 B- 3229.611 2.085 130 911989.341 2.236 - 27 79 52 131 Te -n -85211.012 0.061 8411.233 0.001 B- 2231.699 0.608 130 908522.211 0.065 - 25 78 53 131 I + -87442.710 0.605 8422.297 0.005 B- 970.848 0.605 130 906126.384 0.649 - 23 77 54 131 Xe -88413.558 0.009 8423.736 0.000 B- -354.772 4.974 130 905084.136 0.009 - 21 76 55 131 Cs -88058.786 4.974 8415.056 0.038 B- -1375.055 5.279 130 905464.999 5.340 - 19 75 56 131 Ba -86683.731 2.569 8398.587 0.020 B- -2914.475 28.063 130 906941.181 2.757 - 17 74 57 131 La x -83769.256 27.945 8370.367 0.213 B- -4060.816 43.092 130 910070.000 30.000 - 15 73 58 131 Ce -79708.440 32.802 8333.396 0.250 B- -5407.784 55.446 130 914429.465 35.214 - 13 72 59 131 Pr -74300.656 46.995 8286.143 0.359 B- -6532.623 53.081 130 920234.960 50.451 - 11 71 60 131 Nd -67768.033 27.517 8230.304 0.210 B- -8108# 202# 130 927248.020 29.541 - 9 70 61 131 Pm x -59660# 200# 8162# 2# B- -9527# 448# 130 935952# 215# - 7 69 62 131 Sm x -50133# 401# 8084# 3# B- -10863# 566# 130 946180# 430# - 5 68 63 131 Eu -p -39270# 401# 7995# 3# B- * 130 957842# 430# -0 38 85 47 132 Ag x -33790# 500# 8049# 4# B- 16473# 537# 131 963725# 537# - 36 84 48 132 Cd x -50263# 196# 8168# 1# B- 12148# 205# 131 946040# 210# - 34 83 49 132 In + -62411.542 60.033 8253.715 0.455 B- 14135.000 60.000 131 932998.449 64.447 - 32 82 50 132 Sn -76546.542 1.976 8354.872 0.015 B- 3088.729 3.161 131 917823.902 2.121 - 30 81 51 132 Sb -79635.271 2.467 8372.344 0.019 B- 5552.915 4.271 131 914508.015 2.648 - 28 80 52 132 Te -85188.186 3.486 8408.485 0.026 B- 515.304 3.483 131 908546.716 3.742 - 26 79 53 132 I -85703.490 4.065 8406.462 0.031 B- 3575.472 4.065 131 907993.514 4.364 - 24 78 54 132 Xe -89278.96179 0.00515 8427.622 0.000 B- -2126.280 1.036 131 904155.08697 0.00553 - 22 77 55 132 Cs -87152.681 1.036 8405.587 0.008 B- 1282.336 1.478 131 906437.743 1.112 - 20 76 56 132 Ba -88435.017 1.054 8409.375 0.008 B- -4711.367 36.354 131 905061.098 1.131 - 18 75 57 132 La -83723.650 36.359 8367.756 0.275 B- -1252.754 41.718 131 910118.959 39.032 - 16 74 58 132 Ce -82470.896 20.442 8352.338 0.155 B- -7243.440 35.380 131 911463.846 21.945 - 14 73 59 132 Pr x -75227.456 28.876 8291.537 0.219 B- -3801.648 37.679 131 919240.000 31.000 - 12 72 60 132 Nd x -71425.807 24.205 8256.810 0.183 B- -9798# 151# 131 923321.237 25.985 - 10 71 61 132 Pm x -61628# 149# 8177# 1# B- -6548# 333# 131 933840# 160# - 8 70 62 132 Sm x -55079# 298# 8121# 2# B- -12879# 499# 131 940870# 320# - 6 69 63 132 Eu x -42200# 400# 8018# 3# B- * 131 954696# 429# -0 37 85 48 133 Cd x -43920# 298# 8119# 2# B- 13544# 357# 132 952850# 320# - 35 84 49 133 In x -57464# 196# 8215# 1# B- 13410# 196# 132 938310# 210# - 33 83 50 133 Sn -70873.880 1.904 8310.088 0.014 B- 8049.623 3.662 132 923913.756 2.044 - 31 82 51 133 Sb -78923.503 3.128 8364.729 0.024 B- 4013.619 3.518 132 915272.130 3.357 - 29 81 52 133 Te -82937.122 2.066 8389.025 0.016 B- 2921.139 6.751 132 910963.332 2.218 - 27 80 53 133 I ++ -85858.260 6.427 8405.106 0.048 B- 1785.311 6.861 132 907827.361 6.900 - 25 79 54 133 Xe + -87643.571 2.400 8412.647 0.018 B- 427.360 2.400 132 905910.750 2.576 - 23 78 55 133 Cs -88070.931 0.008 8409.978 0.000 B- -517.319 0.992 132 905451.961 0.008 - 21 77 56 133 Ba -87553.613 0.992 8400.206 0.007 B- -2059.230 27.962 132 906007.325 1.065 - 19 76 57 133 La x -85494.383 27.945 8378.841 0.210 B- -3076.168 32.379 132 908218.000 30.000 - 17 75 58 133 Ce x -82418.214 16.354 8349.829 0.123 B- -4480.634 20.583 132 911520.402 17.557 - 15 74 59 133 Pr x -77937.581 12.497 8310.258 0.094 B- -5605.208 48.222 132 916330.561 13.416 - 13 73 60 133 Nd x -72332.372 46.575 8262.231 0.350 B- -6924.726 68.552 132 922348.000 50.000 - 11 72 61 133 Pm x -65407.646 50.301 8204.283 0.378 B- -8177# 302# 132 929782.000 54.000 - 9 71 62 133 Sm x -57231# 298# 8137# 2# B- -9995# 422# 132 938560# 320# - 7 70 63 133 Eu x -47236# 298# 8056# 2# B- -11376# 582# 132 949290# 320# - 5 69 64 133 Gd x -35860# 500# 7964# 4# B- * 132 961503# 537# -0 38 86 48 134 Cd x -38920# 400# 8082# 3# B- 12741# 499# 133 958218# 429# - 36 85 49 134 In x -51661# 298# 8171# 2# B- 14773# 298# 133 944540# 320# - 34 84 50 134 Sn x -66433.748 3.167 8275.171 0.024 B- 7586.794 3.597 133 928680.433 3.400 - 32 83 51 134 Sb x -74020.542 1.705 8325.950 0.013 B- 8513.200 3.233 133 920535.675 1.830 - 30 82 52 134 Te -82533.741 2.746 8383.643 0.020 B- 1509.687 4.933 133 911396.379 2.948 - 28 81 53 134 I -84043.429 4.857 8389.071 0.036 B- 4082.393 4.857 133 909775.663 5.213 - 26 80 54 134 Xe -88125.822 0.009 8413.699 0.000 B- -1234.667 0.018 133 905393.033 0.010 - 24 79 55 134 Cs -86891.154 0.016 8398.646 0.000 B- 2058.699 0.304 133 906718.503 0.017 - 22 78 56 134 Ba -88949.853 0.304 8408.171 0.002 B- -3731.204 19.932 133 904508.399 0.326 - 20 77 57 134 La x -85218.650 19.930 8374.488 0.149 B- -385.760 28.510 133 908514.011 21.395 - 18 76 58 134 Ce x -84832.889 20.387 8365.771 0.152 B- -6304.898 28.781 133 908928.142 21.886 - 16 75 59 134 Pr x -78527.991 20.316 8312.881 0.152 B- -2881.559 23.503 133 915696.729 21.810 - 14 74 60 134 Nd x -75646.432 11.817 8285.538 0.088 B- -8907.681 58.949 133 918790.210 12.686 - 12 73 61 134 Pm x -66738.751 57.753 8213.225 0.431 B- -5363# 204# 133 928353.000 62.000 - 10 72 62 134 Sm x -61376# 196# 8167# 1# B- -11448# 357# 133 934110# 210# - 8 71 63 134 Eu x -49928# 298# 8076# 2# B- -8626# 499# 133 946400# 320# - 6 70 64 134 Gd x -41302# 401# 8006# 3# B- * 133 955660# 430# -0 37 86 49 135 In x -46528# 401# 8132# 3# B- 14104# 401# 134 950050# 430# - 35 85 50 135 Sn x -60632.244 3.074 8230.687 0.023 B- 9058.079 4.052 134 934908.605 3.300 - 33 84 51 135 Sb -69690.323 2.640 8291.989 0.020 B- 8038.457 3.152 134 925184.357 2.834 - 31 83 52 135 Te -77728.780 1.722 8345.738 0.013 B- 6050.366 2.686 134 916554.718 1.848 - 29 82 53 135 I -83779.145 2.061 8384.760 0.015 B- 2634.005 3.868 134 910059.382 2.212 - 27 81 54 135 Xe -86413.151 3.720 8398.476 0.028 B- 1168.492 3.675 134 907231.661 3.993 - 25 80 55 135 Cs -87581.643 0.992 8401.336 0.007 B- 268.855 1.038 134 905977.234 1.064 - 23 79 56 135 Ba -87850.498 0.306 8397.533 0.002 B- -1207.181 9.430 134 905688.606 0.328 - 21 78 57 135 La -86643.317 9.434 8382.795 0.070 B- -2027.146 4.610 134 906984.568 10.127 - 19 77 58 135 Ce -84616.171 10.267 8361.984 0.076 B- -3680.310 15.655 134 909160.799 11.022 - 17 76 59 135 Pr x -80935.861 11.817 8328.928 0.088 B- -4722.252 22.484 134 913111.774 12.686 - 15 75 60 135 Nd x -76213.609 19.128 8288.153 0.142 B- -6161.534 77.838 134 918181.320 20.534 - 13 74 61 135 Pm x -70052.075 75.451 8236.717 0.559 B- -7194.860 172.054 134 924796.000 81.000 - 11 73 62 135 Sm x -62857.215 154.628 8177.626 1.145 B- -8709# 249# 134 932520.000 166.000 - 9 72 63 135 Eu x -54148# 196# 8107# 1# B- -9757# 445# 134 941870# 210# - 7 71 64 135 Gd x -44390# 400# 8029# 3# B- -11565# 566# 134 952345# 429# - 5 70 65 135 Tb -p -32825# 401# 7938# 3# B- * 134 964760# 430# -0 38 87 49 136 In x -40510# 400# 8087# 3# B- 15389# 499# 135 956511# 429# - 36 86 50 136 Sn x -55899# 298# 8195# 2# B- 8608# 298# 135 939990# 320# - 34 85 51 136 Sb -64506.880 5.830 8252.252 0.043 B- 9918.389 6.260 135 930749.011 6.258 - 32 84 52 136 Te -74425.269 2.281 8319.429 0.017 B- 5119.945 14.188 135 920101.182 2.448 - 30 83 53 136 I -79545.214 14.188 8351.323 0.104 B- 6883.945 14.188 135 914604.695 15.231 - 28 82 54 136 Xe -86429.159 0.007 8396.188 0.000 B- -90.462 1.882 135 907214.476 0.007 - 26 81 55 136 Cs + -86338.697 1.882 8389.770 0.014 B- 2548.224 1.857 135 907311.590 2.020 - 24 80 56 136 Ba -88886.921 0.306 8402.755 0.002 B- -2849.443 53.172 135 904575.959 0.328 - 22 79 57 136 La x -86037.479 53.171 8376.050 0.391 B- 470.893 53.173 135 907634.962 57.081 - 20 78 58 136 Ce -86508.372 0.408 8373.760 0.003 B- -5168.017 11.457 135 907129.438 0.438 - 18 77 59 136 Pr -81340.355 11.455 8330.008 0.084 B- -2141.068 16.458 135 912677.532 12.297 - 16 76 60 136 Nd x -79199.287 11.817 8308.512 0.087 B- -8029.371 70.076 135 914976.064 12.686 - 14 75 61 136 Pm x -71169.915 69.073 8243.720 0.508 B- -4359.026 70.194 135 923595.949 74.152 - 12 74 62 136 Sm x -66810.890 12.497 8205.916 0.092 B- -10567# 196# 135 928275.555 13.416 - 10 73 63 136 Eu x -56244# 196# 8122# 1# B- -7154# 357# 135 939620# 210# - 8 72 64 136 Gd x -49090# 298# 8064# 2# B- -12960# 582# 135 947300# 320# - 6 71 65 136 Tb x -36130# 500# 7963# 4# B- * 135 961213# 537# -0 39 88 49 137 In x -35040# 500# 8047# 4# B- 14748# 641# 136 962383# 537# - 37 87 50 137 Sn x -49788# 401# 8149# 3# B- 10272# 404# 136 946550# 430# - 35 86 51 137 Sb x -60060.384 52.164 8218.476 0.381 B- 9243.369 52.206 136 935522.522 56.000 - 33 85 52 137 Te -69303.753 2.100 8280.235 0.015 B- 7052.506 8.643 136 925599.357 2.254 - 31 84 53 137 I p-2n -76356.258 8.383 8326.002 0.061 B- 6027.145 8.384 136 918028.180 9.000 - 29 83 54 137 Xe -n -82383.404 0.103 8364.286 0.001 B- 4162.203 0.373 136 911557.773 0.111 - 27 82 55 137 Cs + -86545.606 0.358 8388.956 0.003 B- 1175.629 0.172 136 907089.464 0.384 - 25 81 56 137 Ba -87721.235 0.314 8391.827 0.002 B- -580.547 1.632 136 905827.375 0.337 - 23 80 57 137 La + -87140.688 1.659 8381.879 0.012 B- -1222.100 1.600 136 906450.618 1.780 - 21 79 58 137 Ce -85918.588 0.437 8367.248 0.003 B- -2716.895 8.133 136 907762.596 0.469 - 19 78 59 137 Pr -83201.693 8.137 8341.706 0.059 B- -3617.126 14.282 136 910679.304 8.735 - 17 77 60 137 Nd -79584.567 11.737 8309.593 0.086 B- -5511.719 17.545 136 914562.448 12.600 - 15 76 61 137 Pm x -74072.848 13.041 8263.651 0.095 B- -6046.323 44.355 136 920479.522 14.000 - 13 75 62 137 Sm -68026.525 42.395 8213.806 0.309 B- -7880.630 42.620 136 926970.517 45.512 - 11 74 63 137 Eu x -60145.895 4.378 8150.573 0.032 B- -8932# 298# 136 935430.722 4.700 - 9 73 64 137 Gd x -51214# 298# 8080# 2# B- -10246# 499# 136 945020# 320# - 7 72 65 137 Tb x -40967# 401# 7999# 3# B- * 136 956020# 430# -0 38 88 50 138 Sn x -44861# 503# 8113# 4# B- 9360# 1177# 137 951840# 540# - 36 87 51 138 Sb x -54220.403 1064.232 8175.091 7.712 B- 11475.582 1064.239 137 941792.000 1142.500 - 34 86 52 138 Te -65695.985 3.787 8252.578 0.027 B- 6283.914 7.063 137 929472.454 4.065 - 32 85 53 138 I x -71979.900 5.962 8292.444 0.043 B- 7992.334 6.588 137 922726.394 6.400 - 30 84 54 138 Xe -79972.233 2.804 8344.690 0.020 B- 2914.704 9.579 137 914146.271 3.010 - 28 83 55 138 Cs -82886.937 9.159 8360.142 0.066 B- 5374.700 9.159 137 911017.207 9.832 - 26 82 56 138 Ba -88261.638 0.317 8393.420 0.002 B- -1742.458 3.191 137 905247.229 0.339 - 24 81 57 138 La -86519.180 3.188 8375.125 0.023 B- 1051.742 4.038 137 907117.834 3.422 - 22 80 58 138 Ce -87570.922 4.931 8377.077 0.036 B- -4437.000 10.000 137 905988.743 5.293 - 20 79 59 138 Pr - -83133.922 11.150 8339.255 0.081 B- -1115.612 16.090 137 910752.059 11.969 - 18 78 60 138 Nd -82018.310 11.601 8325.502 0.084 B- -7077.827 28.756 137 911949.717 12.454 - 16 77 61 138 Pm -74940.483 27.739 8268.544 0.201 B- -3442.721 30.151 137 919548.077 29.778 - 14 76 62 138 Sm x -71497.762 11.817 8237.928 0.086 B- -9748.093 30.341 137 923243.990 12.686 - 12 75 63 138 Eu x -61749.669 27.945 8161.620 0.202 B- -5949# 198# 137 933709.000 30.000 - 10 74 64 138 Gd x -55800# 196# 8113# 1# B- -12132# 357# 137 940096# 210# - 8 73 65 138 Tb x -43668# 298# 8019# 2# B- -8737# 585# 137 953120# 320# - 6 72 66 138 Dy x -34931# 503# 7950# 4# B- * 137 962500# 540# -0 39 89 50 139 Sn x -38440# 500# 8066# 4# B- 11348# 641# 138 958733# 537# - 37 88 51 139 Sb x -49788# 401# 8142# 3# B- 10417# 401# 138 946550# 430# - 35 87 52 139 Te x -60205.072 3.540 8211.771 0.025 B- 8265.882 5.345 138 935367.193 3.800 - 33 86 53 139 I x -68470.954 4.005 8265.609 0.029 B- 7173.622 4.542 138 926493.403 4.300 - 31 85 54 139 Xe x -75644.576 2.142 8311.590 0.015 B- 5056.346 3.801 138 918792.203 2.300 - 29 84 55 139 Cs + -80700.921 3.140 8342.338 0.023 B- 4212.829 3.123 138 913363.992 3.370 - 27 83 56 139 Ba -84913.751 0.319 8367.017 0.002 B- 2312.461 2.013 138 908841.334 0.342 - 25 82 57 139 La -87226.212 2.009 8378.025 0.014 B- -278.350 6.953 138 906358.804 2.156 - 23 81 58 139 Ce -86947.862 7.230 8370.395 0.052 B- -2129.064 2.996 138 906657.625 7.761 - 21 80 59 139 Pr -84818.798 7.809 8349.449 0.056 B- -2804.856 28.033 138 908943.270 8.383 - 19 79 60 139 Nd -82013.942 27.600 8323.642 0.199 B- -4513.460 25.927 138 911954.407 29.630 - 17 78 61 139 Pm -77500.481 13.593 8285.543 0.098 B- -5120.263 17.414 138 916799.806 14.592 - 15 77 62 139 Sm x -72380.219 10.884 8243.078 0.078 B- -6982.177 17.071 138 922296.634 11.684 - 13 76 63 139 Eu x -65398.042 13.151 8187.218 0.095 B- -7767# 196# 138 929792.310 14.117 - 11 75 64 139 Gd x -57632# 196# 8126# 1# B- -9501# 357# 138 938130# 210# - 9 74 65 139 Tb x -48130# 298# 8052# 2# B- -10489# 585# 138 948330# 320# - 7 73 66 139 Dy x -37642# 503# 7971# 4# B- * 138 959590# 540# -0 38 89 51 140 Sb x -43939# 596# 8100# 4# B- 12638# 599# 139 952830# 640# - 36 88 52 140 Te x -56576.228 62.410 8184.847 0.446 B- 7029.985 63.574 139 939262.917 67.000 - 34 87 53 140 I x -63606.213 12.109 8229.473 0.086 B- 9380.238 12.331 139 931715.917 13.000 - 32 86 54 140 Xe x -72986.451 2.329 8290.887 0.017 B- 4063.654 8.525 139 921645.817 2.500 - 30 85 55 140 Cs -77050.105 8.201 8314.325 0.059 B- 6219.249 9.882 139 917283.305 8.804 - 28 84 56 140 Ba -83269.354 7.933 8353.160 0.057 B- 1046.517 7.993 139 910606.666 8.516 - 26 83 57 140 La -84315.871 2.009 8355.047 0.014 B- 3760.218 1.727 139 909483.184 2.156 - 24 82 58 140 Ce -88076.089 1.596 8376.317 0.011 B- -3388.000 6.000 139 905446.424 1.713 - 22 81 59 140 Pr - -84688.089 6.209 8346.529 0.044 B- -429.177 7.101 139 909083.592 6.665 - 20 80 60 140 Nd x -84258.912 3.447 8337.875 0.025 B- -6045.200 24.000 139 909544.332 3.700 - 18 79 61 140 Pm - -78213.712 24.246 8289.107 0.173 B- -2757.777 27.277 139 916034.122 26.029 - 16 78 62 140 Sm x -75455.935 12.497 8263.820 0.089 B- -8470.000 50.000 139 918994.717 13.416 - 14 77 63 140 Eu - -66985.935 51.538 8197.732 0.368 B- -5203.664 58.627 139 928087.637 55.328 - 12 76 64 140 Gd x -61782.271 27.945 8154.975 0.200 B- -11300.000 800.000 139 933674.000 30.000 - 10 75 65 140 Tb - -50482.271 800.488 8068.672 5.718 B- -7652# 895# 139 945805.049 859.359 - 8 74 66 140 Dy x -42830# 401# 8008# 3# B- -13571# 643# 139 954020# 430# - 6 73 67 140 Ho -p -29259# 503# 7906# 4# B- * 139 968589# 540# -0 39 90 51 141 Sb x -39110# 500# 8066# 4# B- 11377# 641# 140 958014# 537# - 37 89 52 141 Te x -50487# 401# 8141# 3# B- 9440# 401# 140 945800# 430# - 35 88 53 141 I x -59926.657 15.835 8202.255 0.112 B- 8270.642 16.097 140 935666.084 17.000 - 33 87 54 141 Xe x -68197.299 2.888 8255.364 0.020 B- 6280.224 9.638 140 926787.184 3.100 - 31 86 55 141 Cs -74477.523 9.195 8294.356 0.065 B- 5255.103 9.617 140 920045.086 9.871 - 29 85 56 141 Ba -79732.626 5.319 8326.078 0.038 B- 3199.010 6.600 140 914403.500 5.710 - 27 84 57 141 La -82931.636 4.219 8343.217 0.030 B- 2501.280 3.928 140 910969.222 4.528 - 25 83 58 141 Ce -85432.916 1.597 8355.408 0.011 B- 582.728 1.202 140 908283.987 1.714 - 23 82 59 141 Pr -86015.644 1.665 8353.992 0.012 B- -1823.014 2.809 140 907658.403 1.787 - 21 81 60 141 Nd - -84192.630 3.265 8335.515 0.023 B- -3669.709 14.349 140 909615.488 3.505 - 19 80 61 141 Pm x -80522.921 13.972 8303.940 0.099 B- -4589.012 16.375 140 913555.084 15.000 - 17 79 62 141 Sm -75933.909 8.539 8265.845 0.061 B- -6008.280 14.285 140 918481.591 9.167 - 15 78 63 141 Eu -69925.629 12.639 8217.684 0.090 B- -6701.405 23.456 140 924931.745 13.568 - 13 77 64 141 Gd x -63224.224 19.760 8164.608 0.140 B- -8683.387 107.098 140 932126.000 21.213 - 11 76 65 141 Tb x -54540.837 105.259 8097.475 0.747 B- -9158# 316# 140 941448.000 113.000 - 9 75 66 141 Dy x -45382# 298# 8027# 2# B- -11018# 499# 140 951280# 320# - 7 74 67 141 Ho -p -34364# 401# 7943# 3# B- * 140 963108# 430# -0 38 90 52 142 Te x -46370# 503# 8111# 4# B- 8400# 627# 141 950220# 540# - 36 89 53 142 I x -54769.984 374.461 8165.019 2.637 B- 10459.655 374.470 141 941202.000 402.000 - 34 88 54 142 Xe x -65229.639 2.701 8233.169 0.019 B- 5284.911 7.565 141 929973.098 2.900 - 32 87 55 142 Cs -70514.550 7.067 8264.877 0.050 B- 7327.714 8.363 141 924299.512 7.586 - 30 86 56 142 Ba -77842.264 5.920 8310.971 0.042 B- 2181.963 8.391 141 916432.888 6.355 - 28 85 57 142 La -80024.227 6.309 8320.828 0.044 B- 4508.961 5.845 141 914090.454 6.773 - 26 84 58 142 Ce -84533.188 2.509 8347.071 0.018 B- -745.712 2.500 141 909249.884 2.693 - 24 83 59 142 Pr -83787.476 1.665 8336.310 0.012 B- 2162.505 1.416 141 910050.440 1.786 - 22 82 60 142 Nd -85949.980 1.368 8346.030 0.010 B- -4807.936 23.629 141 907728.895 1.468 - 20 81 61 142 Pm -81142.044 23.597 8306.662 0.166 B- -2155.574 23.752 141 912890.428 25.332 - 18 80 62 142 Sm -78986.470 3.079 8285.972 0.022 B- -7673.000 30.000 141 915204.532 3.305 - 16 79 63 142 Eu - -71313.470 30.158 8226.427 0.212 B- -4353.955 41.114 141 923441.836 32.375 - 14 78 64 142 Gd x -66959.515 27.945 8190.256 0.197 B- -10400.000 700.000 141 928116.000 30.000 - 12 77 65 142 Tb - -56559.515 700.558 8111.507 4.934 B- -6440# 200# 141 939280.859 752.079 - 10 76 66 142 Dy - -50120# 729# 8061# 5# B- -12869# 831# 141 946194# 782# - 8 75 67 142 Ho x -37250# 401# 7965# 3# B- -9221# 641# 141 960010# 430# - 6 74 68 142 Er x -28030# 500# 7894# 4# B- * 141 969909# 537# -0 39 91 52 143 Te x -40278# 503# 8068# 4# B- 10353# 541# 142 956760# 540# - 37 90 53 143 I x -50630# 200# 8135# 1# B- 9572# 200# 142 945646# 215# - 35 89 54 143 Xe x -60202.873 4.657 8196.885 0.033 B- 7472.636 8.891 142 935369.553 5.000 - 33 88 55 143 Cs -67675.509 7.573 8243.670 0.053 B- 6261.688 9.730 142 927347.348 8.130 - 31 87 56 143 Ba -73937.197 6.756 8281.987 0.047 B- 4234.318 9.969 142 920625.150 7.253 - 29 86 57 143 La -78171.515 7.330 8306.127 0.051 B- 3435.156 7.595 142 916079.422 7.869 - 27 85 58 143 Ce -81606.671 2.508 8324.678 0.018 B- 1461.575 1.866 142 912391.630 2.692 - 25 84 59 143 Pr -83068.246 1.897 8329.428 0.013 B- 933.988 1.368 142 910822.564 2.037 - 23 83 60 143 Nd -84002.234 1.367 8330.488 0.010 B- -1041.583 2.682 142 909819.887 1.467 - 21 82 61 143 Pm -82960.651 2.996 8317.733 0.021 B- -3443.499 3.560 142 910938.073 3.216 - 19 81 62 143 Sm -79517.152 2.804 8288.182 0.020 B- -5275.851 11.338 142 914634.821 3.010 - 17 80 63 143 Eu x -74241.300 10.986 8245.817 0.077 B- -6010.000 200.000 142 920298.681 11.793 - 15 79 64 143 Gd - -68231.300 200.301 8198.318 1.401 B- -7812.117 206.750 142 926750.682 215.032 - 13 78 65 143 Tb x -60419.183 51.232 8138.217 0.358 B- -8250.242 52.866 142 935137.335 55.000 - 11 77 66 143 Dy x -52168.941 13.041 8075.052 0.091 B- -10121# 298# 142 943994.335 14.000 - 9 76 67 143 Ho x -42048# 298# 7999# 2# B- -10788# 499# 142 954860# 320# - 7 75 68 143 Er x -31260# 400# 7918# 3# B- * 142 966441# 429# -0 38 91 53 144 I x -45280# 401# 8098# 3# B- 11592# 401# 143 951390# 430# - 36 90 54 144 Xe x -56872.293 5.310 8172.884 0.037 B- 6399.060 20.820 143 938945.079 5.700 - 34 89 55 144 Cs -63271.353 20.132 8211.889 0.140 B- 8495.768 20.416 143 932075.404 21.612 - 32 88 56 144 Ba -71767.121 7.136 8265.454 0.050 B- 3082.530 14.774 143 922954.821 7.661 - 30 87 57 144 La x -74849.652 12.937 8281.428 0.090 B- 5582.219 13.254 143 919645.589 13.888 - 28 86 58 144 Ce + -80431.870 2.885 8314.760 0.020 B- 318.646 0.832 143 913652.830 3.096 - 26 85 59 144 Pr + -80750.517 2.762 8311.540 0.019 B- 2997.440 2.400 143 913310.750 2.965 - 24 84 60 144 Nd -83747.957 1.367 8326.922 0.009 B- -2331.863 2.646 143 910092.865 1.467 - 22 83 61 144 Pm -81416.093 2.964 8305.296 0.021 B- 549.442 2.668 143 912596.224 3.181 - 20 82 62 144 Sm -81965.535 1.554 8303.679 0.011 B- -6346.402 10.814 143 912006.373 1.668 - 18 81 63 144 Eu -75619.133 10.789 8254.173 0.075 B- -3859.630 29.955 143 918819.517 11.582 - 16 80 64 144 Gd x -71759.504 27.945 8221.937 0.194 B- -9391.323 39.520 143 922963.000 30.000 - 14 79 65 144 Tb x -62368.181 27.945 8151.287 0.194 B- -5798.098 28.851 143 933045.000 30.000 - 12 78 66 144 Dy x -56570.083 7.173 8105.589 0.050 B- -11960.569 11.104 143 939269.514 7.700 - 10 77 67 144 Ho x -44609.513 8.477 8017.097 0.059 B- -8002# 196# 143 952109.714 9.100 - 8 76 68 144 Er x -36608# 196# 7956# 1# B- -14349# 445# 143 960700# 210# - 6 75 69 144 Tm -p -22259# 400# 7851# 3# B- * 143 976104# 429# -0 39 92 53 145 I x -40939# 503# 8068# 3# B- 10554# 503# 144 956050# 540# - 37 91 54 145 Xe x -51493.329 11.178 8135.087 0.077 B- 8561.086 14.393 144 944719.634 12.000 - 35 90 55 145 Cs -60054.415 9.067 8188.733 0.063 B- 7461.761 12.412 144 935528.930 9.733 - 33 89 56 145 Ba x -67516.176 8.477 8234.798 0.058 B- 5319.141 14.912 144 927518.400 9.100 - 31 88 57 145 La -72835.317 12.269 8266.087 0.085 B- 4231.705 35.300 144 921808.066 13.170 - 29 87 58 145 Ce -77067.022 33.902 8289.875 0.234 B- 2558.918 33.635 144 917265.144 36.395 - 27 86 59 145 Pr -79625.940 7.169 8302.127 0.049 B- 1806.012 7.037 144 914518.033 7.696 - 25 85 60 145 Nd -81431.951 1.384 8309.187 0.010 B- -164.478 2.536 144 912579.199 1.485 - 23 84 61 145 Pm -81267.474 2.859 8302.657 0.020 B- -616.156 2.539 144 912755.773 3.068 - 21 83 62 145 Sm -80651.318 1.578 8293.013 0.011 B- -2659.810 2.723 144 913417.244 1.694 - 19 82 63 145 Eu -77991.507 3.106 8269.274 0.021 B- -5065.187 19.953 144 916272.668 3.334 - 17 81 64 145 Gd -72926.320 19.709 8228.946 0.136 B- -6537.909 108.066 144 921710.370 21.158 - 15 80 65 145 Tb -66388.411 109.174 8178.461 0.753 B- -8145.812 109.369 144 928729.105 117.203 - 13 79 66 145 Dy x -58242.599 6.520 8116.888 0.045 B- -9122.493 9.902 144 937473.994 7.000 - 11 78 67 145 Ho x -49120.105 7.452 8048.578 0.051 B- -9880# 200# 144 947267.394 8.000 - 9 77 68 145 Er x -39240# 200# 7975# 1# B- -11657# 280# 144 957874# 215# - 7 76 69 145 Tm -p -27583# 196# 7889# 1# B- * 144 970389# 210# -0 38 92 54 146 Xe x -47954.943 24.219 8110.415 0.166 B- 7355.429 24.391 145 948518.248 26.000 - 36 91 55 146 Cs x -55310.372 2.893 8155.436 0.020 B- 9636.714 21.063 145 940621.870 3.106 - 34 90 56 146 Ba -64947.086 20.863 8216.082 0.143 B- 4103.197 33.503 145 930276.431 22.397 - 32 89 57 146 La -69050.283 33.616 8238.828 0.230 B- 6585.107 34.456 145 925871.468 36.088 - 30 88 58 146 Ce -75635.389 16.306 8278.573 0.112 B- 1045.616 32.519 145 918802.065 17.504 - 28 87 59 146 Pr -76681.006 34.816 8280.376 0.238 B- 4244.861 34.830 145 917679.549 37.376 - 26 86 60 146 Nd -80925.867 1.386 8304.092 0.009 B- -1471.558 4.119 145 913122.503 1.488 - 24 85 61 146 Pm + -79454.309 4.308 8288.654 0.030 B- 1542.000 3.000 145 914702.286 4.624 - 22 84 62 146 Sm -80996.309 3.092 8293.857 0.021 B- -3878.768 5.869 145 913046.881 3.319 - 20 83 63 146 Eu -77117.541 6.026 8261.932 0.041 B- -1031.758 7.076 145 917210.909 6.468 - 18 82 64 146 Gd -76085.783 4.108 8249.506 0.028 B- -8322.173 44.749 145 918318.548 4.409 - 16 81 65 146 Tb -67763.610 44.862 8187.146 0.307 B- -5208.691 45.160 145 927252.768 48.161 - 14 80 66 146 Dy -62554.918 6.695 8146.112 0.046 B- -11316.699 9.392 145 932844.529 7.187 - 12 79 67 146 Ho -51238.219 6.587 8063.242 0.045 B- -6916.206 9.399 145 944993.506 7.071 - 10 78 68 146 Er -44322.012 6.705 8010.512 0.046 B- -13267# 200# 145 952418.359 7.197 - 8 77 69 146 Tm -p -31055# 200# 7914# 1# B- * 145 966661# 215# -0 39 93 54 147 Xe x -42360# 200# 8072# 1# B- 9560# 200# 146 954525# 215# - 37 92 55 147 Cs x -51920.064 8.383 8131.800 0.057 B- 8343.965 21.454 146 944261.515 9.000 - 35 91 56 147 Ba x -60264.029 19.748 8183.240 0.134 B- 6414.361 22.466 146 935303.900 21.200 - 33 90 57 147 La x -66678.390 10.712 8221.553 0.073 B- 5335.501 13.725 146 928417.800 11.500 - 31 89 58 147 Ce -72013.891 8.580 8252.527 0.058 B- 3430.176 15.533 146 922689.903 9.211 - 29 88 59 147 Pr -75444.067 15.857 8270.539 0.108 B- 2702.681 15.860 146 919007.458 17.023 - 27 87 60 147 Nd -78146.748 1.388 8283.603 0.009 B- 895.512 0.482 146 916106.010 1.490 - 25 86 61 147 Pm -79042.260 1.399 8284.372 0.010 B- 224.094 0.293 146 915144.638 1.501 - 23 85 62 147 Sm -79266.354 1.372 8280.575 0.009 B- -1721.598 2.281 146 914904.064 1.473 - 21 84 63 147 Eu -77544.756 2.630 8263.541 0.018 B- -2187.811 2.524 146 916752.276 2.823 - 19 83 64 147 Gd -75356.945 1.965 8243.336 0.013 B- -4614.280 8.147 146 919100.987 2.109 - 17 82 65 147 Tb -70742.665 8.100 8206.624 0.055 B- -6546.628 11.997 146 924054.620 8.695 - 15 81 66 147 Dy x -64196.038 8.849 8156.767 0.060 B- -8438.945 10.164 146 931082.715 9.500 - 13 80 67 147 Ho -55757.092 5.001 8094.037 0.034 B- -9149.286 38.517 146 940142.295 5.368 - 11 79 68 147 Er x -46607.807 38.191 8026.475 0.260 B- -10633.406 38.799 146 949964.458 41.000 - 9 78 69 147 Tm -35974.400 6.839 7948.817 0.047 B- * 146 961379.890 7.341 -0 40 94 54 148 Xe x -38600# 300# 8047# 2# B- 8311# 300# 147 958561# 322# - 38 93 55 148 Cs x -46910.942 13.041 8097.546 0.088 B- 10682.793 64.413 147 949639.029 14.000 - 36 92 56 148 Ba + -57593.735 63.079 8164.441 0.426 B- 5115.000 60.000 147 938170.578 67.718 - 34 91 57 148 La x -62708.735 19.468 8193.716 0.132 B- 7689.672 22.457 147 932679.400 20.900 - 32 90 58 148 Ce -70398.408 11.195 8240.387 0.076 B- 2137.016 12.567 147 924424.196 12.018 - 30 89 59 148 Pr -72535.424 15.043 8249.540 0.102 B- 4872.572 15.090 147 922130.015 16.148 - 28 88 60 148 Nd -77407.996 2.127 8277.177 0.014 B- -542.280 5.874 147 916899.093 2.283 - 26 87 61 148 Pm +p -76865.716 5.723 8268.226 0.039 B- 2470.548 5.642 147 917481.255 6.143 - 24 86 62 148 Sm -79336.264 1.367 8279.633 0.009 B- -3036.933 10.019 147 914829.012 1.467 - 22 85 63 148 Eu -76299.331 10.013 8253.827 0.068 B- -30.003 10.019 147 918089.294 10.748 - 20 84 64 148 Gd -76269.329 1.554 8248.338 0.011 B- -5732.246 12.529 147 918121.503 1.668 - 18 83 65 148 Tb -70537.082 12.464 8204.321 0.084 B- -2677.532 9.596 147 924275.323 13.380 - 16 82 66 148 Dy -67859.550 8.724 8180.943 0.059 B- -9868.393 84.287 147 927149.772 9.366 - 14 81 67 148 Ho x -57991.158 83.834 8108.979 0.566 B- -6512.169 84.458 147 937743.928 90.000 - 12 80 68 148 Er x -51478.989 10.246 8059.692 0.069 B- -12713.962 14.491 147 944735.029 11.000 - 10 79 69 148 Tm x -38765.027 10.246 7968.500 0.069 B- -8435# 400# 147 958384.029 11.000 - 8 78 70 148 Yb x -30330# 400# 7906# 3# B- * 147 967439# 429# -0 39 94 55 149 Cs x -43250# 400# 8073# 3# B- 9870# 593# 148 953569# 429# - 37 93 56 149 Ba x -53120.309 437.802 8133.793 2.938 B- 7099.605 481.431 148 942973.000 470.000 - 35 92 57 149 La + -60219.913 200.262 8176.191 1.344 B- 6450.000 200.000 148 935351.260 214.990 - 33 91 58 149 Ce x -66669.913 10.246 8214.229 0.069 B- 4369.452 14.230 148 928426.900 11.000 - 31 90 59 149 Pr x -71039.366 9.874 8238.303 0.066 B- 3336.100 10.101 148 923736.100 10.600 - 29 89 60 149 Nd -n -74375.466 2.128 8255.442 0.014 B- 1688.790 2.455 148 920154.648 2.284 - 27 88 61 149 Pm -76064.256 2.267 8261.526 0.015 B- 1071.481 1.875 148 918341.658 2.434 - 25 87 62 149 Sm -77135.737 1.311 8263.466 0.009 B- -694.625 3.788 148 917191.375 1.407 - 23 86 63 149 Eu -76441.112 3.951 8253.554 0.027 B- -1314.101 4.136 148 917937.086 4.241 - 21 85 64 149 Gd -75127.011 3.360 8239.484 0.023 B- -3638.343 4.339 148 919347.831 3.607 - 19 84 65 149 Tb -71488.669 3.667 8209.815 0.025 B- -3792.760 9.162 148 923253.753 3.936 - 17 83 66 149 Dy -67695.909 9.221 8179.109 0.062 B- -6049.330 12.803 148 927325.448 9.898 - 15 82 67 149 Ho -61646.578 11.990 8133.259 0.080 B- -7904.963 30.408 148 933819.672 12.871 - 13 81 68 149 Er x -53741.615 27.945 8074.955 0.188 B- -9859# 198# 148 942306.000 30.000 - 11 80 69 149 Tm x -43883# 196# 8004# 1# B- -10684# 358# 148 952890# 210# - 9 79 70 149 Yb x -33198# 300# 7927# 2# B- * 148 964360# 322# -0 40 95 55 150 Cs x -38170# 400# 8039# 3# B- 11730# 500# 149 959023# 429# - 38 94 56 150 Ba x -49900# 300# 8112# 2# B- 6230# 529# 149 946430# 322# - 36 93 57 150 La x -56129.966 435.473 8148.225 2.903 B- 8716.888 435.631 149 939742.000 467.500 - 34 92 58 150 Ce -64846.854 11.697 8201.122 0.078 B- 3453.625 14.291 149 930384.035 12.556 - 32 91 59 150 Pr -68300.479 9.015 8218.931 0.060 B- 5379.276 9.085 149 926676.415 9.678 - 30 90 60 150 Nd -73679.755 1.289 8249.577 0.009 B- -82.616 20.001 149 920901.525 1.384 - 28 89 61 150 Pm + -73597.139 20.041 8243.810 0.134 B- 3454.000 20.000 149 920990.217 21.514 - 26 88 62 150 Sm -77051.139 1.274 8261.621 0.009 B- -2258.905 6.181 149 917282.195 1.368 - 24 87 63 150 Eu -74792.234 6.253 8241.346 0.042 B- 971.700 3.543 149 919707.229 6.712 - 22 86 64 150 Gd -75763.934 6.076 8242.609 0.041 B- -4658.213 8.379 149 918664.066 6.523 - 20 85 65 150 Tb -71105.721 7.384 8206.338 0.049 B- -1796.122 8.389 149 923664.864 7.927 - 18 84 66 150 Dy -69309.600 4.348 8189.149 0.029 B- -7363.719 14.468 149 925593.080 4.667 - 16 83 67 150 Ho -61945.881 14.168 8134.842 0.094 B- -4114.568 13.591 149 933498.358 15.210 - 14 82 68 150 Er -57831.313 17.195 8102.195 0.115 B- -11340# 196# 149 937915.528 18.459 - 12 81 69 150 Tm x -46491# 196# 8021# 1# B- -7852# 358# 149 950090# 210# - 10 80 70 150 Yb x -38638# 300# 7964# 2# B- -13998# 424# 149 958520# 322# - 8 79 71 150 Lu -p -24640# 300# 7865# 2# B- * 149 973548# 322# -0 41 96 55 151 Cs x -34230# 500# 8013# 3# B- 10710# 640# 150 963253# 537# - 39 95 56 151 Ba x -44940# 400# 8079# 3# B- 8370# 591# 150 951755# 429# - 37 94 57 151 La x -53310.333 435.473 8129.043 2.884 B- 7914.718 435.833 150 942769.000 467.500 - 35 93 58 151 Ce x -61225.052 17.698 8176.277 0.117 B- 5554.578 21.189 150 934272.200 19.000 - 33 92 59 151 Pr -66779.630 11.651 8207.881 0.077 B- 4163.358 11.689 150 928309.114 12.507 - 31 91 60 151 Nd -70942.988 1.293 8230.272 0.009 B- 2443.075 4.473 150 923839.565 1.387 - 29 90 61 151 Pm -73386.063 4.653 8241.270 0.031 B- 1190.217 4.476 150 921216.817 4.994 - 27 89 62 151 Sm -74576.279 1.273 8243.971 0.008 B- 76.574 0.538 150 919939.066 1.367 - 25 88 63 151 Eu -74652.854 1.325 8239.297 0.009 B- -464.116 2.779 150 919856.860 1.422 - 23 87 64 151 Gd -74188.737 3.056 8231.043 0.020 B- -2565.233 3.762 150 920355.109 3.280 - 21 86 65 151 Tb -71623.504 4.137 8208.873 0.027 B- -2871.099 4.944 150 923109.001 4.441 - 19 85 66 151 Dy -a -68752.405 3.293 8184.678 0.022 B- -5129.667 8.756 150 926191.253 3.535 - 17 84 67 151 Ho -a -63622.738 8.302 8145.526 0.055 B- -5356.454 18.444 150 931698.177 8.912 - 15 83 68 151 Er x -58266.284 16.470 8104.872 0.109 B- -7493.528 25.460 150 937448.567 17.681 - 13 82 69 151 Tm +a -50772.756 19.416 8050.064 0.129 B- -9230.414 300.136 150 945493.201 20.843 - 11 81 70 151 Yb ep -41542.342 300.492 7983.755 1.990 B- -11434# 425# 150 955402.458 322.591 - 9 80 71 151 Lu -p -30108# 300# 7903# 2# B- * 150 967677# 322# -0 42 97 55 152 Cs x -28930# 500# 7979# 3# B- 12780# 640# 151 968942# 537# - 40 96 56 152 Ba x -41710# 400# 8057# 3# B- 7580# 500# 151 955222# 429# - 38 95 57 152 La x -49290# 300# 8102# 2# B- 9690# 361# 151 947085# 322# - 36 94 58 152 Ce x -58980# 200# 8161# 1# B- 4778# 201# 151 936682# 215# - 34 93 59 152 Pr x -63758.063 18.537 8187.104 0.122 B- 6391.344 30.710 151 931552.900 19.900 - 32 92 60 152 Nd -70149.407 24.485 8224.005 0.161 B- 1104.778 18.501 151 924691.509 26.285 - 30 91 61 152 Pm -71254.186 25.912 8226.127 0.170 B- 3508.417 25.886 151 923505.481 27.817 - 28 90 62 152 Sm -74762.603 1.212 8244.061 0.008 B- -1874.348 0.687 151 919739.040 1.301 - 26 89 63 152 Eu -72888.255 1.326 8226.583 0.009 B- 1818.661 0.702 151 921751.235 1.423 - 24 88 64 152 Gd -74706.916 1.206 8233.401 0.008 B- -3990.000 40.000 151 919798.822 1.294 - 22 87 65 152 Tb - -70716.916 40.018 8202.004 0.263 B- -599.044 40.258 151 924082.263 42.961 - 20 86 66 152 Dy -a -70117.873 4.624 8192.916 0.030 B- -6513.102 13.325 151 924725.363 4.963 - 18 85 67 152 Ho -63604.771 12.529 8144.919 0.082 B- -3104.394 9.815 151 931717.465 13.450 - 16 84 68 152 Er -60500.377 8.830 8119.349 0.058 B- -8780.104 54.743 151 935050.169 9.479 - 14 83 69 152 Tm -51720.273 54.027 8056.438 0.355 B- -5449.892 139.620 151 944476.000 58.000 - 12 82 70 152 Yb -46270.381 149.708 8015.436 0.985 B- -12848# 246# 151 950326.700 160.718 - 10 81 71 152 Lu x -33422# 196# 7926# 1# B- * 151 964120# 210# -0 41 97 56 153 Ba x -36470# 400# 8023# 3# B- 9590# 500# 152 960848# 429# - 39 96 57 153 La x -46060# 300# 8081# 2# B- 8850# 361# 152 950553# 322# - 37 95 58 153 Ce x -54910# 200# 8134# 1# B- 6659# 201# 152 941052# 215# - 35 94 59 153 Pr -61568.463 11.882 8172.036 0.078 B- 5761.834 12.190 152 933903.532 12.755 - 33 93 60 153 Nd -67330.297 2.747 8204.582 0.018 B- 3317.527 9.355 152 927717.949 2.948 - 31 92 61 153 Pm -70647.824 9.066 8221.152 0.059 B- 1911.862 9.093 152 924156.436 9.732 - 29 91 62 153 Sm -n -72559.686 1.219 8228.534 0.008 B- 807.536 0.708 152 922103.969 1.309 - 27 90 63 153 Eu -73367.222 1.330 8228.699 0.009 B- -484.671 0.717 152 921237.043 1.428 - 25 89 64 153 Gd -72882.551 1.203 8220.418 0.008 B- -1569.213 3.845 152 921757.359 1.291 - 23 88 65 153 Tb -71313.338 3.995 8205.048 0.026 B- -2170.394 1.933 152 923441.978 4.289 - 21 87 66 153 Dy -69142.943 4.048 8185.749 0.026 B- -4130.840 6.157 152 925771.992 4.346 - 19 86 67 153 Ho -a -65012.103 5.094 8153.637 0.033 B- -4543.499 9.916 152 930206.632 5.468 - 17 85 68 153 Er -60468.604 9.321 8118.827 0.061 B- -6495.276 12.891 152 935084.279 10.006 - 15 84 69 153 Tm -53973.329 11.983 8071.261 0.078 B- -6765# 196# 152 942057.244 12.864 - 13 83 70 153 Yb x -47208# 196# 8022# 1# B- -8835# 247# 152 949320# 210# - 11 82 71 153 Lu +a -38372.844 150.034 7959.070 0.981 B- -11073# 335# 152 958805.054 161.068 - 9 81 72 153 Hf x -27300# 300# 7882# 2# B- * 152 970692# 322# -0 42 98 56 154 Ba x -32820# 500# 8000# 3# B- 8709# 583# 153 964766# 537# - 40 97 57 154 La x -41530# 300# 8051# 2# B- 10690# 361# 153 955416# 322# - 38 96 58 154 Ce x -52220# 200# 8116# 1# B- 5885# 230# 153 943940# 215# - 36 95 59 154 Pr + -58104.976 113.009 8148.892 0.734 B- 7720.000 100.000 153 937621.738 121.320 - 34 94 60 154 Nd + -65824.976 52.642 8193.942 0.342 B- 2687.000 25.000 153 929333.977 56.513 - 32 93 61 154 Pm IT -68511.976 46.326 8206.310 0.301 B- 3943.200 46.303 153 926449.364 49.733 - 30 92 62 154 Sm -72455.176 1.462 8226.835 0.009 B- -717.056 1.103 153 922216.164 1.569 - 28 91 63 154 Eu -71738.121 1.346 8217.098 0.009 B- 1967.834 0.755 153 922985.955 1.444 - 26 90 64 154 Gd -73705.954 1.197 8224.796 0.008 B- -3549.651 45.298 153 920873.398 1.285 - 24 89 65 154 Tb - -70156.303 45.314 8196.666 0.294 B- 237.604 45.901 153 924684.106 48.646 - 22 88 66 154 Dy -70393.907 7.445 8193.129 0.048 B- -5754.596 10.178 153 924429.028 7.992 - 20 87 67 154 Ho -a -64639.311 8.228 8150.681 0.053 B- -2034.291 9.463 153 930606.841 8.833 - 18 86 68 154 Er -62605.020 4.986 8132.392 0.032 B- -8177.888 14.916 153 932790.743 5.353 - 16 85 69 154 Tm -a -54427.131 14.412 8074.208 0.094 B- -4495.048 13.953 153 941570.067 15.472 - 14 84 70 154 Yb -49932.083 17.281 8039.939 0.112 B- -10217# 197# 153 946395.701 18.552 - 12 83 71 154 Lu +a -39715# 196# 7969# 1# B- -7045# 358# 153 957364# 211# - 10 82 72 154 Hf x -32670# 300# 7918# 2# B- * 153 964927# 322# -0 41 98 57 155 La x -37930# 400# 8028# 3# B- 9850# 500# 154 959280# 429# - 39 97 58 155 Ce x -47780# 300# 8087# 2# B- 7635# 300# 154 948706# 322# - 37 96 59 155 Pr -55415.268 17.198 8131.039 0.111 B- 6868.456 19.472 154 940509.259 18.462 - 35 95 60 155 Nd -62283.724 9.153 8170.304 0.059 B- 4656.207 10.278 154 933135.668 9.826 - 33 94 61 155 Pm -66939.931 4.718 8195.296 0.030 B- 3250.888 4.946 154 928137.024 5.065 - 31 93 62 155 Sm -n -70190.819 1.487 8211.223 0.010 B- 1627.273 1.202 154 924647.051 1.595 - 29 92 63 155 Eu -71818.092 1.401 8216.674 0.009 B- 251.788 0.870 154 922900.102 1.504 - 27 91 64 155 Gd -72069.880 1.191 8213.251 0.008 B- -819.830 9.789 154 922629.796 1.278 - 25 90 65 155 Tb + -71250.050 9.849 8202.914 0.064 B- -2094.500 1.897 154 923509.921 10.573 - 23 89 66 155 Dy -69155.550 9.665 8184.354 0.062 B- -3116.011 16.590 154 925758.459 10.375 - 21 88 67 155 Ho -66039.539 17.474 8159.203 0.113 B- -3830.350 18.474 154 929103.634 18.759 - 19 87 68 155 Er -a -62209.189 6.098 8129.444 0.039 B- -5583.276 11.515 154 933215.684 6.546 - 17 86 69 155 Tm -a -56625.913 9.925 8088.375 0.064 B- -6123.305 19.341 154 939209.578 10.654 - 15 85 70 155 Yb -a -50502.608 16.600 8043.823 0.107 B- -7957.561 25.416 154 945783.217 17.820 - 13 84 71 155 Lu +a -42545.047 19.246 7987.436 0.124 B- -8375# 299# 154 954326.011 20.661 - 11 83 72 155 Hf x -34170# 298# 7928# 2# B- -10242# 423# 154 963317# 320# - 9 82 73 155 Ta -p -23928# 300# 7857# 2# B- * 154 974312# 322# -0 42 99 57 156 La x -33050# 400# 7997# 3# B- 11769# 500# 155 964519# 429# - 40 98 58 156 Ce x -44820# 300# 8068# 2# B- 6748# 361# 155 951884# 322# - 38 97 59 156 Pr x -51568# 200# 8106# 1# B- 8906# 283# 155 944640# 215# - 36 96 60 156 Nd + -60473.644 200.033 8158.066 1.282 B- 3690.000 200.000 155 935078.868 214.744 - 34 95 61 156 Pm -64163.644 3.631 8176.705 0.023 B- 5196.786 9.285 155 931117.490 3.897 - 32 94 62 156 Sm -69360.430 8.546 8205.003 0.055 B- 722.118 7.902 155 925538.511 9.174 - 30 93 63 156 Eu -70082.548 3.590 8204.617 0.023 B- 2452.366 3.409 155 924763.285 3.853 - 28 92 64 156 Gd -72534.914 1.190 8215.322 0.008 B- -2444.117 3.679 155 922130.562 1.277 - 26 91 65 156 Tb -70090.797 3.814 8194.639 0.024 B- 438.167 3.681 155 924754.430 4.094 - 24 90 66 156 Dy -70528.964 1.194 8192.433 0.008 B- -5050.000 60.000 155 924284.038 1.281 - 22 89 67 156 Ho - -65478.964 60.012 8155.046 0.385 B- -1267.255 64.869 155 929705.436 64.425 - 20 88 68 156 Er -64211.709 24.629 8141.908 0.158 B- -7377.159 26.710 155 931065.890 26.440 - 18 87 69 156 Tm -56834.550 14.279 8089.603 0.092 B- -3568.830 12.548 155 938985.597 15.328 - 16 86 70 156 Yb -53265.721 9.308 8061.711 0.060 B- -9566.176 54.916 155 942816.893 9.992 - 14 85 71 156 Lu -a -43699.544 54.122 7995.374 0.347 B- -5882.648 139.709 155 953086.606 58.102 - 12 84 72 156 Hf -37816.896 149.757 7952.650 0.960 B- -11956# 334# 155 959401.889 160.770 - 10 83 73 156 Ta -p -25861# 298# 7871# 2# B- * 155 972237# 320# -0 41 99 58 157 Ce x -39930# 400# 8037# 3# B- 8610# 500# 156 957133# 429# - 39 98 59 157 Pr x -48540# 300# 8086# 2# B- 7921# 301# 156 947890# 322# - 37 97 60 157 Nd -56461.543 24.918 8131.959 0.159 B- 5835.500 25.877 156 939386.037 26.750 - 35 96 61 157 Pm -62297.043 7.006 8164.145 0.045 B- 4380.534 8.265 156 933121.370 7.521 - 33 95 62 157 Sm -66677.577 4.433 8187.063 0.028 B- 2781.331 6.136 156 928418.673 4.759 - 31 94 63 157 Eu -69458.908 4.259 8199.795 0.027 B- 1364.565 4.203 156 925432.791 4.572 - 29 93 64 157 Gd -70823.473 1.189 8203.504 0.008 B- -60.043 0.297 156 923967.870 1.276 - 27 92 65 157 Tb -70763.430 1.222 8198.138 0.008 B- -1338.872 5.134 156 924032.328 1.311 - 25 91 66 157 Dy -69424.558 5.177 8184.627 0.033 B- -2591.725 23.787 156 925469.667 5.557 - 23 90 67 157 Ho -66832.832 23.469 8163.136 0.149 B- -3419.194 33.668 156 928251.999 25.195 - 21 89 68 157 Er -63413.639 26.505 8136.375 0.169 B- -4704.366 38.515 156 931922.655 28.454 - 19 88 69 157 Tm x -58709.273 27.945 8101.428 0.178 B- -5287.374 30.003 156 936973.000 30.000 - 17 87 70 157 Yb -53421.898 10.920 8062.767 0.070 B- -6981.376 14.241 156 942649.230 11.723 - 15 86 71 157 Lu -46440.523 12.078 8013.317 0.077 B- -7537# 196# 156 950144.045 12.965 - 13 85 72 157 Hf -a -38903# 196# 7960# 1# B- -9310# 247# 156 958236# 210# - 11 84 73 157 Ta IT -29593.330 150.069 7896.043 0.956 B- -10123# 427# 156 968230.251 161.105 - 9 83 74 157 W x -19470# 400# 7827# 3# B- * 156 979098# 429# -0 42 100 58 158 Ce x -36660# 400# 8016# 3# B- 7670# 500# 157 960644# 429# - 40 99 59 158 Pr x -44330# 300# 8060# 2# B- 9725# 361# 157 952410# 322# - 38 98 60 158 Nd x -54055# 200# 8116# 1# B- 5035# 201# 157 941970# 215# - 36 97 61 158 Pm -59089.209 13.453 8143.254 0.085 B- 6161.034 14.299 157 936565.121 14.442 - 34 96 62 158 Sm -65250.243 4.892 8177.297 0.031 B- 2004.945 10.369 157 929950.979 5.251 - 32 95 63 158 Eu -67255.188 10.255 8185.035 0.065 B- 3434.358 10.323 157 927798.581 11.008 - 30 94 64 158 Gd -70689.546 1.189 8201.819 0.008 B- -1218.878 0.987 157 924111.646 1.276 - 28 93 65 158 Tb -69470.668 1.401 8189.153 0.009 B- 936.681 2.495 157 925420.166 1.503 - 26 92 66 158 Dy -70407.349 2.365 8190.130 0.015 B- -4219.755 27.005 157 924414.597 2.538 - 24 91 67 158 Ho - -66187.593 27.108 8158.471 0.172 B- -883.785 37.025 157 928944.692 29.101 - 22 90 68 158 Er -65303.808 25.219 8147.926 0.160 B- -6600.615 31.341 157 929893.474 27.074 - 20 89 69 158 Tm -58703.194 25.219 8101.199 0.160 B- -2692.957 26.456 157 936979.525 27.074 - 18 88 70 158 Yb -56010.237 7.994 8079.203 0.051 B- -8798.047 16.872 157 939870.534 8.582 - 16 87 71 158 Lu -a -47212.190 15.125 8018.568 0.096 B- -5109.800 14.937 157 949315.626 16.237 - 14 86 72 158 Hf -42102.390 17.494 7981.276 0.111 B- -10936# 197# 157 954801.222 18.780 - 12 85 73 158 Ta +a -31167# 196# 7907# 1# B- -7534# 358# 157 966541# 210# - 10 84 74 158 W -a -23633# 300# 7854# 2# B- * 157 974629# 322# -0 41 100 59 159 Pr x -41088# 400# 8039# 3# B- 8719# 500# 158 955890# 429# - 39 99 60 159 Nd x -49807# 300# 8089# 2# B- 6747# 300# 158 946530# 322# - 37 98 61 159 Pm -56554.280 10.039 8126.859 0.063 B- 5653.495 11.644 158 939286.479 10.777 - 35 97 62 159 Sm -62207.775 5.934 8157.495 0.037 B- 3835.510 7.324 158 933217.202 6.369 - 33 96 63 159 Eu -66043.285 4.325 8176.697 0.027 B- 2518.150 4.391 158 929099.612 4.643 - 31 95 64 159 Gd -68561.436 1.192 8187.614 0.007 B- 970.927 0.759 158 926396.267 1.279 - 29 94 65 159 Tb -69532.363 1.256 8188.800 0.008 B- -365.229 1.162 158 925353.933 1.348 - 27 93 66 159 Dy -69167.134 1.528 8181.583 0.010 B- -1837.600 2.683 158 925746.023 1.640 - 25 92 67 159 Ho - -67329.534 3.088 8165.105 0.019 B- -2768.500 2.000 158 927718.768 3.314 - 23 91 68 159 Er - -64561.034 3.679 8142.773 0.023 B- -3990.637 28.186 158 930690.875 3.949 - 21 90 69 159 Tm x -60570.398 27.945 8112.754 0.176 B- -4731.792 33.129 158 934975.000 30.000 - 19 89 70 159 Yb x -55838.606 17.794 8078.074 0.112 B- -6130.002 41.655 158 940054.787 19.102 - 17 88 71 159 Lu x -49708.604 37.663 8034.600 0.237 B- -6856.004 41.246 158 946635.615 40.433 - 15 87 72 159 Hf -a -42852.600 16.813 7986.560 0.106 B- -8413.452 25.891 158 953995.838 18.049 - 13 86 73 159 Ta IT -34439.148 19.689 7928.725 0.124 B- -9145# 299# 158 963028.052 21.137 - 11 85 74 159 W -a -25295# 298# 7866# 2# B- -10550# 426# 158 972845# 320# - 9 84 75 159 Re IT -14745# 305# 7795# 2# B- * 158 984171# 327# -0 42 101 59 160 Pr x -36520# 400# 8011# 2# B- 10613# 500# 159 960794# 429# - 40 100 60 160 Nd x -47134# 300# 8073# 2# B- 5868# 361# 159 949400# 322# - 38 99 61 160 Pm x -53002# 200# 8104# 1# B- 7233# 200# 159 943100# 215# - 36 98 62 160 Sm -60234.793 5.934 8144.625 0.037 B- 3245.670 11.183 159 935335.286 6.370 - 34 97 63 160 Eu -63480.463 9.501 8160.021 0.059 B- 4461.278 9.586 159 931850.916 10.199 - 32 96 64 160 Gd -67941.741 1.278 8183.014 0.008 B- -105.483 1.022 159 927061.537 1.371 - 30 95 65 160 Tb -67836.257 1.262 8177.465 0.008 B- 1836.472 1.172 159 927174.778 1.354 - 28 94 66 160 Dy -69672.730 0.772 8184.054 0.005 B- -3290.000 15.000 159 925203.244 0.828 - 26 93 67 160 Ho - -66382.730 15.020 8158.602 0.094 B- -318.502 28.528 159 928735.204 16.124 - 24 92 68 160 Er -66064.228 24.254 8151.721 0.152 B- -5762.200 40.311 159 929077.130 26.037 - 22 91 69 160 Tm -60302.028 34.262 8110.818 0.214 B- -2139.322 35.017 159 935263.106 36.781 - 20 90 70 160 Yb -58162.706 7.233 8092.557 0.045 B- -7892.769 57.280 159 937559.763 7.764 - 18 89 71 160 Lu x -50269.937 56.821 8038.338 0.355 B- -4330.994 57.617 159 946033.000 61.000 - 16 88 72 160 Hf -45938.943 9.541 8006.380 0.060 B- -10115.249 55.147 159 950682.513 10.242 - 14 87 73 160 Ta -a -35823.695 54.316 7938.270 0.339 B- -6497.240 139.859 159 961541.679 58.310 - 12 86 74 160 W -29326.455 149.827 7892.772 0.936 B- -12588# 334# 159 968516.753 160.846 - 10 85 75 160 Re -a -16739# 298# 7809# 2# B- * 159 982030# 320# -0 41 101 60 161 Nd x -42588# 400# 8044# 2# B- 7648# 499# 160 954280# 429# - 39 100 61 161 Pm x -50235# 298# 8087# 2# B- 6436# 298# 160 946070# 320# - 37 99 62 161 Sm -56671.962 6.817 8122.041 0.042 B- 5119.562 12.415 160 939160.143 7.318 - 35 98 63 161 Eu -61791.524 10.399 8148.980 0.065 B- 3714.299 10.525 160 933664.066 11.164 - 33 97 64 161 Gd -n -65505.824 1.622 8167.191 0.010 B- 1955.765 1.442 160 929676.602 1.741 - 31 96 65 161 Tb -67461.589 1.350 8174.479 0.008 B- 594.212 1.260 160 927577.001 1.449 - 29 95 66 161 Dy -68055.801 0.768 8173.310 0.005 B- -858.530 2.166 160 926939.088 0.824 - 27 94 67 161 Ho -67197.270 2.242 8163.119 0.014 B- -1995.663 9.011 160 927860.759 2.406 - 25 93 68 161 Er +n -65201.608 8.780 8145.864 0.055 B- -3302.900 29.292 160 930003.191 9.425 - 23 92 69 161 Tm x -61898.708 27.945 8120.490 0.174 B- -4059.308 31.885 160 933549.000 30.000 - 21 91 70 161 Yb x -57839.400 15.354 8090.417 0.095 B- -5277.056 31.885 160 937906.846 16.483 - 19 90 71 161 Lu x -52562.344 27.945 8052.781 0.174 B- -6247.672 35.909 160 943572.000 30.000 - 17 89 72 161 Hf -46314.672 22.551 8009.117 0.140 B- -7535.674 33.097 160 950279.151 24.209 - 15 88 73 161 Ta +a -38778.997 24.382 7957.452 0.151 B- -8224# 197# 160 958369.031 26.175 - 13 87 74 161 W -a -30555# 196# 7902# 1# B- -9715# 247# 160 967197# 210# - 11 86 75 161 Re -20840.203 149.922 7836.312 0.931 B- -10861# 427# 160 977627.121 160.948 - 9 85 76 161 Os -a -9979# 400# 7764# 2# B- * 160 989287# 429# -0 42 102 60 162 Nd x -39550# 400# 8026# 2# B- 6819# 500# 161 957541# 429# - 40 101 61 162 Pm x -46370# 300# 8063# 2# B- 8160# 358# 161 950220# 322# - 38 100 62 162 Sm x -54530# 196# 8109# 1# B- 4174# 199# 161 941460# 210# - 36 99 63 162 Eu + -58703.401 35.229 8129.438 0.217 B- 5577.000 35.000 161 936979.303 37.819 - 34 98 64 162 Gd -nn -64280.401 4.009 8159.035 0.025 B- 1395.556 36.581 161 930992.146 4.303 - 32 97 65 162 Tb + -65675.958 36.372 8162.820 0.225 B- 2505.521 36.364 161 929493.955 39.046 - 30 96 66 162 Dy -68181.478 0.767 8173.457 0.005 B- -2139.937 3.113 161 926804.168 0.822 - 28 95 67 162 Ho -66041.541 3.166 8155.418 0.020 B- 292.978 3.127 161 929101.485 3.398 - 26 94 68 162 Er -66334.519 0.822 8152.397 0.005 B- -4856.728 26.047 161 928786.960 0.882 - 24 93 69 162 Tm - -61477.791 26.060 8117.588 0.161 B- -1651.444 30.240 161 934000.872 27.977 - 22 92 70 162 Yb x -59826.347 15.359 8102.565 0.095 B- -6994.593 76.592 161 935773.771 16.488 - 20 91 71 162 Lu x -52831.753 75.036 8054.559 0.463 B- -3662.746 75.570 161 943282.776 80.554 - 18 90 72 162 Hf -49169.008 8.968 8027.120 0.055 B- -9388.814 52.931 161 947214.896 9.627 - 16 89 73 162 Ta -a -39780.194 52.238 7964.335 0.322 B- -5780.987 52.239 161 957294.202 56.079 - 14 88 74 162 W -33999.207 17.658 7923.821 0.109 B- -11498# 197# 161 963500.347 18.956 - 12 87 75 162 Re +a -22501# 196# 7848# 1# B- -8061# 358# 161 975844# 210# - 10 86 76 162 Os -a -14440# 300# 7793# 2# B- * 161 984498# 322# -0 41 102 61 163 Pm x -43249# 400# 8044# 2# B- 7471# 499# 162 953570# 429# - 39 101 62 163 Sm x -50720# 298# 8085# 2# B- 5765# 305# 162 945550# 320# - 37 100 63 163 Eu + -56484.886 65.544 8115.471 0.402 B- 4829.000 65.000 162 939360.977 70.364 - 35 99 64 163 Gd -61313.886 8.426 8140.297 0.052 B- 3282.185 9.358 162 934176.832 9.045 - 33 98 65 163 Tb +p -64596.071 4.073 8155.633 0.025 B- 1785.099 4.001 162 930653.261 4.372 - 31 97 66 163 Dy -66381.170 0.765 8161.785 0.005 B- -2.834 0.019 162 928736.879 0.821 - 29 96 67 163 Ho -66378.335 0.765 8156.968 0.005 B- -1210.612 4.575 162 928739.921 0.821 - 27 95 68 163 Er -65167.723 4.639 8144.741 0.028 B- -2439.000 3.000 162 930039.567 4.980 - 25 94 69 163 Tm - -62728.723 5.524 8124.979 0.034 B- -3429.629 16.309 162 932657.941 5.930 - 23 93 70 163 Yb x -59299.094 15.364 8099.138 0.094 B- -4507.685 31.890 162 936339.800 16.493 - 21 92 71 163 Lu x -54791.409 27.945 8066.684 0.171 B- -5527.726 37.348 162 941179.000 30.000 - 19 91 72 163 Hf -49263.682 24.778 8027.972 0.152 B- -6729.054 45.416 162 947113.258 26.599 - 17 90 73 163 Ta -a -42534.629 38.061 7981.890 0.234 B- -7626.436 65.049 162 954337.195 40.860 - 15 89 74 163 W -a -34908.193 52.751 7930.302 0.324 B- -8905.949 55.912 162 962524.511 56.630 - 13 88 75 163 Re +a -26002.244 18.534 7870.865 0.114 B- -9810# 299# 162 972085.441 19.897 - 11 87 76 163 Os -a -16192# 298# 7806# 2# B- * 162 982617# 320# -0 42 103 61 164 Pm x -38870# 400# 8017# 2# B- 9232# 499# 163 958271# 429# - 40 102 62 164 Sm x -48102# 298# 8069# 2# B- 5279# 319# 163 948360# 320# - 38 101 63 164 Eu + -53381# 114# 8096# 1# B- 6393.000 50.000 163 942693# 122# - 36 100 64 164 Gd x -59774# 102# 8130# 1# B- 2304# 143# 163 935830# 110# - 34 99 65 164 Tb + -62077.965 100.003 8139.765 0.610 B- 3890.000 100.000 163 933356.559 107.357 - 32 98 66 164 Dy -65967.965 0.767 8158.714 0.005 B- -986.463 1.415 163 929180.472 0.823 - 30 97 67 164 Ho -64981.503 1.528 8147.929 0.009 B- 961.387 1.420 163 930239.483 1.639 - 28 96 68 164 Er -65942.890 0.775 8149.020 0.005 B- -4038.855 24.401 163 929207.392 0.832 - 26 95 69 164 Tm -61904.035 24.394 8119.623 0.149 B- -886.617 28.829 163 933543.281 26.188 - 24 94 70 164 Yb x -61017.418 15.369 8109.446 0.094 B- -6375.048 31.892 163 934495.103 16.499 - 22 93 71 164 Lu x -54642.370 27.945 8065.804 0.170 B- -2823.865 32.112 163 941339.000 30.000 - 20 92 72 164 Hf -51818.505 15.820 8043.814 0.096 B- -8535.704 32.112 163 944370.544 16.983 - 18 91 73 164 Ta x -43282.800 27.945 7986.997 0.170 B- -5047.041 29.572 163 953534.000 30.000 - 16 90 74 164 W -38235.759 9.674 7951.452 0.059 B- -10763.323 55.406 163 958952.222 10.385 - 14 89 75 164 Re -a -27472.436 54.555 7881.052 0.333 B- -7050.331 140.051 163 970507.124 58.566 - 12 88 76 164 Os -20422.106 149.919 7833.291 0.914 B- -13078# 348# 163 978075.966 160.945 - 10 87 77 164 Ir -a -7344# 314# 7749# 2# B- * 163 992116# 338# -0 41 103 62 165 Sm x -43808# 401# 8043# 2# B- 6916# 424# 164 952970# 430# - 39 102 63 165 Eu + -50724# 138# 8080# 1# B- 5729.000 65.000 164 945546# 148# - 37 101 64 165 Gd + -56453# 121# 8110# 1# B- 4113.000 65.000 164 939395# 130# - 35 100 65 165 Tb x -60566# 102# 8130# 1# B- 3047# 102# 164 934980# 110# - 33 99 66 165 Dy -n -63612.606 0.769 8143.909 0.005 B- 1286.400 0.829 164 931709.054 0.825 - 31 98 67 165 Ho -64899.006 1.010 8146.964 0.006 B- -377.396 1.033 164 930328.047 1.084 - 29 97 68 165 Er -64521.610 0.964 8139.936 0.006 B- -1591.990 1.538 164 930733.198 1.034 - 27 96 69 165 Tm -62929.621 1.671 8125.546 0.010 B- -2634.239 26.592 164 932442.269 1.793 - 25 95 70 165 Yb -60295.382 26.539 8104.839 0.161 B- -3853.140 35.432 164 935270.241 28.490 - 23 94 71 165 Lu -56442.242 26.539 8076.745 0.161 B- -4806.734 38.539 164 939406.758 28.490 - 21 93 72 165 Hf x -51635.507 27.945 8042.872 0.169 B- -5787.655 31.195 164 944567.000 30.000 - 19 92 73 165 Ta -45847.853 13.863 8003.054 0.084 B- -6986.830 28.566 164 950780.303 14.882 - 17 91 74 165 W -38861.022 24.977 7955.968 0.151 B- -8201.246 34.332 164 958280.974 26.813 - 15 90 75 165 Re +a -30659.776 23.594 7901.522 0.143 B- -8865# 197# 164 967085.375 25.329 - 13 89 76 165 Os -a -21795# 196# 7843# 1# B- -10202# 252# 164 976602# 210# - 11 88 77 165 Ir IT -11593# 158# 7776# 1# B- * 164 987555# 170# -0 42 104 62 166 Sm x -40730# 400# 8024# 2# B- 6478# 537# 165 956275# 429# - 40 103 63 166 Eu + -47208# 358# 8059# 2# B- 7322.000 300.000 165 949320# 384# - 38 102 64 166 Gd x -54530# 196# 8098# 1# B- 3355# 208# 165 941460# 210# - 36 101 65 166 Tb + -57884.789 70.005 8113.680 0.422 B- 4700.000 70.000 165 937858.119 75.153 - 34 100 66 166 Dy -n -62584.789 0.867 8137.280 0.005 B- 486.540 0.921 165 932812.461 0.930 - 32 99 67 166 Ho -63071.329 1.010 8135.499 0.006 B- 1854.713 0.922 165 932290.139 1.084 - 30 98 68 166 Er -64926.042 1.165 8141.959 0.007 B- -3037.667 11.547 165 930299.023 1.251 - 28 97 69 166 Tm - -61888.375 11.606 8118.946 0.070 B- -292.635 13.507 165 933560.092 12.459 - 26 96 70 166 Yb +nn -61595.740 7.101 8112.471 0.043 B- -5574.759 30.642 165 933874.249 7.623 - 24 95 71 166 Lu x -56020.981 29.808 8074.175 0.180 B- -2161.998 40.859 165 939859.000 32.000 - 22 94 72 166 Hf x -53858.983 27.945 8056.438 0.168 B- -7761.208 39.520 165 942180.000 30.000 - 20 93 73 166 Ta x -46097.775 27.945 8004.971 0.168 B- -4209.744 29.508 165 950512.000 30.000 - 18 92 74 166 W -41888.031 9.478 7974.898 0.057 B- -9994.553 72.879 165 955031.346 10.174 - 16 91 75 166 Re -a -31893.478 72.310 7909.977 0.436 B- -6461.961 72.387 165 965760.940 77.628 - 14 90 76 166 Os -25431.517 17.966 7866.336 0.108 B- -12078# 197# 165 972698.141 19.287 - 12 89 77 166 Ir -p -13354# 196# 7789# 1# B- -8624# 359# 165 985664# 210# - 10 88 78 166 Pt -a -4730# 300# 7732# 2# B- * 165 994923# 322# -0 41 104 63 167 Eu x -44010# 400# 8040# 2# B- 6803# 499# 166 952753# 429# - 39 103 64 167 Gd x -50813# 298# 8076# 2# B- 5114# 357# 166 945450# 320# - 37 102 65 167 Tb x -55927# 196# 8102# 1# B- 4004# 205# 166 939960# 210# - 35 101 66 167 Dy + -59930.626 60.228 8120.992 0.361 B- 2350.000 60.000 166 935661.823 64.657 - 33 100 67 167 Ho p2n -62280.626 5.234 8130.379 0.031 B- 1010.554 5.208 166 933138.994 5.618 - 31 99 68 167 Er -63291.180 1.166 8131.746 0.007 B- -747.539 1.501 166 932054.119 1.252 - 29 98 69 167 Tm -62543.641 1.298 8122.585 0.008 B- -1953.065 3.798 166 932856.635 1.393 - 27 97 70 167 Yb -60590.576 3.981 8106.205 0.024 B- -3089.451 31.920 166 934953.337 4.273 - 25 96 71 167 Lu x -57501.125 31.671 8083.021 0.190 B- -4033.369 42.237 166 938270.000 34.000 - 23 95 72 167 Hf x -53467.756 27.945 8054.184 0.167 B- -5116.697 39.520 166 942600.000 30.000 - 21 94 73 167 Ta x -48351.059 27.945 8018.861 0.167 B- -6253.001 33.382 166 948093.000 30.000 - 19 93 74 167 W -42098.058 18.261 7976.733 0.109 B- -7267# 44# 166 954805.873 19.603 - 17 92 75 167 Re +a -34831# 40# 7929# 0# B- -8329# 83# 166 962607# 43# - 15 91 76 167 Os -a -26501.993 72.682 7873.974 0.435 B- -9429.554 74.962 166 971548.938 78.027 - 13 90 77 167 Ir -17072.440 18.346 7812.825 0.110 B- -10460# 303# 166 981671.981 19.695 - 11 89 78 167 Pt -a -6612# 302# 7746# 2# B- * 166 992901# 325# -0 42 105 63 168 Eu x -39740# 500# 8014# 3# B- 8623# 641# 167 957337# 537# - 40 104 64 168 Gd x -48363# 401# 8061# 2# B- 4359# 499# 167 948080# 430# - 38 103 65 168 Tb x -52723# 298# 8082# 2# B- 5837# 329# 167 943400# 320# - 36 102 66 168 Dy +pp -58559.566 140.009 8112.536 0.833 B- 1501.605 143.186 167 937133.716 150.305 - 34 101 67 168 Ho + -60061.171 30.023 8116.817 0.179 B- 2930.000 30.000 167 935521.676 32.230 - 32 100 68 168 Er -62991.171 1.168 8129.601 0.007 B- -1678.250 1.870 167 932376.192 1.254 - 30 99 69 168 Tm -61312.921 1.709 8114.954 0.010 B- 268.980 1.887 167 934177.868 1.834 - 28 98 70 168 Yb -61581.901 1.195 8111.898 0.007 B- -4514.051 39.248 167 933889.106 1.282 - 26 97 71 168 Lu - -57067.850 39.266 8080.372 0.234 B- -1707.299 48.195 167 938735.139 42.153 - 24 96 72 168 Hf x -55360.552 27.945 8065.553 0.166 B- -6966.644 39.520 167 940568.000 30.000 - 22 95 73 168 Ta x -48393.908 27.945 8019.428 0.166 B- -3500.799 30.936 167 948047.000 30.000 - 20 94 74 168 W -44893.109 13.271 7993.933 0.079 B- -9098.224 33.556 167 951805.262 14.247 - 18 93 75 168 Re -a -35794.885 30.821 7935.120 0.183 B- -5799.672 32.373 167 961572.608 33.087 - 16 92 76 168 Os -29995.213 9.904 7895.941 0.059 B- -11328.987 56.098 167 967798.812 10.632 - 14 91 77 168 Ir -a -18666.226 55.216 7823.850 0.329 B- -7658.765 140.344 167 979960.981 59.277 - 12 90 78 168 Pt -a -11007.460 149.951 7773.605 0.893 B- * 167 988183.004 160.978 -0 41 105 64 169 Gd x -44153# 503# 8036# 3# B- 6176# 585# 168 952600# 540# - 39 104 65 169 Tb x -50329# 298# 8068# 2# B- 5269# 423# 168 945970# 320# - 37 103 66 169 Dy + -55597.177 300.670 8094.763 1.779 B- 3200.000 300.000 168 940313.971 322.782 - 35 102 67 169 Ho +p -58797.177 20.060 8109.068 0.119 B- 2125.927 20.053 168 936878.630 21.534 - 33 101 68 169 Er -n -60923.104 1.179 8117.019 0.007 B- 352.108 1.114 168 934596.353 1.265 - 31 100 69 169 Tm -61275.212 0.812 8114.473 0.005 B- -897.650 1.141 168 934218.350 0.871 - 29 99 70 169 Yb -n -60377.563 1.205 8104.532 0.007 B- -2293.000 3.000 168 935182.016 1.293 - 27 98 71 169 Lu - -58084.563 3.233 8086.335 0.019 B- -3367.673 28.131 168 937643.653 3.470 - 25 97 72 169 Hf x -54716.889 27.945 8061.778 0.165 B- -4426.460 39.520 168 941259.000 30.000 - 23 96 73 169 Ta x -50290.430 27.945 8030.957 0.165 B- -5372.557 31.925 168 946011.000 30.000 - 21 95 74 169 W -44917.873 15.436 7994.537 0.091 B- -6508.641 19.173 168 951778.677 16.571 - 19 94 75 169 Re +a -38409.232 11.374 7951.395 0.067 B- -7686.541 27.618 168 958765.991 12.210 - 17 93 76 169 Os -a -30722.691 25.167 7901.284 0.149 B- -8628.852 34.276 168 967017.833 27.017 - 15 92 77 169 Ir +a -22093.839 23.308 7845.596 0.138 B- -9581# 197# 168 976281.287 25.021 - 13 91 78 169 Pt -a -12512# 196# 7784# 1# B- -10724# 357# 168 986567# 210# - 11 90 79 169 Au x -1788# 298# 7716# 2# B- * 168 998080# 320# -0 42 106 64 170 Gd x -41380# 596# 8020# 4# B- 5344# 718# 169 955577# 640# - 40 105 65 170 Tb x -46724# 401# 8047# 2# B- 6940# 446# 169 949840# 430# - 38 104 66 170 Dy x -53663# 196# 8083# 1# B- 2575# 202# 169 942390# 210# - 36 103 67 170 Ho + -56238.681 50.024 8093.796 0.294 B- 3870.000 50.000 169 939625.289 53.702 - 34 102 68 170 Er -60108.681 1.546 8111.959 0.009 B- -312.828 1.821 169 935470.673 1.659 - 32 101 69 170 Tm -59795.853 0.801 8105.517 0.005 B- 968.066 0.801 169 935806.507 0.859 - 30 100 70 170 Yb -60763.919 0.010 8106.609 0.000 B- -3457.695 16.843 169 934767.245 0.011 - 28 99 71 170 Lu - -57306.224 16.843 8081.668 0.099 B- -1052.370 32.628 169 938479.234 18.081 - 26 98 72 170 Hf x -56253.854 27.945 8070.875 0.164 B- -6116.190 39.520 169 939609.000 30.000 - 24 97 73 170 Ta x -50137.665 27.945 8030.296 0.164 B- -2846.832 30.904 169 946175.000 30.000 - 22 96 74 170 W -47290.832 13.195 8008.948 0.078 B- -8377.639 26.611 169 949231.200 14.165 - 20 95 75 170 Re -38913.193 23.109 7955.065 0.136 B- -4986.946 25.091 169 958224.966 24.808 - 18 94 76 170 Os -33926.247 9.773 7921.128 0.057 B- -10567# 89# 169 963578.673 10.491 - 16 93 77 170 Ir -a -23360# 89# 7854# 1# B- -7060# 89# 169 974922# 95# - 14 92 78 170 Pt -16299.193 18.247 7808.236 0.107 B- -12547# 197# 169 982502.095 19.588 - 12 91 79 170 Au -p -3752# 196# 7730# 1# B- * 169 995972# 211# -0 41 106 65 171 Tb x -44032# 503# 8031# 3# B- 6157# 585# 170 952730# 540# - 39 105 66 171 Dy x -50189# 298# 8063# 2# B- 4330# 670# 170 946120# 320# - 37 104 67 171 Ho + -54518.956 600.002 8083.608 3.509 B- 3200.000 600.000 170 941471.490 644.128 - 35 103 68 171 Er -57718.956 1.557 8097.746 0.009 B- 1491.342 1.256 170 938036.148 1.670 - 33 102 69 171 Tm -59210.298 0.972 8101.893 0.006 B- 96.512 0.972 170 936435.126 1.043 - 31 101 70 171 Yb -59306.810 0.013 8097.882 0.000 B- -1478.414 1.862 170 936331.517 0.014 - 29 100 71 171 Lu -57828.395 1.862 8084.661 0.011 B- -2397.050 28.936 170 937918.660 1.998 - 27 99 72 171 Hf x -55431.345 28.876 8066.068 0.169 B- -3711.072 40.184 170 940492.000 31.000 - 25 98 73 171 Ta x -51720.273 27.945 8039.791 0.163 B- -4634.183 39.520 170 944476.000 30.000 - 23 97 74 171 W x -47086.090 27.945 8008.115 0.163 B- -5835.810 39.520 170 949451.000 30.000 - 21 96 75 171 Re x -41250.280 27.945 7969.412 0.163 B- -6948.339 33.145 170 955716.000 30.000 - 19 95 76 171 Os -34301.942 17.823 7924.204 0.104 B- -7889.916 42.395 170 963175.348 19.133 - 17 94 77 171 Ir -a -26412.025 38.466 7873.489 0.225 B- -8942.323 82.291 170 971645.522 41.295 - 15 93 78 171 Pt -a -17469.702 72.747 7816.619 0.425 B- -9907.407 75.639 170 981245.502 78.097 - 13 92 79 171 Au -p -7562.295 20.713 7754.106 0.121 B- -11043# 303# 170 991881.542 22.236 - 11 91 80 171 Hg -a 3480# 303# 7685# 2# B- * 171 003736# 325# -0 42 107 65 172 Tb x -39850# 503# 8007# 3# B- 8159# 585# 171 957219# 540# - 40 106 66 172 Dy x -48009# 298# 8050# 2# B- 3474# 357# 171 948460# 320# - 38 105 67 172 Ho x -51484# 196# 8066# 1# B- 5000# 196# 171 944730# 210# - 36 104 68 172 Er -56483.612 4.008 8090.410 0.023 B- 890.767 4.543 171 939362.344 4.302 - 34 103 69 172 Tm -57374.379 5.503 8091.041 0.032 B- 1881.067 5.503 171 938406.067 5.907 - 32 102 70 172 Yb -59255.446 0.014 8097.429 0.000 B- -2519.466 2.336 171 936386.658 0.014 - 30 101 71 172 Lu -56735.980 2.336 8078.232 0.014 B- -333.754 24.540 171 939091.417 2.507 - 28 100 72 172 Hf x -56402.226 24.428 8071.743 0.142 B- -5072.248 37.117 171 939449.716 26.224 - 26 99 73 172 Ta x -51329.977 27.945 8037.705 0.162 B- -2232.791 39.520 171 944895.000 30.000 - 24 98 74 172 W x -49097.186 27.945 8020.175 0.162 B- -7560.080 47.974 171 947292.000 30.000 - 22 97 75 172 Re -41537.106 38.995 7971.672 0.227 B- -4293.264 41.036 171 955408.079 41.862 - 20 96 76 172 Os -37243.842 12.782 7942.163 0.074 B- -9864.473 34.832 171 960017.088 13.721 - 18 95 77 172 Ir -a -27379.369 32.402 7880.263 0.188 B- -6272.449 34.023 171 970607.036 34.785 - 16 94 78 172 Pt -21106.920 10.377 7839.247 0.060 B- -11788.914 57.108 171 977340.788 11.139 - 14 93 79 172 Au -a -9318.006 56.158 7766.158 0.326 B- -8259.262 140.853 171 989996.708 60.287 - 12 92 80 172 Hg -a -1058.744 150.079 7713.591 0.873 B- * 171 998863.391 161.116 -0 41 107 66 173 Dy x -43939# 401# 8027# 2# B- 5412# 499# 172 952830# 430# - 39 106 67 173 Ho x -49351# 298# 8054# 2# B- 4304# 357# 172 947020# 320# - 37 105 68 173 Er x -53654# 196# 8074# 1# B- 2602# 196# 172 942400# 210# - 35 104 69 173 Tm p2n -56256.059 4.400 8084.463 0.025 B- 1295.166 4.400 172 939606.632 4.723 - 33 103 70 173 Yb -57551.225 0.011 8087.427 0.000 B- -670.310 1.567 172 938216.215 0.012 - 31 102 71 173 Lu -56880.916 1.567 8079.030 0.009 B- -1469.132 27.989 172 938935.822 1.682 - 29 101 72 173 Hf x -55411.784 27.945 8066.016 0.162 B- -3015.246 39.520 172 940513.000 30.000 - 27 100 73 173 Ta x -52396.538 27.945 8044.064 0.162 B- -3669.155 39.520 172 943750.000 30.000 - 25 99 74 173 W x -48727.383 27.945 8018.333 0.162 B- -5173.518 39.520 172 947689.000 30.000 - 23 98 75 173 Re x -43553.865 27.945 7983.906 0.162 B- -6115.608 31.697 172 953243.000 30.000 - 21 97 76 173 Os -37438.257 14.959 7944.033 0.086 B- -7169.822 18.583 172 959808.375 16.059 - 19 96 77 173 Ir -30268.435 11.026 7898.067 0.064 B- -8325.524 57.052 172 967505.496 11.837 - 17 95 78 173 Pt -a -21942.911 55.977 7845.420 0.324 B- -9110.471 60.421 172 976443.315 60.093 - 15 94 79 173 Au +a -12832.440 22.784 7788.237 0.132 B- -10123# 197# 172 986223.808 24.459 - 13 93 80 173 Hg -a -2710# 196# 7725# 1# B- * 172 997091# 210# -0 42 108 66 174 Dy x -41370# 503# 8012# 3# B- 4319# 585# 173 955587# 540# - 40 107 67 174 Ho x -45690# 298# 8033# 2# B- 6260# 422# 173 950950# 320# - 38 106 68 174 Er x -51949# 298# 8064# 2# B- 1915# 301# 173 944230# 320# - 36 105 69 174 Tm + -53864.512 44.721 8070.642 0.257 B- 3080.000 44.721 173 942174.064 48.010 - 34 104 70 174 Yb -56944.512 0.011 8083.847 0.000 B- -1374.317 1.567 173 938867.548 0.011 - 32 103 71 174 Lu -55570.195 1.567 8071.453 0.009 B- 274.286 2.169 173 940342.938 1.682 - 30 102 72 174 Hf -55844.481 2.259 8068.533 0.013 B- -4103.715 28.036 173 940048.480 2.424 - 28 101 73 174 Ta x -51740.766 27.945 8040.452 0.161 B- -1513.678 39.520 173 944454.000 30.000 - 26 100 74 174 W x -50227.088 27.945 8027.256 0.161 B- -6553.992 39.520 173 946079.000 30.000 - 24 99 75 174 Re x -43673.096 27.945 7985.094 0.161 B- -3677.681 29.767 173 953115.000 30.000 - 22 98 76 174 Os -39995.416 10.254 7959.461 0.059 B- -9131.924 26.395 173 957063.152 11.008 - 20 97 77 174 Ir -30863.492 24.322 7902.483 0.140 B- -5545.329 26.433 173 966866.676 26.111 - 18 96 78 174 Pt -a -25318.163 10.351 7866.117 0.059 B- -11083# 89# 173 972819.832 11.112 - 16 95 79 174 Au -a -14235# 89# 7798# 1# B- -7594# 89# 173 984718# 95# - 14 94 80 174 Hg -a -6641.009 19.211 7749.784 0.110 B- * 173 992870.583 20.624 -0 41 108 67 175 Ho x -43203# 401# 8019# 2# B- 5449# 566# 174 953620# 430# - 39 107 68 175 Er x -48652# 401# 8045# 2# B- 3659# 404# 174 947770# 430# - 37 106 69 175 Tm + -52310.549 50.000 8061.766 0.286 B- 2385.000 50.000 174 943842.313 53.677 - 35 105 70 175 Yb -54695.549 0.071 8070.925 0.000 B- 470.033 1.206 174 941281.910 0.076 - 33 104 71 175 Lu -55165.582 1.207 8069.140 0.007 B- -683.920 1.952 174 940777.308 1.295 - 31 103 72 175 Hf -54481.662 2.282 8060.761 0.013 B- -2073.015 28.038 174 941511.527 2.449 - 29 102 73 175 Ta x -52408.647 27.945 8044.445 0.160 B- -2775.852 39.520 174 943737.000 30.000 - 27 101 74 175 W x -49632.795 27.945 8024.112 0.160 B- -4344.488 39.520 174 946717.000 30.000 - 25 100 75 175 Re x -45288.307 27.945 7994.816 0.160 B- -5182.931 30.324 174 951381.000 30.000 - 23 99 76 175 Os -40105.376 11.775 7960.729 0.067 B- -6710.870 17.089 174 956945.105 12.640 - 21 98 77 175 Ir -33394.506 12.384 7917.910 0.071 B- -7681.040 22.001 174 964149.521 13.295 - 19 97 78 175 Pt -25713.466 18.185 7869.548 0.104 B- -8309.511 42.705 174 972395.457 19.522 - 17 96 79 175 Au -a -17403.955 38.640 7817.595 0.221 B- -9431.379 82.504 174 981316.085 41.481 - 15 95 80 175 Hg -a -7972.576 72.896 7759.231 0.417 B- * 174 991441.086 78.257 -0 42 109 67 176 Ho x -39290# 503# 7997# 3# B- 7340# 643# 175 957820# 540# - 40 108 68 176 Er x -46631# 401# 8034# 2# B- 2741# 413# 175 949940# 430# - 38 107 69 176 Tm + -49371.314 100.000 8045.121 0.568 B- 4120.000 100.000 175 946997.711 107.354 - 36 106 70 176 Yb -53491.314 0.015 8064.085 0.000 B- -109.078 1.212 175 942574.708 0.015 - 34 105 71 176 Lu -53382.236 1.212 8059.020 0.007 B- 1194.085 0.874 175 942691.809 1.301 - 32 104 72 176 Hf -54576.321 1.481 8061.359 0.008 B- -3210.948 30.775 175 941409.905 1.590 - 30 103 73 176 Ta x -51365.374 30.739 8038.670 0.175 B- -723.771 41.543 175 944857.000 33.000 - 28 102 74 176 W x -50641.603 27.945 8030.112 0.159 B- -5578.718 39.520 175 945634.000 30.000 - 26 101 75 176 Re x -45062.885 27.945 7993.970 0.159 B- -2964.945 39.520 175 951623.000 30.000 - 24 100 76 176 Os x -42097.940 27.945 7972.679 0.159 B- -8219.614 32.580 175 954806.000 30.000 - 22 99 77 176 Ir -33878.326 16.750 7921.531 0.095 B- -4944.459 21.035 175 963630.119 17.981 - 20 98 78 176 Pt -28933.867 12.724 7888.992 0.072 B- -10412.904 35.541 175 968938.214 13.660 - 18 97 79 176 Au -a -18520.963 33.185 7825.383 0.189 B- -6736.013 34.998 175 980116.927 35.625 - 16 96 80 176 Hg -11784.950 11.119 7782.665 0.063 B- -12366.544 75.904 175 987348.335 11.937 - 14 95 81 176 Tl -p 581.594 75.086 7707.955 0.427 B- * 176 000624.367 80.607 -0 41 109 68 177 Er x -42858# 503# 8013# 3# B- 4611# 585# 176 953990# 540# - 39 108 69 177 Tm x -47469# 298# 8035# 2# B- 3517# 298# 176 949040# 320# - 37 107 70 177 Yb -n -50986.397 0.220 8049.973 0.001 B- 1397.409 1.240 176 945263.848 0.236 - 35 106 71 177 Lu -52383.806 1.220 8053.448 0.007 B- 496.810 0.791 176 943763.668 1.310 - 33 105 72 177 Hf -52880.616 1.408 8051.835 0.008 B- -1166.000 3.000 176 943230.320 1.511 - 31 104 73 177 Ta - -51714.616 3.314 8040.827 0.019 B- -2012.890 28.141 176 944482.073 3.557 - 29 103 74 177 W x -49701.726 27.945 8025.035 0.158 B- -3432.555 39.520 176 946643.000 30.000 - 27 102 75 177 Re x -46269.170 27.945 8001.222 0.158 B- -4312.708 31.535 176 950328.000 30.000 - 25 101 76 177 Os +a -41956.462 14.613 7972.436 0.083 B- -5909.041 24.576 176 954957.882 15.687 - 23 100 77 177 Ir x -36047.421 19.760 7934.632 0.112 B- -6676.976 24.801 176 961301.500 21.213 - 21 99 78 177 Pt -29370.444 14.988 7892.489 0.085 B- -7825.341 18.297 176 968469.529 16.090 - 19 98 79 177 Au -21545.103 10.496 7843.858 0.059 B- -8762.561 75.786 176 976870.379 11.268 - 17 97 80 177 Hg -a -12782.542 75.056 7789.932 0.424 B- -9442.016 78.098 176 986277.376 80.575 - 15 96 81 177 Tl IT -3340.526 21.629 7732.167 0.122 B- * 176 996413.797 23.219 -0 42 110 68 178 Er x -40260# 596# 7999# 3# B- 3855# 718# 177 956779# 640# - 40 109 69 178 Tm x -44116# 401# 8016# 2# B- 5580# 401# 177 952640# 430# - 38 108 70 178 Yb -nn -49695.475 10.000 8042.841 0.056 B- 642.309 10.250 177 946649.710 10.735 - 36 107 71 178 Lu -50337.784 2.251 8042.054 0.013 B- 2097.451 2.057 177 945960.162 2.416 - 34 106 72 178 Hf -52435.236 1.412 8049.442 0.008 B- -1837# 52# 177 943708.456 1.516 - 32 105 73 178 Ta IT -50598# 52# 8035# 0# B- -191# 50# 177 945681# 56# - 30 104 74 178 W - -50406.936 15.199 8029.257 0.085 B- -4753.483 31.810 177 945885.925 16.316 - 28 103 75 178 Re x -45653.453 27.945 7998.157 0.157 B- -2109.183 31.093 177 950989.000 30.000 - 26 102 76 178 Os -43544.270 13.632 7981.912 0.077 B- -7292.386 24.006 177 953253.300 14.634 - 24 101 77 178 Ir x -36251.884 19.760 7936.549 0.111 B- -4254.365 22.207 177 961082.000 21.213 - 22 100 78 178 Pt -31997.519 10.133 7908.252 0.057 B- -9693.776 14.297 177 965649.248 10.878 - 20 99 79 178 Au -22303.743 10.086 7849.398 0.057 B- -5987.841 14.755 177 976055.945 10.827 - 18 98 80 178 Hg -a -16315.901 10.770 7811.363 0.061 B- -11526# 90# 177 982484.158 11.562 - 16 97 81 178 Tl -a -4790# 89# 7742# 1# B- -8365# 91# 177 994857# 96# - 14 96 82 178 Pb -a 3574.294 23.963 7690.830 0.135 B- * 178 003837.163 25.724 -0 41 110 69 179 Tm x -41601# 503# 8002# 3# B- 4937# 540# 178 955340# 540# - 39 109 70 179 Yb x -46537# 196# 8025# 1# B- 2521# 196# 178 950040# 210# - 37 108 71 179 Lu -49058.918 5.150 8035.073 0.029 B- 1403.989 5.067 178 947333.082 5.528 - 35 107 72 179 Hf -50462.907 1.413 8038.546 0.008 B- -105.584 0.409 178 945825.838 1.517 - 33 106 73 179 Ta -50357.323 1.463 8033.585 0.008 B- -1062.195 14.520 178 945939.187 1.571 - 31 105 74 179 W -49295.127 14.573 8023.281 0.081 B- -2710.847 26.802 178 947079.501 15.644 - 29 104 75 179 Re -46584.280 24.639 8003.766 0.138 B- -3564.785 29.656 178 949989.715 26.450 - 27 103 76 179 Os -43019.495 16.504 7979.480 0.092 B- -4937.781 19.180 178 953816.669 17.718 - 25 102 77 179 Ir -38081.714 9.771 7947.524 0.055 B- -5813.569 12.613 178 959117.596 10.489 - 23 101 78 179 Pt -32268.145 7.977 7910.675 0.045 B- -7279.578 14.157 178 965358.719 8.563 - 21 100 79 179 Au -24988.567 11.696 7865.637 0.065 B- -8060.433 29.669 178 973173.668 12.555 - 19 99 80 179 Hg -16928.134 27.267 7816.236 0.152 B- -8659.639 47.417 178 981826.899 29.272 - 17 98 81 179 Tl -a -8268.495 38.793 7763.487 0.217 B- -10319.134 84.963 178 991123.405 41.646 - 15 97 82 179 Pb -a 2050.639 75.590 7701.468 0.422 B- * 179 002201.452 81.149 -0 42 111 69 180 Tm x -37920# 503# 7982# 3# B- 6680# 585# 179 959291# 540# - 40 110 70 180 Yb x -44600# 298# 8015# 2# B- 2076# 306# 179 952120# 320# - 38 109 71 180 Lu + -46676.348 70.725 8022.038 0.393 B- 3103.000 70.711 179 949890.876 75.926 - 36 108 72 180 Hf -49779.348 1.419 8034.930 0.008 B- -846.471 2.269 179 946559.669 1.522 - 34 107 73 180 Ta +n -48932.877 1.939 8025.881 0.011 B- 703.238 2.281 179 947468.392 2.081 - 32 106 74 180 W -49636.115 1.436 8025.442 0.008 B- -3798.757 21.440 179 946713.435 1.542 - 30 105 75 180 Re x -45837.359 21.392 7999.991 0.119 B- -1479.549 26.950 179 950791.568 22.965 - 28 104 76 180 Os -44357.810 16.391 7987.425 0.091 B- -6380.284 27.200 179 952379.930 17.596 - 26 103 77 180 Ir x -37977.526 21.706 7947.633 0.121 B- -3541.649 24.323 179 959229.446 23.302 - 24 102 78 180 Pt +a -34435.877 10.974 7923.611 0.061 B- -8810.368 11.973 179 963031.563 11.781 - 22 101 79 180 Au -25625.509 4.786 7870.318 0.027 B- -5375.062 13.524 179 972489.883 5.137 - 20 100 80 180 Hg -20250.447 12.649 7836.110 0.070 B- -10863.800 61.329 179 978260.249 13.579 - 18 99 81 180 Tl -a -9386.647 60.010 7771.409 0.333 B- -7445.267 61.277 179 989923.019 64.423 - 16 98 82 180 Pb -a -1941.380 12.396 7725.700 0.069 B- * 179 997915.842 13.307 -0 43 112 69 181 Tm x -35170# 596# 7967# 3# B- 5918# 667# 180 962243# 640# - 41 111 70 181 Yb x -41088# 298# 7996# 2# B- 3709# 324# 180 955890# 320# - 39 110 71 181 Lu x -44797.410 125.752 8011.929 0.695 B- 2605.421 125.760 180 951908.000 135.000 - 37 109 72 181 Hf -n -47402.831 1.420 8022.002 0.008 B- 1035.480 1.834 180 949110.965 1.524 - 35 108 73 181 Ta -48438.311 1.403 8023.400 0.008 B- -204.493 1.854 180 947999.331 1.506 - 33 107 74 181 W -n -48233.818 1.445 8017.948 0.008 B- -1716.427 12.629 180 948218.863 1.551 - 31 106 75 181 Re 4n -46517.391 12.549 8004.143 0.069 B- -2967.428 28.275 180 950061.523 13.471 - 29 105 76 181 Os -43549.963 25.338 7983.426 0.140 B- -4086.935 25.876 180 953247.188 27.201 - 27 104 77 181 Ir +a -39463.028 5.245 7956.523 0.029 B- -5081.517 14.660 180 957634.694 5.631 - 25 103 78 181 Pt -34381.511 13.689 7924.126 0.076 B- -6510.375 24.216 180 963089.927 14.695 - 23 102 79 181 Au -a -27871.136 19.976 7883.835 0.110 B- -7210.000 25.212 180 970079.103 21.445 - 21 101 80 181 Hg -20661.136 15.382 7839.679 0.085 B- -7862.401 17.876 180 977819.357 16.513 - 19 100 81 181 Tl -12798.735 9.108 7791.918 0.050 B- -9681.385 75.959 180 986259.992 9.778 - 17 99 82 181 Pb -a -3117.350 75.411 7734.107 0.417 B- * 180 996653.386 80.957 -0 42 112 70 182 Yb x -38820# 401# 7984# 2# B- 3060# 446# 181 958325# 430# - 40 111 71 182 Lu x -41880# 196# 7996# 1# B- 4170# 196# 181 955040# 210# - 38 110 72 182 Hf -nn -46049.508 6.165 8014.837 0.034 B- 380.425 6.274 181 950563.816 6.618 - 36 109 73 182 Ta -46429.934 1.405 8012.628 0.008 B- 1816.126 1.399 181 950155.413 1.508 - 34 108 74 182 W -48246.060 0.738 8018.308 0.004 B- -2800.000 101.980 181 948205.721 0.791 - 32 107 75 182 Re IT -45446.060 101.983 7998.625 0.560 B- -836.955 104.276 181 951211.645 109.483 - 30 106 76 182 Os -44609.104 21.745 7989.728 0.119 B- -5557.426 30.207 181 952110.153 23.344 - 28 105 77 182 Ir -39051.679 20.967 7954.894 0.115 B- -2883.230 24.720 181 958076.296 22.509 - 26 104 78 182 Pt -36168.449 13.095 7934.754 0.072 B- -7867.680 24.123 181 961171.571 14.057 - 24 103 79 182 Au -a -28300.768 20.260 7887.226 0.111 B- -4723.846 22.501 181 969617.874 21.749 - 22 102 80 182 Hg -23576.922 9.790 7856.972 0.054 B- -10248.994 15.363 181 974689.132 10.510 - 20 101 81 182 Tl -a -13327.927 11.839 7796.360 0.065 B- -6502.815 16.927 181 985691.880 12.709 - 18 100 82 182 Pb -a -6825.112 12.098 7756.332 0.066 B- * 181 992672.940 12.987 -0 43 113 70 183 Yb x -35100# 401# 7964# 2# B- 4616# 408# 182 962319# 430# - 41 112 71 183 Lu x -39716.110 80.108 7984.812 0.438 B- 3566.687 85.553 182 957363.000 86.000 - 39 111 72 183 Hf + -43282.796 30.034 8000.027 0.164 B- 2010.000 30.000 182 953534.004 32.242 - 37 110 73 183 Ta -n -45292.796 1.419 8006.735 0.008 B- 1072.783 1.413 182 951376.180 1.523 - 35 109 74 183 W -46365.580 0.737 8008.322 0.004 B- -556.000 8.000 182 950224.500 0.790 - 33 108 75 183 Re - -45809.580 8.034 8001.009 0.044 B- -2145.537 50.405 182 950821.390 8.624 - 31 107 76 183 Os -43664.043 49.760 7985.010 0.272 B- -3460.732 52.733 182 953124.719 53.420 - 29 106 77 183 Ir -40203.311 24.398 7961.823 0.133 B- -4430.824 28.923 182 956839.968 26.191 - 27 105 78 183 Pt -35772.487 15.533 7933.336 0.085 B- -5581.004 18.168 182 961596.653 16.675 - 25 104 79 183 Au -30191.483 9.423 7898.564 0.051 B- -6386.809 11.789 182 967588.108 10.116 - 23 103 80 183 Hg -23804.674 7.084 7859.388 0.039 B- -7217.417 11.716 182 974444.629 7.604 - 21 102 81 183 Tl -16587.257 9.331 7815.673 0.051 B- -9012.038 29.657 182 982192.846 10.017 - 19 101 82 183 Pb -a -7575.218 28.151 7762.152 0.154 B- * 182 991867.668 30.221 -0 44 114 70 184 Yb x -32540# 503# 7951# 3# B- 3872# 585# 183 965067# 540# - 42 113 71 184 Lu x -36412# 298# 7967# 2# B- 5087# 301# 183 960910# 320# - 40 112 72 184 Hf + -41499.373 39.706 7990.722 0.216 B- 1340.000 30.000 183 955448.587 42.625 - 38 111 73 184 Ta + -42839.373 26.010 7993.752 0.141 B- 2866.000 26.000 183 954010.038 27.923 - 36 110 74 184 W -45705.373 0.731 8005.077 0.004 B- -1485.739 4.198 183 950933.260 0.785 - 34 109 75 184 Re -44219.634 4.275 7992.750 0.023 B- 32.898 4.140 183 952528.267 4.589 - 32 108 76 184 Os -44252.533 0.827 7988.677 0.005 B- -4641.682 27.957 183 952492.949 0.887 - 30 107 77 184 Ir x -39610.851 27.945 7959.198 0.152 B- -2276.608 31.997 183 957476.000 30.000 - 28 106 78 184 Pt -37334.243 15.584 7942.574 0.085 B- -7015.533 27.185 183 959920.039 16.730 - 26 105 79 184 Au -a -30318.710 22.275 7900.194 0.121 B- -3969.745 24.442 183 967451.524 23.912 - 24 104 80 184 Hg -26348.965 10.062 7874.367 0.055 B- -9465.723 14.200 183 971713.221 10.802 - 22 103 81 184 Tl -16883.242 10.020 7818.671 0.054 B- -5831.720 16.260 183 981875.093 10.757 - 20 102 82 184 Pb -11051.522 12.806 7782.725 0.070 B- -12114.590 79.153 183 988135.702 13.748 - 18 101 83 184 Bi -a 1063.068 78.110 7712.633 0.425 B- * 184 001141.250 83.854 -0 45 115 70 185 Yb x -28500# 503# 7929# 3# B- 5388# 585# 184 969404# 540# - 43 114 71 185 Lu x -33888# 298# 7954# 2# B- 4432# 305# 184 963620# 320# - 41 113 72 185 Hf x -38319.800 64.273 7973.970 0.347 B- 3074.492 65.815 184 958862.000 69.000 - 39 112 73 185 Ta + -41394.293 14.161 7986.360 0.077 B- 1993.500 14.142 184 955561.396 15.202 - 37 111 74 185 W -43387.793 0.733 7992.907 0.004 B- 431.234 0.661 184 953421.286 0.786 - 35 110 75 185 Re -43819.027 0.818 7991.009 0.004 B- -1013.147 0.419 184 952958.337 0.877 - 33 109 76 185 Os -42805.880 0.830 7981.304 0.004 B- -2470.326 27.957 184 954045.995 0.891 - 31 108 77 185 Ir x -40335.553 27.945 7963.722 0.151 B- -3647.414 38.055 184 956698.000 30.000 - 29 107 78 185 Pt -36688.140 25.832 7939.777 0.140 B- -4829.997 25.963 184 960613.659 27.731 - 27 106 79 185 Au x -31858.143 2.608 7909.440 0.014 B- -5674.477 13.886 184 965798.874 2.800 - 25 105 80 185 Hg -26183.666 13.639 7874.538 0.074 B- -6425.925 24.767 184 971890.676 14.641 - 23 104 81 185 Tl IT -19757.741 20.674 7835.575 0.112 B- -8216.521 26.249 184 978789.191 22.194 - 21 103 82 185 Pb -a -11541.220 16.175 7786.932 0.087 B- -9305# 83# 184 987609.989 17.364 - 19 102 83 185 Bi IT -2236# 81# 7732# 0# B- * 184 997600# 87# -0 44 115 71 186 Lu x -30210# 401# 7935# 2# B- 6214# 404# 185 967568# 430# - 42 114 72 186 Hf x -36424.210 51.232 7964.302 0.275 B- 2183.318 78.906 185 960897.000 55.000 - 40 113 73 186 Ta + -38607.528 60.012 7971.835 0.323 B- 3901.000 60.000 185 958553.111 64.425 - 38 112 74 186 W -42508.528 1.212 7988.601 0.007 B- -581.442 1.244 185 954365.215 1.300 - 36 111 75 186 Re -41927.086 0.826 7981.269 0.004 B- 1072.857 0.837 185 954989.419 0.886 - 34 110 76 186 Os -42999.943 0.761 7982.831 0.004 B- -3827.596 16.543 185 953837.660 0.816 - 32 109 77 186 Ir x -39172.346 16.526 7958.047 0.089 B- -1307.903 27.312 185 957946.754 17.740 - 30 108 78 186 Pt -37864.443 21.745 7946.809 0.117 B- -6149.591 30.207 185 959350.846 23.344 - 28 107 79 186 Au -31714.852 20.967 7909.540 0.113 B- -3175.756 23.987 185 965952.703 22.509 - 26 106 80 186 Hg -28539.097 11.650 7888.260 0.063 B- -8652.484 25.209 185 969362.017 12.507 - 24 105 81 186 Tl x -19886.613 22.356 7837.535 0.120 B- -5204.588 25.078 185 978650.841 24.000 - 22 104 82 186 Pb -a -14682.026 11.363 7805.347 0.061 B- -11535.814 20.329 185 984238.196 12.199 - 20 103 83 186 Bi -a -3146.212 16.857 7739.121 0.091 B- -7247.186 24.870 185 996622.402 18.096 - 18 102 84 186 Po -a 4100.974 18.286 7695.951 0.098 B- * 186 004402.577 19.630 -0 45 116 71 187 Lu x -27580# 401# 7922# 2# B- 5237# 499# 186 970392# 430# - 43 115 72 187 Hf x -32817# 298# 7946# 2# B- 4079# 303# 186 964770# 320# - 41 114 73 187 Ta x -36895.546 55.890 7963.212 0.299 B- 3008.424 55.903 186 960391.000 60.000 - 39 113 74 187 W -39903.970 1.212 7975.116 0.006 B- 1312.508 1.122 186 957161.323 1.300 - 37 112 75 187 Re -41216.478 0.736 7977.951 0.004 B- 2.467 0.002 186 955752.288 0.790 - 35 111 76 187 Os -41218.945 0.736 7973.780 0.004 B- -1669.572 27.955 186 955749.640 0.790 - 33 110 77 187 Ir x -39549.372 27.945 7960.668 0.149 B- -2864.323 36.868 186 957542.000 30.000 - 31 109 78 187 Pt -36685.050 24.048 7941.168 0.129 B- -3657.212 27.377 186 960616.976 25.816 - 29 108 79 187 Au -33027.838 22.308 7917.427 0.119 B- -4909.908 26.287 186 964543.155 23.948 - 27 107 80 187 Hg -28117.930 13.905 7886.987 0.074 B- -5673.343 16.067 186 969814.158 14.928 - 25 106 81 187 Tl -22444.587 8.048 7852.464 0.043 B- -7457.628 9.525 186 975904.743 8.640 - 23 105 82 187 Pb -14986.959 5.094 7808.400 0.027 B- -8603.688 11.227 186 983910.836 5.468 - 21 104 83 187 Bi -a -6383.271 10.005 7758.208 0.054 B- -9211.868 33.430 186 993147.276 10.740 - 19 103 84 187 Po -a 2828.597 31.898 7704.763 0.171 B- * 187 003036.624 34.243 -0 46 117 71 188 Lu x -23790# 503# 7902# 3# B- 7089# 585# 187 974460# 540# - 44 116 72 188 Hf x -30879# 298# 7936# 2# B- 2733# 303# 187 966850# 320# - 42 115 73 188 Ta x -33612.030 54.958 7946.321 0.292 B- 5055.781 55.045 187 963916.000 59.000 - 40 114 74 188 W + -38667.811 3.089 7969.052 0.016 B- 349.000 3.000 187 958488.395 3.316 - 38 113 75 188 Re -n -39016.811 0.738 7966.747 0.004 B- 2120.422 0.152 187 958113.728 0.791 - 36 112 76 188 Os -41137.233 0.734 7973.864 0.004 B- -2792.326 9.416 187 955837.361 0.787 - 34 111 77 188 Ir -38344.907 9.423 7954.850 0.050 B- -523.979 8.686 187 958835.046 10.116 - 32 110 78 188 Pt -37820.929 5.304 7947.902 0.028 B- -5449.621 5.953 187 959397.560 5.694 - 30 109 79 188 Au x -32371.308 2.701 7914.753 0.014 B- -2169.394 12.569 187 965247.969 2.900 - 28 108 80 188 Hg -30201.914 12.275 7899.052 0.065 B- -7865.513 32.325 187 967576.910 13.178 - 26 107 81 188 Tl x -22336.400 29.904 7853.053 0.159 B- -4521.198 31.734 187 976020.886 32.103 - 24 106 82 188 Pb -a -17815.202 10.622 7824.843 0.057 B- -10620.515 15.427 187 980874.592 11.403 - 22 105 83 188 Bi -a -7194.687 11.187 7764.189 0.060 B- -6650.374 22.892 187 992276.184 12.009 - 20 104 84 188 Po -a -544.313 19.973 7724.653 0.106 B- * 187 999415.655 21.441 -0 45 117 72 189 Hf x -27162# 298# 7917# 2# B- 4667# 357# 188 970840# 320# - 43 116 73 189 Ta x -31829# 196# 7938# 1# B- 3788# 200# 188 965830# 210# - 41 115 74 189 W x -35617.536 40.054 7953.454 0.212 B- 2361.507 40.883 188 961763.000 43.000 - 39 114 75 189 Re +p -37979.043 8.191 7961.809 0.043 B- 1007.702 8.167 188 959227.817 8.793 - 37 113 76 189 Os -38986.745 0.666 7963.002 0.004 B- -537.159 12.563 188 958146.005 0.715 - 35 112 77 189 Ir -38449.586 12.576 7956.020 0.067 B- -1980.238 13.636 188 958722.669 13.500 - 33 111 78 189 Pt -36469.348 10.090 7941.403 0.053 B- -2887.394 22.474 188 960848.542 10.832 - 31 110 79 189 Au x -33581.955 20.081 7921.987 0.106 B- -3955.554 37.401 188 963948.286 21.558 - 29 109 80 189 Hg -29626.401 31.553 7896.919 0.167 B- -5010.300 32.643 188 968194.748 33.873 - 27 108 81 189 Tl -24616.100 8.368 7866.270 0.044 B- -6772.066 16.364 188 973573.527 8.983 - 25 107 82 189 Pb -17844.035 14.062 7826.299 0.074 B- -7779.374 25.150 188 980843.639 15.096 - 23 106 83 189 Bi -a -10064.660 20.851 7780.999 0.110 B- -8642.656 30.354 188 989195.141 22.384 - 21 105 84 189 Po -a -1422.005 22.059 7731.131 0.117 B- * 188 998473.415 23.681 -0 46 118 72 190 Hf x -25030# 401# 7907# 2# B- 3483# 446# 189 973129# 430# - 44 117 73 190 Ta x -28513# 196# 7921# 1# B- 5869# 200# 189 969390# 210# - 42 116 74 190 W -34382.313 39.726 7947.573 0.209 B- 1253.517 63.522 189 963089.066 42.647 - 40 115 75 190 Re -35635.830 70.852 7950.053 0.373 B- 3071.941 70.854 189 961743.360 76.063 - 38 114 76 190 Os -38707.771 0.650 7962.104 0.003 B- -1954.227 1.213 189 958445.496 0.697 - 36 113 77 190 Ir +n -36753.544 1.370 7947.701 0.007 B- 552.906 1.282 189 960543.445 1.470 - 34 112 78 190 Pt -37306.450 0.657 7946.493 0.003 B- -4472.917 3.509 189 959949.876 0.704 - 32 111 79 190 Au x -32833.533 3.447 7918.834 0.018 B- -1462.836 16.276 189 964751.750 3.700 - 30 110 80 190 Hg -31370.697 15.907 7907.017 0.084 B- -6998.670 17.782 189 966322.169 17.076 - 28 109 81 190 Tl +a -24372.027 7.948 7866.064 0.042 B- -3955.382 14.825 189 973835.551 8.532 - 26 108 82 190 Pb -a -20416.645 12.514 7841.129 0.066 B- -9817.066 25.800 189 978081.828 13.434 - 24 107 83 190 Bi -a -10599.579 22.562 7785.342 0.119 B- -6035.742 26.275 189 988620.883 24.221 - 22 106 84 190 Po -a -4563.837 13.465 7749.458 0.071 B- * 189 995100.519 14.455 -0 45 118 73 191 Ta x -26492# 298# 7911# 2# B- 4684# 301# 190 971560# 320# - 43 117 74 191 W x -31176.173 41.917 7931.435 0.219 B- 3174.124 43.156 190 966531.000 45.000 - 41 116 75 191 Re +p -34350.296 10.265 7943.957 0.054 B- 2044.889 10.244 190 963123.437 11.019 - 39 115 76 191 Os -36395.185 0.659 7950.568 0.003 B- 313.570 1.141 190 960928.159 0.707 - 37 114 77 191 Ir -36708.756 1.311 7948.113 0.007 B- -1010.518 3.636 190 960591.527 1.406 - 35 113 78 191 Pt -35698.237 4.127 7938.727 0.022 B- -1900.333 6.426 190 961676.363 4.430 - 33 112 79 191 Au -33797.904 4.926 7924.681 0.026 B- -3206.008 22.710 190 963716.455 5.288 - 31 111 80 191 Hg -30591.896 22.280 7903.800 0.117 B- -4308.951 23.461 190 967158.247 23.918 - 29 110 81 191 Tl +a -26282.945 7.349 7877.144 0.038 B- -6051.827 37.978 190 971784.096 7.889 - 27 109 82 191 Pb x -20231.118 37.260 7841.363 0.195 B- -6991.772 38.005 190 978281.000 40.000 - 25 108 83 191 Bi -13239.347 7.487 7800.661 0.039 B- -8170.612 10.320 190 985786.975 8.037 - 23 107 84 191 Po -5068.735 7.103 7753.786 0.037 B- -8932.653 17.600 190 994558.488 7.624 - 21 106 85 191 At -a 3863.917 16.103 7702.923 0.084 B- * 191 004148.086 17.287 -0 46 119 73 192 Ta x -23064# 401# 7894# 2# B- 6586# 446# 191 975240# 430# - 44 118 74 192 W x -29649# 196# 7924# 1# B- 1939# 208# 191 968170# 210# - 42 117 75 192 Re x -31588.825 70.794 7930.238 0.369 B- 4293.366 70.831 191 966088.000 76.000 - 40 116 76 192 Os -35882.191 2.315 7948.525 0.012 B- -1046.630 2.397 191 961478.881 2.485 - 38 115 77 192 Ir -34835.561 1.314 7938.999 0.007 B- 1452.896 2.274 191 962602.485 1.410 - 36 114 78 192 Pt -36288.457 2.570 7942.491 0.013 B- -3516.341 15.617 191 961042.736 2.758 - 34 113 79 192 Au - -32772.116 15.827 7920.102 0.082 B- -760.563 22.178 191 964817.684 16.991 - 32 112 80 192 Hg x -32011.553 15.537 7912.066 0.081 B- -6139.307 35.277 191 965634.182 16.679 - 30 111 81 192 Tl x -25872.246 31.671 7876.016 0.165 B- -3316.226 34.348 191 972225.000 34.000 - 28 110 82 192 Pb -a -22556.020 13.295 7854.669 0.069 B- -9021.485 32.917 191 975785.115 14.273 - 26 109 83 192 Bi -a -13534.535 30.112 7803.608 0.157 B- -5463.873 32.096 191 985470.078 32.326 - 24 108 84 192 Po -a -8070.661 11.110 7771.075 0.058 B- -10996.516 30.008 191 991335.788 11.926 - 22 107 85 192 At -a 2925.854 27.876 7709.727 0.145 B- * 192 003141.034 29.926 -0 47 120 73 193 Ta x -20870# 401# 7884# 2# B- 5417# 446# 192 977595# 430# - 45 119 74 193 W x -26287# 196# 7908# 1# B- 3945# 199# 192 971780# 210# - 43 118 75 193 Re x -30231.638 39.123 7923.937 0.203 B- 3162.652 39.192 192 967545.000 42.000 - 41 117 76 193 Os -33394.289 2.321 7936.270 0.012 B- 1141.946 2.400 192 964149.753 2.491 - 39 116 77 193 Ir -34536.235 1.328 7938.133 0.007 B- -56.628 0.300 192 962923.824 1.425 - 37 115 78 193 Pt -34479.608 1.359 7933.786 0.007 B- -1074.787 8.768 192 962984.616 1.458 - 35 114 79 193 Au -33404.821 8.674 7924.164 0.045 B- -2342.642 14.370 192 964138.447 9.311 - 33 113 80 193 Hg -31062.179 15.505 7907.972 0.080 B- -3584.967 16.894 192 966653.377 16.645 - 31 112 81 193 Tl x -27477.212 6.707 7885.344 0.035 B- -5282.723 50.028 192 970501.997 7.200 - 29 111 82 193 Pb x -22194.490 49.577 7853.919 0.257 B- -6309.931 50.152 192 976173.234 53.222 - 27 110 83 193 Bi -15884.559 7.576 7817.171 0.039 B- -7559.241 16.387 192 982947.223 8.132 - 25 109 84 193 Po -a -8325.318 14.531 7773.950 0.075 B- -8257.998 26.059 192 991062.403 15.599 - 23 108 85 193 At -a -67.320 21.632 7727.109 0.112 B- -9110.231 33.144 192 999927.728 23.222 - 21 107 86 193 Rn -a 9042.911 25.112 7675.852 0.130 B- * 193 009707.964 26.958 -0 48 121 73 194 Ta x -17300# 503# 7866# 3# B- 7227# 585# 193 981428# 540# - 46 120 74 194 W x -24526# 298# 7899# 2# B- 2711# 357# 193 973670# 320# - 44 119 75 194 Re x -27237# 196# 7909# 1# B- 5198# 196# 193 970760# 210# - 42 118 76 194 Os + -32435.108 2.403 7932.022 0.012 B- 96.600 2.000 193 965179.477 2.579 - 40 117 77 194 Ir -n -32531.708 1.332 7928.487 0.007 B- 2228.362 1.257 193 965075.773 1.430 - 38 116 78 194 Pt -34760.070 0.496 7935.941 0.003 B- -2548.134 2.117 193 962683.527 0.532 - 36 115 79 194 Au +3n -32211.936 2.118 7918.774 0.011 B- -27.991 3.581 193 965419.062 2.273 - 34 114 80 194 Hg x -32183.945 2.888 7914.597 0.015 B- -5246.454 14.268 193 965449.111 3.100 - 32 113 81 194 Tl x -26937.491 13.972 7883.520 0.072 B- -2729.552 22.343 193 971081.411 15.000 - 30 112 82 194 Pb -24207.940 17.435 7865.418 0.090 B- -8179.128 18.498 193 974011.706 18.717 - 28 111 83 194 Bi +a -16028.811 6.178 7819.225 0.032 B- -5024.156 14.313 193 982792.362 6.632 - 26 110 84 194 Po -a -11004.655 12.911 7789.294 0.067 B- -10284.492 28.076 193 988186.015 13.860 - 24 109 85 194 At -a -720.163 24.931 7732.249 0.129 B- -6443.658 30.119 193 999226.872 26.764 - 22 108 86 194 Rn -a 5723.495 16.899 7695.001 0.087 B- * 194 006144.424 18.141 -0 47 121 74 195 W x -21010# 298# 7882# 2# B- 4569# 422# 194 977445# 320# - 45 120 75 195 Re x -25579# 298# 7902# 2# B- 3933# 303# 194 972540# 320# - 43 119 76 195 Os x -29511.593 55.890 7917.744 0.287 B- 2180.658 55.906 194 968318.000 60.000 - 41 118 77 195 Ir -n -31692.251 1.333 7924.915 0.007 B- 1101.598 1.264 194 965976.967 1.431 - 39 117 78 195 Pt -32793.849 0.503 7926.552 0.003 B- -226.817 1.000 194 964794.353 0.539 - 37 116 79 195 Au -32567.031 1.119 7921.377 0.006 B- -1553.638 23.156 194 965037.851 1.201 - 35 115 80 195 Hg -31013.393 23.142 7909.397 0.119 B- -2858.145 25.657 194 966705.751 24.843 - 33 114 81 195 Tl -28155.248 11.093 7890.728 0.057 B- -4447.555 21.106 194 969774.096 11.909 - 31 113 82 195 Pb -23707.693 17.960 7863.908 0.092 B- -5682.132 18.722 194 974548.743 19.280 - 29 112 83 195 Bi -18025.561 5.287 7830.757 0.027 B- -6969.303 37.737 194 980648.762 5.675 - 27 111 84 195 Po -a -11056.259 37.364 7791.005 0.192 B- -7585.964 38.571 194 988130.617 40.112 - 25 110 85 195 At -a -3470.295 9.573 7748.091 0.049 B- -8520.575 51.401 194 996274.485 10.276 - 23 109 86 195 Rn -a 5050.281 50.502 7700.383 0.259 B- * 195 005421.699 54.216 -0 48 122 74 196 W x -18880# 401# 7872# 2# B- 3662# 499# 195 979731# 430# - 46 121 75 196 Re x -22542# 298# 7887# 2# B- 5735# 301# 195 975800# 320# - 44 120 76 196 Os +pp -28277.105 40.055 7912.229 0.204 B- 1158.388 55.495 195 969643.277 43.000 - 42 119 77 196 Ir + -29435.493 38.414 7914.148 0.196 B- 3209.016 38.411 195 968399.696 41.239 - 40 118 78 196 Pt -32644.510 0.510 7926.529 0.003 B- -1505.803 2.960 195 964954.675 0.547 - 38 117 79 196 Au -31138.706 2.962 7914.855 0.015 B- 687.235 3.118 195 966571.221 3.179 - 36 116 80 196 Hg -31825.941 2.946 7914.369 0.015 B- -4329.349 12.463 195 965833.444 3.163 - 34 115 81 196 Tl x -27496.592 12.109 7888.289 0.062 B- -2148.280 14.356 195 970481.192 13.000 - 32 114 82 196 Pb -25348.312 7.710 7873.337 0.039 B- -7339.281 25.616 195 972787.466 8.277 - 30 113 83 196 Bi x -18009.031 24.428 7831.900 0.125 B- -4535.989 27.916 195 980666.509 26.224 - 28 112 84 196 Po -a -13473.042 13.512 7804.766 0.069 B- -9558.365 33.162 195 985536.094 14.506 - 26 111 85 196 At -a -3914.677 30.284 7752.007 0.155 B- -5885.668 33.540 195 995797.421 32.511 - 24 110 86 196 Rn -a 1970.991 14.417 7717.987 0.074 B- * 196 002115.945 15.476 -0 49 123 74 197 W x -15140# 401# 7854# 2# B- 5363# 499# 196 983747# 430# - 47 122 75 197 Re x -20502# 298# 7878# 2# B- 4807# 357# 196 977990# 320# - 45 121 76 197 Os x -25309# 196# 7898# 1# B- 2955# 197# 196 972830# 210# - 43 120 77 197 Ir +p -28264.105 20.110 7908.999 0.102 B- 2155.645 20.106 196 969657.233 21.588 - 41 119 78 197 Pt -30419.750 0.536 7915.971 0.003 B- 719.988 0.502 196 967343.053 0.575 - 39 118 79 197 Au -31139.738 0.542 7915.654 0.003 B- -599.509 3.202 196 966570.114 0.581 - 37 117 80 197 Hg -30540.229 3.207 7908.640 0.016 B- -2198.580 16.637 196 967213.713 3.442 - 35 116 81 197 Tl +a -28341.649 16.325 7893.508 0.083 B- -3596.247 17.014 196 969573.986 17.526 - 33 115 82 197 Pb -24745.401 4.804 7871.282 0.024 B- -5058.210 9.619 196 973434.717 5.157 - 31 114 83 197 Bi +a -19687.191 8.333 7841.634 0.042 B- -6329.202 50.373 196 978864.929 8.946 - 29 113 84 197 Po -a -13357.990 49.679 7805.535 0.252 B- -7002.739 50.317 196 985659.607 53.332 - 27 112 85 197 At -6355.250 7.983 7766.017 0.041 B- -7865.603 18.054 196 993177.357 8.570 - 25 111 86 197 Rn -a 1510.353 16.193 7722.118 0.082 B- -8743.618 56.762 197 001621.430 17.383 - 23 110 87 197 Fr -a 10253.971 54.404 7673.763 0.276 B- * 197 011008.090 58.404 -0 48 123 75 198 Re x -17139# 401# 7862# 2# B- 6697# 446# 197 981600# 430# - 46 122 76 198 Os x -23837# 196# 7891# 1# B- 1984# 277# 197 974410# 210# - 44 121 77 198 Ir x -25821# 196# 7897# 1# B- 4083# 196# 197 972280# 210# - 42 120 78 198 Pt -29903.999 2.100 7914.150 0.011 B- -323.219 2.059 197 967896.734 2.254 - 40 119 79 198 Au -29580.781 0.540 7908.567 0.003 B- 1373.530 0.490 197 968243.724 0.579 - 38 118 80 198 Hg -30954.310 0.458 7911.552 0.002 B- -3425.564 7.559 197 966769.179 0.491 - 36 117 81 198 Tl x -27528.746 7.545 7890.300 0.038 B- -1461.257 11.554 197 970446.673 8.100 - 34 116 82 198 Pb -26067.489 8.750 7878.969 0.044 B- -6698.003 29.283 197 972015.397 9.393 - 32 115 83 198 Bi x -19369.486 27.945 7841.189 0.141 B- -3896.134 32.932 197 979206.000 30.000 - 30 114 84 198 Po -15473.352 17.424 7817.561 0.088 B- -8758.839 18.386 197 983388.672 18.705 - 28 113 85 198 At x -6714.513 5.868 7769.373 0.030 B- -5484.155 14.647 197 992791.673 6.300 - 26 112 86 198 Rn -a -1230.358 13.420 7737.724 0.068 B- -10804.382 34.905 197 998679.156 14.406 - 24 111 87 198 Fr -a 9574.024 32.222 7679.205 0.163 B- * 198 010278.138 34.591 -0 49 124 75 199 Re x -14860# 401# 7851# 2# B- 5623# 446# 198 984047# 430# - 47 123 76 199 Os x -20484# 196# 7875# 1# B- 3915# 200# 198 978010# 210# - 45 122 77 199 Ir p-2n -24398.515 41.054 7891.206 0.206 B- 2990.167 41.003 198 973807.115 44.073 - 43 121 78 199 Pt -n -27388.682 2.159 7902.300 0.011 B- 1705.059 2.120 198 970597.038 2.317 - 41 120 79 199 Au -29093.741 0.542 7906.937 0.003 B- 452.327 0.613 198 968766.582 0.581 - 39 119 80 199 Hg -29546.068 0.526 7905.279 0.003 B- -1486.674 27.950 198 968280.989 0.564 - 37 118 81 199 Tl x -28059.394 27.945 7893.877 0.140 B- -2827.589 29.679 198 969877.000 30.000 - 35 117 82 199 Pb +a -25231.804 9.996 7875.736 0.050 B- -4434.239 14.547 198 972912.542 10.730 - 33 116 83 199 Bi -20797.566 10.568 7849.522 0.053 B- -5589.083 20.919 198 977672.893 11.345 - 31 115 84 199 Po -a -15208.483 18.060 7817.505 0.091 B- -6385.111 18.845 198 983673.021 19.387 - 29 114 85 199 At -8823.372 5.384 7781.488 0.027 B- -7323.921 37.972 198 990527.719 5.780 - 27 113 86 199 Rn -a -1499.451 37.588 7740.753 0.189 B- -8270.844 40.015 198 998390.273 40.352 - 25 112 87 199 Fr -a 6771.393 13.726 7695.259 0.069 B- * 199 007269.389 14.734 -0 48 124 76 200 Os x -18779# 298# 7868# 1# B- 2832# 357# 199 979840# 320# - 46 123 77 200 Ir x -21611# 196# 7878# 1# B- 4988# 197# 199 976800# 210# - 44 122 78 200 Pt -nn -26599.160 20.110 7899.198 0.101 B- 640.932 33.439 199 971444.625 21.588 - 42 121 79 200 Au -27240.092 26.717 7898.491 0.134 B- 2263.178 26.719 199 970756.556 28.681 - 40 120 80 200 Hg -29503.270 0.529 7905.895 0.003 B- -2456.040 5.735 199 968326.934 0.568 - 38 119 81 200 Tl - -27047.230 5.759 7889.703 0.029 B- -796.176 12.340 199 970963.602 6.182 - 36 118 82 200 Pb 4n -26251.054 10.927 7881.810 0.055 B- -5880.299 24.852 199 971818.332 11.730 - 34 117 83 200 Bi +a -20370.755 22.321 7848.497 0.112 B- -3428.994 23.573 199 978131.093 23.962 - 32 116 84 200 Po -16941.761 7.579 7827.440 0.038 B- -7953.869 25.612 199 981812.270 8.135 - 30 115 85 200 At -a -8987.892 24.465 7783.759 0.122 B- -4983.127 28.030 199 990351.100 26.264 - 28 114 86 200 Rn -a -4004.765 13.681 7754.932 0.068 B- -10137.263 33.529 199 995700.707 14.686 - 26 113 87 200 Fr -a 6132.498 30.611 7700.334 0.153 B- * 200 006583.507 32.861 -0 49 125 76 201 Os x -15239# 298# 7851# 1# B- 4657# 357# 200 983640# 320# - 47 124 77 201 Ir x -19897# 196# 7871# 1# B- 3844# 202# 200 978640# 210# - 45 123 78 201 Pt + -23740.714 50.103 7885.833 0.249 B- 2660.000 50.000 200 974513.293 53.788 - 43 122 79 201 Au -26400.714 3.218 7895.175 0.016 B- 1261.827 3.147 200 971657.665 3.454 - 41 121 80 201 Hg -27662.542 0.711 7897.560 0.004 B- -481.704 14.181 200 970303.038 0.763 - 39 120 81 201 Tl -27180.838 14.185 7891.271 0.071 B- -1909.802 18.530 200 970820.168 15.228 - 37 119 82 201 Pb -25271.036 13.747 7877.877 0.068 B- -3854.603 20.481 200 972870.425 14.758 - 35 118 83 201 Bi +a -21416.433 15.183 7854.808 0.076 B- -4895.248 15.962 200 977008.512 16.299 - 33 117 84 201 Po -16521.185 4.942 7826.561 0.025 B- -5731.747 9.561 200 982263.777 5.305 - 31 116 85 201 At +a -10789.438 8.184 7794.153 0.041 B- -6717.113 50.401 200 988417.061 8.786 - 29 115 86 201 Rn -a -4072.324 49.732 7756.842 0.247 B- -7660.902 50.554 200 995628.179 53.389 - 27 114 87 201 Fr -a 3588.577 9.080 7714.836 0.045 B- -8348.224 22.239 201 003852.496 9.747 - 25 113 88 201 Ra -a 11936.801 20.301 7669.410 0.101 B- * 201 012814.683 21.794 -0 50 126 76 202 Os x -13087# 401# 7842# 2# B- 3689# 499# 201 985950# 430# - 48 125 77 202 Ir x -16776# 298# 7856# 1# B- 5916# 299# 201 981990# 320# - 46 124 78 202 Pt x -22692.125 25.150 7881.560 0.125 B- 1660.854 34.276 201 975639.000 27.000 - 44 123 79 202 Au x -24352.979 23.287 7885.909 0.115 B- 2992.345 23.298 201 973856.000 25.000 - 42 122 80 202 Hg -27345.324 0.705 7896.850 0.003 B- -1365.108 1.636 201 970643.585 0.756 - 40 121 81 202 Tl -25980.216 1.606 7886.219 0.008 B- -39.602 4.096 201 972109.089 1.723 - 38 120 82 202 Pb -25940.614 3.796 7882.150 0.019 B- -5199.130 15.856 201 972151.604 4.075 - 36 119 83 202 Bi -20741.484 15.396 7852.539 0.076 B- -2799.868 17.666 201 977733.100 16.528 - 34 118 84 202 Po -17941.616 8.670 7834.805 0.043 B- -7350.884 29.289 201 980738.881 9.307 - 32 117 85 202 At -a -10590.732 27.977 7794.541 0.138 B- -4316.097 33.010 201 988630.380 30.034 - 30 116 86 202 Rn -a -6274.635 17.520 7769.301 0.087 B- -9370.871 18.881 201 993263.902 18.808 - 28 115 87 202 Fr -a 3096.237 7.040 7719.038 0.035 B- -5978.625 16.586 202 003323.946 7.557 - 26 114 88 202 Ra -a 9074.861 15.018 7685.568 0.074 B- * 202 009742.264 16.122 -0 51 127 76 203 Os x -7640# 401# 7816# 2# B- 7050# 566# 202 991798# 430# - 49 126 77 203 Ir x -14690# 401# 7847# 2# B- 4937# 446# 202 984230# 430# - 47 125 78 203 Pt x -19627# 196# 7867# 1# B- 3517# 196# 202 978930# 210# - 45 124 79 203 Au -23143.436 3.083 7880.864 0.015 B- 2125.829 3.451 202 975154.498 3.309 - 43 123 80 203 Hg -25269.265 1.627 7887.482 0.008 B- 492.112 1.225 202 972872.326 1.746 - 41 122 81 203 Tl -25761.377 1.166 7886.053 0.006 B- -974.820 6.461 202 972344.022 1.252 - 39 121 82 203 Pb -24786.557 6.554 7877.397 0.032 B- -3261.729 14.356 202 973390.535 7.036 - 37 120 83 203 Bi +a -21524.827 12.778 7857.475 0.063 B- -4213.939 15.433 202 976892.145 13.717 - 35 119 84 203 Po +a -17310.889 8.655 7832.863 0.043 B- -5148.332 13.666 202 981415.995 9.291 - 33 118 85 203 At -12162.557 10.576 7803.648 0.052 B- -6008.858 21.027 202 986942.957 11.353 - 31 117 86 203 Rn -a -6153.699 18.179 7770.193 0.090 B- -7030.116 19.218 202 993393.732 19.516 - 29 116 87 203 Fr 876.417 6.232 7731.708 0.031 B- -7785.309 38.630 203 000940.872 6.689 - 27 115 88 203 Ra -a 8661.726 38.124 7689.503 0.188 B- * 203 009298.745 40.928 -0 50 127 77 204 Ir x -9688# 401# 7824# 2# B- 8234# 446# 203 989600# 430# - 48 126 78 204 Pt x -17922# 196# 7860# 1# B- 2728# 280# 203 980760# 210# - 46 125 79 204 Au + -20650# 200# 7870# 1# B- 4040# 200# 203 977831# 215# - 44 124 80 204 Hg -24690.145 0.498 7885.545 0.002 B- -344.000 1.186 203 973494.037 0.534 - 42 123 81 204 Tl -24346.145 1.152 7880.023 0.006 B- 763.748 0.177 203 973863.337 1.236 - 40 122 82 204 Pb -25109.892 1.146 7879.932 0.006 B- -4463.996 9.248 203 973043.420 1.230 - 38 121 83 204 Bi +a -20645.896 9.180 7854.215 0.045 B- -2304.652 14.335 203 977835.717 9.854 - 36 120 84 204 Po -a -18341.244 11.013 7839.083 0.054 B- -6465.811 24.860 203 980309.863 11.822 - 34 119 85 204 At -11875.433 22.288 7803.552 0.109 B- -3905.240 23.498 203 987251.197 23.926 - 32 118 86 204 Rn -7970.193 7.444 7780.574 0.036 B- -8577.503 25.684 203 991443.644 7.991 - 30 117 87 204 Fr -a 607.310 24.581 7734.692 0.120 B- -5449.477 28.940 204 000651.974 26.389 - 28 116 88 204 Ra -a 6056.787 15.273 7704.144 0.075 B- * 204 006502.228 16.396 -0 51 128 77 205 Ir x -5960# 503# 7807# 2# B- 7007# 585# 204 993602# 540# - 49 127 78 205 Pt x -12966# 298# 7837# 1# B- 5803# 357# 204 986080# 320# - 47 126 79 205 Au x -18770# 196# 7861# 1# B- 3518# 196# 204 979850# 210# - 45 125 80 205 Hg -22287.740 3.654 7874.732 0.018 B- 1533.135 3.724 204 976073.125 3.923 - 43 124 81 205 Tl -23820.874 1.237 7878.394 0.006 B- -50.636 0.503 204 974427.237 1.328 - 41 123 82 205 Pb -23770.239 1.144 7874.331 0.006 B- -2705.734 5.107 204 974481.597 1.228 - 39 122 83 205 Bi -21064.504 5.111 7857.316 0.025 B- -3543.106 11.280 204 977386.323 5.487 - 37 121 84 205 Po -17521.398 10.059 7836.216 0.049 B- -4549.452 18.130 204 981190.004 10.798 - 35 120 85 205 At +a -12971.946 15.085 7810.207 0.074 B- -5262.161 15.913 204 986074.041 16.194 - 33 119 86 205 Rn -7709.786 5.080 7780.722 0.025 B- -6399.973 9.329 204 991723.204 5.453 - 31 118 87 205 Fr x -1309.813 7.824 7745.686 0.038 B- -7148.804 70.954 204 998593.858 8.399 - 29 117 88 205 Ra -a 5838.991 70.521 7706.998 0.344 B- -8267.702 86.923 205 006268.415 75.707 - 27 116 89 205 Ac -a 14106.693 50.818 7662.851 0.248 B- * 205 015144.158 54.555 -0 50 128 78 206 Pt x -9632# 298# 7822# 1# B- 4583# 422# 205 989660# 320# - 48 127 79 206 Au x -14215# 298# 7840# 1# B- 6731# 299# 205 984740# 320# - 46 126 80 206 Hg +a -20945.801 20.440 7869.172 0.099 B- 1307.566 20.410 205 977513.756 21.943 - 44 125 81 206 Tl -22253.367 1.284 7871.721 0.006 B- 1532.217 0.612 205 976110.026 1.378 - 42 124 82 206 Pb -23785.584 1.144 7875.362 0.006 B- -3757.306 7.546 205 974465.124 1.227 - 40 123 83 206 Bi - -20028.278 7.632 7853.324 0.037 B- -1839.604 8.600 205 978498.757 8.193 - 38 122 84 206 Po -a -18188.674 4.012 7840.597 0.019 B- -5758.956 15.580 205 980473.654 4.306 - 36 121 85 206 At -12429.718 15.056 7808.843 0.073 B- -3296.753 17.330 205 986656.148 16.162 - 34 120 86 206 Rn -9132.965 8.591 7789.041 0.042 B- -7890.549 29.475 205 990195.358 9.223 - 32 119 87 206 Fr -a -1242.416 28.195 7746.940 0.137 B- -4807.955 33.455 205 998666.211 30.268 - 30 118 88 206 Ra -a 3565.539 18.008 7719.802 0.087 B- -9913.913 53.608 206 003827.763 19.332 - 28 117 89 206 Ac -a 13479.452 50.493 7667.879 0.245 B- * 206 014470.787 54.206 -0 51 129 78 207 Pt x -4540# 401# 7798# 2# B- 6270# 500# 206 995126# 430# - 49 128 79 207 Au x -10810# 300# 7825# 1# B- 5677# 301# 206 988395# 322# - 47 127 80 207 Hg x -16487.444 29.808 7848.610 0.144 B- 4547.008 30.300 206 982300.000 32.000 - 45 126 81 207 Tl -21034.451 5.439 7866.797 0.026 B- 1417.595 5.402 206 977418.586 5.839 - 43 125 82 207 Pb -22452.047 1.147 7869.866 0.006 B- -2397.420 2.118 206 975896.735 1.230 - 41 124 83 207 Bi -20054.627 2.397 7854.505 0.012 B- -2908.852 6.614 206 978470.471 2.573 - 39 123 84 207 Po -17145.775 6.659 7836.673 0.032 B- -3918.358 14.075 206 981593.252 7.148 - 37 122 85 207 At +a -13227.416 12.406 7813.964 0.060 B- -4592.654 15.037 206 985799.783 13.318 - 35 121 86 207 Rn +a -8634.762 8.497 7787.998 0.041 B- -5790.421 19.458 206 990730.200 9.121 - 33 120 87 207 Fr -2844.341 17.505 7756.246 0.085 B- -6388.826 56.008 206 996946.474 18.792 - 31 119 88 207 Ra -a 3544.485 53.202 7721.602 0.257 B- -7601.748 73.276 207 003805.161 57.115 - 29 118 89 207 Ac -a 11146.233 50.387 7681.099 0.243 B- * 207 011965.973 54.092 -0 52 130 78 208 Pt x -990# 400# 7783# 2# B- 5111# 499# 207 998937# 429# - 50 129 79 208 Au x -6101# 298# 7804# 1# B- 7164# 300# 207 993450# 320# - 48 128 80 208 Hg x -13265.406 30.739 7834.191 0.148 B- 3484.726 30.795 207 985759.000 33.000 - 46 127 81 208 Tl +a -16750.132 1.854 7847.183 0.009 B- 4998.466 1.669 207 982017.992 1.990 - 44 126 82 208 Pb -21748.598 1.148 7867.453 0.006 B- -2878.375 2.013 207 976651.918 1.231 - 42 125 83 208 Bi +n -18870.223 2.304 7849.853 0.011 B- -1400.628 2.397 207 979741.981 2.473 - 40 124 84 208 Po -a -17469.596 1.737 7839.358 0.008 B- -4999.725 9.086 207 981245.616 1.864 - 38 123 85 208 At +a -12469.871 8.921 7811.560 0.043 B- -2814.279 14.269 207 986613.042 9.577 - 36 122 86 208 Rn -a -9655.591 11.138 7794.268 0.054 B- -6989.672 16.251 207 989634.295 11.957 - 34 121 87 208 Fr -2665.919 11.834 7756.903 0.057 B- -4393.774 14.881 207 997138.018 12.704 - 32 120 88 208 Ra -a 1727.856 9.023 7732.017 0.043 B- -9025.380 56.442 208 001854.929 9.686 - 30 119 89 208 Ac -a 10753.235 55.716 7684.865 0.268 B- -5930.495 65.370 208 011544.073 59.813 - 28 118 90 208 Th -a 16683.730 34.190 7652.592 0.164 B- * 208 017910.722 36.704 -0 51 130 79 209 Au x -2540# 400# 7788# 2# B- 6104# 426# 208 997273# 429# - 49 129 80 209 Hg x -8644# 149# 7813# 1# B- 5000# 149# 208 990720# 160# - 47 128 81 209 Tl +a -13644.757 6.110 7833.397 0.029 B- 3969.889 6.211 208 985351.750 6.559 - 45 127 82 209 Pb -17614.646 1.747 7848.648 0.008 B- 644.016 1.146 208 981089.898 1.875 - 43 126 83 209 Bi -18258.662 1.364 7847.987 0.007 B- -1892.570 1.564 208 980398.519 1.464 - 41 125 84 209 Po -a -16366.092 1.778 7835.188 0.009 B- -3483.478 5.287 208 982430.276 1.908 - 39 124 85 209 At -12882.613 5.102 7814.777 0.024 B- -3941.564 11.188 208 986169.944 5.477 - 37 123 86 209 Rn -8941.049 9.960 7792.175 0.048 B- -5171.477 17.713 208 990401.388 10.692 - 35 122 87 209 Fr x -3769.572 14.648 7763.688 0.070 B- -5627.791 15.730 208 995953.197 15.725 - 33 121 88 209 Ra -a 1858.219 5.747 7733.017 0.027 B- -6985.590 50.934 209 001994.879 6.169 - 31 120 89 209 Ac -a 8843.809 50.608 7695.850 0.242 B- -7523# 148# 209 009494.220 54.330 - 29 119 90 209 Th IT 16367# 140# 7656# 1# B- * 209 017571# 150# -0 52 131 79 210 Au x 2329# 401# 7766# 2# B- 7694# 446# 210 002500# 430# - 50 130 80 210 Hg x -5365# 196# 7799# 1# B- 3882# 196# 209 994240# 210# - 48 129 81 210 Tl +a -9246.969 11.604 7813.588 0.055 B- 5481.534 11.561 209 990072.970 12.456 - 46 128 82 210 Pb -14728.502 1.447 7835.965 0.007 B- 63.476 0.499 209 984188.301 1.553 - 44 127 83 210 Bi -14791.979 1.363 7832.542 0.006 B- 1161.159 0.766 209 984120.156 1.462 - 42 126 84 210 Po -15953.137 1.146 7834.346 0.005 B- -3980.960 7.610 209 982873.601 1.230 - 40 125 85 210 At -a -11972.177 7.695 7811.663 0.037 B- -2367.407 8.922 209 987147.338 8.261 - 38 124 86 210 Rn -a -9604.770 4.557 7796.665 0.022 B- -6271.565 15.824 209 989688.854 4.892 - 36 123 87 210 Fr -3333.205 15.154 7763.075 0.072 B- -3775.997 17.720 209 996421.657 16.268 - 34 122 88 210 Ra -a 442.792 9.193 7741.368 0.044 B- -8346.908 58.133 210 000475.356 9.868 - 32 121 89 210 Ac -a 8789.699 57.402 7697.896 0.273 B- -5269.747 60.436 210 009436.130 61.623 - 30 120 90 210 Th -a 14059.446 18.909 7669.076 0.090 B- * 210 015093.437 20.299 -0 51 131 80 211 Hg x -624# 196# 7778# 1# B- 5454# 200# 210 999330# 210# - 49 130 81 211 Tl x -6077.998 41.917 7799.791 0.199 B- 4414.950 41.978 210 993475.000 45.000 - 47 129 82 211 Pb -10492.948 2.261 7817.007 0.011 B- 1366.183 5.471 210 988735.356 2.426 - 45 128 83 211 Bi -11859.131 5.442 7819.774 0.026 B- 573.439 5.430 210 987268.698 5.842 - 43 127 84 211 Po -a -12432.571 1.255 7818.784 0.006 B- -785.307 2.539 210 986653.085 1.347 - 41 126 85 211 At -a -11647.264 2.729 7811.354 0.013 B- -2891.860 6.894 210 987496.147 2.929 - 39 125 86 211 Rn -a -8755.404 6.813 7793.941 0.032 B- -4615.155 13.786 210 990600.686 7.314 - 37 124 87 211 Fr -4140.249 11.991 7768.360 0.057 B- -4972.272 14.369 210 995555.259 12.872 - 35 123 88 211 Ra x 832.023 7.918 7741.087 0.038 B- -6370.191 53.564 211 000893.213 8.500 - 33 122 89 211 Ac -a 7202.214 52.976 7707.189 0.251 B- -6707.958 90.205 211 007731.894 56.871 - 31 121 90 211 Th -a 13910.171 73.010 7671.690 0.346 B- -8170# 126# 211 014933.183 78.379 - 29 120 91 211 Pa x 22080# 102# 7629# 0# B- * 211 023704# 110# -0 52 132 80 212 Hg x 2757# 298# 7763# 1# B- 4308# 359# 212 002960# 320# - 50 131 81 212 Tl +a -1551# 200# 7780# 1# B- 5998# 200# 211 998335# 215# - 48 130 82 212 Pb -7548.850 1.842 7804.319 0.009 B- 569.104 1.825 211 991895.975 1.977 - 46 129 83 212 Bi -8117.954 1.854 7803.313 0.009 B- 2251.533 1.667 211 991285.016 1.989 - 44 128 84 212 Po -10369.487 1.152 7810.243 0.005 B- -1741.266 2.107 211 988867.896 1.236 - 42 127 85 212 At -a -8628.221 2.384 7798.340 0.011 B- 31.387 3.605 211 990737.223 2.559 - 40 126 86 212 Rn -a -8659.608 3.145 7794.797 0.015 B- -5143.640 9.318 211 990703.528 3.376 - 38 125 87 212 Fr -3515.968 8.775 7766.845 0.041 B- -3317.000 14.276 211 996225.453 9.420 - 36 124 88 212 Ra -a -198.968 11.263 7747.508 0.053 B- -7476.266 52.601 211 999786.399 12.091 - 34 123 89 212 Ac -a 7277.298 51.381 7708.552 0.242 B- -4833.510 52.366 212 007812.501 55.160 - 32 122 90 212 Th -a 12110.808 10.109 7682.062 0.048 B- -9482.551 75.541 212 013001.487 10.852 - 30 121 91 212 Pa -a 21593.358 74.862 7633.643 0.353 B- * 212 023181.425 80.367 -0 53 133 80 213 Hg x 7666# 298# 7741# 1# B- 5882# 299# 213 008230# 320# - 51 132 81 213 Tl x 1783.811 27.013 7765.430 0.127 B- 4987.343 27.894 213 001915.000 29.000 - 49 131 82 213 Pb +a -3203.532 6.954 7785.172 0.033 B- 2028.103 8.371 212 996560.867 7.465 - 47 130 83 213 Bi -5231.635 5.082 7791.021 0.024 B- 1421.949 5.490 212 994383.608 5.456 - 45 129 84 213 Po -6653.584 3.053 7794.024 0.014 B- -73.989 5.465 212 992857.083 3.277 - 43 128 85 213 At -a -6579.595 4.898 7790.003 0.023 B- -883.569 5.724 212 992936.514 5.257 - 41 127 86 213 Rn -a -5696.026 3.370 7782.182 0.016 B- -2143.179 6.006 212 993885.064 3.617 - 39 126 87 213 Fr -3552.848 5.091 7768.447 0.024 B- -3898.405 11.057 212 996185.861 5.465 - 37 125 88 213 Ra 345.557 9.818 7746.472 0.046 B- -5809.134 18.156 213 000370.970 10.540 - 35 124 89 213 Ac -a 6154.692 15.272 7715.526 0.072 B- -5965.394 17.834 213 006607.333 16.395 - 33 123 90 213 Th -a 12120.086 9.217 7683.846 0.043 B- -7542.539 71.737 213 013011.447 9.895 - 31 122 91 213 Pa -a 19662.625 71.142 7644.762 0.334 B- * 213 021108.697 76.374 -0 54 134 80 214 Hg x 11178# 401# 7727# 2# B- 4713# 446# 214 012000# 430# - 52 133 81 214 Tl x 6465# 196# 7745# 1# B- 6647# 196# 214 006940# 210# - 50 132 82 214 Pb -182.769 1.975 7772.394 0.009 B- 1017.984 11.256 213 999803.788 2.120 - 48 131 83 214 Bi -1200.753 11.209 7773.495 0.052 B- 3269.293 11.165 213 998710.938 12.033 - 46 130 84 214 Po -4470.046 1.449 7785.116 0.007 B- -1090.215 4.107 213 995201.208 1.555 - 44 129 85 214 At -a -3379.831 4.298 7776.366 0.020 B- 939.911 10.014 213 996371.601 4.614 - 42 128 86 214 Rn -a -4319.742 9.187 7777.102 0.043 B- -3361.035 12.503 213 995362.566 9.862 - 40 127 87 214 Fr -a -958.707 8.634 7757.740 0.040 B- -1051.441 10.086 213 998970.785 9.268 - 38 126 88 214 Ra -a 92.734 5.250 7749.171 0.025 B- -6351.120 16.232 214 000099.554 5.636 - 36 125 89 214 Ac -a 6443.854 15.360 7715.837 0.072 B- -4251.030 18.693 214 006917.762 16.489 - 34 124 90 214 Th -a 10694.885 10.661 7692.317 0.050 B- -8790.630 76.867 214 011481.431 11.445 - 32 123 91 214 Pa -a 19485.515 76.125 7647.583 0.356 B- * 214 020918.561 81.723 -0 55 135 80 215 Hg x 16208# 401# 7705# 2# B- 6297# 499# 215 017400# 430# - 53 134 81 215 Tl x 9911# 298# 7730# 1# B- 5569# 303# 215 010640# 320# - 51 133 82 215 Pb +a 4342.244 52.448 7752.737 0.244 B- 2712.922 52.748 215 004661.590 56.304 - 49 132 83 215 Bi 1629.322 5.624 7761.717 0.026 B- 2171.028 5.530 215 001749.149 6.037 - 47 131 84 215 Po -541.706 2.121 7768.176 0.010 B- 714.049 6.819 214 999418.454 2.276 - 45 130 85 215 At -a -1255.756 6.799 7767.858 0.032 B- -87.195 10.168 214 998651.890 7.299 - 43 129 86 215 Rn -a -1168.561 7.672 7763.814 0.036 B- -1486.625 10.306 214 998745.498 8.236 - 41 128 87 215 Fr -a 318.065 7.066 7753.260 0.033 B- -2215.674 10.077 215 000341.456 7.585 - 39 127 88 215 Ra -a 2533.739 7.613 7739.316 0.035 B- -3496.877 14.551 215 002720.080 8.172 - 37 126 89 215 Ac -a 6030.615 12.406 7719.413 0.058 B- -4890.971 15.234 215 006474.132 13.318 - 35 125 90 215 Th -a 10921.586 8.840 7693.025 0.041 B- -6942.353 73.380 215 011724.805 9.490 - 33 124 91 215 Pa -a 17863.939 72.845 7657.096 0.339 B- -7059.147 114.616 215 019177.728 78.202 - 31 123 92 215 U -a 24923.087 88.490 7620.624 0.412 B- * 215 026756.035 94.997 -0 56 136 80 216 Hg x 19859# 401# 7690# 2# B- 5142# 499# 216 021320# 430# - 54 135 81 216 Tl x 14718# 298# 7710# 1# B- 7238# 357# 216 015800# 320# - 52 134 82 216 Pb x 7480# 196# 7740# 1# B- 1606# 196# 216 008030# 210# - 50 133 83 216 Bi x 5873.991 11.178 7743.499 0.052 B- 4091.571 11.324 216 006305.989 12.000 - 48 132 84 216 Po 1782.420 1.816 7758.819 0.008 B- -474.246 3.571 216 001913.506 1.949 - 46 131 85 216 At -a 2256.666 3.575 7753.002 0.017 B- 2003.799 6.836 216 002422.631 3.837 - 44 130 86 216 Rn -a 252.868 5.994 7758.657 0.028 B- -2718.082 7.126 216 000271.464 6.435 - 42 129 87 216 Fr -a 2970.950 4.173 7742.451 0.019 B- -320.128 9.548 216 003189.445 4.480 - 40 128 88 216 Ra -a 3291.077 8.737 7737.347 0.040 B- -4853.317 13.921 216 003533.117 9.379 - 38 127 89 216 Ac -a 8144.395 10.840 7711.256 0.050 B- -2153.937 16.201 216 008743.367 11.637 - 36 126 90 216 Th -a 10298.332 12.042 7697.662 0.056 B- -7500.882 54.864 216 011055.714 12.928 - 34 125 91 216 Pa -a 17799.214 53.526 7659.314 0.248 B- -5267.137 60.450 216 019108.242 57.462 - 32 124 92 216 U -a 23066.351 28.093 7631.307 0.130 B- * 216 024762.747 30.158 -0 55 136 81 217 Tl x 18313# 401# 7695# 2# B- 6073# 499# 217 019660# 430# - 53 135 82 217 Pb x 12240# 298# 7719# 1# B- 3510# 299# 217 013140# 320# - 51 134 83 217 Bi x 8729.962 17.698 7731.848 0.082 B- 2846.444 18.870 217 009372.000 19.000 - 49 133 84 217 Po +a 5883.518 6.544 7741.360 0.030 B- 1488.883 7.979 217 006316.216 7.025 - 47 132 85 217 At 4394.635 5.001 7744.616 0.023 B- 736.135 6.151 217 004717.835 5.369 - 45 131 86 217 Rn -a 3658.501 4.198 7744.403 0.019 B- -656.089 7.538 217 003927.562 4.506 - 43 130 87 217 Fr -a 4314.590 6.531 7737.775 0.030 B- -1575.067 9.588 217 004631.902 7.010 - 41 129 88 217 Ra -a 5889.656 7.202 7726.911 0.033 B- -2814.017 13.430 217 006322.806 7.731 - 39 128 89 217 Ac -a 8703.673 11.389 7710.338 0.052 B- -3502.107 15.566 217 009343.777 12.226 - 37 127 90 217 Th -a 12205.780 10.614 7690.594 0.049 B- -4862.630 19.132 217 013103.444 11.394 - 35 126 91 217 Pa -a 17068.410 15.918 7664.580 0.073 B- -5905# 73# 217 018323.692 17.089 - 33 125 92 217 U -a 22973# 71# 7634# 0# B- * 217 024663# 77# -0 56 137 81 218 Tl x 23180# 400# 7674# 2# B- 7727# 499# 218 024885# 429# - 54 136 82 218 Pb x 15453# 298# 7706# 1# B- 2237# 299# 218 016590# 320# - 52 135 83 218 Bi x 13216.037 27.013 7712.827 0.124 B- 4859.136 27.085 218 014188.000 29.000 - 50 134 84 218 Po 8356.901 1.973 7731.528 0.009 B- 258.738 11.649 218 008971.502 2.118 - 48 133 85 218 At -a 8098.162 11.604 7729.126 0.053 B- 2880.816 11.705 218 008693.735 12.456 - 46 132 86 218 Rn 5217.347 2.316 7738.752 0.011 B- -1841.770 4.942 218 005601.052 2.486 - 44 131 87 218 Fr -a 7059.117 4.757 7726.715 0.022 B- 407.947 12.039 218 007578.274 5.106 - 42 130 88 218 Ra -a 6651.170 11.176 7724.998 0.051 B- -4192.439 51.931 218 007140.325 11.997 - 40 129 89 218 Ac -a 10843.609 50.740 7702.177 0.233 B- -1523.132 51.815 218 011641.093 54.471 - 38 128 90 218 Th -a 12366.741 10.516 7691.602 0.048 B- -6317.029 21.130 218 013276.242 11.289 - 36 127 91 218 Pa -a 18683.770 18.329 7659.036 0.084 B- -3210.838 22.888 218 020057.853 19.676 - 34 126 92 218 U -a 21894.608 13.714 7640.719 0.063 B- * 218 023504.829 14.722 -0 55 137 82 219 Pb x 20279# 401# 7686# 2# B- 3996# 446# 219 021770# 430# - 53 136 83 219 Bi x 16283# 196# 7700# 1# B- 3601# 196# 219 017480# 210# - 51 135 84 219 Po x 12681.359 15.835 7713.333 0.072 B- 2285.283 16.163 219 013614.000 17.000 - 49 134 85 219 At 10396.076 3.237 7720.196 0.015 B- 1566.675 2.947 219 011160.647 3.474 - 47 133 86 219 Rn 8829.402 2.100 7723.777 0.010 B- 211.635 7.058 219 009478.753 2.254 - 45 132 87 219 Fr -a 8617.767 7.039 7721.171 0.032 B- -776.515 10.772 219 009251.553 7.556 - 43 131 88 219 Ra -a 9394.282 8.258 7714.053 0.038 B- -2175.199 51.142 219 010085.176 8.865 - 41 130 89 219 Ac -a 11569.480 50.497 7700.549 0.231 B- -2901.910 71.425 219 012420.348 54.210 - 39 129 90 219 Th -a 14471.390 50.576 7683.725 0.231 B- -4068.741 72.192 219 015535.677 54.295 - 37 128 91 219 Pa -a 18540.131 51.516 7661.574 0.235 B- -4746.439 72.333 219 019903.650 55.304 - 35 127 92 219 U -a 23286.569 50.775 7636.329 0.232 B- -6170.086 101.905 219 024999.161 54.509 - 33 126 93 219 Np -a 29456.655 88.354 7604.583 0.403 B- * 219 031623.021 94.851 -0 56 138 82 220 Pb x 23669# 401# 7672# 2# B- 2850# 499# 220 025410# 430# - 54 137 83 220 Bi x 20819# 298# 7682# 1# B- 5555# 299# 220 022350# 320# - 52 136 84 220 Po x 15263.461 17.698 7703.224 0.080 B- 887.714 22.549 220 016386.000 19.000 - 50 135 85 220 At x 14375.747 13.972 7703.703 0.064 B- 3763.670 14.090 220 015433.000 15.000 - 48 134 86 220 Rn 10612.077 1.815 7717.254 0.008 B- -870.242 4.026 220 011392.534 1.948 - 46 133 87 220 Fr -a 11482.320 4.028 7709.742 0.018 B- 1212.075 9.061 220 012326.778 4.324 - 44 132 88 220 Ra -a 10270.245 8.237 7711.696 0.037 B- -3473.437 10.141 220 011025.562 8.843 - 42 131 89 220 Ac -a 13743.682 6.129 7692.351 0.028 B- -925.417 22.941 220 014754.450 6.579 - 40 130 90 220 Th -a 14669.100 22.166 7684.589 0.101 B- -5549# 56# 220 015747.926 23.795 - 38 129 91 220 Pa -a 20218# 51# 7656# 0# B- -2715# 113# 220 021705# 55# - 36 128 92 220 U -a 22933# 101# 7640# 0# B- -7378# 220# 220 024620# 108# - 34 127 93 220 Np x 30311# 196# 7603# 1# B- * 220 032540# 210# -0 55 138 83 221 Bi x 24098# 298# 7668# 1# B- 4324# 299# 221 025870# 320# - 53 137 84 221 Po x 19773.755 19.561 7684.481 0.089 B- 2991.027 24.039 221 021228.000 21.000 - 51 136 85 221 At x 16782.727 13.972 7694.475 0.063 B- 2311.308 15.096 221 018017.000 15.000 - 49 135 86 221 Rn +a 14471.420 5.714 7701.393 0.026 B- 1194.130 7.231 221 015535.709 6.134 - 47 134 87 221 Fr 13277.290 4.886 7703.256 0.022 B- 313.479 6.386 221 014253.757 5.245 - 45 133 88 221 Ra -a 12963.811 4.630 7701.135 0.021 B- -1559.298 50.603 221 013917.224 4.970 - 43 132 89 221 Ac -a 14523.109 50.425 7690.539 0.228 B- -2417.261 51.056 221 015591.199 54.133 - 41 131 90 221 Th -a 16940.371 8.166 7676.061 0.037 B- -3435.918 51.915 221 018186.236 8.766 - 39 130 91 221 Pa -a 20376.288 51.281 7656.974 0.232 B- -4143.707 72.404 221 021874.846 55.052 - 37 129 92 221 U -a 24519.995 51.114 7634.684 0.231 B- -5330# 207# 221 026323.299 54.873 - 35 128 93 221 Np x 29850# 200# 7607# 1# B- * 221 032045# 215# -0 56 139 83 222 Bi x 28729# 300# 7649# 1# B- 6243# 303# 222 030842# 322# - 54 138 84 222 Po x 22486.265 40.054 7674.005 0.180 B- 1533.239 43.071 222 024140.000 43.000 - 52 137 85 222 At x 20953.026 15.835 7677.387 0.071 B- 4580.820 15.955 222 022494.000 17.000 - 50 136 86 222 Rn 16372.206 1.950 7694.497 0.009 B- -5.900 7.703 222 017576.286 2.093 - 48 135 87 222 Fr x 16378.105 7.452 7690.947 0.034 B- 2057.917 8.682 222 017582.620 8.000 - 46 134 88 222 Ra 14320.188 4.454 7696.692 0.020 B- -2301.285 6.637 222 015373.355 4.781 - 44 133 89 222 Ac -a 16621.474 5.174 7682.802 0.023 B- -581.637 13.228 222 017843.887 5.554 - 42 132 90 222 Th -a 17203.111 12.279 7676.658 0.055 B- -4951# 74# 222 018468.300 13.182 - 40 131 91 222 Pa -a 22155# 72# 7651# 0# B- -2118# 89# 222 023784# 78# - 38 130 92 222 U -a 24272.827 51.994 7637.764 0.234 B- -6746# 202# 222 026057.953 55.817 - 36 129 93 222 Np x 31019# 196# 7604# 1# B- * 222 033300# 210# -0 57 140 83 223 Bi x 32137# 401# 7636# 2# B- 5058# 446# 223 034500# 430# - 55 139 84 223 Po x 27079# 196# 7655# 1# B- 3651# 196# 223 029070# 210# - 53 138 85 223 At x 23428.006 13.972 7668.055 0.063 B- 3038.267 16.013 223 025151.000 15.000 - 51 137 86 223 Rn 20389.739 7.822 7678.171 0.035 B- 2007.344 8.057 223 021889.285 8.397 - 49 136 87 223 Fr 18382.394 1.932 7683.664 0.009 B- 1149.085 0.848 223 019734.313 2.073 - 47 135 88 223 Ra 17233.309 2.090 7685.309 0.009 B- -592.573 7.128 223 018500.719 2.244 - 45 134 89 223 Ac -a 17825.882 7.110 7679.143 0.032 B- -1559.948 11.563 223 019136.872 7.632 - 43 133 90 223 Th -a 19385.831 9.212 7668.640 0.041 B- -2934.845 71.639 223 020811.546 9.889 - 41 132 91 223 Pa -a 22320.676 71.063 7651.971 0.319 B- -3516.330 100.506 223 023962.232 76.289 - 39 131 92 223 U -a 25837.006 71.119 7632.694 0.319 B- -4763# 208# 223 027737.168 76.349 - 37 130 93 223 Np x 30600# 196# 7608# 1# B- * 223 032850# 210# -0 58 141 83 224 Bi x 36830# 400# 7617# 2# B- 6920# 445# 224 039539# 429# - 56 140 84 224 Po x 29910# 196# 7644# 1# B- 2199# 197# 224 032110# 210# - 54 139 85 224 At x 27711.015 22.356 7650.735 0.100 B- 5265.917 24.415 224 029749.000 24.000 - 52 138 86 224 Rn 22445.098 9.814 7670.751 0.044 B- 696.482 14.875 224 024095.804 10.536 - 50 137 87 224 Fr x 21748.616 11.178 7670.367 0.050 B- 2922.699 11.324 224 023348.100 12.000 - 48 136 88 224 Ra 18825.917 1.813 7679.922 0.008 B- -1408.219 4.087 224 020210.453 1.945 - 46 135 89 224 Ac -a 20234.135 4.089 7670.143 0.018 B- 240.401 10.823 224 021722.239 4.389 - 44 134 90 224 Th -a 19993.734 10.120 7667.724 0.045 B- -3868.544 12.546 224 021464.157 10.864 - 42 133 91 224 Pa -a 23862.278 7.587 7646.961 0.034 B- -1859.974 24.329 224 025617.210 8.145 - 40 132 92 224 U -a 25722.252 23.171 7635.165 0.103 B- -6153# 197# 224 027613.974 24.875 - 38 131 93 224 Np x 31876# 196# 7604# 1# B- * 224 034220# 210# -0 57 141 84 225 Po x 34530# 298# 7626# 1# B- 4136# 422# 225 037070# 320# - 55 140 85 225 At x 30395# 298# 7641# 1# B- 3861# 298# 225 032630# 320# - 53 139 86 225 Rn 26534.141 11.140 7654.357 0.050 B- 2713.531 16.349 225 028485.574 11.958 - 51 138 87 225 Fr 23820.610 11.967 7662.940 0.053 B- 1827.501 12.158 225 025572.478 12.847 - 49 137 88 225 Ra 21993.109 2.596 7667.586 0.012 B- 355.763 5.007 225 023610.574 2.787 - 47 136 89 225 Ac 21637.346 4.758 7665.690 0.021 B- -672.781 6.658 225 023228.647 5.107 - 45 135 90 225 Th -a 22310.127 5.093 7659.222 0.023 B- -2030.598 71.170 225 023950.907 5.467 - 43 134 91 225 Pa -a 24340.725 71.012 7646.720 0.316 B- -3039.196 71.827 225 026130.844 76.234 - 41 133 92 225 U -a 27379.921 10.909 7629.736 0.048 B- -4207.783 72.440 225 029393.555 11.711 - 39 132 93 225 Np -a 31587.704 71.622 7607.557 0.318 B- * 225 033910.797 76.889 -0 58 142 84 226 Po x 37549# 401# 7614# 2# B- 2934# 499# 226 040310# 430# - 56 141 85 226 At x 34614# 298# 7624# 1# B- 5867# 298# 226 037160# 320# - 54 140 86 226 Rn 28747.192 10.477 7646.410 0.046 B- 1226.653 12.190 226 030861.382 11.247 - 52 139 87 226 Fr 27520.539 6.230 7648.376 0.028 B- 3852.715 6.523 226 029544.515 6.688 - 50 138 88 226 Ra 23667.824 1.933 7661.962 0.009 B- -641.440 3.274 226 025408.455 2.075 - 48 137 89 226 Ac 24309.264 3.100 7655.662 0.014 B- 1111.630 4.563 226 026097.069 3.328 - 46 136 90 226 Th 23197.634 4.481 7657.119 0.020 B- -2835.642 12.165 226 024903.686 4.810 - 44 135 91 226 Pa -a 26033.276 11.420 7641.110 0.051 B- -1295.593 17.228 226 027947.872 12.259 - 42 134 92 226 U -a 27328.869 12.999 7631.916 0.058 B- -5448# 89# 226 029338.749 13.955 - 40 133 93 226 Np -a 32777# 88# 7604# 0# B- * 226 035188# 95# -0 59 143 84 227 Po x 42281# 401# 7596# 2# B- 4797# 499# 227 045390# 430# - 57 142 85 227 At x 37483# 298# 7613# 1# B- 4597# 298# 227 040240# 320# - 55 141 86 227 Rn 32885.834 14.091 7630.050 0.062 B- 3203.388 15.276 227 035304.396 15.127 - 53 140 87 227 Fr 29682.445 5.898 7640.715 0.026 B- 2504.734 6.213 227 031865.417 6.332 - 51 139 88 227 Ra -n 27177.711 1.952 7648.303 0.009 B- 1328.132 2.265 227 029176.474 2.095 - 49 138 89 227 Ac 25849.580 1.927 7650.707 0.008 B- 44.757 0.830 227 027750.666 2.068 - 47 137 90 227 Th 25804.823 2.088 7647.458 0.009 B- -1026.375 7.437 227 027702.618 2.241 - 45 136 91 227 Pa -a 26831.198 7.420 7639.490 0.033 B- -2214.264 12.146 227 028804.477 7.965 - 43 135 92 227 U -a 29045.462 9.705 7626.289 0.043 B- -3516.618 73.135 227 031181.587 10.419 - 41 134 93 227 Np -a 32562.080 72.506 7607.351 0.319 B- -4208# 123# 227 034956.832 77.838 - 39 133 94 227 Pu x 36770# 100# 7585# 0# B- * 227 039474# 107# -0 58 143 85 228 At x 41684# 401# 7597# 2# B- 6441# 401# 228 044750# 430# - 56 142 86 228 Rn 35243.465 17.677 7621.645 0.078 B- 1859.244 18.916 228 037835.418 18.977 - 54 141 87 228 Fr 33384.221 6.732 7626.368 0.030 B- 4443.953 7.021 228 035839.437 7.226 - 52 140 88 228 Ra +a 28940.268 1.996 7642.428 0.009 B- 45.540 0.634 228 031068.657 2.142 - 50 139 89 228 Ac - 28894.728 2.094 7639.196 0.009 B- 2123.743 2.645 228 031019.767 2.247 - 48 138 90 228 Th 26770.984 1.807 7645.080 0.008 B- -2152.602 4.340 228 028739.835 1.940 - 46 137 91 228 Pa -a 28923.586 4.340 7632.207 0.019 B- -298.640 14.929 228 031050.748 4.659 - 44 136 92 228 U -a 29222.226 14.354 7627.466 0.063 B- -4373.468 52.545 228 031371.351 15.409 - 42 135 93 228 Np -a 33595.694 50.572 7604.853 0.222 B- -2491.677 58.346 228 036066.462 54.291 - 40 134 94 228 Pu -a 36087.370 29.143 7590.493 0.128 B- * 228 038741.387 31.286 -0 59 144 85 229 At x 44823# 401# 7585# 2# B- 5461# 401# 229 048120# 430# - 57 143 86 229 Rn x 39362.400 13.041 7605.622 0.057 B- 3694.138 13.967 229 042257.276 14.000 - 55 142 87 229 Fr 35668.262 5.001 7618.337 0.022 B- 3106.298 16.231 229 038291.455 5.368 - 53 141 88 229 Ra x 32561.963 15.441 7628.485 0.067 B- 1872.030 19.623 229 034956.707 16.576 - 51 140 89 229 Ac x 30689.933 12.109 7633.244 0.053 B- 1104.350 12.346 229 032947.000 13.000 - 49 139 90 229 Th 29585.583 2.405 7634.650 0.011 B- -311.325 3.715 229 031761.431 2.581 - 47 138 91 229 Pa 29896.908 3.280 7629.874 0.014 B- -1313.646 6.655 229 032095.652 3.521 - 45 137 92 229 U -a 31210.554 5.938 7620.721 0.026 B- -2569.122 87.031 229 033505.909 6.374 - 43 136 93 229 Np -a 33779.675 86.848 7606.086 0.379 B- -3615.915 100.792 229 036263.974 93.235 - 41 135 94 229 Pu -a 37395.590 51.176 7586.880 0.223 B- -4754.430 101.230 229 040145.819 54.939 - 39 134 95 229 Am -a 42150.020 87.348 7562.702 0.381 B- * 229 045249.909 93.772 -0 58 144 86 230 Rn x 42048# 196# 7596# 1# B- 2561# 196# 230 045140# 210# - 56 143 87 230 Fr 39486.768 6.541 7603.704 0.028 B- 4970.462 12.198 230 042390.791 7.022 - 54 142 88 230 Ra x 34516.306 10.296 7621.914 0.045 B- 677.924 18.888 230 037054.780 11.053 - 52 141 89 230 Ac x 33838.383 15.835 7621.460 0.069 B- 2975.789 15.882 230 036327.000 17.000 - 50 140 90 230 Th 30862.593 1.210 7630.996 0.005 B- -1311.014 2.833 230 033132.358 1.299 - 48 139 91 230 Pa 32173.607 3.038 7621.895 0.013 B- 558.605 4.592 230 034539.789 3.261 - 46 138 92 230 U -a 31615.002 4.509 7620.922 0.020 B- -3621.290 51.461 230 033940.102 4.841 - 44 137 93 230 Np -a 35236.291 51.288 7601.776 0.223 B- -1698.101 53.363 230 037827.716 55.059 - 42 136 94 230 Pu -a 36934.392 14.824 7590.991 0.064 B- -5998# 134# 230 039650.703 15.913 - 40 135 95 230 Am -a 42932# 133# 7562# 1# B- * 230 046089# 143# -0 59 145 86 231 Rn x 46454# 298# 7579# 1# B- 4373# 298# 231 049870# 320# - 57 144 87 231 Fr x 42080.575 7.731 7594.500 0.033 B- 3864.089 13.749 231 045175.357 8.300 - 55 143 88 231 Ra 38216.486 11.370 7607.841 0.049 B- 2453.636 17.301 231 041027.086 12.206 - 53 142 89 231 Ac x 35762.849 13.041 7615.076 0.056 B- 1946.959 13.098 231 038393.000 14.000 - 51 141 90 231 Th 33815.891 1.218 7620.118 0.005 B- 391.487 1.460 231 036302.853 1.308 - 49 140 91 231 Pa 33424.404 1.772 7618.426 0.008 B- -381.611 2.033 231 035882.575 1.902 - 47 139 92 231 U -a 33806.015 2.670 7613.387 0.012 B- -1818.498 50.577 231 036292.252 2.866 - 45 138 93 231 Np -a 35624.513 50.547 7602.128 0.219 B- -2684.492 55.333 231 038244.490 54.264 - 43 137 94 231 Pu -a 38309.005 22.549 7587.120 0.098 B- -4101# 301# 231 041126.410 24.206 - 41 136 95 231 Am x 42410# 300# 7566# 1# B- -4860# 424# 231 045529# 322# - 39 135 96 231 Cm x 47270# 300# 7542# 1# B- * 231 050746# 322# -0 58 145 87 232 Fr x 46072.834 13.972 7579.347 0.060 B- 5575.880 16.702 232 049461.224 15.000 - 56 144 88 232 Ra 40496.953 9.151 7600.009 0.039 B- 1342.534 15.931 232 043475.270 9.823 - 54 143 89 232 Ac x 39154.419 13.041 7602.424 0.056 B- 3707.635 13.118 232 042034.000 14.000 - 52 142 90 232 Th 35446.784 1.422 7615.033 0.006 B- -499.850 7.734 232 038053.689 1.526 - 50 141 91 232 Pa + 35946.633 7.645 7609.506 0.033 B- 1337.103 7.428 232 038590.300 8.207 - 48 140 92 232 U 34609.530 1.809 7611.897 0.008 B- -2750# 100# 232 037154.860 1.942 - 46 139 93 232 Np - 37360# 100# 7597# 0# B- -1004# 102# 232 040107# 107# - 44 138 94 232 Pu -a 38363.140 17.595 7588.974 0.076 B- -4976# 300# 232 041184.526 18.888 - 42 137 95 232 Am x 43340# 300# 7564# 1# B- -2973# 362# 232 046527# 322# - 40 136 96 232 Cm -a 46312# 202# 7548# 1# B- * 232 049718# 217# -0 59 146 87 233 Fr x 48920.051 19.561 7569.239 0.084 B- 4585.991 21.369 233 052517.838 21.000 - 57 145 88 233 Ra 44334.060 8.603 7585.564 0.037 B- 3026.027 15.623 233 047594.573 9.235 - 55 144 89 233 Ac x 41308.033 13.041 7595.193 0.056 B- 2576.318 13.118 233 044346.000 14.000 - 53 143 90 233 Th 38731.715 1.425 7602.893 0.006 B- 1242.243 1.122 233 041580.208 1.529 - 51 142 91 233 Pa 37489.472 1.336 7604.866 0.006 B- 570.296 1.975 233 040246.605 1.434 - 49 141 92 233 U 36919.176 2.255 7603.956 0.010 B- -1029.415 51.005 233 039634.367 2.420 - 47 140 93 233 Np -a 37948.590 50.981 7596.181 0.219 B- -2103.179 71.642 233 040739.489 54.729 - 45 139 94 233 Pu -a 40051.769 50.351 7583.796 0.216 B- -3211# 113# 233 042997.345 54.054 - 43 138 95 233 Am -a 43263# 102# 7567# 0# B- -4031# 124# 233 046445# 109# - 41 137 96 233 Cm -a 47294.006 71.547 7545.998 0.307 B- -5567# 235# 233 050772.206 76.809 - 39 136 97 233 Bk -a 52861# 224# 7519# 1# B- * 233 056748# 240# -0 58 146 88 234 Ra x 46930.629 8.383 7576.543 0.036 B- 2089.439 16.294 234 050382.104 9.000 - 56 145 89 234 Ac x 44841.190 13.972 7582.129 0.060 B- 4228.181 14.210 234 048139.000 15.000 - 54 144 90 234 Th +a 40613.009 2.589 7596.855 0.011 B- 274.088 3.172 234 043599.860 2.779 - 52 143 91 234 Pa IT 40338.921 4.094 7594.683 0.017 B- 2193.896 4.000 234 043305.615 4.395 - 50 142 92 234 U 38145.025 1.130 7600.715 0.005 B- -1809.846 8.321 234 040950.370 1.213 - 48 141 93 234 Np - 39954.871 8.397 7589.637 0.036 B- -395.100 10.752 234 042893.320 9.014 - 46 140 94 234 Pu -a 40349.971 6.798 7584.605 0.029 B- -4111# 159# 234 043317.478 7.298 - 44 139 95 234 Am -a 44461# 159# 7564# 1# B- -2263# 159# 234 047731# 170# - 42 138 96 234 Cm -a 46724.633 17.394 7550.677 0.074 B- -6731# 143# 234 050160.959 18.673 - 40 137 97 234 Bk -a 53455# 142# 7519# 1# B- * 234 057387# 153# -0 59 147 88 235 Ra x 51130# 300# 7561# 1# B- 3773# 300# 235 054890# 322# - 57 146 89 235 Ac x 47357.155 13.972 7573.504 0.059 B- 3339.406 19.113 235 050840.000 15.000 - 55 145 90 235 Th x 44017.749 13.041 7584.385 0.055 B- 1728.853 19.113 235 047255.000 14.000 - 53 144 91 235 Pa x 42288.896 13.972 7588.413 0.059 B- 1370.050 14.017 235 045399.000 15.000 - 51 143 92 235 U 40918.846 1.117 7590.914 0.005 B- -124.262 0.852 235 043928.190 1.199 - 49 142 93 235 Np 41043.108 1.389 7587.056 0.006 B- -1139.302 20.499 235 044061.591 1.491 - 47 141 94 235 Pu -a 42182.410 20.521 7578.879 0.087 B- -2443.019 56.045 235 045284.682 22.030 - 45 140 95 235 Am -a 44625.429 52.192 7565.154 0.222 B- -3408# 208# 235 047907.371 56.030 - 43 139 96 235 Cm -a 48034# 201# 7547# 1# B- -4670# 448# 235 051567# 216# - 41 138 97 235 Bk x 52704# 401# 7524# 2# B- * 235 056580# 430# -0 58 147 89 236 Ac x 51220.992 38.191 7559.242 0.162 B- 4965.795 40.667 236 054988.000 41.000 - 56 146 90 236 Th x 46255.198 13.972 7576.968 0.059 B- 921.248 19.760 236 049657.000 15.000 - 54 145 91 236 Pa x 45333.950 13.972 7577.557 0.059 B- 2889.306 14.017 236 048668.000 15.000 - 52 144 92 236 U 42444.644 1.113 7586.484 0.005 B- -933.534 50.415 236 045566.201 1.194 - 50 143 93 236 Np IT 43378.178 50.421 7579.214 0.214 B- 476.585 50.389 236 046568.392 54.129 - 48 142 94 236 Pu 42901.593 1.811 7577.918 0.008 B- -3139# 112# 236 046056.756 1.944 - 46 141 95 236 Am -a 46041# 112# 7561# 0# B- -1814# 113# 236 049427# 120# - 44 140 96 236 Cm -a 47855.045 18.315 7550.299 0.078 B- -5687# 401# 236 051374.506 19.662 - 42 139 97 236 Bk x 53542# 401# 7523# 2# B- * 236 057480# 430# -0 59 148 89 237 Ac x 54020# 400# 7550# 2# B- 4065# 400# 237 057993# 429# - 57 147 90 237 Th x 49955.092 15.835 7563.443 0.067 B- 2427.473 20.514 237 053629.000 17.000 - 55 146 91 237 Pa x 47527.619 13.041 7570.384 0.055 B- 2137.425 13.096 237 051023.000 14.000 - 53 145 92 237 U 45390.194 1.203 7576.102 0.005 B- 518.534 0.520 237 048728.380 1.291 - 51 144 93 237 Np 44871.659 1.120 7574.989 0.005 B- -220.063 1.294 237 048171.710 1.202 - 49 143 94 237 Pu 45091.722 1.697 7570.759 0.007 B- -1478# 59# 237 048407.957 1.822 - 47 142 95 237 Am -a 46570# 59# 7561# 0# B- -2677# 93# 237 049995# 64# - 45 141 96 237 Cm -a 49247.085 70.960 7546.624 0.299 B- -3941# 235# 237 052868.923 76.178 - 43 140 97 237 Bk -a 53188# 224# 7527# 1# B- -4751# 241# 237 057100# 241# - 41 139 98 237 Cf -a 57938.921 87.287 7503.347 0.368 B- * 237 062199.993 93.706 -0 58 148 90 238 Th +a 52525# 283# 7555# 1# B- 1631# 284# 238 056388# 304# - 56 147 91 238 Pa x 50894.038 15.835 7558.344 0.067 B- 3586.255 15.906 238 054637.000 17.000 - 54 146 92 238 U 47307.783 1.493 7570.125 0.006 B- -146.874 1.201 238 050786.996 1.602 - 52 145 93 238 Np -n 47454.656 1.138 7566.221 0.005 B- 1291.443 0.457 238 050944.671 1.221 - 50 144 94 238 Pu 46163.213 1.139 7568.360 0.005 B- -2258.273 50.688 238 049558.250 1.222 - 48 143 95 238 Am -a 48421.487 50.700 7555.584 0.213 B- -1023.701 52.145 238 051982.607 54.428 - 46 142 96 238 Cm -a 49445.188 12.234 7547.996 0.051 B- -4771# 255# 238 053081.595 13.133 - 44 141 97 238 Bk -a 54216# 255# 7525# 1# B- -3061# 392# 238 058203# 274# - 42 140 98 238 Cf x 57278# 298# 7509# 1# B- * 238 061490# 320# -0 59 149 90 239 Th x 56450# 400# 7541# 2# B- 3113# 445# 239 060602# 429# - 57 148 91 239 Pa x 53337# 196# 7550# 1# B- 2765# 196# 239 057260# 210# - 55 147 92 239 U -n 50572.718 1.503 7558.561 0.006 B- 1261.661 1.493 239 054292.048 1.613 - 53 146 93 239 Np 49311.057 1.311 7560.567 0.005 B- 722.774 0.930 239 052937.599 1.407 - 51 145 94 239 Pu 48588.282 1.113 7560.318 0.005 B- -802.142 1.664 239 052161.669 1.195 - 49 144 95 239 Am -a 49390.424 1.982 7553.688 0.008 B- -1756.602 54.058 239 053022.803 2.128 - 47 143 96 239 Cm -a 51147.025 54.047 7543.065 0.226 B- -3103# 214# 239 054908.593 58.022 - 45 142 97 239 Bk -a 54250# 207# 7527# 1# B- -4019# 294# 239 058240# 222# - 43 141 98 239 Cf -a 58269# 209# 7507# 1# B- -5287# 364# 239 062554# 224# - 41 140 99 239 Es x 63556# 298# 7481# 1# B- * 239 068230# 320# -0 58 149 91 240 Pa x 56910# 200# 7538# 1# B- 4194# 200# 240 061095# 215# - 56 148 92 240 U 52715.505 2.553 7551.770 0.011 B- 399.233 17.083 240 056592.425 2.740 - 54 147 93 240 Np 52316.272 17.032 7550.173 0.071 B- 2190.891 17.015 240 056163.830 18.284 - 52 146 94 240 Pu 50125.380 1.106 7556.042 0.005 B- -1384.789 13.788 240 053811.812 1.187 - 50 145 95 240 Am +n 51510.169 13.832 7547.013 0.058 B- -214.137 13.897 240 055298.444 14.849 - 48 144 96 240 Cm 51724.306 1.906 7542.861 0.008 B- -3940# 150# 240 055528.329 2.046 - 46 143 97 240 Bk - 55664# 150# 7523# 1# B- -2327# 151# 240 059758# 161# - 44 142 98 240 Cf -a 57990.944 18.700 7510.230 0.078 B- -6208# 401# 240 062255.842 20.075 - 42 141 99 240 Es x 64199# 401# 7481# 2# B- * 240 068920# 430# -0 59 150 91 241 Pa x 59640# 300# 7528# 1# B- 3443# 358# 241 064026# 322# - 57 149 92 241 U x 56197# 196# 7539# 1# B- 1937# 208# 241 060330# 210# - 55 148 93 241 Np + 54260.175 70.719 7544.270 0.293 B- 1305.000 70.711 241 058250.697 75.920 - 53 147 94 241 Pu 52955.175 1.106 7546.439 0.005 B- 20.780 0.166 241 056849.722 1.187 - 51 146 95 241 Am 52934.395 1.114 7543.278 0.005 B- -767.434 1.168 241 056827.413 1.195 - 49 145 96 241 Cm 53701.830 1.608 7536.848 0.007 B- -2330# 200# 241 057651.288 1.726 - 47 144 97 241 Bk - 56032# 200# 7524# 1# B- -3295# 260# 241 060153# 215# - 45 143 98 241 Cf -a 59327# 166# 7507# 1# B- -4537# 280# 241 063690# 178# - 43 142 99 241 Es -a 63863# 225# 7485# 1# B- -5263# 374# 241 068560# 242# - 41 141 100 241 Fm x 69126# 298# 7460# 1# B- * 241 074210# 320# -0 58 150 92 242 U +a 58620# 201# 7532# 1# B- 1203# 283# 242 062931# 215# - 56 149 93 242 Np + 57416.932 200.004 7533.403 0.826 B- 2700.000 200.000 242 061639.615 214.713 - 54 148 94 242 Pu 54716.932 1.245 7541.327 0.005 B- -751.140 0.708 242 058741.045 1.336 - 52 147 95 242 Am -n 55468.072 1.119 7534.991 0.005 B- 664.309 0.414 242 059547.428 1.200 - 50 146 96 242 Cm 54803.764 1.142 7534.503 0.005 B- -2930# 200# 242 058834.263 1.225 - 48 145 97 242 Bk - 57734# 200# 7519# 1# B- -1653# 200# 242 061980# 215# - 46 144 98 242 Cf -a 59386.966 12.892 7509.098 0.053 B- -5414# 256# 242 063754.533 13.840 - 44 143 99 242 Es -a 64801# 256# 7483# 1# B- -3598# 475# 242 069567# 275# - 42 142 100 242 Fm x 68400# 401# 7465# 2# B- * 242 073430# 430# -0 59 151 92 243 U x 62360# 300# 7518# 1# B- 2484# 302# 243 066946# 322# - 57 150 93 243 Np IT 59876# 32# 7525# 0# B- 2121# 32# 243 064279# 34# - 55 149 94 243 Pu 57754.602 2.542 7531.008 0.010 B- 579.556 2.622 243 062002.119 2.728 - 53 148 95 243 Am 57175.046 1.388 7530.173 0.006 B- -6.952 1.569 243 061379.940 1.490 - 51 147 96 243 Cm -a 57181.998 1.496 7526.925 0.006 B- -1507.695 4.506 243 061387.403 1.606 - 49 146 97 243 Bk -a 58689.693 4.524 7517.501 0.019 B- -2300# 114# 243 063005.980 4.857 - 47 145 98 243 Cf -a 60990# 114# 7505# 0# B- -3757# 236# 243 065475# 123# - 45 144 99 243 Es -a 64747# 207# 7486# 1# B- -4640# 298# 243 069509# 222# - 43 143 100 243 Fm -a 69387# 215# 7464# 1# B- * 243 074490# 231# -0 58 151 93 244 Np x 63202# 298# 7514# 1# B- 3396# 298# 244 067850# 320# - 56 150 94 244 Pu 59806.028 2.346 7524.815 0.010 B- -73.168 2.686 244 064204.415 2.518 - 54 149 95 244 Am + 59879.196 1.492 7521.308 0.006 B- 1427.300 1.000 244 064282.964 1.601 - 52 148 96 244 Cm -a 58451.896 1.107 7523.952 0.005 B- -2261.989 14.357 244 062750.694 1.188 - 50 147 97 244 Bk -a 60713.885 14.399 7511.475 0.059 B- -764.294 14.572 244 065179.039 15.457 - 48 146 98 244 Cf 61478.179 2.618 7505.136 0.011 B- -4547# 181# 244 065999.543 2.810 - 46 145 99 244 Es -a 66026# 181# 7483# 1# B- -2940# 271# 244 070881# 195# - 44 144 100 244 Fm -a 68966# 201# 7468# 1# B- * 244 074038# 216# -0 59 152 93 245 Np x 65890# 300# 7505# 1# B- 2712# 300# 245 070736# 322# - 57 151 94 245 Pu -n 63178.179 13.620 7513.281 0.056 B- 1277.710 13.733 245 067824.568 14.621 - 55 150 95 245 Am +a 61900.469 1.887 7515.303 0.008 B- 895.889 1.549 245 066452.890 2.025 - 53 149 96 245 Cm 61004.580 1.150 7515.767 0.005 B- -809.256 1.496 245 065491.113 1.234 - 51 148 97 245 Bk -a 61813.836 1.793 7509.270 0.007 B- -1571.374 2.586 245 066359.885 1.924 - 49 147 98 245 Cf 63385.210 2.428 7499.663 0.010 B- -2981# 200# 245 068046.825 2.606 - 47 146 99 245 Es -a 66366# 200# 7484# 1# B- -3821# 279# 245 071247# 215# - 45 145 100 245 Fm -a 70187# 195# 7466# 1# B- -5085# 362# 245 075349# 209# - 43 144 101 245 Md -a 75272# 305# 7442# 1# B- * 245 080808# 328# -0 58 152 94 246 Pu 65394.801 14.985 7506.539 0.061 B- 401# 14# 246 070204.209 16.087 - 56 151 95 246 Am IT 64994# 18# 7505# 0# B- 2377# 18# 246 069774# 19# - 54 150 96 246 Cm 62616.967 1.526 7511.471 0.006 B- -1350.000 60.000 246 067222.082 1.638 - 52 149 97 246 Bk - 63966.967 60.019 7502.803 0.244 B- -123.325 60.020 246 068671.367 64.433 - 50 148 98 246 Cf 64090.292 1.515 7499.121 0.006 B- -3810# 224# 246 068803.762 1.626 - 48 147 99 246 Es -a 67901# 224# 7480# 1# B- -2288# 224# 246 072894# 240# - 46 146 100 246 Fm -a 70188.833 15.333 7467.970 0.062 B- -5926# 260# 246 075350.815 16.460 - 44 145 101 246 Md -a 76115# 259# 7441# 1# B- * 246 081713# 278# -0 59 153 94 247 Pu x 69108# 196# 7494# 1# B- 1954# 220# 247 074190# 210# - 57 152 95 247 Am + 67153# 100# 7499# 0# B- 1620# 100# 247 072092# 107# - 55 151 96 247 Cm 65533.143 3.797 7501.931 0.015 B- 43.581 6.324 247 070352.726 4.076 - 53 150 97 247 Bk -a 65489.562 5.189 7498.940 0.021 B- -614.341 16.188 247 070305.940 5.570 - 51 149 98 247 Cf +a 66103.903 15.334 7493.285 0.062 B- -2474.485 24.760 247 070965.462 16.461 - 49 148 99 247 Es +a 68578.388 19.441 7480.100 0.079 B- -3094# 116# 247 073621.932 20.870 - 47 147 100 247 Fm +a 71673# 115# 7464# 0# B- -4264# 237# 247 076944# 123# - 45 146 101 247 Md -a 75937# 207# 7444# 1# B- * 247 081521# 222# -0 58 153 95 248 Am + 70563# 200# 7487# 1# B- 3170# 200# 248 075752# 215# - 56 152 96 248 Cm 67392.755 2.358 7496.728 0.010 B- -687# 71# 248 072349.101 2.531 - 54 151 97 248 Bk IT 68080# 71# 7491# 0# B- 842# 71# 248 073087# 76# - 52 150 98 248 Cf -a 67238.012 5.121 7491.043 0.021 B- -3061# 53# 248 072182.978 5.497 - 50 149 99 248 Es -a 70299# 52# 7476# 0# B- -1599# 53# 248 075469# 56# - 48 148 100 248 Fm 71897.857 8.497 7465.944 0.034 B- -5250# 238# 248 077185.528 9.122 - 46 147 101 248 Md -a 77148# 237# 7442# 1# B- -3473# 327# 248 082822# 255# - 44 146 102 248 No -a 80621# 224# 7424# 1# B- * 248 086550# 241# -0 59 154 95 249 Am x 73104# 298# 7479# 1# B- 2353# 298# 249 078480# 320# - 57 153 96 249 Cm -n 70750.702 2.371 7485.550 0.010 B- 904.317 2.594 249 075954.006 2.545 - 55 152 97 249 Bk + 69846.384 1.249 7486.040 0.005 B- 123.600 0.400 249 074983.182 1.340 - 53 151 98 249 Cf 69722.784 1.183 7483.394 0.005 B- -1452# 30# 249 074850.491 1.270 - 51 150 99 249 Es -a 71175# 30# 7474# 0# B- -2344# 31# 249 076409# 32# - 49 149 100 249 Fm 73519.188 6.212 7461.864 0.025 B- -3713# 201# 249 078926.098 6.668 - 47 148 101 249 Md -a 77232# 201# 7444# 1# B- -4550# 344# 249 082912# 216# - 45 147 102 249 No -a 81782# 279# 7422# 1# B- * 249 087797# 300# -0 58 154 96 250 Cm -nn 72989.594 10.274 7478.938 0.041 B- 39.616 10.894 250 078357.556 11.029 - 56 153 97 250 Bk +a 72949.978 3.719 7475.967 0.015 B- 1779.587 3.386 250 078315.027 3.992 - 54 152 98 250 Cf -a 71170.391 1.538 7479.956 0.006 B- -2055# 100# 250 076404.561 1.651 - 52 151 99 250 Es - 73225# 100# 7469# 0# B- -847# 100# 250 078611# 107# - 50 150 100 250 Fm 74072.243 7.888 7462.090 0.032 B- -4558# 301# 250 079519.828 8.468 - 48 149 101 250 Md -a 78630# 301# 7441# 1# B- -2933# 362# 250 084413# 323# - 46 148 102 250 No -a 81564# 201# 7426# 1# B- * 250 087562# 215# -0 59 155 96 251 Cm + 76648.018 22.698 7466.722 0.090 B- 1420.000 20.000 251 082285.036 24.367 - 57 154 97 251 Bk + 75228.018 10.734 7469.263 0.043 B- 1093.000 10.000 251 080760.603 11.523 - 55 153 98 251 Cf -a 74135.018 3.901 7470.500 0.016 B- -377.259 7.057 251 079587.219 4.187 - 53 152 99 251 Es -a 74512.277 5.994 7465.881 0.024 B- -1441.641 16.342 251 079992.224 6.434 - 51 151 100 251 Fm +a 75953.919 15.203 7457.020 0.061 B- -3012.825 24.271 251 081539.889 16.320 - 49 150 101 251 Md +a 78966.744 18.919 7441.900 0.075 B- -3882# 116# 251 084774.291 20.310 - 47 149 102 251 No IT 82849# 114# 7423# 0# B- -4879# 319# 251 088942# 123# - 45 148 103 251 Lr x 87728# 298# 7401# 1# B- * 251 094180# 320# -0 60 156 96 252 Cm x 79056# 298# 7460# 1# B- 521# 359# 252 084870# 320# - 58 155 97 252 Bk + 78535# 200# 7459# 1# B- 2500# 200# 252 084310# 215# - 56 154 98 252 Cf -a 76034.617 2.358 7465.347 0.009 B- -1260.000 50.000 252 081626.523 2.531 - 54 153 99 252 Es - 77294.617 50.056 7457.242 0.199 B- 478.990 50.351 252 082979.189 53.736 - 52 152 100 252 Fm -a 76815.627 5.498 7456.038 0.022 B- -3695# 130# 252 082464.972 5.902 - 50 151 101 252 Md IT 80510# 130# 7438# 1# B- -2361# 131# 252 086432# 140# - 48 150 102 252 No 82871.427 9.292 7425.798 0.037 B- -5866# 238# 252 088966.141 9.975 - 46 149 103 252 Lr -a 88737# 238# 7399# 1# B- * 252 095263# 255# -0 59 156 97 253 Bk -a 80929# 359# 7451# 1# B- 1627# 359# 253 086880# 385# - 57 155 98 253 Cf -a 79301.567 4.257 7454.829 0.017 B- 291.030 4.385 253 085133.738 4.570 - 55 154 99 253 Es -a 79010.538 1.250 7452.887 0.005 B- -335.202 2.713 253 084821.305 1.341 - 53 153 100 253 Fm -a 79345.740 2.932 7448.470 0.012 B- -1827# 31# 253 085181.160 3.148 - 51 152 101 253 Md -a 81173# 31# 7438# 0# B- -3186# 32# 253 087143# 34# - 49 151 102 253 No 84358.735 6.912 7422.471 0.027 B- -4217# 202# 253 090562.831 7.420 - 47 150 103 253 Lr -a 88575# 202# 7403# 1# B- -4982# 457# 253 095089# 217# - 45 149 104 253 Rf -a 93557# 410# 7380# 2# B- * 253 100438# 440# -0 60 157 97 254 Bk x 84393# 298# 7440# 1# B- 3052# 298# 254 090600# 320# - 58 156 98 254 Cf -a 81341.401 11.462 7449.225 0.045 B- -649.193 12.113 254 087323.590 12.304 - 56 155 99 254 Es -a 81990.594 4.010 7443.589 0.016 B- 1087.800 3.202 254 088020.527 4.304 - 54 154 100 254 Fm -a 80902.794 2.414 7444.792 0.010 B- -2550# 100# 254 086852.726 2.591 - 52 153 101 254 Md - 83453# 100# 7432# 0# B- -1271# 100# 254 089590# 107# - 50 152 102 254 No 84723.347 9.658 7423.590 0.038 B- -5148# 301# 254 090954.259 10.367 - 48 151 103 254 Lr -a 89871# 301# 7400# 1# B- -3327# 414# 254 096481# 323# - 46 150 104 254 Rf -a 93199# 283# 7384# 1# B- * 254 100053# 304# -0 59 157 98 255 Cf + 84809# 200# 7438# 1# B- 720# 200# 255 091047# 215# - 57 156 99 255 Es -a 84089.274 10.817 7437.821 0.042 B- 289.620 10.247 255 090273.553 11.612 - 55 155 100 255 Fm -a 83799.654 4.291 7435.888 0.017 B- -1043.416 7.747 255 089962.633 4.607 - 53 154 101 255 Md -a 84843.070 6.553 7428.729 0.026 B- -1964.164 16.281 255 091082.787 7.035 - 51 153 102 255 No x 86807.234 14.904 7417.958 0.058 B- -3140.066 23.138 255 093191.404 16.000 - 49 152 103 255 Lr x 89947.300 17.698 7402.576 0.069 B- -4382# 116# 255 096562.404 19.000 - 47 151 104 255 Rf -a 94330# 115# 7382# 0# B- -5263# 377# 255 101267# 123# - 45 150 105 255 Db -a 99593# 359# 7359# 1# B- * 255 106918# 385# -0 60 158 98 256 Cf -a 87041# 314# 7432# 1# B- -146# 330# 256 093442# 338# - 58 157 99 256 Es + 87187# 100# 7428# 0# B- 1700# 100# 256 093599# 108# - 56 156 100 256 Fm -a 85486.817 5.600 7431.780 0.022 B- -1969# 123# 256 091773.878 6.012 - 54 155 101 256 Md IT 87456# 122# 7421# 0# B- -366# 123# 256 093888# 132# - 52 154 102 256 No -a 87822.062 7.743 7416.546 0.030 B- -3924.536 83.264 256 094280.866 8.312 - 50 153 103 256 Lr x 91746.598 82.903 7398.160 0.324 B- -2475.451 84.802 256 098494.029 89.000 - 48 152 104 256 Rf -a 94222.049 17.848 7385.434 0.070 B- -6276# 241# 256 101151.535 19.160 - 46 151 105 256 Db -a 100498# 240# 7358# 1# B- * 256 107889# 258# -0 59 158 99 257 Es -a 89403# 411# 7422# 2# B- 813# 411# 257 095979# 441# - 57 157 100 257 Fm -a 88590.033 4.486 7422.194 0.017 B- -403.020 4.715 257 095105.317 4.815 - 55 156 101 257 Md -a 88993.053 1.601 7417.582 0.006 B- -1254.202 6.661 257 095537.977 1.718 - 53 155 102 257 No -a 90247.256 6.678 7409.657 0.026 B- -2418# 45# 257 096884.419 7.169 - 51 154 103 257 Lr -a 92665# 44# 7397# 0# B- -3201# 45# 257 099480# 47# - 49 153 104 257 Rf -a 95866.427 10.817 7381.704 0.042 B- -4340# 203# 257 102916.848 11.612 - 47 152 105 257 Db -a 100207# 203# 7362# 1# B- * 257 107576# 218# -0 60 159 99 258 Es x 92702# 401# 7412# 2# B- 2276# 448# 258 099520# 430# - 58 158 100 258 Fm -a 90426# 200# 7418# 1# B- -1260# 200# 258 097077# 215# - 56 157 101 258 Md -a 91686.792 4.419 7409.675 0.017 B- 209# 100# 258 098429.825 4.743 - 54 156 102 258 No -a 91478# 100# 7407# 0# B- -3304# 143# 258 098205# 107# - 52 155 103 258 Lr -a 94782# 102# 7392# 0# B- -1559# 107# 258 101753# 109# - 50 154 104 258 Rf -a 96341.036 31.967 7382.538 0.124 B- -5456# 307# 258 103426.362 34.317 - 48 153 105 258 Db -a 101797# 305# 7358# 1# B- -3447# 513# 258 109284# 328# - 46 152 106 258 Sg -a 105244# 413# 7342# 2# B- * 258 112984# 443# -0 59 159 100 259 Fm -a 93704# 283# 7407# 1# B- 80# 346# 259 100596# 304# - 57 158 101 259 Md -a 93624# 200# 7405# 1# B- -454# 200# 259 100510# 215# - 55 157 102 259 No -a 94078.569 6.589 7399.974 0.025 B- -1773# 71# 259 100997.503 7.073 - 53 156 103 259 Lr -a 95852# 71# 7390# 0# B- -2510# 101# 259 102901# 76# - 51 155 104 259 Rf -a 98362# 72# 7377# 0# B- -3629# 90# 259 105596# 78# - 49 154 105 259 Db -a 101991.016 53.040 7360.362 0.205 B- -4529# 126# 259 109491.865 56.940 - 47 153 106 259 Sg -a 106520# 115# 7340# 0# B- * 259 114353# 123# -0 60 160 100 260 Fm -a 95766# 435# 7402# 2# B- -786# 537# 260 102809# 467# - 58 159 101 260 Md -a 96552# 316# 7396# 1# B- 940# 374# 260 103653# 340# - 56 158 102 260 No -a 95612# 200# 7397# 1# B- -2665# 235# 260 102643# 215# - 54 157 103 260 Lr -a 98277# 124# 7383# 0# B- -870# 236# 260 105504# 133# - 52 156 104 260 Rf -a 99147# 200# 7377# 1# B- -4526# 221# 260 106439# 215# - 50 155 105 260 Db -a 103673# 93# 7357# 0# B- -2875# 95# 260 111297# 100# - 48 154 106 260 Sg -a 106547.552 20.536 7342.562 0.079 B- -6776# 246# 260 114383.508 22.045 - 46 153 107 260 Bh -a 113323# 245# 7313# 1# B- * 260 121658# 263# -0 59 160 101 261 Md -a 98578# 509# 7391# 2# B- 123# 547# 261 105828# 546# - 57 159 102 261 No -a 98455# 200# 7388# 1# B- -1103# 283# 261 105696# 215# - 55 158 103 261 Lr -a 99558# 200# 7381# 1# B- -1761# 206# 261 106880# 215# - 53 157 104 261 Rf -a 101318.594 50.444 7371.384 0.193 B- -2990# 121# 261 108769.990 54.153 - 51 156 105 261 Db -a 104308# 110# 7357# 0# B- -3697# 112# 261 111980# 118# - 49 155 106 261 Sg -a 108005.043 18.494 7339.770 0.071 B- -5128# 210# 261 115948.188 19.853 - 47 154 107 261 Bh -a 113133# 209# 7317# 1# B- * 261 121454# 224# -0 60 161 101 262 Md -a 101627# 500# 7382# 2# B- 1526# 617# 262 109101# 537# - 58 160 102 262 No -a 100101# 361# 7385# 1# B- -2000# 412# 262 107463# 387# - 56 159 103 262 Lr -a 102102# 200# 7374# 1# B- -291# 300# 262 109611# 215# - 54 158 104 262 Rf -a 102393# 224# 7370# 1# B- -3861# 265# 262 109923# 240# - 52 157 105 262 Db -a 106253# 143# 7352# 1# B- -2112# 147# 262 114068# 154# - 50 156 106 262 Sg -a 108365.771 35.411 7341.185 0.135 B- -6176# 308# 262 116335.446 38.015 - 48 155 107 262 Bh -a 114541# 306# 7315# 1# B- * 262 122965# 328# -0 59 161 102 263 No -a 103129# 490# 7376# 2# B- -600# 566# 263 110714# 526# - 57 160 103 263 Lr -a 103729# 283# 7371# 1# B- -1027# 322# 263 111358# 304# - 55 159 104 263 Rf -a 104756# 153# 7364# 1# B- -2355# 227# 263 112460# 164# - 53 158 105 263 Db -a 107111# 168# 7352# 1# B- -3079# 193# 263 114988# 181# - 51 157 106 263 Sg -a 110190# 95# 7337# 0# B- -4306# 319# 263 118294# 102# - 49 156 107 263 Bh -a 114496# 305# 7318# 1# B- -5182# 329# 263 122916# 327# - 47 155 108 263 Hs -a 119678# 125# 7295# 0# B- * 263 128480# 134# -0 60 162 102 264 No -a 105011# 591# 7371# 2# B- -1366# 734# 264 112734# 634# - 58 161 103 264 Lr -a 106377# 436# 7363# 2# B- 300# 566# 264 114200# 468# - 56 160 104 264 Rf -a 106077# 361# 7361# 1# B- -3285# 431# 264 113878# 387# - 54 159 105 264 Db -a 109362# 235# 7346# 1# B- -1420# 368# 264 117405# 253# - 52 158 106 264 Sg -a 110782# 283# 7338# 1# B- -5276# 334# 264 118929# 304# - 50 157 107 264 Bh -a 116058# 177# 7315# 1# B- -3506# 180# 264 124593# 190# - 48 156 108 264 Hs -a 119563.222 28.881 7298.375 0.109 B- * 264 128356.405 31.005 -0 59 162 103 265 Lr -a 108233# 547# 7359# 2# B- -457# 655# 265 116193# 587# - 57 161 104 265 Rf -a 108690# 361# 7354# 1# B- -1793# 424# 265 116683# 387# - 55 160 105 265 Db -a 110483# 224# 7344# 1# B- -2312# 255# 265 118608# 240# - 53 159 106 265 Sg -a 112794# 123# 7333# 0# B- -3621# 264# 265 121090# 132# - 51 158 107 265 Bh -a 116415# 234# 7316# 1# B- -4485# 235# 265 124977# 251# - 49 157 108 265 Hs -a 120900.283 23.958 7296.247 0.090 B- -5778# 452# 265 129791.799 25.719 - 47 156 109 265 Mt -a 126678# 451# 7271# 2# B- * 265 135995# 484# -0 60 163 103 266 Lr -a 111622# 583# 7349# 2# B- 1546# 749# 266 119831# 626# - 58 162 104 266 Rf -a 110076# 469# 7352# 2# B- -2660# 548# 266 118172# 504# - 56 161 105 266 Db -a 112737# 283# 7339# 1# B- -881# 374# 266 121028# 304# - 54 160 106 266 Sg -a 113618# 245# 7332# 1# B- -4487# 294# 266 121973# 263# - 52 159 107 266 Bh -a 118104# 163# 7313# 1# B- -3032# 167# 266 126790# 175# - 50 158 108 266 Hs -a 121136.373 38.695 7298.273 0.145 B- -6826# 309# 266 130045.252 41.540 - 48 157 109 266 Mt -a 127962# 307# 7270# 1# B- * 266 137373# 329# -0 59 163 104 267 Rf -a 113444# 575# 7342# 2# B- -630# 707# 267 121787# 617# - 57 162 105 267 Db -a 114074# 412# 7336# 2# B- -1732# 486# 267 122464# 443# - 55 161 106 267 Sg -a 115806# 257# 7327# 1# B- -2960# 367# 267 124322# 276# - 53 160 107 267 Bh -a 118766# 263# 7313# 1# B- -3887# 279# 267 127500# 282# - 51 159 108 267 Hs -a 122653# 96# 7295# 0# B- -5138# 512# 267 131673# 103# - 49 158 109 267 Mt -a 127791# 503# 7273# 2# B- -6089# 521# 267 137189# 540# - 47 157 110 267 Ds -a 133880# 135# 7248# 1# B- * 267 143726# 145# -0 60 164 104 268 Rf -a 115476# 662# 7337# 2# B- -1586# 848# 268 123968# 711# - 58 163 105 268 Db -a 117062# 529# 7328# 2# B- 260# 707# 268 125671# 568# - 56 162 106 268 Sg -a 116802# 469# 7326# 2# B- -4005# 605# 268 125392# 504# - 54 161 107 268 Bh -a 120807# 381# 7308# 1# B- -2023# 475# 268 129691# 409# - 52 160 108 268 Hs -a 122830# 283# 7298# 1# B- -6321# 367# 268 131863# 304# - 50 159 109 268 Mt -a 129151# 233# 7271# 1# B- -4497# 381# 268 138649# 250# - 48 158 110 268 Ds -a 133648# 301# 7252# 1# B- * 268 143477# 324# -0 59 164 105 269 Db -a 119148# 624# 7323# 2# B- -614# 722# 269 127911# 669# - 57 163 106 269 Sg -a 119763# 364# 7318# 1# B- -1715# 522# 269 128570# 391# - 55 162 107 269 Bh -a 121478# 374# 7309# 1# B- -3086# 394# 269 130412# 402# - 53 161 108 269 Hs -a 124564# 124# 7294# 0# B- -4806# 480# 269 133725# 133# - 51 160 109 269 Mt -a 129370# 463# 7273# 2# B- -5465# 464# 269 138884# 497# - 49 159 110 269 Ds -a 134834.709 31.403 7250.154 0.117 B- * 269 144751.021 33.712 -0 60 165 105 270 Db -a 122307# 617# 7314# 2# B- 816# 831# 270 131302# 662# - 58 164 106 270 Sg -a 121491# 557# 7314# 2# B- -2735# 627# 270 130426# 598# - 56 163 107 270 Bh -a 124226# 287# 7301# 1# B- -886# 379# 270 133362# 308# - 54 162 108 270 Hs -a 125112# 248# 7295# 1# B- -5598# 301# 270 134314# 266# - 52 161 109 270 Mt -a 130710# 170# 7271# 1# B- -3968# 177# 270 140323# 183# - 50 160 110 270 Ds -a 134678.282 48.011 7253.775 0.178 B- * 270 144583.090 51.542 -0 59 165 106 271 Sg -a 124757# 585# 7305# 2# B- -1164# 718# 271 133932# 628# - 57 164 107 271 Bh -a 125921# 415# 7298# 2# B- -1819# 501# 271 135182# 446# - 55 163 108 271 Hs -a 127740# 280# 7288# 1# B- -3361# 433# 271 137135# 301# - 53 162 109 271 Mt -a 131101# 330# 7273# 1# B- -4847# 344# 271 140742# 354# - 51 161 110 271 Ds -a 135948# 97# 7252# 0# B- * 271 145946# 104# -0 60 166 106 272 Sg -a 126580# 727# 7301# 3# B- -2209# 901# 272 135890# 781# - 58 165 107 272 Bh -a 128789# 532# 7290# 2# B- -217# 737# 272 138261# 571# - 56 164 108 272 Hs -a 129006# 510# 7286# 2# B- -4575# 704# 272 138494# 547# - 54 163 109 272 Mt -a 133581# 485# 7267# 2# B- -2433# 637# 272 143406# 521# - 52 162 110 272 Ds -a 136015# 413# 7255# 2# B- -6758# 474# 272 146018# 443# - 50 161 111 272 Rg -a 142773# 233# 7227# 1# B- * 272 153273# 251# -0 61 167 106 273 Sg x 130018# 503# 7291# 2# B- -615# 855# 273 139580# 540# - 59 166 107 273 Bh -a 130633# 692# 7286# 3# B- -1257# 783# 273 140240# 743# - 57 165 108 273 Hs -a 131890# 367# 7279# 1# B- -2822# 561# 273 141590# 394# - 55 164 109 273 Mt -a 134713# 424# 7265# 2# B- -3643# 445# 273 144620# 455# - 53 163 110 273 Ds -a 138356# 134# 7249# 0# B- -4339# 543# 273 148531# 144# - 51 162 111 273 Rg -a 142695# 526# 7231# 2# B- * 273 153189# 565# -0 60 167 107 274 Bh -a 133682# 619# 7278# 2# B- 196# 856# 274 143513# 664# - 58 166 108 274 Hs -a 133486# 592# 7276# 2# B- -3760# 689# 274 143303# 635# - 56 165 109 274 Mt -a 137246# 354# 7259# 1# B- -1952# 526# 274 147339# 380# - 54 164 110 274 Ds -a 139197# 389# 7249# 1# B- -5416# 428# 274 149434# 418# - 52 163 111 274 Rg -a 144613# 177# 7227# 1# B- * 274 155249# 190# -0 61 168 107 275 Bh x 135691# 596# 7273# 2# B- -929# 837# 275 145670# 640# - 59 167 108 275 Hs -a 136620# 587# 7267# 2# B- -2209# 721# 275 146667# 631# - 57 166 109 275 Mt -a 138829# 418# 7256# 2# B- -2736# 586# 275 149039# 449# - 55 165 110 275 Ds -a 141565# 410# 7244# 1# B- -3731# 661# 275 151976# 441# - 53 164 111 275 Rg -a 145296# 519# 7227# 2# B- * 275 155981# 557# -0 60 168 108 276 Hs -a 138285# 754# 7264# 3# B- -3029# 923# 276 148455# 810# - 58 167 109 276 Mt -a 141315# 532# 7250# 2# B- -1227# 763# 276 151708# 571# - 56 166 110 276 Ds -a 142541# 548# 7243# 2# B- -4945# 834# 276 153024# 588# - 54 165 111 276 Rg -a 147486# 629# 7222# 2# B- -2866# 866# 276 158333# 675# - 52 164 112 276 Cn x 150352# 596# 7209# 2# B- * 276 161410# 640# -0 61 169 108 277 Hs -a 141493# 541# 7255# 2# B- -1475# 884# 277 151899# 581# - 59 168 109 277 Mt -a 142968# 699# 7247# 3# B- -2172# 798# 277 153483# 751# - 57 167 110 277 Ds -a 145140# 384# 7237# 1# B- -3197# 646# 277 155815# 412# - 55 166 111 277 Rg -a 148338# 520# 7222# 2# B- -4065# 539# 277 159247# 558# - 53 165 112 277 Cn -a 152403# 143# 7205# 1# B- * 277 163611# 153# -0 60 169 109 278 Mt -a 145736# 621# 7240# 2# B- -645# 881# 278 156454# 666# - 58 168 110 278 Ds -a 146381# 625# 7235# 2# B- -4136# 719# 278 157146# 671# - 56 167 111 278 Rg -a 150517# 357# 7218# 1# B- -2415# 565# 278 161587# 383# - 54 166 112 278 Cn -a 152932# 438# 7206# 2# B- -5957# 475# 278 164179# 470# - 52 165 113 278 Ed -a 158889# 184# 7182# 1# B- * 278 170574# 198# -0 61 170 109 279 Mt -a 147496# 667# 7237# 2# B- -1630# 896# 279 158343# 716# - 59 169 110 279 Ds -a 149126# 598# 7228# 2# B- -2649# 731# 279 160093# 642# - 57 168 111 279 Rg -a 151775# 421# 7216# 2# B- -3255# 621# 279 162937# 452# - 55 167 112 279 Cn -a 155030# 456# 7202# 2# B- -4209# 835# 279 166432# 490# - 53 166 113 279 Ed x 159239# 699# 7184# 3# B- * 279 170950# 750# -0 60 170 110 280 Ds -a 150520# 780# 7226# 3# B- -3366# 944# 280 161590# 838# - 58 169 111 280 Rg -a 153886# 532# 7212# 2# B- -1810# 789# 280 165203# 571# - 56 168 112 280 Cn -a 155696# 583# 7202# 2# B- -5444# 707# 280 167147# 626# - 54 167 113 280 Ed x 161140# 400# 7180# 1# B- * 280 172991# 429# -0 61 171 110 281 Ds -a 153431# 579# 7219# 2# B- -1866# 992# 281 164715# 622# - 59 170 111 281 Rg -a 155297# 806# 7210# 3# B- -2722# 894# 281 166718# 865# - 57 169 112 281 Cn -a 158019# 387# 7197# 1# B- -3790# 490# 281 169641# 416# - 55 168 113 281 Ed x 161810# 300# 7181# 1# B- * 281 173710# 322# -0 60 171 111 282 Rg -a 157800# 654# 7204# 2# B- -1176# 926# 282 169405# 702# - 58 170 112 282 Cn -a 158976# 656# 7197# 2# B- -4749# 748# 282 170668# 704# - 56 169 113 282 Ed -a 163725# 361# 7177# 1# B- * 282 175766# 387# -0 61 172 111 283 Rg -a 159281# 697# 7202# 2# B- -2205# 925# 283 170995# 748# - 59 171 112 283 Cn -a 161486# 608# 7191# 2# B- -3221# 748# 283 173362# 653# - 57 170 113 283 Ed -a 164707# 436# 7177# 2# B- * 283 176820# 468# -0 60 172 112 284 Cn -a 162545# 806# 7190# 3# B- -4046# 966# 284 174499# 865# - 58 171 113 284 Ed -a 166591# 534# 7173# 2# B- -2330# 846# 284 178843# 573# - 56 170 114 284 Fl -a 168921# 656# 7162# 2# B- * 284 181344# 704# -0 61 173 112 285 Cn -a 165173# 581# 7184# 2# B- -2557# 995# 285 177321# 624# - 59 172 113 285 Ed -a 167731# 807# 7173# 3# B- -3272# 897# 285 180066# 866# - 57 171 114 285 Fl -a 171003# 391# 7158# 1# B- * 285 183579# 419# -0 60 173 113 286 Ed -a 170014# 656# 7168# 2# B- -1758# 928# 286 182518# 704# - 58 172 114 286 Fl -a 171773# 657# 7159# 2# B- * 286 184406# 705# -0 61 174 113 287 Ed -a 171245# 725# 7167# 3# B- -2827# 948# 287 183840# 778# - 59 173 114 287 Fl -a 174073# 610# 7154# 2# B- -3823# 752# 287 186875# 655# - 57 172 115 287 Ef -a 177895# 439# 7138# 2# B- * 287 190978# 471# -0 60 174 114 288 Fl -a 175042# 806# 7154# 3# B- -4728# 968# 288 187916# 865# - 58 173 115 288 Ef -a 179771# 536# 7135# 2# B- * 288 192992# 576# -0 61 175 114 289 Fl -a 177564# 584# 7148# 2# B- -3102# 997# 289 190623# 626# - 59 174 115 289 Ef -a 180666# 809# 7135# 3# B- -3861# 947# 289 193953# 868# - 57 173 116 289 Lv -a 184528# 492# 7119# 2# B- * 289 198099# 529# -0 60 175 115 290 Ef -a 182894# 658# 7130# 2# B- -2304# 932# 290 196345# 706# - 58 174 116 290 Lv -a 185198# 660# 7120# 2# B- * 290 198818# 708# -0 61 176 115 291 Ef -a 183990# 784# 7130# 3# B- -3397# 995# 291 197522# 842# - 59 175 116 291 Lv -a 187387# 612# 7116# 2# B- -4413# 853# 291 201169# 658# - 57 174 117 291 Eh -a 191800# 594# 7098# 2# B- * 291 205906# 637# -0 60 176 116 292 Lv -a 188242# 806# 7116# 3# B- -5334# 1047# 292 202086# 865# - 58 175 117 292 Eh -a 193576# 669# 7095# 2# B- * 292 207812# 718# -0 61 177 116 293 Lv -a 190669# 586# 7111# 2# B- -3716# 1000# 293 204691# 629# - 59 176 117 293 Eh -a 194385# 810# 7095# 3# B- -4488# 1072# 293 208680# 870# - 57 175 118 293 Ei -a 198873# 702# 7077# 2# B- * 293 213498# 753# -0 60 177 117 294 Eh -a 196521# 660# 7092# 2# B- -2942# 936# 294 210974# 708# - 58 176 118 294 Ei -a 199463# 663# 7079# 2# B- * 294 214132# 712# -0 59 177 118 295 Ei -a 201512# 644# 7075# 2# B- * 295 216332# 692# diff --git a/openmc/data/multipole.py b/openmc/data/multipole.py deleted file mode 100644 index 6178161ef..000000000 --- a/openmc/data/multipole.py +++ /dev/null @@ -1,535 +0,0 @@ -from numbers import Integral, Real -from math import exp, erf, pi, sqrt - -import h5py -import numpy as np - -from . import WMP_VERSION, WMP_VERSION_MAJOR -from .data import K_BOLTZMANN -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin - - -# Constants that determine which value to access -_MP_EA = 0 # Pole - -# Residue indices -_MP_RS = 1 # Residue scattering -_MP_RA = 2 # Residue absorption -_MP_RF = 3 # Residue fission - -# Polynomial fit indices -_FIT_S = 0 # Scattering -_FIT_A = 1 # Absorption -_FIT_F = 2 # Fission - - -def _faddeeva(z): - r"""Evaluate the complex Faddeeva function. - - Technically, the value we want is given by the equation: - - .. math:: - w(z) = \frac{i}{\pi} \int_{-\infty}^{\infty} \frac{1}{z - t} - \exp(-t^2) \text{d}t - - as shown in Equation 63 from Hwang, R. N. "A rigorous pole - representation of multilevel cross sections and its practical - applications." Nuclear Science and Engineering 96.3 (1987): 192-209. - - The :func:`scipy.special.wofz` function evaluates - :math:`w(z) = \exp(-z^2) \text{erfc}(-iz)`. These two forms of the Faddeeva - function are related by a transformation. - - If we call the integral form :math:`w_\text{int}`, and the function form - :math:`w_\text{fun}`: - - .. math:: - w_\text{int}(z) = - \begin{cases} - w_\text{fun}(z) & \text{for } \text{Im}(z) > 0\\ - -w_\text{fun}(z^*)^* & \text{for } \text{Im}(z) < 0 - \end{cases} - - Parameters - ---------- - z : complex - Argument to the Faddeeva function. - - Returns - ------- - complex - :math:`\frac{i}{\pi} \int_{-\infty}^{\infty} \frac{1}{z - t} \exp(-t^2) - \text{d}t` - - """ - from scipy.special import wofz - if np.angle(z) > 0: - return wofz(z) - else: - return -np.conj(wofz(z.conjugate())) - - -def _broaden_wmp_polynomials(E, dopp, n): - r"""Evaluate Doppler-broadened windowed multipole curvefit. - - The curvefit is a polynomial of the form :math:`\frac{a}{E} - + \frac{b}{\sqrt{E}} + c + d \sqrt{E} + \ldots` - - Parameters - ---------- - E : Real - Energy to evaluate at. - dopp : Real - sqrt(atomic weight ratio / kT) in units of eV. - n : Integral - Number of components to the polynomial. - - Returns - ------- - numpy.ndarray - The value of each Doppler-broadened curvefit polynomial term. - - """ - sqrtE = sqrt(E) - beta = sqrtE * dopp - half_inv_dopp2 = 0.5 / dopp**2 - quarter_inv_dopp4 = half_inv_dopp2**2 - - if beta > 6.0: - # Save time, ERF(6) is 1 to machine precision. - # beta/sqrtpi*exp(-beta**2) is also approximately 1 machine epsilon. - erf_beta = 1.0 - exp_m_beta2 = 0.0 - else: - erf_beta = erf(beta) - exp_m_beta2 = exp(-beta**2) - - # Assume that, for sure, we'll use a second order (1/E, 1/V, const) - # fit, and no less. - - factors = np.zeros(n) - - factors[0] = erf_beta / E - factors[1] = 1.0 / sqrtE - factors[2] = (factors[0] * (half_inv_dopp2 + E) - + exp_m_beta2 / (beta * sqrt(pi))) - - # Perform recursive broadening of high order components. range(1, n-2) - # replaces a do i = 1, n-3. All indices are reduced by one due to the - # 1-based vs. 0-based indexing. - for i in range(1, n-2): - if i != 1: - factors[i+2] = (-factors[i-2] * (i - 1.0) * i * quarter_inv_dopp4 - + factors[i] * (E + (1.0 + 2.0 * i) * half_inv_dopp2)) - else: - factors[i+2] = factors[i]*(E + (1.0 + 2.0 * i) * half_inv_dopp2) - - return factors - - -class WindowedMultipole(EqualityMixin): - """Resonant cross sections represented in the windowed multipole format. - - Parameters - ---------- - name : str - Name of the nuclide using the GND naming convention - - Attributes - ---------- - fit_order : Integral - Order of the windowed curvefit. - fissionable : bool - Whether or not the target nuclide has fission data. - spacing : Real - The width of each window in sqrt(E)-space. For example, the frst window - will end at (sqrt(E_min) + spacing)**2 and the second window at - (sqrt(E_min) + 2*spacing)**2. - sqrtAWR : Real - Square root of the atomic weight ratio of the target nuclide. - E_min : Real - Lowest energy in eV the library is valid for. - E_max : Real - Highest energy in eV the library is valid for. - data : np.ndarray - A 2D array of complex poles and residues. data[i, 0] gives the energy - at which pole i is located. data[i, 1:] gives the residues associated - with the i-th pole. There are 3 residues, one each for the scattering, - absorption, and fission channels. - windows : np.ndarray - A 2D array of Integral values. windows[i, 0] - 1 is the index of the - first pole in window i. windows[i, 1] - 1 is the index of the last pole - in window i. - broaden_poly : np.ndarray - A 1D array of boolean values indicating whether or not the polynomial - curvefit in that window should be Doppler broadened. - curvefit : np.ndarray - A 3D array of Real curvefit polynomial coefficients. curvefit[i, 0, :] - gives coefficients for the scattering cross section in window i. - curvefit[i, 1, :] gives absorption coefficients and curvefit[i, 2, :] - gives fission coefficients. The polynomial terms are increasing powers - of sqrt(E) starting with 1/E e.g: - a/E + b/sqrt(E) + c + d sqrt(E) + ... - - """ - def __init__(self, name): - self.name = name - self.spacing = None - self.sqrtAWR = None - self.E_min = None - self.E_max = None - self.data = None - self.windows = None - self.broaden_poly = None - self.curvefit = None - - @property - def name(self): - return self._name - - @property - def fit_order(self): - return self.curvefit.shape[1] - 1 - - @property - def fissionable(self): - return self.data.shape[1] == 4 - - @property - def spacing(self): - return self._spacing - - @property - def sqrtAWR(self): - return self._sqrtAWR - - @property - def E_min(self): - return self._E_min - - @property - def E_max(self): - return self._E_max - - @property - def data(self): - return self._data - - @property - def windows(self): - return self._windows - - @property - def broaden_poly(self): - return self._broaden_poly - - @property - def curvefit(self): - return self._curvefit - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @spacing.setter - def spacing(self, spacing): - if spacing is not None: - cv.check_type('spacing', spacing, Real) - cv.check_greater_than('spacing', spacing, 0.0, equality=False) - self._spacing = spacing - - @sqrtAWR.setter - def sqrtAWR(self, sqrtAWR): - if sqrtAWR is not None: - cv.check_type('sqrtAWR', sqrtAWR, Real) - cv.check_greater_than('sqrtAWR', sqrtAWR, 0.0, equality=False) - self._sqrtAWR = sqrtAWR - - @E_min.setter - def E_min(self, E_min): - if E_min is not None: - cv.check_type('E_min', E_min, Real) - cv.check_greater_than('E_min', E_min, 0.0, equality=True) - self._E_min = E_min - - @E_max.setter - def E_max(self, E_max): - if E_max is not None: - cv.check_type('E_max', E_max, Real) - cv.check_greater_than('E_max', E_max, 0.0, equality=False) - self._E_max = E_max - - @data.setter - def data(self, data): - if data is not None: - cv.check_type('data', data, np.ndarray) - if len(data.shape) != 2: - raise ValueError('Multipole data arrays must be 2D') - if data.shape[1] not in (3, 4): - raise ValueError( - 'data.shape[1] must be 3 or 4. One value for the pole.' - ' One each for the scattering and absorption residues. ' - 'Possibly one more for a fission residue.') - if not np.issubdtype(data.dtype, np.complexfloating): - raise TypeError('Multipole data arrays must be complex dtype') - self._data = data - - @windows.setter - def windows(self, windows): - if windows is not None: - cv.check_type('windows', windows, np.ndarray) - if len(windows.shape) != 2: - raise ValueError('Multipole windows arrays must be 2D') - if not np.issubdtype(windows.dtype, np.integer): - raise TypeError('Multipole windows arrays must be integer' - ' dtype') - self._windows = windows - - @broaden_poly.setter - def broaden_poly(self, broaden_poly): - if broaden_poly is not None: - cv.check_type('broaden_poly', broaden_poly, np.ndarray) - if len(broaden_poly.shape) != 1: - raise ValueError('Multipole broaden_poly arrays must be 1D') - if not np.issubdtype(broaden_poly.dtype, np.bool_): - raise TypeError('Multipole broaden_poly arrays must be boolean' - ' dtype') - self._broaden_poly = broaden_poly - - @curvefit.setter - def curvefit(self, curvefit): - if curvefit is not None: - 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): # sig_s, 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, np.floating): - raise TypeError('Multipole curvefit arrays must be float dtype') - self._curvefit = curvefit - - @classmethod - def from_hdf5(cls, group_or_filename): - """Construct a WindowedMultipole object from an HDF5 group or file. - - Parameters - ---------- - group_or_filename : h5py.Group or str - HDF5 group containing multipole data. If given as a string, it is - assumed to be the filename for the HDF5 file, and the first group is - used to read from. - - Returns - ------- - openmc.data.WindowedMultipole - Resonant cross sections represented in the windowed multipole - format. - - """ - - if isinstance(group_or_filename, h5py.Group): - group = group_or_filename - else: - h5file = h5py.File(str(group_or_filename), 'r') - - # Make sure version matches - if 'version' in h5file.attrs: - major, minor = h5file.attrs['version'] - if major != WMP_VERSION_MAJOR: - raise IOError( - 'WMP data format uses version {}. {} whereas your ' - 'installation of the OpenMC Python API expects version ' - '{}.x.'.format(major, minor, WMP_VERSION_MAJOR)) - else: - raise IOError( - 'WMP data does not indicate a version. Your installation of ' - 'the OpenMC Python API expects version {}.x data.' - .format(WMP_VERSION_MAJOR)) - - group = list(h5file.values())[0] - - name = group.name[1:] - out = cls(name) - - # Read scalars. - - out.spacing = group['spacing'][()] - out.sqrtAWR = group['sqrtAWR'][()] - out.E_min = group['E_min'][()] - out.E_max = group['E_max'][()] - - # Read arrays. - - err = "WMP '{}' array shape is not consistent with the '{}' array shape" - - out.data = group['data'][()] - - out.windows = group['windows'][()] - - out.broaden_poly = group['broaden_poly'][...].astype(np.bool) - if out.broaden_poly.shape[0] != out.windows.shape[0]: - raise ValueError(err.format('broaden_poly', 'windows')) - - out.curvefit = group['curvefit'][()] - if out.curvefit.shape[0] != out.windows.shape[0]: - raise ValueError(err.format('curvefit', 'windows')) - - # _broaden_wmp_polynomials assumes the curve fit has at least 3 terms. - if out.fit_order < 2: - raise ValueError("Windowed multipole is only supported for " - "curvefits with 3 or more terms.") - - return out - - def _evaluate(self, E, T): - """Compute scattering, absorption, and fission cross sections. - - Parameters - ---------- - E : Real - Energy of the incident neutron in eV. - T : Real - Temperature of the target in K. - - Returns - ------- - 3-tuple of Real - Total, absorption, and fission microscopic cross sections at the - given energy and temperature. - - """ - - if E < self.E_min: return (0, 0, 0) - if E > self.E_max: return (0, 0, 0) - - # ====================================================================== - # Bookkeeping - - # Define some frequently used variables. - sqrtkT = sqrt(K_BOLTZMANN * T) - sqrtE = sqrt(E) - invE = 1.0 / E - - # 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 - # decreased by 1. endw does not need to be decreased because - # range(startw, endw) does not include endw. - i_window = int(np.floor((sqrtE - sqrt(self.E_min)) / self.spacing)) - startw = self.windows[i_window, 0] - 1 - endw = self.windows[i_window, 1] - - # Initialize the ouptut cross sections. - sig_s = 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): - sig_s += (self.curvefit[i_window, i_poly, _FIT_S] - * broadened_polynomials[i_poly]) - sig_a += (self.curvefit[i_window, i_poly, _FIT_A] - * broadened_polynomials[i_poly]) - if self.fissionable: - 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): - sig_s += self.curvefit[i_window, i_poly, _FIT_S] * temp - sig_a += self.curvefit[i_window, i_poly, _FIT_A] * temp - if self.fissionable: - sig_f += self.curvefit[i_window, i_poly, _FIT_F] * temp - temp *= sqrtE - - # ====================================================================== - # Add the contribution from the poles in this window. - - if sqrtkT == 0.0: - # If at 0K, use asymptotic form. - for i_pole in range(startw, endw): - psi_chi = -1j / (self.data[i_pole, _MP_EA] - sqrtE) - c_temp = psi_chi / E - sig_s += (self.data[i_pole, _MP_RS] * c_temp).real - sig_a += (self.data[i_pole, _MP_RA] * c_temp).real - if self.fissionable: - sig_f += (self.data[i_pole, _MP_RF] * c_temp).real - - 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) - sig_s += (self.data[i_pole, _MP_RS] * w_val).real - sig_a += (self.data[i_pole, _MP_RA] * w_val).real - if self.fissionable: - sig_f += (self.data[i_pole, _MP_RF] * w_val).real - - return sig_s, sig_a, sig_f - - def __call__(self, E, T): - """Compute scattering, absorption, and fission cross sections. - - Parameters - ---------- - E : Real or Iterable of Real - Energy of the incident neutron in eV. - T : Real - Temperature of the target in K. - - Returns - ------- - 3-tuple of Real or 3-tuple of numpy.ndarray - Total, absorption, and fission microscopic cross sections at the - given energy and temperature. - - """ - - fun = np.vectorize(lambda x: self._evaluate(x, T)) - return fun(E) - - def export_to_hdf5(self, path, mode='a', libver='earliest'): - """Export windowed multipole data to an HDF5 file. - - Parameters - ---------- - path : str - Path to write HDF5 file to - 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. - with h5py.File(str(path), mode, libver=libver) as f: - f.attrs['filetype'] = np.string_('data_wmp') - f.attrs['version'] = np.array(WMP_VERSION) - - g = f.create_group(self.name) - - # Write scalars. - g.create_dataset('spacing', data=np.array(self.spacing)) - g.create_dataset('sqrtAWR', data=np.array(self.sqrtAWR)) - g.create_dataset('E_min', data=np.array(self.E_min)) - g.create_dataset('E_max', data=np.array(self.E_max)) - - # Write arrays. - g.create_dataset('data', data=self.data) - g.create_dataset('windows', data=self.windows) - g.create_dataset('broaden_poly', - data=self.broaden_poly.astype(np.int8)) - g.create_dataset('curvefit', data=self.curvefit) diff --git a/openmc/data/nbody.py b/openmc/data/nbody.py deleted file mode 100644 index 4db9934b9..000000000 --- a/openmc/data/nbody.py +++ /dev/null @@ -1,165 +0,0 @@ -from numbers import Real, Integral - -import numpy as np - -import openmc.checkvalue as cv -from .angle_energy import AngleEnergy -from .endf import get_cont_record - -class NBodyPhaseSpace(AngleEnergy): - """N-body phase space distribution - - Parameters - ---------- - total_mass : float - Total mass of product particles - n_particles : int - Number of product particles - atomic_weight_ratio : float - Atomic weight ratio of target nuclide - q_value : float - Q value for reaction in eV - - Attributes - ---------- - total_mass : float - Total mass of product particles - n_particles : int - Number of product particles - atomic_weight_ratio : float - Atomic weight ratio of target nuclide - q_value : float - Q value for reaction in eV - - """ - - def __init__(self, total_mass, n_particles, atomic_weight_ratio, q_value): - self.total_mass = total_mass - self.n_particles = n_particles - self.atomic_weight_ratio = atomic_weight_ratio - self.q_value = q_value - - @property - def total_mass(self): - return self._total_mass - - @property - def n_particles(self): - return self._n_particles - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @property - def q_value(self): - return self._q_value - - @total_mass.setter - def total_mass(self, total_mass): - name = 'N-body phase space total mass' - cv.check_type(name, total_mass, Real) - cv.check_greater_than(name, total_mass, 0.) - self._total_mass = total_mass - - @n_particles.setter - def n_particles(self, n_particles): - name = 'N-body phase space number of particles' - cv.check_type(name, n_particles, Integral) - cv.check_greater_than(name, n_particles, 0) - self._n_particles = n_particles - - @atomic_weight_ratio.setter - def atomic_weight_ratio(self, atomic_weight_ratio): - name = 'N-body phase space atomic weight ratio' - cv.check_type(name, atomic_weight_ratio, Real) - cv.check_greater_than(name, atomic_weight_ratio, 0.0) - self._atomic_weight_ratio = atomic_weight_ratio - - @q_value.setter - def q_value(self, q_value): - name = 'N-body phase space Q value' - cv.check_type(name, q_value, Real) - self._q_value = q_value - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('nbody') - group.attrs['total_mass'] = self.total_mass - group.attrs['n_particles'] = self.n_particles - group.attrs['atomic_weight_ratio'] = self.atomic_weight_ratio - group.attrs['q_value'] = self.q_value - - @classmethod - def from_hdf5(cls, group): - """Generate N-body phase space distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.NBodyPhaseSpace - N-body phase space distribution - - """ - total_mass = group.attrs['total_mass'] - n_particles = group.attrs['n_particles'] - awr = group.attrs['atomic_weight_ratio'] - q_value = group.attrs['q_value'] - return cls(total_mass, n_particles, awr, q_value) - - @classmethod - def from_ace(cls, ace, idx, q_value): - """Generate N-body phase space distribution from ACE data - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - idx : int - Index in XSS array of the start of the energy distribution data - (LDIS + LOCC - 1) - q_value : float - Q-value for reaction in eV - - Returns - ------- - openmc.data.NBodyPhaseSpace - N-body phase space distribution - - """ - n_particles = int(ace.xss[idx]) - total_mass = ace.xss[idx + 1] - return cls(total_mass, n_particles, ace.atomic_weight_ratio, q_value) - - @classmethod - def from_endf(cls, file_obj): - """Generate N-body phase space distribution from an ENDF evaluation - - Parameters - ---------- - file_obj : file-like object - ENDF file positions at the start of the N-body phase space - distribution - - Returns - ------- - openmc.data.NBodyPhaseSpace - N-body phase space distribution - - """ - items = get_cont_record(file_obj) - total_mass = items[0] - n_particles = items[5] - # TODO: get awr and Q value - return cls(total_mass, n_particles, 1.0, 0.0) diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py deleted file mode 100644 index ea14be784..000000000 --- a/openmc/data/neutron.py +++ /dev/null @@ -1,926 +0,0 @@ -from collections import OrderedDict -from collections.abc import Mapping, MutableMapping -from io import StringIO -from math import log10 -from numbers import Integral, Real -import os -import tempfile -from warnings import warn - -import numpy as np -import h5py - -from . import HDF5_VERSION, HDF5_VERSION_MAJOR -from .ace import Library, Table, get_table, get_metadata -from .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV -from .endf import ( - Evaluation, SUM_RULES, get_head_record, get_tab1_record, get_evaluations) -from .fission_energy import FissionEnergyRelease -from .function import Tabulated1D, Sum, ResonancesWithBackground -from .grid import linearize, thin -from .njoy import make_ace -from .product import Product -from .reaction import Reaction, _get_photon_products_ace -from . import resonance as res -from . import resonance_covariance as res_cov -from .urr import ProbabilityTables -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin - - -# Fractions of resonance widths used for reconstructing resonances -_RESONANCE_ENERGY_GRID = np.logspace(-3, 3, 61) - - -class IncidentNeutron(EqualityMixin): - """Continuous-energy neutron interaction data. - - This class stores data derived from an ENDF-6 format neutron interaction - sublibrary. Instances of this class are not normally instantiated by the - user but rather created using the factory methods - :meth:`IncidentNeutron.from_hdf5`, :meth:`IncidentNeutron.from_ace`, and - :meth:`IncidentNeutron.from_endf`. - - Parameters - ---------- - name : str - Name of the nuclide using the GND naming convention - atomic_number : int - Number of protons in the target nucleus - mass_number : int - Number of nucleons in the target nucleus - metastable : int - Metastable state of the target nucleus. A value of zero indicates ground - state. - atomic_weight_ratio : float - Atomic mass ratio of the target nuclide. - kTs : Iterable of float - List of temperatures of the target nuclide in the data set. - The temperatures have units of eV. - - Attributes - ---------- - atomic_number : int - Number of protons in the target nucleus - atomic_symbol : str - Atomic symbol of the nuclide, e.g., 'Zr' - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide. - fission_energy : None or openmc.data.FissionEnergyRelease - The energy released by fission, tabulated by component (e.g. prompt - neutrons or beta particles) and dependent on incident neutron energy - mass_number : int - Number of nucleons in the target nucleus - metastable : int - Metastable state of the target nucleus. A value of zero indicates ground - state. - name : str - Name of the nuclide using the GND naming convention - reactions : collections.OrderedDict - Contains the cross sections, secondary angle and energy distributions, - and other associated data for each reaction. The keys are the MT values - and the values are Reaction objects. - resonances : openmc.data.Resonances or None - Resonance parameters - resonance_covariance : openmc.data.ResonanceCovariance or None - Covariance for resonance parameters - temperatures : list of str - List of string representations the temperatures of the target nuclide - in the data set. The temperatures are strings of the temperature, - rounded to the nearest integer; e.g., '294K' - kTs : Iterable of float - List of temperatures of the target nuclide in the data set. - The temperatures have units of eV. - urr : dict - Dictionary whose keys are temperatures (e.g., '294K') and values are - unresolved resonance region probability tables. - - """ - - def __init__(self, name, atomic_number, mass_number, metastable, - atomic_weight_ratio, kTs): - self.name = name - self.atomic_number = atomic_number - self.mass_number = mass_number - self.metastable = metastable - self.atomic_weight_ratio = atomic_weight_ratio - self.kTs = kTs - self.energy = {} - self._fission_energy = None - self.reactions = OrderedDict() - self._urr = {} - self._resonances = None - - def __contains__(self, mt): - return mt in self.reactions - - def __getitem__(self, mt): - if mt in self.reactions: - return self.reactions[mt] - else: - raise KeyError('No reaction with MT={}.'.format(mt)) - - def __repr__(self): - return "".format(self.name) - - def __iter__(self): - return iter(self.reactions.values()) - - @property - def name(self): - return self._name - - @property - def atomic_number(self): - return self._atomic_number - - @property - def mass_number(self): - return self._mass_number - - @property - def metastable(self): - return self._metastable - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @property - def fission_energy(self): - return self._fission_energy - - @property - def reactions(self): - return self._reactions - - @property - def resonances(self): - return self._resonances - - @property - def resonance_covariance(self): - return self._resonance_covariance - - @property - def urr(self): - return self._urr - - @property - def temperatures(self): - return ["{}K".format(int(round(kT / K_BOLTZMANN))) for kT in self.kTs] - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @property - def atomic_symbol(self): - return ATOMIC_SYMBOL[self.atomic_number] - - @atomic_number.setter - def atomic_number(self, atomic_number): - cv.check_type('atomic number', atomic_number, Integral) - cv.check_greater_than('atomic number', atomic_number, 0, True) - self._atomic_number = atomic_number - - @mass_number.setter - def mass_number(self, mass_number): - cv.check_type('mass number', mass_number, Integral) - cv.check_greater_than('mass number', mass_number, 0, True) - self._mass_number = mass_number - - @metastable.setter - def metastable(self, metastable): - cv.check_type('metastable', metastable, Integral) - cv.check_greater_than('metastable', metastable, 0, True) - self._metastable = metastable - - @atomic_weight_ratio.setter - def atomic_weight_ratio(self, atomic_weight_ratio): - cv.check_type('atomic weight ratio', atomic_weight_ratio, Real) - cv.check_greater_than('atomic weight ratio', atomic_weight_ratio, 0.0) - self._atomic_weight_ratio = atomic_weight_ratio - - @fission_energy.setter - def fission_energy(self, fission_energy): - cv.check_type('fission energy release', fission_energy, - FissionEnergyRelease) - self._fission_energy = fission_energy - - @reactions.setter - def reactions(self, reactions): - cv.check_type('reactions', reactions, Mapping) - self._reactions = reactions - - @resonances.setter - def resonances(self, resonances): - cv.check_type('resonances', resonances, res.Resonances) - self._resonances = resonances - - @resonance_covariance.setter - def resonance_covariance(self, resonance_covariance): - cv.check_type('resonance covariance', resonance_covariance, - res_cov.ResonanceCovariances) - self._resonance_covariance = resonance_covariance - - @urr.setter - def urr(self, urr): - cv.check_type('probability table dictionary', urr, MutableMapping) - for key, value in urr: - cv.check_type('probability table temperature', key, str) - cv.check_type('probability tables', value, ProbabilityTables) - self._urr = urr - - def add_temperature_from_ace(self, ace_or_filename, metastable_scheme='nndc'): - """Append data from an ACE file at a different temperature. - - Parameters - ---------- - ace_or_filename : openmc.data.ace.Table or str - ACE table to read from. If given as a string, it is assumed to be - the filename for the ACE file. - metastable_scheme : {'nndc', 'mcnp'} - Determine how ZAID identifiers are to be interpreted in the case of - a metastable nuclide. Because the normal ZAID (=1000*Z + A) does not - encode metastable information, different conventions are used among - different libraries. In MCNP libraries, the convention is to add 400 - for a metastable nuclide except for Am242m, for which 95242 is - metastable and 95642 (or 1095242 in newer libraries) is the ground - state. For NNDC libraries, ZAID is given as 1000*Z + A + 100*m. - - """ - - data = IncidentNeutron.from_ace(ace_or_filename, metastable_scheme) - - # Check if temprature already exists - strT = data.temperatures[0] - if strT in self.temperatures: - warn('Cross sections at T={} already exist.'.format(strT)) - return - - # Check that name matches - if data.name != self.name: - raise ValueError('Data provided for an incorrect nuclide.') - - # Add temperature - self.kTs += data.kTs - - # Add energy grid - self.energy[strT] = data.energy[strT] - - # Add normal and redundant reactions - for mt in data.reactions: - if mt in self: - self[mt].xs[strT] = data[mt].xs[strT] - else: - warn("Tried to add cross sections for MT={} at T={} but this " - "reaction doesn't exist.".format(mt, strT)) - - # Add probability tables - if strT in data.urr: - self.urr[strT] = data.urr[strT] - - def add_elastic_0K_from_endf(self, filename, overwrite=False): - """Append 0K elastic scattering cross section from an ENDF file. - - Parameters - ---------- - filename : str - Path to ENDF file - overwrite : bool - If existing 0 K data is present, this flag can be used to indicate - that it should be overwritten. Otherwise, an exception will be - thrown. - - Raises - ------ - ValueError - If 0 K data is already present and the `overwrite` parameter is - False. - - """ - # Check for existing data - if '0K' in self.energy and not overwrite: - raise ValueError('0 K data already exists for this nuclide.') - - data = type(self).from_endf(filename) - if data.resonances is not None: - x = [] - y = [] - for rr in data.resonances: - if isinstance(rr, res.RMatrixLimited): - raise TypeError('R-Matrix Limited not supported.') - elif isinstance(rr, res.Unresolved): - continue - - # Get energies/widths for resonances - e_peak = rr.parameters['energy'].values - if isinstance(rr, res.MultiLevelBreitWigner): - gamma = rr.parameters['totalWidth'].values - elif isinstance(rr, res.ReichMoore): - df = rr.parameters - gamma = (df['neutronWidth'] + - df['captureWidth'] + - abs(df['fissionWidthA']) + - abs(df['fissionWidthB'])).values - - # Determine peak energies and widths - e_min, e_max = rr.energy_min, rr.energy_max - in_range = (e_peak > e_min) & (e_peak < e_max) - e_peak = e_peak[in_range] - gamma = gamma[in_range] - - # Get midpoints between resonances (use min/max energy of - # resolved region as absolute lower/upper bound) - e_mid = np.concatenate( - ([e_min], (e_peak[1:] + e_peak[:-1])/2, [e_max])) - - # Add grid around each resonance that includes the peak +/- the - # width times each value in _RESONANCE_ENERGY_GRID. Values are - # constrained so that points around one resonance don't overlap - # with points around another. This algorithm is from Fudge. - energies = [] - for e, g, e_lower, e_upper in zip(e_peak, gamma, e_mid[:-1], - e_mid[1:]): - e_left = e - g*_RESONANCE_ENERGY_GRID - energies.append(e_left[e_left > e_lower][::-1]) - e_right = e + g*_RESONANCE_ENERGY_GRID[1:] - energies.append(e_right[e_right < e_upper]) - - # Concatenate all points - energies = np.concatenate(energies) - - # Create 1000 equal log-spaced energies over RRR, combine with - # resonance peaks and half-height energies - e_log = np.logspace(log10(e_min), log10(e_max), 1000) - energies = np.union1d(e_log, energies) - - # Linearize and thin cross section - xi, yi = linearize(energies, data[2].xs['0K']) - xi, yi = thin(xi, yi) - - # If there are multiple resolved resonance ranges (e.g. Pu239 in - # ENDF/B-VII.1), combine them - x = np.concatenate((x, xi)) - y = np.concatenate((y, yi)) - else: - energies = data[2].xs['0K'].x - x, y = linearize(energies, data[2].xs['0K']) - x, y = thin(x, y) - - # Set 0K energy grid and elastic scattering cross section - self.energy['0K'] = x - self[2].xs['0K'] = Tabulated1D(x, y) - - def get_reaction_components(self, mt): - """Determine what reactions make up redundant reaction. - - Parameters - ---------- - mt : int - ENDF MT number of the reaction to find components of. - - Returns - ------- - mts : list of int - ENDF MT numbers of reactions that make up the redundant reaction and - have cross sections provided. - - """ - mts = [] - if mt in SUM_RULES: - for mt_i in SUM_RULES[mt]: - mts += self.get_reaction_components(mt_i) - if mts: - return mts - else: - return [mt] if mt in self else [] - - def export_to_hdf5(self, path, mode='a', libver='earliest'): - """Export incident neutron data to an HDF5 file. - - Parameters - ---------- - path : str - Path to write HDF5 file to - 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 - if hasattr(self, '_evaluation'): - raise NotImplementedError('Cannot export incident neutron data that ' - 'originated from an ENDF file.') - - # Open file and write version - f = h5py.File(str(path), mode, libver=libver) - f.attrs['filetype'] = np.string_('data_neutron') - f.attrs['version'] = np.array(HDF5_VERSION) - - # Write basic data - g = f.create_group(self.name) - g.attrs['Z'] = self.atomic_number - g.attrs['A'] = self.mass_number - g.attrs['metastable'] = self.metastable - g.attrs['atomic_weight_ratio'] = self.atomic_weight_ratio - ktg = g.create_group('kTs') - for i, temperature in enumerate(self.temperatures): - ktg.create_dataset(temperature, data=self.kTs[i]) - - # Write energy grid - eg = g.create_group('energy') - for temperature in self.temperatures: - eg.create_dataset(temperature, data=self.energy[temperature]) - - # Write 0K energy grid if needed - if '0K' in self.energy and '0K' not in eg: - eg.create_dataset('0K', data=self.energy['0K']) - - # Write reaction data - rxs_group = g.create_group('reactions') - for rx in self.reactions.values(): - # Skip writing redundant reaction if it doesn't have photon - # production or is a summed transmutation reaction. MT=4 is also - # sometimes needed for probability tables. Also write gas - # production, heating, and damage energy production. - if rx.redundant: - photon_rx = any(p.particle == 'photon' for p in rx.products) - keep_mts = (4, 16, 103, 104, 105, 106, 107, - 203, 204, 205, 206, 207, 301, 444, 901) - if not (photon_rx or rx.mt in keep_mts): - continue - - rx_group = rxs_group.create_group('reaction_{:03}'.format(rx.mt)) - rx.to_hdf5(rx_group) - - # Write total nu data if available - if len(rx.derived_products) > 0 and 'total_nu' not in g: - tgroup = g.create_group('total_nu') - rx.derived_products[0].to_hdf5(tgroup) - - # Write unresolved resonance probability tables - if self.urr: - urr_group = g.create_group('urr') - for temperature, urr in self.urr.items(): - tgroup = urr_group.create_group(temperature) - urr.to_hdf5(tgroup) - - # Write fission energy release data - if self.fission_energy is not None: - fer_group = g.create_group('fission_energy_release') - self.fission_energy.to_hdf5(fer_group) - - f.close() - - @classmethod - def from_hdf5(cls, group_or_filename): - """Generate continuous-energy neutron interaction data from HDF5 group - - Parameters - ---------- - group_or_filename : h5py.Group or str - HDF5 group containing interaction data. If given as a string, it is - assumed to be the filename for the HDF5 file, and the first group is - used to read from. - - Returns - ------- - openmc.data.IncidentNeutron - Continuous-energy neutron interaction data - - """ - if isinstance(group_or_filename, h5py.Group): - group = group_or_filename - else: - h5file = h5py.File(str(group_or_filename), 'r') - - # Make sure version matches - if 'version' in h5file.attrs: - major, minor = h5file.attrs['version'] - # For now all versions of HDF5 data can be read - else: - raise IOError( - 'HDF5 data does not indicate a version. Your installation of ' - 'the OpenMC Python API expects version {}.x data.' - .format(HDF5_VERSION_MAJOR)) - - group = list(h5file.values())[0] - - name = group.name[1:] - atomic_number = group.attrs['Z'] - mass_number = group.attrs['A'] - metastable = group.attrs['metastable'] - atomic_weight_ratio = group.attrs['atomic_weight_ratio'] - kTg = group['kTs'] - kTs = [] - for temp in kTg: - kTs.append(kTg[temp][()]) - - data = cls(name, atomic_number, mass_number, metastable, - atomic_weight_ratio, kTs) - - # Read energy grid - e_group = group['energy'] - for temperature, dset in e_group.items(): - data.energy[temperature] = dset[()] - - # Read reaction data - rxs_group = group['reactions'] - for name, obj in sorted(rxs_group.items()): - if name.startswith('reaction_'): - rx = Reaction.from_hdf5(obj, data.energy) - data.reactions[rx.mt] = rx - - # Read total nu data if available - if rx.mt in (18, 19, 20, 21, 38) and 'total_nu' in group: - tgroup = group['total_nu'] - rx.derived_products.append(Product.from_hdf5(tgroup)) - - # Read unresolved resonance probability tables - if 'urr' in group: - urr_group = group['urr'] - for temperature, tgroup in urr_group.items(): - data.urr[temperature] = ProbabilityTables.from_hdf5(tgroup) - - # Read fission energy release data - if 'fission_energy_release' in group: - fer_group = group['fission_energy_release'] - data.fission_energy = FissionEnergyRelease.from_hdf5(fer_group) - - return data - - @classmethod - def from_ace(cls, ace_or_filename, metastable_scheme='nndc'): - """Generate incident neutron continuous-energy data from an ACE table - - Parameters - ---------- - ace_or_filename : openmc.data.ace.Table or str - ACE table to read from. If the value is a string, it is assumed to - be the filename for the ACE file. - metastable_scheme : {'nndc', 'mcnp'} - Determine how ZAID identifiers are to be interpreted in the case of - a metastable nuclide. Because the normal ZAID (=1000*Z + A) does not - encode metastable information, different conventions are used among - different libraries. In MCNP libraries, the convention is to add 400 - for a metastable nuclide except for Am242m, for which 95242 is - metastable and 95642 (or 1095242 in newer libraries) is the ground - state. For NNDC libraries, ZAID is given as 1000*Z + A + 100*m. - - Returns - ------- - openmc.data.IncidentNeutron - Incident neutron continuous-energy data - - """ - - # First obtain the data for the first provided ACE table/file - if isinstance(ace_or_filename, Table): - ace = ace_or_filename - else: - ace = get_table(ace_or_filename) - - # If mass number hasn't been specified, make an educated guess - zaid, xs = ace.name.split('.') - if not xs.endswith('c'): - raise TypeError( - "{} is not a continuous-energy neutron ACE table.".format(ace)) - name, element, Z, mass_number, metastable = \ - get_metadata(int(zaid), metastable_scheme) - - # Assign temperature to the running list - kTs = [ace.temperature*EV_PER_MEV] - - data = cls(name, Z, mass_number, metastable, - ace.atomic_weight_ratio, kTs) - - # Get string of temperature to use as a dictionary key - strT = data.temperatures[0] - - # Read energy grid - n_energy = ace.nxs[3] - i = ace.jxs[1] - energy = ace.xss[i : i + n_energy]*EV_PER_MEV - data.energy[strT] = energy - total_xs = ace.xss[i + n_energy : i + 2*n_energy] - absorption_xs = ace.xss[i + 2*n_energy : i + 3*n_energy] - heating_number = ace.xss[i + 4*n_energy : i + 5*n_energy]*EV_PER_MEV - - # Create redundant reactions (total, absorption, and heating) - total = Reaction(1) - total.xs[strT] = Tabulated1D(energy, total_xs) - total.redundant = True - data.reactions[1] = total - - if np.count_nonzero(absorption_xs) > 0: - absorption = Reaction(101) - absorption.xs[strT] = Tabulated1D(energy, absorption_xs) - absorption.redundant = True - data.reactions[101] = absorption - - heating = Reaction(301) - heating.xs[strT] = Tabulated1D(energy, heating_number*total_xs) - heating.redundant = True - data.reactions[301] = heating - - # Read each reaction - n_reaction = ace.nxs[4] + 1 - for i in range(n_reaction): - rx = Reaction.from_ace(ace, i) - data.reactions[rx.mt] = rx - - # Some photon production reactions may be assigned to MTs that don't - # exist, usually MT=4. In this case, we create a new reaction and add - # them - n_photon_reactions = ace.nxs[6] - photon_mts = ace.xss[ace.jxs[13]:ace.jxs[13] + - n_photon_reactions].astype(int) - - for mt in np.unique(photon_mts // 1000): - if mt not in data: - if mt not in SUM_RULES: - warn('Photon production is present for MT={} but no ' - 'cross section is given.'.format(mt)) - continue - - # Create redundant reaction with appropriate cross section - mts = data.get_reaction_components(mt) - if len(mts) == 0: - warn('Photon production is present for MT={} but no ' - 'reaction components exist.'.format(mt)) - continue - - # Determine redundant cross section - rx = data._get_redundant_reaction(mt, mts) - rx.products += _get_photon_products_ace(ace, rx) - data.reactions[mt] = rx - - # For transmutation reactions, sometimes only individual levels are - # present in an ACE file, e.g. MT=600-649 instead of the summation - # MT=103. In this case, if a user wants to tally (n,p), OpenMC doesn't - # know about the total cross section. Here, we explicitly create a - # redundant reaction for this purpose. - for mt in (16, 103, 104, 105, 106, 107): - if mt not in data: - # Determine if any individual levels are present - mts = data.get_reaction_components(mt) - if len(mts) == 0: - continue - - # Determine redundant cross section - rx = data._get_redundant_reaction(mt, mts) - data.reactions[mt] = rx - - # Make sure redundant cross sections that are present in an ACE file get - # marked as such - for rx in data: - mts = data.get_reaction_components(rx.mt) - if mts != [rx.mt]: - rx.redundant = True - if rx.mt in (203, 204, 205, 206, 207, 444): - rx.redundant = True - - # Read unresolved resonance probability tables - urr = ProbabilityTables.from_ace(ace) - if urr is not None: - data.urr[strT] = urr - - return data - - @classmethod - def from_endf(cls, ev_or_filename, covariance=False): - """Generate incident neutron continuous-energy data from an ENDF evaluation - - Parameters - ---------- - ev_or_filename : openmc.data.endf.Evaluation or str - ENDF evaluation to read from. If given as a string, it is assumed to - be the filename for the ENDF file. - - covariance : bool - Flag to indicate whether or not covariance data from File 32 should be - retrieved - - Returns - ------- - openmc.data.IncidentNeutron - Incident neutron continuous-energy data - - """ - if isinstance(ev_or_filename, Evaluation): - ev = ev_or_filename - else: - ev = Evaluation(ev_or_filename) - - atomic_number = ev.target['atomic_number'] - mass_number = ev.target['mass_number'] - metastable = ev.target['isomeric_state'] - atomic_weight_ratio = ev.target['mass'] - temperature = ev.target['temperature'] - - # Determine name - element = ATOMIC_SYMBOL[atomic_number] - if metastable > 0: - name = '{}{}_m{}'.format(element, mass_number, metastable) - else: - name = '{}{}'.format(element, mass_number) - - # Instantiate incident neutron data - data = cls(name, atomic_number, mass_number, metastable, - atomic_weight_ratio, [temperature]) - - if (2, 151) in ev.section: - data.resonances = res.Resonances.from_endf(ev) - - if (32, 151) in ev.section and covariance: - data.resonance_covariance = ( - res_cov.ResonanceCovariances.from_endf(ev, data.resonances) - ) - - # Read each reaction - for mf, mt, nc, mod in ev.reaction_list: - if mf == 3: - data.reactions[mt] = Reaction.from_endf(ev, mt) - - # Replace cross sections for elastic, capture, fission - try: - if any(isinstance(r, res._RESOLVED) for r in data.resonances): - for mt in (2, 102, 18): - if mt in data.reactions: - rx = data.reactions[mt] - rx.xs['0K'] = ResonancesWithBackground( - data.resonances, rx.xs['0K'], mt) - except ValueError: - # Thrown if multiple resolved ranges (e.g. Pu239 in ENDF/B-VII.1) - pass - - # If first-chance, second-chance, etc. fission are present, check - # whether energy distributions were specified in MF=5. If not, copy the - # energy distribution from MT=18. - for mt, rx in data.reactions.items(): - if mt in (19, 20, 21, 38): - if (5, mt) not in ev.section: - if rx.products: - neutron = data.reactions[18].products[0] - rx.products[0].applicability = neutron.applicability - rx.products[0].distribution = neutron.distribution - - # Read fission energy release (requires that we already know nu for - # fission) - if (1, 458) in ev.section: - data.fission_energy = FissionEnergyRelease.from_endf(ev, data) - - data._evaluation = ev - return data - - @classmethod - def from_njoy(cls, filename, temperatures=None, evaluation=None, **kwargs): - """Generate incident neutron data by running NJOY. - - Parameters - ---------- - filename : str - Path to ENDF file - temperatures : iterable of float - Temperatures in Kelvin to produce data at. If omitted, data is - produced at room temperature (293.6 K) - evaluation : openmc.data.endf.Evaluation, optional - If the ENDF file contains multiple material evaluations, this - argument indicates which evaluation to use. - **kwargs - Keyword arguments passed to :func:`openmc.data.njoy.make_ace` - - Returns - ------- - data : openmc.data.IncidentNeutron - Incident neutron continuous-energy data - - """ - with tempfile.TemporaryDirectory() as tmpdir: - # Run NJOY to create an ACE library - kwargs.setdefault("output_dir", tmpdir) - for key in ("acer", "pendf", "heatr", "broadr", "gaspr", "purr"): - kwargs.setdefault(key, os.path.join(kwargs["output_dir"], key)) - kwargs['evaluation'] = evaluation - make_ace(filename, temperatures, **kwargs) - - # Create instance from ACE tables within library - lib = Library(kwargs['acer']) - data = cls.from_ace(lib.tables[0]) - for table in lib.tables[1:]: - data.add_temperature_from_ace(table) - - # Add 0K elastic scattering cross section - if '0K' not in data.energy: - pendf = Evaluation(kwargs['pendf']) - file_obj = StringIO(pendf.section[3, 2]) - get_head_record(file_obj) - params, xs = get_tab1_record(file_obj) - data.energy['0K'] = xs.x - data[2].xs['0K'] = xs - - # Add fission energy release data - ev = evaluation if evaluation is not None else Evaluation(filename) - if (1, 458) in ev.section: - data.fission_energy = f = FissionEnergyRelease.from_endf(ev, data) - else: - f = None - - # For energy deposition, we want to store two different KERMAs: - # one calculated assuming outgoing photons deposit their energy - # locally, and one calculated assuming they carry their energy - # away. This requires two HEATR runs (which make_ace does by - # default). Here, we just need to correct for the fact that NJOY - # uses a fission heating number of h = EFR, whereas we want: - # - # 1) h = EFR + EGP + EGD + EB (for local case) - # 2) h = EFR + EB (for non-local case) - # - # The best way to handle this is to subtract off the fission - # KERMA that NJOY calculates and add back exactly what we want. - - # If NJOY is not run with HEATR at all, skip everything below - if not kwargs["heatr"]: - return data - - # Helper function to get a cross section from an ENDF file on a - # given energy grid - def get_file3_xs(ev, mt, E): - file_obj = StringIO(ev.section[3, mt]) - get_head_record(file_obj) - _, xs = get_tab1_record(file_obj) - return xs(E) - - heating_local = Reaction(901) - heating_local.redundant = True - - heatr_evals = get_evaluations(kwargs["heatr"]) - heatr_local_evals = get_evaluations(kwargs["heatr"] + "_local") - for ev, ev_local in zip(heatr_evals, heatr_local_evals): - temp = "{}K".format(round(ev.target["temperature"])) - - # Get total KERMA (originally from ACE file) and energy grid - kerma = data.reactions[301].xs[temp] - E = kerma.x - - if f is not None: - # Replace fission KERMA with (EFR + EB)*sigma_f - fission = data.reactions[18].xs[temp] - kerma_fission = get_file3_xs(ev, 318, E) - kerma.y = kerma.y - kerma_fission + ( - f.fragments(E) + f.betas(E)) * fission(E) - - # For local KERMA, we first need to get the values from the - # HEATR run with photon energy deposited locally and put - # them on the same energy grid - kerma_local = get_file3_xs(ev_local, 301, E) - - if f is not None: - # When photons deposit their energy locally, we replace the - # fission KERMA with (EFR + EGP + EGD + EB)*sigma_f - kerma_fission_local = get_file3_xs(ev_local, 318, E) - kerma_local = kerma_local - kerma_fission_local + ( - f.fragments(E) + f.prompt_photons(E) - + f.delayed_photons(E) + f.betas(E))*fission(E) - - heating_local.xs[temp] = Tabulated1D(E, kerma_local) - - data.reactions[901] = heating_local - - return data - - def _get_redundant_reaction(self, mt, mts): - """Create redundant reaction from its components - - Parameters - ---------- - mt : int - MT value of the desired reaction - mts : iterable of int - MT values of its components - - Returns - ------- - openmc.Reaction - Redundant reaction - - """ - # Get energy grid - strT = self.temperatures[0] - energy = self.energy[strT] - - rx = Reaction(mt) - xss = [self.reactions[mt_i].xs[strT] for mt_i in mts] - idx = min([xs._threshold_idx if hasattr(xs, '_threshold_idx') - else 0 for xs in xss]) - rx.xs[strT] = Tabulated1D(energy[idx:], Sum(xss)(energy[idx:])) - rx.xs[strT]._threshold_idx = idx - rx.redundant = True - - return rx diff --git a/openmc/data/njoy.py b/openmc/data/njoy.py deleted file mode 100644 index 0c853102f..000000000 --- a/openmc/data/njoy.py +++ /dev/null @@ -1,593 +0,0 @@ -from collections import namedtuple -from io import StringIO -import os -import shutil -from subprocess import Popen, PIPE, STDOUT, CalledProcessError -import tempfile -from pathlib import Path - -from . import endf - - -# For a given MAT number, give a name for the ACE table and a list of ZAID -# identifiers. This is based on Appendix C in the ENDF manual. -ThermalTuple = namedtuple('ThermalTuple', ['name', 'zaids', 'nmix']) -_THERMAL_DATA = { - 1: ThermalTuple('hh2o', [1001], 1), - 2: ThermalTuple('parah', [1001], 1), - 3: ThermalTuple('orthoh', [1001], 1), - 5: ThermalTuple('hyh2', [1001], 1), - 7: ThermalTuple('hzrh', [1001], 1), - 8: ThermalTuple('hcah2', [1001], 1), - 10: ThermalTuple('hice', [1001], 1), - 11: ThermalTuple('dd2o', [1002], 1), - 12: ThermalTuple('parad', [1002], 1), - 13: ThermalTuple('orthod', [1002], 1), - 14: ThermalTuple('dice', [1002], 1), - 26: ThermalTuple('be', [4009], 1), - 27: ThermalTuple('bebeo', [4009], 1), - 28: ThermalTuple('bebe2c', [4009], 1), - 30: ThermalTuple('graph', [6000, 6012, 6013], 1), - 31: ThermalTuple('grph10', [6000, 6012, 6013], 1), - 32: ThermalTuple('grph30', [6000, 6012, 6013], 1), - 33: ThermalTuple('lch4', [1001], 1), - 34: ThermalTuple('sch4', [1001], 1), - 35: ThermalTuple('sch4p2', [1001], 1), - 37: ThermalTuple('hch2', [1001], 1), - 38: ThermalTuple('mesi00', [1001], 1), - 39: ThermalTuple('lucite', [1001], 1), - 40: ThermalTuple('benz', [1001, 6000, 6012], 2), - 42: ThermalTuple('tol00', [1001], 1), - 43: ThermalTuple('sisic', [14028, 14029, 14030], 1), - 44: ThermalTuple('csic', [6000, 6012, 6013], 1), - 45: ThermalTuple('ouo2', [8016, 8017, 8018], 1), - 46: ThermalTuple('obeo', [8016, 8017, 8018], 1), - 47: ThermalTuple('sio2-a', [8016, 8017, 8018, 14028, 14029, 14030], 3), - 48: ThermalTuple('osap00', [92238], 1), - 49: ThermalTuple('sio2-b', [8016, 8017, 8018, 14028, 14029, 14030], 3), - 50: ThermalTuple('oice', [8016, 8017, 8018], 1), - 51: ThermalTuple('od2o', [8016, 8017, 8018], 1), - 52: ThermalTuple('mg24', [12024], 1), - 53: ThermalTuple('al27', [13027], 1), - 55: ThermalTuple('yyh2', [39089], 1), - 56: ThermalTuple('fe56', [26056], 1), - 58: ThermalTuple('zrzrh', [40000, 40090, 40091, 40092, 40094, 40096], 1), - 59: ThermalTuple('si00', [14028], 1), - 60: ThermalTuple('asap00', [13027], 1), - 71: ThermalTuple('n-un', [7014, 7015], 1), - 72: ThermalTuple('u-un', [92238], 1), - 75: ThermalTuple('uuo2', [8016, 8017, 8018], 1), -} - - -def _get_thermal_data(ev, mat): - """Return appropriate ThermalTuple, accounting for bugs.""" - - # JEFF assigns MAT=59 to Ca in CaH2 (which is supposed to be silicon). - if ev.info['library'][0] == 'JEFF': - if ev.material == 59: - if 'CaH2' in ''.join(ev.info['description']): - zaids = [20040, 20042, 20043, 20044, 20046, 20048] - return ThermalTuple('cacah2', zaids, 1) - - # Before ENDF/B-VIII.0, crystalline graphite was MAT=31 - if ev.info['library'] != ('ENDF/B', 8, 0): - if ev.material == 31: - return _THERMAL_DATA[30] - - # ENDF/B incorrectly assigns MAT numbers for UO2 - # - # Material | ENDF Manual | VII.0 | VII.1 | VIII.0 - # ---------|-------------|-------|-------|------- - # O in UO2 | 45 | 75 | 75 | 75 - # U in UO2 | 75 | 76 | 48 | 48 - if ev.info['library'][0] == 'ENDF/B': - if ev.material == 75: - return _THERMAL_DATA[45] - version = ev.info['library'][1:] - if version in ((7, 1), (8, 0)) and ev.material == 48: - return _THERMAL_DATA[75] - if version == (7, 0) and ev.material == 76: - return _THERMAL_DATA[75] - - # If not a problematic material, use the dictionary as is - return _THERMAL_DATA[mat] - - -_TEMPLATE_RECONR = """ -reconr / %%%%%%%%%%%%%%%%%%% Reconstruct XS for neutrons %%%%%%%%%%%%%%%%%%%%%%% -{nendf} {npendf} -'{library} PENDF for {zsymam}'/ -{mat} 2/ -{error}/ err -'{library}: {zsymam}'/ -'Processed by NJOY'/ -0/ -""" - -_TEMPLATE_BROADR = """ -broadr / %%%%%%%%%%%%%%%%%%%%%%% Doppler broaden XS %%%%%%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {npendf} {nbroadr} -{mat} {num_temp} 0 0 0. / -{error}/ errthn -{temps} -0/ -""" - -_TEMPLATE_HEATR = """ -heatr / %%%%%%%%%%%%%%%%%%%%%%%%% Add heating kerma %%%%%%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {nheatr_in} {nheatr} / -{mat} 4 0 0 0 / -302 318 402 444 / -""" - -_TEMPLATE_HEATR_LOCAL = """ -heatr / %%%%%%%%%%%%%%%%% Add heating kerma (local photons) %%%%%%%%%%%%%%%%%%%% -{nendf} {nheatr_in} {nheatr_local} / -{mat} 4 0 0 1 / -302 318 402 444 / -""" - -_TEMPLATE_GASPR = """ -gaspr / %%%%%%%%%%%%%%%%%%%%%%%%% Add gas production %%%%%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {ngaspr_in} {ngaspr} / -""" - -_TEMPLATE_PURR = """ -purr / %%%%%%%%%%%%%%%%%%%%%%%% Add probability tables %%%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {npurr_in} {npurr} / -{mat} {num_temp} 1 20 64 / -{temps} -1.e10 -0/ -""" - -_TEMPLATE_ACER = """ -acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {nacer_in} 0 {nace} {ndir} -1 0 1 .{ext} / -'{library}: {zsymam} at {temperature}'/ -{mat} {temperature} -1 1/ -/ -""" - -_THERMAL_TEMPLATE_THERMR = """ -thermr / %%%%%%%%%%%%%%%% Add thermal scattering data (free gas) %%%%%%%%%%%%%%% -0 {nthermr1_in} {nthermr1} -0 {mat} 12 {num_temp} 1 0 {iform} 1 221 1/ -{temps} -{error} {energy_max} -thermr / %%%%%%%%%%%%%%%% Add thermal scattering data (bound) %%%%%%%%%%%%%%%%%% -{nthermal_endf} {nthermr2_in} {nthermr2} -{mat_thermal} {mat} 16 {num_temp} {inelastic} {elastic} {iform} {natom} 222 1/ -{temps} -{error} {energy_max} -""" - -_THERMAL_TEMPLATE_ACER = """ -acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%% -{nendf} {nthermal_acer_in} 0 {nace} {ndir} -2 0 1 .{ext}/ -'{library}: {zsymam_thermal} processed by NJOY'/ -{mat} {temperature} '{data.name}' / -{zaids} / -222 64 {mt_elastic} {elastic_type} {data.nmix} {energy_max} {iwt}/ -""" - - -def run(commands, tapein, tapeout, input_filename=None, stdout=False, - njoy_exec='njoy'): - """Run NJOY with given commands - - Parameters - ---------- - commands : str - Input commands for NJOY - tapein : dict - Dictionary mapping tape numbers to paths for any input files - tapeout : dict - Dictionary mapping tape numbers to paths for any output files - input_filename : str, optional - File name to write out NJOY input commands - stdout : bool, optional - Whether to display output when running NJOY - njoy_exec : str, optional - Path to NJOY executable - - Raises - ------ - subprocess.CalledProcessError - If the NJOY process returns with a non-zero status - - """ - - if input_filename is not None: - with open(str(input_filename), 'w') as f: - f.write(commands) - - 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)) - shutil.copy(str(filename), tmpfilename) - - # Start up NJOY process - njoy = Popen([njoy_exec], cwd=tmpdir, stdin=PIPE, stdout=PIPE, - stderr=STDOUT, universal_newlines=True) - - 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, str(filename)) - - -def make_pendf(filename, pendf='pendf', error=0.001, stdout=False): - """Generate pointwise ENDF file from an ENDF file - - Parameters - ---------- - filename : str - Path to ENDF file - pendf : str, optional - Path of pointwise ENDF file to write - error : float, optional - Fractional error tolerance for NJOY processing - stdout : bool - Whether to display NJOY standard output - - Raises - ------ - subprocess.CalledProcessError - If the NJOY process returns with a non-zero status - - """ - - make_ace(filename, pendf=pendf, error=error, broadr=False, - heatr=False, purr=False, acer=False, stdout=stdout) - - -def make_ace(filename, temperatures=None, acer=True, xsdir=None, - output_dir=None, pendf=False, error=0.001, broadr=True, - heatr=True, gaspr=True, purr=True, evaluation=None, **kwargs): - """Generate incident neutron ACE file from an ENDF file - - File names can be passed to - ``[acer, xsdir, pendf, broadr, heatr, gaspr, purr]`` - to specify the exact output for the given module. - Otherwise, the files will be writen to the current directory - or directory specified by ``output_dir``. Default file - names mirror the variable names, e.g. ``heatr`` output - will be written to a file named ``heatr`` unless otherwise - specified. - - Parameters - ---------- - filename : str - Path to ENDF file - temperatures : iterable of float, optional - Temperatures in Kelvin to produce ACE files at. If omitted, data is - produced at room temperature (293.6 K). - acer : bool or str, optional - Flag indicating if acer should be run. If a string is give, write the - resulting ``ace`` file to this location. Path of ACE file to write. - Defaults to ``"ace"`` - xsdir : str, optional - Path of xsdir file to write. Defaults to ``"xsdir"`` in the same - directory as ``acer`` - output_dir : str, optional - Directory to write output for requested modules. If not provided - and at least one of ``[pendf, broadr, heatr, gaspr, purr, acer]`` - is ``True``, then write output files to current directory. If given, - must be a path to a directory. - pendf : str, optional - Path of pendf file to write. If omitted, the pendf file is not saved. - error : float, optional - Fractional error tolerance for NJOY processing - broadr : bool or str, optional - Indicating whether to Doppler broaden XS when running NJOY. If string, - write the output tape to this file. - heatr : bool or str, optional - Indicating whether to add heating kerma when running NJOY. If string, - write the output tape to this file. - gaspr : bool or str, optional - Indicating whether to add gas production data when running NJOY. - If string, write the output tape to this file. - purr : bool or str, optional - Indicating whether to add probability table when running NJOY. - If string, write the output tape to this file. - evaluation : openmc.data.endf.Evaluation, optional - If the ENDF file contains multiple material evaluations, this argument - indicates which evaluation should be used. - **kwargs - Keyword arguments passed to :func:`openmc.data.njoy.run` - - Raises - ------ - subprocess.CalledProcessError - If the NJOY process returns with a non-zero status - IOError - If ``output_dir`` does not point to a directory - - """ - if output_dir is None: - output_dir = Path() - else: - output_dir = Path(output_dir) - if not output_dir.is_dir(): - raise IOError("{} is not a directory".format(output_dir)) - - ev = evaluation if evaluation is not None else endf.Evaluation(filename) - mat = ev.material - zsymam = ev.target['zsymam'] - - # Determine name of library - library = '{}-{}.{}'.format(*ev.info['library']) - - if temperatures is None: - temperatures = [293.6] - num_temp = len(temperatures) - temps = ' '.join(str(i) for i in temperatures) - - # Create njoy commands by modules - commands = "" - - nendf, npendf = 20, 21 - tapein = {nendf: filename} - tapeout = {} - if pendf: - tapeout[npendf] = (output_dir / "pendf") if pendf is True else pendf - - # reconr - commands += _TEMPLATE_RECONR - nlast = npendf - - # broadr - if broadr: - nbroadr = nlast + 1 - tapeout[nbroadr] = (output_dir / "broadr") if broadr is True else broadr - commands += _TEMPLATE_BROADR - nlast = nbroadr - - # heatr - if heatr: - nheatr_in = nlast - nheatr_local = nheatr_in + 1 - tapeout[nheatr_local] = (output_dir / "heatr_local") if heatr is True \ - else heatr + '_local' - commands += _TEMPLATE_HEATR_LOCAL - nheatr = nheatr_local + 1 - tapeout[nheatr] = (output_dir / "heatr") if heatr is True else heatr - commands += _TEMPLATE_HEATR - nlast = nheatr - - # gaspr - if gaspr: - ngaspr_in = nlast - ngaspr = ngaspr_in + 1 - tapeout[ngaspr] = (output_dir / "gaspr") if gaspr is True else gaspr - commands += _TEMPLATE_GASPR - nlast = ngaspr - - # purr - if purr: - npurr_in = nlast - npurr = npurr_in + 1 - tapeout[npurr] = (output_dir / "purr") if purr is True else purr - commands += _TEMPLATE_PURR - nlast = npurr - - commands = commands.format(**locals()) - - # acer - if acer: - nacer_in = nlast - fname = '{}_{:.1f}' - for i, temperature in enumerate(temperatures): - # Extend input with an ACER run for each temperature - nace = nacer_in + 1 + 2*i - ndir = nace + 1 - ext = '{:02}'.format(i + 1) - commands += _TEMPLATE_ACER.format(**locals()) - - # Indicate tapes to save for each ACER run - tapeout[nace] = fname.format("ace", temperature) - tapeout[ndir] = fname.format("xsdir", temperature) - commands += 'stop\n' - run(commands, tapein, tapeout, **kwargs) - - if acer: - ace = (output_dir / "ace") if acer is True else Path(acer) - xsdir = (ace.parent / "xsdir") if xsdir is None else xsdir - with ace.open('w') as ace_file, xsdir.open('w') as xsdir_file: - for temperature in temperatures: - # Get contents of ACE file - text = open(fname.format("ace", temperature), 'r').read() - - # If the target is metastable, make sure that ZAID in the ACE - # file reflects this by adding 400 - if ev.target['isomeric_state'] > 0: - mass_first_digit = int(text[3]) - if mass_first_digit <= 2: - text = text[:3] + str(mass_first_digit + 4) + text[4:] - - # Concatenate into destination ACE file - ace_file.write(text) - - # Concatenate into destination xsdir file - 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)) - - -def make_ace_thermal(filename, filename_thermal, temperatures=None, - ace='ace', xsdir='xsdir', error=0.001, iwt=2, - evaluation=None, evaluation_thermal=None, **kwargs): - """Generate thermal scattering ACE file from ENDF files - - Parameters - ---------- - filename : str - Path to ENDF neutron sublibrary file - filename_thermal : str - Path to ENDF thermal scattering sublibrary file - temperatures : iterable of float, optional - Temperatures in Kelvin to produce data at. If omitted, data is produced - at all temperatures given in the ENDF thermal scattering sublibrary. - ace : str, optional - Path of ACE file to write - xsdir : str, optional - Path of xsdir file to write - error : float, optional - Fractional error tolerance for NJOY processing - iwt : int - `iwt` parameter used in NJOR/ACER card 9 - evaluation : openmc.data.endf.Evaluation, optional - If the ENDF neutron sublibrary file contains multiple material - evaluations, this argument indicates which evaluation to use. - evaluation_thermal : openmc.data.endf.Evaluation, optional - If the ENDF thermal scattering sublibrary file contains multiple - material evaluations, this argument indicates which evaluation to use. - **kwargs - Keyword arguments passed to :func:`openmc.data.njoy.run` - - Raises - ------ - subprocess.CalledProcessError - If the NJOY process returns with a non-zero status - - """ - ev = evaluation if evaluation is not None else endf.Evaluation(filename) - mat = ev.material - zsymam = ev.target['zsymam'] - - ev_thermal = (evaluation_thermal if evaluation_thermal is not None - else endf.Evaluation(filename_thermal)) - mat_thermal = ev_thermal.material - zsymam_thermal = ev_thermal.target['zsymam'] - - # Determine name, isotopes based on MAT number - data = _get_thermal_data(ev_thermal, mat_thermal) - zaids = ' '.join(str(zaid) for zaid in data.zaids[:3]) - - # Determine name of library - library = '{}-{}.{}'.format(*ev_thermal.info['library']) - - # Determine if thermal elastic is present - if (7, 2) in ev_thermal.section: - elastic = 1 - mt_elastic = 223 - - # Determine whether elastic is incoherent (0) or coherent (1) - file_obj = StringIO(ev_thermal.section[7, 2]) - elastic_type = endf.get_head_record(file_obj)[2] - 1 - else: - elastic = 0 - mt_elastic = 0 - elastic_type = 0 - - # Determine number of principal atoms - file_obj = StringIO(ev_thermal.section[7, 4]) - items = endf.get_head_record(file_obj) - items, values = endf.get_list_record(file_obj) - energy_max = values[3] - natom = int(values[5]) - - # Note that the 'iform' parameter is omitted in NJOY 99. We assume that the - # user is using NJOY 2012 or later. - iform = 0 - inelastic = 2 - - # Determine temperatures from MF=7, MT=4 if none were specified - if temperatures is None: - file_obj = StringIO(ev_thermal.section[7, 4]) - endf.get_head_record(file_obj) - endf.get_list_record(file_obj) - endf.get_tab2_record(file_obj) - params = endf.get_tab1_record(file_obj)[0] - temperatures = [params[0]] - for i in range(params[2]): - temperatures.append(endf.get_list_record(file_obj)[0][0]) - - num_temp = len(temperatures) - temps = ' '.join(str(i) for i in temperatures) - - # Create njoy commands by modules - commands = "" - - nendf, nthermal_endf, npendf = 20, 21, 22 - tapein = {nendf: filename, nthermal_endf: filename_thermal} - tapeout = {} - - # reconr - commands += _TEMPLATE_RECONR - nlast = npendf - - # broadr - nbroadr = nlast + 1 - commands += _TEMPLATE_BROADR - nlast = nbroadr - - # thermr - nthermr1_in = nlast - nthermr1 = nthermr1_in + 1 - nthermr2_in = nthermr1 - nthermr2 = nthermr2_in + 1 - commands += _THERMAL_TEMPLATE_THERMR - nlast = nthermr2 - - commands = commands.format(**locals()) - - # acer - nthermal_acer_in = nlast - fname = '{}_{:.1f}' - for i, temperature in enumerate(temperatures): - # Extend input with an ACER run for each temperature - nace = nthermal_acer_in + 1 + 2*i - ndir = nace + 1 - ext = '{:02}'.format(i + 1) - commands += _THERMAL_TEMPLATE_ACER.format(**locals()) - - # Indicate tapes to save for each ACER run - tapeout[nace] = fname.format(ace, temperature) - tapeout[ndir] = fname.format(xsdir, temperature) - commands += 'stop\n' - run(commands, tapein, tapeout, **kwargs) - - 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 - for temperature in temperatures: - os.remove(fname.format(ace, temperature)) - os.remove(fname.format(xsdir, temperature)) diff --git a/openmc/data/photon.py b/openmc/data/photon.py deleted file mode 100644 index 3766b697e..000000000 --- a/openmc/data/photon.py +++ /dev/null @@ -1,1306 +0,0 @@ -from collections import OrderedDict -from collections.abc import Mapping, Callable -from copy import deepcopy -from io import StringIO -from numbers import Integral, Real -from math import pi, sqrt -import os - -import h5py -import numpy as np -import pandas as pd -from scipy.interpolate import CubicSpline -from scipy.integrate import quad - -from openmc.mixin import EqualityMixin -import openmc.checkvalue as cv -from . import HDF5_VERSION -from .ace import Table, get_metadata, get_table -from .data import ATOMIC_SYMBOL, EV_PER_MEV -from .endf import Evaluation, get_head_record, get_tab1_record, get_list_record -from .function import Tabulated1D - - -# Constants -MASS_ELECTRON_EV = 0.5109989461e6 # Electron mass energy -PLANCK_C = 1.2398419739062977e4 # Planck's constant times c in eV-Angstroms -FINE_STRUCTURE = 137.035999139 # Inverse fine structure constant -CM_PER_ANGSTROM = 1.0e-8 -# classical electron radius in cm -R0 = CM_PER_ANGSTROM * PLANCK_C / (2.0 * pi * FINE_STRUCTURE * MASS_ELECTRON_EV) - -# Electron subshell labels -_SUBSHELLS = [None, 'K', 'L1', 'L2', 'L3', 'M1', 'M2', 'M3', 'M4', 'M5', - 'N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'O1', 'O2', 'O3', - 'O4', 'O5', 'O6', 'O7', 'O8', 'O9', 'P1', 'P2', 'P3', 'P4', - 'P5', 'P6', 'P7', 'P8', 'P9', 'P10', 'P11','Q1', 'Q2', 'Q3'] - -_REACTION_NAME = { - 501: ('Total photon interaction', 'total'), - 502: ('Photon coherent scattering', 'coherent'), - 504: ('Photon incoherent scattering', 'incoherent'), - 515: ('Pair production, electron field', 'pair_production_electron'), - 516: ('Total pair production', 'pair_production_total'), - 517: ('Pair production, nuclear field', 'pair_production_nuclear'), - 522: ('Photoelectric absorption', 'photoelectric'), - 525: ('Heating', 'heating'), - 526: ('Electro-atomic scattering', 'electro_atomic_scat'), - 527: ('Electro-atomic bremsstrahlung', 'electro_atomic_brem'), - 528: ('Electro-atomic excitation', 'electro_atomic_excit'), - 534: ('K (1s1/2) subshell photoelectric', 'K'), - 535: ('L1 (2s1/2) subshell photoelectric', 'L1'), - 536: ('L2 (2p1/2) subshell photoelectric', 'L2'), - 537: ('L3 (2p3/2) subshell photoelectric', 'L3'), - 538: ('M1 (3s1/2) subshell photoelectric', 'M1'), - 539: ('M2 (3p1/2) subshell photoelectric', 'M2'), - 540: ('M3 (3p3/2) subshell photoelectric', 'M3'), - 541: ('M4 (3d3/2) subshell photoelectric', 'M4'), - 542: ('M5 (3d5/2) subshell photoelectric', 'M5'), - 543: ('N1 (4s1/2) subshell photoelectric', 'N1'), - 544: ('N2 (4p1/2) subshell photoelectric', 'N2'), - 545: ('N3 (4p3/2) subshell photoelectric', 'N3'), - 546: ('N4 (4d3/2) subshell photoelectric', 'N4'), - 547: ('N5 (4d5/2) subshell photoelectric', 'N5'), - 548: ('N6 (4f5/2) subshell photoelectric', 'N6'), - 549: ('N7 (4f7/2) subshell photoelectric', 'N7'), - 550: ('O1 (5s1/2) subshell photoelectric', 'O1'), - 551: ('O2 (5p1/2) subshell photoelectric', 'O2'), - 552: ('O3 (5p3/2) subshell photoelectric', 'O3'), - 553: ('O4 (5d3/2) subshell photoelectric', 'O4'), - 554: ('O5 (5d5/2) subshell photoelectric', 'O5'), - 555: ('O6 (5f5/2) subshell photoelectric', 'O6'), - 556: ('O7 (5f7/2) subshell photoelectric', 'O7'), - 557: ('O8 (5g7/2) subshell photoelectric', 'O8'), - 558: ('O9 (5g9/2) subshell photoelectric', 'O9'), - 559: ('P1 (6s1/2) subshell photoelectric', 'P1'), - 560: ('P2 (6p1/2) subshell photoelectric', 'P2'), - 561: ('P3 (6p3/2) subshell photoelectric', 'P3'), - 562: ('P4 (6d3/2) subshell photoelectric', 'P4'), - 563: ('P5 (6d5/2) subshell photoelectric', 'P5'), - 564: ('P6 (6f5/2) subshell photoelectric', 'P6'), - 565: ('P7 (6f7/2) subshell photoelectric', 'P7'), - 566: ('P8 (6g7/2) subshell photoelectric', 'P8'), - 567: ('P9 (6g9/2) subshell photoelectric', 'P9'), - 568: ('P10 (6h9/2) subshell photoelectric', 'P10'), - 569: ('P11 (6h11/2) subshell photoelectric', 'P11'), - 570: ('Q1 (7s1/2) subshell photoelectric', 'Q1'), - 571: ('Q2 (7p1/2) subshell photoelectric', 'Q2'), - 572: ('Q3 (7p3/2) subshell photoelectric', 'Q3') -} - -# Compton profiles are read from a pre-generated HDF5 file when they are first -# needed. The dictionary stores an array of electron momentum values (at which -# the profiles are tabulated) with the key 'pz' and the profile for each element -# is a 2D array with shape (n_shells, n_momentum_values) stored on the key Z -_COMPTON_PROFILES = {} - -# Scaled bremsstrahlung DCSs are read from a data file provided by Selzter and -# Berger when they are first needed. The dictionary stores an array of n -# incident electron kinetic energies with key 'electron_energies', an array of -# k reduced photon energies with key 'photon_energies', and the cross sections -# for each element are in a 2D array with shape (n, k) stored on the key 'Z'. -# It also stores data used for calculating the density effect correction and -# stopping power, namely, the mean excitation energy with the key 'I', number -# of electrons per subshell with the key 'num_electrons', and binding energies -# with the key 'ionization_energy'. -_BREMSSTRAHLUNG = {} - - -class AtomicRelaxation(EqualityMixin): - """Atomic relaxation data. - - This class stores the binding energy, number of electrons, and electron - transitions possible from ioniziation for each electron subshell of an - atom. All of the data originates from an ENDF-6 atomic relaxation - sub-library (NSUB=6). Instances of this class are not normally instantiated - directly but rather created using the factory method - :math:`AtomicRelaxation.from_endf`. - - Parameters - ---------- - binding_energy : dict - Dictionary indicating the binding energy in eV (values) for given - subshells (keys). The subshells should be given as strings, e.g., 'K', - 'L1', 'L2', etc. - num_electrons : dict - Dictionary indicating the number of electrons in a subshell when neutral - (values) for given subshells (keys). The subshells should be given as - strings, e.g., 'K', 'L1', 'L2', etc. - transitions : pandas.DataFrame - Dictionary indicating allowed transitions and their probabilities - (values) for given subshells (keys). The subshells should be given as - strings, e.g., 'K', 'L1', 'L2', etc. The transitions are represented as - a DataFrame with columns indicating the secondary and tertiary subshell, - the energy of the transition in eV, and the fractional probability of - the transition. - - Attributes - ---------- - binding_energy : dict - Dictionary indicating the binding energy in eV (values) for given - subshells (keys). The subshells should be given as strings, e.g., 'K', - 'L1', 'L2', etc. - num_electrons : dict - Dictionary indicating the number of electrons in a subshell when neutral - (values) for given subshells (keys). The subshells should be given as - strings, e.g., 'K', 'L1', 'L2', etc. - transitions : pandas.DataFrame - Dictionary indicating allowed transitions and their probabilities - (values) for given subshells (keys). The subshells should be given as - strings, e.g., 'K', 'L1', 'L2', etc. The transitions are represented as - a DataFrame with columns indicating the secondary and tertiary subshell, - the energy of the transition in eV, and the fractional probability of - the transition. - - See Also - -------- - IncidentPhoton - - """ - def __init__(self, binding_energy, num_electrons, transitions): - self.binding_energy = binding_energy - self.num_electrons = num_electrons - self.transitions = transitions - self._e_fluorescence = {} - - @property - def binding_energy(self): - return self._binding_energy - - @property - def num_electrons(self): - return self._num_electrons - - @property - def subshells(self): - return list(sorted(self.binding_energy.keys())) - - @property - def transitions(self): - return self._transitions - - @binding_energy.setter - def binding_energy(self, binding_energy): - cv.check_type('binding energies', binding_energy, Mapping) - for subshell, energy in binding_energy.items(): - cv.check_value('subshell', subshell, _SUBSHELLS) - cv.check_type('binding energy', energy, Real) - cv.check_greater_than('binding energy', energy, 0.0, True) - self._binding_energy = binding_energy - - @num_electrons.setter - def num_electrons(self, num_electrons): - cv.check_type('number of electrons', num_electrons, Mapping) - for subshell, num in num_electrons.items(): - cv.check_value('subshell', subshell, _SUBSHELLS) - cv.check_type('number of electrons', num, Real) - cv.check_greater_than('number of electrons', num, 0.0, True) - self._num_electrons = num_electrons - - @transitions.setter - def transitions(self, transitions): - cv.check_type('transitions', transitions, Mapping) - for subshell, df in transitions.items(): - cv.check_value('subshell', subshell, _SUBSHELLS) - cv.check_type('transitions', df, pd.DataFrame) - self._transitions = transitions - - @classmethod - def from_ace(cls, ace): - """Generate atomic relaxation data from an ACE file - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - - Returns - ------- - openmc.data.AtomicRelaxation - Atomic relaxation data - - """ - # Create data dictionaries - binding_energy = {} - num_electrons = {} - transitions = {} - - # Get shell designators - n = ace.nxs[7] - idx = ace.jxs[11] - shells = [_SUBSHELLS[int(i)] for i in ace.xss[idx : idx+n]] - - # Get number of electrons for each shell - idx = ace.jxs[12] - for shell, num in zip(shells, ace.xss[idx : idx+n]): - num_electrons[shell] = num - - # Get binding energy for each shell - idx = ace.jxs[13] - for shell, e in zip(shells, ace.xss[idx : idx+n]): - binding_energy[shell] = e*EV_PER_MEV - - # Get transition table - columns = ['secondary', 'tertiary', 'energy (eV)', 'probability'] - idx = ace.jxs[18] - for i, subi in enumerate(shells): - n_transitions = int(ace.xss[ace.jxs[15] + i]) - if n_transitions > 0: - records = [] - for j in range(n_transitions): - subj = _SUBSHELLS[int(ace.xss[idx])] - subk = _SUBSHELLS[int(ace.xss[idx + 1])] - etr = ace.xss[idx + 2]*EV_PER_MEV - if j == 0: - ftr = ace.xss[idx + 3] - else: - ftr = ace.xss[idx + 3] - ace.xss[idx - 1] - records.append((subj, subk, etr, ftr)) - idx += 4 - - # Create dataframe for transitions - transitions[subi] = pd.DataFrame.from_records( - records, columns=columns) - - return cls(binding_energy, num_electrons, transitions) - - @classmethod - def from_endf(cls, ev_or_filename): - """Generate atomic relaxation data from an ENDF evaluation - - Parameters - ---------- - ev_or_filename : str or openmc.data.endf.Evaluation - ENDF atomic relaxation evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Returns - ------- - openmc.data.AtomicRelaxation - Atomic relaxation data - - """ - if isinstance(ev_or_filename, Evaluation): - ev = ev_or_filename - else: - ev = Evaluation(ev_or_filename) - - # Atomic relaxation data is always MF=28, MT=533 - if (28, 533) not in ev.section: - raise IOError('{} does not appear to be an atomic relaxation ' - 'sublibrary.'.format(ev)) - - # Determine number of subshells - file_obj = StringIO(ev.section[28, 533]) - params = get_head_record(file_obj) - n_subshells = params[4] - - # Create data dictionaries - binding_energy = {} - num_electrons = {} - transitions = {} - columns = ['secondary', 'tertiary', 'energy (eV)', 'probability'] - - # Read data for each subshell - for i in range(n_subshells): - params, list_items = get_list_record(file_obj) - subi = _SUBSHELLS[int(params[0])] - n_transitions = int(params[5]) - binding_energy[subi] = list_items[0] - num_electrons[subi] = list_items[1] - - if n_transitions > 0: - # Read transition data - records = [] - for j in range(n_transitions): - subj = _SUBSHELLS[int(list_items[6*(j+1)])] - subk = _SUBSHELLS[int(list_items[6*(j+1) + 1])] - etr = list_items[6*(j+1) + 2] - ftr = list_items[6*(j+1) + 3] - records.append((subj, subk, etr, ftr)) - - # Create dataframe for transitions - transitions[subi] = pd.DataFrame.from_records( - records, columns=columns) - - # Return instance of class - return cls(binding_energy, num_electrons, transitions) - - @classmethod - def from_hdf5(cls, group): - """Generate atomic relaxation data from an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.AtomicRelaxation - Atomic relaxation data - - """ - # Create data dictionaries - binding_energy = {} - num_electrons = {} - transitions = {} - - designators = [s.decode() for s in group.attrs['designators']] - columns = ['secondary', 'tertiary', 'energy (eV)', 'probability'] - for shell in designators: - # Shell group - sub_group = group[shell] - - # Read subshell binding energy and number of electrons - if 'binding_energy' in sub_group.attrs: - binding_energy[shell] = sub_group.attrs['binding_energy'] - if 'num_electrons' in sub_group.attrs: - num_electrons[shell] = sub_group.attrs['num_electrons'] - - # Read transition data - if 'transitions' in sub_group: - df = pd.DataFrame(sub_group['transitions'][()], - columns=columns) - # Replace float indexes back to subshell strings - df[columns[:2]] = df[columns[:2]].replace( - np.arange(float(len(_SUBSHELLS))), _SUBSHELLS) - transitions[shell] = df - - return cls(binding_energy, num_electrons, transitions) - - def to_hdf5(self, group, shell): - """Write atomic relaxation data to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - shell : str - The subshell to write data for - - """ - - # Write subshell binding energy and number of electrons - group.attrs['binding_energy'] = self.binding_energy[shell] - group.attrs['num_electrons'] = self.num_electrons[shell] - - # Write transition data with replacements - if shell in self.transitions: - df = self.transitions[shell].replace( - _SUBSHELLS, range(len(_SUBSHELLS))) - group.create_dataset('transitions', data=df.values.astype(float)) - - def energy_fluorescence(self, shell): - """Compute expected energy of fluorescent photons for the shell - - Parameters - ---------- - shell : str - The subshell to compute - - Returns - ------- - float - Energy of fluorescent photons - - """ - - if shell not in self.binding_energy: - raise KeyError('Invalid shell {}.'.format(shell)) - - if shell in self._e_fluorescence: - # Already computed - return self._e_fluorescence[shell] - e = 0.0 - if shell not in self.transitions or self.transitions[shell].empty: - e = self.binding_energy[shell] - else: - df = self.transitions[shell] - for primary, secondary, energy, prob in df.itertuples(index=False): - e_row = 0.0 - if secondary is None: - # Fluorescent photon release in radiative transition - e_row += energy - else: - # Fill the hole left by auger electron - e_row += self.energy_fluorescence(secondary) - - # Fill the photoelectron hole - e_row += self.energy_fluorescence(primary) - - # Expected fluorescent photon energy - e += e_row * prob - - self._e_fluorescence[shell] = e - return e - -class IncidentPhoton(EqualityMixin): - r"""Photon interaction data. - - This class stores photo-atomic, photo-nuclear, atomic relaxation, - Compton profile, stopping power, and bremsstrahlung data assembled from - different sources. To create an instance, the factory method - :meth:`IncidentPhoton.from_endf` can be used. To add atomic relaxation or - Compton profile data, set the :attr:`IncidentPhoton.atomic_relaxation` and - :attr:`IncidentPhoton.compton_profiles` attributes directly. - - Parameters - ---------- - atomic_number : int - Number of protons in the target nucleus - - Attributes - ---------- - atomic_number : int - Number of protons in the target nucleus - atomic_relaxation : openmc.data.AtomicRelaxation or None - Atomic relaxation data - bremsstrahlung : dict - Dictionary of bremsstrahlung data with keys 'I' (mean excitation energy - in [eV]), 'num_electrons' (number of electrons in each subshell), - 'ionization_energy' (ionization potential of each subshell), - 'electron_energy' (incident electron kinetic energy values in [eV]), - 'photon_energy' (ratio of the energy of the emitted photon to the - incident electron kinetic energy), and 'dcs' (cross section values in - [b]). The cross sections are in scaled form: :math:`(\beta^2/Z^2) E_k - (d\sigma/dE_k)`, where :math:`E_k` is the energy of the emitted photon. - A negative number of electrons in a subshell indicates conduction - electrons. - compton_profiles : dict - Dictionary of Compton profile data with keys 'num_electrons' (number of - electrons in each subshell), 'binding_energy' (ionization potential of - each subshell), and 'J' (Hartree-Fock Compton profile as a function of - the projection of the electron momentum on the scattering vector, - :math:`p_z` for each subshell). Note that subshell occupancies may not - match the atomic relaxation data. - reactions : collections.OrderedDict - Contains the cross sections for each photon reaction. The keys are MT - values and the values are instances of :class:`PhotonReaction`. - - """ - - def __init__(self, atomic_number): - self.atomic_number = atomic_number - self._atomic_relaxation = None - self.reactions = OrderedDict() - self.compton_profiles = {} - self.bremsstrahlung = {} - - def __contains__(self, mt): - return mt in self.reactions - - def __getitem__(self, mt): - if mt in self.reactions: - return self.reactions[mt] - else: - raise KeyError('No reaction with MT={}.'.format(mt)) - - def __repr__(self): - return "".format(self.name) - - def __iter__(self): - return iter(self.reactions.values()) - - @property - def atomic_number(self): - return self._atomic_number - - @property - def atomic_relaxation(self): - return self._atomic_relaxation - - @property - def name(self): - return ATOMIC_SYMBOL[self.atomic_number] - - @atomic_number.setter - def atomic_number(self, atomic_number): - cv.check_type('atomic number', atomic_number, Integral) - cv.check_greater_than('atomic number', atomic_number, 0, True) - self._atomic_number = atomic_number - - @atomic_relaxation.setter - def atomic_relaxation(self, atomic_relaxation): - cv.check_type('atomic relaxation data', atomic_relaxation, - AtomicRelaxation) - self._atomic_relaxation = atomic_relaxation - - @classmethod - def from_ace(cls, ace_or_filename): - """Generate incident photon data from an ACE table - - Parameters - ---------- - ace_or_filename : str or openmc.data.ace.Table - ACE table to read from. If given as a string, it is assumed to be - the filename for the ACE file. - - Returns - ------- - openmc.data.IncidentPhoton - Photon interaction data - - """ - # First obtain the data for the first provided ACE table/file - if isinstance(ace_or_filename, Table): - ace = ace_or_filename - else: - ace = get_table(ace_or_filename) - - # Get atomic number based on name of ACE table - zaid, xs = ace.name.split('.') - if not xs.endswith('p'): - raise TypeError("{} is not a photoatomic transport ACE table.".format(ace)) - Z = get_metadata(int(zaid))[2] - - # Read each reaction - data = cls(Z) - for mt in (502, 504, 515, 522, 525): - data.reactions[mt] = PhotonReaction.from_ace(ace, mt) - - # Get heating cross sections [eV-barn] from factors [eV per collision] - # by multiplying with total xs - data.reactions[525].xs.y *= sum([data.reactions[mt].xs.y for mt in - (502, 504, 515, 522)]) - - # Compton profiles - n_shell = ace.nxs[5] - if n_shell != 0: - # Get number of electrons in each shell - idx = ace.jxs[6] - data.compton_profiles['num_electrons'] = ace.xss[idx : idx+n_shell] - - # Get binding energy for each shell - idx = ace.jxs[7] - e = ace.xss[idx : idx+n_shell]*EV_PER_MEV - data.compton_profiles['binding_energy'] = e - - # Create Compton profile for each electron shell - profiles = [] - for k in range(n_shell): - # Get number of momentum values and interpolation scheme - loca = int(ace.xss[ace.jxs[9] + k]) - jj = int(ace.xss[ace.jxs[10] + loca - 1]) - m = int(ace.xss[ace.jxs[10] + loca]) - - # Read momentum and PDF - idx = ace.jxs[10] + loca + 1 - pz = ace.xss[idx : idx+m] - pdf = ace.xss[idx+m : idx+2*m] - - # Create proflie function - J_k = Tabulated1D(pz, pdf, [m], [jj]) - profiles.append(J_k) - data.compton_profiles['J'] = profiles - - # Subshell photoelectric xs and atomic relaxation data - if ace.nxs[7] > 0: - data.atomic_relaxation = AtomicRelaxation.from_ace(ace) - - # Get subshell designators - n_subshells = ace.nxs[7] - idx = ace.jxs[11] - designators = [int(i) for i in ace.xss[idx : idx+n_subshells]] - - # Get energy grid for subshell photoionization - n_energy = ace.nxs[3] - idx = ace.jxs[1] - energy = np.exp(ace.xss[idx : idx+n_energy])*EV_PER_MEV - - # Get cross section for each subshell - idx = ace.jxs[16] - for d in designators: - # Create photon reaction - mt = 533 + d - rx = PhotonReaction(mt) - data.reactions[mt] = rx - - # Store cross section - xs = ace.xss[idx : idx+n_energy].copy() - nonzero = (xs != 0.0) - xs[nonzero] = np.exp(xs[nonzero]) - rx.xs = Tabulated1D(energy, xs, [n_energy], [5]) - idx += n_energy - - # Copy binding energy - shell = _SUBSHELLS[d] - e = data.atomic_relaxation.binding_energy[shell] - rx.subshell_binding_energy = e - - # Add bremsstrahlung DCS data - data._add_bremsstrahlung() - - return data - - @classmethod - def from_endf(cls, photoatomic, relaxation=None): - """Generate incident photon data from an ENDF evaluation - - Parameters - ---------- - photoatomic : str or openmc.data.endf.Evaluation - ENDF photoatomic data evaluation to read from. If given as a string, - it is assumed to be the filename for the ENDF file. - relaxation : str or openmc.data.endf.Evaluation, optional - ENDF atomic relaxation data evaluation to read from. If given as a - string, it is assumed to be the filename for the ENDF file. - - Returns - ------- - openmc.data.IncidentPhoton - Photon interaction data - - """ - if isinstance(photoatomic, Evaluation): - ev = photoatomic - else: - ev = Evaluation(photoatomic) - - Z = ev.target['atomic_number'] - data = cls(Z) - - # Read each reaction - for mf, mt, nc, mod in ev.reaction_list: - if mf == 23: - data.reactions[mt] = PhotonReaction.from_endf(ev, mt) - - # Add atomic relaxation data if it hasn't been added already - if relaxation is not None: - data.atomic_relaxation = AtomicRelaxation.from_endf(relaxation) - - # If Compton profile data hasn't been loaded, do so - if not _COMPTON_PROFILES: - filename = os.path.join(os.path.dirname(__file__), 'compton_profiles.h5') - with h5py.File(filename, 'r') as f: - _COMPTON_PROFILES['pz'] = f['pz'][()] - for i in range(1, 101): - group = f['{:03}'.format(i)] - num_electrons = group['num_electrons'][()] - binding_energy = group['binding_energy'][()]*EV_PER_MEV - J = group['J'][()] - _COMPTON_PROFILES[i] = {'num_electrons': num_electrons, - 'binding_energy': binding_energy, - 'J': J} - - # Add Compton profile data - pz = _COMPTON_PROFILES['pz'] - profile = _COMPTON_PROFILES[Z] - data.compton_profiles['num_electrons'] = profile['num_electrons'] - data.compton_profiles['binding_energy'] = profile['binding_energy'] - data.compton_profiles['J'] = [Tabulated1D(pz, J_k) for J_k in profile['J']] - - # Add bremsstrahlung DCS data - data._add_bremsstrahlung() - - # Add heating cross sections - data._compute_heating() - - return data - - @classmethod - def from_hdf5(cls, group_or_filename): - """Generate photon reaction from an HDF5 group - - Parameters - ---------- - group_or_filename : h5py.Group or str - HDF5 group containing interaction data. If given as a string, it is - assumed to be the filename for the HDF5 file, and the first group is - used to read from. - - Returns - ------- - openmc.data.IncidentPhoton - Photon interaction data - - """ - if isinstance(group_or_filename, h5py.Group): - group = group_or_filename - else: - h5file = h5py.File(str(group_or_filename), 'r') - - # Make sure version matches - if 'version' in h5file.attrs: - major, minor = h5file.attrs['version'] - # For now all versions of HDF5 data can be read - else: - raise IOError( - 'HDF5 data does not indicate a version. Your installation ' - 'of the OpenMC Python API expects version {}.x data.' - .format(HDF5_VERSION_MAJOR)) - - group = list(h5file.values())[0] - - Z = group.attrs['Z'] - data = cls(Z) - - # Read energy grid - energy = group['energy'][()] - - # Read cross section data - for mt, (name, key) in _REACTION_NAME.items(): - if key in group: - rgroup = group[key] - elif key in group['subshells']: - rgroup = group['subshells'][key] - else: - continue - - data.reactions[mt] = PhotonReaction.from_hdf5(rgroup, mt, energy) - - # Check for necessary reactions - for mt in (502, 504, 522): - assert mt in data, "Reaction {} not found".format(mt) - - # Read atomic relaxation - data.atomic_relaxation = AtomicRelaxation.from_hdf5(group['subshells']) - - # Read Compton profiles - if 'compton_profiles' in group: - rgroup = group['compton_profiles'] - profile = data.compton_profiles - profile['num_electrons'] = rgroup['num_electrons'][()] - profile['binding_energy'] = rgroup['binding_energy'][()] - - # Get electron momentum values - pz = rgroup['pz'][()] - J = rgroup['J'][()] - if pz.size != J.shape[1]: - raise ValueError("'J' array shape is not consistent with the " - "'pz' array shape") - profile['J'] = [Tabulated1D(pz, Jk) for Jk in J] - - # Read bremsstrahlung - if 'bremsstrahlung' in group: - rgroup = group['bremsstrahlung'] - data.bremsstrahlung['I'] = rgroup.attrs['I'] - for key in ('dcs', 'electron_energy', 'ionization_energy', - 'num_electrons', 'photon_energy'): - data.bremsstrahlung[key] = rgroup[key][()] - - return data - - def export_to_hdf5(self, path, mode='a', libver='earliest'): - """Export incident photon data to an HDF5 file. - - Parameters - ---------- - path : str - Path to write HDF5 file to - 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(str(path), mode, libver=libver) - f.attrs['filetype'] = np.string_('data_photon') - if 'version' not in f.attrs: - f.attrs['version'] = np.array(HDF5_VERSION) - - group = f.create_group(self.name) - group.attrs['Z'] = Z = self.atomic_number - - # Determine union energy grid - union_grid = np.array([]) - for rx in self: - union_grid = np.union1d(union_grid, rx.xs.x) - group.create_dataset('energy', data=union_grid) - - # Write cross sections - shell_group = group.create_group('subshells') - designators = [] - for mt, rx in self.reactions.items(): - name, key = _REACTION_NAME[mt] - if mt in (502, 504, 515, 517, 522, 525): - sub_group = group.create_group(key) - elif mt >= 534 and mt <= 572: - # Subshell - designators.append(key) - sub_group = shell_group.create_group(key) - - # Write atomic relaxation - if key in self.atomic_relaxation.subshells: - self.atomic_relaxation.to_hdf5(sub_group, key) - else: - continue - - rx.to_hdf5(sub_group, union_grid, Z) - - shell_group.attrs['designators'] = np.array(designators, dtype='S') - - # Write Compton profiles - if self.compton_profiles: - compton_group = group.create_group('compton_profiles') - - profile = self.compton_profiles - compton_group.create_dataset('num_electrons', - data=profile['num_electrons']) - compton_group.create_dataset('binding_energy', - data=profile['binding_energy']) - - # Get electron momentum values - compton_group.create_dataset('pz', data=profile['J'][0].x) - - # Create/write 2D array of profiles - J = np.array([Jk.y for Jk in profile['J']]) - compton_group.create_dataset('J', data=J) - - # Write bremsstrahlung - if self.bremsstrahlung: - brem_group = group.create_group('bremsstrahlung') - for key, value in self.bremsstrahlung.items(): - if key == 'I': - brem_group.attrs[key] = value - else: - brem_group.create_dataset(key, data=value) - - def _add_bremsstrahlung(self): - """Add the data used in the thick-target bremsstrahlung approximation - - """ - # Load bremsstrahlung data if it has not yet been loaded - if not _BREMSSTRAHLUNG: - # Add data used for density effect correction - filename = os.path.join(os.path.dirname(__file__), 'density_effect.h5') - with h5py.File(filename, 'r') as f: - for i in range(1, 101): - group = f['{:03}'.format(i)] - _BREMSSTRAHLUNG[i] = { - 'I': group.attrs['I'], - 'num_electrons': group['num_electrons'][()], - 'ionization_energy': group['ionization_energy'][()] - } - - filename = os.path.join(os.path.dirname(__file__), 'BREMX.DAT') - brem = open(filename, 'r').read().split() - - # Incident electron kinetic energy grid in eV - _BREMSSTRAHLUNG['electron_energy'] = np.logspace(3, 9, 200) - log_energy = np.log(_BREMSSTRAHLUNG['electron_energy']) - - # Get number of tabulated electron and photon energy values - n = int(brem[37]) - k = int(brem[38]) - - # Index in data - p = 39 - - # Get log of incident electron kinetic energy values, used for - # cubic spline interpolation in log energy. Units are in MeV, so - # convert to eV. - logx = np.log(np.fromiter(brem[p:p+n], float, n)*EV_PER_MEV) - p += n - - # Get reduced photon energy values - _BREMSSTRAHLUNG['photon_energy'] = np.fromiter(brem[p:p+k], float, k) - p += k - - for i in range(1, 101): - dcs = np.empty([len(log_energy), k]) - - # Get the scaled cross section values for each electron energy - # and reduced photon energy for this Z. Units are in mb, so - # convert to b. - y = np.reshape(np.fromiter(brem[p:p+n*k], float, n*k), (n, k))*1.0e-3 - p += k*n - - for j in range(k): - # Cubic spline interpolation in log energy and linear DCS - cs = CubicSpline(logx, y[:,j]) - - # Get scaled DCS values (millibarns) on new energy grid - dcs[:,j] = cs(log_energy) - - _BREMSSTRAHLUNG[i]['dcs'] = dcs - - # Add bremsstrahlung DCS data - self.bremsstrahlung['electron_energy'] = _BREMSSTRAHLUNG['electron_energy'] - self.bremsstrahlung['photon_energy'] = _BREMSSTRAHLUNG['photon_energy'] - self.bremsstrahlung.update(_BREMSSTRAHLUNG[self.atomic_number]) - - def _compute_heating(self): - r"""Compute heating cross sections (KERMA) - - Photon energy is deposited as energy loss in three reactions: - incoherent scattering, pair production and photoelectric effect. - The point-wise heating cross section is calculated as: - - .. math:: - \begin{aligned} - \sigma_{Hx}(E) &= (E - \overline{E}_x(E)) \cdot \sigma_x(E), x \in \left\{I, PP, PE \right\} \\ - \overline{E}_I(E) &= \frac {\int E' \sigma_I (E,E',\mu) d\mu} {\int \sigma_I (E,E',\mu) d\mu} \\ - \overline{E}_{PP} &= 2 m_e c^2 = 1.022 \times 10^6 eV \\ - \overline{E}_{PE} &= E(\text{fluorescent photons}) - \end{aligned} - - The differential cross section representation for incoherent - scattering can be found in the theory manual. - - """ - - # Determine a union energy grid - energy = np.array([]) - for mt in (504, 515, 517, 522): - if mt in self: - energy = np.union1d(energy, self[mt].xs.x) - - heating_xs = np.zeros_like(energy) - - # Incoherent scattering - if 504 in self: - rx = self[504] - - def dsigma_dmu(mu, E): - k = E / MASS_ELECTRON_EV - krat = 1.0 / (1.0 + k * (1.0 - mu)) - x = E * sqrt(0.5 * (1.0 - mu)) / PLANCK_C - return pi * R0*R0 * krat*krat * (krat + 1/krat + - mu*mu - 1.0) * rx.scattering_factor(x) - - def eout_dsigma_dmu(mu, E): - Eout = E / (1.0 + E / MASS_ELECTRON_EV * (1.0 - mu)) - return Eout * dsigma_dmu(mu, E) - - def eout_average(E): - integral_sigma = quad(dsigma_dmu, -1.0, 1.0, - args=(E,), epsabs=0.0, epsrel=1e-3)[0] - integral_sigma_e = quad(eout_dsigma_dmu, -1.0, 1.0, - args=(E,), epsabs=0.0, epsrel=1e-3)[0] - return integral_sigma_e / integral_sigma - - e_out = np.vectorize(eout_average)(energy) - heating_xs += (energy - e_out) * rx.xs(energy) - - # Pair production, electron field - if 515 in self: - heating_xs += (energy - 2*MASS_ELECTRON_EV)*self[515].xs(energy) - - # Pair production, nuclear field - if 517 in self: - heating_xs += (energy - 2*MASS_ELECTRON_EV)*self[517].xs(energy) - - # Photoelectric effect - if 522 in self: - # Account for fluorescent photons - for mt, rx in self.reactions.items(): - if mt >= 534 and mt <= 572: - shell = _REACTION_NAME[mt][1] - e_f = self.atomic_relaxation.energy_fluorescence(shell) - heating_xs += (energy - e_f) * rx.xs(energy) - - heat_rx = PhotonReaction(525) - heat_rx.xs = Tabulated1D(energy, heating_xs, [energy.size], [5]) - self.reactions[525] = heat_rx - -class PhotonReaction(EqualityMixin): - """Photon-induced reaction - - Parameters - ---------- - mt : int - The ENDF MT number for this reaction. - - Attributes - ---------- - anomalous_real : openmc.data.Tabulated1D - Real part of the anomalous scattering factor - anomlaous_imag : openmc.data.Tabulated1D - Imaginary part of the anomalous scatttering factor - mt : int - The ENDF MT number for this reaction. - scattering_factor : openmc.data.Tabulated1D - Coherent or incoherent form factor. - xs : Callable - Cross section as a function of incident photon energy - - """ - - def __init__(self, mt): - self.mt = mt - self._xs = None - self._scattering_factor = None - self._anomalous_real = None - self._anomalous_imag = None - - def __repr__(self): - if self.mt in _REACTION_NAME: - return "".format( - self.mt, _REACTION_NAME[self.mt][0]) - else: - return "".format(self.mt) - - @property - def anomalous_real(self): - return self._anomalous_real - - @property - def anomalous_imag(self): - return self._anomalous_imag - - @property - def scattering_factor(self): - return self._scattering_factor - - @property - def xs(self): - return self._xs - - @anomalous_real.setter - def anomalous_real(self, anomalous_real): - cv.check_type('real part of anomalous scattering factor', - anomalous_real, Callable) - self._anomalous_real = anomalous_real - - @anomalous_imag.setter - def anomalous_imag(self, anomalous_imag): - cv.check_type('imaginary part of anomalous scattering factor', - anomalous_imag, Callable) - self._anomalous_imag = anomalous_imag - - @scattering_factor.setter - def scattering_factor(self, scattering_factor): - cv.check_type('scattering factor', scattering_factor, Callable) - self._scattering_factor = scattering_factor - - @xs.setter - def xs(self, xs): - cv.check_type('reaction cross section', xs, Callable) - self._xs = xs - - @classmethod - def from_ace(cls, ace, mt): - """Generate photon reaction from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - mt : int - The MT value of the reaction to get data for - - Returns - ------- - openmc.data.PhotonReaction - Photon reaction data - - """ - # Create instance - rx = cls(mt) - - # Get energy grid (stored as logarithms) - n = ace.nxs[3] - idx = ace.jxs[1] - energy = np.exp(ace.xss[idx : idx+n])*EV_PER_MEV - - # Get index for appropriate reaction - if mt == 502: - # Coherent scattering - idx = ace.jxs[1] + 2*n - elif mt == 504: - # Incoherent scattering - idx = ace.jxs[1] + n - elif mt == 515: - # Pair production - idx = ace.jxs[1] + 4*n - elif mt == 522: - # Photoelectric - idx = ace.jxs[1] + 3*n - elif mt == 525: - # Heating - idx = ace.jxs[5] - else: - raise ValueError('ACE photoatomic cross sections do not have ' - 'data for MT={}.'.format(mt)) - - # Store cross section - xs = ace.xss[idx : idx+n].copy() - if mt == 525: - # Get heating factors in [eV per collision] - xs *= EV_PER_MEV - else: - nonzero = (xs != 0.0) - xs[nonzero] = np.exp(xs[nonzero]) - rx.xs = Tabulated1D(energy, xs, [n], [5]) - - # Get form factors for incoherent/coherent scattering - new_format = (ace.nxs[6] > 0) - if mt == 502: - idx = ace.jxs[3] - if new_format: - n = (ace.jxs[4] - ace.jxs[3]) // 3 - x = ace.xss[idx : idx+n] - idx += n - else: - x = np.array([ - 0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.1, 0.12, - 0.15, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, - 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, - 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, - 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, - 5.8, 6.0]) - n = x.size - ff = ace.xss[idx+n : idx+2*n] - rx.scattering_factor = Tabulated1D(x, ff) - - elif mt == 504: - idx = ace.jxs[2] - if new_format: - n = (ace.jxs[3] - ace.jxs[2]) // 2 - x = ace.xss[idx : idx+n] - idx += n - else: - x = np.array([ - 0.0, 0.005, 0.01, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, - 0.7, 0.8, 0.9, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 8.0 - ]) - n = x.size - ff = ace.xss[idx : idx+n] - rx.scattering_factor = Tabulated1D(x, ff) - - return rx - - @classmethod - def from_endf(cls, ev, mt): - """Generate photon reaction from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF photo-atomic interaction data evaluation - mt : int - The MT value of the reaction to get data for - - Returns - ------- - openmc.data.PhotonReaction - Photon reaction data - - """ - rx = cls(mt) - - # Read photon cross section - if (23, mt) in ev.section: - file_obj = StringIO(ev.section[23, mt]) - get_head_record(file_obj) - params, rx.xs = get_tab1_record(file_obj) - - # Set subshell binding energy and/or fluorescence yield - if mt >= 534 and mt <= 599: - rx.subshell_binding_energy = params[0] - if mt >= 534 and mt <= 572: - rx.fluorescence_yield = params[1] - - # Read form factors / scattering functions - if (27, mt) in ev.section: - file_obj = StringIO(ev.section[27, mt]) - get_head_record(file_obj) - params, rx.scattering_factor = get_tab1_record(file_obj) - - # Check for anomalous scattering factor - if mt == 502: - if (27, 506) in ev.section: - file_obj = StringIO(ev.section[27, 506]) - get_head_record(file_obj) - params, rx.anomalous_real = get_tab1_record(file_obj) - - if (27, 505) in ev.section: - file_obj = StringIO(ev.section[27, 505]) - get_head_record(file_obj) - params, rx.anomalous_imag = get_tab1_record(file_obj) - - return rx - - @classmethod - def from_hdf5(cls, group, mt, energy): - """Generate photon reaction from an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - mt : int - The MT value of the reaction to get data for - energy : Iterable of float - arrays of energies at which cross sections are tabulated at - - Returns - ------- - openmc.data.PhotonReaction - Photon reaction data - - """ - # Create instance - rx = cls(mt) - - # Cross sections - xs = group['xs'][()] - # Replace zero elements to small non-zero to enable log-log - xs[xs == 0.0] = np.exp(-500.0) - - # Threshold - threshold_idx = 0 - if 'threshold_idx' in group['xs'].attrs: - threshold_idx = group['xs'].attrs['threshold_idx'] - - # Store cross section - rx.xs = Tabulated1D(energy[threshold_idx:], xs, [len(xs)], [5]) - - # Check for anomalous scattering factor - if 'anomalous_real' in group: - rx.anomalous_real = Tabulated1D.from_hdf5(group['anomalous_real']) - if 'anomalous_imag' in group: - rx.anomalous_imag = Tabulated1D.from_hdf5(group['anomalous_imag']) - - # Check for factors / scattering functions - if 'scattering_factor' in group: - rx.scattering_factor = Tabulated1D.from_hdf5(group['scattering_factor']) - - return rx - - def to_hdf5(self, group, energy, Z): - """Write photon reaction to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - energy : Iterable of float - arrays of energies at which cross sections are tabulated at - Z : int - atomic number - - """ - - # Write cross sections - if self.mt >= 534 and self.mt <= 572: - # Determine threshold - threshold = self.xs.x[0] - idx = np.searchsorted(energy, threshold, side='right') - 1 - - # Interpolate cross section onto union grid and write - photoionization = self.xs(energy[idx:]) - group.create_dataset('xs', data=photoionization) - assert len(energy) == len(photoionization) + idx - group['xs'].attrs['threshold_idx'] = idx - else: - group.create_dataset('xs', data=self.xs(energy)) - - # Write scattering factor - if self.scattering_factor is not None: - if self.mt == 502: - # Create integrated form factor - ff = deepcopy(self.scattering_factor) - ff.x *= ff.x - ff.y *= ff.y/Z**2 - int_ff = Tabulated1D(ff.x, ff.integral()) - int_ff.to_hdf5(group, 'integrated_scattering_factor') - self.scattering_factor.to_hdf5(group, 'scattering_factor') - if self.anomalous_real is not None: - self.anomalous_real.to_hdf5(group, 'anomalous_real') - if self.anomalous_imag is not None: - self.anomalous_imag.to_hdf5(group, 'anomalous_imag') diff --git a/openmc/data/product.py b/openmc/data/product.py deleted file mode 100644 index 5b8652d77..000000000 --- a/openmc/data/product.py +++ /dev/null @@ -1,187 +0,0 @@ -from collections.abc import Iterable -from io import StringIO -from numbers import Real -import sys - -import numpy as np - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from .angle_energy import AngleEnergy -from .function import Tabulated1D, Polynomial, Function1D - - -class Product(EqualityMixin): - """Secondary particle emitted in a nuclear reaction - - Parameters - ---------- - particle : str, optional - What particle the reaction product is. Defaults to 'neutron'. - - Attributes - ---------- - applicability : Iterable of openmc.data.Tabulated1D - Probability of sampling a given distribution for this product. - decay_rate : float - Decay rate in inverse seconds - distribution : Iterable of openmc.data.AngleEnergy - Distributions of energy and angle of product. - emission_mode : {'prompt', 'delayed', 'total'} - Indicate whether the particle is emitted immediately or whether it - results from the decay of reaction product (e.g., neutron emitted from a - delayed neutron precursor). A special value of 'total' is used when the - yield represents particles from prompt and delayed sources. - particle : str - What particle the reaction product is. - yield_ : openmc.data.Function1D - Yield of secondary particle in the reaction. - - """ - - def __init__(self, particle='neutron'): - self.particle = particle - self.decay_rate = 0.0 - self.emission_mode = 'prompt' - self.distribution = [] - self.applicability = [] - self.yield_ = Polynomial((1,)) # 0-order polynomial i.e. a constant - - def __repr__(self): - if isinstance(self.yield_, Real): - return "".format( - self.particle, self.emission_mode, self.yield_) - elif isinstance(self.yield_, Tabulated1D): - if np.all(self.yield_.y == self.yield_.y[0]): - return "".format( - self.particle, self.emission_mode, self.yield_.y[0]) - else: - return "".format( - self.particle, self.emission_mode) - else: - return "".format( - self.particle, self.emission_mode) - - @property - def applicability(self): - return self._applicability - - @property - def decay_rate(self): - return self._decay_rate - - @property - def distribution(self): - return self._distribution - - @property - def emission_mode(self): - return self._emission_mode - - @property - def particle(self): - return self._particle - - @property - def yield_(self): - return self._yield - - @applicability.setter - def applicability(self, applicability): - cv.check_type('product distribution applicability', applicability, - Iterable, Tabulated1D) - self._applicability = applicability - - @decay_rate.setter - def decay_rate(self, decay_rate): - cv.check_type('product decay rate', decay_rate, Real) - cv.check_greater_than('product decay rate', decay_rate, 0.0, True) - self._decay_rate = decay_rate - - @distribution.setter - def distribution(self, distribution): - cv.check_type('product angle-energy distribution', distribution, - Iterable, AngleEnergy) - self._distribution = distribution - - @emission_mode.setter - def emission_mode(self, emission_mode): - cv.check_value('product emission mode', emission_mode, - ('prompt', 'delayed', 'total')) - self._emission_mode = emission_mode - - @particle.setter - def particle(self, particle): - cv.check_type('product particle type', particle, str) - self._particle = particle - - @yield_.setter - def yield_(self, yield_): - cv.check_type('product yield', yield_, Function1D) - self._yield = yield_ - - def to_hdf5(self, group): - """Write product to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['particle'] = np.string_(self.particle) - group.attrs['emission_mode'] = np.string_(self.emission_mode) - if self.decay_rate > 0.0: - group.attrs['decay_rate'] = self.decay_rate - - # Write yield - self.yield_.to_hdf5(group, 'yield') - - # Write applicability/distribution - group.attrs['n_distribution'] = len(self.distribution) - for i, d in enumerate(self.distribution): - dgroup = group.create_group('distribution_{}'.format(i)) - if self.applicability: - self.applicability[i].to_hdf5(dgroup, 'applicability') - d.to_hdf5(dgroup) - - @classmethod - def from_hdf5(cls, group): - """Generate reaction product from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.Product - Reaction product - - """ - particle = group.attrs['particle'].decode() - p = cls(particle) - - p.emission_mode = group.attrs['emission_mode'].decode() - if 'decay_rate' in group.attrs: - p.decay_rate = group.attrs['decay_rate'] - - # Read yield - p.yield_ = Function1D.from_hdf5(group['yield']) - - # Read applicability/distribution - n_distribution = group.attrs['n_distribution'] - distribution = [] - applicability = [] - for i in range(n_distribution): - dgroup = group['distribution_{}'.format(i)] - if 'applicability' in dgroup: - applicability.append(Tabulated1D.from_hdf5( - dgroup['applicability'])) - distribution.append(AngleEnergy.from_hdf5(dgroup)) - - p.distribution = distribution - p.applicability = applicability - - return p diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py deleted file mode 100644 index 83e773f20..000000000 --- a/openmc/data/reaction.py +++ /dev/null @@ -1,1189 +0,0 @@ -from collections.abc import Iterable, Callable, MutableMapping -from copy import deepcopy -from numbers import Real, Integral -from warnings import warn -from io import StringIO - -import numpy as np - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from openmc.stats import Uniform, Tabular, Legendre -from .angle_distribution import AngleDistribution -from .angle_energy import AngleEnergy -from .correlated import CorrelatedAngleEnergy -from .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV -from .endf import get_head_record, get_tab1_record, get_list_record, \ - get_tab2_record, get_cont_record -from .energy_distribution import EnergyDistribution, LevelInelastic, \ - DiscretePhoton -from .function import Tabulated1D, Polynomial -from .kalbach_mann import KalbachMann -from .laboratory import LaboratoryAngleEnergy -from .nbody import NBodyPhaseSpace -from .product import Product -from .uncorrelated import UncorrelatedAngleEnergy - - -REACTION_NAME = {1: '(n,total)', 2: '(n,elastic)', 4: '(n,level)', - 5: '(n,misc)', 11: '(n,2nd)', 16: '(n,2n)', 17: '(n,3n)', - 18: '(n,fission)', 19: '(n,f)', 20: '(n,nf)', 21: '(n,2nf)', - 22: '(n,na)', 23: '(n,n3a)', 24: '(n,2na)', 25: '(n,3na)', - 27: '(n,absorption)', 28: '(n,np)', 29: '(n,n2a)', - 30: '(n,2n2a)', 32: '(n,nd)', 33: '(n,nt)', 34: '(n,nHe-3)', - 35: '(n,nd2a)', 36: '(n,nt2a)', 37: '(n,4n)', 38: '(n,3nf)', - 41: '(n,2np)', 42: '(n,3np)', 44: '(n,n2p)', 45: '(n,npa)', - 91: '(n,nc)', 101: '(n,disappear)', 102: '(n,gamma)', - 103: '(n,p)', 104: '(n,d)', 105: '(n,t)', 106: '(n,3He)', - 107: '(n,a)', 108: '(n,2a)', 109: '(n,3a)', 111: '(n,2p)', - 112: '(n,pa)', 113: '(n,t2a)', 114: '(n,d2a)', 115: '(n,pd)', - 116: '(n,pt)', 117: '(n,da)', 152: '(n,5n)', 153: '(n,6n)', - 154: '(n,2nt)', 155: '(n,ta)', 156: '(n,4np)', 157: '(n,3nd)', - 158: '(n,nda)', 159: '(n,2npa)', 160: '(n,7n)', 161: '(n,8n)', - 162: '(n,5np)', 163: '(n,6np)', 164: '(n,7np)', 165: '(n,4na)', - 166: '(n,5na)', 167: '(n,6na)', 168: '(n,7na)', 169: '(n,4nd)', - 170: '(n,5nd)', 171: '(n,6nd)', 172: '(n,3nt)', 173: '(n,4nt)', - 174: '(n,5nt)', 175: '(n,6nt)', 176: '(n,2n3He)', - 177: '(n,3n3He)', 178: '(n,4n3He)', 179: '(n,3n2p)', - 180: '(n,3n3a)', 181: '(n,3npa)', 182: '(n,dt)', - 183: '(n,npd)', 184: '(n,npt)', 185: '(n,ndt)', - 186: '(n,np3He)', 187: '(n,nd3He)', 188: '(n,nt3He)', - 189: '(n,nta)', 190: '(n,2n2p)', 191: '(n,p3He)', - 192: '(n,d3He)', 193: '(n,3Hea)', 194: '(n,4n2p)', - 195: '(n,4n2a)', 196: '(n,4npa)', 197: '(n,3p)', - 198: '(n,n3p)', 199: '(n,3n2pa)', 200: '(n,5n2p)', 203: '(n,Xp)', - 204: '(n,Xd)', 205: '(n,Xt)', 206: '(n,X3He)', 207: '(n,Xa)', - 301: 'heating', 444: 'damage-energy', - 649: '(n,pc)', 699: '(n,dc)', 749: '(n,tc)', 799: '(n,3Hec)', - 849: '(n,ac)', 891: '(n,2nc)', 901: 'heating-local'} -REACTION_NAME.update({i: '(n,n{})'.format(i - 50) for i in range(50, 91)}) -REACTION_NAME.update({i: '(n,p{})'.format(i - 600) for i in range(600, 649)}) -REACTION_NAME.update({i: '(n,d{})'.format(i - 650) for i in range(650, 699)}) -REACTION_NAME.update({i: '(n,t{})'.format(i - 700) for i in range(700, 749)}) -REACTION_NAME.update({i: '(n,3He{})'.format(i - 750) for i in range(750, 799)}) -REACTION_NAME.update({i: '(n,a{})'.format(i - 800) for i in range(800, 849)}) -REACTION_NAME.update({i: '(n,2n{})'.format(i - 875) for i in range(875, 891)}) - - -def _get_products(ev, mt): - """Generate products from MF=6 in an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation to read from - mt : int - The MT value of the reaction to get products for - - Returns - ------- - products : list of openmc.data.Product - Products of the reaction - - """ - file_obj = StringIO(ev.section[6, mt]) - - # Read HEAD record - items = get_head_record(file_obj) - reference_frame = {1: 'laboratory', 2: 'center-of-mass', - 3: 'light-heavy', 4: 'breakup'}[items[3]] - n_products = items[4] - - products = [] - for i in range(n_products): - # Get yield for this product - params, yield_ = get_tab1_record(file_obj) - - za = int(params[0]) - awr = params[1] - lip = params[2] - law = params[3] - - if za == 0: - p = Product('photon') - elif za == 1: - p = Product('neutron') - elif za == 1000: - p = Product('electron') - else: - Z, A = divmod(za, 1000) - p = Product('{}{}'.format(ATOMIC_SYMBOL[Z], A)) - - p.yield_ = yield_ - - """ - # Set reference frame - if reference_frame == 'laboratory': - p.center_of_mass = False - elif reference_frame == 'center-of-mass': - p.center_of_mass = True - elif reference_frame == 'light-heavy': - p.center_of_mass = (awr <= 4.0) - """ - - if law == 0: - # No distribution given - pass - if law == 1: - # Continuum energy-angle distribution - - # Peak ahead to determine type of distribution - position = file_obj.tell() - params = get_cont_record(file_obj) - file_obj.seek(position) - - lang = params[2] - if lang == 1: - p.distribution = [CorrelatedAngleEnergy.from_endf(file_obj)] - elif lang == 2: - p.distribution = [KalbachMann.from_endf(file_obj)] - - elif law == 2: - # Discrete two-body scattering - params, tab2 = get_tab2_record(file_obj) - ne = params[5] - energy = np.zeros(ne) - mu = [] - for i in range(ne): - items, values = get_list_record(file_obj) - energy[i] = items[1] - lang = items[2] - if lang == 0: - mu.append(Legendre(values)) - elif lang == 12: - mu.append(Tabular(values[::2], values[1::2])) - elif lang == 14: - mu.append(Tabular(values[::2], values[1::2], - 'log-linear')) - - angle_dist = AngleDistribution(energy, mu) - dist = UncorrelatedAngleEnergy(angle_dist) - p.distribution = [dist] - # TODO: Add level-inelastic info? - - elif law == 3: - # Isotropic discrete emission - p.distribution = [UncorrelatedAngleEnergy()] - # TODO: Add level-inelastic info? - - elif law == 4: - # Discrete two-body recoil - pass - - elif law == 5: - # Charged particle elastic scattering - pass - - elif law == 6: - # N-body phase-space distribution - p.distribution = [NBodyPhaseSpace.from_endf(file_obj)] - - elif law == 7: - # Laboratory energy-angle distribution - p.distribution = [LaboratoryAngleEnergy.from_endf(file_obj)] - - products.append(p) - - return products - - -def _get_fission_products_ace(ace): - """Generate fission products from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - - Returns - ------- - products : list of openmc.data.Product - Prompt and delayed fission neutrons - derived_products : list of openmc.data.Product - "Total" fission neutron - - """ - # No NU block - if ace.jxs[2] == 0: - return None, None - - products = [] - derived_products = [] - - # Either prompt nu or total nu is given - if ace.xss[ace.jxs[2]] > 0: - whichnu = 'prompt' if ace.jxs[24] > 0 else 'total' - - neutron = Product('neutron') - neutron.emission_mode = whichnu - - idx = ace.jxs[2] - LNU = int(ace.xss[idx]) - if LNU == 1: - # Polynomial function form of nu - NC = int(ace.xss[idx+1]) - coefficients = ace.xss[idx+2 : idx+2+NC].copy() - for i in range(coefficients.size): - coefficients[i] *= EV_PER_MEV**(-i) - neutron.yield_ = Polynomial(coefficients) - elif LNU == 2: - # Tabular data form of nu - neutron.yield_ = Tabulated1D.from_ace(ace, idx + 1) - - products.append(neutron) - - # Both prompt nu and total nu - elif ace.xss[ace.jxs[2]] < 0: - # Read prompt neutron yield - prompt_neutron = Product('neutron') - prompt_neutron.emission_mode = 'prompt' - - idx = ace.jxs[2] + 1 - LNU = int(ace.xss[idx]) - if LNU == 1: - # Polynomial function form of nu - NC = int(ace.xss[idx+1]) - coefficients = ace.xss[idx+2 : idx+2+NC].copy() - for i in range(coefficients.size): - coefficients[i] *= EV_PER_MEV**(-i) - prompt_neutron.yield_ = Polynomial(coefficients) - elif LNU == 2: - # Tabular data form of nu - prompt_neutron.yield_ = Tabulated1D.from_ace(ace, idx + 1) - - # Read total neutron yield - total_neutron = Product('neutron') - total_neutron.emission_mode = 'total' - - idx = ace.jxs[2] + int(abs(ace.xss[ace.jxs[2]])) + 1 - LNU = int(ace.xss[idx]) - - if LNU == 1: - # Polynomial function form of nu - NC = int(ace.xss[idx+1]) - coefficients = ace.xss[idx+2 : idx+2+NC].copy() - for i in range(coefficients.size): - coefficients[i] *= EV_PER_MEV**(-i) - total_neutron.yield_ = Polynomial(coefficients) - elif LNU == 2: - # Tabular data form of nu - total_neutron.yield_ = Tabulated1D.from_ace(ace, idx + 1) - - products.append(prompt_neutron) - derived_products.append(total_neutron) - - # Check for delayed nu data - if ace.jxs[24] > 0: - yield_delayed = Tabulated1D.from_ace(ace, ace.jxs[24] + 1) - - # Delayed neutron precursor distribution - idx = ace.jxs[25] - n_group = ace.nxs[8] - total_group_probability = 0. - for group in range(n_group): - delayed_neutron = Product('neutron') - delayed_neutron.emission_mode = 'delayed' - - # Convert units of inverse shakes to inverse seconds - delayed_neutron.decay_rate = ace.xss[idx] * 1.e8 - - group_probability = Tabulated1D.from_ace(ace, idx + 1) - if np.all(group_probability.y == group_probability.y[0]): - delayed_neutron.yield_ = deepcopy(yield_delayed) - delayed_neutron.yield_.y *= group_probability.y[0] - total_group_probability += group_probability.y[0] - else: - # Get union energy grid and ensure energies are within - # interpolable range of both functions - max_energy = min(yield_delayed.x[-1], group_probability.x[-1]) - energy = np.union1d(yield_delayed.x, group_probability.x) - energy = energy[energy <= max_energy] - - # Calculate group yield - group_yield = yield_delayed(energy) * group_probability(energy) - delayed_neutron.yield_ = Tabulated1D(energy, group_yield) - - # Advance position - nr = int(ace.xss[idx + 1]) - ne = int(ace.xss[idx + 2 + 2*nr]) - idx += 3 + 2*nr + 2*ne - - # Energy distribution for delayed fission neutrons - location_start = int(ace.xss[ace.jxs[26] + group]) - delayed_neutron.distribution.append( - AngleEnergy.from_ace(ace, ace.jxs[27], location_start)) - - products.append(delayed_neutron) - - # Renormalize delayed neutron yields to reflect fact that in ACE - # file, the sum of the group probabilities is not exactly one - for product in products[1:]: - if total_group_probability > 0.: - product.yield_.y /= total_group_probability - - return products, derived_products - - -def _get_fission_products_endf(ev): - """Generate fission products from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - - Returns - ------- - products : list of openmc.data.Product - Prompt and delayed fission neutrons - derived_products : list of openmc.data.Product - "Total" fission neutron - - """ - products = [] - derived_products = [] - - if (1, 456) in ev.section: - prompt_neutron = Product('neutron') - prompt_neutron.emission_mode = 'prompt' - - # Prompt nu values - file_obj = StringIO(ev.section[1, 456]) - lnu = get_head_record(file_obj)[3] - if lnu == 1: - # Polynomial representation - items, coefficients = get_list_record(file_obj) - prompt_neutron.yield_ = Polynomial(coefficients) - elif lnu == 2: - # Tabulated representation - params, prompt_neutron.yield_ = get_tab1_record(file_obj) - - products.append(prompt_neutron) - - if (1, 452) in ev.section: - total_neutron = Product('neutron') - total_neutron.emission_mode = 'total' - - # Total nu values - file_obj = StringIO(ev.section[1, 452]) - lnu = get_head_record(file_obj)[3] - if lnu == 1: - # Polynomial representation - items, coefficients = get_list_record(file_obj) - total_neutron.yield_ = Polynomial(coefficients) - elif lnu == 2: - # Tabulated representation - params, total_neutron.yield_ = get_tab1_record(file_obj) - - if (1, 456) in ev.section: - derived_products.append(total_neutron) - else: - products.append(total_neutron) - - if (1, 455) in ev.section: - file_obj = StringIO(ev.section[1, 455]) - - # Determine representation of delayed nu data - items = get_head_record(file_obj) - ldg = items[2] - lnu = items[3] - - if ldg == 0: - # Delayed-group constants energy independent - items, decay_constants = get_list_record(file_obj) - for constant in decay_constants: - delayed_neutron = Product('neutron') - delayed_neutron.emission_mode = 'delayed' - delayed_neutron.decay_rate = constant - products.append(delayed_neutron) - elif ldg == 1: - # Delayed-group constants energy dependent - raise NotImplementedError('Delayed neutron with energy-dependent ' - 'group constants.') - - # In MF=1, MT=455, the delayed-group abundances are actually not - # specified if the group constants are energy-independent. In this case, - # the abundances must be inferred from MF=5, MT=455 where multiple - # energy distributions are given. - if lnu == 1: - # Nu represented as polynomial - items, coefficients = get_list_record(file_obj) - yield_ = Polynomial(coefficients) - for neutron in products[-6:]: - neutron.yield_ = deepcopy(yield_) - elif lnu == 2: - # Nu represented by tabulation - params, yield_ = get_tab1_record(file_obj) - for neutron in products[-6:]: - neutron.yield_ = deepcopy(yield_) - - if (5, 455) in ev.section: - file_obj = StringIO(ev.section[5, 455]) - items = get_head_record(file_obj) - nk = items[4] - if nk != len(decay_constants): - raise ValueError( - 'Number of delayed neutron fission spectra ({}) does not ' - 'match number of delayed neutron precursors ({}).'.format( - nk, len(decay_constants))) - for i in range(nk): - params, applicability = get_tab1_record(file_obj) - dist = UncorrelatedAngleEnergy() - dist.energy = EnergyDistribution.from_endf(file_obj, params) - - delayed_neutron = products[1 + i] - yield_ = delayed_neutron.yield_ - - # Here we handle the fact that the delayed neutron yield is the - # product of the total delayed neutron yield and the - # "applicability" of the energy distribution law in file 5. - if isinstance(yield_, Tabulated1D): - if np.all(applicability.y == applicability.y[0]): - yield_.y *= applicability.y[0] - else: - # Get union energy grid and ensure energies are within - # interpolable range of both functions - max_energy = min(yield_.x[-1], applicability.x[-1]) - energy = np.union1d(yield_.x, applicability.x) - energy = energy[energy <= max_energy] - - # Calculate group yield - group_yield = yield_(energy) * applicability(energy) - delayed_neutron.yield_ = Tabulated1D(energy, group_yield) - elif isinstance(yield_, Polynomial): - if len(yield_) == 1: - delayed_neutron.yield_ = deepcopy(applicability) - delayed_neutron.yield_.y *= yield_.coef[0] - else: - if np.all(applicability.y == applicability.y[0]): - yield_.coef[0] *= applicability.y[0] - else: - raise NotImplementedError( - 'Total delayed neutron yield and delayed group ' - 'probability are both energy-dependent.') - - delayed_neutron.distribution.append(dist) - - return products, derived_products - - -def _get_activation_products(ev, rx): - """Generate activation products from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - The ENDF evaluation - rx : openmc.data.Reaction - Reaction which generates activation products - - Returns - ------- - products : list of openmc.data.Product - Activation products - - """ - file_obj = StringIO(ev.section[8, rx.mt]) - - # Determine total number of states and whether decay chain is given in a - # decay sublibrary - items = get_head_record(file_obj) - n_states = items[4] - decay_sublib = (items[5] == 1) - - # Determine if file 9/10 are present - present = {9: False, 10: False} - for i in range(n_states): - if decay_sublib: - items = get_cont_record(file_obj) - else: - items, values = get_list_record(file_obj) - lmf = items[2] - if lmf == 9: - present[9] = True - elif lmf == 10: - present[10] = True - - products = [] - - for mf in (9, 10): - if not present[mf]: - continue - - file_obj = StringIO(ev.section[mf, rx.mt]) - items = get_head_record(file_obj) - n_states = items[4] - for i in range(n_states): - # Determine what the product is - items, xs = get_tab1_record(file_obj) - Z, A = divmod(items[2], 1000) - excited_state = items[3] - - # Get GND name for product - symbol = ATOMIC_SYMBOL[Z] - if excited_state > 0: - name = '{}{}_e{}'.format(symbol, A, excited_state) - else: - name = '{}{}'.format(symbol, A) - - p = Product(name) - if mf == 9: - p.yield_ = xs - else: - # Re-interpolate production cross section and neutron cross - # section to union energy grid - energy = np.union1d(xs.x, rx.xs['0K'].x) - prod_xs = xs(energy) - neutron_xs = rx.xs['0K'](energy) - idx = np.where(neutron_xs > 0) - - # Calculate yield as ratio - yield_ = np.zeros_like(energy) - yield_[idx] = prod_xs[idx] / neutron_xs[idx] - p.yield_ = Tabulated1D(energy, yield_) - - # Check if product already exists from MF=6 and if it does, just - # overwrite the existing yield. - for product in rx.products: - if name == product.particle: - product.yield_ = p.yield_ - break - else: - products.append(p) - - return products - - -def _get_photon_products_ace(ace, rx): - """Generate photon products from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - rx : openmc.data.Reaction - Reaction that generates photons - - Returns - ------- - photons : list of openmc.Products - Photons produced from reaction with given MT - - """ - n_photon_reactions = ace.nxs[6] - photon_mts = ace.xss[ace.jxs[13]:ace.jxs[13] + - n_photon_reactions].astype(int) - - photons = [] - for i in range(n_photon_reactions): - # Determine corresponding reaction - neutron_mt = photon_mts[i] // 1000 - - if neutron_mt != rx.mt: - continue - - # Create photon product and assign to reactions - photon = Product('photon') - - # ================================================================== - # Photon yield / production cross section - - loca = int(ace.xss[ace.jxs[14] + i]) - idx = ace.jxs[15] + loca - 1 - mftype = int(ace.xss[idx]) - idx += 1 - - if mftype in (12, 16): - # Yield data taken from ENDF File 12 or 6 - mtmult = int(ace.xss[idx]) - assert mtmult == neutron_mt - - # Read photon yield as function of energy - photon.yield_ = Tabulated1D.from_ace(ace, idx + 1) - - elif mftype == 13: - # Cross section data from ENDF File 13 - - # Energy grid index at which data starts - threshold_idx = int(ace.xss[idx]) - 1 - n_energy = int(ace.xss[idx + 1]) - energy = ace.xss[ace.jxs[1] + threshold_idx: - ace.jxs[1] + threshold_idx + n_energy]*EV_PER_MEV - - # Get photon production cross section - photon_prod_xs = ace.xss[idx + 2:idx + 2 + n_energy] - neutron_xs = list(rx.xs.values())[0](energy) - idx = np.where(neutron_xs > 0.) - - # Calculate photon yield - yield_ = np.zeros_like(photon_prod_xs) - yield_[idx] = photon_prod_xs[idx] / neutron_xs[idx] - photon.yield_ = Tabulated1D(energy, yield_) - - else: - raise ValueError("MFTYPE must be 12, 13, 16. Got {0}".format( - mftype)) - - # ================================================================== - # Photon energy distribution - - location_start = int(ace.xss[ace.jxs[18] + i]) - distribution = AngleEnergy.from_ace(ace, ace.jxs[19], location_start) - assert isinstance(distribution, UncorrelatedAngleEnergy) - - # ================================================================== - # Photon angular distribution - loc = int(ace.xss[ace.jxs[16] + i]) - - if loc == 0: - # No angular distribution data are given for this reaction, - # isotropic scattering is asssumed in LAB - energy = np.array([photon.yield_.x[0], photon.yield_.x[-1]]) - mu_isotropic = Uniform(-1., 1.) - distribution.angle = AngleDistribution( - energy, [mu_isotropic, mu_isotropic]) - else: - distribution.angle = AngleDistribution.from_ace(ace, ace.jxs[17], loc) - - # Add to list of distributions - photon.distribution.append(distribution) - photons.append(photon) - - return photons - - -def _get_photon_products_endf(ev, rx): - """Generate photon products from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation to read from - rx : openmc.data.Reaction - Reaction that generates photons - - Returns - ------- - products : list of openmc.Products - Photons produced from reaction with given MT - - """ - products = [] - - if (12, rx.mt) in ev.section: - file_obj = StringIO(ev.section[12, rx.mt]) - - items = get_head_record(file_obj) - option = items[2] - - if option == 1: - # Multiplicities given - n_discrete_photon = items[4] - if n_discrete_photon > 1: - items, total_yield = get_tab1_record(file_obj) - for k in range(n_discrete_photon): - photon = Product('photon') - - # Get photon yield - items, photon.yield_ = get_tab1_record(file_obj) - - # Get photon energy distribution - law = items[3] - dist = UncorrelatedAngleEnergy() - if law == 1: - # TODO: Get file 15 distribution - pass - elif law == 2: - energy = items[1] - primary_flag = items[2] - dist.energy = DiscretePhoton(primary_flag, energy, - ev.target['mass']) - - photon.distribution.append(dist) - products.append(photon) - - elif option == 2: - # Transition probability arrays given - ppyield = {} - ppyield['type'] = 'transition' - ppyield['transition'] = transition = {} - - # Determine whether simple (LG=1) or complex (LG=2) transitions - lg = items[3] - - # Get transition data - items, values = get_list_record(file_obj) - transition['energy_start'] = items[0] - transition['energies'] = np.array(values[::lg + 1]) - transition['direct_probability'] = np.array(values[1::lg + 1]) - if lg == 2: - # Complex case - transition['conditional_probability'] = np.array( - values[2::lg + 1]) - - elif (13, rx.mt) in ev.section: - file_obj = StringIO(ev.section[13, rx.mt]) - - # Determine option - items = get_head_record(file_obj) - n_discrete_photon = items[4] - if n_discrete_photon > 1: - items, total_xs = get_tab1_record(file_obj) - for k in range(n_discrete_photon): - photon = Product('photon') - items, xs = get_tab1_record(file_obj) - - # Re-interpolate photon production cross section and neutron cross - # section to union energy grid - energy = np.union1d(xs.x, rx.xs['0K'].x) - photon_prod_xs = xs(energy) - neutron_xs = rx.xs['0K'](energy) - idx = np.where(neutron_xs > 0) - - # Calculate yield as ratio - yield_ = np.zeros_like(energy) - yield_[idx] = photon_prod_xs[idx] / neutron_xs[idx] - photon.yield_ = Tabulated1D(energy, yield_) - - # Get photon energy distribution - law = items[3] - dist = UncorrelatedAngleEnergy() - if law == 1: - # TODO: Get file 15 distribution - pass - elif law == 2: - energy = items[1] - primary_flag = items[2] - dist.energy = DiscretePhoton(primary_flag, energy, - ev.target['mass']) - - photon.distribution.append(dist) - products.append(photon) - - return products - - -class Reaction(EqualityMixin): - """A nuclear reaction - - A Reaction object represents a single reaction channel for a nuclide with - an associated cross section and, if present, a secondary angle and energy - distribution. - - Parameters - ---------- - mt : int - The ENDF MT number for this reaction. - - Attributes - ---------- - center_of_mass : bool - Indicates whether scattering kinematics should be performed in the - center-of-mass or laboratory reference frame. - grid above the threshold value in barns. - redundant : bool - Indicates whether or not this is a redundant reaction - mt : int - The ENDF MT number for this reaction. - q_value : float - The Q-value of this reaction in eV. - xs : dict of str to openmc.data.Function1D - Microscopic cross section for this reaction as a function of incident - energy; these cross sections are provided in a dictionary where the key - is the temperature of the cross section set. - products : Iterable of openmc.data.Product - Reaction products - derived_products : Iterable of openmc.data.Product - Derived reaction products. Used for 'total' fission neutron data when - prompt/delayed data also exists. - - """ - - def __init__(self, mt): - self._center_of_mass = True - self._redundant = False - self._q_value = 0. - self._xs = {} - self._products = [] - self._derived_products = [] - - self.mt = mt - - def __repr__(self): - if self.mt in REACTION_NAME: - return "".format(self.mt, REACTION_NAME[self.mt]) - else: - return "".format(self.mt) - - @property - def center_of_mass(self): - return self._center_of_mass - - @property - def redundant(self): - return self._redundant - - @property - def q_value(self): - return self._q_value - - @property - def products(self): - return self._products - - @property - def derived_products(self): - return self._derived_products - - @property - def xs(self): - return self._xs - - @center_of_mass.setter - def center_of_mass(self, center_of_mass): - cv.check_type('center of mass', center_of_mass, (bool, np.bool_)) - self._center_of_mass = center_of_mass - - @redundant.setter - def redundant(self, redundant): - cv.check_type('redundant', redundant, (bool, np.bool_)) - self._redundant = redundant - - @q_value.setter - def q_value(self, q_value): - cv.check_type('Q value', q_value, Real) - self._q_value = q_value - - @products.setter - def products(self, products): - cv.check_type('reaction products', products, Iterable, Product) - self._products = products - - @derived_products.setter - def derived_products(self, derived_products): - cv.check_type('reaction derived products', derived_products, - Iterable, Product) - self._derived_products = derived_products - - @xs.setter - 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, str) - cv.check_type('reaction cross section', value, Callable) - self._xs = xs - - def to_hdf5(self, group): - """Write reaction to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - - group.attrs['mt'] = self.mt - if self.mt in REACTION_NAME: - group.attrs['label'] = np.string_(REACTION_NAME[self.mt]) - else: - group.attrs['label'] = np.string_(self.mt) - group.attrs['Q_value'] = self.q_value - group.attrs['center_of_mass'] = 1 if self.center_of_mass else 0 - group.attrs['redundant'] = 1 if self.redundant else 0 - for T in self.xs: - Tgroup = group.create_group(T) - if self.xs[T] is not None: - dset = Tgroup.create_dataset('xs', data=self.xs[T].y) - threshold_idx = getattr(self.xs[T], '_threshold_idx', 0) - dset.attrs['threshold_idx'] = threshold_idx - for i, p in enumerate(self.products): - pgroup = group.create_group('product_{}'.format(i)) - p.to_hdf5(pgroup) - - @classmethod - def from_hdf5(cls, group, energy): - """Generate reaction from an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - energy : dict - Dictionary whose keys are temperatures (e.g., '300K') and values are - arrays of energies at which cross sections are tabulated at. - - Returns - ------- - openmc.data.Reaction - Reaction data - - """ - - mt = group.attrs['mt'] - rx = cls(mt) - rx.q_value = group.attrs['Q_value'] - rx.center_of_mass = bool(group.attrs['center_of_mass']) - rx.redundant = bool(group.attrs.get('redundant', False)) - - # Read cross section at each temperature - for T, Tgroup in group.items(): - if T.endswith('K'): - if 'xs' in Tgroup: - # Make sure temperature has associated energy grid - if T not in energy: - raise ValueError( - 'Could not create reaction cross section for MT={} ' - 'at T={} because no corresponding energy grid ' - 'exists.'.format(mt, T)) - xs = Tgroup['xs'][()] - threshold_idx = Tgroup['xs'].attrs['threshold_idx'] - tabulated_xs = Tabulated1D(energy[T][threshold_idx:], xs) - tabulated_xs._threshold_idx = threshold_idx - rx.xs[T] = tabulated_xs - - # Determine number of products - n_product = 0 - for name in group: - if name.startswith('product_'): - n_product += 1 - - # Read reaction products - for i in range(n_product): - pgroup = group['product_{}'.format(i)] - rx.products.append(Product.from_hdf5(pgroup)) - - return rx - - @classmethod - def from_ace(cls, ace, i_reaction): - # Get nuclide energy grid - n_grid = ace.nxs[3] - grid = ace.xss[ace.jxs[1]:ace.jxs[1] + n_grid]*EV_PER_MEV - - # Convert data temperature to a "300.0K" number for indexing - # temperature data - strT = str(int(round(ace.temperature*EV_PER_MEV / K_BOLTZMANN))) + "K" - - if i_reaction > 0: - mt = int(ace.xss[ace.jxs[3] + i_reaction - 1]) - rx = cls(mt) - - # Get Q-value of reaction - rx.q_value = ace.xss[ace.jxs[4] + i_reaction - 1]*EV_PER_MEV - - # ================================================================== - # CROSS SECTION - - # Get locator for cross-section data - loc = int(ace.xss[ace.jxs[6] + i_reaction - 1]) - - # Determine starting index on energy grid - threshold_idx = int(ace.xss[ace.jxs[7] + loc - 1]) - 1 - - # Determine number of energies in reaction - n_energy = int(ace.xss[ace.jxs[7] + loc]) - energy = grid[threshold_idx:threshold_idx + n_energy] - - # Read reaction cross section - xs = ace.xss[ace.jxs[7] + loc + 1:ace.jxs[7] + loc + 1 + n_energy] - - # For damage energy production, convert to eV - if mt == 444: - xs *= EV_PER_MEV - - # Fix negatives -- known issue for Y89 in JEFF 3.2 - if np.any(xs < 0.0): - warn("Negative cross sections found for MT={} in {}. Setting " - "to zero.".format(rx.mt, ace.name)) - xs[xs < 0.0] = 0.0 - - tabulated_xs = Tabulated1D(energy, xs) - tabulated_xs._threshold_idx = threshold_idx - rx.xs[strT] = tabulated_xs - - # ================================================================== - # YIELD AND ANGLE-ENERGY DISTRIBUTION - - # Determine multiplicity - ty = int(ace.xss[ace.jxs[5] + i_reaction - 1]) - rx.center_of_mass = (ty < 0) - if i_reaction < ace.nxs[5] + 1: - if ty != 19: - if abs(ty) > 100: - # Energy-dependent neutron yield - idx = ace.jxs[11] + abs(ty) - 101 - yield_ = Tabulated1D.from_ace(ace, idx) - else: - # 0-order polynomial i.e. a constant - yield_ = Polynomial((abs(ty),)) - - neutron = Product('neutron') - neutron.yield_ = yield_ - rx.products.append(neutron) - else: - assert mt in (18, 19, 20, 21, 38) - rx.products, rx.derived_products = _get_fission_products_ace(ace) - - for p in rx.products: - if p.emission_mode in ('prompt', 'total'): - neutron = p - break - else: - raise Exception("Couldn't find prompt/total fission neutron") - - # Determine locator for ith energy distribution - lnw = int(ace.xss[ace.jxs[10] + i_reaction - 1]) - while lnw > 0: - # Applicability of this distribution - neutron.applicability.append(Tabulated1D.from_ace( - ace, ace.jxs[11] + lnw + 2)) - - # Read energy distribution data - neutron.distribution.append(AngleEnergy.from_ace( - ace, ace.jxs[11], lnw, rx)) - - lnw = int(ace.xss[ace.jxs[11] + lnw - 1]) - - else: - # Elastic scattering - mt = 2 - rx = cls(mt) - - # Get elastic cross section values - elastic_xs = ace.xss[ace.jxs[1] + 3*n_grid:ace.jxs[1] + 4*n_grid] - - # Fix negatives -- known issue for Ti46,49,50 in JEFF 3.2 - if np.any(elastic_xs < 0.0): - warn("Negative elastic scattering cross section found for {}. " - "Setting to zero.".format(ace.name)) - elastic_xs[elastic_xs < 0.0] = 0.0 - - tabulated_xs = Tabulated1D(grid, elastic_xs) - tabulated_xs._threshold_idx = 0 - rx.xs[strT] = tabulated_xs - - # No energy distribution for elastic scattering - neutron = Product('neutron') - neutron.distribution.append(UncorrelatedAngleEnergy()) - rx.products.append(neutron) - - # ====================================================================== - # ANGLE DISTRIBUTION (FOR UNCORRELATED) - - if i_reaction < ace.nxs[5] + 1: - # Check if angular distribution data exist - loc = int(ace.xss[ace.jxs[8] + i_reaction]) - if loc <= 0: - # Angular distribution is either given as part of a product - # angle-energy distribution or is not given at all (in which - # case isotropic scattering is assumed) - angle_dist = None - else: - angle_dist = AngleDistribution.from_ace(ace, ace.jxs[9], loc) - - # Apply angular distribution to each uncorrelated angle-energy - # distribution - if angle_dist is not None: - for d in neutron.distribution: - d.angle = angle_dist - - # ====================================================================== - # PHOTON PRODUCTION - - rx.products += _get_photon_products_ace(ace, rx) - - return rx - - @classmethod - def from_endf(cls, ev, mt): - """Generate a reaction from an ENDF evaluation - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - mt : int - The MT value of the reaction to get data for - - Returns - ------- - rx : openmc.data.Reaction - Reaction data - - """ - rx = Reaction(mt) - - # Integrated cross section - if (3, mt) in ev.section: - file_obj = StringIO(ev.section[3, mt]) - get_head_record(file_obj) - params, rx.xs['0K'] = get_tab1_record(file_obj) - rx.q_value = params[1] - - # Get fission product yields (nu) as well as delayed neutron energy - # distributions - if mt in (18, 19, 20, 21, 38): - rx.products, rx.derived_products = _get_fission_products_endf(ev) - - if (6, mt) in ev.section: - # Product angle-energy distribution - for product in _get_products(ev, mt): - if mt in (18, 19, 20, 21, 38) and product.particle == 'neutron': - rx.products[0].applicability = product.applicability - rx.products[0].distribution = product.distribution - else: - rx.products.append(product) - - elif (4, mt) in ev.section or (5, mt) in ev.section: - # Uncorrelated angle-energy distribution - neutron = Product('neutron') - - # Note that the energy distribution for MT=455 is read in - # _get_fission_products_endf rather than here - if (5, mt) in ev.section: - file_obj = StringIO(ev.section[5, mt]) - items = get_head_record(file_obj) - nk = items[4] - for i in range(nk): - params, applicability = get_tab1_record(file_obj) - dist = UncorrelatedAngleEnergy() - dist.energy = EnergyDistribution.from_endf(file_obj, params) - - neutron.applicability.append(applicability) - neutron.distribution.append(dist) - elif mt == 2: - # Elastic scattering -- no energy distribution is given since it - # can be calulcated analytically - dist = UncorrelatedAngleEnergy() - neutron.distribution.append(dist) - elif mt >= 51 and mt < 91: - # Level inelastic scattering -- no energy distribution is given - # since it can be calculated analytically. Here we determine the - # necessary parameters to create a LevelInelastic object - dist = UncorrelatedAngleEnergy() - - A = ev.target['mass'] - threshold = (A + 1.)/A*abs(rx.q_value) - mass_ratio = (A/(A + 1.))**2 - dist.energy = LevelInelastic(threshold, mass_ratio) - - neutron.distribution.append(dist) - - if (4, mt) in ev.section: - for dist in neutron.distribution: - dist.angle = AngleDistribution.from_endf(ev, mt) - - if mt in (18, 19, 20, 21, 38) and (5, mt) in ev.section: - # For fission reactions, - rx.products[0].applicability = neutron.applicability - rx.products[0].distribution = neutron.distribution - else: - rx.products.append(neutron) - - if (8, mt) in ev.section: - rx.products += _get_activation_products(ev, rx) - - if (12, mt) in ev.section or (13, mt) in ev.section: - rx.products += _get_photon_products_endf(ev, rx) - - return rx diff --git a/openmc/data/reconstruct.pyx b/openmc/data/reconstruct.pyx deleted file mode 100644 index f63a155b1..000000000 --- a/openmc/data/reconstruct.pyx +++ /dev/null @@ -1,522 +0,0 @@ -from libc.stdlib cimport malloc, calloc, free -from libc.math cimport cos, sin, sqrt, atan, M_PI - -cimport numpy as np -import numpy as np -from numpy.linalg import inv -cimport cython - - -cdef extern from "complex.h": - double cabs(double complex) - double complex conj(double complex) - double creal(complex double) - double cimag(complex double) - double complex cexp(double complex) - -# Physical constants are from CODATA 2014 -cdef double NEUTRON_MASS_ENERGY = 939.5654133e6 # eV/c^2 -cdef double HBAR_C = 197.3269788e5 # eV-b^0.5 - - -@cython.cdivision(True) -def wave_number(double A, double E): - r"""Neutron wave number in center-of-mass system. - - ENDF-102 defines the neutron wave number in the center-of-mass system in - Equation D.10 as - - .. math:: - k = \frac{2m_n}{\hbar} \frac{A}{A + 1} \sqrt{|E|} - - Parameters - ---------- - A : double - Ratio of target mass to neutron mass - E : double - Energy in eV - - Returns - ------- - double - Neutron wave number in b^-0.5 - - """ - return A/(A + 1)*sqrt(2*NEUTRON_MASS_ENERGY*abs(E))/HBAR_C - -@cython.cdivision(True) -cdef double _wave_number(double A, double E): - return A/(A + 1)*sqrt(2*NEUTRON_MASS_ENERGY*abs(E))/HBAR_C - - -@cython.cdivision(True) -cdef double phaseshift(int l, double rho): - """Calculate hardsphere phase shift as given in ENDF-102, Equation D.13 - - Parameters - ---------- - l : int - Angular momentum quantum number - rho : float - Product of the wave number and the channel radius - - Returns - ------- - double - Hardsphere phase shift - - """ - if l == 0: - return rho - elif l == 1: - return rho - atan(rho) - elif l == 2: - return rho - atan(3*rho/(3 - rho**2)) - elif l == 3: - return rho - atan((15*rho - rho**3)/(15 - 6*rho**2)) - elif l == 4: - return rho - atan((105*rho - 10*rho**3)/(105 - 45*rho**2 + rho**4)) - - -@cython.cdivision(True) -def penetration_shift(int l, double rho): - r"""Calculate shift and penetration factors as given in ENDF-102, Equations D.11 - and D.12. - - Parameters - ---------- - l : int - Angular momentum quantum number - rho : float - Product of the wave number and the channel radius - - Returns - ------- - double - Penetration factor for given :math:`l` - double - Shift factor for given :math:`l` - - """ - cdef double den - - if l == 0: - return rho, 0. - elif l == 1: - den = 1 + rho**2 - return rho**3/den, -1/den - elif l == 2: - den = 9 + 3*rho**2 + rho**4 - return rho**5/den, -(18 + 3*rho**2)/den - elif l == 3: - den = 225 + 45*rho**2 + 6*rho**4 + rho**6 - return rho**7/den, -(675 + 90*rho**2 + 6*rho**4)/den - elif l == 4: - den = 11025 + 1575*rho**2 + 135*rho**4 + 10*rho**6 + rho**8 - return rho**9/den, -(44100 + 4725*rho**2 + 270*rho**4 + 10*rho**6)/den - - -@cython.boundscheck(False) -@cython.wraparound(False) -@cython.cdivision(True) -def reconstruct_mlbw(mlbw, double E): - """Evaluate cross section using MLBW data. - - Parameters - ---------- - mlbw : openmc.data.MultiLevelBreitWigner - Multi-level Breit-Wigner resonance parameters - E : double - Energy in eV at which to evaluate the cross section - - Returns - ------- - elastic : double - Elastic scattering cross section in barns - capture : double - Radiative capture cross section in barns - fission : double - Fission cross section in barns - - """ - cdef int i, nJ, ij, l, n_res, i_res - cdef double elastic, capture, fission - cdef double A, k, rho, rhohat, I - cdef double P, S, phi, cos2phi, sin2phi - cdef double Ex, Q, rhoc, rhochat, P_c, S_c - cdef double jmin, jmax, j, Dl - cdef double E_r, gt, gn, gg, gf, gx, P_r, S_r, P_rx - cdef double gnE, gtE, Eprime, x, f - cdef double *g - cdef double (*s)[2] - cdef double [:,:] params - - I = mlbw.target_spin - A = mlbw.atomic_weight_ratio - k = _wave_number(A, E) - - elastic = 0. - capture = 0. - fission = 0. - - for i, l in enumerate(mlbw._l_values): - params = mlbw._parameter_matrix[l] - - rho = k*mlbw.channel_radius[l](E) - rhohat = k*mlbw.scattering_radius[l](E) - P, S = penetration_shift(l, rho) - phi = phaseshift(l, rhohat) - cos2phi = cos(2*phi) - sin2phi = sin(2*phi) - - # Determine shift and penetration at modified energy - if mlbw._competitive[i]: - Ex = E + mlbw.q_value[l]*(A + 1)/A - rhoc = mlbw.channel_radius[l](Ex) - rhochat = mlbw.scattering_radius[l](Ex) - P_c, S_c = penetration_shift(l, rhoc) - if Ex < 0: - P_c = 0 - - # Determine range of total angular momentum values based on equation - # 41 in LA-UR-12-27079 - jmin = abs(abs(I - l) - 0.5) - jmax = I + l + 0.5 - nJ = int(jmax - jmin + 1) - - # Determine Dl factor using Equation 43 in LA-UR-12-27079 - Dl = 2*l + 1 - g = malloc(nJ*sizeof(double)) - for ij in range(nJ): - j = jmin + ij - g[ij] = (2*j + 1)/(4*I + 2) - Dl -= g[ij] - - s = calloc(2*nJ, sizeof(double)) - for i_res in range(params.shape[0]): - # Copy resonance parameters - E_r = params[i_res, 0] - j = params[i_res, 2] - ij = int(j - jmin) - gt = params[i_res, 3] - gn = params[i_res, 4] - gg = params[i_res, 5] - gf = params[i_res, 6] - gx = params[i_res, 7] - P_r = params[i_res, 8] - S_r = params[i_res, 9] - P_rx = params[i_res, 10] - - # Calculate neutron and total width at energy E - gnE = P*gn/P_r # ENDF-102, Equation D.7 - gtE = gnE + gg + gf - if gx > 0: - gtE += gx*P_c/P_rx - - Eprime = E_r + (S_r - S)/(2*P_r)*gn # ENDF-102, Equation D.9 - x = 2*(E - Eprime)/gtE # LA-UR-12-27079, Equation 26 - f = 2*gnE/(gtE*(1 + x*x)) # Common factor in Equation 40 - s[ij][0] += f # First sum in Equation 40 - s[ij][1] += f*x # Second sum in Equation 40 - capture += f*g[ij]*gg/gtE - if gf > 0: - fission += f*g[ij]*gf/gtE - - for ij in range(nJ): - # Add all but last term of LA-UR-12-27079, Equation 40 - elastic += g[ij]*((1 - cos2phi - s[ij][0])**2 + - (sin2phi + s[ij][1])**2) - - # Add final term with Dl from Equation 40 - elastic += 2*Dl*(1 - cos2phi) - - # Free memory - free(g) - free(s) - - capture *= 2*M_PI/(k*k) - fission *= 2*M_PI/(k*k) - elastic *= M_PI/(k*k) - - return (elastic, capture, fission) - - -@cython.boundscheck(False) -@cython.wraparound(False) -@cython.cdivision(True) -def reconstruct_slbw(slbw, double E): - """Evaluate cross section using SLBW data. - - Parameters - ---------- - slbw : openmc.data.SingleLevelBreitWigner - Single-level Breit-Wigner resonance parameters - E : double - Energy in eV at which to evaluate the cross section - - Returns - ------- - elastic : double - Elastic scattering cross section in barns - capture : double - Radiative capture cross section in barns - fission : double - Fission cross section in barns - - """ - cdef int i, l, i_res - cdef double elastic, capture, fission - cdef double A, k, rho, rhohat, I - cdef double P, S, phi, cos2phi, sin2phi, sinphi2 - cdef double Ex, rhoc, rhochat, P_c, S_c - cdef double E_r, J, gt, gn, gg, gf, gx, P_r, S_r, P_rx - cdef double gnE, gtE, Eprime, f - cdef double x, theta, psi, chi - cdef double [:,:] params - - I = slbw.target_spin - A = slbw.atomic_weight_ratio - k = _wave_number(A, E) - - elastic = 0. - capture = 0. - fission = 0. - - for i, l in enumerate(slbw._l_values): - params = slbw._parameter_matrix[l] - - rho = k*slbw.channel_radius[l](E) - rhohat = k*slbw.scattering_radius[l](E) - P, S = penetration_shift(l, rho) - phi = phaseshift(l, rhohat) - cos2phi = cos(2*phi) - sin2phi = sin(2*phi) - sinphi2 = sin(phi)**2 - - # Add potential scattering -- first term in ENDF-102, Equation D.2 - elastic += 4*M_PI/(k*k)*(2*l + 1)*sinphi2 - - # Determine shift and penetration at modified energy - if slbw._competitive[i]: - Ex = E + slbw.q_value[l]*(A + 1)/A - rhoc = slbw.channel_radius[l](Ex) - rhochat = slbw.scattering_radius[l](Ex) - P_c, S_c = penetration_shift(l, rhoc) - if Ex < 0: - P_c = 0 - - for i_res in range(params.shape[0]): - # Copy resonance parameters - E_r = params[i_res, 0] - J = params[i_res, 2] - gt = params[i_res, 3] - gn = params[i_res, 4] - gg = params[i_res, 5] - gf = params[i_res, 6] - gx = params[i_res, 7] - P_r = params[i_res, 8] - S_r = params[i_res, 9] - P_rx = params[i_res, 10] - - # Calculate neutron and total width at energy E - gnE = P*gn/P_r # Equation D.7 - gtE = gnE + gg + gf - if gx > 0: - gtE += gx*P_c/P_rx - - Eprime = E_r + (S_r - S)/(2*P_r)*gn # Equation D.9 - gJ = (2*J + 1)/(4*I + 2) # Mentioned in section D.1.1.4 - - # Calculate common factor for elastic, capture, and fission - # cross sections - f = M_PI/(k*k)*gJ*gnE/((E - Eprime)**2 + gtE**2/4) - - # Add contribution to elastic per Equation D.2 - elastic += f*(gnE*cos2phi - 2*(gg + gf)*sinphi2 - + 2*(E - Eprime)*sin2phi) - - # Add contribution to capture per Equation D.3 - capture += f*gg - - # Add contribution to fission per Equation D.6 - if gf > 0: - fission += f*gf - - return (elastic, capture, fission) - - -@cython.boundscheck(False) -@cython.wraparound(False) -@cython.cdivision(True) -def reconstruct_rm(rm, double E): - """Evaluate cross section using Reich-Moore data. - - Parameters - ---------- - rm : openmc.data.ReichMoore - Reich-Moore resonance parameters - E : double - Energy in eV at which to evaluate the cross section - - Returns - ------- - elastic : double - Elastic scattering cross section in barns - capture : double - Radiative capture cross section in barns - fission : double - Fission cross section in barns - - """ - cdef int i, l, m, n, i_res - cdef int i_s, num_s, i_J, num_J - cdef double elastic, capture, fission, total - cdef double A, k, rho, rhohat, I - cdef double P, S, phi - cdef double smin, smax, s, Jmin, Jmax, J, j - cdef double E_r, gn, gg, gfa, gfb, P_r - cdef double E_diff, abs_value, gJ - cdef double Kr, Ki, x - cdef double complex Ubar, U_, factor - cdef bint hasfission - cdef np.ndarray[double, ndim=2] one - cdef np.ndarray[double complex, ndim=2] K, Imat, U - cdef double [:,:] params - - # Get nuclear spin - I = rm.target_spin - - elastic = 0. - fission = 0. - total = 0. - A = rm.atomic_weight_ratio - k = _wave_number(A, E) - one = np.eye(3) - K = np.zeros((3,3), dtype=complex) - - for i, l in enumerate(rm._l_values): - # Check for l-dependent scattering radius - rho = k*rm.channel_radius[l](E) - rhohat = k*rm.scattering_radius[l](E) - - # Calculate shift and penetrability - P, S = penetration_shift(l, rho) - - # Calculate phase shift - phi = phaseshift(l, rhohat) - - # Calculate common factor on collision matrix terms (term outside curly - # braces in ENDF-102, Eq. D.27) - Ubar = cexp(-2j*phi) - - # The channel spin is the vector sum of the target spin, I, and the - # neutron spin, 1/2, so can take on values of |I - 1/2| < s < I + 1/2 - smin = abs(I - 0.5) - smax = I + 0.5 - num_s = int(smax - smin + 1) - - for i_s in range(num_s): - s = i_s + smin - - # Total angular momentum is the vector sum of l and s and can assume - # values between |l - s| < J < l + s - Jmin = abs(l - s) - Jmax = l + s - num_J = int(Jmax - Jmin + 1) - - for i_J in range(num_J): - J = i_J + Jmin - - # Initialize K matrix - for m in range(3): - for n in range(3): - K[m,n] = 0.0 - - hasfission = False - if (l, J) in rm._parameter_matrix: - params = rm._parameter_matrix[l, J] - - for i_res in range(params.shape[0]): - # Sometimes, the same (l, J) quantum numbers can occur - # for different values of the channel spin, s. In this - # case, the sign of the channel spin indicates which - # spin is to be used. If the spin is negative assume - # this resonance comes from the I - 1/2 channel and vice - # versa. - j = params[i_res, 2] - if l > 0: - if (j < 0 and s != smin) or (j > 0 and s != smax): - continue - - # Copy resonance parameters - E_r = params[i_res, 0] - gn = params[i_res, 3] - gg = params[i_res, 4] - gfa = params[i_res, 5] - gfb = params[i_res, 6] - P_r = params[i_res, 7] - - # Calculate neutron width at energy E - gn = sqrt(P*gn/P_r) - - # Calculate j/2 * inverse of denominator of K matrix terms - factor = 0.5j/(E_r - E - 0.5j*gg) - - # Upper triangular portion of K matrix -- see ENDF-102, - # Equation D.28 - K[0,0] = K[0,0] + gn*gn*factor - if gfa != 0.0 or gfb != 0.0: - # Negate fission widths if necessary - gfa = (-1 if gfa < 0 else 1)*sqrt(abs(gfa)) - gfb = (-1 if gfb < 0 else 1)*sqrt(abs(gfb)) - - K[0,1] = K[0,1] + gn*gfa*factor - K[0,2] = K[0,2] + gn*gfb*factor - K[1,1] = K[1,1] + gfa*gfa*factor - K[1,2] = K[1,2] + gfa*gfb*factor - K[2,2] = K[2,2] + gfb*gfb*factor - hasfission = True - - # Get collision matrix - gJ = (2*J + 1)/(4*I + 2) - if hasfission: - # Copy upper triangular portion of K to lower triangular - K[1,0] = K[0,1] - K[2,0] = K[0,2] - K[2,1] = K[1,2] - - Imat = inv(one - K) - U = Ubar*(2*Imat - one) # ENDF-102, Eq. D.27 - elastic += gJ*cabs(1 - U[0,0])**2 # ENDF-102, Eq. D.24 - total += 2*gJ*(1 - creal(U[0,0])) # ENDF-102, Eq. D.23 - - # Calculate fission from ENDF-102, Eq. D.26 - fission += 4*gJ*(cabs(Imat[1,0])**2 + cabs(Imat[2,0])**2) - else: - U_ = Ubar*(2/(1 - K[0,0]) - 1) - if abs(creal(K[0,0])) < 3e-4 and abs(phi) < 3e-4: - # If K and phi are both very small, the calculated cross - # sections can lose precision because the real part of U - # ends up very close to unity. To get around this, we - # use Euler's formula to express Ubar by real and - # imaginary parts, expand cos(2phi) = 1 - 2phi^2 + - # O(phi^4), and then simplify - Kr = creal(K[0,0]) - Ki = cimag(K[0,0]) - x = 2*(-Kr + (Kr*Kr + Ki*Ki)*(1 - phi*phi) + phi*phi - - sin(2*phi)*Ki)/((1 - Kr)*(1 - Kr) + Ki*Ki) - total += 2*gJ*x - elastic += gJ*(x*x + cimag(U_)**2) - else: - total += 2*gJ*(1 - creal(U_)) # ENDF-102, Eq. D.23 - elastic += gJ*cabs(1 - U_)**2 # ENDF-102, Eq. D.24 - - # Calculate capture as difference of other cross sections as per ENDF-102, - # Equation D.25 - capture = total - elastic - fission - - elastic *= M_PI/(k*k) - capture *= M_PI/(k*k) - fission *= M_PI/(k*k) - - return (elastic, capture, fission) diff --git a/openmc/data/resonance.py b/openmc/data/resonance.py deleted file mode 100644 index 5e4bd7129..000000000 --- a/openmc/data/resonance.py +++ /dev/null @@ -1,1071 +0,0 @@ -from collections import defaultdict -from collections.abc import MutableSequence, Iterable -import io - -import numpy as np -from numpy.polynomial import Polynomial -import pandas as pd - -from .data import NEUTRON_MASS -from .endf import get_head_record, get_cont_record, get_tab1_record, get_list_record -try: - from .reconstruct import wave_number, penetration_shift, reconstruct_mlbw, \ - reconstruct_slbw, reconstruct_rm - _reconstruct = True -except ImportError: - _reconstruct = False -import openmc.checkvalue as cv - - -class Resonances(object): - """Resolved and unresolved resonance data - - Parameters - ---------- - ranges : list of openmc.data.ResonanceRange - Distinct energy ranges for resonance data - - Attributes - ---------- - ranges : list of openmc.data.ResonanceRange - Distinct energy ranges for resonance data - resolved : openmc.data.ResonanceRange or None - Resolved resonance range - unresolved : openmc.data.Unresolved or None - Unresolved resonance range - - """ - - def __init__(self, ranges): - self.ranges = ranges - - def __iter__(self): - for r in self.ranges: - yield r - - @property - def ranges(self): - return self._ranges - - @property - def resolved(self): - resolved_ranges = [r for r in self.ranges - if not isinstance(r, Unresolved)] - if len(resolved_ranges) > 1: - raise ValueError('More than one resolved range present') - elif len(resolved_ranges) == 0: - return None - else: - return resolved_ranges[0] - - @property - def unresolved(self): - for r in self.ranges: - if isinstance(r, Unresolved): - return r - else: - return None - - @ranges.setter - def ranges(self, ranges): - cv.check_type('resonance ranges', ranges, MutableSequence) - self._ranges = cv.CheckedList(ResonanceRange, 'resonance ranges', - ranges) - - @classmethod - def from_endf(cls, ev): - """Generate resonance data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - - Returns - ------- - openmc.data.Resonances - Resonance data - - """ - file_obj = io.StringIO(ev.section[2, 151]) - - # Determine whether discrete or continuous representation - items = get_head_record(file_obj) - n_isotope = items[4] # Number of isotopes - - ranges = [] - for iso in range(n_isotope): - items = get_cont_record(file_obj) - abundance = items[1] - fission_widths = (items[3] == 1) # fission widths are given? - n_ranges = items[4] # number of resonance energy ranges - - for j in range(n_ranges): - items = get_cont_record(file_obj) - resonance_flag = items[2] # flag for resolved (1)/unresolved (2) - formalism = items[3] # resonance formalism - - if resonance_flag in (0, 1): - # resolved resonance region - erange = _FORMALISMS[formalism].from_endf(ev, file_obj, items) - - elif resonance_flag == 2: - # unresolved resonance region - erange = Unresolved.from_endf(file_obj, items, fission_widths) - - # erange.material = self - ranges.append(erange) - - return cls(ranges) - - -class ResonanceRange(object): - """Resolved resonance range - - Parameters - ---------- - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - channel : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - scattering : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - - Attributes - ---------- - channel_radius : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - energy_max : float - Maximum energy of the resolved resonance range in eV - energy_min : float - Minimum energy of the resolved resonance range in eV - scattering_radius : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energ - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - - """ - def __init__(self, target_spin, energy_min, energy_max, channel, scattering): - self.target_spin = target_spin - self.energy_min = energy_min - self.energy_max = energy_max - self.channel_radius = channel - self.scattering_radius = scattering - - self._prepared = False - self._parameter_matrix = {} - - def __copy__(self): - cls = type(self) - new_copy = cls.__new__(cls) - new_copy.__dict__.update(self.__dict__) - new_copy._prepared = False - return new_copy - - @classmethod - def from_endf(cls, ev, file_obj, items): - """Create resonance range from an ENDF evaluation. - - This factory method is only used when LRU=0, indicating that only a - scattering radius appears in MF=2, MT=151. All subclasses of - ResonanceRange override this method with their own. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - - Returns - ------- - openmc.data.ResonanceRange - Resonance range data - - """ - energy_min, energy_max = items[0:2] - - # For scattering radius-only, NRO must be zero - assert items[4] == 0 - - # Get energy-independent scattering radius - items = get_cont_record(file_obj) - target_spin = items[0] - ap = Polynomial((items[1],)) - - # Calculate channel radius from ENDF-102 equation D.14 - a = Polynomial((0.123 * (NEUTRON_MASS*ev.target['mass'])**(1./3.) + 0.08,)) - - return cls(target_spin, energy_min, energy_max, {0: a}, {0: ap}) - - def reconstruct(self, energies): - """Evaluate cross section at specified energies. - - Parameters - ---------- - energies : float or Iterable of float - Energies at which the cross section should be evaluated - - Returns - ------- - 3-tuple of float or numpy.ndarray - Elastic, capture, and fission cross sections at the specified - energies - - """ - if not _reconstruct: - raise RuntimeError("Resonance reconstruction not available.") - - # Pre-calculate penetrations and shifts for resonances - if not self._prepared: - self._prepare_resonances() - - if isinstance(energies, Iterable): - elastic = np.zeros_like(energies) - capture = np.zeros_like(energies) - fission = np.zeros_like(energies) - - for i, E in enumerate(energies): - xse, xsg, xsf = self._reconstruct(self, E) - elastic[i] = xse - capture[i] = xsg - fission[i] = xsf - else: - elastic, capture, fission = self._reconstruct(self, energies) - - return {2: elastic, 102: capture, 18: fission} - - -class MultiLevelBreitWigner(ResonanceRange): - """Multi-level Breit-Wigner resolved resonance formalism data. - - Multi-level Breit-Wigner resolved resonance data is identified by LRF=2 in - the ENDF-6 format. - - Parameters - ---------- - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - channel : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - scattering : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - - Attributes - ---------- - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide given as a function of - l-value. Note that this may be different than the value for the - evaluation as a whole. - channel_radius : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - energy_max : float - Maximum energy of the resolved resonance range in eV - energy_min : float - Minimum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Energies, spins, and resonances widths for each resonance - q_value : dict - Q-value to be added to incident particle's center-of-mass energy to - determine the channel energy for use in the penetrability factor. The - keys of the dictionary are l-values. - scattering_radius : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - - """ - - def __init__(self, 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 - - # Set resonance reconstruction function - if _reconstruct: - self._reconstruct = reconstruct_mlbw - else: - self._reconstruct = None - - @classmethod - def from_endf(cls, ev, file_obj, items): - """Create MLBW data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - - Returns - ------- - openmc.data.MultiLevelBreitWigner - Multi-level Breit-Wigner resonance parameters - - """ - - # Read energy-dependent scattering radius if present - energy_min, energy_max = items[0:2] - nro, naps = items[4:6] - if nro != 0: - params, ape = get_tab1_record(file_obj) - - # Other scatter radius parameters - items = get_cont_record(file_obj) - target_spin = items[0] - ap = Polynomial((items[1],)) # energy-independent scattering-radius - NLS = items[4] # number of l-values - - # Read resonance widths, J values, etc - channel_radius = {} - scattering_radius = {} - q_value = {} - records = [] - for l in range(NLS): - items, values = get_list_record(file_obj) - l_value = items[2] - awri = items[0] - q_value[l_value] = items[1] - competitive = items[3] - - # Calculate channel radius from ENDF-102 equation D.14 - a = Polynomial((0.123 * (NEUTRON_MASS*awri)**(1./3.) + 0.08,)) - - # Construct scattering and channel radius - if nro == 0: - scattering_radius[l_value] = ap - if naps == 0: - channel_radius[l_value] = a - elif naps == 1: - channel_radius[l_value] = ap - elif nro == 1: - scattering_radius[l_value] = ape - if naps == 0: - channel_radius[l_value] = a - elif naps == 1: - channel_radius[l_value] = ape - elif naps == 2: - channel_radius[l_value] = ap - - energy = values[0::6] - spin = values[1::6] - gt = np.asarray(values[2::6]) - gn = np.asarray(values[3::6]) - gg = np.asarray(values[4::6]) - gf = np.asarray(values[5::6]) - if competitive > 0: - gx = gt - (gn + gg + gf) - else: - gx = np.zeros_like(gt) - - for i, E in enumerate(energy): - records.append([energy[i], l_value, spin[i], gt[i], gn[i], - gg[i], gf[i], gx[i]]) - - columns = ['energy', 'L', 'J', 'totalWidth', 'neutronWidth', - 'captureWidth', 'fissionWidth', 'competitiveWidth'] - parameters = pd.DataFrame.from_records(records, columns=columns) - - # Create instance of class - mlbw = cls(target_spin, energy_min, energy_max, - channel_radius, scattering_radius) - mlbw.q_value = q_value - mlbw.atomic_weight_ratio = awri - mlbw.parameters = parameters - - return mlbw - - def _prepare_resonances(self): - df = self.parameters.copy() - - # Penetration and shift factors - p = np.zeros(len(df)) - s = np.zeros(len(df)) - - # Penetration and shift factors for competitive reaction - px = np.zeros(len(df)) - sx = np.zeros(len(df)) - - l_values = [] - competitive = [] - - A = self.atomic_weight_ratio - for i, E, l, J, gt, gn, gg, gf, gx in df.itertuples(): - if l not in l_values: - l_values.append(l) - competitive.append(gx > 0) - - # Determine penetration and shift corresponding to resonance energy - k = wave_number(A, E) - rho = k*self.channel_radius[l](E) - rhohat = k*self.scattering_radius[l](E) - p[i], s[i] = penetration_shift(l, rho) - - # Determine penetration at modified energy for competitive reaction - if gx > 0: - Ex = E + self.q[l]*(A + 1)/A - rho = k*self.channel_radius[l](Ex) - rhohat = k*self.scattering_radius[l](Ex) - px[i], sx[i] = penetration_shift(l, rho) - else: - px[i] = sx[i] = 0.0 - - df['p'] = p - df['s'] = s - df['px'] = px - df['sx'] = sx - - self._l_values = np.array(l_values) - self._competitive = np.array(competitive) - for l in l_values: - self._parameter_matrix[l] = df[df.L == l].values - - self._prepared = True - - -class SingleLevelBreitWigner(MultiLevelBreitWigner): - """Single-level Breit-Wigner resolved resonance formalism data. - - Single-level Breit-Wigner resolved resonance data is is identified by LRF=1 - in the ENDF-6 format. - - Parameters - ---------- - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - channel : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - scattering : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - - Attributes - ---------- - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide given as a function of - l-value. Note that this may be different than the value for the - evaluation as a whole. - channel_radius : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - energy_max : float - Maximum energy of the resolved resonance range in eV - energy_min : float - Minimum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Energies, spins, and resonances widths for each resonance - q_value : dict - Q-value to be added to incident particle's center-of-mass energy to - determine the channel energy for use in the penetrability factor. The - keys of the dictionary are l-values. - scattering_radius : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - - """ - - def __init__(self, target_spin, energy_min, energy_max, channel, scattering): - super().__init__(target_spin, energy_min, energy_max, channel, - scattering) - - # Set resonance reconstruction function - if _reconstruct: - self._reconstruct = reconstruct_slbw - else: - self._reconstruct = None - - -class ReichMoore(ResonanceRange): - """Reich-Moore resolved resonance formalism data. - - Reich-Moore resolved resonance data is identified by LRF=3 in the ENDF-6 - format. - - Parameters - ---------- - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - channel : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - scattering : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - - Attributes - ---------- - angle_distribution : bool - Indicate whether parameters can be used to compute angular distributions - atomic_weight_ratio : float - Atomic weight ratio of the target nuclide given as a function of - l-value. Note that this may be different than the value for the - evaluation as a whole. - channel_radius : dict - Dictionary whose keys are l-values and values are channel radii as a - function of energy - energy_max : float - Maximum energy of the resolved resonance range in eV - energy_min : float - Minimum energy of the resolved resonance range in eV - num_l_convergence : int - Number of l-values which must be used to converge the calculation - scattering_radius : dict - Dictionary whose keys are l-values and values are scattering radii as a - function of energy - parameters : pandas.DataFrame - Energies, spins, and resonances widths for each resonance - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - - """ - - def __init__(self, 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 - - # Set resonance reconstruction function - if _reconstruct: - self._reconstruct = reconstruct_rm - else: - self._reconstruct = None - - @classmethod - def from_endf(cls, ev, file_obj, items): - """Create Reich-Moore resonance data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - - Returns - ------- - openmc.data.ReichMoore - Reich-Moore resonance parameters - - """ - # Read energy-dependent scattering radius if present - energy_min, energy_max = items[0:2] - nro, naps = items[4:6] - if nro != 0: - params, ape = get_tab1_record(file_obj) - - # Other scatter radius parameters - items = get_cont_record(file_obj) - target_spin = items[0] - ap = Polynomial((items[1],)) - angle_distribution = (items[3] == 1) # Flag for angular distribution - NLS = items[4] # Number of l-values - num_l_convergence = items[5] # Number of l-values for convergence - - # Read resonance widths, J values, etc - channel_radius = {} - scattering_radius = {} - records = [] - for i in range(NLS): - items, values = get_list_record(file_obj) - apl = Polynomial((items[1],)) if items[1] != 0.0 else ap - l_value = items[2] - awri = items[0] - - # Calculate channel radius from ENDF-102 equation D.14 - a = Polynomial((0.123 * (NEUTRON_MASS*awri)**(1./3.) + 0.08,)) - - # Construct scattering and channel radius - if nro == 0: - scattering_radius[l_value] = apl - if naps == 0: - channel_radius[l_value] = a - elif naps == 1: - channel_radius[l_value] = apl - elif nro == 1: - if naps == 0: - channel_radius[l_value] = a - scattering_radius[l_value] = ape - elif naps == 1: - channel_radius[l_value] = scattering_radius[l_value] = ape - elif naps == 2: - channel_radius[l_value] = apl - scattering_radius[l_value] = ape - - energy = values[0::6] - spin = values[1::6] - gn = values[2::6] - gg = values[3::6] - gfa = values[4::6] - gfb = values[5::6] - - for i, E in enumerate(energy): - records.append([energy[i], l_value, spin[i], gn[i], gg[i], - gfa[i], gfb[i]]) - - # Create pandas DataFrame with resonance data - columns = ['energy', 'L', 'J', 'neutronWidth', 'captureWidth', - 'fissionWidthA', 'fissionWidthB'] - parameters = pd.DataFrame.from_records(records, columns=columns) - - # Create instance of ReichMoore - rm = cls(target_spin, energy_min, energy_max, - channel_radius, scattering_radius) - rm.parameters = parameters - rm.angle_distribution = angle_distribution - rm.num_l_convergence = num_l_convergence - rm.atomic_weight_ratio = awri - - return rm - - def _prepare_resonances(self): - df = self.parameters.copy() - - # Penetration and shift factors - p = np.zeros(len(df)) - s = np.zeros(len(df)) - - l_values = [] - lj_values = [] - - A = self.atomic_weight_ratio - for i, E, l, J, gn, gg, gfa, gfb in df.itertuples(): - if l not in l_values: - l_values.append(l) - if (l, abs(J)) not in lj_values: - lj_values.append((l, abs(J))) - - # Determine penetration and shift corresponding to resonance energy - k = wave_number(A, E) - rho = k*self.channel_radius[l](E) - rhohat = k*self.scattering_radius[l](E) - p[i], s[i] = penetration_shift(l, rho) - - df['p'] = p - df['s'] = s - - self._l_values = np.array(l_values) - for (l, J) in lj_values: - self._parameter_matrix[l, J] = df[(df.L == l) & - (abs(df.J) == J)].values - - self._prepared = True - - -class RMatrixLimited(ResonanceRange): - """R-matrix limited resolved resonance formalism data. - - R-matrix limited resolved resonance data is identified by LRF=7 in the - ENDF-6 format. - - Parameters - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - particle_pairs : list of dict - List of particle pairs. Each particle pair is represented by a - dictionary that contains the mass, atomic number, spin, and parity of - each particle as well as other characteristics. - spin_groups : list of dict - List of spin groups. Each spin group is characterized by channels, - resonance energies, and resonance widths. - - Attributes - ---------- - reduced_width : bool - Flag indicating whether channel widths in eV or reduced-width amplitudes - in eV^1/2 are given - formalism : int - Flag to specify which formulae for the R-matrix are to be used - particle_pairs : list of dict - List of particle pairs. Each particle pair is represented by a - dictionary that contains the mass, atomic number, spin, and parity of - each particle as well as other characteristics. - spin_groups : list of dict - List of spin groups. Each spin group is characterized by channels, - resonance energies, and resonance widths. - - """ - - def __init__(self, energy_min, energy_max, particle_pairs, spin_groups): - super().__init__(0.0, energy_min, energy_max, None, None) - self.reduced_width = False - self.formalism = 3 - self.particle_pairs = particle_pairs - self.spin_groups = spin_groups - - @classmethod - def from_endf(cls, ev, file_obj, items): - """Read R-Matrix limited resonance data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - - Returns - ------- - openmc.data.RMatrixLimited - R-matrix limited resonance parameters - - """ - energy_min, energy_max = items[0:2] - - items = get_cont_record(file_obj) - reduced_width = (items[2] == 1) # reduced width amplitude? - formalism = items[3] # Specify which formulae are used - n_spin_groups = items[4] # Number of Jpi values (NJS) - - particle_pairs = [] - spin_groups = [] - - items, values = get_list_record(file_obj) - n_pairs = items[5]//2 # Number of particle pairs (NPP) - for i in range(n_pairs): - first = {'mass': values[12*i], - 'z': int(values[12*i + 2]), - 'spin': values[12*i + 4], - 'parity': values[12*i + 10]} - second = {'mass': values[12*i + 1], - 'z': int(values[12*i + 3]), - 'spin': values[12*i + 5], - 'parity': values[12*i + 11]} - - q_value = values[12*i + 6] - penetrability = values[12*i + 7] - shift = values[12*i + 8] - mt = int(values[12*i + 9]) - - particle_pairs.append(ParticlePair( - first, second, q_value, penetrability, shift, mt)) - - # loop over spin groups - for i in range(n_spin_groups): - items, values = get_list_record(file_obj) - J = items[0] - if J == 0.0: - parity = '+' if items[1] == 1.0 else '-' - else: - parity = '+' if J > 0. else '-' - J = abs(J) - kbk = items[2] - kps = items[3] - n_channels = items[5] - channels = [] - for j in range(n_channels): - channel = {} - channel['particle_pair'] = particle_pairs[ - int(values[6*j]) - 1] - channel['l'] = values[6*j + 1] - channel['spin'] = values[6*j + 2] - channel['boundary'] = values[6*j + 3] - channel['effective_radius'] = values[6*j + 4] - channel['true_radius'] = values[6*j + 5] - channels.append(channel) - - # Read resonance energies and widths - items, values = get_list_record(file_obj) - n_resonances = items[3] - records = [] - m = n_channels//6 + 1 - for j in range(n_resonances): - energy = values[6*m*j] - records.append([energy] + [values[6*m*j + k + 1] - for k in range(n_channels)]) - - # Determine column names - columns = ['energy'] - for channel in channels: - mt = channel['particle_pair'].mt - if mt == 2: - columns.append('neutronWidth') - elif mt == 18: - columns.append('fissionWidth') - elif mt == 102: - columns.append('captureWidth') - else: - columns.append('width (MT={})'.format(mt)) - - # Create Pandas dataframe with resonance parameters - parameters = pd.DataFrame.from_records(records, columns=columns) - - # Construct SpinGroup instance and add to list - sg = SpinGroup(J, parity, channels, parameters) - spin_groups.append(sg) - - # Optional extension (Background R-Matrix) - if kbk > 0: - items, values = get_list_record(file_obj) - lbk = items[4] - if lbk == 1: - params, rbr = get_tab1_record(file_obj) - params, rbi = get_tab1_record(file_obj) - - # Optional extension (Tabulated phase shifts) - if kps > 0: - items, values = get_list_record(file_obj) - lps = items[4] - if lps == 1: - params, psr = get_tab1_record(file_obj) - params, psi = get_tab1_record(file_obj) - - rml = cls(energy_min, energy_max, particle_pairs, spin_groups) - rml.reduced_width = reduced_width - rml.formalism = formalism - - return rml - - -class ParticlePair(object): - def __init__(self, first, second, q_value, penetrability, - shift, mt): - self.first = first - self.second = second - self.q_value = q_value - self.penetrability = penetrability - self.shift = shift - self.mt = mt - - -class SpinGroup(object): - """Resonance spin group - - Attributes - ---------- - spin : float - Total angular momentum (nuclear spin) - parity : {'+', '-'} - Even (+) or odd(-) parity - channels : list of openmc.data.Channel - Available channels - parameters : pandas.DataFrame - Energies/widths for each resonance/channel - - """ - - def __init__(self, spin, parity, channels, parameters): - self.spin = spin - self.parity = parity - self.channels = channels - self.parameters = parameters - - def __repr__(self): - return ''.format(self.spin, self.parity) - - -class Unresolved(ResonanceRange): - """Unresolved resonance parameters as identified by LRU=2 in MF=2. - - Parameters - ---------- - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - energy_min : float - Minimum energy of the unresolved resonance range in eV - energy_max : float - Maximum energy of the unresolved resonance range in eV - scatter : openmc.data.Function1D - Scattering radii as a function of energy - - Attributes - ---------- - add_to_background : bool - If True, file 3 contains partial cross sections to be added to the - average unresolved cross sections calculated from parameters. - energies : Iterable of float - Energies at which parameters are tabulated - energy_max : float - Maximum energy of the unresolved resonance range in eV - energy_min : float - Minimum energy of the unresolved resonance range in eV - parameters : list of pandas.DataFrame - Average resonance parameters at each energy - scattering_radius : openmc.data.Function1D - Scattering radii as a function of energy - target_spin : float - Intrinsic spin, :math:`I`, of the target nuclide - - """ - - def __init__(self, target_spin, energy_min, energy_max, scatter): - super().__init__(target_spin, energy_min, energy_max, None, scatter) - self.energies = None - self.parameters = None - self.add_to_background = False - - @classmethod - def from_endf(cls, file_obj, items, fission_widths): - """Read unresolved resonance data from an ENDF evaluation. - - Parameters - ---------- - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - fission_widths : bool - Whether fission widths are given - - Returns - ------- - openmc.data.Unresolved - Unresolved resonance region parameters - - """ - # Read energy-dependent scattering radius if present - energy_min, energy_max = items[0:2] - nro = items[4] - if nro != 0: - params, scattering_radius = get_tab1_record(file_obj) - - # Get SPI, AP, and LSSF - formalism = items[3] - if not (fission_widths and formalism == 1): - items = get_cont_record(file_obj) - target_spin = items[0] - if nro == 0: - scattering_radius = items[1] - add_to_background = (items[2] == 0) - - if not fission_widths and formalism == 1: - # Case A -- fission widths not given, all parameters are - # energy-independent - NLS = items[4] - columns = ['L', 'J', 'd', 'amun', 'gn', 'gg', 'gf'] - records = [] - for ls in range(NLS): - items, values = get_list_record(file_obj) - l = items[2] - NJS = items[5] - for j in range(NJS): - d, j, amun, gn, gg = values[6*j:6*j + 5] - records.append([l, j, d, amun, gn, gg, 0.0]) - parameters = pd.DataFrame.from_records(records, columns=columns) - energies = None - - elif fission_widths and formalism == 1: - # Case B -- fission widths given, only fission widths are - # energy-dependent - items, energies = get_list_record(file_obj) - target_spin = items[0] - if nro == 0: - scattering_radius = items[1] - add_to_background = (items[2] == 0) - NE, NLS = items[4:6] - l_values = np.zeros(NLS, int) - records = [[] for e in energies] - columns = ['L', 'J', 'd', 'amun', 'gn0', 'gg', 'gf'] - for ls in range(NLS): - items = get_cont_record(file_obj) - l = items[2] - NJS = items[4] - for j in range(NJS): - items, values = get_list_record(file_obj) - muf = items[3] - d = values[0] - j = values[1] - amun = values[2] - gn0 = values[3] - gg = values[4] - gf = values[6:] - for k, gf_i in enumerate(gf): - records[k].append([l, j, d, amun, gn0, gg, gf]) - parameters = [pd.DataFrame(r, columns=columns) for r in records] - - elif formalism == 2: - # Case C -- all parameters are energy-dependent - NLS = items[4] - columns = ['L', 'J', 'E', 'd', 'gx', 'gn0', 'gg', 'gf'] - records = [] - for ls in range(NLS): - items = get_cont_record(file_obj) - l = items[2] - NJS = items[4] - for j in range(NJS): - items, values = get_list_record(file_obj) - ne = items[5] - j = items[0] - amux = values[2] - amun = values[3] - amug = values[4] - amuf = values[5] - for k in range(1, ne + 1): - E = values[6*k] - d = values[6*k + 1] - gx = values[6*k + 2] - gn0 = values[6*k + 3] - gg = values[6*k + 4] - gf = values[6*k + 5] - records.append([l, j, E, d, gx, gn0, gg, gf]) - parameters = pd.DataFrame.from_records(records, columns=columns) - energies = None - - urr = cls(target_spin, energy_min, energy_max, scattering_radius) - urr.parameters = parameters - urr.add_to_background = add_to_background - urr.energies = energies - - return urr - - -_FORMALISMS = {0: ResonanceRange, - 1: SingleLevelBreitWigner, - 2: MultiLevelBreitWigner, - 3: ReichMoore, - 7: RMatrixLimited} - -_RESOLVED = (SingleLevelBreitWigner, MultiLevelBreitWigner, - ReichMoore, RMatrixLimited) diff --git a/openmc/data/resonance_covariance.py b/openmc/data/resonance_covariance.py deleted file mode 100644 index 9e80e52f2..000000000 --- a/openmc/data/resonance_covariance.py +++ /dev/null @@ -1,708 +0,0 @@ -from collections.abc import MutableSequence -import warnings -import io -import copy - -import numpy as np -import pandas as pd - -from . import endf -import openmc.checkvalue as cv -from .resonance import Resonances - - -def _add_file2_contributions(file32params, file2params): - """Function for aiding in adding resonance parameters from File 2 that are - not always present in File 32. Uses already imported resonance data. - - Paramaters - ---------- - file32params : pandas.Dataframe - Incomplete set of resonance parameters contained in File 32. - file2params : pandas.Dataframe - Resonance parameters from File 2. Ordered by energy. - - Returns - ------- - parameters : pandas.Dataframe - Complete set of parameters ordered by L-values and then energy - - """ - # Use l-values and competitiveWidth from File 2 data - # Re-sort File 2 by energy to match File 32 - file2params = file2params.sort_values(by=['energy']) - file2params.reset_index(drop=True, inplace=True) - # Sort File 32 parameters by energy as well (maintaining index) - file32params.sort_values(by=['energy'], inplace=True) - # Add in values (.values converts to array first to ignore index) - file32params['L'] = file2params['L'].values - if 'competitiveWidth' in file2params.columns: - file32params['competitiveWidth'] = file2params['competitiveWidth'].values - # Resort to File 32 order (by L then by E) for use with covariance - file32params.sort_index(inplace=True) - return file32params - - -class ResonanceCovariances(Resonances): - """Resolved resonance covariance data - - Parameters - ---------- - ranges : list of openmc.data.ResonanceCovarianceRange - Distinct energy ranges for resonance data - - Attributes - ---------- - ranges : list of openmc.data.ResonanceCovarianceRange - Distinct energy ranges for resonance data - - """ - - @property - def ranges(self): - return self._ranges - - @ranges.setter - def ranges(self, ranges): - cv.check_type('resonance ranges', ranges, MutableSequence) - self._ranges = cv.CheckedList(ResonanceCovarianceRange, - 'resonance range', ranges) - - @classmethod - def from_endf(cls, ev, resonances): - """Generate resonance covariance data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - resonances : openmc.data.Resonance object - openmc.data.Resonanance object generated from the same evaluation - used to import values not contained in File 32 - - Returns - ------- - openmc.data.ResonanceCovariances - Resonance covariance data - - """ - file_obj = io.StringIO(ev.section[32, 151]) - - # Determine whether discrete or continuous representation - items = endf.get_head_record(file_obj) - n_isotope = items[4] # Number of isotopes - - ranges = [] - for iso in range(n_isotope): - items = endf.get_cont_record(file_obj) - abundance = items[1] - fission_widths = (items[3] == 1) # Flag for fission widths - n_ranges = items[4] # Number of resonance energy ranges - - for j in range(n_ranges): - items = endf.get_cont_record(file_obj) - # Unresolved flags - 0: only scattering radius given - # 1: resolved parameters given - # 2: unresolved parameters given - unresolved_flag = items[2] - formalism = items[3] # resonance formalism - - # Throw error for unsupported formalisms - if formalism in [0, 7]: - error = 'LRF='+str(formalism)+' covariance not supported '\ - 'for this formalism' - raise NotImplementedError(error) - - if unresolved_flag in (0, 1): - # Resolved resonance region - resonance = resonances.ranges[j] - erange = _FORMALISMS[formalism].from_endf(ev, file_obj, - items, resonance) - ranges.append(erange) - - elif unresolved_flag == 2: - warn = 'Unresolved resonance not supported. Covariance '\ - 'values for the unresolved region not imported.' - warnings.warn(warn) - - return cls(ranges) - - -class ResonanceCovarianceRange: - """Resonace covariance range. Base class for different formalisms. - - Parameters - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - - Attributes - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Resonance parameters - covariance : numpy.array - The covariance matrix contained within the ENDF evaluation - lcomp : int - Flag indicating format of the covariance matrix within the ENDF file - file2res : openmc.data.ResonanceRange object - Corresponding resonance range with File 2 data. - mpar : int - Number of parameters in covariance matrix for each individual resonance - formalism : str - String descriptor of formalism - """ - def __init__(self, energy_min, energy_max): - self.energy_min = energy_min - self.energy_max = energy_max - - def subset(self, parameter_str, bounds): - """Produce a subset of resonance parameters and the corresponding - covariance matrix to an IncidentNeutron object. - - Parameters - ---------- - parameter_str : str - parameter to be discriminated - (i.e. 'energy', 'captureWidth', 'fissionWidthA'...) - bounds : np.array - [low numerical bound, high numerical bound] - - Returns - ------- - res_cov_range : openmc.data.ResonanceCovarianceRange - ResonanceCovarianceRange object that contains a subset of the - covariance matrix (upper triangular) as well as a subset parameters - within self.file2params - - """ - # Copy range and prevent change of original - res_cov_range = copy.deepcopy(self) - - parameters = self.file2res.parameters - cov = res_cov_range.covariance - mpar = res_cov_range.mpar - # Create mask - mask1 = parameters[parameter_str] >= bounds[0] - mask2 = parameters[parameter_str] <= bounds[1] - mask = mask1 & mask2 - res_cov_range.parameters = parameters[mask] - indices = res_cov_range.parameters.index.values - # Build subset of covariance - sub_cov_dim = len(indices)*mpar - cov_subset_vals = [] - for index1 in indices: - for i in range(mpar): - for index2 in indices: - for j in range(mpar): - if index2*mpar+j >= index1*mpar+i: - cov_subset_vals.append(cov[index1*mpar+i, - index2*mpar+j]) - - cov_subset = np.zeros([sub_cov_dim, sub_cov_dim]) - tri_indices = np.triu_indices(sub_cov_dim) - cov_subset[tri_indices] = cov_subset_vals - - res_cov_range.file2res.parameters = parameters[mask] - res_cov_range.covariance = cov_subset - return res_cov_range - - def sample(self, n_samples): - """Sample resonance parameters based on the covariances provided - within an ENDF evaluation. - - Parameters - ---------- - n_samples : int - The number of samples to produce - - Returns - ------- - samples : list of openmc.data.ResonanceCovarianceRange objects - List of samples size `n_samples` - - """ - warn_str = 'Sampling routine does not guarantee positive values for '\ - 'parameters. This can lead to undefined behavior in the '\ - 'reconstruction routine.' - warnings.warn(warn_str) - parameters = self.parameters - cov = self.covariance - - # Symmetrizing covariance matrix - cov = cov + cov.T - np.diag(cov.diagonal()) - formalism = self.formalism - mpar = self.mpar - samples = [] - - # Handling MLBW/SLBW sampling - if formalism == 'mlbw' or formalism == 'slbw': - params = ['energy', 'neutronWidth', 'captureWidth', 'fissionWidth', - 'competitiveWidth'] - param_list = params[:mpar] - mean_array = parameters[param_list].values - mean = mean_array.flatten() - par_samples = np.random.multivariate_normal(mean, cov, - size=n_samples) - spin = parameters['J'].values - l_value = parameters['L'].values - for sample in par_samples: - energy = sample[0::mpar] - gn = sample[1::mpar] - gg = sample[2::mpar] - gf = sample[3::mpar] if mpar > 3 else parameters['fissionWidth'].values - gx = sample[4::mpar] if mpar > 4 else parameters['competitiveWidth'].values - gt = gn + gg + gf + gx - - records = [] - for j, E in enumerate(energy): - records.append([energy[j], l_value[j], spin[j], gt[j], - gn[j], gg[j], gf[j], gx[j]]) - columns = ['energy', 'L', 'J', 'totalWidth', 'neutronWidth', - 'captureWidth', 'fissionWidth', 'competitiveWidth'] - sample_params = pd.DataFrame.from_records(records, - columns=columns) - # Copy ResonanceRange object - res_range = copy.copy(self.file2res) - res_range.parameters = sample_params - samples.append(res_range) - - # Handling RM sampling - elif formalism == 'rm': - params = ['energy', 'neutronWidth', 'captureWidth', - 'fissionWidthA', 'fissionWidthB'] - param_list = params[:mpar] - mean_array = parameters[param_list].values - mean = mean_array.flatten() - par_samples = np.random.multivariate_normal(mean, cov, - size=n_samples) - spin = parameters['J'].values - l_value = parameters['L'].values - for sample in par_samples: - energy = sample[0::mpar] - gn = sample[1::mpar] - gg = sample[2::mpar] - gfa = sample[3::mpar] if mpar > 3 else parameters['fissionWidthA'].values - gfb = sample[4::mpar] if mpar > 3 else parameters['fissionWidthB'].values - - records = [] - for j, E in enumerate(energy): - records.append([energy[j], l_value[j], spin[j], gn[j], - gg[j], gfa[j], gfb[j]]) - columns = ['energy', 'L', 'J', 'neutronWidth', - 'captureWidth', 'fissionWidthA', 'fissionWidthB'] - sample_params = pd.DataFrame.from_records(records, - columns=columns) - # Copy ResonanceRange object - res_range = copy.copy(self.file2res) - res_range.parameters = sample_params - samples.append(res_range) - - return samples - - -class MultiLevelBreitWignerCovariance(ResonanceCovarianceRange): - """Multi-level Breit-Wigner resolved resonance formalism covariance data. - Parameters - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - - Attributes - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Resonance parameters - covariance : numpy.array - The covariance matrix contained within the ENDF evaluation - mpar : int - Number of parameters in covariance matrix for each individual resonance - lcomp : int - Flag indicating format of the covariance matrix within the ENDF file - file2res : openmc.data.ResonanceRange object - Corresponding resonance range with File 2 data. - formalism : str - String descriptor of formalism - - """ - - def __init__(self, energy_min, energy_max, parameters, covariance, mpar, - lcomp, file2res): - super().__init__(energy_min, energy_max) - self.parameters = parameters - self.covariance = covariance - self.mpar = mpar - self.lcomp = lcomp - self.file2res = copy.copy(file2res) - self.formalism = 'mlbw' - - @classmethod - def from_endf(cls, ev, file_obj, items, resonance): - """Create MLBW covariance data from an ENDF evaluation. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=32, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - resonance : openmc.data.ResonanceRange object - Corresponding resonance range with File 2 data. - - Returns - ------- - openmc.data.MultiLevelBreitWignerCovariance - Multi-level Breit-Wigner resonance covariance parameters - - """ - - # Read energy-dependent scattering radius if present - energy_min, energy_max = items[0:2] - nro, naps = items[4:6] - if nro != 0: - params, ape = endf.get_tab1_record(file_obj) - - # Other scatter radius parameters - items = endf.get_cont_record(file_obj) - target_spin = items[0] - lcomp = items[3] # Flag for compatibility 0, 1, 2 - 2 is compact form - nls = items[4] # number of l-values - - # Build covariance matrix for General Resolved Resonance Formats - if lcomp == 1: - items = endf.get_cont_record(file_obj) - # Number of short range type resonance covariances - num_short_range = items[4] - # Number of long range type resonance covariances - num_long_range = items[5] - - # Read resonance widths, J values, etc - records = [] - for i in range(num_short_range): - items, values = endf.get_list_record(file_obj) - mpar = items[2] - num_res = items[5] - num_par_vals = num_res*6 - res_values = values[:num_par_vals] - cov_values = values[num_par_vals:] - - energy = res_values[0::6] - spin = res_values[1::6] - gt = res_values[2::6] - gn = res_values[3::6] - gg = res_values[4::6] - gf = res_values[5::6] - - for i, E in enumerate(energy): - records.append([energy[i], spin[i], gt[i], gn[i], - gg[i], gf[i]]) - - # Build the upper-triangular covariance matrix - cov_dim = mpar*num_res - cov = np.zeros([cov_dim, cov_dim]) - indices = np.triu_indices(cov_dim) - cov[indices] = cov_values - - # Compact format - Resonances and individual uncertainties followed by - # compact correlations - elif lcomp == 2: - items, values = endf.get_list_record(file_obj) - mean = items - num_res = items[5] - energy = values[0::12] - spin = values[1::12] - gt = values[2::12] - gn = values[3::12] - gg = values[4::12] - gf = values[5::12] - par_unc = [] - for i in range(num_res): - res_unc = values[i*12+6 : i*12+12] - # Delete 0 values (not provided, no fission width) - # DAJ/DGT always zero, DGF sometimes nonzero [1, 2, 5] - res_unc_nonzero = [] - for j in range(6): - if j in [1, 2, 5] and res_unc[j] != 0.0: - res_unc_nonzero.append(res_unc[j]) - elif j in [0, 3, 4]: - res_unc_nonzero.append(res_unc[j]) - par_unc.extend(res_unc_nonzero) - - records = [] - for i, E in enumerate(energy): - records.append([energy[i], spin[i], gt[i], gn[i], - gg[i], gf[i]]) - - corr = endf.get_intg_record(file_obj) - cov = np.diag(par_unc).dot(corr).dot(np.diag(par_unc)) - - # Compatible resolved resonance format - elif lcomp == 0: - cov = np.zeros([4, 4]) - records = [] - cov_index = 0 - for i in range(nls): - items, values = endf.get_list_record(file_obj) - num_res = items[5] - for j in range(num_res): - one_res = values[18*j:18*(j+1)] - res_values = one_res[:6] - cov_values = one_res[6:] - records.append(list(res_values)) - - # Populate the coviariance matrix for this resonance - # There are no covariances between resonances in lcomp=0 - cov[cov_index, cov_index] = cov_values[0] - cov[cov_index+1, cov_index+1 : cov_index+2] = cov_values[1:2] - cov[cov_index+1, cov_index+3] = cov_values[4] - cov[cov_index+2, cov_index+2] = cov_values[3] - cov[cov_index+2, cov_index+3] = cov_values[5] - cov[cov_index+3, cov_index+3] = cov_values[6] - - cov_index += 4 - if j < num_res-1: # Pad matrix for additional values - cov = np.pad(cov, ((0, 4), (0, 4)), 'constant', - constant_values=0) - - # Create pandas DataFrame with resonance data, currently - # redundant with data.IncidentNeutron.resonance - columns = ['energy', 'J', 'totalWidth', 'neutronWidth', - 'captureWidth', 'fissionWidth'] - parameters = pd.DataFrame.from_records(records, columns=columns) - # Determine mpar (number of parameters for each resonance in - # covariance matrix) - nparams, params = parameters.shape - covsize = cov.shape[0] - mpar = int(covsize/nparams) - # Add parameters from File 2 - parameters = _add_file2_contributions(parameters, - resonance.parameters) - # Create instance of class - mlbw = cls(energy_min, energy_max, parameters, cov, mpar, lcomp, - resonance) - return mlbw - - -class SingleLevelBreitWignerCovariance(MultiLevelBreitWignerCovariance): - """Single-level Breit-Wigner resolved resonance formalism covariance data. - Single-level Breit-Wigner resolved resonance data is is identified by LRF=1 - in the ENDF-6 format. - - Parameters - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - - Attributes - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Resonance parameters - covariance : numpy.array - The covariance matrix contained within the ENDF evaluation - mpar : int - Number of parameters in covariance matrix for each individual resonance - formalism : str - String descriptor of formalism - lcomp : int - Flag indicating format of the covariance matrix within the ENDF file - file2res : openmc.data.ResonanceRange object - Corresponding resonance range with File 2 data. - """ - - def __init__(self, energy_min, energy_max, parameters, covariance, mpar, - lcomp, file2res): - super().__init__(energy_min, energy_max, parameters, covariance, mpar, - lcomp, file2res) - self.formalism = 'slbw' - - -class ReichMooreCovariance(ResonanceCovarianceRange): - """Reich-Moore resolved resonance formalism covariance data. - - Reich-Moore resolved resonance data is identified by LRF=3 in the ENDF-6 - format. - - Parameters - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - - Attributes - ---------- - energy_min : float - Minimum energy of the resolved resonance range in eV - energy_max : float - Maximum energy of the resolved resonance range in eV - parameters : pandas.DataFrame - Resonance parameters - covariance : numpy.array - The covariance matrix contained within the ENDF evaluation - lcomp : int - Flag indicating format of the covariance matrix within the ENDF file - mpar : int - Number of parameters in covariance matrix for each individual resonance - file2res : openmc.data.ResonanceRange object - Corresponding resonance range with File 2 data. - formalism : str - String descriptor of formalism - """ - - def __init__(self, energy_min, energy_max, parameters, covariance, mpar, - lcomp, file2res): - super().__init__(energy_min, energy_max) - self.parameters = parameters - self.covariance = covariance - self.mpar = mpar - self.lcomp = lcomp - self.file2res = copy.copy(file2res) - self.formalism = 'rm' - - @classmethod - def from_endf(cls, ev, file_obj, items, resonance): - """Create Reich-Moore resonance covariance data from an ENDF - evaluation. Includes the resonance parameters contained separately in - File 32. - - Parameters - ---------- - ev : openmc.data.endf.Evaluation - ENDF evaluation - file_obj : file-like object - ENDF file positioned at the second record of a resonance range - subsection in MF=2, MT=151 - items : list - Items from the CONT record at the start of the resonance range - subsection - resonance : openmc.data.Resonance object - openmc.data.Resonanance object generated from the same evaluation - used to import values not contained in File 32 - - Returns - ------- - openmc.data.ReichMooreCovariance - Reich-Moore resonance covariance parameters - - """ - # Read energy-dependent scattering radius if present - energy_min, energy_max = items[0:2] - nro, naps = items[4:6] - if nro != 0: - params, ape = endf.get_tab1_record(file_obj) - - # Other scatter radius parameters - items = endf.get_cont_record(file_obj) - target_spin = items[0] - lcomp = items[3] # Flag for compatibility 0, 1, 2 - 2 is compact form - nls = items[4] # Number of l-values - - # Build covariance matrix for General Resolved Resonance Formats - if lcomp == 1: - items = endf.get_cont_record(file_obj) - # Number of short range type resonance covariances - num_short_range = items[4] - # Number of long range type resonance covariances - num_long_range = items[5] - # Read resonance widths, J values, etc - channel_radius = {} - scattering_radius = {} - records = [] - for i in range(num_short_range): - items, values = endf.get_list_record(file_obj) - mpar = items[2] - num_res = items[5] - num_par_vals = num_res*6 - res_values = values[:num_par_vals] - cov_values = values[num_par_vals:] - - energy = res_values[0::6] - spin = res_values[1::6] - gn = res_values[2::6] - gg = res_values[3::6] - gfa = res_values[4::6] - gfb = res_values[5::6] - - for i, E in enumerate(energy): - records.append([energy[i], spin[i], gn[i], gg[i], - gfa[i], gfb[i]]) - - # Build the upper-triangular covariance matrix - cov_dim = mpar*num_res - cov = np.zeros([cov_dim, cov_dim]) - indices = np.triu_indices(cov_dim) - cov[indices] = cov_values - - # Compact format - Resonances and individual uncertainties followed by - # compact correlations - elif lcomp == 2: - items, values = endf.get_list_record(file_obj) - num_res = items[5] - energy = values[0::12] - spin = values[1::12] - gn = values[2::12] - gg = values[3::12] - gfa = values[4::12] - gfb = values[5::12] - par_unc = [] - for i in range(num_res): - res_unc = values[i*12+6 : i*12+12] - # Delete 0 values (not provided in evaluation) - res_unc = [x for x in res_unc if x != 0.0] - par_unc.extend(res_unc) - - records = [] - for i, E in enumerate(energy): - records.append([energy[i], spin[i], gn[i], gg[i], - gfa[i], gfb[i]]) - - corr = endf.get_intg_record(file_obj) - cov = np.diag(par_unc).dot(corr).dot(np.diag(par_unc)) - - # Create pandas DataFrame with resonacne data - columns = ['energy', 'J', 'neutronWidth', 'captureWidth', - 'fissionWidthA', 'fissionWidthB'] - parameters = pd.DataFrame.from_records(records, columns=columns) - - # Determine mpar (number of parameters for each resonance in - # covariance matrix) - nparams, params = parameters.shape - covsize = cov.shape[0] - mpar = int(covsize/nparams) - - # Add parameters from File 2 - parameters = _add_file2_contributions(parameters, - resonance.parameters) - # Create instance of ReichMooreCovariance - rmc = cls(energy_min, energy_max, parameters, cov, mpar, lcomp, - resonance) - return rmc - - -_FORMALISMS = { - 0: ResonanceCovarianceRange, - 1: SingleLevelBreitWignerCovariance, - 2: MultiLevelBreitWignerCovariance, - 3: ReichMooreCovariance - # 7: RMatrixLimitedCovariance -} diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py deleted file mode 100644 index 067c0a703..000000000 --- a/openmc/data/thermal.py +++ /dev/null @@ -1,927 +0,0 @@ -from collections.abc import Iterable -from collections import namedtuple -from difflib import get_close_matches -from numbers import Real -from io import StringIO -import itertools -import os -import re -import tempfile -from warnings import warn - -import numpy as np -import h5py - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from openmc.stats import Discrete, Tabular -from . import HDF5_VERSION, HDF5_VERSION_MAJOR, endf -from .data import K_BOLTZMANN, ATOMIC_SYMBOL, EV_PER_MEV, NATURAL_ABUNDANCE -from .ace import Table, get_table, Library -from .angle_energy import AngleEnergy -from .function import Tabulated1D, Function1D -from .njoy import make_ace_thermal -from .thermal_angle_energy import (CoherentElasticAE, IncoherentElasticAE, - IncoherentElasticAEDiscrete, - IncoherentInelasticAEDiscrete, - IncoherentInelasticAE) - - -_THERMAL_NAMES = { - 'c_Al27': ('al', 'al27', 'al-27'), - 'c_Al_in_Sapphire': ('asap00',), - 'c_Be': ('be', 'be-metal', 'be-met', 'be00'), - 'c_BeO': ('beo',), - 'c_Be_in_BeO': ('bebeo', 'be-beo', 'be-o', 'be/o', 'bbeo00'), - 'c_Be_in_Be2C': ('bebe2c',), - 'c_C6H6': ('benz', 'c6h6'), - 'c_C_in_SiC': ('csic', 'c-sic'), - 'c_Ca_in_CaH2': ('cah', 'cah00'), - 'c_D_in_D2O': ('dd2o', 'd-d2o', 'hwtr', 'hw', 'dhw00'), - 'c_D_in_D2O_ice': ('dice',), - 'c_Fe56': ('fe', 'fe56', 'fe-56'), - 'c_Graphite': ('graph', 'grph', 'gr', 'gr00'), - 'c_Graphite_10p': ('grph10',), - 'c_Graphite_30p': ('grph30',), - 'c_H_in_CaH2': ('hcah2', 'hca00'), - 'c_H_in_CH2': ('hch2', 'poly', 'pol', 'h-poly', 'pol00'), - 'c_H_in_CH4_liquid': ('lch4', 'lmeth'), - 'c_H_in_CH4_solid': ('sch4', 'smeth'), - 'c_H_in_CH4_solid_phase_II': ('sch4p2',), - 'c_H_in_H2O': ('hh2o', 'h-h2o', 'lwtr', 'lw', 'lw00'), - 'c_H_in_H2O_solid': ('hice', 'h-ice', 'ice00'), - 'c_H_in_C5O2H8': ('lucite', 'c5o2h8', 'h-luci'), - 'c_H_in_Mesitylene': ('mesi00',), - 'c_H_in_Toluene': ('tol00',), - 'c_H_in_YH2': ('hyh2', 'h-yh2'), - 'c_H_in_ZrH': ('hzrh', 'h-zrh', 'h-zr', 'h/zr', 'hzr', 'hzr00'), - 'c_Mg24': ('mg', 'mg24', 'mg00'), - 'c_O_in_Sapphire': ('osap00',), - 'c_O_in_BeO': ('obeo', 'o-beo', 'o-be', 'o/be', 'obeo00'), - 'c_O_in_D2O': ('od2o', 'o-d2o', 'ohw00'), - 'c_O_in_H2O_ice': ('oice', 'o-ice'), - 'c_O_in_UO2': ('ouo2', 'o-uo2', 'o2-u', 'o2/u', 'ouo200'), - 'c_N_in_UN': ('n-un',), - 'c_ortho_D': ('orthod', 'orthoD', 'dortho', 'od200'), - 'c_ortho_H': ('orthoh', 'orthoH', 'hortho', 'oh200'), - 'c_Si28': ('si00',), - 'c_Si_in_SiC': ('sisic', 'si-sic'), - 'c_SiO2_alpha': ('sio2', 'sio2a'), - 'c_SiO2_beta': ('sio2b',), - 'c_para_D': ('parad', 'paraD', 'dpara', 'pd200'), - 'c_para_H': ('parah', 'paraH', 'hpara', 'ph200'), - 'c_U_in_UN': ('u-un',), - 'c_U_in_UO2': ('uuo2', 'u-uo2', 'u-o2', 'u/o2', 'uuo200'), - 'c_Y_in_YH2': ('yyh2', 'y-yh2'), - 'c_Zr_in_ZrH': ('zrzrh', 'zr-zrh', 'zr-h', 'zr/h') -} - - -def _temperature_str(T): - # round() normally returns an int when called with a single argument, but - # numpy floats overload rounding to return another float - return "{}K".format(int(round(T))) - - -def get_thermal_name(name): - """Get proper S(a,b) table name, e.g. 'HH2O' -> 'c_H_in_H2O' - - Parameters - ---------- - name : str - Name of an ACE thermal scattering table - - Returns - ------- - str - GND-format thermal scattering name - - """ - if name in _THERMAL_NAMES: - return name - else: - for proper_name, names in _THERMAL_NAMES.items(): - if name.lower() in names: - return proper_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 - - # 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 matches: - # 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. ' - 'Assigning a name of c_{0}.'.format(name)) - return 'c_' + name - - -class CoherentElastic(Function1D): - r"""Coherent elastic scattering data from a crystalline material - - The integrated cross section for coherent elastic scattering from a - powdered crystalline material may be represented as: - - .. math:: - \sigma(E,T) = \frac{1}{E} \sum\limits_{i=1}^{E_i < E} s_i(T) - - where :math:`s_i(T)` is proportional the structure factor in [eV-b] at - the moderator temperature :math:`T` in Kelvin. - - Parameters - ---------- - bragg_edges : Iterable of float - Bragg edge energies in eV - factors : Iterable of float - Partial sum of structure factors, :math:`\sum\limits_{i=1}^{E_i= 0 - xs = np.zeros_like(E) - xs[nonzero] = self.factors[idx[nonzero]] / E[nonzero] - return xs - else: - return self.factors[idx] / E if idx >= 0 else 0.0 - - def __len__(self): - return len(self.bragg_edges) - - @property - def bragg_edges(self): - return self._bragg_edges - - @property - def factors(self): - return self._factors - - @bragg_edges.setter - def bragg_edges(self, bragg_edges): - cv.check_type('Bragg edges', bragg_edges, Iterable, Real) - self._bragg_edges = np.asarray(bragg_edges) - - @factors.setter - def factors(self, factors): - cv.check_type('structure factor cumulative sums', factors, - Iterable, Real) - self._factors = np.asarray(factors) - - def to_hdf5(self, group, name): - """Write coherent elastic scattering to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : str - Name of the dataset to create - - """ - dataset = group.create_dataset(name, data=np.vstack( - [self.bragg_edges, self.factors])) - dataset.attrs['type'] = np.string_(type(self).__name__) - - @classmethod - def from_hdf5(cls, dataset): - """Read coherent elastic scattering from an HDF5 dataset - - Parameters - ---------- - dataset : h5py.Dataset - HDF5 dataset to read from - - Returns - ------- - openmc.data.CoherentElastic - Coherent elastic scattering cross section - - """ - bragg_edges = dataset[0, :] - factors = dataset[1, :] - return cls(bragg_edges, factors) - - -class IncoherentElastic(Function1D): - r"""Incoherent elastic scattering cross section - - Elastic scattering can be treated in the incoherent approximation for - partially ordered systems such as ZrHx and polyethylene. The integrated - cross section can be obtained as: - - .. math:: - \sigma(E,T) = \frac{\sigma_b}{2} \left ( \frac{1 - e^{-4EW'(T)}} - {2EW'(T)} \right ) - - where :math:`\sigma_b` is the characteristic bound cross section, and - :math:`W'(T)` is the Debye-Waller integral divided by the atomic mass - in [eV\ :math:`^{-1}`]. - - Parameters - ---------- - bound_xs : float - Characteristic bound cross section in [b] - debye_waller : float - Debye-Waller integral in [eV\ :math:`^{-1}`] - - Attributes - ---------- - bound_xs : float - Characteristic bound cross section in [b] - debye_waller : float - Debye-Waller integral in [eV\ :math:`^{-1}`] - - """ - def __init__(self, bound_xs, debye_waller): - self.bound_xs = bound_xs - self.debye_waller = debye_waller - - def __call__(self, E): - W = self.debye_waller - return self.bound_xs / 2.0 * (1 - np.exp(-4*E*W)) / (2*E*W) - - def to_hdf5(self, group, name): - """Write incoherent elastic scattering to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : str - Name of the dataset to create - - """ - data = np.array([self.bound_xs, self.debye_waller]) - dataset = group.create_dataset(name, data=data) - dataset.attrs['type'] = np.string_(type(self).__name__) - - @classmethod - def from_hdf5(cls, dataset): - """Read incoherent elastic scattering from an HDF5 dataset - - Parameters - ---------- - dataset : h5py.Dataset - HDF5 dataset to read from - - Returns - ------- - openmc.data.IncoherentElastic - Incoherent elastic scattering cross section - - """ - bound_xs, debye_waller = dataset[()] - return cls(bound_xs, debye_waller) - - -class ThermalScatteringReaction(EqualityMixin): - r"""Thermal scattering reaction - - This class is used to hold the integral and differential cross sections - for either elastic or inelastic thermal scattering. - - Parameters - ---------- - xs : dict of str to Function1D - Integral cross section at each temperature - distribution : dict of str to AngleEnergy - Secondary angle-energy distribution at each temperature - - Attributes - ---------- - xs : dict of str to Function1D - Integral cross section at each temperature - distribution : dict of str to AngleEnergy - Secondary angle-energy distribution at each temperature - - """ - def __init__(self, xs, distribution): - self.xs = xs - self.distribution = distribution - - def to_hdf5(self, group, name): - """Write thermal scattering reaction to HDF5 - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - name : {'elastic', 'inelastic'} - Name of reaction to write - - """ - for T, xs in self.xs.items(): - Tgroup = group.require_group(T) - rx_group = Tgroup.create_group(name) - xs.to_hdf5(rx_group, 'xs') - dgroup = rx_group.create_group('distribution') - self.distribution[T].to_hdf5(dgroup) - - @classmethod - def from_hdf5(cls, group, name, temperatures): - """Generate thermal scattering reaction data from HDF5 - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - name : {'elastic', 'inelastic'} - Name of the reaction to read - temperatures : Iterable of str - Temperatures to read - - Returns - ------- - openmc.data.ThermalScatteringReaction - Thermal scattering reaction data - - """ - xs = {} - distribution = {} - for T in temperatures: - rx_group = group[T][name] - xs[T] = Function1D.from_hdf5(rx_group['xs']) - if isinstance(xs[T], CoherentElastic): - distribution[T] = CoherentElasticAE(xs[T]) - else: - distribution[T] = AngleEnergy.from_hdf5(rx_group['distribution']) - return cls(xs, distribution) - - -class ThermalScattering(EqualityMixin): - """A ThermalScattering object contains thermal scattering data as represented by - an S(alpha, beta) table. - - Parameters - ---------- - name : str - Name of the material using GND convention, e.g. c_H_in_H2O - atomic_weight_ratio : float - Atomic mass ratio of the target nuclide. - kTs : Iterable of float - List of temperatures of the target nuclide in the data set. - The temperatures have units of eV. - - Attributes - ---------- - atomic_weight_ratio : float - Atomic mass ratio of the target nuclide. - energy_max : float - Maximum energy for thermal scattering data in [eV] - elastic : openmc.data.ThermalScatteringReaction or None - Elastic scattering derived in the coherent or incoherent approximation - inelastic : openmc.data.ThermalScatteringReaction - Inelastic scattering cross section derived in the incoherent - approximation - name : str - Name of the material using GND convention, e.g. c_H_in_H2O - temperatures : Iterable of str - List of string representations the temperatures of the target nuclide - in the data set. The temperatures are strings of the temperature, - rounded to the nearest integer; e.g., '294K' - kTs : Iterable of float - List of temperatures of the target nuclide in the data set. - The temperatures have units of eV. - nuclides : Iterable of str - Nuclide names that the thermal scattering data applies to - - """ - - def __init__(self, name, atomic_weight_ratio, energy_max, kTs): - self.name = name - self.atomic_weight_ratio = atomic_weight_ratio - self.energy_max = energy_max - self.kTs = kTs - self.elastic = None - self.inelastic = None - self.nuclides = [] - - def __repr__(self): - if hasattr(self, 'name'): - return "".format(self.name) - else: - return "" - - @property - def temperatures(self): - return [_temperature_str(kT / K_BOLTZMANN) for kT in self.kTs] - - def export_to_hdf5(self, path, mode='a', libver='earliest'): - """Export table to an HDF5 file. - - Parameters - ---------- - path : str - Path to write HDF5 file to - 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 - with h5py.File(str(path), mode, libver=libver) as f: - f.attrs['filetype'] = np.string_('data_thermal') - f.attrs['version'] = np.array(HDF5_VERSION) - - # Write basic data - g = f.create_group(self.name) - g.attrs['atomic_weight_ratio'] = self.atomic_weight_ratio - g.attrs['energy_max'] = self.energy_max - g.attrs['nuclides'] = np.array(self.nuclides, dtype='S') - ktg = g.create_group('kTs') - for i, temperature in enumerate(self.temperatures): - ktg.create_dataset(temperature, data=self.kTs[i]) - - # Write elastic/inelastic reaction data - if self.elastic is not None: - self.elastic.to_hdf5(g, 'elastic') - self.inelastic.to_hdf5(g, 'inelastic') - - def add_temperature_from_ace(self, ace_or_filename, name=None): - """Add data to the ThermalScattering object from an ACE file at a - different temperature. - - Parameters - ---------- - ace_or_filename : openmc.data.ace.Table or str - ACE table to read from. If given as a string, it is assumed to be - the filename for the ACE file. - name : str - GND-conforming name of the material, e.g. c_H_in_H2O. If none is - passed, the appropriate name is guessed based on the name of the ACE - table. - - Returns - ------- - openmc.data.ThermalScattering - Thermal scattering data - - """ - data = ThermalScattering.from_ace(ace_or_filename, name) - - # Check if temprature already exists - strT = data.temperatures[0] - if strT in self.temperatures: - warn('S(a,b) data at T={} already exists.'.format(strT)) - return - - # Check that name matches - if data.name != self.name: - raise ValueError('Data provided for an incorrect material.') - - # Add temperature - self.kTs += data.kTs - - # Add inelastic cross section and distributions - if data.inelastic is not None: - self.inelastic.xs.update(data.inelastic.xs) - self.inelastic.distribution.update(data.inelastic.distribution) - - # Add elastic cross sectoin and angular distribution - if data.elastic is not None: - self.elastic.xs.update(data.elastic.xs) - self.elastic.distribution.update(data.elastic.distribution) - - @classmethod - def from_hdf5(cls, group_or_filename): - """Generate thermal scattering data from HDF5 group - - Parameters - ---------- - group_or_filename : h5py.Group or str - HDF5 group containing interaction data. If given as a string, it is - assumed to be the filename for the HDF5 file, and the first group - is used to read from. - - Returns - ------- - openmc.data.ThermalScattering - Neutron thermal scattering data - - """ - if isinstance(group_or_filename, h5py.Group): - group = group_or_filename - else: - h5file = h5py.File(str(group_or_filename), 'r') - - # Make sure version matches - if 'version' in h5file.attrs: - major, minor = h5file.attrs['version'] - if major != HDF5_VERSION_MAJOR: - raise IOError( - 'HDF5 data format uses version {}.{} whereas your ' - 'installation of the OpenMC Python API expects version ' - '{}.x.'.format(major, minor, HDF5_VERSION_MAJOR)) - else: - raise IOError( - 'HDF5 data does not indicate a version. Your installation of ' - 'the OpenMC Python API expects version {}.x data.' - .format(HDF5_VERSION_MAJOR)) - - group = list(h5file.values())[0] - - name = group.name[1:] - atomic_weight_ratio = group.attrs['atomic_weight_ratio'] - energy_max = group.attrs['energy_max'] - kTg = group['kTs'] - kTs = [dataset[()] for dataset in kTg.values()] - - table = cls(name, atomic_weight_ratio, energy_max, kTs) - table.nuclides = [nuc.decode() for nuc in group.attrs['nuclides']] - - # Read thermal elastic scattering - if 'elastic' in group[table.temperatures[0]]: - table.elastic = ThermalScatteringReaction.from_hdf5( - group, 'elastic', table.temperatures - ) - - # Read thermal inelastic scattering - table.inelastic = ThermalScatteringReaction.from_hdf5( - group, 'inelastic', table.temperatures - ) - - return table - - @classmethod - def from_ace(cls, ace_or_filename, name=None): - """Generate thermal scattering data from an ACE table - - Parameters - ---------- - ace_or_filename : openmc.data.ace.Table or str - ACE table to read from. If given as a string, it is assumed to be - the filename for the ACE file. - name : str - GND-conforming name of the material, e.g. c_H_in_H2O. If none is - passed, the appropriate name is guessed based on the name of the ACE - table. - - Returns - ------- - openmc.data.ThermalScattering - Thermal scattering data - - """ - if isinstance(ace_or_filename, Table): - ace = ace_or_filename - else: - ace = get_table(ace_or_filename) - - # Get new name that is GND-consistent - ace_name, xs = ace.name.split('.') - if not xs.endswith('t'): - raise TypeError("{} is not a thermal scattering ACE table.".format(ace)) - name = get_thermal_name(ace_name) - - # Assign temperature to the running list - kTs = [ace.temperature*EV_PER_MEV] - - # Incoherent inelastic scattering cross section - idx = ace.jxs[1] - n_energy = int(ace.xss[idx]) - energy = ace.xss[idx+1 : idx+1+n_energy]*EV_PER_MEV - xs = ace.xss[idx+1+n_energy : idx+1+2*n_energy] - inelastic_xs = Tabulated1D(energy, xs) - energy_max = energy[-1] - - # Incoherent inelastic angle-energy distribution - continuous = (ace.nxs[7] == 2) - n_energy_out = ace.nxs[4] - if not continuous: - n_mu = ace.nxs[3] - idx = ace.jxs[3] - energy_out = ace.xss[idx:idx + n_energy * n_energy_out * - (n_mu + 2): n_mu + 2]*EV_PER_MEV - energy_out.shape = (n_energy, n_energy_out) - - mu_out = ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2)] - mu_out.shape = (n_energy, n_energy_out, n_mu+2) - mu_out = mu_out[:, :, 1:] - skewed = (ace.nxs[7] == 1) - distribution = IncoherentInelasticAEDiscrete(energy_out, mu_out, skewed) - else: - n_mu = ace.nxs[3] - 1 - idx = ace.jxs[3] - locc = ace.xss[idx:idx + n_energy].astype(int) - n_energy_out = \ - ace.xss[idx + n_energy:idx + 2 * n_energy].astype(int) - energy_out = [] - mu_out = [] - for i in range(n_energy): - idx = locc[i] - - # Outgoing energy distribution for incoming energy i - e = ace.xss[idx + 1:idx + 1 + n_energy_out[i]*(n_mu + 3): - n_mu + 3]*EV_PER_MEV - p = ace.xss[idx + 2:idx + 2 + n_energy_out[i]*(n_mu + 3): - n_mu + 3]/EV_PER_MEV - c = ace.xss[idx + 3:idx + 3 + n_energy_out[i]*(n_mu + 3): - n_mu + 3] - eout_i = Tabular(e, p, 'linear-linear', ignore_negative=True) - eout_i.c = c - - # Outgoing angle distribution for each - # (incoming, outgoing) energy pair - mu_i = [] - for j in range(n_energy_out[i]): - mu = ace.xss[idx + 4:idx + 4 + n_mu] - p_mu = 1. / n_mu * np.ones(n_mu) - mu_ij = Discrete(mu, p_mu) - mu_ij.c = np.cumsum(p_mu) - mu_i.append(mu_ij) - idx += 3 + n_mu - - energy_out.append(eout_i) - mu_out.append(mu_i) - - # Create correlated angle-energy distribution - breakpoints = [n_energy] - interpolation = [2] - energy = inelastic_xs.x - distribution = IncoherentInelasticAE( - breakpoints, interpolation, energy, energy_out, mu_out) - - table = cls(name, ace.atomic_weight_ratio, energy_max, kTs) - T = table.temperatures[0] - table.inelastic = ThermalScatteringReaction( - {T: inelastic_xs}, {T: distribution} - ) - - # Incoherent/coherent elastic scattering cross section - idx = ace.jxs[4] - n_mu = ace.nxs[6] + 1 - if idx != 0: - n_energy = int(ace.xss[idx]) - energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV - P = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] - - if ace.nxs[5] == 4: - # Coherent elastic - xs = CoherentElastic(energy, P*EV_PER_MEV) - distribution = CoherentElasticAE(xs) - - # Coherent elastic shouldn't have angular distributions listed - assert n_mu == 0 - else: - # Incoherent elastic - xs = Tabulated1D(energy, P) - - # Angular distribution - assert n_mu > 0 - idx = ace.jxs[6] - mu_out = ace.xss[idx:idx + n_energy * n_mu] - mu_out.shape = (n_energy, n_mu) - distribution = IncoherentElasticAEDiscrete(mu_out) - - table.elastic = ThermalScatteringReaction({T: xs}, {T: distribution}) - - # Get relevant nuclides -- NJOY only allows one to specify three - # nuclides that the S(a,b) table applies to. Thus, for all elements - # other than H and Fe, we automatically add all the naturally-occurring - # isotopes. - for zaid, awr in ace.pairs: - if zaid > 0: - Z, A = divmod(zaid, 1000) - element = ATOMIC_SYMBOL[Z] - if element in ['H', 'Fe']: - table.nuclides.append(element + str(A)) - else: - if element + '0' not in table.nuclides: - table.nuclides.append(element + '0') - for isotope in sorted(NATURAL_ABUNDANCE): - if re.match(r'{}\d+'.format(element), isotope): - if isotope not in table.nuclides: - table.nuclides.append(isotope) - - return table - - @classmethod - def from_njoy(cls, filename, filename_thermal, temperatures=None, - evaluation=None, evaluation_thermal=None, - use_endf_data=True, **kwargs): - """Generate thermal scattering data by running NJOY. - - Parameters - ---------- - filename : str - Path to ENDF neutron sublibrary file - filename_thermal : str - Path to ENDF thermal scattering sublibrary file - temperatures : iterable of float - Temperatures in Kelvin to produce data at. If omitted, data is - produced at all temperatures in the ENDF thermal scattering - sublibrary. - evaluation : openmc.data.endf.Evaluation, optional - If the ENDF neutron sublibrary file contains multiple material - evaluations, this argument indicates which evaluation to use. - evaluation_thermal : openmc.data.endf.Evaluation, optional - If the ENDF thermal scattering sublibrary file contains multiple - material evaluations, this argument indicates which evaluation to - use. - use_endf_data : bool - If the material has incoherent elastic scattering, the ENDF data - will be used rather than the ACE data. - **kwargs - Keyword arguments passed to :func:`openmc.data.njoy.make_ace_thermal` - - Returns - ------- - data : openmc.data.ThermalScattering - Thermal scattering data - - """ - with tempfile.TemporaryDirectory() as tmpdir: - # Run NJOY to create an ACE library - kwargs.setdefault('ace', os.path.join(tmpdir, 'ace')) - kwargs.setdefault('xsdir', os.path.join(tmpdir, 'xsdir')) - kwargs['evaluation'] = evaluation - kwargs['evaluation_thermal'] = evaluation_thermal - make_ace_thermal(filename, filename_thermal, temperatures, **kwargs) - - # Create instance from ACE tables within library - lib = Library(kwargs['ace']) - data = cls.from_ace(lib.tables[0]) - for table in lib.tables[1:]: - data.add_temperature_from_ace(table) - - # Load ENDF data to replace incoherent elastic - if use_endf_data: - data_endf = cls.from_endf(filename_thermal) - if data_endf.elastic is not None: - # Get appropriate temperatures - if temperatures is None: - temperatures = data_endf.temperatures - else: - temperatures = [_temperature_str(t) for t in temperatures] - - # Replace ACE data with ENDF data - rx, rx_endf = data.elastic, data_endf.elastic - for t in temperatures: - if isinstance(rx_endf.xs[t], IncoherentElastic): - rx.xs[t] = rx_endf.xs[t] - rx.distribution[t] = rx_endf.distribution[t] - - return data - - @classmethod - def from_endf(cls, ev_or_filename): - """Generate thermal scattering data from an ENDF file - - Parameters - ---------- - ev_or_filename : openmc.data.endf.Evaluation or str - ENDF evaluation to read from. If given as a string, it is assumed to - be the filename for the ENDF file. - - Returns - ------- - openmc.data.ThermalScattering - Thermal scattering data - - """ - if isinstance(ev_or_filename, endf.Evaluation): - ev = ev_or_filename - else: - ev = endf.Evaluation(ev_or_filename) - - # Read coherent/incoherent elastic data - elastic = None - if (7, 2) in ev.section: - xs = {} - distribution = {} - - file_obj = StringIO(ev.section[7, 2]) - lhtr = endf.get_head_record(file_obj)[2] - if lhtr == 1: - # coherent elastic - - # Get structure factor at first temperature - params, S = endf.get_tab1_record(file_obj) - strT = _temperature_str(params[0]) - n_temps = params[2] - bragg_edges = S.x - xs[strT] = CoherentElastic(bragg_edges, S.y) - distribution = {strT: CoherentElasticAE(xs[strT])} - - # Get structure factor for subsequent temperatures - for _ in range(n_temps): - params, S = endf.get_list_record(file_obj) - strT = _temperature_str(params[0]) - xs[strT] = CoherentElastic(bragg_edges, S) - distribution[strT] = CoherentElasticAE(xs[strT]) - - elif lhtr == 2: - # incoherent elastic - params, W = endf.get_tab1_record(file_obj) - bound_xs = params[0] - for T, debye_waller in zip(W.x, W.y): - strT = _temperature_str(T) - xs[strT] = IncoherentElastic(bound_xs, debye_waller) - distribution[strT] = IncoherentElasticAE(debye_waller) - - elastic = ThermalScatteringReaction(xs, distribution) - - # Read incoherent inelastic data - assert (7, 4) in ev.section, 'No MF=7, MT=4 found in thermal scattering' - file_obj = StringIO(ev.section[7, 4]) - params = endf.get_head_record(file_obj) - data = {'symmetric': params[4] == 0} - - # Get information about principal atom - params, B = endf.get_list_record(file_obj) - data['log'] = bool(params[2]) - data['free_atom_xs'] = B[0] - data['epsilon'] = B[1] - data['A0'] = awr = B[2] - data['e_max'] = energy_max = B[3] - data['M0'] = B[5] - - # Get information about non-principal atoms - n_non_principal = params[5] - data['non_principal'] = [] - NonPrincipal = namedtuple('NonPrincipal', ['func', 'xs', 'A', 'M']) - for i in range(1, n_non_principal + 1): - func = {0.0: 'SCT', 1.0: 'free gas', 2.0: 'diffusive'}[B[6*i]] - xs = B[6*i + 1] - A = B[6*i + 2] - M = B[6*i + 5] - data['non_principal'].append(NonPrincipal(func, xs, A, M)) - - # Get S(alpha,beta,T) - kTs = [] - if data['free_atom_xs'] > 0.0: - params, _ = endf.get_tab2_record(file_obj) - n_beta = params[5] - sab = {'beta': np.empty(n_beta)} - for i in range(n_beta): - params, S = endf.get_tab1_record(file_obj) - T0, beta, lt = params[:3] - if i == 0: - sab['alpha'] = alpha = S.x - sab[T0] = np.empty((alpha.size, n_beta)) - kTs.append(K_BOLTZMANN * T0) - sab['beta'][i] = beta - sab[T0][:, i] = S.y - for _ in range(lt): - params, S = endf.get_list_record(file_obj) - T = params[0] - if i == 0: - sab[T] = np.empty((alpha.size, n_beta)) - kTs.append(K_BOLTZMANN * T) - sab[T][:, i] = S - data['sab'] = sab - - # Get effective temperature for each atom - _, Teff = endf.get_tab1_record(file_obj) - data['effective_temperature'] = [Teff] - for atom in data['non_principal']: - if atom.func == 'SCT': - _, Teff = endf.get_tab1_record(file_obj) - data['effective_temperature'].append(Teff) - - name = ev.target['zsymam'].strip() - instance = cls(name, awr, energy_max, kTs) - if elastic is not None: - instance.elastic = elastic - - # Currently we don't have a proper cross section or distribution for - # incoherent inelastic, so we just create an empty object and attach - # all the data as a dictionary - instance.inelastic = ThermalScatteringReaction(None, None) - instance.inelastic.data = data - - return instance diff --git a/openmc/data/thermal_angle_energy.py b/openmc/data/thermal_angle_energy.py deleted file mode 100644 index 05393e7bb..000000000 --- a/openmc/data/thermal_angle_energy.py +++ /dev/null @@ -1,212 +0,0 @@ -import numpy as np - -from .angle_energy import AngleEnergy -from .correlated import CorrelatedAngleEnergy - - -class CoherentElasticAE(AngleEnergy): - r"""Differential cross section for coherent elastic scattering - - The differential cross section for coherent elastic scattering from a - powdered crystalline material may be represented as: - - .. math:: - \frac{d^2\sigma}{dE'd\Omega} (E\rightarrow E',\mu,T) = \frac{1}{E} \sum - \limits_{i=1}^{E_i < E} s_i(T) \delta(\mu - \mu_i) \delta (E - E') - /(2\pi) - - where :math:`E_i` are the energies of the Bragg edges in [eV], :math:`s_i(T)` - is the structure factor in [eV-b] at the moderator temperature :math:`T` - in [K], and :math:`\mu_i = 1 - 2E_i/E`. - - Parameters - ---------- - coherent_xs : openmc.data.CoherentElastic - Coherent elastic scattering cross section - - Attributes - ---------- - coherent_xs : openmc.data.CoherentElastic - Coherent elastic scattering cross section - - """ - def __init__(self, coherent_xs): - self.coherent_xs = coherent_xs - - def to_hdf5(self, group): - """Write coherent elastic distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('coherent_elastic') - group['coherent_xs'] = group.parent['xs'] - - -class IncoherentElasticAE(AngleEnergy): - r"""Differential cross section for incoherent elastic scattering - - The differential cross section for incoherent elastic scattering may be - represented as: - - .. math:: - \frac{d^2\sigma}{dE'd\Omega} (E\rightarrow E',\mu,T) = \frac{\sigma_b} - {4\pi} e^{-2EW'(T)(1-\mu)} \delta(E - E') - - where :math:`\sigma_b` is the characteristic cross section in [b] and - :math:`W'(T)` is the Debye-Waller integral divided by the atomic mass in - [eV\ :math:`^{-1}`]. - - Parameters - ---------- - debye_waller : float - Debye-Waller integral in [eV\ :math:`^{-1}`] - - Attributes - ---------- - debye_waller : float - Debye-Waller integral in [eV\ :math:`^{-1}`] - - """ - def __init__(self, debye_waller): - self.debye_waller = debye_waller - - def to_hdf5(self, group): - """Write incoherent elastic distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('incoherent_elastic') - group.create_dataset('debye_waller', data=self.debye_waller) - - @classmethod - def from_hdf5(cls, group): - """Generate incoherent elastic distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.IncoherentElasticAE - Incoherent elastic distribution - - """ - return cls(group['debye_waller']) - - -class IncoherentElasticAEDiscrete(AngleEnergy): - """Discrete angle representation of incoherent elastic scattering - - Parameters - ---------- - mu_out : numpy.ndarray - Equi-probable discrete angles at each incoming energy - - """ - def __init__(self, mu_out): - self.mu_out = mu_out - - def to_hdf5(self, group): - """Write discrete incoherent elastic distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('incoherent_elastic_discrete') - group.create_dataset('mu_out', data=self.mu_out) - - @classmethod - def from_hdf5(cls, group): - """Generate discrete incoherent elastic distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.IncoherentElasticAEDiscrete - Discrete incoherent elastic distribution - - """ - return cls(group['mu_out'][()]) - - -class IncoherentInelasticAEDiscrete(AngleEnergy): - """Discrete angle representation of incoherent inelastic scattering - - Parameters - ---------- - energy_out : numpy.ndarray - Outgoing energies for each incoming energy - mu_out : numpy.ndarray - Discrete angles for each incoming/outgoing energy - skewed : bool - Whether discrete angles are equi-probable or have a skewed distribution - - Attributes - ---------- - energy_out : numpy.ndarray - Outgoing energies for each incoming energy - mu_out : numpy.ndarray - Discrete angles for each incoming/outgoing energy - skewed : bool - Whether discrete angles are equi-probable or have a skewed distribution - - """ - def __init__(self, energy_out, mu_out, skewed=False): - self.energy_out = energy_out - self.mu_out = mu_out - self.skewed = skewed - - def to_hdf5(self, group): - """Write discrete incoherent inelastic distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('incoherent_inelastic_discrete') - group.create_dataset('energy_out', data=self.energy_out) - group.create_dataset('mu_out', data=self.mu_out) - group.create_dataset('skewed', data=self.skewed) - - @classmethod - def from_hdf5(cls, group): - """Generate discrete incoherent inelastic distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.IncoherentInelasticAEDiscrete - Discrete incoherent inelastic distribution - - """ - energy_out = group['energy_out'][()] - mu_out = group['mu_out'][()] - skewed = bool(group['skewed']) - return cls(energy_out, mu_out, skewed) - - -class IncoherentInelasticAE(CorrelatedAngleEnergy): - _name = 'incoherent_inelastic' diff --git a/openmc/data/uncorrelated.py b/openmc/data/uncorrelated.py deleted file mode 100644 index 0361c9b37..000000000 --- a/openmc/data/uncorrelated.py +++ /dev/null @@ -1,95 +0,0 @@ -import numpy as np - -import openmc.checkvalue as cv -from .angle_energy import AngleEnergy -from .energy_distribution import EnergyDistribution -from .angle_distribution import AngleDistribution - - -class UncorrelatedAngleEnergy(AngleEnergy): - """Uncorrelated angle-energy distribution - - Parameters - ---------- - angle : openmc.data.AngleDistribution - Distribution of outgoing angles represented as scattering cosines - energy : openmc.data.EnergyDistribution - Distribution of outgoing energies - - Attributes - ---------- - angle : openmc.data.AngleDistribution - Distribution of outgoing angles represented as scattering cosines - energy : openmc.data.EnergyDistribution - Distribution of outgoing energies - - """ - - def __init__(self, angle=None, energy=None): - self._angle = None - self._energy = None - - if angle is not None: - self.angle = angle - if energy is not None: - self.energy = energy - - @property - def angle(self): - return self._angle - - @property - def energy(self): - return self._energy - - @angle.setter - def angle(self, angle): - cv.check_type('uncorrelated angle distribution', angle, - AngleDistribution) - self._angle = angle - - @energy.setter - def energy(self, energy): - cv.check_type('uncorrelated energy distribution', energy, - EnergyDistribution) - self._energy = energy - - def to_hdf5(self, group): - """Write distribution to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['type'] = np.string_('uncorrelated') - if self.angle is not None: - angle_group = group.create_group('angle') - self.angle.to_hdf5(angle_group) - - if self.energy is not None: - energy_group = group.create_group('energy') - self.energy.to_hdf5(energy_group) - - @classmethod - def from_hdf5(cls, group): - """Generate uncorrelated angle-energy distribution from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.UncorrelatedAngleEnergy - Uncorrelated angle-energy distribution - - """ - dist = cls() - if 'angle' in group: - dist.angle = AngleDistribution.from_hdf5(group['angle']) - if 'energy' in group: - dist.energy = EnergyDistribution.from_hdf5(group['energy']) - return dist diff --git a/openmc/data/urr.py b/openmc/data/urr.py deleted file mode 100644 index 53961a50a..000000000 --- a/openmc/data/urr.py +++ /dev/null @@ -1,215 +0,0 @@ -from collections.abc import Iterable -from numbers import Integral, Real - -import numpy as np - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin -from .data import EV_PER_MEV - - -class ProbabilityTables(EqualityMixin): - r"""Unresolved resonance region probability tables. - - Parameters - ---------- - energy : Iterable of float - Energies in eV at which probability tables exist - table : numpy.ndarray - Probability tables for each energy. This array is of shape (N, 6, M) - where N is the number of energies and M is the number of bands. The - second dimension indicates whether the value is for the cumulative - probability (0), total (1), elastic (2), fission (3), :math:`(n,\gamma)` - (4), or heating number (5). - interpolation : {2, 5} - Interpolation scheme between tables - inelastic_flag : int - A value less than zero indicates that the inelastic cross section is - zero within the unresolved energy range. A value greater than zero - indicates the MT number for a reaction whose cross section is to be used - in the unresolved range. - absorption_flag : int - A value less than zero indicates that the "other absorption" cross - section is zero within the unresolved energy range. A value greater than - zero indicates the MT number for a reaction whose cross section is to be - used in the unresolved range. - multiply_smooth : bool - Indicate whether probability table values are cross sections (False) or - whether they must be multiply by the corresponding "smooth" cross - sections (True). - - Attributes - ---------- - energy : Iterable of float - Energies in eV at which probability tables exist - table : numpy.ndarray - Probability tables for each energy. This array is of shape (N, 6, M) - where N is the number of energies and M is the number of bands. The - second dimension indicates whether the value is for the cumulative - probability (0), total (1), elastic (2), fission (3), :math:`(n,\gamma)` - (4), or heating number (5). - interpolation : {2, 5} - Interpolation scheme between tables - inelastic_flag : int - A value less than zero indicates that the inelastic cross section is - zero within the unresolved energy range. A value greater than zero - indicates the MT number for a reaction whose cross section is to be used - in the unresolved range. - absorption_flag : int - A value less than zero indicates that the "other absorption" cross - section is zero within the unresolved energy range. A value greater than - zero indicates the MT number for a reaction whose cross section is to be - used in the unresolved range. - multiply_smooth : bool - Indicate whether probability table values are cross sections (False) or - whether they must be multiply by the corresponding "smooth" cross - sections (True). - """ - - def __init__(self, energy, table, interpolation, inelastic_flag=-1, - absorption_flag=-1, multiply_smooth=False): - self.energy = energy - self.table = table - self.interpolation = interpolation - self.inelastic_flag = inelastic_flag - self.absorption_flag = absorption_flag - self.multiply_smooth = multiply_smooth - - @property - def absorption_flag(self): - return self._absorption_flag - - @property - def energy(self): - return self._energy - - @property - def inelastic_flag(self): - return self._inelastic_flag - - @property - def interpolation(self): - return self._interpolation - - @property - def multiply_smooth(self): - return self._multiply_smooth - - @property - def table(self): - return self._table - - @absorption_flag.setter - def absorption_flag(self, absorption_flag): - cv.check_type('absorption flag', absorption_flag, Integral) - self._absorption_flag = absorption_flag - - @energy.setter - def energy(self, energy): - cv.check_type('probability table energies', energy, Iterable, Real) - self._energy = energy - - @inelastic_flag.setter - def inelastic_flag(self, inelastic_flag): - cv.check_type('inelastic flag', inelastic_flag, Integral) - self._inelastic_flag = inelastic_flag - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_value('interpolation', interpolation, [2, 5]) - self._interpolation = interpolation - - @multiply_smooth.setter - def multiply_smooth(self, multiply_smooth): - cv.check_type('multiply by smooth', multiply_smooth, bool) - self._multiply_smooth = multiply_smooth - - @table.setter - def table(self, table): - cv.check_type('probability tables', table, np.ndarray) - self._table = table - - def to_hdf5(self, group): - """Write probability tables to an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to write to - - """ - group.attrs['interpolation'] = self.interpolation - group.attrs['inelastic'] = self.inelastic_flag - group.attrs['absorption'] = self.absorption_flag - group.attrs['multiply_smooth'] = int(self.multiply_smooth) - - group.create_dataset('energy', data=self.energy) - group.create_dataset('table', data=self.table) - - @classmethod - def from_hdf5(cls, group): - """Generate probability tables from HDF5 data - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Returns - ------- - openmc.data.ProbabilityTables - Probability tables - - """ - interpolation = group.attrs['interpolation'] - inelastic_flag = group.attrs['inelastic'] - absorption_flag = group.attrs['absorption'] - multiply_smooth = bool(group.attrs['multiply_smooth']) - - energy = group['energy'][()] - table = group['table'][()] - - return cls(energy, table, interpolation, inelastic_flag, - absorption_flag, multiply_smooth) - - @classmethod - def from_ace(cls, ace): - """Generate probability tables from an ACE table - - Parameters - ---------- - ace : openmc.data.ace.Table - ACE table to read from - - Returns - ------- - openmc.data.ProbabilityTables - Unresolved resonance region probability tables - - """ - # Check if URR probability tables are present - idx = ace.jxs[23] - if idx == 0: - return None - - N = int(ace.xss[idx]) # Number of incident energies - M = int(ace.xss[idx+1]) # Length of probability table - interpolation = int(ace.xss[idx+2]) - inelastic_flag = int(ace.xss[idx+3]) - absorption_flag = int(ace.xss[idx+4]) - multiply_smooth = (int(ace.xss[idx+5]) == 1) - idx += 6 - - # Get energies at which tables exist - energy = ace.xss[idx : idx+N]*EV_PER_MEV - idx += N - - # Get probability tables - table = ace.xss[idx : idx+N*6*M].copy() - table.shape = (N, 6, M) - - # Convert units on heating numbers - table[:,5,:] *= EV_PER_MEV - - return cls(energy, table, interpolation, inelastic_flag, - absorption_flag, multiply_smooth) diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py deleted file mode 100644 index b54d7f11d..000000000 --- a/openmc/deplete/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -openmc.deplete -============== - -A depletion front-end tool. -""" -import sys -from unittest.mock import Mock - -from h5py import get_config - -from .dummy_comm import DummyCommunicator - -try: - from mpi4py import MPI - - comm = MPI.COMM_WORLD - have_mpi = True - # check if running with MPI and if using parallel HDF5 - - if not get_config().mpi and comm.size > 1: - # Raise exception only on process 0 - if comm.rank: - sys.exit() - raise RuntimeError( - "Need parallel HDF5 installed to perform depletion with MPI" - ) -except ImportError: - comm = DummyCommunicator() - have_mpi = False - MPI = Mock() - -from .nuclide import * -from .chain import * -from .operator import * -from .reaction_rates import * -from .atom_number import * -from .results import * -from .results_list import * -from .integrators import * -from . import abc -from . import cram -from . import helpers diff --git a/openmc/deplete/_matrix_funcs.py b/openmc/deplete/_matrix_funcs.py deleted file mode 100644 index a606d739f..000000000 --- a/openmc/deplete/_matrix_funcs.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Functions to form the special matrix for depletion""" - - -def celi_f1(chain, rates, fission_yields=None): - return (5 / 12 * chain.form_matrix(rates[0], fission_yields) - + 1 / 12 * chain.form_matrix(rates[1], fission_yields)) - - -def celi_f2(chain, rates, fission_yields=None): - return (1 / 12 * chain.form_matrix(rates[0], fission_yields) - + 5 / 12 * chain.form_matrix(rates[1], fission_yields)) - - -def cf4_f1(chain, rates, fission_yields=None): - return 1 / 2 * chain.form_matrix(rates, fission_yields) - - -def cf4_f2(chain, rates, fission_yields=None): - return (-1 / 2 * chain.form_matrix(rates[0], fission_yields) - + chain.form_matrix(rates[1], fission_yields)) - - -def cf4_f3(chain, rates, fission_yields=None): - return (1 / 4 * chain.form_matrix(rates[0], fission_yields) - + 1 / 6 * chain.form_matrix(rates[1], fission_yields) - + 1 / 6 * chain.form_matrix(rates[2], fission_yields) - - 1 / 12 * chain.form_matrix(rates[3], fission_yields)) - - -def cf4_f4(chain, rates, fission_yields=None): - return (-1 / 12 * chain.form_matrix(rates[0], fission_yields) - + 1 / 6 * chain.form_matrix(rates[1], fission_yields) - + 1 / 6 * chain.form_matrix(rates[2], fission_yields) - + 1 / 4 * chain.form_matrix(rates[3], fission_yields)) - - -def rk4_f1(chain, rates, fission_yields=None): - return 1 / 2 * chain.form_matrix(rates, fission_yields) - - -def rk4_f4(chain, rates, fission_yields=None): - return (1 / 6 * chain.form_matrix(rates[0], fission_yields) - + 1 / 3 * chain.form_matrix(rates[1], fission_yields) - + 1 / 3 * chain.form_matrix(rates[2], fission_yields) - + 1 / 6 * chain.form_matrix(rates[3], fission_yields)) - - -def leqi_f1(chain, inputs, fission_yields): - f1 = chain.form_matrix(inputs[0], fission_yields) - f2 = chain.form_matrix(inputs[1], fission_yields) - dt_l, dt = inputs[2], inputs[3] - return -dt / (12 * dt_l) * f1 + (dt + 6 * dt_l) / (12 * dt_l) * f2 - - -def leqi_f2(chain, inputs, fission_yields=None): - f1 = chain.form_matrix(inputs[0], fission_yields) - f2 = chain.form_matrix(inputs[1], fission_yields) - dt_l, dt = inputs[2], inputs[3] - return -5 * dt / (12 * dt_l) * f1 + (5 * dt + 6 * dt_l) / (12 * dt_l) * f2 - - -def leqi_f3(chain, inputs, fission_yields=None): - f1 = chain.form_matrix(inputs[0], fission_yields) - f2 = chain.form_matrix(inputs[1], fission_yields) - f3 = chain.form_matrix(inputs[2], fission_yields) - dt_l, dt = inputs[3], inputs[4] - return (-dt ** 2 / (12 * dt_l * (dt + dt_l)) * f1 - + (dt ** 2 + 6 * dt * dt_l + 5 * dt_l ** 2) - / (12 * dt_l * (dt + dt_l)) * f2 + dt_l / (12 * (dt + dt_l)) * f3) - - -def leqi_f4(chain, inputs, fission_yields=None): - f1 = chain.form_matrix(inputs[0], fission_yields) - f2 = chain.form_matrix(inputs[1], fission_yields) - f3 = chain.form_matrix(inputs[2], fission_yields) - dt_l, dt = inputs[3], inputs[4] - return (-dt ** 2 / (12 * dt_l * (dt + dt_l)) * f1 - + (dt ** 2 + 2 * dt * dt_l + dt_l ** 2) - / (12 * dt_l * (dt + dt_l)) * f2 - + (4 * dt * dt_l + 5 * dt_l ** 2) / (12 * dt_l * (dt + dt_l)) * f3) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py deleted file mode 100644 index 462d0f346..000000000 --- a/openmc/deplete/abc.py +++ /dev/null @@ -1,895 +0,0 @@ -"""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 -from collections import defaultdict -from collections.abc import Iterable -import os -from pathlib import Path -from abc import ABC, abstractmethod -from copy import deepcopy -from warnings import warn -from numbers import Real, Integral - -from numpy import nonzero, empty, asarray -from uncertainties import ufloat - -from openmc.data import DataLibrary, JOULE_PER_EV -from openmc.lib import MaterialFilter, Tally -from openmc.checkvalue import check_type, check_greater_than -from .results import Results -from .chain import Chain -from .results_list import ResultsList - - -__all__ = [ - "OperatorResult", "TransportOperator", "ReactionRateHelper", - "EnergyHelper", "FissionYieldHelper", "TalliedFissionYieldHelper", - "Integrator", "SIIntegrator", "DepSystemSolver"] - - -OperatorResult = namedtuple('OperatorResult', ['k', 'rates']) -OperatorResult.__doc__ = """\ -Result of applying transport operator - -Parameters ----------- -k : uncertainties.ufloat - Resulting eigenvalue and standard deviation -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(ABC): - """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 file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. - fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. If not given, - values will be pulled from the ``chain_file``. - dilute_initial : float, optional - Initial atom density [atoms/cm^3] 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. - prev_results : ResultsList, optional - Results from a previous depletion calculation. - - Attributes - ---------- - dilute_initial : float - Initial atom density [atoms/cm^3] 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. - prev_res : ResultsList or None - Results from a previous depletion calculation. ``None`` if no - results are to be used. - """ - def __init__(self, chain_file=None, fission_q=None, dilute_initial=1.0e3, - prev_results=None): - self.dilute_initial = dilute_initial - 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: - data = DataLibrary.from_xml() - # search for depletion_chain path from end of list - for lib in reversed(data.libraries): - if lib['type'] == 'depletion_chain': - break - else: - raise IOError( - "No chain specified, either manually or " - "under depletion_chain in environment variable " - "OPENMC_CROSS_SECTIONS.") - chain_file = lib['path'] - else: - warn("Use of OPENMC_DEPLETE_CHAIN is deprecated in favor " - "of adding depletion_chain to OPENMC_CROSS_SECTIONS", - FutureWarning) - self.chain = Chain.from_xml(chain_file, fission_q) - if prev_results is None: - self.prev_res = None - else: - check_type("previous results", prev_results, ResultsList) - self.prev_results = prev_results - - @property - def dilute_initial(self): - """Initial atom density for nuclides with zero initial concentration""" - return self._dilute_initial - - @dilute_initial.setter - def dilute_initial(self, value): - check_type("dilute_initial", value, Real) - check_greater_than("dilute_initial", value, 0.0, equality=True) - self._dilute_initial = value - - @abstractmethod - def __call__(self, vec, power): - """Runs a simulation. - - Parameters - ---------- - vec : list of numpy.ndarray - Total atoms to be used in function. - power : float - Power of the reactor in [W] - - Returns - ------- - openmc.deplete.OperatorResult - Eigenvalue and reaction rates resulting from transport operator - - """ - - 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. - """ - - @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. - """ - - def finalize(self): - pass - - @abstractmethod - def write_bos_data(self, step): - """Document beginning of step data for a given step - - Called at the beginning of a depletion step and at - the final point in the simulation. - - Parameters - ---------- - step : int - Current depletion step including restarts - """ - - -class ReactionRateHelper(ABC): - """Abstract class for generating reaction rates for operators - - Responsible for generating reaction rate tallies for burnable - materials, given nuclides and scores from the operator. - - Reaction rates are passed back to the operator for be used in - an :class:`openmc.deplete.OperatorResult` instance - - Parameters - ---------- - n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` - n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` - - Attributes - ---------- - nuclides : list of str - All nuclides with desired reaction rates. - """ - - def __init__(self, n_nucs, n_react): - self._nuclides = None - self._rate_tally = None - self._results_cache = empty((n_nucs, n_react)) - - @abstractmethod - def generate_tallies(self, materials, scores): - """Use the C API to build tallies needed for reaction rates""" - - @property - def nuclides(self): - """List of nuclides with requested reaction rates""" - return self._nuclides - - @nuclides.setter - def nuclides(self, nuclides): - check_type("nuclides", nuclides, list, str) - self._nuclides = nuclides - self._rate_tally.nuclides = nuclides - - @abstractmethod - def get_material_rates(self, mat_id, nuc_index, react_index): - """Return 2D array of [nuclide, reaction] reaction rates - - Parameters - ---------- - mat_id : int - Unique ID for the requested material - nuc_index : list of str - Ordering of desired nuclides - react_index : list of str - Ordering of reactions - """ - - def divide_by_adens(self, number): - """Normalize reaction rates by number of nuclides - - Acts on the current material examined by - :meth:`get_material_rates` - - Parameters - ---------- - number : iterable of float - Number density [atoms/b-cm] of each nuclide tracked in the - calculation. - - Returns - ------- - results : numpy.ndarray - Array of reactions rates of shape ``(n_nuclides, n_rxns)`` - normalized by the number of nuclides - """ - - mask = nonzero(number) - results = self._results_cache - for col in range(results.shape[1]): - results[mask, col] /= number[mask] - return results - - -class EnergyHelper(ABC): - """Abstract class for obtaining energy produced - - The ultimate goal of this helper is to provide instances of - :class:`openmc.deplete.Operator` with the total energy produced - in a transport simulation. This information, provided with the - power requested by the user and reaction rates from a - :class:`ReactionRateHelper` will scale reaction rates to the - correct values. - - Attributes - ---------- - nuclides : list of str - All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.Operator` - energy : float - Total energy [J/s/source neutron] produced in a transport simulation. - Updated in the material iteration with :meth:`update`. - """ - - def __init__(self): - self._nuclides = None - self._energy = 0.0 - - @property - def energy(self): - return self._energy * JOULE_PER_EV - - def reset(self): - """Reset energy produced prior to unpacking tallies""" - self._energy = 0.0 - - @abstractmethod - def prepare(self, chain_nucs, rate_index, materials): - """Perform work needed to obtain energy produced - - This method is called prior to the transport simulations - in :meth:`openmc.deplete.Operator.initial_condition`. - - Parameters - ---------- - chain_nucs : list of str - All nuclides to be tracked in this problem - rate_index : dict of str to int - Mapping from nuclide name to index in the - `fission_rates` for :meth:`update`. - materials : list of str - All materials tracked on the operator helped by this - object. Should correspond to - :attr:`openmc.deplete.Operator.burnable_materials` - """ - - def update(self, fission_rates, mat_index): - """Update the energy produced - - Parameters - ---------- - fission_rates : numpy.ndarray - fission reaction rate for each isotope in the specified - material. Should be ordered corresponding to initial - ``rate_index`` used in :meth:`prepare` - mat_index : int - Index for the specific material in the list of all burnable - materials. - """ - - @property - def nuclides(self): - """List of nuclides with requested reaction rates""" - return self._nuclides - - @nuclides.setter - def nuclides(self, nuclides): - check_type("nuclides", nuclides, list, str) - self._nuclides = nuclides - - -class FissionYieldHelper(ABC): - """Abstract class for processing energy dependent fission yields - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. All nuclides are - not required to have fission yield data. - - Attributes - ---------- - constant_yields : collections.defaultdict - Fission yields for all nuclides that only have one set of - fission yield data. Dictionary of form ``{str: {str: float}}`` - representing yields for ``{parent: {product: yield}}``. Default - return object is an empty dictionary - - """ - - def __init__(self, chain_nuclides): - self._chain_nuclides = {} - self._constant_yields = defaultdict(dict) - - # Get all nuclides with fission yield data - for nuc in chain_nuclides: - if nuc.yield_data is None: - continue - if len(nuc.yield_data) == 1: - self._constant_yields[nuc.name] = ( - nuc.yield_data[nuc.yield_energies[0]]) - elif len(nuc.yield_data) > 1: - self._chain_nuclides[nuc.name] = nuc - self._chain_set = set(self._chain_nuclides) | set(self._constant_yields) - - @property - def constant_yields(self): - return deepcopy(self._constant_yields) - - @abstractmethod - def weighted_yields(self, local_mat_index): - """Return fission yields for a specific material - - Parameters - ---------- - local_mat_index : int - Index for the material with requested fission yields. - Should correspond to the material represented in - ``mat_indexes[local_mat_index]`` during - :meth:`generate_tallies`. - - Returns - ------- - library : collections.abc.Mapping - Dictionary-like object mapping ``{str: {str: float}``. - This reflects fission yields for ``{parent: {product: fyield}}``. - """ - - @staticmethod - def unpack(): - """Unpack tally data prior to compute fission yields. - - Called after a :meth:`openmc.deplete.Operator.__call__` - routine during the normalization of reaction rates. - - Not necessary for all subclasses to implement, unless tallies - are used. - """ - - @staticmethod - def generate_tallies(materials, mat_indexes): - """Construct tallies necessary for computing fission yields - - Called during the operator set up phase prior to depleting. - Not necessary for subclasses to implement - - Parameters - ---------- - materials : iterable of C-API materials - Materials to be used in :class:`openmc.lib.MaterialFilter` - mat_indexes : iterable of int - Indices of tallied materials that will have their fission - yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper - may only burn a subset of all materials when running - in parallel mode. - """ - - def update_tally_nuclides(self, nuclides): - """Return nuclides with non-zero densities and yield data - - Parameters - ---------- - nuclides : iterable of str - Nuclides with non-zero densities from the - :class:`openmc.deplete.Operator` - - Returns - ------- - nuclides : list of str - Union of nuclides that the :class:`openmc.deplete.Operator` - says have non-zero densities at this stage and those that - have yield data. Sorted by nuclide name - - """ - return sorted(self._chain_set & set(nuclides)) - - @classmethod - def from_operator(cls, operator, **kwargs): - """Create a new instance by pulling data from the operator - - All keyword arguments should be identical to their counterpart - in the main ``__init__`` method - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator with a depletion chain - kwargs: optional - Additional keyword arguments to be used in constuction - """ - return cls(operator.chain.nuclides, **kwargs) - - -class TalliedFissionYieldHelper(FissionYieldHelper): - """Abstract class for computing fission yields with tallies - - Generates a basic fission rate tally in all burnable materials with - :meth:`generate_tallies`, and set nuclides to be tallied with - :meth:`update_tally_nuclides`. Subclasses will need to implement - :meth:`unpack` and :meth:`weighted_yields`. - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. Not necessary - that all have yield data. - - Attributes - ---------- - constant_yields : dict of str to :class:`openmc.deplete.FissionYield` - Fission yields for all nuclides that only have one set of - fission yield data. Can be accessed as ``{parent: {product: yield}}`` - results : None or numpy.ndarray - Tally results shaped in a manner useful to this helper. - """ - - _upper_energy = 20.0e6 # upper energy for tallies - - def __init__(self, chain_nuclides): - super().__init__(chain_nuclides) - self._local_indexes = None - self._fission_rate_tally = None - self._tally_nucs = [] - self.results = None - - def generate_tallies(self, materials, mat_indexes): - """Construct the fission rate tally - - Parameters - ---------- - materials : iterable of :class:`openmc.lib.Material` - Materials to be used in :class:`openmc.lib.MaterialFilter` - mat_indexes : iterable of int - Indices of tallied materials that will have their fission - yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper - may only burn a subset of all materials when running - in parallel mode. - """ - self._local_indexes = asarray(mat_indexes) - - # Tally group-wise fission reaction rates - self._fission_rate_tally = Tally() - self._fission_rate_tally.writable = False - self._fission_rate_tally.scores = ['fission'] - - self._fission_rate_tally.filters = [MaterialFilter(materials)] - - def update_tally_nuclides(self, nuclides): - """Tally nuclides with non-zero density and multiple yields - - Must be run after :meth:`generate_tallies`. - - Parameters - ---------- - nuclides : iterable of str - Potential nuclides to be tallied, such as those with - non-zero density at this stage. - - Returns - ------- - nuclides : list of str - Union of input nuclides and those that have multiple sets - of yield data. Sorted by nuclide name - - Raises - ------ - AttributeError - If tallies not generated - """ - assert self._fission_rate_tally is not None, ( - "Run generate_tallies first") - overlap = set(self._chain_nuclides).intersection(set(nuclides)) - nuclides = sorted(overlap) - self._tally_nucs = [self._chain_nuclides[n] for n in nuclides] - self._fission_rate_tally.nuclides = nuclides - return nuclides - - @abstractmethod - def unpack(self): - """Unpack tallies after a transport run. - - Abstract because each subclass will need to arrange its - tally data. - """ - - -class Integrator(ABC): - """Abstract class for solving the time-integration for depletion - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - - def __init__(self, operator, timesteps, power=None, power_density=None): - # Check number of stages previously used - if operator.prev_res is not None: - res = operator.prev_res[-1] - if res.data.shape[0] != self._num_stages: - raise ValueError( - "{} incompatible with previous restart calculation. " - "Previous scheme used {} intermediate solutions, while " - "this uses {}".format( - self.__class__.__name__, res.data.shape[0], - self._num_stages)) - self.operator = operator - self.chain = operator.chain - if not isinstance(timesteps, Iterable): - self.timesteps = [timesteps] - else: - self.timesteps = timesteps - if power is None: - if power_density is None: - raise ValueError("Either power or power density must be set") - if not isinstance(power_density, Iterable): - power = power_density * operator.heavy_metal - else: - power = [p * operator.heavy_metal for p in power_density] - - if not isinstance(power, Iterable): - # Ensure that power is single value if that is the case - power = [power] * len(self.timesteps) - elif len(power) != len(self.timesteps): - raise ValueError( - "Number of time steps != number of powers. {} vs {}".format( - len(self.timesteps), len(power))) - - self.power = power - - @abstractmethod - def __call__(self, conc, rates, dt, power, i): - """Perform the integration across one time step - - Parameters - ---------- - conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - i : int - Current depletion step index - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulations - """ - - @property - @abstractmethod - def _num_stages(self): - """Number of intermediate transport solutions - - Needed to ensure schemes are consistent with restarts - """ - - def __iter__(self): - """Return pairs of time steps in [s] and powers in [W]""" - return zip(self.timesteps, self.power) - - def __len__(self): - """Return integer number of depletion intervals""" - return len(self.timesteps) - - def _get_bos_data_from_operator(self, step_index, step_power, bos_conc): - """Get beginning of step concentrations, reaction rates from Operator - """ - x = deepcopy(bos_conc) - res = self.operator(x, step_power) - self.operator.write_bos_data(step_index + self._i_res) - return x, res - - def _get_bos_data_from_restart(self, step_index, step_power, bos_conc): - """Get beginning of step concentrations, reaction rates from restart""" - res = self.operator.prev_res[-1] - # Depletion methods expect list of arrays - bos_conc = list(res.data[0]) - rates = res.rates[0] - k = ufloat(res.k[0, 0], res.k[0, 1]) - - # Scale rates by ratio of powers - rates *= step_power / res.power[0] - return bos_conc, OperatorResult(k, rates) - - def _get_start_data(self): - if self.operator.prev_res is None: - return 0.0, 0 - return (self.operator.prev_res[-1].time[-1], - len(self.operator.prev_res) - 1) - - def integrate(self): - """Perform the entire depletion process across all steps""" - with self.operator as conc: - t, self._i_res = self._get_start_data() - - for i, (dt, p) in enumerate(self): - if i > 0 or self.operator.prev_res is None: - conc, res = self._get_bos_data_from_operator(i, p, conc) - else: - conc, res = self._get_bos_data_from_restart(i, p, conc) - proc_time, conc_list, res_list = self(conc, res.rates, dt, p, i) - - # Insert BOS concentration, transport results - conc_list.insert(0, conc) - res_list.insert(0, res) - - # Remove actual EOS concentration for next step - conc = conc_list.pop() - - Results.save(self.operator, conc_list, res_list, [t, t + dt], - p, self._i_res + i, proc_time) - - t += dt - - # Final simulation - res_list = [self.operator(conc, p)] - Results.save(self.operator, [conc], res_list, [t, t], - p, self._i_res + len(self), proc_time) - self.operator.write_bos_data(len(self) + self._i_res) - - -class SIIntegrator(Integrator): - """Abstract class for the Stochastic Implicit Euler integrators - - Does not provide a ``__call__`` method, but scales and resets - the number of particles used in initial transport calculation - - 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, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - n_steps : int, optional - Number of stochastic iterations per depletion interval. - Must be greater than zero. Default : 10 - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - n_steps : int - Number of stochastic iterations per depletion interval - """ - def __init__(self, operator, timesteps, power=None, power_density=None, - n_steps=10): - check_type("n_steps", n_steps, Integral) - check_greater_than("n_steps", n_steps, 0) - super().__init__(operator, timesteps, power, power_density) - self.n_steps = n_steps - - def _get_bos_data_from_operator(self, step_index, step_power, bos_conc): - reset_particles = False - if step_index == 0 and hasattr(self.operator, "settings"): - reset_particles = True - self.operator.settings.particles *= self.n_stages - inherited = super()._get_bos_data_from_operator( - step_index, step_power, bos_conc) - if reset_particles: - self.operator.settings.particles //= self.n_stages - return inherited - - def integrate(self): - """Perform the entire depletion process across all steps""" - with self.operator as conc: - t, self._i_res = self._get_start_data() - - for i, (dt, p) in enumerate(self): - if i == 0: - if self.operator.prev_res is None: - conc, res = self._get_bos_data_from_operator(i, p, conc) - else: - conc, res = self._get_bos_data_from_restart(i, p, conc) - else: - # Pull rates, k from previous iteration w/o - # re-running transport - res = res_list[-1] # defined in previous i iteration - - proc_time, conc_list, res_list = self(conc, res.rates, dt, p, i) - - # Insert BOS concentration, transport results - conc_list.insert(0, conc) - res_list.insert(0, res) - - # Remove actual EOS concentration for next step - conc = conc_list.pop() - - Results.save(self.operator, conc_list, res_list, [t, t + dt], - p, self._i_res + i, proc_time) - - t += dt - - # No final simulation for SIE, use last iteration results - Results.save(self.operator, [conc], [res_list[-1]], [t, t], - p, self._i_res + len(self), proc_time) - self.operator.write_bos_data(self._i_res + len(self)) - - -class DepSystemSolver(ABC): - r"""Abstract class for solving depletion equations - - Responsible for solving - - .. math:: - - \frac{\partial \vec{N}}{\partial t} = \bar{A}\vec{N}(t), - - for :math:`0< t\leq t +\Delta t`, given :math:`\vec{N}(0) = \vec{N}_0` - - """ - - @abstractmethod - def __call__(self, A, n0, dt): - """Solve the linear system of equations for depletion - - Parameters - ---------- - A : scipy.sparse.csr_matrix - Sparse transmutation matrix ``A[j, i]`` desribing rates at - which isotope ``i`` transmutes to isotope ``j`` - n0 : numpy.ndarray - Initial compositions, typically given in number of atoms in some - material or an atom density - dt : float - Time [s] of the specific interval to be solved - - Returns - ------- - numpy.ndarray - Final compositions after ``dt``. Should be of identical shape - to ``n0``. - - """ diff --git a/openmc/deplete/atom_number.py b/openmc/deplete/atom_number.py deleted file mode 100644 index b5357280c..000000000 --- a/openmc/deplete/atom_number.py +++ /dev/null @@ -1,214 +0,0 @@ -"""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) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py deleted file mode 100644 index a2f7db818..000000000 --- a/openmc/deplete/chain.py +++ /dev/null @@ -1,786 +0,0 @@ -"""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 io import StringIO -from itertools import chain -import math -import re -from collections import OrderedDict, defaultdict -from collections.abc import Mapping, Iterable -from numbers import Real -from warnings import warn - -from openmc.checkvalue import check_type, check_greater_than -from openmc.data import gnd_name, zam -from .nuclide import FissionYieldDistribution - -# 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._xml import clean_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)) -] - - -__all__ = ["Chain"] - -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 - - -_SECONDARY_PARTICLES = { - "(n,p)": ["H1"], "(n,d)": ["H2"], "(n,t)": ["H3"], "(n,3He)": ["He3"], - "(n,a)": ["He4"], "(n,2nd)": ["H2"], "(n,na)": ["He4"], "(n,3na)": ["He4"], - "(n,n3a)": ["He4"] * 3, "(n,2na)": ["He4"], "(n,np)": ["H1"], - "(n,n2a)": ["He4"] * 2, "(n,2n2a)": ["He4"] * 2, "(n,nd)": ["H2"], - "(n,nt)": ["H3"], "(n,nHe-3)": ["He3"], "(n,nd2a)": ["H2", "He4"], - "(n,nt2a)": ["H3", "He4", "He4"], "(n,2np)": ["H1"], "(n,3np)": ["H1"], - "(n,n2p)": ["H1"] * 2, "(n,2a)": ["He4"] * 2, "(n,3a)": ["He4"] * 3, - "(n,2p)": ["H1"] * 2, "(n,pa)": ["H1", "He4"], - "(n,t2a)": ["H3", "He4", "He4"], "(n,d2a)": ["H2", "He4", "He4"], - "(n,pd)": ["H1", "H2"], "(n,pt)": ["H1", "H3"], "(n,da)": ["H2", "He4"]} - - -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 - ``depletion_chain`` item in the :envvar:`OPENMC_CROSS_SECTIONS` - 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. - fission_yields : None or iterable of dict - List of effective fission yields for materials. Each dictionary - should be of the form ``{parent: {product: yield}}`` with - types ``{str: {str: float}}``, where ``yield`` is the fission product - yield for isotope ``parent`` producing isotope ``product``. - A single entry indicates yields are constant across all materials. - Otherwise, an entry can be added for each material to be burned. - Ordering should be identical to how the operator orders reaction - rates for burnable materials. - """ - - def __init__(self): - self.nuclides = [] - self.reactions = [] - self.nuclide_dict = OrderedDict() - self._fission_yields = None - - 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(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: - yield_energies = fpy.energies - else: - yield_energies = [0.0] - - yield_data = {} - for E, table in zip(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 - 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)) - yield_data[E] = yields - - nuclide.yield_data = FissionYieldDistribution(yield_data) - - # 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, fission_q=None): - """Reads a depletion chain XML file. - - Parameters - ---------- - filename : str - The path to the depletion chain XML file. - fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. - If not given, values will be pulled from ``filename`` - - """ - chain = cls() - - if fission_q is not None: - check_type("fission_q", fission_q, Mapping) - else: - fission_q = {} - - # Load XML tree - root = ET.parse(str(filename)) - - for i, nuclide_elem in enumerate(root.findall('nuclide')): - this_q = fission_q.get(nuclide_elem.get("name")) - - nuc = Nuclide.from_xml(nuclide_elem, this_q) - 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_indentation(root_elem) - tree.write(str(filename), encoding='utf-8') - - def get_default_fission_yields(self): - """Return fission yields at lowest incident neutron energy - - Used as the default set of fission yields for :meth:`form_matrix` - if ``fission_yields`` are not provided - - Returns - ------- - fission_yields : dict - Dictionary of ``{parent: {product: f_yield}}`` - where ``parent`` and ``product`` are both string - names of nuclides with yield data and ``f_yield`` - is a float for the fission yield. - """ - out = defaultdict(dict) - for nuc in self.nuclides: - if nuc.yield_data is None: - continue - yield_obj = nuc.yield_data[min(nuc.yield_energies)] - out[nuc.name] = dict(yield_obj) - return out - - def form_matrix(self, rates, fission_yields=None): - """Forms depletion matrix. - - Parameters - ---------- - rates : numpy.ndarray - 2D array indexed by (nuclide, reaction) - fission_yields : dict, optional - Option to use a custom set of fission yields. Expected - to be of the form ``{parent : {product : f_yield}}`` - with string nuclide names for ``parent`` and ``product``, - and ``f_yield`` as the respective fission yield - - Returns - ------- - scipy.sparse.csr_matrix - Sparse matrix representing depletion. - - See Also - -------- - :meth:`get_default_fission_yields` - """ - matrix = defaultdict(float) - reactions = set() - - if fission_yields is None: - fission_yields = self.get_default_fission_yields() - - 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: - for product, y in fission_yields[nuc.name].items(): - 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() - - def get_branch_ratios(self, reaction="(n,gamma)"): - """Return a dictionary with reaction branching ratios - - Parameters - ---------- - reaction : str, optional - Reaction name like ``"(n,gamma)"`` [default], or - ``"(n,alpha)"``. - - Returns - ------- - branches : dict - nested dict of parent nuclide keys with reaction targets and - branching ratios. Consider the capture, ``"(n,gamma)"``, - reaction for Am241:: - - {"Am241": {"Am242": 0.91, "Am242_m1": 0.09}} - - See Also - -------- - :meth:`set_branch_ratios` - """ - - capt = {} - for nuclide in self.nuclides: - nuc_capt = {} - for rx in nuclide.reactions: - if rx.type == reaction and rx.branching_ratio != 1.0: - nuc_capt[rx.target] = rx.branching_ratio - if len(nuc_capt) > 0: - capt[nuclide.name] = nuc_capt - return capt - - def set_branch_ratios(self, branch_ratios, reaction="(n,gamma)", - strict=True, tolerance=1e-5): - """Set the branching ratios for a given reactions - - Parameters - ---------- - branch_ratios : dict of {str: {str: float}} - Capture branching ratios to be inserted. - First layer keys are names of parent nuclides, e.g. - ``"Am241"``. The branching ratios for these - parents will be modified. Corresponding values are - dictionaries of ``{target: branching_ratio}`` - reaction : str, optional - Reaction name like ``"(n,gamma)"`` [default], or - ``"(n, alpha)"``. - strict : bool, optional - Error control. If this evalutes to ``True``, then errors will - be raised if inconsistencies are found. Otherwise, warnings - will be raised for most issues. - tolerance : float, optional - Tolerance on the sum of all branching ratios for a - single parent. Will be checked with:: - - 1 - tol < sum_br < 1 + tol - - Raises - ------ - IndexError - If no isotopes were found on the chain that have the requested - reaction - KeyError - If ``strict`` evaluates to ``False`` and a parent isotope in - ``branch_ratios`` does not exist on the chain - AttributeError - If ``strict`` evaluates to ``False`` and a parent isotope in - ``branch_ratios`` does not have the requested reaction - ValueError - If ``strict`` evalutes to ``False`` and the sum of one parents - branch ratios is outside 1 +/- ``tolerance`` - - See Also - -------- - :meth:`get_branch_ratios` - """ - - # Store some useful information through the validation stage - - sums = {} - rxn_ix_map = {} - grounds = {} - - tolerance = abs(tolerance) - - missing_parents = set() - missing_products = {} - missing_reaction = set() - bad_sums = {} - - # Secondary products, like alpha particles, should not be modified - secondary = _SECONDARY_PARTICLES.get(reaction, []) - - # Check for validity before manipulation - - for parent, sub in branch_ratios.items(): - if parent not in self: - if strict: - raise KeyError(parent) - missing_parents.add(parent) - continue - - # Make sure all products are present in the chain - - prod_flag = False - - for product in sub: - if product not in self: - if strict: - raise KeyError(product) - missing_products[parent] = product - prod_flag = True - break - - if prod_flag: - continue - - # Make sure this nuclide has the reaction - - indexes = [] - for ix, rx in enumerate(self[parent].reactions): - if rx.type == reaction and rx.target not in secondary: - indexes.append(ix) - if "_m" not in rx.target: - grounds[parent] = rx.target - - if len(indexes) == 0: - if strict: - raise AttributeError( - "Nuclide {} does not have {} reactions".format( - parent, reaction)) - missing_reaction.add(parent) - continue - - this_sum = sum(sub.values()) - # sum of branching ratios can be lower than 1 if no ground - # target is given, but never greater - if (this_sum >= 1 + tolerance or (grounds[parent] in sub - and this_sum <= 1 - tolerance)): - if strict: - msg = ("Sum of {} branching ratios for {} " - "({:7.3f}) outside tolerance of 1 +/- " - "{:5.3e}".format( - reaction, parent, this_sum, tolerance)) - raise ValueError(msg) - bad_sums[parent] = this_sum - else: - rxn_ix_map[parent] = indexes - sums[parent] = this_sum - - if len(rxn_ix_map) == 0: - raise IndexError( - "No {} reactions found in this {}".format( - reaction, self.__class__.__name__)) - - if len(missing_parents) > 0: - warn("The following nuclides were not found in {}: {}".format( - self.__class__.__name__, ", ".join(sorted(missing_parents)))) - - if len(missing_reaction) > 0: - warn("The following nuclides did not have {} reactions: " - "{}".format(reaction, ", ".join(sorted(missing_reaction)))) - - if len(missing_products) > 0: - tail = ("{} -> {}".format(k, v) - for k, v in sorted(missing_products.items())) - warn("The following products were not found in the {} and " - "parents were unmodified: \n{}".format( - self.__class__.__name__, ", ".join(tail))) - - if len(bad_sums) > 0: - tail = ("{}: {:5.3f}".format(k, s) - for k, s in sorted(bad_sums.items())) - warn("The following parent nuclides were given {} branch ratios " - "with a sum outside tolerance of 1 +/- {:5.3e}:\n{}".format( - reaction, tolerance, "\n".join(tail))) - - # Insert new ReactionTuples with updated branch ratios - - for parent_name, rxn_index in rxn_ix_map.items(): - - parent = self[parent_name] - new_ratios = branch_ratios[parent_name] - rxn_index = rxn_ix_map[parent_name] - - # Assume Q value is independent of target state - rxn_Q = parent.reactions[rxn_index[0]].Q - - # Remove existing reactions - - for ix in reversed(rxn_index): - parent.reactions.pop(ix) - - all_meta = True - - for tgt, br in new_ratios.items(): - all_meta = all_meta and ("_m" in tgt) - parent.reactions.append(ReactionTuple( - reaction, tgt, rxn_Q, br)) - - if all_meta and sums[parent_name] != 1.0: - ground_br = 1.0 - sums[parent_name] - ground_tgt = grounds.get(parent_name) - if ground_tgt is None: - pz, pa, pm = zam(parent_name) - ground_tgt = gnd_name(pz, pa + 1, 0) - new_ratios[ground_tgt] = ground_br - parent.reactions.append(ReactionTuple( - reaction, ground_tgt, rxn_Q, ground_br)) - - @property - def fission_yields(self): - if self._fission_yields is None: - self._fission_yields = [self.get_default_fission_yields()] - return self._fission_yields - - @fission_yields.setter - def fission_yields(self, yields): - if yields is not None: - if isinstance(yields, Mapping): - yields = [yields] - check_type("fission_yields", yields, Iterable, Mapping) - self._fission_yields = yields - - def validate(self, strict=True, quiet=False, tolerance=1e-4): - """Search for possible inconsistencies - - The following checks are performed for all nuclides present: - - 1) For all non-fission reactions, does the sum of branching - ratios equal about one? - 2) For fission reactions, does the sum of fission yield - fractions equal about two? - - Parameters - ---------- - strict : bool, optional - Raise exceptions at the first inconsistency if true. - Otherwise mark a warning - quiet : bool, optional - Flag to suppress warnings and return immediately at - the first inconsistency. Used only if - ``strict`` does not evaluate to ``True``. - tolerance : float, optional - Absolute tolerance for comparisons. Used to compare computed - value ``x`` to intended value ``y`` as:: - - valid = (y - tolerance <= x <= y + tolerance) - - Returns - ------- - valid : bool - True if no inconsistencies were found - - Raises - ------ - ValueError - If ``strict`` evaluates to ``True`` and an inconistency was - found - - See Also - -------- - openmc.deplete.Nuclide.validate - """ - check_type("tolerance", tolerance, Real) - check_greater_than("tolerance", tolerance, 0.0, True) - valid = True - # Sort through nuclides by name - for name in sorted(self.nuclide_dict): - stat = self[name].validate(strict, quiet, tolerance) - if quiet and not stat: - return stat - valid = valid and stat - return valid diff --git a/openmc/deplete/cram.py b/openmc/deplete/cram.py deleted file mode 100644 index 7dad820a9..000000000 --- a/openmc/deplete/cram.py +++ /dev/null @@ -1,255 +0,0 @@ -"""Chebyshev Rational Approximation Method module - -Implements two different forms of CRAM for use in openmc.deplete. -""" - -import numbers -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 openmc.checkvalue import check_type, check_length -from .abc import DepSystemSolver - -__all__ = [ - "deplete", "timed_deplete", "CRAM16", "CRAM48", - "Cram16Solver", "Cram48Solver", "IPFCramSolver"] - - -def deplete(chain, x, rates, dt, matrix_func=None): - """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 - rates : openmc.deplete.ReactionRates - Reaction rates (from transport operator) - dt : float - Time in [s] to deplete for - maxtrix_func : Callable, optional - Function to form the depletion matrix after calling - ``matrix_func(chain, rates, fission_yields)``, where - ``fission_yields = {parent: {product: yield_frac}}`` - Expected to return the depletion matrix required by - :func:`CRAM48`. - - Returns - ------- - x_result : list of numpy.ndarray - Updated atom number vectors for each material - """ - - fission_yields = chain.fission_yields - if len(fission_yields) == 1: - fission_yields = repeat(fission_yields[0]) - elif len(fission_yields) != len(x): - raise ValueError( - "Number of material fission yield distributions {} is not equal " - "to the number of compositions {}".format(len(fission_yields), - len(x))) - - if matrix_func is None: - matrices = map(chain.form_matrix, rates, fission_yields) - else: - matrices = map(matrix_func, repeat(chain), rates, fission_yields) - - # Use multiprocessing pool to distribute work - with Pool() as pool: - inputs = zip(matrices, x, repeat(dt)) - x_result = list(pool.starmap(CRAM48, inputs)) - - return x_result - - -def timed_deplete(*args, **kwargs): - """Wrapper over :func:`deplete` that also returns process time - - All arguments and keyword arguments are passed onto - :func:`deplete` directly. - - Returns - ------- - proc_time: float - Process time required to return from deplete - results: list of numpy arrays - Output from :func:`deplete` call - """ - - start = time.time() - results = deplete(*args, **kwargs) - return time.time() - start, results - - -class IPFCramSolver(DepSystemSolver): - r"""CRAM depletion solver that uses incomplete partial factorization - - Provides a :meth:`__call__` that utilizes an incomplete - partial factorization (IPF) for the Chebyshev Rational Approximation - Method (CRAM), as described in the following paper: M. Pusa, "`Higher-Order - Chebyshev Rational Approximation Method and Application to Burnup Equations - `_," Nucl. Sci. Eng., 182:3, 297-318. - - Parameters - ---------- - alpha : numpy.ndarray - Complex residues of poles used in the factorization. Must be a - vector with even number of items. - theta : numpy.ndarray - Complex poles. Must have an equal size as ``alpha``. - alpha0 : float - Limit of the approximation at infinity - - Attributes - ---------- - alpha : numpy.ndarray - Complex residues of poles :attr:`theta` in the incomplete partial - factorization. Denoted as :math:`\tilde{\alpha}` - theta : numpy.ndarray - Complex poles :math:`\theta` of the rational approximation - alpha0 : float - Limit of the approximation at infinity - - """ - - def __init__(self, alpha, theta, alpha0): - check_type("alpha", alpha, np.ndarray, numbers.Complex) - check_type("theta", theta, np.ndarray, numbers.Complex) - check_length("theta", theta, alpha.size) - check_type("alpha0", alpha0, numbers.Real) - self.alpha = alpha - self.theta = theta - self.alpha0 = alpha0 - - def __call__(self, A, n0, dt): - """Solve depletion equations using IPF CRAM - - Parameters - ---------- - A : scipy.sparse.csr_matrix - Sparse transmutation matrix ``A[j, i]`` desribing rates at - which isotope ``i`` transmutes to isotope ``j`` - n0 : numpy.ndarray - Initial compositions, typically given in number of atoms in some - material or an atom density - dt : float - Time [s] of the specific interval to be solved - - Returns - ------- - numpy.ndarray - Final compositions after ``dt`` - - """ - A = sp.csr_matrix(A * dt, dtype=np.float64) - y = np.asarray(n0, dtype=np.float64) - ident = sp.eye(A.shape[0]) - for alpha, theta in zip(self.alpha, self.theta): - y += 2*np.real(alpha*sla.spsolve(A - theta*ident, y)) - return y * self.alpha0 - - -# Coefficients for IPF Cram 16 -c16_alpha = np.array([ - +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) - -c16_theta = np.array([ - +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) - -c16_alpha0 = 2.124853710495224e-16 -Cram16Solver = IPFCramSolver(c16_alpha, c16_theta, c16_alpha0) -CRAM16 = Cram16Solver.__call__ - -del c16_alpha, c16_alpha0, c16_theta - -# Coefficients for 48th order IPF Cram - -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]) - -c48_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]) - -c48_alpha = np.array(alpha_r + alpha_i * 1j, dtype=np.complex128) - -c48_alpha0 = 2.258038182743983e-47 - -Cram48Solver = IPFCramSolver(c48_alpha, c48_theta, c48_alpha0) - -del c48_alpha, c48_alpha0, c48_theta, alpha_r, alpha_i, theta_r, theta_i - -CRAM48 = Cram48Solver.__call__ diff --git a/openmc/deplete/dummy_comm.py b/openmc/deplete/dummy_comm.py deleted file mode 100644 index 2648fdedc..000000000 --- a/openmc/deplete/dummy_comm.py +++ /dev/null @@ -1,32 +0,0 @@ -import sys - -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] - - def Abort(self, exit_code_or_msg): - sys.exit(exit_code_or_msg) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py deleted file mode 100644 index d79a03111..000000000 --- a/openmc/deplete/helpers.py +++ /dev/null @@ -1,683 +0,0 @@ -""" -Class for normalizing fission energy deposition -""" -from copy import deepcopy -from itertools import product -from numbers import Real -import bisect -from collections import defaultdict - -from numpy import dot, zeros, newaxis - -from . import comm -from openmc.checkvalue import check_type, check_greater_than -from openmc.lib import ( - Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter) -from .abc import ( - ReactionRateHelper, EnergyHelper, FissionYieldHelper, - TalliedFissionYieldHelper) - -__all__ = ( - "DirectReactionRateHelper", "ChainFissionHelper", - "ConstantFissionYieldHelper", "FissionYieldCutoffHelper", - "AveragedFissionYieldHelper") - -# ------------------------------------- -# Helpers for generating reaction rates -# ------------------------------------- - - -class DirectReactionRateHelper(ReactionRateHelper): - """Class that generates tallies for one-group rates - - Parameters - ---------- - n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` - n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` - - Attributes - ---------- - nuclides : list of str - All nuclides with desired reaction rates. - """ - - def generate_tallies(self, materials, scores): - """Produce one-group reaction rate tally - - Uses the :mod:`openmc.lib` to generate a tally - of relevant reactions across all burnable materials. - - Parameters - ---------- - materials : iterable of :class:`openmc.Material` - Burnable materials in the problem. Used to - construct a :class:`openmc.MaterialFilter` - scores : iterable of str - Reaction identifiers, e.g. ``"(n, fission)"``, - ``"(n, gamma)"``, needed for the reaction rate tally. - """ - self._rate_tally = Tally() - self._rate_tally.writable = False - self._rate_tally.scores = scores - self._rate_tally.filters = [MaterialFilter(materials)] - - def get_material_rates(self, mat_id, nuc_index, react_index): - """Return an array of reaction rates for a material - - Parameters - ---------- - mat_id : int - Unique ID for the requested material - nuc_index : iterable of int - Index for each nuclide in :attr:`nuclides` in the - desired reaction rate matrix - react_index : iterable of int - Index for each reaction scored in the tally - - Returns - ------- - rates : numpy.ndarray - Array with shape ``(n_nuclides, n_rxns)`` with the - reaction rates in this material - """ - self._results_cache.fill(0.0) - full_tally_res = self._rate_tally.results[mat_id, :, 1] - for i_tally, (i_nuc, i_react) in enumerate( - product(nuc_index, react_index)): - self._results_cache[i_nuc, i_react] = full_tally_res[i_tally] - - return self._results_cache - - -# ---------------------------- -# Helpers for obtaining energy -# ---------------------------- - - -class ChainFissionHelper(EnergyHelper): - """Computes energy using fission Q values from depletion chain - - Attributes - ---------- - nuclides : list of str - All nuclides with desired reaction rates. Ordered to be - consistent with :class:`openmc.deplete.Operator` - energy : float - Total energy [J/s/source neutron] produced in a transport simulation. - Updated in the material iteration with :meth:`update`. - """ - - def __init__(self): - super().__init__() - self._fission_q_vector = None - - def prepare(self, chain_nucs, rate_index, _materials): - """Populate the fission Q value vector from a chain. - - Parameters - ---------- - chain_nucs : iterable of :class:`openmc.deplete.Nuclide` - Nuclides used in this depletion chain. Do not need - to be ordered - rate_index : dict of str to int - Dictionary mapping names of nuclides, e.g. ``"U235"``, - to a corresponding index in the desired fission Q - vector. - _materials : list of str - Unused. Materials to be tracked for this helper. - """ - if (self._fission_q_vector is not None - and self._fission_q_vector.shape == (len(rate_index),)): - return - - fission_qs = zeros(len(rate_index)) - - for nuclide in chain_nucs: - if nuclide.name in rate_index: - for rx in nuclide.reactions: - if rx.type == "fission": - fission_qs[rate_index[nuclide.name]] = rx.Q - break - - self._fission_q_vector = fission_qs - - def update(self, fission_rates, _mat_index): - """Update energy produced with fission rates in a material - - Parameters - ---------- - fission_rates : numpy.ndarray - fission reaction rate for each isotope in the specified - material. Should be ordered corresponding to initial - ``rate_index`` used in :meth:`prepare` - _mat_index : int - index for the material requested. Unused, as identical - isotopes in all materials have the same Q value. - """ - self._energy += dot(fission_rates, self._fission_q_vector) - - -class EnergyScoreHelper(EnergyHelper): - """Class responsible for obtaining system energy via a tally score - - Parameters - ---------- - score : string - Valid score to use when obtaining system energy from OpenMC. - Defaults to "heating-local" - - Attributes - ---------- - nuclides : list of str - List of nuclides with reaction rates. Not needed, but provided - for a consistent API across other :class:`EnergyHelper` - energy : float - System energy [eV] computed from the tally. Will be zero for - all MPI processes that are not the "master" process to avoid - artificially increasing the tallied energy. - score : str - Score used to obtain system energy - - """ - - def __init__(self, score="heating-local"): - super().__init__() - self.score = score - self._tally = None - - def prepare(self, *args, **kwargs): - """Create a tally for system energy production - - Input arguments are not used, as the only information needed - is :attr:`score` - - """ - self._tally = Tally() - self._tally.writable = False - self._tally.scores = [self.score] - - def reset(self): - """Obtain system energy from tally - - Only the master process, ``comm.rank == 0`` will - have a non-zero :attr:`energy` taken from the tally. - This avoids accidentally scaling the system power by - the number of MPI processes - """ - super().reset() - if comm.rank == 0: - self._energy = self._tally.results[0, 0, 1] - -# ------------------------------------ -# Helper for collapsing fission yields -# ------------------------------------ - - -class ConstantFissionYieldHelper(FissionYieldHelper): - """Class that uses a single set of fission yields on each isotope - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. All nuclides are - not required to have fission yield data. - energy : float, optional - Key in :attr:`openmc.deplete.Nuclide.yield_data` corresponding - to the desired set of fission yield data. Typically one of - ``{0.0253, 500000, 14000000}`` corresponding to 0.0253 eV, - 500 keV, and 14 MeV yield libraries. If the specific key is not - found, will fall back to closest energy present. - Default: 0.0253 eV for thermal yields - - Attributes - ---------- - constant_yields : collections.defaultdict - Fission yields for all nuclides that only have one set of - fission yield data. Dictionary of form ``{str: {str: float}}`` - representing yields for ``{parent: {product: yield}}``. Default - return object is an empty dictionary - energy : float - Energy of fission yield libraries. - """ - - def __init__(self, chain_nuclides, energy=0.0253): - check_type("energy", energy, Real) - check_greater_than("energy", energy, 0.0, equality=True) - self._energy = energy - super().__init__(chain_nuclides) - # Iterate over all nuclides with > 1 set of yields - for name, nuc in self._chain_nuclides.items(): - yield_data = nuc.yield_data.get(energy) - if yield_data is not None: - self._constant_yields[name] = yield_data - continue - # Specific energy not found, use closest energy - distances = [abs(energy - ene) for ene in nuc.yield_energies] - min_E = min(nuc.yield_energies, key=lambda e: abs(e - energy)) - self._constant_yields[name] = nuc.yield_data[min_E] - - @classmethod - def from_operator(cls, operator, **kwargs): - """Return a new ConstantFissionYieldHelper using operator data - - All keyword arguments should be identical to their counterpart - in the main ``__init__`` method - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - operator with a depletion chain - kwargs: - Additional keyword arguments to be used in construction - - Returns - ------- - ConstantFissionYieldHelper - """ - return cls(operator.chain.nuclides, **kwargs) - - @property - def energy(self): - return self._energy - - def weighted_yields(self, _local_mat_index=None): - """Return fission yields for all nuclides requested - - Parameters - ---------- - _local_mat_index : int, optional - Current material index. Not used since all yields are - constant - - Returns - ------- - library : collections.defaultdict - Dictionary of ``{parent: {product: fyield}}`` - """ - return self.constant_yields - - -class FissionYieldCutoffHelper(TalliedFissionYieldHelper): - """Helper that computes fission yields based on a cutoff energy - - Tally fission rates above and below the cutoff energy. - Assume that all fissions below cutoff energy have use thermal fission - product yield distributions, while all fissions above use a faster - set of yield distributions. - - Uses a limit of 20 MeV for tallying fission. - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. All nuclides are - not required to have fission yield data. - n_bmats : int, optional - Number of burnable materials tracked in the problem - cutoff : float, optional - Cutoff energy in [eV] below which all fissions will be - use thermal yields. All other fissions will use a - faster set of yields. Default: 112 [eV] - thermal_energy : float, optional - Energy of yield data corresponding to thermal yields. - Default: 0.0253 [eV] - fast_energy : float, optional - Energy of yield data corresponding to fast yields. - Default: 500 [kev] - - Attributes - ---------- - n_bmats : int - Number of burnable materials tracked in the problem. - Must be set prior to generating tallies - thermal_yields : dict - Dictionary of the form ``{parent: {product: yield}}`` - with thermal yields - fast_yields : dict - Dictionary of the form ``{parent: {product: yield}}`` - with fast yields - constant_yields : collections.defaultdict - Fission yields for all nuclides that only have one set of - fission yield data. Dictionary of form ``{str: {str: float}}`` - representing yields for ``{parent: {product: yield}}``. Default - return object is an empty dictionary - results : numpy.ndarray - Array of fission rate fractions with shape - ``(n_mats, 2, n_nucs)``. ``results[:, 0]`` - corresponds to the fraction of all fissions - that occured below ``cutoff``. The number - of materials in the first axis corresponds - to the number of materials burned by the - :class:`openmc.deplete.Operator` - """ - - def __init__(self, chain_nuclides, n_bmats, cutoff=112.0, - thermal_energy=0.0253, fast_energy=500.0e3): - check_type("cutoff", cutoff, Real) - check_type("thermal_energy", thermal_energy, Real) - check_type("fast_energy", fast_energy, Real) - check_greater_than("thermal_energy", thermal_energy, 0.0, equality=True) - check_greater_than("cutoff", cutoff, thermal_energy, equality=False) - check_greater_than("fast_energy", fast_energy, cutoff, equality=False) - self.n_bmats = n_bmats - super().__init__(chain_nuclides) - self._cutoff = cutoff - self._thermal_yields = {} - self._fast_yields = {} - convert_to_constant = set() - for name, nuc in self._chain_nuclides.items(): - yields = nuc.yield_data - energies = nuc.yield_energies - thermal = yields.get(thermal_energy) - fast = yields.get(fast_energy) - if thermal is None or fast is None: - if cutoff <= energies[0]: - # use lowest energy yields as constant - self._constant_yields[name] = yields[energies[0]] - convert_to_constant.add(name) - continue - if cutoff >= energies[-1]: - # use highest energy yields as constant - self._constant_yields[name] = yields[energies[-1]] - convert_to_constant.add(name) - continue - cutoff_ix = bisect.bisect_left(energies, cutoff) - # find closest energy to requested thermal, fast energies - if thermal is None: - min_E = min(energies[:cutoff_ix], - key=lambda e: abs(e - thermal_energy)) - thermal = yields[min_E] - if fast is None: - min_E = min(energies[cutoff_ix:], - key=lambda e: abs(e - fast_energy)) - fast = yields[min_E] - self._thermal_yields[name] = thermal - self._fast_yields[name] = fast - for name in convert_to_constant: - self._chain_nuclides.pop(name) - - @classmethod - def from_operator(cls, operator, **kwargs): - """Construct a helper from an operator - - All keyword arguments should be identical to their counterpart - in the main ``__init__`` method - - Parameters - ---------- - operator : openmc.deplete.Operator - Operator with a chain and burnable materials - kwargs: - Additional keyword arguments to be used in construction - - Returns - ------- - FissionYieldCutoffHelper - - """ - return cls(operator.chain.nuclides, len(operator.burnable_mats), - **kwargs) - - def generate_tallies(self, materials, mat_indexes): - """Use C API to produce a fission rate tally in burnable materials - - Include a :class:`openmc.lib.EnergyFilter` to tally fission rates - above and below cutoff energy. - - Parameters - ---------- - materials : iterable of :class:`openmc.lib.Material` - Materials to be used in :class:`openmc.lib.MaterialFilter` - mat_indexes : iterable of int - Indices of tallied materials that will have their fission - yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper - may only burn a subset of all materials when running - in parallel mode. - """ - super().generate_tallies(materials, mat_indexes) - energy_filter = EnergyFilter([0.0, self._cutoff, self._upper_energy]) - self._fission_rate_tally.filters = ( - self._fission_rate_tally.filters + [energy_filter]) - - def unpack(self): - """Obtain fast and thermal fission fractions from tally""" - if not self._tally_nucs: - self.results = None - return - fission_rates = self._fission_rate_tally.results[..., 1].reshape( - self.n_bmats, 2, len(self._tally_nucs)) - self.results = fission_rates[self._local_indexes] - total_fission = self.results.sum(axis=1) - nz_mat, nz_nuc = total_fission.nonzero() - self.results[nz_mat, :, nz_nuc] /= total_fission[nz_mat, newaxis, nz_nuc] - - def weighted_yields(self, local_mat_index): - """Return fission yields for a specific material - - For nuclides with both yield data above and below - the cutoff energy, the effective yield for nuclide ``A`` - will be a weighted sum of fast and thermal yields. The - weights will be the fraction of ``A`` fission events - in the above and below the cutoff energy. - - If ``A`` has fission product distribution ``F`` - for fast fissions and ``T`` for thermal fissions, and - 70% of ``A`` fissions are considered thermal, then - the effective fission product yield distributions - for ``A`` is ``0.7 * T + 0.3 * F`` - - Parameters - ---------- - local_mat_index : int - Index for specific burnable material. Effective - yields will be produced using - ``self.results[local_mat_index]`` - - Returns - ------- - library : collections.defaultdict - Dictionary of ``{parent: {product: fyield}}`` - """ - yields = self.constant_yields - if not self._tally_nucs: - return yields - rates = self.results[local_mat_index] - # iterate over thermal then fast yields, prefer __mul__ to __rmul__ - for therm_frac, fast_frac, nuc in zip(rates[0], rates[1], self._tally_nucs): - yields[nuc.name] = (self._thermal_yields[nuc.name] * therm_frac - + self._fast_yields[nuc.name] * fast_frac) - return yields - - @property - def thermal_yields(self): - return deepcopy(self._thermal_yields) - - @property - def fast_yields(self): - return deepcopy(self._fast_yields) - - -class AveragedFissionYieldHelper(TalliedFissionYieldHelper): - r"""Class that computes fission yields based on average fission energy - - Computes average energy at which fission events occured with - - .. math:: - - \bar{E} = \frac{ - \int_0^\infty E\sigma_f(E)\phi(E)dE - }{ - \int_0^\infty\sigma_f(E)\phi(E)dE - } - - If the average energy for a nuclide is below the lowest energy - with yield data, that set of fission yields is taken. - Conversely, if the average energy is above the highest energy - with yield data, that set of fission yields is used. - For the case where the average energy is between two sets - of yields, the effective fission yield computed by - linearly interpolating between yields provided at the - nearest energies above and below the average. - - Parameters - ---------- - chain_nuclides : iterable of openmc.deplete.Nuclide - Nuclides tracked in the depletion chain. All nuclides are - not required to have fission yield data. - - Attributes - ---------- - constant_yields : collections.defaultdict - Fission yields for all nuclides that only have one set of - fission yield data. Dictionary of form ``{str: {str: float}}`` - representing yields for ``{parent: {product: yield}}``. Default - return object is an empty dictionary - results : None or numpy.ndarray - If tallies have been generated and unpacked, then the array will - have shape ``(n_mats, n_tnucs)``, where ``n_mats`` is the number - of materials where fission reactions were tallied and ``n_tnucs`` - is the number of nuclides with multiple sets of fission yields. - Data in the array are the average energy of fission events for - tallied nuclides across burnable materials. - """ - - def __init__(self, chain_nuclides): - super().__init__(chain_nuclides) - self._weighted_tally = None - - def generate_tallies(self, materials, mat_indexes): - """Construct tallies to determine average energy of fissions - - Parameters - ---------- - materials : iterable of :class:`openmc.lib.Material` - Materials to be used in :class:`openmc.lib.MaterialFilter` - mat_indexes : iterable of int - Indices of tallied materials that will have their fission - yields computed by this helper. Necessary as the - :class:`openmc.deplete.Operator` that uses this helper - may only burn a subset of all materials when running - in parallel mode. - """ - super().generate_tallies(materials, mat_indexes) - fission_tally = self._fission_rate_tally - filters = fission_tally.filters - - ene_filter = EnergyFilter([0, self._upper_energy]) - fission_tally.filters = filters + [ene_filter] - - func_filter = EnergyFunctionFilter() - func_filter.set_data((0, self._upper_energy), (0, self._upper_energy)) - weighted_tally = Tally() - weighted_tally.writable = False - weighted_tally.scores = ['fission'] - weighted_tally.filters = filters + [func_filter] - self._weighted_tally = weighted_tally - - def update_tally_nuclides(self, nuclides): - """Tally nuclides with non-zero density and multiple yields - - Must be run after :meth:`generate_tallies`. - - Parameters - ---------- - nuclides : iterable of str - Potential nuclides to be tallied, such as those with - non-zero density at this stage. - - Returns - ------- - nuclides : tuple of str - Union of input nuclides and those that have multiple sets - of yield data. Sorted by nuclide name - - Raises - ------ - AttributeError - If tallies not generated - """ - tally_nucs = super().update_tally_nuclides(nuclides) - self._weighted_tally.nuclides = tally_nucs - return tally_nucs - - def unpack(self): - """Unpack tallies and populate :attr:`results` with average energies""" - if not self._tally_nucs: - self.results = None - return - fission_results = ( - self._fission_rate_tally.results[self._local_indexes, :, 1]) - self.results = ( - self._weighted_tally.results[self._local_indexes, :, 1]).copy() - nz_mat, nz_nuc = fission_results.nonzero() - self.results[nz_mat, nz_nuc] /= fission_results[nz_mat, nz_nuc] - - def weighted_yields(self, local_mat_index): - """Return fission yields for a specific material - - Use the computed average energy of fission - events to determine fission yields. If average - energy is between two sets of yields, linearly - interpolate bewteen the two. - Otherwise take the closet set of yields. - - Parameters - ---------- - local_mat_index : int - Index for specific burnable material. Effective - yields will be produced using - ``self.results[local_mat_index]`` - - Returns - ------- - library : collections.defaultdict - Dictionary of ``{parent: {product: fyield}}``. Default return - value is an empty dictionary - """ - if not self._tally_nucs: - return self.constant_yields - mat_yields = defaultdict(dict) - average_energies = self.results[local_mat_index] - for avg_e, nuc in zip(average_energies, self._tally_nucs): - nuc_energies = nuc.yield_energies - if avg_e <= nuc_energies[0]: - mat_yields[nuc.name] = nuc.yield_data[nuc_energies[0]] - continue - if avg_e >= nuc_energies[-1]: - mat_yields[nuc.name] = nuc.yield_data[nuc_energies[-1]] - continue - # in-between two energies - # linear search since there are usually ~3 energies - for ix, ene in enumerate(nuc_energies[:-1]): - if nuc_energies[ix + 1] > avg_e: - break - lower, upper = nuc_energies[ix:ix + 2] - fast_frac = (avg_e - lower) / (upper - lower) - mat_yields[nuc.name] = ( - nuc.yield_data[lower] * (1 - fast_frac) - + nuc.yield_data[upper] * fast_frac) - mat_yields.update(self.constant_yields) - return mat_yields - - @classmethod - def from_operator(cls, operator, **kwargs): - """Return a new helper with data from an operator - - All keyword arguments should be identical to their counterpart - in the main ``__init__`` method - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator with a depletion chain - kwargs : - Additional keyword arguments to be used in construction - - Returns - ------- - AveragedFissionYieldHelper - """ - return cls(operator.chain.nuclides) diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py deleted file mode 100644 index 67106aa3e..000000000 --- a/openmc/deplete/integrators.py +++ /dev/null @@ -1,836 +0,0 @@ -import copy -from itertools import repeat - -from .abc import Integrator, SIIntegrator, OperatorResult -from .cram import timed_deplete -from ._matrix_funcs import ( - cf4_f1, cf4_f2, cf4_f3, cf4_f4, celi_f1, celi_f2, - leqi_f1, leqi_f2, leqi_f3, leqi_f4, rk4_f1, rk4_f4 -) - -__all__ = [ - "PredictorIntegrator", "CECMIntegrator", "CF4Integrator", - "CELIIntegrator", "EPCRK4Integrator", "LEQIIntegrator", - "SICELIIntegrator", "SILEQIIntegrator"] - - -class PredictorIntegrator(Integrator): - r"""Deplete using a first-order predictor algorithm. - - Implements the first-order predictor algorithm. This algorithm is - mathematically defined as: - - .. math:: - \begin{aligned} - y' &= A(y, t) y(t) \\ - A_p &= A(y_n, t_n) \\ - y_{n+1} &= \text{expm}(A_p h) y_n - \end{aligned} - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 1 - - def __call__(self, conc, rates, dt, power, _i=None): - """Perform the integration across one time step - - Parameters - ---------- - conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - _i : int or None - Iteration index. Not used - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at end of interval - op_results : empty list - Kept for consistency with API. No intermediate calls to - operator with predictor - - """ - proc_time, conc_end = timed_deplete(self.chain, conc, rates, dt) - return proc_time, [conc_end], [] - - -class CECMIntegrator(Integrator): - r"""Deplete using the CE/CM algorithm. - - Implements the second order `CE/CM predictor-corrector algorithm - `_. - - "CE/CM" stands for constant extrapolation on predictor and constant - midpoint on corrector. This algorithm is mathematically defined as: - - .. math:: - \begin{aligned} - 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 - \end{aligned} - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 2 - - def __call__(self, conc, rates, dt, power, _i=None): - """Integrate using CE/CM - - Parameters - ---------- - conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system [W] - _i : int, optional - Current iteration count. Not used - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from transport simulations - """ - # deplete across first half of inteval - time0, x_middle = timed_deplete(self.chain, conc, rates, dt / 2) - res_middle = self.operator(x_middle, power) - - # deplete across entire interval with BOS concentrations, - # MOS reaction rates - time1, x_end = timed_deplete(self.chain, conc, res_middle.rates, dt) - - return time0 + time1, [x_middle, x_end], [res_middle] - - -class CF4Integrator(Integrator): - r"""Deplete using the CF4 algorithm. - - Implements the fourth order `commutator-free Lie algorithm - `_. - This algorithm is mathematically defined as: - - .. math:: - \begin{aligned} - F_1 &= h A(y_0) \\ - y_1 &= \text{expm}(1/2 F_1) y_0 \\ - F_2 &= h A(y_1) \\ - y_2 &= \text{expm}(1/2 F_2) y_0 \\ - F_3 &= h A(y_2) \\ - y_3 &= \text{expm}(-1/2 F_1 + F_3) y_1 \\ - F_4 &= h A(y_3) \\ - y_4 &= \text{expm}( 1/4 F_1 + 1/6 F_2 + 1/6 F_3 - 1/12 F_4) - \text{expm}(-1/12 F_1 + 1/6 F_2 + 1/6 F_3 + 1/4 F_4) y_0 - \end{aligned} - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 4 - - def __call__(self, bos_conc, bos_rates, dt, power, _i=None): - """Perform the integration across one time step - - Parameters - ---------- - bos_conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - bos_rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - _i : int, optional - Current depletion step index. Not used - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulations - """ - # Step 1: deplete with matrix 1/2*A(y0) - time1, conc_eos1 = timed_deplete( - self.chain, bos_conc, bos_rates, dt, matrix_func=cf4_f1) - res1 = self.operator(conc_eos1, power) - - # Step 2: deplete with matrix 1/2*A(y1) - time2, conc_eos2 = timed_deplete( - self.chain, bos_conc, res1.rates, dt, matrix_func=cf4_f1) - res2 = self.operator(conc_eos2, power) - - # Step 3: deplete with matrix -1/2*A(y0)+A(y2) - list_rates = list(zip(bos_rates, res2.rates)) - time3, conc_eos3 = timed_deplete( - self.chain, conc_eos1, list_rates, dt, matrix_func=cf4_f2) - res3 = self.operator(conc_eos3, power) - - # Step 4: deplete with two matrix exponentials - list_rates = list(zip(bos_rates, res1.rates, res2.rates, res3.rates)) - time4, conc_inter = timed_deplete( - self.chain, bos_conc, list_rates, dt, matrix_func=cf4_f3) - time5, conc_eos5 = timed_deplete( - self.chain, conc_inter, list_rates, dt, matrix_func=cf4_f4) - - return (time1 + time2 + time3 + time4 + time5, - [conc_eos1, conc_eos2, conc_eos3, conc_eos5], - [res1, res2, res3]) - - -class CELIIntegrator(Integrator): - r"""Deplete using the CE/LI CFQ4 algorithm. - - Implements the CE/LI Predictor-Corrector algorithm using the `fourth order - commutator-free integrator `_. - - "CE/LI" stands for constant extrapolation on predictor and linear - interpolation on corrector. This algorithm is mathematically defined as: - - .. math:: - \begin{aligned} - y' &= A(y, t) y(t) \\ - A_0 &= A(y_n, t_n) \\ - y_p &= \text{expm}(h A_0) y_n \\ - A_1 &= A(y_p, t_n + h) \\ - y_{n+1} &= \text{expm}(\frac{h}{12} A_0 + \frac{5h}{12} A1) - \text{expm}(\frac{5h}{12} A_0 + \frac{h}{12} A1) y_n - \end{aligned} - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 2 - - def __call__(self, bos_conc, rates, dt, power, _i=None): - """Perform the integration across one time step - - Parameters - ---------- - bos_conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - _i : int, optional - Current iteration count. Not used - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulation - """ - # deplete to end using BOS rates - proc_time, conc_ce = timed_deplete(self.chain, bos_conc, rates, dt) - res_ce = self.operator(conc_ce, power) - - # deplete using two matrix exponentials - list_rates = list(zip(rates, res_ce.rates)) - - time_le1, conc_inter = timed_deplete( - self.chain, bos_conc, list_rates, dt, matrix_func=celi_f1) - - time_le2, conc_end = timed_deplete( - self.chain, conc_inter, list_rates, dt, matrix_func=celi_f2) - - return proc_time + time_le1 + time_le1, [conc_ce, conc_end], [res_ce] - - -class EPCRK4Integrator(Integrator): - r"""Deplete using the EPC-RK4 algorithm. - - Implements an extended predictor-corrector algorithm with traditional - Runge-Kutta 4 method. This algorithm is mathematically defined as: - - .. math:: - \begin{aligned} - F_1 &= h A(y_0) \\ - y_1 &= \text{expm}(1/2 F_1) y_0 \\ - F_2 &= h A(y_1) \\ - y_2 &= \text{expm}(1/2 F_2) y_0 \\ - F_3 &= h A(y_2) \\ - y_3 &= \text{expm}(F_3) y_0 \\ - F_4 &= h A(y_3) \\ - y_4 &= \text{expm}(1/6 F_1 + 1/3 F_2 + 1/3 F_3 + 1/6 F_4) y_0 - \end{aligned} - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 4 - - def __call__(self, conc, rates, dt, power, _i=None): - """Perform the integration across one time step - - Parameters - ---------- - conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - _i : int, optional - Current depletion step index, unused. - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulations - """ - - # Step 1: deplete with matrix A(y0) / 2 - time1, conc1 = timed_deplete( - self.chain, conc, rates, dt, matrix_func=rk4_f1) - res1 = self.operator(conc1, power) - - # Step 2: deplete with matrix A(y1) / 2 - time2, conc2 = timed_deplete( - self.chain, conc, res1.rates, dt, matrix_func=rk4_f1) - res2 = self.operator(conc2, power) - - # Step 3: deplete with matrix A(y2) - time3, conc3 = timed_deplete( - self.chain, conc, res2.rates, dt) - res3 = self.operator(conc3, power) - - # Step 4: deplete with matrix built from weighted rates - list_rates = list(zip(rates, res1.rates, res2.rates, res3.rates)) - time4, conc4 = timed_deplete( - self.chain, conc, list_rates, dt, matrix_func=rk4_f4) - - return (time1 + time2 + time3 + time4, [conc1, conc2, conc3, conc4], - [res1, res2, res3]) - - -class LEQIIntegrator(Integrator): - r"""Deplete using the LE/QI CFQ4 algorithm. - - Implements the LE/QI Predictor-Corrector algorithm using the `fourth order - commutator-free integrator `_. - - "LE/QI" stands for linear extrapolation on predictor and quadratic - interpolation on corrector. This algorithm is mathematically defined as: - - .. math:: - \begin{aligned} - y' &= A(y, t) y(t) \\ - A_{last} &= A(y_{n-1}, t_n - h_1) \\ - A_0 &= A(y_n, t_n) \\ - F_1 &= \frac{-h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+h_2)}{12h_1} A_0 \\ - F_2 &= \frac{-5h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+5h_2)}{12h_1} A_0 \\ - y_p &= \text{expm}(F_2) \text{expm}(F_1) y_n \\ - A_1 &= A(y_p, t_n + h_2) \\ - F_3 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} + - \frac{h_2 (5 h_1^2 + 6 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 + - \frac{h_2 h_1)}{12 (h_1 + h_2)} A_1 \\ - F_4 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} + - \frac{h_2 (h_1^2 + 2 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 + - \frac{h_2 (5 h_1^2 + 4 h_2 h_1)}{12 h_1 (h_1 + h_2)} A_1 \\ - y_{n+1} &= \text{expm}(F_4) \text{expm}(F_3) y_n - \end{aligned} - - It is initialized using the CE/LI algorithm. - - Parameters - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - """ - _num_stages = 2 - - def __call__(self, bos_conc, bos_rates, dt, power, i): - """Perform the integration across one time step - - Parameters - ---------- - conc : numpy.ndarray - Initial concentrations for all nuclides in [atom] - rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - i : int - Current depletion step index - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulation - """ - if i == 0: - if self._i_res < 1: # need at least previous transport solution - self._prev_rates = bos_rates - return CELIIntegrator.__call__( - self, bos_conc, bos_rates, dt, power, i) - prev_res = self.operator.prev_res[-2] - prev_dt = self.timesteps[i] - prev_res.time[0] - self._prev_rates = prev_res.rates[0] - else: - prev_dt = self.timesteps[i - 1] - - # Remaining LE/QI - bos_res = self.operator(bos_conc, power) - - le_inputs = list(zip( - self._prev_rates, bos_res.rates, repeat(prev_dt), repeat(dt))) - - time1, conc_inter = timed_deplete( - self.chain, bos_conc, le_inputs, dt, matrix_func=leqi_f1) - time2, conc_eos0 = timed_deplete( - self.chain, conc_inter, le_inputs, dt, matrix_func=leqi_f2) - - res_inter = self.operator(conc_eos0, power) - - qi_inputs = list(zip( - self._prev_rates, bos_res.rates, res_inter.rates, - repeat(prev_dt), repeat(dt))) - - time3, conc_inter = timed_deplete( - self.chain, bos_conc, qi_inputs, dt, matrix_func=leqi_f3) - time4, conc_eos1 = timed_deplete( - self.chain, conc_inter, qi_inputs, dt, matrix_func=leqi_f4) - - # store updated rates - self._prev_rates = copy.deepcopy(bos_res.rates) - - return ( - time1 + time2 + time3 + time4, [conc_eos0, conc_eos1], - [bos_res, res_inter]) - - -class SICELIIntegrator(SIIntegrator): - r"""Deplete using the SI-CE/LI CFQ4 algorithm. - - Implements the stochastic implicit CE/LI predictor-corrector algorithm - using the `fourth order commutator-free integrator - `_. - - Detailed algorithm can be found in section 3.2 in `Colin Josey's thesis - `_. - - 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, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - n_steps : int, optional - Number of stochastic iterations per depletion interval. - Must be greater than zero. Default : 10 - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - n_steps : int - Number of stochastic iterations per depletion interval - """ - _num_stages = 2 - - def __call__(self, bos_conc, bos_rates, dt, power, _i=None): - """Perform the integration across one time step - - Parameters - ---------- - bos_conc : numpy.ndarray - Initial bos_concentrations for all nuclides in [atom] - bos_rates : openmc.deplete.ReactionRates - Reaction rates from operator - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - _i : int, optional - Current depletion step index. Not used - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - bos_conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final bos_concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulations - """ - proc_time, eos_conc = timed_deplete( - self.chain, bos_conc, bos_rates, dt) - inter_conc = copy.deepcopy(eos_conc) - - # Begin iteration - for j in range(self.n_steps + 1): - inter_res = self.operator(inter_conc, power) - - if j <= 1: - res_bar = copy.deepcopy(inter_res) - else: - rates = 1/j * inter_res.rates + (1 - 1 / j) * res_bar.rates - k = 1/j * inter_res.k + (1 - 1 / j) * res_bar.k - res_bar = OperatorResult(k, rates) - - list_rates = list(zip(bos_rates, res_bar.rates)) - time1, inter_conc = timed_deplete( - self.chain, bos_conc, list_rates, dt, matrix_func=celi_f1) - time2, inter_conc = timed_deplete( - self.chain, inter_conc, list_rates, dt, matrix_func=celi_f2) - proc_time += time1 + time2 - - # end iteration - return proc_time, [eos_conc, inter_conc], [res_bar] - - -class SILEQIIntegrator(SIIntegrator): - r"""Deplete using the SI-LE/QI CFQ4 algorithm. - - Implements the Stochastic Implicit LE/QI Predictor-Corrector algorithm - using the `fourth order commutator-free integrator - `_. - - Detailed algorithm can be found in Section 3.2 in `Colin Josey's thesis - `_. - - 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, optional - 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]. Either ``power`` or ``power_density`` must be - specified. - power_density : float or iterable of float, optional - Power density of the reactor in [W/gHM]. It is multiplied by - initial heavy metal inventory to get total power if ``power`` - is not speficied. - n_steps : int, optional - Number of stochastic iterations per depletion interval. - Must be greater than zero. Default : 10 - - Attributes - ---------- - operator : openmc.deplete.TransportOperator - Operator to perform transport simulations - chain : openmc.deplete.Chain - Depletion chain - timesteps : iterable of float - Size of each depletion interval in [s] - power : iterable of float - Power of the reactor in [W] for each interval in :attr:`timesteps` - n_steps : int - Number of stochastic iterations per depletion interval - """ - _num_stages = 2 - - def __call__(self, bos_conc, bos_rates, dt, power, i): - """Perform the integration across one time step - - Parameters - ---------- - bos_conc : list of numpy.ndarray - Initial concentrations for all nuclides in [atom] for - all depletable materials - bos_rates : list of openmc.deplete.ReactionRates - Reaction rates from operator for all depletable materials - dt : float - Time in [s] for the entire depletion interval - power : float - Power of the system in [W] - i : int - Current depletion step index - - Returns - ------- - proc_time : float - Time spent in CRAM routines for all materials in [s] - conc_list : list of numpy.ndarray - Concentrations at each of the intermediate points with - the final concentration as the last element - op_results : list of openmc.deplete.OperatorResult - Eigenvalue and reaction rates from intermediate transport - simulation - """ - if i == 0: - if self._i_res < 1: - self._prev_rates = bos_rates - # Perform CELI for initial steps - return SICELIIntegrator.__call__( - self, bos_conc, bos_rates, dt, power, i) - prev_res = self.operator.prev_res[-2] - prev_dt = self.timesteps[i] - prev_res.time[0] - self._prev_rates = prev_res.rates[0] - else: - prev_dt = self.timesteps[i - 1] - - # Perform remaining LE/QI - inputs = list(zip(self._prev_rates, bos_rates, - repeat(prev_dt), repeat(dt))) - proc_time, inter_conc = timed_deplete( - self.chain, bos_conc, inputs, dt, matrix_func=leqi_f1) - time1, eos_conc = timed_deplete( - self.chain, inter_conc, inputs, dt, matrix_func=leqi_f2) - - proc_time += time1 - inter_conc = copy.deepcopy(eos_conc) - - for j in range(self.n_steps + 1): - inter_res = self.operator(inter_conc, power) - - if j <= 1: - res_bar = copy.deepcopy(inter_res) - else: - rates = 1 / j * inter_res.rates + (1 - 1 / j) * res_bar.rates - k = 1 / j * inter_res.k + (1 - 1 / j) * res_bar.k - res_bar = OperatorResult(k, rates) - - inputs = list(zip(self._prev_rates, bos_rates, res_bar.rates, - repeat(prev_dt), repeat(dt))) - time1, inter_conc = timed_deplete( - self.chain, bos_conc, inputs, dt, matrix_func=leqi_f3) - time2, inter_conc = timed_deplete( - self.chain, inter_conc, inputs, dt, matrix_func=leqi_f4) - proc_time += time1 + time2 - - return proc_time, [eos_conc, inter_conc], [res_bar] diff --git a/openmc/deplete/nuclide.py b/openmc/deplete/nuclide.py deleted file mode 100644 index ec1668dac..000000000 --- a/openmc/deplete/nuclide.py +++ /dev/null @@ -1,570 +0,0 @@ -"""Nuclide module. - -Contains the per-nuclide components of a depletion chain. -""" - -import bisect -from collections.abc import Mapping -from collections import namedtuple, defaultdict -from warnings import warn -from numbers import Real -try: - import lxml.etree as ET -except ImportError: - import xml.etree.ElementTree as ET - -from numpy import empty - -from openmc.checkvalue import check_type - -__all__ = [ - "DecayTuple", "ReactionTuple", "Nuclide", "FissionYield", - "FissionYieldDistribution"] - - -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. - - Parameters - ---------- - name : str, optional - GND name of this nuclide, e.g. ``"He4"``, ``"Am242_m1"`` - - Attributes - ---------- - name : str or None - Name of nuclide. - half_life : float or None - 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 : FissionYieldDistribution or None - Fission product yields at tabulated energies for this nuclide. Can be - treated as a nested dictionary ``{energy: {product: yield}}`` - yield_energies : tuple of float or None - Energies at which fission product yields exist - """ - - def __init__(self, name=None): - # Information about the nuclide - self.name = name - 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 = None - - @property - def n_decay_modes(self): - return len(self.decay_modes) - - @property - def n_reaction_paths(self): - return len(self.reactions) - - @property - def yield_data(self): - if self._yield_data is None: - return None - return self._yield_data - - @yield_data.setter - def yield_data(self, fission_yields): - if fission_yields is None: - self._yield_data = None - else: - check_type("fission_yields", fission_yields, Mapping) - if isinstance(fission_yields, FissionYieldDistribution): - self._yield_data = fission_yields - else: - self._yield_data = FissionYieldDistribution(fission_yields) - - @property - def yield_energies(self): - if self._yield_data is None: - return None - return self.yield_data.energies - - @classmethod - def from_xml(cls, element, fission_q=None): - """Read nuclide from an XML element. - - Parameters - ---------- - element : xml.etree.ElementTree.Element - XML element to write nuclide data to - fission_q : None or float - User-supplied fission Q value [eV]. - Will be read from the element if not given - - 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 - if fission_q is not None: - Q = fission_q - - # 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: - nuc.yield_data = FissionYieldDistribution.from_xml_element(fpy_elem) - - 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) - self.yield_data.to_xml_element(fpy_elem) - - return elem - - def validate(self, strict=True, quiet=False, tolerance=1e-4): - """Search for possible inconsistencies - - The following checks are performed: - - 1) for all non-fission reactions and decay modes, - does the sum of branching ratios equal about one? - 2) for fission reactions, does the sum of fission yield - fractions equal about two? - - Parameters - ---------- - strict : bool, optional - Raise exceptions at the first inconsistency if true. - Otherwise mark a warning - quiet : bool, optional - Flag to suppress warnings and return immediately at - the first inconsistency. Used only if - ``strict`` does not evaluate to ``True``. - tolerance : float, optional - Absolute tolerance for comparisons. Used to compare computed - value ``x`` to intended value ``y`` as:: - - valid = (y - tolerance <= x <= y + tolerance) - - Returns - ------- - valid : bool - True if no inconsistencies were found - - Raises - ------ - ValueError - If ``strict`` evaluates to ``True`` and an inconistency was - found - - See Also - -------- - openmc.deplete.Chain.validate - """ - - msg_func = ("Nuclide {name} has {prop} that sum to {actual} " - "instead of {expected} +/- {tol:7.4e}").format - valid = True - - # check decay modes - if self.decay_modes: - sum_br = sum(m.branching_ratio for m in self.decay_modes) - stat = 1.0 - tolerance <= sum_br <= 1.0 + tolerance - if not stat: - msg = msg_func( - name=self.name, actual=sum_br, expected=1.0, tol=tolerance, - prop="decay mode branch ratios") - if strict: - raise ValueError(msg) - elif quiet: - return False - warn(msg) - valid = False - - if self.reactions: - type_map = defaultdict(set) - for reaction in self.reactions: - type_map[reaction.type].add(reaction) - for rxn_type, reactions in type_map.items(): - sum_rxn = sum(rx.branching_ratio for rx in reactions) - stat = 1.0 - tolerance <= sum_rxn <= 1.0 + tolerance - if stat: - continue - msg = msg_func( - name=self.name, actual=sum_br, expected=1.0, tol=tolerance, - prop="{} reaction branch ratios".format(rxn_type)) - if strict: - raise ValueError(msg) - elif quiet: - return False - warn(msg) - valid = False - - if self.yield_data: - for energy, fission_yield in self.yield_data.items(): - sum_yield = fission_yield.yields.sum() - stat = 2.0 - tolerance <= sum_yield <= 2.0 + tolerance - if stat: - continue - msg = msg_func( - name=self.name, actual=sum_yield, - expected=2.0, tol=tolerance, - prop="fission yields (E = {:7.4e} eV)".format(energy)) - if strict: - raise ValueError(msg) - elif quiet: - return False - warn(msg) - valid = False - - return valid - - -class FissionYieldDistribution(Mapping): - """Energy-dependent fission product yields for a single nuclide - - Can be used as a dictionary mapping energies and products to fission - yields:: - - >>> fydist = FissionYieldDistribution{ - ... {0.0253: {"Xe135": 0.021}}) - >>> fydist[0.0253]["Xe135"] - 0.021 - - Parameters - ---------- - fission_yields : dict - Dictionary of energies and fission product yields for that energy. - Expected to be of the form ``{float: {str: float}}``. The first - float is the energy, typically in eV, that represents this - distribution. The underlying dictionary maps fission products - to their respective yields. - - Attributes - ---------- - energies : tuple - Energies for which fission yields exist. Sorted by - increasing energy - products : tuple - Fission products produced at all energies. Sorted by name. - yield_matrix : numpy.ndarray - Array ``(n_energy, n_products)`` where - ``yield_matrix[g, j]`` is the fission yield of product - ``j`` for energy group ``g``. - - See Also - -------- - * :meth:`from_xml_element` - Construction methods - * :class:`FissionYield` - Class used for storing yields at a given energy - """ - - def __init__(self, fission_yields): - # mapping {energy: {product: value}} - energies = sorted(fission_yields) - - # Get a consistent set of products to produce a matrix of yields - shared_prod = set.union(*(set(x) for x in fission_yields.values())) - ordered_prod = sorted(shared_prod) - - yield_matrix = empty((len(energies), len(shared_prod))) - - for g_index, energy in enumerate(energies): - prod_map = fission_yields[energy] - for prod_ix, product in enumerate(ordered_prod): - yield_val = prod_map.get(product) - yield_matrix[g_index, prod_ix] = ( - 0.0 if yield_val is None else yield_val) - self.energies = tuple(energies) - self.products = tuple(ordered_prod) - self.yield_matrix = yield_matrix - - def __len__(self): - return len(self.energies) - - def __getitem__(self, energy): - if energy not in self.energies: - raise KeyError(energy) - return FissionYield( - self.products, self.yield_matrix[self.energies.index(energy)]) - - def __iter__(self): - return iter(self.energies) - - def __repr__(self): - return "<{} with {} products at {} energies>".format( - self.__class__.__name__, self.yield_matrix.shape[1], - len(self.energies)) - - @classmethod - def from_xml_element(cls, element): - """Construct a distribution from a depletion chain xml file - - Parameters - ---------- - element : xml.etree.ElementTree.Element - XML element to pull fission yield data from - - Returns - ------- - FissionYieldDistribution - """ - all_yields = {} - for elem_index, yield_elem in enumerate(element.iter("fission_yields")): - energy = float(yield_elem.get("energy")) - products = yield_elem.find("products").text.split() - yields = map(float, yield_elem.find("data").text.split()) - # Get a map of products to their corresponding yield - all_yields[energy] = dict(zip(products, yields)) - - return cls(all_yields) - - def to_xml_element(self, root): - """Write fission yield data to an xml element - - Parameters - ---------- - root : xml.etree.ElementTree.Element - Element to write distribution data to - """ - for energy, yield_obj in self.items(): - yield_element = ET.SubElement(root, "fission_yields") - yield_element.set("energy", str(energy)) - product_elem = ET.SubElement(yield_element, "products") - product_elem.text = " ".join(map(str, yield_obj.products)) - data_elem = ET.SubElement(yield_element, "data") - data_elem.text = " ".join(map(str, yield_obj.yields)) - - -class FissionYield(Mapping): - """Mapping for fission yields of a parent at a specific energy - - Separated to support nested dictionary-like behavior for - :class:`FissionYieldDistribution`, and allowing math operations - on a single vector of yields. Can in turn be used like a - dictionary to fetch fission yields. - Supports multiplication of a scalar to scale the fission - yields and addition of another set of yields. - - Does not support resizing / inserting new products that do - not exist. - - Parameters - ---------- - products : tuple of str - Products for this specific distribution - yields : numpy.ndarray - Fission product yields for each product in ``products`` - - Attributes - ---------- - products : tuple of str - Products for this specific distribution - yields : numpy.ndarray - Fission product yields for each product in ``products`` - - Examples - -------- - >>> import numpy - >>> fy_vector = FissionYield( - ... ("Xe135", "I129", "Sm149"), - ... numpy.array((0.002, 0.001, 0.0003))) - >>> fy_vector["Xe135"] - 0.002 - >>> new = fy_vector.copy() - >>> fy_vector *= 2 - >>> fy_vector["Xe135"] - 0.004 - >>> new["Xe135"] - 0.002 - >>> (new + fy_vector)["Sm149"] - 0.0009 - >>> dict(new) - {"Xe135": 0.002, "I129": 0.001, "Sm149": 0.0003} - """ - - def __init__(self, products, yields): - self.products = products - self.yields = yields - - def __contains__(self, product): - ix = bisect.bisect_left(self.products, product) - return ix != len(self.products) and self.products[ix] == product - - def __getitem__(self, product): - ix = bisect.bisect_left(self.products, product) - if ix == len(self.products) or self.products[ix] != product: - raise KeyError(product) - return self.yields[ix] - - def __len__(self): - return len(self.products) - - def __iter__(self): - return iter(self.products) - - def items(self): - """Return pairs of product, yield""" - return zip(self.products, self.yields) - - def __add__(self, other): - if not isinstance(other, FissionYield): - return NotImplemented - new = FissionYield(self.products, self.yields.copy()) - new += other - return new - - def __iadd__(self, other): - """Increment value from other fission yield""" - if not isinstance(other, FissionYield): - return NotImplemented - self.yields += other.yields - return self - - def __radd__(self, other): - return self + other - - def __imul__(self, scalar): - if not isinstance(scalar, Real): - return NotImplemented - self.yields *= scalar - return self - - def __mul__(self, scalar): - if not isinstance(scalar, Real): - return NotImplemented - new = FissionYield(self.products, self.yields.copy()) - new *= scalar - return new - - def __rmul__(self, scalar): - return self * scalar - - def __repr__(self): - return "<{} containing {} products and yields>".format( - self.__class__.__name__, len(self)) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py deleted file mode 100644 index e3a767e57..000000000 --- a/openmc/deplete/operator.py +++ /dev/null @@ -1,743 +0,0 @@ -"""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 sys -import copy -from collections import OrderedDict -from itertools import chain -import os -import time -import xml.etree.ElementTree as ET -from warnings import warn - -import h5py -import numpy as np -from uncertainties import ufloat - -import openmc -import openmc.lib -from . import comm -from .abc import TransportOperator, OperatorResult -from .atom_number import AtomNumber -from .reaction_rates import ReactionRates -from .results_list import ResultsList -from .helpers import ( - DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper, - FissionYieldCutoffHelper, AveragedFissionYieldHelper, EnergyScoreHelper) - - -__all__ = ["Operator", "OperatorResult"] - - -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 - class, such as :class:`openmc.deplete.CECMIntegrator`. - - 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 file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. - prev_results : ResultsList, optional - Results from a previous depletion calculation. If this argument is - specified, the depletion calculation will start from the latest state - in the previous results. - diff_burnable_mats : bool, optional - Whether to differentiate burnable materials with multiple instances. - Default: False. - energy_mode : {"energy-deposition", "fission-q"} - Indicator for computing system energy. ``"energy-deposition"`` will - compute with a single energy deposition tally, taking fission energy - release data and heating into consideration. ``"fission-q"`` will - use the fission Q values from the depletion chain - fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. If not given, - values will be pulled from the ``chain_file``. Only applicable - if ``"energy_mode" == "fission-q"`` - dilute_initial : float, optional - Initial atom density [atoms/cm^3] 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. - fission_yield_mode : {"constant", "cutoff", "average"} - Key indicating what fission product yield scheme to use. The - key determines what fission energy helper is used: - - * "constant": :class:`~openmc.deplete.helpers.ConstantFissionYieldHelper` - * "cutoff": :class:`~openmc.deplete.helpers.FissionYieldCutoffHelper` - * "average": :class:`~openmc.deplete.helpers.AveragedFissionYieldHelper` - - The documentation on these classes describe their methodology - and differences. Default: ``"constant"`` - fission_yield_opts : dict of str to option, optional - Optional arguments to pass to the helper determined by - ``fission_yield_mode``. Will be passed directly on to the - helper. Passing a value of None will use the defaults for - the associated helper. - - Attributes - ---------- - geometry : openmc.Geometry - OpenMC geometry object - settings : openmc.Settings - OpenMC settings object - dilute_initial : float - Initial atom density [atoms/cm^3] 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. - 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 - heavy_metal : float - Initial heavy metal inventory [g] - local_mats : list of str - All burnable material IDs being managed by a single process - prev_res : ResultsList or None - Results from a previous depletion calculation. ``None`` if no - results are to be used. - diff_burnable_mats : bool - Whether to differentiate burnable materials with multiple instances - """ - _fission_helpers = { - "average": AveragedFissionYieldHelper, - "constant": ConstantFissionYieldHelper, - "cutoff": FissionYieldCutoffHelper, - } - - def __init__(self, geometry, settings, chain_file=None, prev_results=None, - diff_burnable_mats=False, energy_mode="fission-q", - fission_q=None, dilute_initial=1.0e3, - fission_yield_mode="constant", fission_yield_opts=None): - if fission_yield_mode not in self._fission_helpers: - raise KeyError( - "fission_yield_mode must be one of {}, not {}".format( - ", ".join(self._fission_helpers), fission_yield_mode)) - if energy_mode == "energy-deposition": - if fission_q is not None: - warn("Fission Q dictionary not used if energy deposition " - "is used") - fission_q = None - elif energy_mode != "fission-q": - raise ValueError( - "energy_mode {} not supported. Must be energy-deposition " - "or fission-q".format(energy_mode)) - super().__init__(chain_file, fission_q, dilute_initial, prev_results) - self.round_number = False - self.prev_res = None - self.settings = settings - self.geometry = geometry - self.diff_burnable_mats = diff_burnable_mats - - # Differentiate burnable materials with multiple instances - if self.diff_burnable_mats: - self._differentiate_burnable_mats() - - # 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) - - # Generate map from local materials => material index - self._mat_index_map = { - lm: self.burnable_mats.index(lm) for lm in self.local_mats} - - if self.prev_res is not None: - # Reload volumes into geometry - prev_results[-1].transfer_volumes(geometry) - - # Store previous results in operator - # Distribute reaction rates according to those tracked - # on this process - if comm.size == 1: - self.prev_res = prev_results - else: - self.prev_res = ResultsList() - mat_indexes = _distribute(range(len(self.burnable_mats))) - for res_obj in prev_results: - new_res = res_obj.distribute(self.local_mats, mat_indexes) - self.prev_res.append(new_res) - - # Determine which nuclides have incident neutron data - self.nuclides_with_data = self._get_nuclides_with_data() - - # Select nuclides with data that are also in the chain - self._burnable_nucs = [nuc.name for nuc in self.chain.nuclides - if nuc.name in self.nuclides_with_data] - - # Extract number densities from the geometry / previous depletion run - self._extract_number(self.local_mats, volume, nuclides, self.prev_res) - - # Create reaction rates array - self.reaction_rates = ReactionRates( - self.local_mats, self._burnable_nucs, self.chain.reactions) - - # Get classes to assist working with tallies - self._rate_helper = DirectReactionRateHelper( - self.reaction_rates.n_nuc, self.reaction_rates.n_react) - if energy_mode == "fission-q": - self._energy_helper = ChainFissionHelper() - else: - score = "heating" if settings.photon_transport else "heating-local" - self._energy_helper = EnergyScoreHelper(score) - - # Select and create fission yield helper - fission_helper = self._fission_helpers[fission_yield_mode] - fission_yield_opts = ( - {} if fission_yield_opts is None else fission_yield_opts) - self._yield_helper = fission_helper.from_operator( - self, **fission_yield_opts) - - def __call__(self, vec, power): - """Runs a simulation. - - Simulation will abort under the following circumstances: - - 1) No energy is computed using OpenMC tallies. - - Parameters - ---------- - vec : list of numpy.ndarray - Total atoms to be used in function. - power : float - Power of the reactor in [W] - - 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) - - # Update material compositions and tally nuclides - self._update_materials() - nuclides = self._get_tally_nuclides() - self._rate_helper.nuclides = nuclides - self._energy_helper.nuclides = nuclides - self._yield_helper.update_tally_nuclides(nuclides) - - # Run OpenMC - openmc.lib.reset() - openmc.lib.run() - - # Extract results - op_result = self._unpack_tallies_and_normalize(power) - - return copy.deepcopy(op_result) - - @staticmethod - def write_bos_data(step): - """Write a state-point file with beginning of step data - - Parameters - ---------- - step : int - Current depletion step including restarts - """ - openmc.lib.statepoint_write( - "openmc_simulation_n{}.h5".format(step), - write_source=False) - - def _differentiate_burnable_mats(self): - """Assign distribmats for each burnable material - - """ - - # Count the number of instances for each cell and material - self.geometry.determine_paths(instances_only=True) - - # Extract all burnable materials which have multiple instances - distribmats = set( - [mat for mat in self.geometry.get_all_materials().values() - if mat.depletable and mat.num_instances > 1]) - - if distribmats: - # Assign distribmats to cells - for cell in self.geometry.get_all_material_cells().values(): - if cell.fill in distribmats and cell.num_instances > 1: - cell.fill = [cell.fill.clone() - for i in range(cell.num_instances)] - - def _get_burnable_mats(self): - """Determine depletable materials, volumes, and nuclides - - 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() - - self.heavy_metal = 0.0 - - # 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 - self.heavy_metal += mat.fissionable_mass - - # 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, prev_res=None): - """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. - prev_res : ResultsList, optional - Results from a previous depletion calculation - - """ - 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 and store the number densities - # From the geometry if no previous depletion results - if prev_res is None: - for mat in self.geometry.get_all_materials().values(): - if str(mat.id) in local_mats: - self._set_number_from_mat(mat) - - # Else from previous depletion results - else: - for mat in self.geometry.get_all_materials().values(): - if str(mat.id) in local_mats: - self._set_number_from_results(mat, prev_res) - - 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 _set_number_from_results(self, mat, prev_res): - """Extracts material nuclides and number densities. - - If the nuclide concentration's evolution is tracked, the densities come - from depletion results. Else, densities are extracted from the geometry - in the summary. - - Parameters - ---------- - mat : openmc.Material - The material to read from - prev_res : ResultsList - Results from a previous depletion calculation - - """ - mat_id = str(mat.id) - - # Get nuclide lists from geometry and depletion results - depl_nuc = prev_res[-1].nuc_to_ind - geom_nuc_densities = mat.get_nuclide_atom_densities() - - # Merge lists of nuclides, with the same order for every calculation - geom_nuc_densities.update(depl_nuc) - - for nuclide in geom_nuc_densities.keys(): - if nuclide in depl_nuc: - concentration = prev_res.get_atoms(mat_id, nuclide)[1][-1] - volume = prev_res[-1].volume[mat_id] - number = concentration / volume - else: - density = geom_nuc_densities[nuclide][1] - 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.lib.init(intracomm=comm) - - # Generate tallies in memory - materials = [openmc.lib.materials[int(i)] - for i in self.burnable_mats] - self._rate_helper.generate_tallies(materials, self.chain.reactions) - self._energy_helper.prepare( - self.chain.nuclides, self.reaction_rates.index_nuc, materials) - # Tell fission yield helper what materials this process is - # responsible for - self._yield_helper.generate_tallies( - materials, tuple(sorted(self._mat_index_map.values()))) - - # Return number density vector - return list(self.number.get_mat_slice(np.s_[:])) - - def finalize(self): - """Finalize a depletion simulation and release resources.""" - openmc.lib.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 - - # Update densities on C API side - mat_internal = openmc.lib.materials[int(mat)] - mat_internal.set_densities(nuclides, densities) - - #TODO Update densities on the Python side, otherwise the - # summary.h5 file contains densities at the first time step - - 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 _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.fill(0.0) - - # Get k and uncertainty - k_combined = ufloat(*openmc.lib.keff()) - - # Extract tally bins - nuclides = self._rate_helper.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 - - # Keep track of energy produced from all reactions in eV per source - # particle - self._energy_helper.reset() - self._yield_helper.unpack() - - # Store fission yield dictionaries - fission_yields = [] - - # Create arrays to store fission Q values, reaction rates, and nuclide - # numbers, zeroed out in material iteration - number = np.empty(rates.n_nuc) - - fission_ind = rates.index_rx["fission"] - - # Extract results - for i, mat in enumerate(self.local_mats): - # Get tally index - mat_index = self._mat_index_map[mat] - - # Zero out reaction rates and nuclide numbers - number.fill(0.0) - - # Get new number densities - for nuc, i_nuc_results in zip(nuclides, nuc_ind): - number[i_nuc_results] = self.number[mat, nuc] - - tally_rates = self._rate_helper.get_material_rates( - mat_index, nuc_ind, react_ind) - - # Compute fission yields for this material - fission_yields.append(self._yield_helper.weighted_yields(i)) - - # Accumulate energy from fission - self._energy_helper.update(tally_rates[:, fission_ind], mat_index) - - # Divide by total number and store - rates[i] = self._rate_helper.divide_by_adens(number) - - # Reduce energy produced from all processes - # J / s / source neutron - energy = comm.allreduce(self._energy_helper.energy) - - # Guard against divide by zero - if energy == 0: - if comm.rank == 0: - sys.stderr.flush() - print(" No energy reported from OpenMC tallies. Do your HDF5 " - "files have heating data?\n", file=sys.stderr, flush=True) - comm.barrier() - comm.Abort(1) - - # Scale reaction rates to obtain units of reactions/sec - rates *= power / energy - - # Store new fission yields on the chain - self.chain.fission_yields = fission_yields - - 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 diff --git a/openmc/deplete/reaction_rates.py b/openmc/deplete/reaction_rates.py deleted file mode 100644 index 85c8d8998..000000000 --- a/openmc/deplete/reaction_rates.py +++ /dev/null @@ -1,153 +0,0 @@ -"""ReactionRates module. - -An ndarray to store reaction rates with string, integer, or slice indexing. -""" -from collections import OrderedDict - -import numpy as np - - -__all__ = ["ReactionRates"] - - -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 - from_results : boolean - If the reaction rates are loaded from results, indexing dictionnaries - need to be kept the same. - - 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, from_results=False): - # 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, keep same indexing if from depletion_results - if from_results: - obj.index_mat = local_mats - obj.index_nuc = nuclides - obj.index_rx = reactions - # Else, assumes that reaction rates are ordered the same way as - # the lists of local_mats, nuclides and reactions (or keys if these - # are dictionnaries) - else: - 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 diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py deleted file mode 100644 index b44739bc5..000000000 --- a/openmc/deplete/results.py +++ /dev/null @@ -1,496 +0,0 @@ -"""The results module. - -Contains results generation and saving capabilities. -""" - -from collections import OrderedDict -import copy -from warnings import warn - -import numpy as np -import h5py - -from . import comm, have_mpi, MPI -from .reaction_rates import ReactionRates - -_VERSION_RESULTS = (1, 0) - - -__all__ = ["Results"] - - -class Results(object): - """Output of a depletion run - - Attributes - ---------- - k : list of (float, float) - Eigenvalue and uncertainty for each substep. - time : list of float - Time at beginning, end of step, in seconds. - power : float - Power during time step, in Watts - 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. - proc_time: int - Average time spent depleting a material across all - materials and processes - - """ - def __init__(self): - self.k = None - self.time = None - self.power = None - self.rates = None - self.volume = None - self.proc_time = 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 distribute(self, local_materials, ranges): - """Create a new object containing data for distributed materials - - Parameters - ---------- - local_materials : iterable of str - Materials for this process - ranges : iterable of int - Slice-like object indicating indicies of ``local_materials`` - in the material dimension of :attr:`data` and each element - in :attr:`rates` - - Returns - ------- - Results - New results object - """ - new = Results() - new.volume = {lm: self.volume[lm] for lm in local_materials} - new.mat_to_ind = dict(zip( - local_materials, range(len(local_materials)))) - # Direct transfer - direct_attrs = ("time", "k", "power", "nuc_to_ind", - "mat_to_hdf5_ind", "proc_time") - for attr in direct_attrs: - setattr(new, attr, getattr(self, attr)) - # Get applicable slice of data - new.data = self.data[:, ranges] - new.rates = [r[ranges] for r in self.rates] - return new - - 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 = {} - - # Write new file if first time step, else add to existing file - 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, 2), - maxshape=(None, n_stages, 2), dtype='float64') - - handle.create_dataset("time", (1, 2), maxshape=(None, 2), dtype='float64') - - handle.create_dataset("power", (1, n_stages), maxshape=(None, n_stages), - dtype='float64') - - handle.create_dataset( - "depletion time", (1,), maxshape=(None,), - 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"] - power_dset = handle["/power"] - proc_time_dset = handle["/depletion 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) - - power_shape = list(power_dset.shape) - power_shape[0] = new_shape - power_dset.resize(power_shape) - - proc_shape = list(proc_time_dset.shape) - proc_shape[0] = new_shape - proc_time_dset.resize(proc_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 - power_dset[index, :] = self.power - if self.proc_time is not None: - proc_time_dset[index] = ( - self.proc_time / (comm.size * self.n_hdf5_mats) - ) - - @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 - Index for depletion step - """ - results = cls() - - # Grab handles - number_dset = handle["/number"] - eigenvalues_dset = handle["/eigenvalues"] - time_dset = handle["/time"] - power_dset = handle["/power"] - - results.data = number_dset[step, :, :, :] - results.k = eigenvalues_dset[step, :] - results.time = time_dset[step, :] - results.power = power_dset[step, :] - - if "depletion time" in handle: - proc_time_dset = handle["/depletion time"] - if step < proc_time_dset.shape[0]: - results.proc_time = proc_time_dset[step] - - if results.proc_time is None: - results.proc_time = np.array([np.nan]) - - # 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, True) - - rate[:] = handle["/reaction rates"][step, i, :, :, :] - results.rates.append(rate) - - return results - - @staticmethod - def save(op, x, op_results, t, power, step_ind, proc_time=None): - """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. - power : float - Power during time step - step_ind : int - Step index. - proc_time : float or None - Total process time spent depleting materials. This may - be process-dependent and will be reduced across MPI - processes. - - """ - # Get indexing terms - vol_dict, nuc_list, burn_list, full_burn_list = op.get_results_info() - - stages = len(x) - - # Create results - 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.nominal_value, r.k.std_dev) for r in op_results] - results.rates = [r.rates for r in op_results] - results.time = t - results.power = power - results.proc_time = proc_time - if results.proc_time is not None: - results.proc_time = comm.reduce(proc_time, op=MPI.SUM) - - results.export_to_hdf5("depletion_results.h5", step_ind) - - def transfer_volumes(self, geometry): - """Transfers volumes from depletion results to geometry - - Parameters - ---------- - geometry : OpenMC geometry to be used in a depletion restart - calculation - - """ - for cell in geometry.get_all_material_cells().values(): - for material in cell.get_all_materials().values(): - if material.depletable: - material.volume = self.volume[str(material.id)] diff --git a/openmc/deplete/results_list.py b/openmc/deplete/results_list.py deleted file mode 100644 index 1b5b81ac4..000000000 --- a/openmc/deplete/results_list.py +++ /dev/null @@ -1,167 +0,0 @@ -import h5py -import numpy as np - -from .results import Results, _VERSION_RESULTS -from openmc.checkvalue import check_filetype_version - - -__all__ = ["ResultsList"] - - -class ResultsList(list): - """A list of openmc.deplete.Results objects - - It is recommended to use :meth:`from_hdf5` over - direct creation. - """ - - @classmethod - def from_hdf5(cls, filename): - """Load in depletion results from a previous file - - Parameters - ---------- - filename : str - Path to depletion result file - - Returns - ------- - new : ResultsList - New instance of depletion results - """ - with h5py.File(str(filename), "r") as fh: - check_filetype_version(fh, 'depletion results', _VERSION_RESULTS[0]) - new = cls() - - # Get number of results stored - n = fh["number"][...].shape[0] - - for i in range(n): - new.append(Results.from_hdf5(fh, i)) - return new - - def get_atoms(self, mat, nuc): - """Get number of nuclides over time from a single material - - .. note:: - - Initial values for some isotopes that do not appear in - initial concentrations may be non-zero, depending on the - value of :class:`openmc.deplete.Operator` ``dilute_initial``. - The :class:`openmc.deplete.Operator` adds isotopes according - to this setting, which can be set to zero. - - 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, dtype=float) - concentration = np.empty_like(self, dtype=float) - - # 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 - - .. note:: - - Initial values for some isotopes that do not appear in - initial concentrations may be non-zero, depending on the - value of :class:`openmc.deplete.Operator` ``dilute_initial`` - The :class:`openmc.deplete.Operator` adds isotopes according - to this setting, which can be set to zero. - - 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, dtype=float) - rate = np.empty_like(self, dtype=float) - - # 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. Column 0 - contains the eigenvalue, while column - 1 contains the associated uncertainty - - """ - time = np.empty_like(self, dtype=float) - eigenvalue = np.empty((len(self), 2), dtype=float) - - # 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 - - def get_depletion_time(self): - """Return an array of the average time to deplete a material - - .. note:: - - Will have one fewer row than number of other methods, - like :meth:`get_eigenvalues`, because no depletion - is performed at the final transport stage - - Returns - ------- - times : :class:`numpy.ndarray` - Vector of average time to deplete a single material - across all processes and materials. - - """ - times = np.empty(len(self) - 1) - # Need special logic because the predictor - # writes EOS values for step i as BOS values - # for step i+1 - # The first proc_time may be zero - if self[0].proc_time > 0.0: - items = self[:-1] - else: - items = self[1:] - for ix, res in enumerate(items): - times[ix] = res.proc_time - return times diff --git a/openmc/element.py b/openmc/element.py deleted file mode 100644 index 5b2a878a8..000000000 --- a/openmc/element.py +++ /dev/null @@ -1,208 +0,0 @@ -from collections import OrderedDict -import re -import os -from xml.etree import ElementTree as ET - -import openmc -import openmc.checkvalue as cv -from openmc.data import NATURAL_ABUNDANCE, atomic_mass - - -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 - is created. - - Parameters - ---------- - name : str - Chemical symbol of the element, e.g. Pu - - Attributes - ---------- - name : str - Chemical symbol of the element, e.g. Pu - - """ - - 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 - - def expand(self, percent, percent_type, enrichment=None, - cross_sections=None): - """Expand natural element into its naturally-occurring isotopes. - - An optional cross_sections argument or the OPENMC_CROSS_SECTIONS - environment variable is used to specify a cross_sections.xml file. - If the cross_sections.xml file is found, the element is expanded only - into the isotopes/nuclides present in cross_sections.xml. If no - cross_sections.xml file is found, the element is expanded based on its - naturally occurring isotopes. - - Parameters - ---------- - percent : float - Atom or weight percent - percent_type : {'ao', 'wo'} - 'ao' for atom percent and 'wo' for weight percent - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - cross_sections : str, optional - Location of cross_sections.xml file. Default is None. - - Returns - ------- - isotopes : list - Naturally-occurring isotopes of the element. Each item of the list - is a tuple consisting of a nuclide string, the atom/weight percent, - and the string 'ao' or 'wo'. - - Notes - ----- - When the `enrichment` argument is specified, a correlation from - `ORNL/CSD/TM-244 `_ is used to - calculate the weight fractions of U234, U235, U236, and U238. Namely, - the weight fraction of U234 and U236 are taken to be 0.89% and 0.46%, - respectively, of the U235 weight fraction. The remainder of the isotopic - weight is assigned to U238. - - """ - - # Get the nuclides present in nature - natural_nuclides = set() - for nuclide in sorted(NATURAL_ABUNDANCE.keys()): - if re.match(r'{}\d+'.format(self), nuclide): - natural_nuclides.add(nuclide) - - # Create dict to store the expanded nuclides and abundances - abundances = OrderedDict() - - # If cross_sections is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable - if cross_sections is None: - cross_sections = os.environ.get('OPENMC_CROSS_SECTIONS') - - # If a cross_sections library is present, check natural nuclides - # against the nuclides in the library - if cross_sections is not None: - - library_nuclides = set() - tree = ET.parse(cross_sections) - root = tree.getroot() - for child in root.findall('library'): - nuclide = child.attrib['materials'] - if re.match(r'{}\d+'.format(self), nuclide) and \ - '_m' not in nuclide: - library_nuclides.add(nuclide) - - # Get a set of the mutual and absent nuclides. Convert to lists - # and sort to avoid different ordering between Python 2 and 3. - mutual_nuclides = natural_nuclides.intersection(library_nuclides) - absent_nuclides = natural_nuclides.difference(mutual_nuclides) - mutual_nuclides = sorted(list(mutual_nuclides)) - absent_nuclides = sorted(list(absent_nuclides)) - - # If all natural nuclides are present in the library, expand element - # using all natural nuclides - if len(absent_nuclides) == 0: - for nuclide in mutual_nuclides: - abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] - - # If no natural elements are present in the library, check if the - # 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 + '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) - raise ValueError(msg) - - # If some, but not all, natural nuclides are in the library, add - # the mutual nuclides. For the absent nuclides, add them based on - # our knowledge of the common cross section libraries - # (ENDF, JEFF, and JENDL) - else: - - # Add the mutual isotopes - for nuclide in mutual_nuclides: - abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] - - # Adjust the abundances for the absent nuclides - for nuclide in absent_nuclides: - - if nuclide in ['O17', 'O18'] and 'O16' in mutual_nuclides: - abundances['O16'] += NATURAL_ABUNDANCE[nuclide] - elif nuclide == 'Ta180' and 'Ta181' in mutual_nuclides: - abundances['Ta181'] += NATURAL_ABUNDANCE[nuclide] - elif nuclide == 'W180' and 'W182' in mutual_nuclides: - abundances['W182'] += NATURAL_ABUNDANCE[nuclide] - else: - msg = 'Unsure how to partition natural abundance of ' \ - 'isotope {0} into other natural isotopes of ' \ - 'this element that are present in the cross ' \ - 'section library provided. Consider adding ' \ - 'the isotopes of this element individually.' - raise ValueError(msg) - - # If a cross_section library is not present, expand the element into - # its natural nuclides - else: - for nuclide in natural_nuclides: - abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] - - # Modify mole fractions if enrichment provided - if enrichment is not None: - - # Calculate the mass fractions of isotopes - abundances['U234'] = 0.0089 * enrichment - abundances['U235'] = enrichment - abundances['U236'] = 0.0046 * enrichment - abundances['U238'] = 100.0 - 1.0135 * enrichment - - # Convert the mass fractions to mole fractions - for nuclide in abundances.keys(): - abundances[nuclide] /= atomic_mass(nuclide) - - # Normalize the mole fractions to one - sum_abundances = sum(abundances.values()) - for nuclide in abundances.keys(): - abundances[nuclide] /= sum_abundances - - # Compute the ratio of the nuclide atomic masses to the element - # atomic mass - if percent_type == 'wo': - - # Compute the element atomic mass - element_am = 0. - for nuclide in abundances.keys(): - element_am += atomic_mass(nuclide) * abundances[nuclide] - - # Convert the molar fractions to mass fractions - for nuclide in abundances.keys(): - abundances[nuclide] *= atomic_mass(nuclide) / element_am - - # Normalize the mass fractions to one - sum_abundances = sum(abundances.values()) - for nuclide in abundances.keys(): - abundances[nuclide] /= sum_abundances - - # Create a list of the isotopes in this element - isotopes = [] - for nuclide, abundance in abundances.items(): - isotopes.append((nuclide, percent * abundance, percent_type)) - - return isotopes diff --git a/openmc/examples.py b/openmc/examples.py deleted file mode 100644 index 4e8c8cf92..000000000 --- a/openmc/examples.py +++ /dev/null @@ -1,642 +0,0 @@ -from numbers import Integral - -import numpy as np - -import openmc -import openmc.model - - -def pwr_pin_cell(): - """Create a PWR pin-cell model. - - This model is a single fuel pin with 2.4 w/o enriched UO2 corresponding to a - beginning-of-cycle condition and borated water. The specifications are from - the `BEAVRS `_ benchmark. Note that the - number of particles/batches is initially set very low for testing purposes. - - Returns - ------- - model : openmc.model.Model - A PWR pin-cell model - - """ - model = openmc.model.Model() - - # Define materials. - fuel = openmc.Material(name='UO2 (2.4%)') - fuel.set_density('g/cm3', 10.29769) - fuel.add_nuclide("U234", 4.4843e-6) - fuel.add_nuclide("U235", 5.5815e-4) - fuel.add_nuclide("U238", 2.2408e-2) - fuel.add_nuclide("O16", 4.5829e-2) - - clad = openmc.Material(name='Zircaloy') - clad.set_density('g/cm3', 6.55) - clad.add_nuclide("Zr90", 2.1827e-2) - clad.add_nuclide("Zr91", 4.7600e-3) - clad.add_nuclide("Zr92", 7.2758e-3) - clad.add_nuclide("Zr94", 7.3734e-3) - clad.add_nuclide("Zr96", 1.1879e-3) - - hot_water = openmc.Material(name='Hot borated water') - hot_water.set_density('g/cm3', 0.740582) - hot_water.add_nuclide("H1", 4.9457e-2) - hot_water.add_nuclide("O16", 2.4672e-2) - hot_water.add_nuclide("B10", 8.0042e-6) - hot_water.add_nuclide("B11", 3.2218e-5) - hot_water.add_s_alpha_beta('c_H_in_H2O') - - # Define the materials file. - model.materials = (fuel, clad, hot_water) - - # Instantiate ZCylinder surfaces - pitch = 1.26 - fuel_or = openmc.ZCylinder(x0=0, y0=0, r=0.39218, name='Fuel OR') - clad_or = openmc.ZCylinder(x0=0, y0=0, r=0.45720, name='Clad OR') - left = openmc.XPlane(x0=-pitch/2, name='left', boundary_type='reflective') - right = openmc.XPlane(x0=pitch/2, name='right', boundary_type='reflective') - bottom = openmc.YPlane(y0=-pitch/2, name='bottom', - boundary_type='reflective') - top = openmc.YPlane(y0=pitch/2, name='top', boundary_type='reflective') - - # Instantiate Cells - fuel_pin = openmc.Cell(name='Fuel', fill=fuel) - cladding = openmc.Cell(name='Cladding', fill=clad) - water = openmc.Cell(name='Water', fill=hot_water) - - # Use surface half-spaces to define regions - fuel_pin.region = -fuel_or - cladding.region = +fuel_or & -clad_or - water.region = +clad_or & +left & -right & +bottom & -top - - # Create root universe - model.geometry.root_universe = openmc.Universe(0, name='root universe') - model.geometry.root_universe.add_cells([fuel_pin, cladding, water]) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 100 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-pitch/2, -pitch/2, -1], [pitch/2, pitch/2, 1], only_fissionable=True)) - - plot = openmc.Plot.from_geometry(model.geometry) - plot.pixels = (300, 300) - plot.color_by = 'material' - model.plots.append(plot) - - return model - - -def pwr_core(): - """Create a PWR full-core model. - - This model is the OECD/NEA Monte Carlo Performance benchmark which is a - grossly simplified pressurized water reactor (PWR) with 241 fuel - assemblies. Note that the number of particles/batches is initially set very - low for testing purposes. - - Returns - ------- - model : openmc.model.Model - Full-core PWR model - - """ - model = openmc.model.Model() - - # Define materials. - fuel = openmc.Material(1, name='UOX fuel') - fuel.set_density('g/cm3', 10.062) - fuel.add_nuclide("U234", 4.9476e-6) - fuel.add_nuclide("U235", 4.8218e-4) - fuel.add_nuclide("U238", 2.1504e-2) - fuel.add_nuclide("Xe135", 1.0801e-8) - fuel.add_nuclide("O16", 4.5737e-2) - - clad = openmc.Material(2, name='Zircaloy') - clad.set_density('g/cm3', 5.77) - clad.add_nuclide("Zr90", 0.5145) - clad.add_nuclide("Zr91", 0.1122) - clad.add_nuclide("Zr92", 0.1715) - clad.add_nuclide("Zr94", 0.1738) - clad.add_nuclide("Zr96", 0.0280) - - cold_water = openmc.Material(3, name='Cold borated water') - cold_water.set_density('atom/b-cm', 0.07416) - cold_water.add_nuclide("H1", 2.0) - cold_water.add_nuclide("O16", 1.0) - cold_water.add_nuclide("B10", 6.490e-4) - cold_water.add_nuclide("B11", 2.689e-3) - cold_water.add_s_alpha_beta('c_H_in_H2O') - - hot_water = openmc.Material(4, name='Hot borated water') - hot_water.set_density('atom/b-cm', 0.06614) - hot_water.add_nuclide("H1", 2.0) - hot_water.add_nuclide("O16", 1.0) - hot_water.add_nuclide("B10", 6.490e-4) - hot_water.add_nuclide("B11", 2.689e-3) - hot_water.add_s_alpha_beta('c_H_in_H2O') - - rpv_steel = openmc.Material(5, name='Reactor pressure vessel steel') - rpv_steel.set_density('g/cm3', 7.9) - rpv_steel.add_nuclide("Fe54", 0.05437098, 'wo') - rpv_steel.add_nuclide("Fe56", 0.88500663, 'wo') - rpv_steel.add_nuclide("Fe57", 0.0208008, 'wo') - rpv_steel.add_nuclide("Fe58", 0.00282159, 'wo') - rpv_steel.add_nuclide("Ni58", 0.0067198, 'wo') - rpv_steel.add_nuclide("Ni60", 0.0026776, 'wo') - rpv_steel.add_nuclide("Mn55", 0.01, 'wo') - rpv_steel.add_nuclide("Cr52", 0.002092475, 'wo') - rpv_steel.add_nuclide("C0", 0.0025, 'wo') - rpv_steel.add_nuclide("Cu63", 0.0013696, 'wo') - - lower_rad_ref = openmc.Material(6, name='Lower radial reflector') - lower_rad_ref.set_density('g/cm3', 4.32) - lower_rad_ref.add_nuclide("H1", 0.0095661, 'wo') - lower_rad_ref.add_nuclide("O16", 0.0759107, 'wo') - lower_rad_ref.add_nuclide("B10", 3.08409e-5, 'wo') - lower_rad_ref.add_nuclide("B11", 1.40499e-4, 'wo') - lower_rad_ref.add_nuclide("Fe54", 0.035620772088, 'wo') - lower_rad_ref.add_nuclide("Fe56", 0.579805982228, 'wo') - lower_rad_ref.add_nuclide("Fe57", 0.01362750048, 'wo') - lower_rad_ref.add_nuclide("Fe58", 0.001848545204, 'wo') - lower_rad_ref.add_nuclide("Ni58", 0.055298376566, 'wo') - lower_rad_ref.add_nuclide("Mn55", 0.0182870, 'wo') - lower_rad_ref.add_nuclide("Cr52", 0.145407678031, 'wo') - lower_rad_ref.add_s_alpha_beta('c_H_in_H2O') - - upper_rad_ref = openmc.Material(7, name='Upper radial reflector / Top plate region') - upper_rad_ref.set_density('g/cm3', 4.28) - upper_rad_ref.add_nuclide("H1", 0.0086117, 'wo') - upper_rad_ref.add_nuclide("O16", 0.0683369, 'wo') - upper_rad_ref.add_nuclide("B10", 2.77638e-5, 'wo') - upper_rad_ref.add_nuclide("B11", 1.26481e-4, 'wo') - upper_rad_ref.add_nuclide("Fe54", 0.035953677186, 'wo') - upper_rad_ref.add_nuclide("Fe56", 0.585224740891, 'wo') - upper_rad_ref.add_nuclide("Fe57", 0.01375486056, 'wo') - upper_rad_ref.add_nuclide("Fe58", 0.001865821363, 'wo') - upper_rad_ref.add_nuclide("Ni58", 0.055815129186, 'wo') - upper_rad_ref.add_nuclide("Mn55", 0.0184579, 'wo') - upper_rad_ref.add_nuclide("Cr52", 0.146766614995, 'wo') - upper_rad_ref.add_s_alpha_beta('c_H_in_H2O') - - bot_plate = openmc.Material(8, name='Bottom plate region') - bot_plate.set_density('g/cm3', 7.184) - bot_plate.add_nuclide("H1", 0.0011505, 'wo') - bot_plate.add_nuclide("O16", 0.0091296, 'wo') - bot_plate.add_nuclide("B10", 3.70915e-6, 'wo') - bot_plate.add_nuclide("B11", 1.68974e-5, 'wo') - bot_plate.add_nuclide("Fe54", 0.03855611055, 'wo') - bot_plate.add_nuclide("Fe56", 0.627585036425, 'wo') - bot_plate.add_nuclide("Fe57", 0.014750478, 'wo') - bot_plate.add_nuclide("Fe58", 0.002000875025, 'wo') - bot_plate.add_nuclide("Ni58", 0.059855207342, 'wo') - bot_plate.add_nuclide("Mn55", 0.0197940, 'wo') - bot_plate.add_nuclide("Cr52", 0.157390026871, 'wo') - bot_plate.add_s_alpha_beta('c_H_in_H2O') - - bot_nozzle = openmc.Material(9, name='Bottom nozzle region') - bot_nozzle.set_density('g/cm3', 2.53) - bot_nozzle.add_nuclide("H1", 0.0245014, 'wo') - bot_nozzle.add_nuclide("O16", 0.1944274, 'wo') - bot_nozzle.add_nuclide("B10", 7.89917e-5, 'wo') - bot_nozzle.add_nuclide("B11", 3.59854e-4, 'wo') - bot_nozzle.add_nuclide("Fe54", 0.030411411144, 'wo') - bot_nozzle.add_nuclide("Fe56", 0.495012237964, 'wo') - bot_nozzle.add_nuclide("Fe57", 0.01163454624, 'wo') - bot_nozzle.add_nuclide("Fe58", 0.001578204652, 'wo') - bot_nozzle.add_nuclide("Ni58", 0.047211231662, 'wo') - bot_nozzle.add_nuclide("Mn55", 0.0156126, 'wo') - bot_nozzle.add_nuclide("Cr52", 0.124142524198, 'wo') - bot_nozzle.add_s_alpha_beta('c_H_in_H2O') - - top_nozzle = openmc.Material(10, name='Top nozzle region') - top_nozzle.set_density('g/cm3', 1.746) - top_nozzle.add_nuclide("H1", 0.0358870, 'wo') - top_nozzle.add_nuclide("O16", 0.2847761, 'wo') - top_nozzle.add_nuclide("B10", 1.15699e-4, 'wo') - top_nozzle.add_nuclide("B11", 5.27075e-4, 'wo') - top_nozzle.add_nuclide("Fe54", 0.02644016154, 'wo') - top_nozzle.add_nuclide("Fe56", 0.43037146399, 'wo') - top_nozzle.add_nuclide("Fe57", 0.0101152584, 'wo') - top_nozzle.add_nuclide("Fe58", 0.00137211607, 'wo') - top_nozzle.add_nuclide("Ni58", 0.04104621835, 'wo') - top_nozzle.add_nuclide("Mn55", 0.0135739, 'wo') - top_nozzle.add_nuclide("Cr52", 0.107931450781, 'wo') - top_nozzle.add_s_alpha_beta('c_H_in_H2O') - - top_fa = openmc.Material(11, name='Top of fuel assemblies') - top_fa.set_density('g/cm3', 3.044) - top_fa.add_nuclide("H1", 0.0162913, 'wo') - top_fa.add_nuclide("O16", 0.1292776, 'wo') - top_fa.add_nuclide("B10", 5.25228e-5, 'wo') - top_fa.add_nuclide("B11", 2.39272e-4, 'wo') - top_fa.add_nuclide("Zr90", 0.43313403903, 'wo') - top_fa.add_nuclide("Zr91", 0.09549277374, 'wo') - top_fa.add_nuclide("Zr92", 0.14759527104, 'wo') - top_fa.add_nuclide("Zr94", 0.15280552077, 'wo') - top_fa.add_nuclide("Zr96", 0.02511169542, 'wo') - top_fa.add_s_alpha_beta('c_H_in_H2O') - - bot_fa = openmc.Material(12, name='Bottom of fuel assemblies') - bot_fa.set_density('g/cm3', 1.762) - bot_fa.add_nuclide("H1", 0.0292856, 'wo') - bot_fa.add_nuclide("O16", 0.2323919, 'wo') - bot_fa.add_nuclide("B10", 9.44159e-5, 'wo') - bot_fa.add_nuclide("B11", 4.30120e-4, 'wo') - bot_fa.add_nuclide("Zr90", 0.3741373658, 'wo') - bot_fa.add_nuclide("Zr91", 0.0824858164, 'wo') - bot_fa.add_nuclide("Zr92", 0.1274914944, 'wo') - bot_fa.add_nuclide("Zr94", 0.1319920622, 'wo') - bot_fa.add_nuclide("Zr96", 0.0216912612, 'wo') - bot_fa.add_s_alpha_beta('c_H_in_H2O') - - # Define the materials file. - model.materials = (fuel, clad, cold_water, hot_water, rpv_steel, - lower_rad_ref, upper_rad_ref, bot_plate, - bot_nozzle, top_nozzle, top_fa, bot_fa) - - # Define surfaces. - s1 = openmc.ZCylinder(r=0.41, surface_id=1) - s2 = openmc.ZCylinder(r=0.475, surface_id=2) - s3 = openmc.ZCylinder(r=0.56, surface_id=3) - s4 = openmc.ZCylinder(r=0.62, surface_id=4) - s5 = openmc.ZCylinder(r=187.6, surface_id=5) - s6 = openmc.ZCylinder(r=209.0, surface_id=6) - s7 = openmc.ZCylinder(r=229.0, surface_id=7) - s8 = openmc.ZCylinder(r=249.0, surface_id=8, boundary_type='vacuum') - - s31 = openmc.ZPlane(z0=-229.0, surface_id=31, boundary_type='vacuum') - s32 = openmc.ZPlane(z0=-199.0, surface_id=32) - s33 = openmc.ZPlane(z0=-193.0, surface_id=33) - s34 = openmc.ZPlane(z0=-183.0, surface_id=34) - s35 = openmc.ZPlane(z0=0.0, surface_id=35) - s36 = openmc.ZPlane(z0=183.0, surface_id=36) - s37 = openmc.ZPlane(z0=203.0, surface_id=37) - s38 = openmc.ZPlane(z0=215.0, surface_id=38) - s39 = openmc.ZPlane(z0=223.0, surface_id=39, boundary_type='vacuum') - - # Define pin cells. - fuel_cold = openmc.Universe(name='Fuel pin, cladding, cold water', - universe_id=1) - c21 = openmc.Cell(cell_id=21, fill=fuel, region=-s1) - c22 = openmc.Cell(cell_id=22, fill=clad, region=+s1 & -s2) - c23 = openmc.Cell(cell_id=23, fill=cold_water, region=+s2) - fuel_cold.add_cells((c21, c22, c23)) - - tube_cold = openmc.Universe(name='Instrumentation guide tube, ' - 'cold water', universe_id=2) - c24 = openmc.Cell(cell_id=24, fill=cold_water, region=-s3) - c25 = openmc.Cell(cell_id=25, fill=clad, region=+s3 & -s4) - c26 = openmc.Cell(cell_id=26, fill=cold_water, region=+s4) - tube_cold.add_cells((c24, c25, c26)) - - fuel_hot = openmc.Universe(name='Fuel pin, cladding, hot water', - universe_id=3) - c27 = openmc.Cell(cell_id=27, fill=fuel, region=-s1) - c28 = openmc.Cell(cell_id=28, fill=clad, region=+s1 & -s2) - c29 = openmc.Cell(cell_id=29, fill=hot_water, region=+s2) - fuel_hot.add_cells((c27, c28, c29)) - - tube_hot = openmc.Universe(name='Instrumentation guide tube, hot water', - universe_id=4) - c30 = openmc.Cell(cell_id=30, fill=hot_water, region=-s3) - c31 = openmc.Cell(cell_id=31, fill=clad, region=+s3 & -s4) - c32 = openmc.Cell(cell_id=32, fill=hot_water, region=+s4) - tube_hot.add_cells((c30, c31, c32)) - - # Set positions occupied by guide tubes - tube_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8, 11, 14, - 2, 5, 8, 11, 14, 3, 13, 5, 8, 11]) - tube_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, - 11, 11, 11, 11, 11, 13, 13, 14, 14, 14]) - - # Define fuel lattices. - l100 = openmc.RectLattice(name='Fuel assembly (lower half)', lattice_id=100) - l100.lower_left = (-10.71, -10.71) - l100.pitch = (1.26, 1.26) - l100.universes = np.tile(fuel_cold, (17, 17)) - l100.universes[tube_x, tube_y] = tube_cold - - l101 = openmc.RectLattice(name='Fuel assembly (upper half)', lattice_id=101) - l101.lower_left = (-10.71, -10.71) - l101.pitch = (1.26, 1.26) - l101.universes = np.tile(fuel_hot, (17, 17)) - l101.universes[tube_x, tube_y] = tube_hot - - # Define assemblies. - fa_cw = openmc.Universe(name='Water assembly (cold)', universe_id=5) - c50 = openmc.Cell(cell_id=50, fill=cold_water, region=+s34 & -s35) - fa_cw.add_cell(c50) - - fa_hw = openmc.Universe(name='Water assembly (hot)', universe_id=7) - c70 = openmc.Cell(cell_id=70, fill=hot_water, region=+s35 & -s36) - fa_hw.add_cell(c70) - - fa_cold = openmc.Universe(name='Fuel assembly (cold)', universe_id=6) - c60 = openmc.Cell(cell_id=60, fill=l100, region=+s34 & -s35) - fa_cold.add_cell(c60) - - fa_hot = openmc.Universe(name='Fuel assembly (hot)', universe_id=8) - c80 = openmc.Cell(cell_id=80, fill=l101, region=+s35 & -s36) - fa_hot.add_cell(c80) - - # Define core lattices - l200 = openmc.RectLattice(name='Core lattice (lower half)', lattice_id=200) - l200.lower_left = (-224.91, -224.91) - l200.pitch = (21.42, 21.42) - l200.universes = [ - [fa_cw]*21, - [fa_cw]*21, - [fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7, - [fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5, - [fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4, - [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, - [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2, - [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, - [fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3, - [fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4, - [fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5, - [fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7, - [fa_cw]*21, - [fa_cw]*21] - - l201 = openmc.RectLattice(name='Core lattice (lower half)', lattice_id=201) - l201.lower_left = (-224.91, -224.91) - l201.pitch = (21.42, 21.42) - l201.universes = [ - [fa_hw]*21, - [fa_hw]*21, - [fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7, - [fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5, - [fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4, - [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, - [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2, - [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, - [fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3, - [fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4, - [fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5, - [fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7, - [fa_hw]*21, - [fa_hw]*21] - - # Define root universe. - root = openmc.Universe(universe_id=0, name='root universe') - c1 = openmc.Cell(cell_id=1, fill=l200, region=-s6 & +s34 & -s35) - c2 = openmc.Cell(cell_id=2, fill=l201, region=-s6 & +s35 & -s36) - c3 = openmc.Cell(cell_id=3, fill=bot_plate, region=-s7 & +s31 & -s32) - c4 = openmc.Cell(cell_id=4, fill=bot_nozzle, region=-s5 & +s32 & -s33) - c5 = openmc.Cell(cell_id=5, fill=bot_fa, region=-s5 & +s33 & -s34) - c6 = openmc.Cell(cell_id=6, fill=top_fa, region=-s5 & +s36 & -s37) - c7 = openmc.Cell(cell_id=7, fill=top_nozzle, region=-s5 & +s37 & -s38) - c8 = openmc.Cell(cell_id=8, fill=upper_rad_ref, region=-s7 & +s38 & -s39) - c9 = openmc.Cell(cell_id=9, fill=bot_nozzle, region=+s6 & -s7 & +s32 & -s38) - c10 = openmc.Cell(cell_id=10, fill=rpv_steel, region=+s7 & -s8 & +s31 & -s39) - c11 = openmc.Cell(cell_id=11, fill=lower_rad_ref, region=+s5 & -s6 & +s32 & -s34) - c12 = openmc.Cell(cell_id=12, fill=upper_rad_ref, region=+s5 & -s6 & +s36 & -s38) - root.add_cells((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)) - - # Assign root universe to geometry - model.geometry.root_universe = root - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 100 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-160, -160, -183], [160, 160, 183])) - - plot = openmc.Plot() - plot.origin = (125, 125, 0) - plot.width = (250, 250) - plot.pixels = (3000, 3000) - plot.color_by = 'material' - model.plots.append(plot) - - return model - - -def pwr_assembly(): - """Create a PWR assembly model. - - This model is a reflected 17x17 fuel assembly from the the `BEAVRS - `_ benchmark. The fuel is 2.4 w/o - enriched UO2 corresponding to a beginning-of-cycle condition. Note that the - number of particles/batches is initially set very low for testing purposes. - - Returns - ------- - model : openmc.model.Model - A PWR assembly model - - """ - - model = openmc.model.Model() - - # Define materials. - fuel = openmc.Material(name='Fuel') - fuel.set_density('g/cm3', 10.29769) - fuel.add_nuclide("U234", 4.4843e-6) - fuel.add_nuclide("U235", 5.5815e-4) - fuel.add_nuclide("U238", 2.2408e-2) - fuel.add_nuclide("O16", 4.5829e-2) - - clad = openmc.Material(name='Cladding') - clad.set_density('g/cm3', 6.55) - clad.add_nuclide("Zr90", 2.1827e-2) - clad.add_nuclide("Zr91", 4.7600e-3) - clad.add_nuclide("Zr92", 7.2758e-3) - clad.add_nuclide("Zr94", 7.3734e-3) - clad.add_nuclide("Zr96", 1.1879e-3) - - hot_water = openmc.Material(name='Hot borated water') - hot_water.set_density('g/cm3', 0.740582) - hot_water.add_nuclide("H1", 4.9457e-2) - hot_water.add_nuclide("O16", 2.4672e-2) - hot_water.add_nuclide("B10", 8.0042e-6) - hot_water.add_nuclide("B11", 3.2218e-5) - hot_water.add_s_alpha_beta('c_H_in_H2O') - - # Define the materials file. - model.materials = (fuel, clad, hot_water) - - # Instantiate ZCylinder surfaces - fuel_or = openmc.ZCylinder(x0=0, y0=0, r=0.39218, name='Fuel OR') - clad_or = openmc.ZCylinder(x0=0, y0=0, r=0.45720, name='Clad OR') - - # Create boundary planes to surround the geometry - pitch = 21.42 - min_x = openmc.XPlane(x0=-pitch/2, boundary_type='reflective') - max_x = openmc.XPlane(x0=+pitch/2, boundary_type='reflective') - min_y = openmc.YPlane(y0=-pitch/2, boundary_type='reflective') - max_y = openmc.YPlane(y0=+pitch/2, boundary_type='reflective') - - # Create a fuel pin universe - fuel_pin_universe = openmc.Universe(name='Fuel Pin') - fuel_cell = openmc.Cell(name='fuel', fill=fuel, region=-fuel_or) - clad_cell = openmc.Cell(name='clad', fill=clad, region=+fuel_or & -clad_or) - hot_water_cell = openmc.Cell(name='hot water', fill=hot_water, region=+clad_or) - fuel_pin_universe.add_cells([fuel_cell, clad_cell, hot_water_cell]) - - - # Create a control rod guide tube universe - guide_tube_universe = openmc.Universe(name='Guide Tube') - gt_inner_cell = openmc.Cell(name='guide tube inner water', fill=hot_water, - region=-fuel_or) - gt_clad_cell = openmc.Cell(name='guide tube clad', fill=clad, - region=+fuel_or & -clad_or) - gt_outer_cell = openmc.Cell(name='guide tube outer water', fill=hot_water, - region=+clad_or) - guide_tube_universe.add_cells([gt_inner_cell, gt_clad_cell, gt_outer_cell]) - - # Create fuel assembly Lattice - assembly = openmc.RectLattice(name='Fuel Assembly') - assembly.pitch = (pitch/17, pitch/17) - assembly.lower_left = (-pitch/2, -pitch/2) - - # Create array indices for guide tube locations in lattice - template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8, - 11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11]) - template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8, - 8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14]) - - # Create 17x17 array of universes - assembly.universes = np.tile(fuel_pin_universe, (17, 17)) - assembly.universes[template_x, template_y] = guide_tube_universe - - # Create root Cell - root_cell = openmc.Cell(name='root cell', fill=assembly) - root_cell.region = +min_x & -max_x & +min_y & -max_y - - # Create root Universe - model.geometry.root_universe = openmc.Universe(name='root universe') - model.geometry.root_universe.add_cell(root_cell) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 100 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-pitch/2, -pitch/2, -1], [pitch/2, pitch/2, 1], only_fissionable=True)) - - plot = openmc.Plot() - plot.origin = (0.0, 0.0, 0) - plot.width = (21.42, 21.42) - plot.pixels = (300, 300) - plot.color_by = 'material' - model.plots.append(plot) - - return model - - -def slab_mg(num_regions=1, mat_names=None, mgxslib_name='2g.h5'): - """Create a 1D slab model. - - Parameters - ---------- - num_regions : int, optional - Number of regions in the problem, each with a unique MGXS dataset. - Defaults to 1. - - mat_names : Iterable of str, optional - List of the material names to use; defaults to ['mat_1', 'mat_2',...]. - - mgxslib_name : str, optional - MGXS Library file to use; defaults to '2g.h5'. - - Returns - ------- - model : openmc.model.Model - One-group, 1D slab model - - """ - - openmc.check_type('num_regions', num_regions, Integral) - openmc.check_greater_than('num_regions', num_regions, 0) - if mat_names is not None: - openmc.check_length('mat_names', mat_names, num_regions) - openmc.check_iterable_type('mat_names', mat_names, str) - else: - mat_names = [] - for i in range(num_regions): - mat_names.append('mat_' + str(i + 1)) - - # # Make Materials - materials_file = openmc.Materials() - macros = [] - mats = [] - for i in range(len(mat_names)): - macros.append(openmc.Macroscopic('mat_' + str(i + 1))) - mats.append(openmc.Material(name=mat_names[i])) - mats[-1].set_density('macro', 1.0) - mats[-1].add_macroscopic(macros[-1]) - - materials_file += mats - - materials_file.cross_sections = mgxslib_name - - # # Make Geometry - rad_outer = 929.45 - # Set a cell boundary to exist for every material above (exclude the 0) - rads = np.linspace(0., rad_outer, len(mats) + 1, endpoint=True)[1:] - - # Instantiate Universe - root = openmc.Universe(universe_id=0, name='root universe') - cells = [] - - surfs = [] - surfs.append(openmc.XPlane(x0=0., boundary_type='reflective')) - for r, rad in enumerate(rads): - if r == len(rads) - 1: - surfs.append(openmc.XPlane(x0=rad, boundary_type='vacuum')) - else: - surfs.append(openmc.XPlane(x0=rad)) - - # Instantiate Cells - cells = [] - for c in range(len(surfs) - 1): - cells.append(openmc.Cell()) - cells[-1].region = (+surfs[c] & -surfs[c + 1]) - cells[-1].fill = mats[c] - - # Register Cells with Universe - root.add_cells(cells) - - # Instantiate a Geometry, register the root Universe, and export to XML - geometry_file = openmc.Geometry(root) - - # # Make Settings - # Instantiate a Settings object, set all runtime parameters - settings_file = openmc.Settings() - settings_file.energy_mode = "multi-group" - settings_file.tabular_legendre = {'enable': False} - settings_file.batches = 10 - settings_file.inactive = 5 - settings_file.particles = 1000 - - # Build source distribution - INF = 1000. - bounds = [0., -INF, -INF, rads[0], INF, INF] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) - settings_file.source = openmc.source.Source(space=uniform_dist) - - settings_file.output = {'summary': False} - - model = openmc.model.Model() - model.geometry = geometry_file - model.materials = materials_file - model.settings = settings_file - model.xs_data = macros - - return model diff --git a/openmc/exceptions.py b/openmc/exceptions.py deleted file mode 100644 index c87bfc82c..000000000 --- a/openmc/exceptions.py +++ /dev/null @@ -1,38 +0,0 @@ -class OpenMCError(Exception): - """Root exception class for OpenMC.""" - - -class GeometryError(OpenMCError): - """Geometry-related error""" - - -class InvalidIDError(OpenMCError): - """Use of an ID that is invalid.""" - - -class AllocationError(OpenMCError): - """Error related to memory allocation.""" - - -class OutOfBoundsError(OpenMCError): - """Index in array out of bounds.""" - - -class DataError(OpenMCError): - """Error relating to nuclear data.""" - - -class PhysicsError(OpenMCError): - """Error relating to performing physics.""" - - -class InvalidArgumentError(OpenMCError): - """Argument passed was invalid.""" - - -class InvalidTypeError(OpenMCError): - """Tried to perform an operation on the wrong type.""" - - -class SetupError(OpenMCError): - """Error while setting up a problem.""" diff --git a/openmc/executor.py b/openmc/executor.py deleted file mode 100644 index 8ad2bd896..000000000 --- a/openmc/executor.py +++ /dev/null @@ -1,212 +0,0 @@ -from collections.abc import Iterable -import subprocess -from numbers import Integral - -import openmc -from openmc import VolumeCalculation - - -def _run(args, output, cwd): - # Launch a subprocess - p = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, - 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='') - - # 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='.'): - """Run OpenMC in plotting mode - - Parameters - ---------- - output : bool, optional - Capture OpenMC output from standard out - openmc_exec : str, optional - Path to OpenMC executable - cwd : str, optional - Path to working directory to run in - - Raises - ------ - subprocess.CalledProcessError - If the `openmc` executable returns a non-zero status - - """ - _run([openmc_exec, '-p'], output, cwd) - - -def plot_inline(plots, openmc_exec='openmc', cwd='.', convert_exec='convert'): - """Display plots inline in a Jupyter notebook. - - This function requires that you have a program installed to convert PPM - files to PNG files. Typically, that would be `ImageMagick - `_ which includes a `convert` command. - - Parameters - ---------- - plots : Iterable of openmc.Plot - Plots to display - openmc_exec : str - Path to OpenMC executable - cwd : str, optional - Path to working directory to run in - 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 - - if not isinstance(plots, Iterable): - plots = [plots] - - # Create plots.xml - openmc.Plots(plots).export_to_xml() - - # Run OpenMC in geometry plotting mode - plot_geometry(False, openmc_exec, cwd) - - images = [] - if plots is not None: - for p in plots: - if p.filename is not None: - ppm_file = '{}.ppm'.format(p.filename) - else: - ppm_file = 'plot_{}.ppm'.format(p.id) - png_file = ppm_file.replace('.ppm', '.png') - subprocess.check_call([convert_exec, ppm_file, png_file]) - images.append(Image(png_file)) - display(*images) - - -def calculate_volumes(threads=None, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None): - """Run stochastic volume calculations in OpenMC. - - This function runs OpenMC in stochastic volume calculation mode. To specify - the parameters of a volume calculation, one must first create a - :class:`openmc.VolumeCalculation` instance and assign it to - :attr:`openmc.Settings.volume_calculations`. For example: - - >>> vol = openmc.VolumeCalculation(domains=[cell1, cell2], samples=100000) - >>> settings = openmc.Settings() - >>> settings.volume_calculations = [vol] - >>> settings.export_to_xml() - >>> openmc.calculate_volumes() - - Parameters - ---------- - threads : int, optional - Number of OpenMP threads. If OpenMC is compiled with OpenMP threading - enabled, the default is implementation-dependent but is usually equal to - the number of hardware threads available (or a value set by the - :envvar:`OMP_NUM_THREADS` environment variable). - output : bool, optional - Capture OpenMC output from standard out - openmc_exec : str, optional - Path to OpenMC executable. Defaults to 'openmc'. - mpi_args : list of str, optional - MPI execute command and any additional MPI arguments to pass, - e.g. ['mpiexec', '-n', '8']. - cwd : str, optional - 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 - - """ - args = [openmc_exec, '--volume'] - - if isinstance(threads, Integral) and threads > 0: - args += ['-s', str(threads)] - if mpi_args is not None: - args = mpi_args + args - - _run(args, output, cwd) - - -def run(particles=None, threads=None, geometry_debug=False, - restart_file=None, tracks=False, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None): - """Run an OpenMC simulation. - - Parameters - ---------- - particles : int, optional - Number of particles to simulate per generation. - threads : int, optional - Number of OpenMP threads. If OpenMC is compiled with OpenMP threading - enabled, the default is implementation-dependent but is usually equal to - the number of hardware threads available (or a value set by the - :envvar:`OMP_NUM_THREADS` environment variable). - geometry_debug : bool, optional - Turn on geometry debugging during simulation. Defaults to False. - restart_file : str, optional - Path to restart file to use - tracks : bool, optional - Write tracks for all particles. Defaults to False. - output : bool - Capture OpenMC output from standard out - cwd : str, optional - Path to working directory to run in. Defaults to the current working - directory. - openmc_exec : str, optional - Path to OpenMC executable. Defaults to 'openmc'. - mpi_args : list of str, optional - 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: - args += ['-n', str(particles)] - - if isinstance(threads, Integral) and threads > 0: - args += ['-s', str(threads)] - - if geometry_debug: - args.append('-g') - - if isinstance(restart_file, str): - args += ['-r', restart_file] - - if tracks: - args.append('-t') - - if mpi_args is not None: - args = mpi_args + args - - _run(args, output, cwd) diff --git a/openmc/filter.py b/openmc/filter.py deleted file mode 100644 index 8527ca9b9..000000000 --- a/openmc/filter.py +++ /dev/null @@ -1,1810 +0,0 @@ -from abc import ABCMeta -from collections import OrderedDict -from collections.abc import Iterable -import copy -import hashlib -from itertools import product -from numbers import Real, Integral -from xml.etree import ElementTree as ET - -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 .surface import Surface -from .universe import Universe - - -_FILTER_TYPES = ( - 'universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', - 'energyout', 'mu', 'polar', 'azimuthal', 'distribcell', 'delayedgroup', - 'energyfunction', 'cellfrom', 'legendre', 'spatiallegendre', - 'sphericalharmonics', 'zernike', 'zernikeradial', 'particle' -) - -_CURRENT_NAMES = ( - 'x-min out', 'x-min in', 'x-max out', 'x-max in', - 'y-min out', 'y-min in', 'y-max out', 'y-max in', - 'z-min out', 'z-min in', 'z-max out', 'z-max in' -) - -_PARTICLES = {'neutron', 'photon', 'electron', 'positron'} - - -class FilterMeta(ABCMeta): - def __new__(cls, name, bases, namespace, **kwargs): - # Check the class name. - if not name.endswith('Filter'): - raise ValueError("All filter class names must end with 'Filter'") - - # Create a 'short_name' attribute that removes the 'Filter' suffix. - namespace['short_name'] = name[:-6] - - # Subclass methods can sort of inherit the docstring of parent class - # methods. If a function is defined without a docstring, most (all?) - # Python interpreters will search through the parent classes to see if - # there is a docstring for a function with the same name, and they will - # use that docstring. However, Sphinx does not have that functionality. - # This chunk of code handles this docstring inheritance manually so that - # the autodocumentation will pick it up. - if name != 'Filter': - # Look for newly-defined functions that were also in Filter. - for func_name in namespace: - if func_name in Filter.__dict__: - # Inherit the docstring from Filter if not defined. - if isinstance(namespace[func_name], - (classmethod, staticmethod)): - new_doc = namespace[func_name].__func__.__doc__ - old_doc = Filter.__dict__[func_name].__func__.__doc__ - if new_doc is None and old_doc is not None: - namespace[func_name].__func__.__doc__ = old_doc - else: - new_doc = namespace[func_name].__doc__ - old_doc = Filter.__dict__[func_name].__doc__ - if new_doc is None and old_doc is not None: - namespace[func_name].__doc__ = old_doc - - # Make the class. - return super().__new__(cls, name, bases, namespace, **kwargs) - - -class Filter(IDManagerMixin, metaclass=FilterMeta): - """Tally modifier that describes phase-space and other characteristics. - - Parameters - ---------- - bins : Integral or Iterable of Integral or Iterable of Real - The bins for the filter. This takes on different meaning for different - filters. See the docstrings for sublcasses of this filter or the online - documentation for more details. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Integral or Iterable of Integral or Iterable of Real - The bins for the filter - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, bins, filter_id=None): - self.bins = bins - self.id = filter_id - - def __eq__(self, other): - if type(self) is not type(other): - return False - elif len(self.bins) != len(other.bins): - return False - else: - return np.allclose(self.bins, other.bins) - - def __ne__(self, other): - return not self == other - - def __gt__(self, other): - if type(self) is not type(other): - if self.short_name in _FILTER_TYPES and \ - other.short_name in _FILTER_TYPES: - delta = _FILTER_TYPES.index(self.short_name) - \ - _FILTER_TYPES.index(other.short_name) - return delta > 0 - else: - return False - else: - return max(self.bins) > max(other.bins) - - def __lt__(self, other): - return not self > other - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tBins', self.bins) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tBins', self.bins) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @classmethod - def _recursive_subclasses(cls): - """Return all subclasses and their subclasses, etc.""" - all_subclasses = [] - - for subclass in cls.__subclasses__(): - all_subclasses.append(subclass) - all_subclasses.extend(subclass._recursive_subclasses()) - - return all_subclasses - - @classmethod - def from_hdf5(cls, group, **kwargs): - """Construct a new Filter instance from HDF5 data. - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - - Keyword arguments - ----------------- - meshes : dict - Dictionary mapping integer IDs to openmc.MeshBase objects. Only - used for openmc.MeshFilter objects. - - """ - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - # 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'][()].decode() == cls.short_name.lower(): - out = cls(group['bins'][()], filter_id=filter_id) - out._num_bins = group['n_bins'][()] - return out - - # Search through all subclasses and find the one matching the HDF5 - # 'type'. Call that class's from_hdf5 method. - for subclass in cls._recursive_subclasses(): - if group['type'][()].decode() == subclass.short_name.lower(): - return subclass.from_hdf5(group, **kwargs) - - raise ValueError("Unrecognized Filter class: '" - + group['type'][()].decode() + "'") - - @property - def bins(self): - return self._bins - - @bins.setter - def bins(self, bins): - self.check_bins(bins) - self._bins = bins - - @property - def num_bins(self): - return len(self.bins) - - def check_bins(self, bins): - """Make sure given bins are valid for this filter. - - Raises - ------ - TypeError - ValueError - - """ - - pass - - def to_xml_element(self): - """Return XML Element representing the Filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing filter data - - """ - element = ET.Element('filter') - element.set('id', str(self.id)) - element.set('type', self.short_name.lower()) - - subelement = ET.SubElement(element, 'bins') - subelement.text = ' '.join(str(b) for b in self.bins) - - return element - - def can_merge(self, other): - """Determine if filter can be merged with another. - - Parameters - ---------- - other : openmc.Filter - Filter to compare with - - Returns - ------- - bool - Whether the filter can be merged - - """ - return type(self) is type(other) - - def merge(self, other): - """Merge this filter with another. - - Parameters - ---------- - other : openmc.Filter - Filter to merge with - - Returns - ------- - merged_filter : openmc.Filter - Filter resulting from the merge - - """ - - if not self.can_merge(other): - msg = 'Unable to merge "{0}" with "{1}" '.format( - type(self), type(other)) - raise ValueError(msg) - - # Merge unique filter bins - merged_bins = np.concatenate((self.bins, other.bins)) - merged_bins = np.unique(merged_bins) - - # Create a new filter with these bins and a new auto-generated ID - return type(self)(merged_bins) - - def is_subset(self, other): - """Determine if another filter is a subset of this filter. - - If all of the bins in the other filter are included as bins in this - filter, then it is a subset of this filter. - - Parameters - ---------- - other : openmc.Filter - The filter to query as a subset of this filter - - Returns - ------- - bool - Whether or not the other filter is a subset of this filter - - """ - - if type(self) is not type(other): - return False - - for bin in other.bins: - if bin not in self.bins: - return False - - return True - - def get_bin_index(self, filter_bin): - """Returns the index in the Filter for some bin. - - Parameters - ---------- - filter_bin : int or tuple - The bin is the integer ID for 'material', 'surface', 'cell', - 'cellborn', and 'universe' Filters. The bin is an integer for the - cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of - floats for 'energy' and 'energyout' filters corresponding to the - energy boundaries of the bin of interest. The bin is an (x,y,z) - 3-tuple for 'mesh' filters corresponding to the mesh cell of - interest. - - Returns - ------- - filter_index : int - The index in the Tally data array for this filter bin. - - """ - - if filter_bin not in self.bins: - msg = 'Unable to get the bin index for Filter since "{0}" ' \ - 'is not one of the bins'.format(filter_bin) - raise ValueError(msg) - - if isinstance(self.bins, np.ndarray): - return np.where(self.bins == filter_bin)[0][0] - else: - return self.bins.index(filter_bin) - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - 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 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 - the same universes and cells but different lattice cell indices. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with columns of strings that characterize the - filter's bins. The number of rows in the DataFrame is the same as - the total number of bins in the corresponding tally, with the filter - bin appropriately tiled to map to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - 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( - {self.short_name.lower(): filter_bins})]) - - return df - - -class WithIDFilter(Filter): - """Abstract parent for filters of types with IDs (Cell, Material, etc.).""" - def __init__(self, bins, filter_id=None): - bins = np.atleast_1d(bins) - - # Make sure bins are either integers or appropriate objects - cv.check_iterable_type('filter bins', bins, - (Integral, self.expected_type)) - - # Extract ID values - bins = np.array([b if isinstance(b, Integral) else b.id - for b in bins]) - self.bins = bins - self.id = filter_id - - def check_bins(self, bins): - # Check the bin values. - for edge in bins: - cv.check_greater_than('filter bin', edge, 0, equality=True) - - -class UniverseFilter(WithIDFilter): - """Bins tally event locations based on the Universe they occured in. - - Parameters - ---------- - bins : openmc.Universe, int, or iterable thereof - The Universes to tally. Either openmc.Universe objects or their - Integral ID numbers can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - openmc.Universe IDs. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Universe - - -class MaterialFilter(WithIDFilter): - """Bins tally event locations based on the Material they occured in. - - Parameters - ---------- - bins : openmc.Material, Integral, or iterable thereof - The Materials to tally. Either openmc.Material objects or their - Integral ID numbers can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - openmc.Material IDs. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Material - - -class CellFilter(WithIDFilter): - """Bins tally event locations based on the Cell they occured in. - - Parameters - ---------- - bins : openmc.Cell, int, or iterable thereof - The cells to tally. Either openmc.Cell objects or their ID numbers can - be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - openmc.Cell IDs. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Cell - - -class CellFromFilter(WithIDFilter): - """Bins tally on which Cell the neutron came from. - - Parameters - ---------- - bins : openmc.Cell, Integral, or iterable thereof - The Cell(s) to tally. Either openmc.Cell objects or their - Integral ID numbers can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Integral or Iterable of Integral - openmc.Cell IDs. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Cell - - -class CellbornFilter(WithIDFilter): - """Bins tally events based on which Cell the neutron was born in. - - Parameters - ---------- - bins : openmc.Cell, Integral, or iterable thereof - The birth Cells to tally. Either openmc.Cell objects or their - Integral ID numbers can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - openmc.Cell IDs. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Cell - - -class SurfaceFilter(WithIDFilter): - """Filters particles by surface crossing - - Parameters - ---------- - bins : openmc.Surface, int, or iterable of Integral - The surfaces to tally over. Either openmc.Surface objects or their ID - numbers can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - The surfaces to tally over. Either openmc.Surface objects or their ID - numbers can be used. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - expected_type = Surface - - -class ParticleFilter(Filter): - """Bins tally events based on the Particle type. - - Parameters - ---------- - bins : str, or iterable of str - The particles to tally represented as strings ('neutron', 'photon', - 'electron', 'positron'). - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - The Particles to tally - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - @property - def bins(self): - return self._bins - - @bins.setter - def bins(self, bins): - bins = np.atleast_1d(bins) - cv.check_iterable_type('filter bins', bins, str) - for edge in bins: - cv.check_value('filter bin', edge, _PARTICLES) - self._bins = bins - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - particles = [b.decode() for b in group['bins'][()]] - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - return cls(particles, filter_id=filter_id) - - -class MeshFilter(Filter): - """Bins tally event locations onto a regular, rectangular mesh. - - Parameters - ---------- - mesh : openmc.MeshBase - The mesh object that events will be tallied onto - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - mesh : openmc.MeshBase - The mesh object that events will be tallied onto - id : int - Unique identifier for the filter - bins : list of tuple - A list of mesh indices for each filter bin, e.g. [(1, 1, 1), (2, 1, 1), - ...] - num_bins : Integral - The number of filter bins - - """ - - def __init__(self, mesh, filter_id=None): - self.mesh = mesh - self.id = filter_id - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tMesh ID', self.mesh.id) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tMesh ID', self.mesh.id) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - if 'meshes' not in kwargs: - raise ValueError(cls.__name__ + " requires a 'meshes' keyword " - "argument.") - - mesh_id = group['bins'][()] - mesh_obj = kwargs['meshes'][mesh_id] - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - out = cls(mesh_obj, filter_id=filter_id) - - return out - - @property - def mesh(self): - return self._mesh - - @mesh.setter - def mesh(self, mesh): - cv.check_type('filter mesh', mesh, openmc.MeshBase) - self._mesh = mesh - self.bins = list(mesh.indices) - - def can_merge(self, other): - # Mesh filters cannot have more than one bin - return False - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - data_size : int - The total number of bins in the tally corresponding to this filter - stride : int - Stride in memory for the filter - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with three columns describing the x,y,z mesh - cell indices corresponding to each filter bin. The number of rows - in the DataFrame is the same as the total number of bins in the - corresponding tally, with the filter bin appropriately tiled to map - to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - # Initialize dictionary to build Pandas Multi-index column - filter_dict = {} - - # Append mesh ID as outermost index of multi-index - mesh_key = 'mesh {}'.format(self.mesh.id) - - # Find mesh dimensions - use 3D indices for simplicity - n_dim = len(self.mesh.dimension) - if n_dim == 3: - nx, ny, nz = self.mesh.dimension - elif n_dim == 2: - nx, ny = self.mesh.dimension - nz = 1 - else: - nx = self.mesh.dimension - ny = nz = 1 - - # Generate multi-index sub-column for x-axis - filter_bins = np.arange(1, nx + 1) - 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) - filter_dict[(mesh_key, 'x')] = filter_bins - - # Generate multi-index sub-column for y-axis - filter_bins = np.arange(1, ny + 1) - repeat_factor = nx * stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'y')] = filter_bins - - # Generate multi-index sub-column for z-axis - filter_bins = np.arange(1, nz + 1) - repeat_factor = nx * ny * stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'z')] = filter_bins - - # Initialize a Pandas DataFrame from the mesh dictionary - df = pd.concat([df, pd.DataFrame(filter_dict)]) - - return df - - def to_xml_element(self): - """Return XML Element representing the Filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing filter data - - """ - element = super().to_xml_element() - element[0].text = str(self.mesh.id) - return element - - -class MeshSurfaceFilter(MeshFilter): - """Filter events by surface crossings on a regular, rectangular mesh. - - Parameters - ---------- - mesh : openmc.MeshBase - The mesh object that events will be tallied onto - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Integral - The mesh ID - mesh : openmc.MeshBase - The mesh object that events will be tallied onto - id : int - Unique identifier for the filter - bins : list of tuple - - A list of mesh indices / surfaces for each filter bin, e.g. [(1, 1, - 'x-min out'), (1, 1, 'x-min in'), ...] - - num_bins : Integral - The number of filter bins - - """ - - @MeshFilter.mesh.setter - def mesh(self, mesh): - cv.check_type('filter mesh', mesh, openmc.MeshBase) - self._mesh = mesh - - # Take the product of mesh indices and current names - n_dim = mesh.n_dimension - self.bins = [mesh_tuple + (surf,) for mesh_tuple, surf in - product(mesh.indices, _CURRENT_NAMES[:4*n_dim])] - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - data_size : int - The total number of bins in the tally corresponding to this filter - stride : int - Stride in memory for the filter - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with three columns describing the x,y,z mesh - cell indices corresponding to each filter bin. The number of rows - in the DataFrame is the same as the total number of bins in the - corresponding tally, with the filter bin appropriately tiled to map - to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - # Initialize dictionary to build Pandas Multi-index column - filter_dict = {} - - # Append mesh ID as outermost index of multi-index - mesh_key = 'mesh {}'.format(self.mesh.id) - - # Find mesh dimensions - use 3D indices for simplicity - n_surfs = 4 * len(self.mesh.dimension) - if len(self.mesh.dimension) == 3: - nx, ny, nz = self.mesh.dimension - elif len(self.mesh.dimension) == 2: - nx, ny = self.mesh.dimension - nz = 1 - else: - nx = self.mesh.dimension - ny = nz = 1 - - # Generate multi-index sub-column for x-axis - filter_bins = np.arange(1, nx + 1) - repeat_factor = n_surfs * stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'x')] = filter_bins - - # Generate multi-index sub-column for y-axis - if len(self.mesh.dimension) > 1: - filter_bins = np.arange(1, ny + 1) - repeat_factor = n_surfs * nx * stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'y')] = filter_bins - - # Generate multi-index sub-column for z-axis - if len(self.mesh.dimension) > 2: - filter_bins = np.arange(1, nz + 1) - repeat_factor = n_surfs * nx * ny * stride - filter_bins = np.repeat(filter_bins, repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'z')] = filter_bins - - # Generate multi-index sub-column for surface - repeat_factor = stride - filter_bins = np.repeat(_CURRENT_NAMES[:n_surfs], repeat_factor) - tile_factor = data_size // len(filter_bins) - filter_bins = np.tile(filter_bins, tile_factor) - filter_dict[(mesh_key, 'surf')] = filter_bins - - # Initialize a Pandas DataFrame from the mesh dictionary - return pd.concat([df, pd.DataFrame(filter_dict)]) - - -class RealFilter(Filter): - """Tally modifier that describes phase-space and other characteristics - - Parameters - ---------- - values : iterable of float - A list of values for which each successive pair constitutes a range of - values for a single bin - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - values for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of values indicating a - filter bin range - num_bins : int - The number of filter bins - - """ - def __init__(self, values, filter_id=None): - self.values = np.asarray(values) - self.bins = np.vstack((self.values[:-1], self.values[1:])).T - self.id = filter_id - - def __gt__(self, other): - if type(self) is type(other): - # Compare largest/smallest bin edges in filters - # This logic is used when merging tallies with real filters - return self.values[0] >= other.values[-1] - else: - return super().__gt__(other) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tValues', self.values) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @Filter.bins.setter - def bins(self, bins): - Filter.bins.__set__(self, np.asarray(bins)) - - def check_bins(self, bins): - for v0, v1 in bins: - # Values should be real - cv.check_type('filter value', v0, Real) - cv.check_type('filter value', v1, Real) - - # Make sure that each tuple has values that are increasing - if v1 < v0: - raise ValueError('Values {} and {} appear to be out of order' - .format(v0, v1)) - - for pair0, pair1 in zip(bins[:-1], bins[1:]): - # Successive pairs should be ordered - if pair1[1] < pair0[1]: - raise ValueError('Values {} and {} appear to be out of order' - .format(pair1[1], pair0[1])) - - def can_merge(self, other): - if type(self) is not type(other): - return False - - if self.bins[0, 0] == other.bins[-1][1]: - # This low edge coincides with other's high edge - return True - elif self.bins[-1][1] == other.bins[0, 0]: - # This high edge coincides with other's low edge - return True - else: - return False - - def merge(self, other): - if not self.can_merge(other): - msg = 'Unable to merge "{0}" with "{1}" ' \ - 'filters'.format(type(self), type(other)) - raise ValueError(msg) - - # Merge unique filter bins - merged_values = np.concatenate((self.values, other.values)) - merged_values = np.unique(merged_values) - - # Create a new filter with these bins and a new auto-generated ID - return type(self)(sorted(merged_values)) - - def is_subset(self, other): - """Determine if another filter is a subset of this filter. - - If all of the bins in the other filter are included as bins in this - filter, then it is a subset of this filter. - - Parameters - ---------- - other : openmc.Filter - The filter to query as a subset of this filter - - Returns - ------- - bool - Whether or not the other filter is a subset of this filter - - """ - - if type(self) is not type(other): - return False - elif self.num_bins != other.num_bins: - return False - else: - return np.allclose(self.values, other.values) - - def get_bin_index(self, filter_bin): - i = np.where(self.bins[:, 1] == filter_bin[1])[0] - if len(i) == 0: - msg = 'Unable to get the bin index for Filter since "{0}" ' \ - 'is not one of the bins'.format(filter_bin) - raise ValueError(msg) - else: - return i[0] - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - data_size : int - The total number of bins in the tally corresponding to this filter - stride : int - Stride in memory for the filter - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with one column of the lower energy bound and one - column of upper energy bound for each filter bin. The number of - rows in the DataFrame is the same as the total number of bins in the - corresponding tally, with the filter bin appropriately tiled to map - to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - # 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[:, 0], 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) - - # Add the new energy columns to the DataFrame. - if hasattr(self, 'units'): - units = ' [{}]'.format(self.units) - else: - units = '' - - df.loc[:, self.short_name.lower() + ' low' + units] = lo_bins - df.loc[:, self.short_name.lower() + ' high' + units] = hi_bins - - return df - - def to_xml_element(self): - """Return XML Element representing the Filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing filter data - - """ - element = super().to_xml_element() - element[0].text = ' '.join(str(x) for x in self.values) - return element - - -class EnergyFilter(RealFilter): - """Bins tally events based on incident particle energy. - - Parameters - ---------- - values : Iterable of Real - A list of values for which each successive pair constitutes a range of - energies in [eV] for a single bin - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - energies in [eV] for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of energies in [eV] - for a single filter bin - num_bins : int - The number of filter bins - - """ - units = 'eV' - - def get_bin_index(self, filter_bin): - # Use lower energy bound to find index for RealFilters - deltas = np.abs(self.bins[:, 1] - filter_bin[1]) / filter_bin[1] - min_delta = np.min(deltas) - if min_delta < 1E-3: - return deltas.argmin() - else: - msg = 'Unable to get the bin index for Filter since "{0}" ' \ - 'is not one of the bins'.format(filter_bin) - raise ValueError(msg) - - def check_bins(self, bins): - super().check_bins(bins) - for v0, v1 in bins: - cv.check_greater_than('filter value', v0, 0., equality=True) - cv.check_greater_than('filter value', v1, 0., equality=True) - - -class EnergyoutFilter(EnergyFilter): - """Bins tally events based on outgoing particle energy. - - Parameters - ---------- - values : Iterable of Real - A list of values for which each successive pair constitutes a range of - energies in [eV] for a single bin - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - energies in [eV] for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of energies in [eV] - for a single filter bin - num_bins : int - The number of filter bins - - """ - - -def _path_to_levels(path): - """Convert distribcell path to list of levels - - Parameters - ---------- - path : str - Distribcell path - - Returns - ------- - list - List of levels in path - - """ - # Split path into universes/cells/lattices - path_items = path.split('->') - - # Pair together universe and cell information from the same level - idx = [i for i, item in enumerate(path_items) if item.startswith('u')] - for i in reversed(idx): - univ_id = int(path_items.pop(i)[1:]) - cell_id = int(path_items.pop(i)[1:]) - path_items.insert(i, ('universe', univ_id, cell_id)) - - # Reformat lattice into tuple - idx = [i for i, item in enumerate(path_items) if isinstance(item, str)] - for i in idx: - item = path_items.pop(i)[1:-1] - lat_id, lat_xyz = item.split('(') - lat_id = int(lat_id) - lat_xyz = tuple(int(x) for x in lat_xyz.split(',')) - path_items.insert(i, ('lattice', lat_id, lat_xyz)) - - return path_items - - -class DistribcellFilter(Filter): - """Bins tally event locations on instances of repeated cells. - - Parameters - ---------- - cell : openmc.Cell or Integral - The distributed cell to tally. Either an openmc.Cell or an Integral - cell ID number can be used. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : Iterable of Integral - An iterable with one element---the ID of the distributed Cell. - id : int - Unique identifier for the filter - num_bins : int - The number of filter bins - paths : list of str - The paths traversed through the CSG tree to reach each distribcell - instance (for 'distribcell' filters only) - - """ - - def __init__(self, cell, filter_id=None): - self._paths = None - super().__init__(cell, filter_id) - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - out = cls(group['bins'][()], filter_id=filter_id) - out._num_bins = group['n_bins'][()] - - return out - - @property - 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 - - @Filter.bins.setter - def bins(self, bins): - # Format the bins as a 1D numpy array. - bins = np.atleast_1d(bins) - - # Make sure there is only 1 bin. - if not len(bins) == 1: - msg = 'Unable to add bins "{0}" to a DistribcellFilter since ' \ - 'only a single distribcell can be used per tally'.format(bins) - raise ValueError(msg) - - # Check the type and extract the id, if necessary. - cv.check_type('distribcell bin', bins[0], (Integral, openmc.Cell)) - if isinstance(bins[0], openmc.Cell): - bins = np.atleast_1d(bins[0].id) - - self._bins = bins - - @paths.setter - def paths(self, paths): - cv.check_iterable_type('paths', paths, str) - self._paths = paths - - def can_merge(self, other): - # Distribcell filters cannot have more than one bin - return False - - def get_bin_index(self, filter_bin): - # Filter bins for distribcells are indices of each unique placement of - # the Cell in the Geometry (consecutive integers starting at 0). - return filter_bin - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - 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 - 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 the same universes and cells but - different lattice cell indices. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with columns describing distributed cells. The - for will be either: - - 1. a single column with the cell instance IDs (without summary info) - 2. separate columns for the cell IDs, universe IDs, and lattice IDs - and x,y,z cell indices corresponding to each (distribcell paths). - - The number of rows in the DataFrame is the same as the total number - of bins in the corresponding tally, with the filter bin - appropriately tiled to map to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - level_df = None - - paths = kwargs.setdefault('paths', True) - - # Create Pandas Multi-index columns for each level in CSG tree - if paths: - - # Distribcell paths require linked metadata from the Summary - if self.paths is None: - msg = 'Unable to construct distribcell paths since ' \ - 'the Summary is not linked to the StatePoint' - raise ValueError(msg) - - # Make copy of array of distribcell paths to use in - # Pandas Multi-index column construction - num_offsets = len(self.paths) - paths = [_path_to_levels(p) for p in self.paths] - - # Loop over CSG levels in the distribcell paths - num_levels = len(paths[0]) - for i_level in range(num_levels): - # Use level key as first index in Pandas Multi-index column - level_key = 'level {}'.format(i_level + 1) - - # Create a dictionary for this level for Pandas Multi-index - level_dict = OrderedDict() - - # Use the first distribcell path to determine if level - # is a universe/cell or lattice level - path = paths[0] - if path[i_level][0] == 'lattice': - # Initialize prefix Multi-index keys - lat_id_key = (level_key, 'lat', 'id') - lat_x_key = (level_key, 'lat', 'x') - lat_y_key = (level_key, 'lat', 'y') - lat_z_key = (level_key, 'lat', 'z') - - # Allocate NumPy arrays for each CSG level and - # each Multi-index column in the DataFrame - level_dict[lat_id_key] = np.empty(num_offsets) - level_dict[lat_x_key] = np.empty(num_offsets) - level_dict[lat_y_key] = np.empty(num_offsets) - if len(path[i_level][2]) == 3: - level_dict[lat_z_key] = np.empty(num_offsets) - - else: - # Initialize prefix Multi-index keys - univ_key = (level_key, 'univ', 'id') - cell_key = (level_key, 'cell', 'id') - - # Allocate NumPy arrays for each CSG level and - # each Multi-index column in the DataFrame - level_dict[univ_key] = np.empty(num_offsets) - level_dict[cell_key] = np.empty(num_offsets) - - # Populate Multi-index arrays with all distribcell paths - for i, path in enumerate(paths): - - level = path[i_level] - if level[0] == 'lattice': - # Assign entry to Lattice Multi-index column - level_dict[lat_id_key][i] = level[1] - level_dict[lat_x_key][i] = level[2][0] - level_dict[lat_y_key][i] = level[2][1] - if len(level[2]) == 3: - level_dict[lat_z_key][i] = level[2][2] - - else: - # Assign entry to Universe, Cell Multi-index columns - level_dict[univ_key][i] = level[1] - level_dict[cell_key][i] = level[2] - - # Tile the Multi-index columns - for level_key, level_bins in level_dict.items(): - 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 - - # Initialize a Pandas DataFrame from the level dictionary - if level_df is None: - level_df = pd.DataFrame(level_dict) - else: - level_df = pd.concat([level_df, pd.DataFrame(level_dict)], - axis=1) - - # Create DataFrame column for distribcell instance IDs - # NOTE: This is performed regardless of whether the user - # requests Summary geometric information - filter_bins = np.arange(self.num_bins) - filter_bins = np.repeat(filter_bins, 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}) - - # Concatenate with DataFrame of distribcell instance IDs - if level_df is not None: - level_df = level_df.dropna(axis=1, how='all') - level_df = level_df.astype(np.int) - df = pd.concat([level_df, df], axis=1) - - return df - - -class MuFilter(RealFilter): - """Bins tally events based on particle scattering angle. - - Parameters - ---------- - values : int or Iterable of Real - A grid of scattering angles which events will binned into. Values - represent the cosine of the scattering angle. If an iterable is given, - the values will be used explicitly as grid points. If a single int is - given, the range [-1, 1] will be divided up equally into that number of - bins. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - scattering angle cosines for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of scattering angle - cosines for a single filter bin - num_bins : Integral - The number of filter bins - - """ - def __init__(self, values, filter_id=None): - if isinstance(values, Integral): - values = np.linspace(-1., 1., values + 1) - super().__init__(values, filter_id) - - def check_bins(self, bins): - super().check_bins(bins) - for x in np.ravel(bins): - if not np.isclose(x, -1.): - cv.check_greater_than('filter value', x, -1., equality=True) - if not np.isclose(x, 1.): - cv.check_less_than('filter value', x, 1., equality=True) - - -class PolarFilter(RealFilter): - """Bins tally events based on the incident particle's direction. - - Parameters - ---------- - values : int or Iterable of Real - A grid of polar angles which events will binned into. Values represent - an angle in radians relative to the z-axis. If an iterable is given, the - values will be used explicitly as grid points. If a single int is given, - the range [0, pi] will be divided up equally into that number of bins. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - polar angles in [rad] for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of polar angles for a - single filter bin - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - units = 'rad' - - def __init__(self, values, filter_id=None): - if isinstance(values, Integral): - values = np.linspace(0., np.pi, values + 1) - super().__init__(values, filter_id) - - def check_bins(self, bins): - super().check_bins(bins) - for x in np.ravel(bins): - if not np.isclose(x, 0.): - cv.check_greater_than('filter value', x, 0., equality=True) - if not np.isclose(x, np.pi): - cv.check_less_than('filter value', x, np.pi, equality=True) - - -class AzimuthalFilter(RealFilter): - """Bins tally events based on the incident particle's direction. - - Parameters - ---------- - values : int or Iterable of Real - A grid of azimuthal angles which events will binned into. Values - represent an angle in radians relative to the x-axis and perpendicular - to the z-axis. If an iterable is given, the values will be used - explicitly as grid points. If a single int is given, the range - [-pi, pi) will be divided up equally into that number of bins. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - values : numpy.ndarray - An array of values for which each successive pair constitutes a range of - azimuthal angles in [rad] for a single bin - id : int - Unique identifier for the filter - bins : numpy.ndarray - An array of shape (N, 2) where each row is a pair of azimuthal angles - for a single filter bin - num_bins : Integral - The number of filter bins - - """ - units = 'rad' - - def __init__(self, values, filter_id=None): - if isinstance(values, Integral): - values = np.linspace(-np.pi, np.pi, values + 1) - super().__init__(values, filter_id) - - def check_bins(self, bins): - super().check_bins(bins) - for x in np.ravel(bins): - if not np.isclose(x, -np.pi): - cv.check_greater_than('filter value', x, -np.pi, equality=True) - if not np.isclose(x, np.pi): - cv.check_less_than('filter value', x, np.pi, equality=True) - - -class DelayedGroupFilter(Filter): - """Bins fission events based on the produced neutron precursor groups. - - Parameters - ---------- - bins : iterable of int - The delayed neutron precursor groups. For example, ENDF/B-VII.1 uses - 6 precursor groups so a tally with all groups will have bins = - [1, 2, 3, 4, 5, 6]. - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - bins : iterable of int - The delayed neutron precursor groups. For example, ENDF/B-VII.1 uses - 6 precursor groups so a tally with all groups will have bins = - [1, 2, 3, 4, 5, 6]. - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins - - """ - def check_bins(self, bins): - # Check the bin values. - for g in bins: - cv.check_greater_than('delayed group', g, 0) - - -class EnergyFunctionFilter(Filter): - """Multiplies tally scores by an arbitrary function of incident energy. - - The arbitrary function is described by a piecewise linear-linear - interpolation of energy and y values. Values outside of the given energy - range will be evaluated as zero. - - Parameters - ---------- - energy : Iterable of Real - A grid of energy values in [eV] - y : iterable of Real - A grid of interpolant values in [eV] - filter_id : int - Unique identifier for the filter - - Attributes - ---------- - energy : Iterable of Real - A grid of energy values in [eV] - y : iterable of Real - A grid of interpolant values in [eV] - id : int - Unique identifier for the filter - num_bins : Integral - The number of filter bins (always 1 for this filter) - - """ - - def __init__(self, energy, y, filter_id=None): - self.energy = energy - self.y = y - self.id = filter_id - - def __eq__(self, other): - if type(self) is not type(other): - return False - elif not all(self.energy == other.energy): - return False - elif not all(self.y == other.y): - return False - else: - return True - - def __gt__(self, other): - if type(self) is not type(other): - if self.short_name in _FILTER_TYPES and \ - other.short_name in _FILTER_TYPES: - delta = _FILTER_TYPES.index(self.short_name) - \ - _FILTER_TYPES.index(other.short_name) - return delta > 0 - else: - return False - else: - return False - - def __lt__(self, other): - if type(self) is not type(other): - if self.short_name in _FILTER_TYPES and \ - other.short_name in _FILTER_TYPES: - delta = _FILTER_TYPES.index(self.short_name) - \ - _FILTER_TYPES.index(other.short_name) - return delta < 0 - else: - return False - else: - return False - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tEnergy', self.energy) - string += '{: <16}=\t{}\n'.format('\tInterpolant', self.y) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tEnergy', self.energy) - string += '{: <16}=\t{}\n'.format('\tInterpolant', self.y) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - energy = group['energy'][()] - y = group['y'][()] - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - return cls(energy, y, filter_id=filter_id) - - @classmethod - def from_tabulated1d(cls, tab1d): - """Construct a filter from a Tabulated1D object. - - Parameters - ---------- - tab1d : openmc.data.Tabulated1D - A linear-linear Tabulated1D object with only a single interpolation - region. - - Returns - ------- - EnergyFunctionFilter - - """ - cv.check_type('EnergyFunctionFilter tab1d', tab1d, - openmc.data.Tabulated1D) - if tab1d.n_regions > 1: - raise ValueError('Only Tabulated1Ds with a single interpolation ' - 'region are supported') - if tab1d.interpolation[0] != 2: - raise ValueError('Only linear-linar Tabulated1Ds are supported') - - return cls(tab1d.x, tab1d.y) - - @property - def energy(self): - return self._energy - - @property - def y(self): - return self._y - - @property - def bins(self): - raise AttributeError('EnergyFunctionFilters have no bins.') - - @property - def num_bins(self): - return 1 - - @energy.setter - def energy(self, energy): - # Format the bins as a 1D numpy array. - energy = np.atleast_1d(energy) - - # Make sure the values are Real and positive. - cv.check_type('filter energy grid', energy, Iterable, Real) - for E in energy: - cv.check_greater_than('filter energy grid', E, 0, equality=True) - - self._energy = energy - - @y.setter - def y(self, y): - # Format the bins as a 1D numpy array. - y = np.atleast_1d(y) - - # Make sure the values are Real. - cv.check_type('filter interpolant values', y, Iterable, Real) - - self._y = y - - @bins.setter - def bins(self, bins): - raise RuntimeError('EnergyFunctionFilters have no bins.') - - def to_xml_element(self): - """Return XML Element representing the Filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing filter data - - """ - element = ET.Element('filter') - element.set('id', str(self.id)) - element.set('type', self.short_name.lower()) - - subelement = ET.SubElement(element, 'energy') - subelement.text = ' '.join(str(e) for e in self.energy) - - subelement = ET.SubElement(element, 'y') - subelement.text = ' '.join(str(y) for y in self.y) - - return element - - def can_merge(self, other): - return False - - def is_subset(self, other): - return self == other - - def get_bin_index(self, filter_bin): - # This filter only has one bin. Always return 0. - return 0 - - 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 - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - data_size : int - The total number of bins in the tally corresponding to this filter - stride : int - Stride in memory for the filter - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with a column that is filled with a hash of this - filter. EnergyFunctionFilters have only 1 bin so the purpose of this - DataFrame column is to differentiate the filter from other - EnergyFunctionFilters. The number of rows in the DataFrame is the - same as the total number of bins in the corresponding tally. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - df = pd.DataFrame() - - # There is no clean way of sticking all the energy, y data into a - # DataFrame so instead we'll just make a column with the filter name - # and fill it with a hash of the __repr__. We want a hash that is - # reproducible after restarting the interpreter so we'll use hashlib.md5 - # rather than the intrinsic hash(). - hash_fun = hashlib.md5() - hash_fun.update(repr(self).encode('utf-8')) - out = hash_fun.hexdigest() - - # The full 16 bytes make for a really wide column. Just 7 bytes (14 - # hex characters) of the digest are probably sufficient. - out = out[:14] - - 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( - {self.short_name.lower(): filter_bins})]) - - return df diff --git a/openmc/filter_expansion.py b/openmc/filter_expansion.py deleted file mode 100644 index cc085df8a..000000000 --- a/openmc/filter_expansion.py +++ /dev/null @@ -1,528 +0,0 @@ -from numbers import Integral, Real -from xml.etree import ElementTree as ET - -import numpy as np -import pandas as pd - -import openmc.checkvalue as cv -from . import Filter - - -class ExpansionFilter(Filter): - """Abstract filter class for functional expansions.""" - - def __init__(self, order, filter_id=None): - self.order = order - self.id = filter_id - - def __eq__(self, other): - if type(self) is not type(other): - return False - else: - return hash(self) == hash(other) - - @property - def order(self): - return self._order - - @order.setter - def order(self, order): - cv.check_type('expansion order', order, Integral) - cv.check_greater_than('expansion order', order, 0, equality=True) - self._order = order - - def to_xml_element(self): - """Return XML Element representing the filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Legendre filter data - - """ - element = ET.Element('filter') - element.set('id', str(self.id)) - element.set('type', self.short_name.lower()) - - subelement = ET.SubElement(element, 'order') - subelement.text = str(self.order) - - return element - - -class LegendreFilter(ExpansionFilter): - r"""Score Legendre expansion moments up to specified order. - - This filter allows scores to be multiplied by Legendre polynomials of the - change in particle angle (:math:`\mu`) up to a user-specified order. - - Parameters - ---------- - order : int - Maximum Legendre polynomial order - filter_id : int or None - Unique identifier for the filter - - Attributes - ---------- - order : int - Maximum Legendre polynomial order - id : int - Unique identifier for the filter - num_bins : int - The number of filter bins - - """ - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @ExpansionFilter.order.setter - def order(self, order): - ExpansionFilter.order.__set__(self, order) - self.bins = ['P{}'.format(i) for i in range(order + 1)] - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - out = cls(group['order'][()], filter_id) - - return out - - -class SpatialLegendreFilter(ExpansionFilter): - r"""Score Legendre expansion moments in space up to specified order. - - This filter allows scores to be multiplied by Legendre polynomials of the - the particle's position along a particular axis, normalized to a given - range, up to a user-specified order. - - Parameters - ---------- - order : int - Maximum Legendre polynomial order - axis : {'x', 'y', 'z'} - Axis along which to take the expansion - minimum : float - Minimum value along selected axis - maximum : float - Maximum value along selected axis - filter_id : int or None - Unique identifier for the filter - - Attributes - ---------- - order : int - Maximum Legendre polynomial order - axis : {'x', 'y', 'z'} - Axis along which to take the expansion - minimum : float - Minimum value along selected axis - maximum : float - Maximum value along selected axis - id : int - Unique identifier for the filter - num_bins : int - The number of filter bins - - """ - - def __init__(self, order, axis, minimum, maximum, filter_id=None): - super().__init__(order, filter_id) - self.axis = axis - self.minimum = minimum - self.maximum = maximum - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tAxis', self.axis) - string += '{: <16}=\t{}\n'.format('\tMin', self.minimum) - string += '{: <16}=\t{}\n'.format('\tMax', self.maximum) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tAxis', self.axis) - string += '{: <16}=\t{}\n'.format('\tMin', self.minimum) - string += '{: <16}=\t{}\n'.format('\tMax', self.maximum) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @ExpansionFilter.order.setter - def order(self, order): - ExpansionFilter.order.__set__(self, order) - self.bins = ['P{}'.format(i) for i in range(order + 1)] - - @property - def axis(self): - return self._axis - - @axis.setter - def axis(self, axis): - cv.check_value('axis', axis, ('x', 'y', 'z')) - self._axis = axis - - @property - def minimum(self): - return self._minimum - - @minimum.setter - def minimum(self, minimum): - cv.check_type('minimum', minimum, Real) - self._minimum = minimum - - @property - def maximum(self): - return self._maximum - - @maximum.setter - def maximum(self, maximum): - cv.check_type('maximum', maximum, Real) - self._maximum = maximum - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - order = group['order'][()] - axis = group['axis'][()].decode() - min_, max_ = group['min'][()], group['max'][()] - - return cls(order, axis, min_, max_, filter_id) - - def to_xml_element(self): - """Return XML Element representing the filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Legendre filter data - - """ - element = super().to_xml_element() - subelement = ET.SubElement(element, 'axis') - subelement.text = self.axis - subelement = ET.SubElement(element, 'min') - subelement.text = str(self.minimum) - subelement = ET.SubElement(element, 'max') - subelement.text = str(self.maximum) - - return element - - -class SphericalHarmonicsFilter(ExpansionFilter): - r"""Score spherical harmonic expansion moments up to specified order. - - This filter allows you to obtain real spherical harmonic moments of either - the particle's direction or the cosine of the scattering angle. Specifying - a filter with order :math:`\ell` tallies moments for all orders from 0 to - :math:`\ell`. - - Parameters - ---------- - order : int - Maximum spherical harmonics order, :math:`\ell` - filter_id : int or None - Unique identifier for the filter - - Attributes - ---------- - order : int - Maximum spherical harmonics order, :math:`\ell` - id : int - Unique identifier for the filter - cosine : {'scatter', 'particle'} - How to handle the cosine term. - num_bins : int - The number of filter bins - - """ - - def __init__(self, order, filter_id=None): - super().__init__(order, filter_id) - self._cosine = 'particle' - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tCosine', self.cosine) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tCosine', self.cosine) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @ExpansionFilter.order.setter - def order(self, order): - ExpansionFilter.order.__set__(self, order) - self.bins = ['Y{},{}'.format(n, m) - for n in range(order + 1) - for m in range(-n, n + 1)] - - @property - def cosine(self): - return self._cosine - - @cosine.setter - def cosine(self, cosine): - cv.check_value('Spherical harmonics cosine treatment', cosine, - ('scatter', 'particle')) - self._cosine = cosine - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - - out = cls(group['order'][()], filter_id) - out.cosine = group['cosine'][()].decode() - - return out - - def to_xml_element(self): - """Return XML Element representing the filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing spherical harmonics filter data - - """ - element = super().to_xml_element() - element.set('cosine', self.cosine) - return element - - -class ZernikeFilter(ExpansionFilter): - r"""Score Zernike expansion moments in space up to specified order. - - This filter allows scores to be multiplied by Zernike polynomials of the - particle's position normalized to a given unit circle, up to a - user-specified order. The standard Zernike polynomials follow the - definition by Born and Wolf, *Principles of Optics* and are defined as - - .. math:: - Z_n^m(\rho, \theta) = R_n^m(\rho) \cos (m\theta), \quad m > 0 - - Z_n^{m}(\rho, \theta) = R_n^{m}(\rho) \sin (m\theta), \quad m < 0 - - Z_n^{m}(\rho, \theta) = R_n^{m}(\rho), \quad m = 0 - - where the radial polynomials are - - .. math:: - R_n^m(\rho) = \sum\limits_{k=0}^{(n-m)/2} \frac{(-1)^k (n-k)!}{k! ( - \frac{n+m}{2} - k)! (\frac{n-m}{2} - k)!} \rho^{n-2k}. - - With this definition, the integral of :math:`(Z_n^m)^2` over the unit disk - is :math:`\frac{\epsilon_m\pi}{2n+2}` for each polynomial where - :math:`\epsilon_m` is 2 if :math:`m` equals 0 and 1 otherwise. - - Specifying a filter with order N tallies moments for all :math:`n` from 0 - to N and each value of :math:`m`. The ordering of the Zernike polynomial - moments follows the ANSI Z80.28 standard, where the one-dimensional index - :math:`j` corresponds to the :math:`n` and :math:`m` by - - .. math:: - j = \frac{n(n + 2) + m}{2}. - - Parameters - ---------- - order : int - Maximum Zernike polynomial order - x : float - x-coordinate of center of circle for normalization - y : float - y-coordinate of center of circle for normalization - r : int or None - Radius of circle for normalization - - Attributes - ---------- - order : int - Maximum Zernike polynomial order - x : float - x-coordinate of center of circle for normalization - y : float - y-coordinate of center of circle for normalization - r : int or None - Radius of circle for normalization - id : int - Unique identifier for the filter - num_bins : int - The number of filter bins - - """ - - def __init__(self, order, x=0.0, y=0.0, r=1.0, filter_id=None): - super().__init__(order, filter_id) - self.x = x - self.y = y - self.r = r - - def __hash__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tX', self.x) - string += '{: <16}=\t{}\n'.format('\tY', self.y) - string += '{: <16}=\t{}\n'.format('\tR', self.r) - return hash(string) - - def __repr__(self): - string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tOrder', self.order) - string += '{: <16}=\t{}\n'.format('\tID', self.id) - return string - - @ExpansionFilter.order.setter - def order(self, order): - ExpansionFilter.order.__set__(self, order) - self.bins = ['Z{},{}'.format(n, m) - for n in range(order + 1) - for m in range(-n, n + 1, 2)] - - @property - def x(self): - return self._x - - @x.setter - def x(self, x): - cv.check_type('x', x, Real) - self._x = x - - @property - def y(self): - return self._y - - @y.setter - def y(self, y): - cv.check_type('y', y, Real) - self._y = y - - @property - def r(self): - return self._r - - @r.setter - def r(self, r): - cv.check_type('r', r, Real) - self._r = r - - @classmethod - def from_hdf5(cls, group, **kwargs): - if group['type'][()].decode() != cls.short_name.lower(): - raise ValueError("Expected HDF5 data for filter type '" - + cls.short_name.lower() + "' but got '" - + group['type'][()].decode() + " instead") - - filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - order = group['order'][()] - x, y, r = group['x'][()], group['y'][()], group['r'][()] - - return cls(order, x, y, r, filter_id) - - def to_xml_element(self): - """Return XML Element representing the filter. - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Zernike filter data - - """ - element = super().to_xml_element() - subelement = ET.SubElement(element, 'x') - subelement.text = str(self.x) - subelement = ET.SubElement(element, 'y') - subelement.text = str(self.y) - subelement = ET.SubElement(element, 'r') - subelement.text = str(self.r) - - return element - - -class ZernikeRadialFilter(ZernikeFilter): - r"""Score the :math:`m = 0` (radial variation only) Zernike moments up to - specified order. - - The Zernike polynomials are defined the same as in :class:`ZernikeFilter`. - - .. math:: - - Z_n^{0}(\rho, \theta) = R_n^{0}(\rho) - - where the radial polynomials are - - .. math:: - R_n^{0}(\rho) = \sum\limits_{k=0}^{n/2} \frac{(-1)^k (n-k)!}{k! (( - \frac{n}{2} - k)!)^{2}} \rho^{n-2k}. - - With this definition, the integral of :math:`(Z_n^0)^2` over the unit disk - is :math:`\frac{\pi}{n+1}`. - - If there is only radial dependency, the polynomials are integrated over - the azimuthal angles. The only terms left are :math:`Z_n^{0}(\rho, \theta) - = R_n^{0}(\rho)`. Note that :math:`n` could only be even orders. - Therefore, for a radial Zernike polynomials up to order of :math:`n`, - there are :math:`\frac{n}{2} + 1` terms in total. The indexing is from the - lowest even order (0) to highest even order. - - Parameters - ---------- - order : int - Maximum radial Zernike polynomial order - x : float - x-coordinate of center of circle for normalization - y : float - y-coordinate of center of circle for normalization - r : int or None - Radius of circle for normalization - - Attributes - ---------- - order : int - Maximum radial Zernike polynomial order - x : float - x-coordinate of center of circle for normalization - y : float - y-coordinate of center of circle for normalization - r : int or None - Radius of circle for normalization - id : int - Unique identifier for the filter - num_bins : int - The number of filter bins - - """ - - @ExpansionFilter.order.setter - def order(self, order): - ExpansionFilter.order.__set__(self, order) - self.bins = ['Z{},0'.format(n) for n in range(0, order+1, 2)] diff --git a/openmc/geometry.py b/openmc/geometry.py deleted file mode 100644 index 260bb9e83..000000000 --- a/openmc/geometry.py +++ /dev/null @@ -1,610 +0,0 @@ -from collections import OrderedDict, defaultdict -from collections.abc import Iterable -from copy import deepcopy -from pathlib import Path -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc -import openmc._xml as xml -from openmc.checkvalue import check_type - - -class Geometry(object): - """Geometry representing a collection of surfaces, cells, and universes. - - Parameters - ---------- - root : openmc.Universe or Iterable of openmc.Cell, optional - Root universe which contains all others, or an iterable of cells that - should be used to create a root universe. - - Attributes - ---------- - root_universe : openmc.Universe - Root universe which contains all others - bounding_box : 2-tuple of numpy.array - Lower-left and upper-right coordinates of an axis-aligned bounding box - of the universe. - - """ - - def __init__(self, root=None): - self._root_universe = None - self._offsets = {} - if root is not None: - if isinstance(root, openmc.Universe): - self.root_universe = root - else: - univ = openmc.Universe() - for cell in root: - univ.add_cell(cell) - self._root_universe = univ - - @property - def root_universe(self): - return self._root_universe - - @property - def bounding_box(self): - return self.root_universe.bounding_box - - @root_universe.setter - def root_universe(self, root_universe): - check_type('root universe', root_universe, openmc.Universe) - self._root_universe = root_universe - - def add_volume_information(self, volume_calc): - """Add volume information from a stochastic volume calculation. - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if volume_calc.domain_type == 'cell': - for cell in self.get_all_cells().values(): - if cell.id in volume_calc.volumes: - cell.add_volume_information(volume_calc) - elif volume_calc.domain_type == 'material': - for material in self.get_all_materials().values(): - if material.id in volume_calc.volumes: - material.add_volume_information(volume_calc) - elif volume_calc.domain_type == 'universe': - for universe in self.get_all_universes().values(): - if universe.id in volume_calc.volumes: - universe.add_volume_information(volume_calc) - - def export_to_xml(self, path='geometry.xml'): - """Export geometry to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'geometry.xml'. - - """ - # Create XML representation - root_element = ET.Element("geometry") - self.root_universe.create_xml_subelement(root_element) - - # Sort the elements in the file - root_element[:] = sorted(root_element, key=lambda x: ( - x.tag, int(x.get('id')))) - - # Clean the indentation in the file to be user-readable - xml.clean_indentation(root_element) - - # Check if path is a directory - p = Path(path) - if p.is_dir(): - p /= 'geometry.xml' - - # Write the XML Tree to the geometry.xml file - tree = ET.ElementTree(root_element) - tree.write(str(p), xml_declaration=True, encoding='utf-8') - - @classmethod - def from_xml(cls, path='geometry.xml', materials=None): - """Generate geometry from XML file - - Parameters - ---------- - path : str, optional - Path to geometry XML file - materials : openmc.Materials or None - Materials used to assign to cells. If None, an attempt is made to - generate it from the materials.xml file. - - Returns - ------- - openmc.Geometry - Geometry object - - """ - # Helper function for keeping a cache of Universe instances - universes = {} - def get_universe(univ_id): - if univ_id not in universes: - univ = openmc.Universe(univ_id) - universes[univ_id] = univ - return universes[univ_id] - - tree = ET.parse(path) - root = tree.getroot() - - # Get surfaces - surfaces = {} - periodic = {} - for surface in root.findall('surface'): - s = openmc.Surface.from_xml_element(surface) - surfaces[s.id] = s - - # Check for periodic surface - other_id = xml.get_text(surface, 'periodic_surface_id') - if other_id is not None: - periodic[s.id] = int(other_id) - - # Apply periodic surfaces - for s1, s2 in periodic.items(): - surfaces[s1].periodic_surface = surfaces[s2] - - # Dictionary that maps each universe to a list of cells/lattices that - # contain it (needed to determine which universe is the root) - child_of = defaultdict(list) - - for elem in root.findall('lattice'): - lat = openmc.RectLattice.from_xml_element(elem, get_universe) - universes[lat.id] = lat - if lat.outer is not None: - child_of[lat.outer].append(lat) - for u in lat.universes.ravel(): - child_of[u].append(lat) - - for elem in root.findall('hex_lattice'): - lat = openmc.HexLattice.from_xml_element(elem, get_universe) - universes[lat.id] = lat - if lat.outer is not None: - child_of[lat.outer].append(lat) - if lat.ndim == 2: - for ring in lat.universes: - for u in ring: - child_of[u].append(lat) - else: - for axial_slice in lat.universes: - for ring in axial_slice: - for u in ring: - child_of[u].append(lat) - - # Create dictionary to easily look up materials - if materials is None: - filename = Path(path).parent / 'materials.xml' - materials = openmc.Materials.from_xml(str(filename)) - mats = {str(m.id): m for m in materials} - mats['void'] = None - - for elem in root.findall('cell'): - c = openmc.Cell.from_xml_element(elem, surfaces, mats, get_universe) - if c.fill_type in ('universe', 'lattice'): - child_of[c.fill].append(c) - - # Determine which universe is the root by finding one which is not a - # child of any other object - for u in universes.values(): - if not child_of[u]: - return cls(u) - else: - raise ValueError('Error determining root universe.') - - def find(self, point): - """Find cells/universes/lattices which contain a given point - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates of the point - - Returns - ------- - list - Sequence of universes, cells, and lattices which are traversed to - find the given point - - """ - return self.root_universe.find(point) - - def get_instances(self, paths): - """Return the instance number(s) for a cell/material in a geometry path. - - The instance numbers are used as indices into distributed - material/temperature arrays and tally distribcell filter arrays. - - Parameters - ---------- - paths : str or iterable of str - The path traversed through the CSG tree to reach a cell or material - instance. For example, 'u0->c10->l20(2,2,1)->u5->c5' would indicate - the cell instance whose first level is universe 0 and cell 10, - second level is lattice 20 position (2,2,1), and third level is - universe 5 and cell 5. - - Returns - ------- - int or list of int - Instance number(s) for the given path(s) - - """ - # Make sure we are working with an iterable - return_list = (isinstance(paths, Iterable) and - not isinstance(paths, str)) - path_list = paths if return_list else [paths] - - indices = [] - for p in path_list: - # Extract the cell id from the path - last_index = p.rfind('>') - last_path = p[last_index+1:] - uid = int(last_path[1:]) - - # Get corresponding cell/material - if last_path[0] == 'c': - obj = self.get_all_cells()[uid] - elif last_path[0] == 'm': - obj = self.get_all_materials()[uid] - - # Determine index in paths array - try: - indices.append(obj.paths.index(p)) - except ValueError: - indices.append(None) - - return indices if return_list else indices[0] - - def get_all_cells(self): - """Return all cells in the geometry. - - Returns - ------- - collections.OrderedDict - Dictionary mapping cell IDs to :class:`openmc.Cell` instances - - """ - if self.root_universe is not None: - return self.root_universe.get_all_cells() - else: - return [] - - def get_all_universes(self): - """Return all universes in the geometry. - - Returns - ------- - collections.OrderedDict - Dictionary mapping universe IDs to :class:`openmc.Universe` - instances - - """ - universes = OrderedDict() - universes[self.root_universe.id] = self.root_universe - universes.update(self.root_universe.get_all_universes()) - return universes - - def get_all_materials(self): - """Return all materials within the geometry. - - Returns - ------- - collections.OrderedDict - Dictionary mapping material IDs to :class:`openmc.Material` - instances - - """ - return self.root_universe.get_all_materials() - - def get_all_material_cells(self): - """Return all cells filled by a material - - Returns - ------- - collections.OrderedDict - Dictionary mapping cell IDs to :class:`openmc.Cell` instances that - are filled with materials or distributed materials. - - """ - material_cells = OrderedDict() - - for cell in self.get_all_cells().values(): - if cell.fill_type in ('material', 'distribmat'): - if cell not in material_cells: - material_cells[cell.id] = cell - - return material_cells - - def get_all_material_universes(self): - """Return all universes having at least one material-filled cell. - - This method can be used to find universes that have at least one cell - that is filled with a material or is void. - - Returns - ------- - collections.OrderedDict - Dictionary mapping universe IDs to :class:`openmc.Universe` - instances with at least one material-filled cell - - """ - material_universes = OrderedDict() - - for universe in self.get_all_universes().values(): - for cell in universe.cells.values(): - if cell.fill_type in ('material', 'distribmat', 'void'): - if universe not in material_universes: - material_universes[universe.id] = universe - - return material_universes - - def get_all_lattices(self): - """Return all lattices defined - - Returns - ------- - collections.OrderedDict - Dictionary mapping lattice IDs to :class:`openmc.Lattice` instances - - """ - lattices = OrderedDict() - - for cell in self.get_all_cells().values(): - if cell.fill_type == 'lattice': - if cell.fill.id not in lattices: - lattices[cell.fill.id] = cell.fill - - return lattices - - def get_all_surfaces(self): - """ - Return all surfaces used in the geometry - - Returns - ------- - collections.OrderedDict - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - """ - surfaces = OrderedDict() - - for cell in self.get_all_cells().values(): - surfaces = cell.region.get_surfaces(surfaces) - return surfaces - - def get_materials_by_name(self, name, case_sensitive=False, matching=False): - """Return a list of materials with matching names. - - Parameters - ---------- - name : str - The name to match - case_sensitive : bool - Whether to distinguish upper and lower case letters in each - material's name (default is False) - matching : bool - Whether the names must match completely (default is False) - - Returns - ------- - list of openmc.Material - Materials matching the queried name - - """ - - if not case_sensitive: - name = name.lower() - - all_materials = self.get_all_materials().values() - materials = set() - - for material in all_materials: - material_name = material.name - if not case_sensitive: - material_name = material_name.lower() - - if material_name == name: - materials.add(material) - elif not matching and name in material_name: - materials.add(material) - - return sorted(materials, key=lambda x: x.id) - - def get_cells_by_name(self, name, case_sensitive=False, matching=False): - """Return a list of cells with matching names. - - Parameters - ---------- - name : str - The name to search match - case_sensitive : bool - Whether to distinguish upper and lower case letters in each - cell's name (default is False) - matching : bool - Whether the names must match completely (default is False) - - Returns - ------- - list of openmc.Cell - Cells matching the queried name - - """ - - if not case_sensitive: - name = name.lower() - - all_cells = self.get_all_cells().values() - cells = set() - - for cell in all_cells: - cell_name = cell.name - if not case_sensitive: - cell_name = cell_name.lower() - - if cell_name == name: - cells.add(cell) - elif not matching and name in cell_name: - cells.add(cell) - - return sorted(cells, key=lambda x: x.id) - - def get_cells_by_fill_name(self, name, case_sensitive=False, matching=False): - """Return a list of cells with fills with matching names. - - Parameters - ---------- - name : str - The name to match - case_sensitive : bool - Whether to distinguish upper and lower case letters in each - cell's name (default is False) - matching : bool - Whether the names must match completely (default is False) - - Returns - ------- - list of openmc.Cell - Cells with fills matching the queried name - - """ - - if not case_sensitive: - name = name.lower() - - cells = set() - - for cell in self.get_all_cells().values(): - names = [] - if cell.fill_type in ('material', 'universe', 'lattice'): - names.append(cell.fill.name) - elif cell.fill_type == 'distribmat': - for mat in cell.fill: - if mat is not None: - names.append(mat.name) - - for fill_name in names: - if not case_sensitive: - fill_name = fill_name.lower() - - if fill_name == name: - cells.add(cell) - elif not matching and name in fill_name: - cells.add(cell) - - return sorted(cells, key=lambda x: x.id) - - def get_universes_by_name(self, name, case_sensitive=False, matching=False): - """Return a list of universes with matching names. - - Parameters - ---------- - name : str - The name to match - case_sensitive : bool - Whether to distinguish upper and lower case letters in each - universe's name (default is False) - matching : bool - Whether the names must match completely (default is False) - - Returns - ------- - list of openmc.Universe - Universes matching the queried name - - """ - - if not case_sensitive: - name = name.lower() - - all_universes = self.get_all_universes().values() - universes = set() - - for universe in all_universes: - universe_name = universe.name - if not case_sensitive: - universe_name = universe_name.lower() - - if universe_name == name: - universes.add(universe) - elif not matching and name in universe_name: - universes.add(universe) - - return sorted(universes, key=lambda x: x.id) - - def get_lattices_by_name(self, name, case_sensitive=False, matching=False): - """Return a list of lattices with matching names. - - Parameters - ---------- - name : str - The name to match - case_sensitive : bool - Whether to distinguish upper and lower case letters in each - lattice's name (default is False) - matching : bool - Whether the names must match completely (default is False) - - Returns - ------- - list of openmc.Lattice - Lattices matching the queried name - - """ - - if not case_sensitive: - name = name.lower() - - all_lattices = self.get_all_lattices().values() - lattices = set() - - for lattice in all_lattices: - lattice_name = lattice.name - if not case_sensitive: - lattice_name = lattice_name.lower() - - if lattice_name == name: - lattices.add(lattice) - elif not matching and name in lattice_name: - lattices.add(lattice) - - return sorted(lattices, key=lambda x: x.id) - - def determine_paths(self, instances_only=False): - """Determine paths through CSG tree for cells and materials. - - This method recursively traverses the CSG tree to determine each unique - path that reaches every cell and material. The paths are stored in the - :attr:`Cell.paths` and :attr:`Material.paths` attributes. - - Parameters - ---------- - instances_only : bool, optional - If true, this method will only determine the number of instances of - each cell and material. - - """ - # (Re-)initialize all cell instances to 0 - for cell in self.get_all_cells().values(): - cell._paths = [] - cell._num_instances = 0 - for material in self.get_all_materials().values(): - material._paths = [] - material._num_instances = 0 - - # Recursively traverse the CSG tree to count all cell instances - self.root_universe._determine_paths(instances_only=instances_only) - - def clone(self): - """Create a copy of this geometry with new unique IDs for all of its - enclosed materials, surfaces, cells, universes and lattices.""" - - clone = deepcopy(self) - clone.root_universe = self.root_universe.clone() - return clone diff --git a/openmc/lattice.py b/openmc/lattice.py deleted file mode 100644 index 4776222da..000000000 --- a/openmc/lattice.py +++ /dev/null @@ -1,1901 +0,0 @@ -from abc import ABCMeta -from collections import OrderedDict -from collections.abc import Iterable -from copy import deepcopy -from math import sqrt, floor -from numbers import Real, Integral -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc.checkvalue as cv -import openmc -from openmc._xml import get_text -from openmc.mixin import IDManagerMixin - - -class Lattice(IDManagerMixin, metaclass=ABCMeta): - """A repeating structure wherein each element is a universe. - - Parameters - ---------- - lattice_id : int, optional - Unique identifier for the lattice. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the lattice. If not specified, the name is the empty string. - - Attributes - ---------- - id : int - Unique identifier for the lattice - name : str - Name of the lattice - pitch : Iterable of float - Pitch of the lattice in each direction in cm - outer : openmc.Universe - A universe to fill all space outside the lattice - universes : Iterable of Iterable of openmc.Universe - A two-or three-dimensional list/array of universes filling each element - of the lattice - - """ - - next_id = 1 - used_ids = openmc.Universe.used_ids - - def __init__(self, lattice_id=None, name=''): - # Initialize Lattice class attributes - self.id = lattice_id - self.name = name - self._pitch = None - self._outer = None - self._universes = None - - @property - def name(self): - return self._name - - @property - def pitch(self): - return self._pitch - - @property - def outer(self): - return self._outer - - @property - def universes(self): - return self._universes - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('lattice name', name, str) - self._name = name - else: - self._name = '' - - @outer.setter - def outer(self, outer): - cv.check_type('outer universe', outer, openmc.Universe) - self._outer = outer - - @staticmethod - def from_hdf5(group, universes): - """Create lattice from HDF5 group - - Parameters - ---------- - group : h5py.Group - Group in HDF5 file - universes : dict - Dictionary mapping universe IDs to instances of - :class:`openmc.Universe`. - - Returns - ------- - openmc.Lattice - Instance of lattice subclass - - """ - lattice_id = int(group.name.split('/')[-1].lstrip('lattice ')) - name = group['name'][()].decode() if 'name' in group else '' - lattice_type = group['type'][()].decode() - - if lattice_type == 'rectangular': - dimension = group['dimension'][...] - lower_left = group['lower_left'][...] - pitch = group['pitch'][...] - outer = group['outer'][()] - universe_ids = group['universes'][...] - - # Create the Lattice - lattice = openmc.RectLattice(lattice_id, name) - lattice.lower_left = lower_left - lattice.pitch = pitch - - # If the Universe specified outer the Lattice is not void - if outer >= 0: - lattice.outer = universes[outer] - - # Build array of Universe pointers for the Lattice - uarray = np.empty(universe_ids.shape, dtype=openmc.Universe) - - for z in range(universe_ids.shape[0]): - for y in range(universe_ids.shape[1]): - for x in range(universe_ids.shape[2]): - uarray[z, y, x] = universes[universe_ids[z, y, x]] - - # Use 2D NumPy array to store lattice universes for 2D lattices - if len(dimension) == 2: - uarray = np.squeeze(uarray) - uarray = np.atleast_2d(uarray) - - # Set the universes for the lattice - lattice.universes = uarray - - elif lattice_type == 'hexagonal': - n_rings = group['n_rings'][()] - n_axial = group['n_axial'][()] - center = group['center'][()] - pitch = group['pitch'][()] - outer = group['outer'][()] - if 'orientation' in group: - orientation = group['orientation'][()].decode() - else: - orientation = "y" - - universe_ids = group['universes'][()] - - # Create the Lattice - lattice = openmc.HexLattice(lattice_id, name) - lattice.center = center - lattice.pitch = pitch - lattice.orientation = orientation - # If the Universe specified outer the Lattice is not void - if outer >= 0: - lattice.outer = universes[outer] - if orientation == "y": - # Build array of Universe pointers for the Lattice. Note that - # we need to convert between the HDF5's square array of - # (x, alpha, z) to the Python API's format of a ragged nested - # list of (z, ring, theta). - uarray = [] - for z in range(n_axial): - # Add a list for this axial level. - uarray.append([]) - x = n_rings - 1 - a = 2*n_rings - 2 - for r in range(n_rings - 1, 0, -1): - # Add a list for this ring. - uarray[-1].append([]) - - # Climb down the top-right. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - x += 1 - a -= 1 - - # Climb down the right. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - a -= 1 - - # Climb down the bottom-right. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - x -= 1 - - # Climb up the bottom-left. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - x -= 1 - a += 1 - - # Climb up the left. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - a += 1 - - # Climb up the top-left. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, a, x]) - x += 1 - - # Move down to the next ring. - a -= 1 - - # Convert the ids into Universe objects. - uarray[-1][-1] = [universes[u_id] - for u_id in uarray[-1][-1]] - - # Handle the degenerate center ring separately. - u_id = universe_ids[z, a, x] - uarray[-1].append([universes[u_id]]) - else: - # Build array of Universe pointers for the Lattice. Note that - # we need to convert between the HDF5's square array of - # (alpha, y, z) to the Python API's format of a ragged nested - # list of (z, ring, theta). - uarray = [] - for z in range(n_axial): - # Add a list for this axial level. - uarray.append([]) - a = 2*n_rings - 2 - y = n_rings - 1 - for r in range(n_rings - 1, 0, -1): - # Add a list for this ring. - uarray[-1].append([]) - - # Climb down the bottom-right. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - y -= 1 - - # Climb across the bottom. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - a -= 1 - - # Climb up the bottom-left. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - a -= 1 - y +=1 - - # Climb up the top-left. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - y += 1 - - # Climb across the top. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - a += 1 - - # Climb down the top-right. - for i in range(r): - uarray[-1][-1].append(universe_ids[z, y, a]) - a += 1 - y -= 1 - - # Move down to the next ring. - a -= 1 - - # Convert the ids into Universe objects. - uarray[-1][-1] = [universes[u_id] - for u_id in uarray[-1][-1]] - - # Handle the degenerate center ring separately. - u_id = universe_ids[z, y, a] - uarray[-1].append([universes[u_id]]) - - # Add the universes to the lattice. - if len(pitch) == 2: - # Lattice is 3D - lattice.universes = uarray - else: - # Lattice is 2D; extract the only axial level - lattice.universes = uarray[0] - - return lattice - - def get_unique_universes(self): - """Determine all unique universes in the lattice - - Returns - ------- - universes : collections.OrderedDict - Dictionary whose keys are universe IDs and values are - :class:`openmc.Universe` instances - - """ - - univs = OrderedDict() - for k in range(len(self._universes)): - for j in range(len(self._universes[k])): - if isinstance(self._universes[k][j], openmc.Universe): - u = self._universes[k][j] - univs[u._id] = u - else: - for i in range(len(self._universes[k][j])): - u = self._universes[k][j][i] - assert isinstance(u, openmc.Universe) - univs[u._id] = u - - if self.outer is not None: - univs[self.outer._id] = self.outer - - return univs - - def get_nuclides(self): - """Returns all nuclides in the lattice - - Returns - ------- - nuclides : list of str - List of nuclide names - - """ - - nuclides = [] - - # Get all unique Universes contained in each of the lattice cells - unique_universes = self.get_unique_universes() - - # Append all Universes containing each cell to the dictionary - for universe in unique_universes.values(): - for nuclide in universe.get_nuclides(): - if nuclide not in nuclides: - nuclides.append(nuclide) - - return nuclides - - def get_all_cells(self): - """Return all cells that are contained within the lattice - - Returns - ------- - cells : collections.OrderedDict - Dictionary whose keys are cell IDs and values are :class:`Cell` - instances - - """ - - cells = OrderedDict() - unique_universes = self.get_unique_universes() - - for universe_id, universe in unique_universes.items(): - cells.update(universe.get_all_cells()) - - return cells - - def get_all_materials(self): - """Return all materials that are contained within the lattice - - Returns - ------- - materials : collections.OrderedDict - Dictionary whose keys are material IDs and values are - :class:`Material` instances - - """ - - materials = OrderedDict() - - # Append all Cells in each Cell in the Universe to the dictionary - cells = self.get_all_cells() - for cell_id, cell in cells.items(): - materials.update(cell.get_all_materials()) - - return materials - - def get_all_universes(self): - """Return all universes that are contained within the lattice - - Returns - ------- - universes : collections.OrderedDict - Dictionary whose keys are universe IDs and values are - :class:`Universe` instances - - """ - - # Initialize a dictionary of all Universes contained by the Lattice - # in each nested Universe level - all_universes = OrderedDict() - - # Get all unique Universes contained in each of the lattice cells - unique_universes = self.get_unique_universes() - - # Add the unique Universes filling each Lattice cell - all_universes.update(unique_universes) - - # Append all Universes containing each cell to the dictionary - for universe_id, universe in unique_universes.items(): - all_universes.update(universe.get_all_universes()) - - return all_universes - - def get_universe(self, idx): - r"""Return universe corresponding to a lattice element index - - Parameters - ---------- - idx : Iterable of int - Lattice element indices. For a rectangular lattice, the indices are - given in the :math:`(x,y)` or :math:`(x,y,z)` coordinate system. For - hexagonal lattices, they are given in the :math:`x,\alpha` or - :math:`x,\alpha,z` coordinate systems for "y" orientations and - :math:`\alpha,y` or :math:`\alpha,y,z` coordinate systems for "x" - orientations. - - Returns - ------- - openmc.Universe - Universe with given indices - - """ - idx_u = self.get_universe_index(idx) - if self.ndim == 2: - return self.universes[idx_u[0]][idx_u[1]] - else: - return self.universes[idx_u[0]][idx_u[1]][idx_u[2]] - - def find(self, point): - """Find cells/universes/lattices which contain a given point - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates of the point - - Returns - ------- - list - Sequence of universes, cells, and lattices which are traversed to - find the given point - - """ - idx, p = self.find_element(point) - if self.is_valid_index(idx): - u = self.get_universe(idx) - else: - if self.outer is not None: - u = self.outer - else: - return [] - return [(self, idx)] + u.find(p) - - def clone(self, memo=None): - """Create a copy of this lattice with a new unique ID, and clones - all universes within this lattice. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Lattice - The clone of this lattice - - """ - - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - clone = deepcopy(self) - clone.id = None - - if self.outer is not None: - clone.outer = self.outer.clone(memo) - - # Assign universe clones to the lattice clone - for i in self.indices: - if isinstance(self, RectLattice): - clone.universes[i] = self.universes[i].clone(memo) - else: - if self.ndim == 2: - clone.universes[i[0]][i[1]] = \ - self.universes[i[0]][i[1]].clone(memo) - else: - clone.universes[i[0]][i[1]][i[2]] = \ - self.universes[i[0]][i[1]][i[2]].clone(memo) - - # Memoize the clone - memo[self] = clone - - return memo[self] - - -class RectLattice(Lattice): - """A lattice consisting of rectangular prisms. - - To completely define a rectangular lattice, the - :attr:`RectLattice.lower_left` :attr:`RectLattice.pitch`, - :attr:`RectLattice.outer`, and :attr:`RectLattice.universes` properties need - to be set. - - Most methods for this class use a natural indexing scheme wherein elements - are assigned an index corresponding to their position relative to the - (x,y,z) axes in a Cartesian coordinate system, i.e., an index of (0,0,0) in - the lattice gives the element whose x, y, and z coordinates are the - smallest. However, note that when universes are assigned to lattice elements - using the :attr:`RectLattice.universes` property, the array indices do not - correspond to natural indices. - - Parameters - ---------- - lattice_id : int, optional - Unique identifier for the lattice. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the lattice. If not specified, the name is the empty string. - - Attributes - ---------- - id : int - Unique identifier for the lattice - name : str - Name of the lattice - pitch : Iterable of float - Pitch of the lattice in the x, y, and (if applicable) z directions in - cm. - outer : openmc.Universe - A universe to fill all space outside the lattice - universes : Iterable of Iterable of openmc.Universe - A two- or three-dimensional list/array of universes filling each element - of the lattice. The first dimension corresponds to the z-direction (if - applicable), the second dimension corresponds to the y-direction, and - the third dimension corresponds to the x-direction. Note that for the - y-direction, a higher index corresponds to a lower physical - y-value. Each z-slice in the array can be thought of as a top-down view - of the lattice. - lower_left : Iterable of float - The Cartesian coordinates of the lower-left corner of the lattice. If - the lattice is two-dimensional, only the x- and y-coordinates are - specified. - indices : list of tuple - A list of all possible (z,y,x) or (y,x) lattice element indices. These - indices correspond to indices in the :attr:`RectLattice.universes` - property. - ndim : int - The number of dimensions of the lattice - shape : Iterable of int - An array of two or three integers representing the number of lattice - cells in the x- and y- (and z-) directions, respectively. - - """ - - def __init__(self, lattice_id=None, name=''): - super().__init__(lattice_id, name) - - # Initialize Lattice class attributes - self._lower_left = None - - def __repr__(self): - string = 'RectLattice\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tShape', '=\t', - self.shape) - string += '{0: <16}{1}{2}\n'.format('\tLower Left', '=\t', - self._lower_left) - string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) - - if self._outer is not None: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer._id) - else: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer) - - string += '{0: <16}\n'.format('\tUniverses') - - # Lattice nested Universe IDs - column major for Fortran - for i, universe in enumerate(np.ravel(self._universes)): - string += '{0} '.format(universe._id) - - # Add a newline character every time we reach end of row of cells - if (i+1) % self.shape[0] == 0: - string += '\n' - - string = string.rstrip('\n') - - return string - - @property - def indices(self): - if self.ndim == 2: - return list(np.broadcast(*np.ogrid[ - :self.shape[1], :self.shape[0]])) - else: - return list(np.broadcast(*np.ogrid[ - :self.shape[2], :self.shape[1], :self.shape[0]])) - - @property - def _natural_indices(self): - """Iterate over all possible (x,y) or (x,y,z) lattice element indices. - - This property is used when constructing distributed cell and material - paths. Most importantly, the iteration order matches that used on the - Fortran side. - - """ - if self.ndim == 2: - nx, ny = self.shape - for iy in range(ny): - for ix in range(nx): - yield (ix, iy) - else: - nx, ny, nz = self.shape - for iz in range(nz): - for iy in range(ny): - for ix in range(nx): - yield (ix, iy, iz) - - @property - def lower_left(self): - return self._lower_left - - @property - def ndim(self): - if self.pitch is not None: - return len(self.pitch) - else: - raise ValueError('Number of dimensions cannot be determined until ' - 'the lattice pitch has been set.') - - @property - def shape(self): - return self._universes.shape[::-1] - - @lower_left.setter - def lower_left(self, lower_left): - cv.check_type('lattice lower left corner', lower_left, Iterable, Real) - cv.check_length('lattice lower left corner', lower_left, 2, 3) - self._lower_left = lower_left - - @Lattice.pitch.setter - def pitch(self, pitch): - cv.check_type('lattice pitch', pitch, Iterable, Real) - cv.check_length('lattice pitch', pitch, 2, 3) - for dim in pitch: - cv.check_greater_than('lattice pitch', dim, 0.0) - self._pitch = pitch - - @Lattice.universes.setter - def universes(self, universes): - cv.check_iterable_type('lattice universes', universes, openmc.Universe, - min_depth=2, max_depth=3) - self._universes = np.asarray(universes) - - def find_element(self, point): - """Determine index of lattice element and local coordinates for a point - - Parameters - ---------- - point : Iterable of float - Cartesian coordinates of point - - Returns - ------- - 2- or 3-tuple of int - A tuple of the corresponding (x,y,z) lattice element indices - 3-tuple of float - Carestian coordinates of the point in the corresponding lattice - element coordinate system - - """ - ix = floor((point[0] - self.lower_left[0])/self.pitch[0]) - iy = floor((point[1] - self.lower_left[1])/self.pitch[1]) - if self.ndim == 2: - idx = (ix, iy) - else: - iz = floor((point[2] - self.lower_left[2])/self.pitch[2]) - idx = (ix, iy, iz) - return idx, self.get_local_coordinates(point, idx) - - def get_local_coordinates(self, point, idx): - """Determine local coordinates of a point within a lattice element - - Parameters - ---------- - point : Iterable of float - Cartesian coordinates of point - idx : Iterable of int - (x,y,z) indices of lattice element. If the lattice is 2D, the z - index can be omitted. - - Returns - ------- - 3-tuple of float - Cartesian coordinates of point in the lattice element coordinate - system - - """ - x = point[0] - (self.lower_left[0] + (idx[0] + 0.5)*self.pitch[0]) - y = point[1] - (self.lower_left[1] + (idx[1] + 0.5)*self.pitch[1]) - if self.ndim == 2: - z = point[2] - else: - z = point[2] - (self.lower_left[2] + (idx[2] + 0.5)*self.pitch[2]) - return (x, y, z) - - def get_universe_index(self, idx): - """Return index in the universes array corresponding - to a lattice element index - - Parameters - ---------- - idx : Iterable of int - Lattice element indices in the :math:`(x,y,z)` coordinate system - - Returns - ------- - 2- or 3-tuple of int - Indices used when setting the :attr:`RectLattice.universes` property - - """ - max_y = self.shape[1] - 1 - if self.ndim == 2: - x, y = idx - return (max_y - y, x) - else: - x, y, z = idx - return (z, max_y - y, x) - - def is_valid_index(self, idx): - """Determine whether lattice element index is within defined range - - Parameters - ---------- - idx : Iterable of int - Lattice element indices in the :math:`(x,y,z)` coordinate system - - Returns - ------- - bool - Whether index is valid - - """ - if self.ndim == 2: - return (0 <= idx[0] < self.shape[0] and - 0 <= idx[1] < self.shape[1]) - else: - return (0 <= idx[0] < self.shape[0] and - 0 <= idx[1] < self.shape[1] and - 0 <= idx[2] < self.shape[2]) - - def create_xml_subelement(self, xml_element): - - # Determine if XML element already contains subelement for this Lattice - path = './lattice[@id=\'{0}\']'.format(self._id) - test = xml_element.find(path) - - # If the element does contain the Lattice subelement, then return - if test is not None: - return - - lattice_subelement = ET.Element("lattice") - lattice_subelement.set("id", str(self._id)) - - if len(self._name) > 0: - lattice_subelement.set("name", str(self._name)) - - # Export the Lattice cell pitch - pitch = ET.SubElement(lattice_subelement, "pitch") - pitch.text = ' '.join(map(str, self._pitch)) - - # Export the Lattice outer Universe (if specified) - if self._outer is not None: - outer = ET.SubElement(lattice_subelement, "outer") - outer.text = '{0}'.format(self._outer._id) - self._outer.create_xml_subelement(xml_element) - - # Export Lattice cell dimensions - dimension = ET.SubElement(lattice_subelement, "dimension") - dimension.text = ' '.join(map(str, self.shape)) - - # Export Lattice lower left - lower_left = ET.SubElement(lattice_subelement, "lower_left") - lower_left.text = ' '.join(map(str, self._lower_left)) - - # Export the Lattice nested Universe IDs - column major for Fortran - universe_ids = '\n' - - # 3D Lattices - if self.ndim == 3: - for z in range(self.shape[2]): - for y in range(self.shape[1]): - for x in range(self.shape[0]): - universe = self._universes[z][y][x] - - # Append Universe ID to the Lattice XML subelement - universe_ids += '{0} '.format(universe._id) - - # Create XML subelement for this Universe - universe.create_xml_subelement(xml_element) - - # Add newline character when we reach end of row of cells - universe_ids += '\n' - - # Add newline character when we reach end of row of cells - universe_ids += '\n' - - # 2D Lattices - else: - for y in range(self.shape[1]): - for x in range(self.shape[0]): - universe = self._universes[y][x] - - # Append Universe ID to Lattice XML subelement - universe_ids += '{0} '.format(universe._id) - - # Create XML subelement for this Universe - universe.create_xml_subelement(xml_element) - - # Add newline character when we reach end of row of cells - universe_ids += '\n' - - # Remove trailing newline character from Universe IDs string - universe_ids = universe_ids.rstrip('\n') - - universes = ET.SubElement(lattice_subelement, "universes") - universes.text = universe_ids - - # Append the XML subelement for this Lattice to the XML element - xml_element.append(lattice_subelement) - - @classmethod - def from_xml_element(cls, elem, get_universe): - """Generate rectangular lattice from XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - `` element - get_universe : function - Function returning universe (defined in - :meth:`openmc.Geometry.from_xml`) - - Returns - ------- - RectLattice - Rectangular lattice - - """ - lat_id = int(get_text(elem, 'id')) - name = get_text(elem, 'name') - lat = cls(lat_id, name) - lat.lower_left = [float(i) - for i in get_text(elem, 'lower_left').split()] - lat.pitch = [float(i) for i in get_text(elem, 'pitch').split()] - outer = get_text(elem, 'outer') - if outer is not None: - lat.outer = get_universe(int(outer)) - - # Get array of universes - dimension = get_text(elem, 'dimension').split() - shape = np.array(dimension, dtype=int)[::-1] - uarray = np.array([get_universe(int(i)) for i in - get_text(elem, 'universes').split()]) - uarray.shape = shape - lat.universes = uarray - return lat - - -class HexLattice(Lattice): - r"""A lattice consisting of hexagonal prisms. - - To completely define a hexagonal lattice, the :attr:`HexLattice.center`, - :attr:`HexLattice.pitch`, :attr:`HexLattice.universes`, and - :attr:`HexLattice.outer` properties need to be set. - - Most methods for this class use a natural indexing scheme wherein elements - are assigned an index corresponding to their position relative to skewed - :math:`(x,\alpha,z)` or :math:`(\alpha,y,z)` bases, depending on the lattice - orientation, as described fully in :ref:`hexagonal_indexing`. However, note - that when universes are assigned to lattice elements using the - :attr:`HexLattice.universes` property, the array indices do not correspond - to natural indices. - - .. versionchanged:: 0.11 - The orientation of the lattice can now be changed with the - :attr:`orientation` attribute. - - Parameters - ---------- - lattice_id : int, optional - Unique identifier for the lattice. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the lattice. If not specified, the name is the empty string. - - Attributes - ---------- - id : int - Unique identifier for the lattice - name : str - Name of the lattice - pitch : Iterable of float - Pitch of the lattice in cm. The first item in the iterable specifies the - pitch in the radial direction and, if the lattice is 3D, the second item - in the iterable specifies the pitch in the axial direction. - outer : openmc.Universe - A universe to fill all space outside the lattice - universes : Nested Iterable of openmc.Universe - A two- or three-dimensional list/array of universes filling each element - of the lattice. Each sub-list corresponds to one ring of universes and - should be ordered from outermost ring to innermost ring. The universes - within each sub-list are ordered from the "top" and proceed in a - clockwise fashion. The :meth:`HexLattice.show_indices` method can be - used to help figure out indices for this property. - center : Iterable of float - Coordinates of the center of the lattice. If the lattice does not have - axial sections then only the x- and y-coordinates are specified - indices : list of tuple - A list of all possible (z,r,i) or (r,i) lattice element indices that are - possible, where z is the axial index, r is in the ring index (starting - from the outermost ring), and i is the index with a ring starting from - the top and proceeding clockwise. - orientation : {'x', 'y'} - str by default 'y' orientation of main lattice diagonal another option - - 'x' - num_rings : int - Number of radial ring positions in the xy-plane - num_axial : int - Number of positions along the z-axis. - - """ - - def __init__(self, lattice_id=None, name=''): - super().__init__(lattice_id, name) - - # Initialize Lattice class attributes - self._num_rings = None - self._num_axial = None - self._center = None - self._orientation = 'y' - - def __repr__(self): - string = 'HexLattice\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tOrientation', '=\t', - self._orientation) - string += '{0: <16}{1}{2}\n'.format('\t# Rings', '=\t', self._num_rings) - string += '{0: <16}{1}{2}\n'.format('\t# Axial', '=\t', self._num_axial) - string += '{0: <16}{1}{2}\n'.format('\tCenter', '=\t', - self._center) - string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch) - - if self._outer is not None: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer._id) - else: - string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t', - self._outer) - - string += '{0: <16}\n'.format('\tUniverses') - - if self._num_axial is not None: - slices = [self._repr_axial_slice(x) for x in self._universes] - string += '\n'.join(slices) - - else: - string += self._repr_axial_slice(self._universes) - - return string - - @property - def num_rings(self): - return self._num_rings - - @property - def orientation(self): - return self._orientation - - @property - def num_axial(self): - return self._num_axial - - @property - def center(self): - return self._center - - @property - def indices(self): - if self.num_axial is None: - return [(r, i) for r in range(self.num_rings) - for i in range(max(6*(self.num_rings - 1 - r), 1))] - else: - return [(z, r, i) for z in range(self.num_axial) - for r in range(self.num_rings) - for i in range(max(6*(self.num_rings - 1 - r), 1))] - - @property - def _natural_indices(self): - """Iterate over all possible (x,alpha) or (x,alpha,z) lattice element - indices. - - This property is used when constructing distributed cell and material - paths. Most importantly, the iteration order matches that used on the - Fortran side. - - """ - r = self.num_rings - if self.num_axial is None: - for a in range(-r + 1, r): - for x in range(-r + 1, r): - idx = (x, a) - if self.is_valid_index(idx): - yield idx - else: - for z in range(self.num_axial): - for a in range(-r + 1, r): - for x in range(-r + 1, r): - idx = (x, a, z) - if self.is_valid_index(idx): - yield idx - - @property - def ndim(self): - return 2 if isinstance(self.universes[0][0], openmc.Universe) else 3 - - @center.setter - def center(self, center): - cv.check_type('lattice center', center, Iterable, Real) - cv.check_length('lattice center', center, 2, 3) - self._center = center - - @orientation.setter - def orientation(self, orientation): - cv.check_value('orientation', orientation.lower(), ('x', 'y')) - self._orientation = orientation.lower() - - @Lattice.pitch.setter - def pitch(self, pitch): - cv.check_type('lattice pitch', pitch, Iterable, Real) - cv.check_length('lattice pitch', pitch, 1, 2) - for dim in pitch: - cv.check_greater_than('lattice pitch', dim, 0) - self._pitch = pitch - - @Lattice.universes.setter - def universes(self, universes): - cv.check_iterable_type('lattice universes', universes, openmc.Universe, - min_depth=2, max_depth=3) - self._universes = universes - - # NOTE: This routine assumes that the user creates a "ragged" list of - # lists, where each sub-list corresponds to one ring of Universes. - # The sub-lists are ordered from outermost ring to innermost ring. - # The Universes within each sub-list are ordered from the "top" in a - # clockwise fashion. - - # Set the number of axial positions. - if self.ndim == 3: - self._num_axial = len(self._universes) - else: - self._num_axial = None - - # Set the number of rings and make sure this number is consistent for - # all axial positions. - if self.ndim == 3: - self._num_rings = len(self._universes[0]) - for rings in self._universes: - if len(rings) != self._num_rings: - msg = 'HexLattice ID={0:d} has an inconsistent number of ' \ - 'rings per axial positon'.format(self._id) - raise ValueError(msg) - - else: - self._num_rings = len(self._universes) - - # Make sure there are the correct number of elements in each ring. - if self.ndim == 3: - for axial_slice in self._universes: - # Check the center ring. - if len(axial_slice[-1]) != 1: - msg = 'HexLattice ID={0:d} has the wrong number of ' \ - 'elements in the innermost ring. Only 1 element is ' \ - 'allowed in the innermost ring.'.format(self._id) - raise ValueError(msg) - - # Check the outer rings. - for r in range(self._num_rings-1): - if len(axial_slice[r]) != 6*(self._num_rings - 1 - r): - msg = 'HexLattice ID={0:d} has the wrong number of ' \ - 'elements in ring number {1:d} (counting from the '\ - 'outermost ring). This ring should have {2:d} ' \ - 'elements.'.format(self._id, r, - 6*(self._num_rings - 1 - r)) - raise ValueError(msg) - - else: - axial_slice = self._universes - # Check the center ring. - if len(axial_slice[-1]) != 1: - msg = 'HexLattice ID={0:d} has the wrong number of ' \ - 'elements in the innermost ring. Only 1 element is ' \ - 'allowed in the innermost ring.'.format(self._id) - raise ValueError(msg) - - # Check the outer rings. - for r in range(self._num_rings-1): - if len(axial_slice[r]) != 6*(self._num_rings - 1 - r): - msg = 'HexLattice ID={0:d} has the wrong number of ' \ - 'elements in ring number {1:d} (counting from the '\ - 'outermost ring). This ring should have {2:d} ' \ - 'elements.'.format(self._id, r, - 6*(self._num_rings - 1 - r)) - raise ValueError(msg) - - def find_element(self, point): - r"""Determine index of lattice element and local coordinates for a point - - Parameters - ---------- - point : Iterable of float - Cartesian coordinates of point - - Returns - ------- - 3-tuple of int - Indices of corresponding lattice element in :math:`(x,\alpha,z)` - or :math:`(\alpha,y,z)` bases - numpy.ndarray - Carestian coordinates of the point in the corresponding lattice - element coordinate system - - """ - # Convert coordinates to skewed bases - x = point[0] - self.center[0] - y = point[1] - self.center[1] - if self._num_axial is None: - iz = 1 - else: - z = point[2] - self.center[2] - iz = floor(z/self.pitch[1] + 0.5*self.num_axial) - if self._orientation == 'x': - alpha = y - x*sqrt(3.) - i1 = floor(-alpha/(sqrt(3.0) * self.pitch[0])) - i2 = floor(y/(sqrt(0.75) * self.pitch[0])) - else: - alpha = y - x/sqrt(3.) - i1 = floor(x/(sqrt(0.75) * self.pitch[0])) - i2 = floor(alpha/self.pitch[0]) - # Check four lattice elements to see which one is closest based on local - # coordinates - indices = [(i1, i2, iz), (i1 + 1, i2, iz), (i1, i2 + 1, iz), - (i1 + 1, i2 + 1, iz)] - d_min = np.inf - - for idx in indices: - p = self.get_local_coordinates(point, idx) - d = p[0]**2 + p[1]**2 - if d < d_min: - d_min = d - idx_min = idx - p_min = p - - return idx_min, p_min - - def get_local_coordinates(self, point, idx): - r"""Determine local coordinates of a point within a lattice element - - Parameters - ---------- - point : Iterable of float - Cartesian coordinates of point - idx : Iterable of int - Indices of lattice element in :math:`(x,\alpha,z)` - or :math:`(\alpha,y,z)` bases - - Returns - ------- - 3-tuple of float - Cartesian coordinates of point in the lattice element coordinate - system - - """ - if self._orientation == 'x': - x = point[0] - (self.center[0] + self.pitch[0]*idx[0] + - 0.5*self.pitch[0]*idx[1]) - y = point[1] - (self.center[1] + - sqrt(0.75)*self.pitch[0]*idx[1]) - else: - x = point[0] - (self.center[0] - + sqrt(0.75)*self.pitch[0]*idx[0]) - y = point[1] - (self.center[1] - + (0.5*idx[0] + idx[1])*self.pitch[0]) - - if self._num_axial is None: - z = point[2] - else: - z = point[2] - (self.center[2] + (idx[2] + 0.5 - 0.5*self.num_axial)* - self.pitch[1]) - return (x, y, z) - - def get_universe_index(self, idx): - r"""Return index in the universes array corresponding - to a lattice element index - - Parameters - ---------- - idx : Iterable of int - Lattice element indices in the :math:`(x,\alpha,z)` coordinate - system in 'y' orientation case, or indices in the - :math:`(\alpha,y,z)` coordinate system in 'x' one - - Returns - ------- - 2- or 3-tuple of int - Indices used when setting the :attr:`HexLattice.universes` - property - - """ - - # First we determine which ring the index corresponds to. - x = idx[0] - a = idx[1] - z = -a - x - g = max(abs(x), abs(a), abs(z)) - - # Next we use a clever method to figure out where along the ring we are. - i_ring = self._num_rings - 1 - g - if x >= 0: - if a >= 0: - i_within = x - else: - i_within = 2*g + z - else: - if a <= 0: - i_within = 3*g - x - else: - i_within = 5*g - z - - if self._orientation == 'x' and g > 0: - i_within = (i_within + 5*g) % (6*g) - - if self.num_axial is None: - return (i_ring, i_within) - else: - return (idx[2], i_ring, i_within) - - def is_valid_index(self, idx): - r"""Determine whether lattice element index is within defined range - - Parameters - ---------- - idx : Iterable of int - Lattice element indices in the both :math:`(x,\alpha,z)` - and :math:`(\alpha,y,z)` coordinate system - - Returns - ------- - bool - Whether index is valid - - """ - x = idx[0] - y = idx[1] - z = 0 - y - x - g = max(abs(x), abs(y), abs(z)) - if self.num_axial is None: - return g < self.num_rings - else: - return g < self.num_rings and 0 <= idx[2] < self.num_axial - - def create_xml_subelement(self, xml_element): - # Determine if XML element already contains subelement for this Lattice - path = './hex_lattice[@id=\'{0}\']'.format(self._id) - test = xml_element.find(path) - - # If the element does contain the Lattice subelement, then return - if test is not None: - return - - lattice_subelement = ET.Element("hex_lattice") - lattice_subelement.set("id", str(self._id)) - - if len(self._name) > 0: - lattice_subelement.set("name", str(self._name)) - - # Export the Lattice cell pitch - pitch = ET.SubElement(lattice_subelement, "pitch") - pitch.text = ' '.join(map(str, self._pitch)) - - # Export the Lattice outer Universe (if specified) - if self._outer is not None: - outer = ET.SubElement(lattice_subelement, "outer") - outer.text = '{0}'.format(self._outer._id) - self._outer.create_xml_subelement(xml_element) - - lattice_subelement.set("n_rings", str(self._num_rings)) - # If orientation is "x" export it to XML - if self._orientation == 'x': - lattice_subelement.set("orientation", "x") - - if self._num_axial is not None: - lattice_subelement.set("n_axial", str(self._num_axial)) - - # Export Lattice cell center - center = ET.SubElement(lattice_subelement, "center") - center.text = ' '.join(map(str, self._center)) - - # Export the Lattice nested Universe IDs. - - # 3D Lattices - if self._num_axial is not None: - slices = [] - for z in range(self._num_axial): - # Initialize the center universe. - universe = self._universes[z][-1][0] - universe.create_xml_subelement(xml_element) - - # Initialize the remaining universes. - for r in range(self._num_rings-1): - for theta in range(6*(self._num_rings - 1 - r)): - universe = self._universes[z][r][theta] - universe.create_xml_subelement(xml_element) - - # Get a string representation of the universe IDs. - slices.append(self._repr_axial_slice(self._universes[z])) - - # Collapse the list of axial slices into a single string. - universe_ids = '\n'.join(slices) - - # 2D Lattices - else: - # Initialize the center universe. - universe = self._universes[-1][0] - universe.create_xml_subelement(xml_element) - - # Initialize the remaining universes. - for r in range(self._num_rings - 1): - for theta in range(6*(self._num_rings - 1 - r)): - universe = self._universes[r][theta] - universe.create_xml_subelement(xml_element) - - # Get a string representation of the universe IDs. - universe_ids = self._repr_axial_slice(self._universes) - - universes = ET.SubElement(lattice_subelement, "universes") - universes.text = '\n' + universe_ids - - # Append the XML subelement for this Lattice to the XML element - xml_element.append(lattice_subelement) - - @classmethod - def from_xml_element(cls, elem, get_universe): - """Generate hexagonal lattice from XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - `` element - get_universe : function - Function returning universe (defined in - :meth:`openmc.Geometry.from_xml`) - - Returns - ------- - HexLattice - Hexagonal lattice - - """ - lat_id = int(get_text(elem, 'id')) - name = get_text(elem, 'name') - lat = cls(lat_id, name) - lat.center = [float(i) for i in get_text(elem, 'center').split()] - lat.pitch = [float(i) for i in get_text(elem, 'pitch').split()] - lat.orientation = get_text(elem, 'orientation', 'y') - outer = get_text(elem, 'outer') - if outer is not None: - lat.outer = get_universe(int(outer)) - - # Get nested lists of universes - lat._num_rings = n_rings = int(get_text(elem, 'n_rings')) - lat._num_axial = n_axial = int(get_text(elem, 'n_axial', 1)) - - # Create empty nested lists for one axial level - univs = [[None for _ in range(max(6*(n_rings - 1 - r), 1))] - for r in range(n_rings)] - if n_axial > 1: - univs = [deepcopy(univs) for i in range(n_axial)] - - # Get flat array of universes - uarray = np.array([get_universe(int(i)) for i in - get_text(elem, 'universes').split()]) - - # Fill nested lists - j = 0 - for z in range(n_axial): - # Get list for a single axial level - axial_level = univs[z] if n_axial > 1 else univs - - if lat.orientation == 'y': - # Start iterating from top - x, alpha = 0, n_rings - 1 - while True: - # Set entry in list based on (x,alpha,z) coordinates - _, i_ring, i_within = lat.get_universe_index((x, alpha, z)) - axial_level[i_ring][i_within] = uarray[j] - - # Move to the right - x += 2 - alpha -= 1 - if not lat.is_valid_index((x, alpha, z)): - # Move down in y direction - alpha += x - 1 - x = 1 - x - if not lat.is_valid_index((x, alpha, z)): - # Move to the right - x += 2 - alpha -= 1 - if not lat.is_valid_index((x, alpha, z)): - # Reached the bottom - break - j += 1 - else: - # Start iterating from top - alpha, y = 1 - n_rings, n_rings - 1 - while True: - # Set entry in list based on (alpha,y,z) coordinates - _, i_ring, i_within = lat.get_universe_index((alpha, y, z)) - axial_level[i_ring][i_within] = uarray[j] - - # Move to the right - alpha += 1 - if not lat.is_valid_index((alpha, y, z)): - # Move down to next row - alpha = 1 - n_rings - y -= 1 - - # Check if we've reached the bottom - if y == -n_rings: - break - - while not lat.is_valid_index((alpha, y, z)): - # Move to the right - alpha += 1 - j += 1 - - lat.universes = univs - return lat - - def _repr_axial_slice(self, universes): - """Return string representation for the given 2D group of universes. - - The 'universes' argument should be a list of lists of universes where - each sub-list represents a single ring. The first list should be the - outer ring. - """ - if self._orientation == 'x': - return self._repr_axial_slice_x(universes) - else: - return self._repr_axial_slice_y(universes) - - def _repr_axial_slice_x(self, universes): - """Return string representation for the given 2D group of universes - in 'x' orientation case. - - The 'universes' argument should be a list of lists of universes where - each sub-list represents a single ring. The first list should be the - outer ring. - """ - - # Find the largest universe ID and count the number of digits so we can - # properly pad the output string later. - largest_id = max([max([univ._id for univ in ring]) - for ring in universes]) - n_digits = len(str(largest_id)) - pad = ' '*n_digits - id_form = '{: ^' + str(n_digits) + 'd}' - - # Initialize the list for each row. - rows = [[] for i in range(2*self._num_rings - 1)] - middle = self._num_rings - 1 - - # Start with the degenerate first ring. - universe = universes[-1][0] - rows[middle] = [id_form.format(universe._id)] - - # Add universes one ring at a time. - for r in range(1, self._num_rings): - # r_prime increments down while r increments up. - r_prime = self._num_rings - 1 - r - theta = 0 - y = middle - - # Climb down the bottom-right - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - y += 1 - theta += 1 - - # Climb left across the bottom - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - theta += 1 - - # Climb up the bottom-left - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - y -= 1 - theta += 1 - - # Climb up the top-left - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - y -= 1 - theta += 1 - - # Climb right across the top - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - theta += 1 - - # Climb down the top-right - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - y += 1 - theta += 1 - - # Flip the rows and join each row into a single string. - rows = [pad.join(x) for x in rows] - - # Pad the beginning of the rows so they line up properly. - for y in range(self._num_rings - 1): - rows[y] = (self._num_rings - 1 - y)*pad + rows[y] - rows[-1 - y] = (self._num_rings - 1 - y)*pad + rows[-1 - y] - - # Join the rows together and return the string. - universe_ids = '\n'.join(rows) - return universe_ids - - def _repr_axial_slice_y(self, universes): - """Return string representation for the given 2D group of universes in - 'y' orientation case.. - - The 'universes' argument should be a list of lists of universes where - each sub-list represents a single ring. The first list should be the - outer ring. - """ - - # Find the largest universe ID and count the number of digits so we can - # properly pad the output string later. - largest_id = max([max([univ._id for univ in ring]) - for ring in universes]) - n_digits = len(str(largest_id)) - pad = ' '*n_digits - id_form = '{: ^' + str(n_digits) + 'd}' - - # Initialize the list for each row. - rows = [[] for i in range(1 + 4 * (self._num_rings-1))] - middle = 2 * (self._num_rings - 1) - - # Start with the degenerate first ring. - universe = universes[-1][0] - rows[middle] = [id_form.format(universe._id)] - - # Add universes one ring at a time. - for r in range(1, self._num_rings): - # r_prime increments down while r increments up. - r_prime = self._num_rings - 1 - r - theta = 0 - y = middle + 2*r - - # Climb down the top-right. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - y -= 1 - theta += 1 - - # Climb down the right. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - y -= 2 - theta += 1 - - # Climb down the bottom-right. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].append(id_form.format(universe._id)) - - # Translate the indices. - y -= 1 - theta += 1 - - # Climb up the bottom-left. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - y += 1 - theta += 1 - - # Climb up the left. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - y += 2 - theta += 1 - - # Climb up the top-left. - for i in range(r): - # Add the universe. - universe = universes[r_prime][theta] - rows[y].insert(0, id_form.format(universe._id)) - - # Translate the indices. - y += 1 - theta += 1 - - # Flip the rows and join each row into a single string. - rows = [pad.join(x) for x in rows[::-1]] - - # Pad the beginning of the rows so they line up properly. - for y in range(self._num_rings - 1): - rows[y] = (self._num_rings - 1 - y)*pad + rows[y] - rows[-1 - y] = (self._num_rings - 1 - y)*pad + rows[-1 - y] - - for y in range(self._num_rings % 2, self._num_rings, 2): - rows[middle + y] = pad + rows[middle + y] - if y != 0: - rows[middle - y] = pad + rows[middle - y] - - # Join the rows together and return the string. - universe_ids = '\n'.join(rows) - return universe_ids - - @staticmethod - def _show_indices_y(num_rings): - """Return a diagram of the hexagonal lattice layout with indices. - - This method can be used to show the proper indices to be used when - setting the :attr:`HexLattice.universes` property. For example, running - this method with num_rings=3 will return the following diagram:: - - (0, 0) - (0,11) (0, 1) - (0,10) (1, 0) (0, 2) - (1, 5) (1, 1) - (0, 9) (2, 0) (0, 3) - (1, 4) (1, 2) - (0, 8) (1, 3) (0, 4) - (0, 7) (0, 5) - (0, 6) - - Parameters - ---------- - num_rings : int - Number of rings in the hexagonal lattice - - Returns - ------- - str - Diagram of the hexagonal lattice showing indices - - """ - - # Find the largest string and count the number of digits so we can - # properly pad the output string later - largest_index = 6*(num_rings - 1) - n_digits_index = len(str(largest_index)) - n_digits_ring = len(str(num_rings - 1)) - str_form = '({{:{}}},{{:{}}})'.format(n_digits_ring, n_digits_index) - pad = ' '*(n_digits_index + n_digits_ring + 3) - - # Initialize the list for each row. - rows = [[] for i in range(1 + 4 * (num_rings-1))] - middle = 2 * (num_rings - 1) - - # Start with the degenerate first ring. - rows[middle] = [str_form.format(num_rings - 1, 0)] - - # Add universes one ring at a time. - for r in range(1, num_rings): - # r_prime increments down while r increments up. - r_prime = num_rings - 1 - r - theta = 0 - y = middle + 2*r - - for i in range(r): - # Climb down the top-right. - rows[y].append(str_form.format(r_prime, theta)) - y -= 1 - theta += 1 - - for i in range(r): - # Climb down the right. - rows[y].append(str_form.format(r_prime, theta)) - y -= 2 - theta += 1 - - for i in range(r): - # Climb down the bottom-right. - rows[y].append(str_form.format(r_prime, theta)) - y -= 1 - theta += 1 - - for i in range(r): - # Climb up the bottom-left. - rows[y].insert(0, str_form.format(r_prime, theta)) - y += 1 - theta += 1 - - for i in range(r): - # Climb up the left. - rows[y].insert(0, str_form.format(r_prime, theta)) - y += 2 - theta += 1 - - for i in range(r): - # Climb up the top-left. - rows[y].insert(0, str_form.format(r_prime, theta)) - y += 1 - theta += 1 - - # Flip the rows and join each row into a single string. - rows = [pad.join(x) for x in rows[::-1]] - - # Pad the beginning of the rows so they line up properly. - for y in range(num_rings - 1): - rows[y] = (num_rings - 1 - y)*pad + rows[y] - rows[-1 - y] = (num_rings - 1 - y)*pad + rows[-1 - y] - - for y in range(num_rings % 2, num_rings, 2): - rows[middle + y] = pad + rows[middle + y] - if y != 0: - rows[middle - y] = pad + rows[middle - y] - - # Join the rows together and return the string. - return '\n'.join(rows) - - @staticmethod - def _show_indices_x(num_rings): - """Return a diagram of the hexagonal lattice with x orientation - layout with indices. - - This method can be used to show the proper indices to be used when - setting the :attr:`HexLattice.universes` property. For example,running - this method with num_rings=3 will return the similar diagram:: - - (0, 8) (0, 9) (0,10) - - (0, 7) (1, 4) (1, 5) (0,11) - - (0, 6) (1, 3) (2, 0) (1, 0) (0, 0) - - (0, 5) (1, 2) (1, 1) (0, 1) - - (0, 4) (0, 3) (0, 2) - - Parameters - ---------- - num_rings : int - Number of rings in the hexagonal lattice - - Returns - ------- - str - Diagram of the hexagonal lattice showing indices in OX orientation - - """ - - # Find the largest string and count the number of digits so we can - # properly pad the output string later - largest_index = 6*(num_rings - 1) - n_digits_index = len(str(largest_index)) - n_digits_ring = len(str(num_rings - 1)) - str_form = '({{:{}}},{{:{}}})'.format(n_digits_ring, n_digits_index) - pad = ' '*(n_digits_index + n_digits_ring + 3) - - # Initialize the list for each row. - rows = [[] for i in range(2*num_rings - 1)] - middle = num_rings - 1 - - # Start with the degenerate first ring. - rows[middle] = [str_form.format(num_rings - 1, 0)] - - # Add universes one ring at a time. - for r in range(1, num_rings): - # r_prime increments down while r increments up. - r_prime = num_rings - 1 - r - theta = 0 - y = middle - - for i in range(r): - # Climb down the bottom-right - rows[y].append(str_form.format(r_prime, theta)) - y += 1 - theta += 1 - - for i in range(r): - # Climb left across the bottom - rows[y].insert(0, str_form.format(r_prime, theta)) - theta += 1 - - for i in range(r): - # Climb up the bottom-left - rows[y].insert(0, str_form.format(r_prime, theta)) - y -= 1 - theta += 1 - - for i in range(r): - # Climb up the top-left - rows[y].insert(0, str_form.format(r_prime, theta)) - y -= 1 - theta += 1 - - for i in range(r): - # Climb right across the top - rows[y].append(str_form.format(r_prime, theta)) - theta += 1 - - for i in range(r): - # Climb down the top-right - rows[y].append(str_form.format(r_prime, theta)) - y += 1 - theta += 1 - - # Flip the rows and join each row into a single string. - rows = [pad.join(x) for x in rows] - - # Pad the beginning of the rows so they line up properly. - for y in range(num_rings - 1): - rows[y] = (num_rings - 1 - y)*pad + rows[y] - rows[-1 - y] = (num_rings - 1 - y)*pad + rows[-1 - y] - - # Join the rows together and return the string. - return '\n\n'.join(rows) - - @staticmethod - def show_indices(num_rings, orientation="y"): - """Return a diagram of the hexagonal lattice layout with indices. - - Parameters - ---------- - num_rings : int - Number of rings in the hexagonal lattice - orientation : {"x", "y"} - Orientation of the hexagonal lattice - - Returns - ------- - str - Diagram of the hexagonal lattice showing indices - - """ - - if orientation == 'x': - return HexLattice._show_indices_x(num_rings) - else: - return HexLattice._show_indices_y(num_rings) diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py deleted file mode 100644 index 92fd1730d..000000000 --- a/openmc/lib/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -This module provides bindings to C/C++ functions defined by OpenMC shared -library. When the :mod:`openmc.lib` package is imported, the OpenMC shared -library is automatically loaded. Calls to the OpenMC library can then be via -functions or objects in :mod:`openmc.lib`, for example: - -.. code-block:: python - - openmc.lib.init() - openmc.lib.run() - openmc.lib.finalize() - -""" - -from ctypes import CDLL, c_bool -import os -import sys - -import pkg_resources - - -# Determine shared-library suffix -if sys.platform == 'darwin': - _suffix = 'dylib' -else: - _suffix = 'so' - -if os.environ.get('READTHEDOCS', None) != 'True': - # Open shared library - _filename = pkg_resources.resource_filename( - __name__, 'libopenmc.{}'.format(_suffix)) - _dll = CDLL(_filename) -else: - # For documentation builds, we don't actually have the shared library - # available. Instead, we create a mock object so that when the modules - # within the openmc.lib package try to configure arguments and return - # values for symbols, no errors occur - from unittest.mock import Mock - _dll = Mock() - - -def _dagmc_enabled(): - return c_bool.in_dll(_dll, "dagmc_enabled").value - -from .error import * -from .core import * -from .nuclide import * -from .material import * -from .cell import * -from .mesh import * -from .filter import * -from .tally import * -from .settings import settings -from .math import * -from .plot import * diff --git a/openmc/lib/cell.py b/openmc/lib/cell.py deleted file mode 100644 index 6ed4bca1e..000000000 --- a/openmc/lib/cell.py +++ /dev/null @@ -1,228 +0,0 @@ -import sys - -from collections.abc import Mapping, Iterable -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 - -from openmc.exceptions import AllocationError, InvalidIDError -from . import _dll -from .core import _FortranObjectWithID -from .error import _error_handler -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_get_temperature.argtypes = [ - c_int32, POINTER(c_int32), POINTER(c_double)] -_dll.openmc_cell_get_temperature.restype = c_int -_dll.openmc_cell_get_temperature.errcheck = _error_handler -_dll.openmc_cell_get_name.argtypes = [c_int32, POINTER(c_char_p)] -_dll.openmc_cell_get_name.restype = c_int -_dll.openmc_cell_get_name.errcheck = _error_handler -_dll.openmc_cell_set_name.argtypes = [c_int32, c_char_p] -_dll.openmc_cell_set_name.restype = c_int -_dll.openmc_cell_set_name.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 -_dll.openmc_cell_set_temperature.errcheck = _error_handler -_dll.openmc_get_cell_index.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_get_cell_index.restype = c_int -_dll.openmc_get_cell_index.errcheck = _error_handler -_dll.cells_size.restype = c_int -_dll.openmc_cell_bounding_box.argtypes = [c_int, - POINTER(c_double), - POINTER(c_double)] -_dll.openmc_cell_bounding_box.restype = c_int -_dll.openmc_cell_bounding_box.errcheck = _error_handler - - -class Cell(_FortranObjectWithID): - """Cell stored internally. - - This class exposes a cell that is stored internally in the OpenMC - library. To obtain a view of a cell with a given ID, use the - :data:`openmc.lib.cells` mapping. - - Parameters - ---------- - index : int - Index in the `cells` array. - - Attributes - ---------- - id : int - ID of the cell - - """ - __instances = WeakValueDictionary() - - 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): - cell_id = c_int32() - _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 name(self): - name = c_char_p() - _dll.openmc_cell_get_name(self._index, name) - return name.value.decode() - - @name.setter - def name(self, name): - name_ptr = c_char_p(name.encode()) - _dll.openmc_cell_set_name(self._index, name_ptr) - - @property - def fill(self): - fill_type = c_int() - indices = POINTER(c_int32)() - n = c_int32() - _dll.openmc_cell_get_fill(self._index, fill_type, indices, n) - - if fill_type.value == 1: - if n.value > 1: - return [Material(index=i) for i in indices[:n.value]] - else: - index = indices[0] - return Material(index=index) - else: - raise NotImplementedError - - @fill.setter - def fill(self, fill): - if isinstance(fill, Iterable): - n = len(fill) - indices = (c_int32*n)(*(m._index if m is not None else -1 - for m in fill)) - _dll.openmc_cell_set_fill(self._index, 1, n, indices) - elif isinstance(fill, Material): - indices = (c_int32*1)(fill._index) - _dll.openmc_cell_set_fill(self._index, 1, 1, indices) - elif fill is None: - indices = (c_int32*1)(-1) - _dll.openmc_cell_set_fill(self._index, 1, 1, indices) - - def get_temperature(self, instance=None): - """Get the temperature of a cell - - Parameters - ---------- - instance: int or None - Which instance of the cell - - """ - - if instance is not None: - instance = c_int32(instance) - - T = c_double() - _dll.openmc_cell_get_temperature(self._index, instance, T) - return T.value - - def set_temperature(self, T, instance=None): - """Set the temperature of a cell - - Parameters - ---------- - T : float - Temperature in K - instance : int or None - Which instance of the cell - - """ - - if instance is not None: - instance = c_int32(instance) - - _dll.openmc_cell_set_temperature(self._index, T, instance) - - @property - def bounding_box(self): - inf = sys.float_info.max - llc = np.zeros(3) - urc = np.zeros(3) - _dll.openmc_cell_bounding_box(self._index, - llc.ctypes.data_as(POINTER(c_double)), - urc.ctypes.data_as(POINTER(c_double))) - llc[llc == inf] = np.inf - urc[urc == inf] = np.inf - llc[llc == -inf] = -np.inf - urc[urc == -inf] = -np.inf - - return llc, urc - -class _CellMapping(Mapping): - def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_cell_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return Cell(index=index.value) - - def __iter__(self): - for i in range(len(self)): - yield Cell(index=i).id - - def __len__(self): - return _dll.cells_size() - - def __repr__(self): - return repr(dict(self)) - -cells = _CellMapping() diff --git a/openmc/lib/core.py b/openmc/lib/core.py deleted file mode 100644 index 0bfdb457b..000000000 --- a/openmc/lib/core.py +++ /dev/null @@ -1,411 +0,0 @@ -import sys - -from contextlib import contextmanager -from ctypes import (CDLL, c_bool, c_int, c_int32, c_int64, c_double, c_char_p, - c_char, POINTER, Structure, c_void_p, create_string_buffer) -from warnings import warn - -import numpy as np -from numpy.ctypeslib import as_array - -from openmc.exceptions import AllocationError -from . import _dll -from .error import _error_handler -import openmc.lib - - -class _Bank(Structure): - _fields_ = [('r', c_double*3), - ('u', c_double*3), - ('E', c_double), - ('wgt', c_double), - ('delayed_group', c_int), - ('particle', c_int)] - - -# Define input type for numpy arrays that will be passed into C++ functions -# Must be an int or double array, with single dimension that is contiguous -_array_1d_int = np.ctypeslib.ndpointer(dtype=np.int32, ndim=1, - flags='CONTIGUOUS') -_array_1d_dble = np.ctypeslib.ndpointer(dtype=np.double, ndim=1, - flags='CONTIGUOUS') - -_dll.openmc_calculate_volumes.restype = c_int -_dll.openmc_calculate_volumes.errcheck = _error_handler -_dll.openmc_finalize.restype = c_int -_dll.openmc_finalize.errcheck = _error_handler -_dll.openmc_find_cell.argtypes = [POINTER(c_double*3), POINTER(c_int32), - POINTER(c_int32)] -_dll.openmc_find_cell.restype = c_int -_dll.openmc_find_cell.errcheck = _error_handler -_dll.openmc_hard_reset.restype = c_int -_dll.openmc_hard_reset.errcheck = _error_handler -_dll.openmc_init.argtypes = [c_int, POINTER(POINTER(c_char)), c_void_p] -_dll.openmc_init.restype = c_int -_dll.openmc_init.errcheck = _error_handler -_dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] -_dll.openmc_get_keff.restype = c_int -_dll.openmc_get_keff.errcheck = _error_handler -_init_linsolver_argtypes = [_array_1d_int, c_int, _array_1d_int, c_int, c_int, - c_double, _array_1d_int, _array_1d_int] -_dll.openmc_initialize_linsolver.argtypes = _init_linsolver_argtypes -_dll.openmc_initialize_linsolver.restype = None -_dll.openmc_is_statepoint_batch.restype = c_bool -_dll.openmc_master.restype = c_bool -_dll.openmc_next_batch.argtypes = [POINTER(c_int)] -_dll.openmc_next_batch.restype = c_int -_dll.openmc_next_batch.errcheck = _error_handler -_dll.openmc_plot_geometry.restype = c_int -_dll.openmc_plot_geometry.restype = _error_handler -_dll.openmc_run.restype = c_int -_dll.openmc_run.errcheck = _error_handler -_dll.openmc_reset.restype = c_int -_dll.openmc_reset.errcheck = _error_handler -_run_linsolver_argtypes = [_array_1d_dble, _array_1d_dble, _array_1d_dble, - c_double] -_dll.openmc_run_linsolver.argtypes = _run_linsolver_argtypes -_dll.openmc_run_linsolver.restype = c_int -_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 = c_int -_dll.openmc_simulation_init.errcheck = _error_handler -_dll.openmc_simulation_finalize.restype = c_int -_dll.openmc_simulation_finalize.errcheck = _error_handler -_dll.openmc_statepoint_write.argtypes = [c_char_p, POINTER(c_bool)] -_dll.openmc_statepoint_write.restype = c_int -_dll.openmc_statepoint_write.errcheck = _error_handler -_dll.openmc_global_bounding_box.argtypes = [POINTER(c_double), - POINTER(c_double)] -_dll.openmc_global_bounding_box.restype = c_int -_dll.openmc_global_bounding_box.errcheck = _error_handler - - -def global_bounding_box(): - """Calculate a global bounding box for the model""" - inf = sys.float_info.max - llc = np.zeros(3) - urc = np.zeros(3) - _dll.openmc_global_bounding_box(llc.ctypes.data_as(POINTER(c_double)), - urc.ctypes.data_as(POINTER(c_double))) - llc[llc == inf] = np.inf - urc[urc == inf] = np.inf - llc[llc == -inf] = -np.inf - urc[urc == -inf] = -np.inf - - return llc, urc - -def calculate_volumes(): - """Run stochastic volume calculation""" - _dll.openmc_calculate_volumes() - - -def current_batch(): - """Return the current batch of the simulation. - - Returns - ------- - int - Current batch of the simulation - - """ - return c_int.in_dll(_dll, 'current_batch').value - - -def finalize(): - """Finalize simulation and free memory""" - _dll.openmc_finalize() - - -def find_cell(xyz): - """Find the cell at a given point - - Parameters - ---------- - xyz : iterable of float - Cartesian coordinates of position - - Returns - ------- - openmc.lib.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. - - """ - index = c_int32() - instance = c_int32() - _dll.openmc_find_cell((c_double*3)(*xyz), index, instance) - return openmc.lib.Cell(index=index.value), instance.value - - -def find_material(xyz): - """Find the material at a given point - - Parameters - ---------- - xyz : iterable of float - Cartesian coordinates of position - - Returns - ------- - openmc.lib.Material or None - Material containing the point, or None is no material is found - - """ - index = c_int32() - instance = c_int32() - _dll.openmc_find_cell((c_double*3)(*xyz), index, instance) - - mats = openmc.lib.Cell(index=index.value).fill - if isinstance(mats, (openmc.lib.Material, type(None))): - return mats - else: - return mats[instance.value] - - -def hard_reset(): - """Reset tallies, timers, and pseudo-random number generator state.""" - _dll.openmc_hard_reset() - - -def init(args=None, intracomm=None): - """Initialize OpenMC - - Parameters - ---------- - args : list of str - Command-line arguments - intracomm : mpi4py.MPI.Intracomm or None - MPI intracommunicator - - """ - if args is not None: - args = ['openmc'] + list(args) - argc = len(args) - - # Create the argv array. Note that it is actually expected to be of - # length argc + 1 with the final item being a null pointer. - argv = (POINTER(c_char) * (argc + 1))() - for i, arg in enumerate(args): - argv[i] = create_string_buffer(arg.encode()) - else: - argc = 0 - argv = None - - if intracomm is not None: - # If an mpi4py communicator was passed, convert it to void* to be passed - # to openmc_init - try: - from mpi4py import MPI - except ImportError: - intracomm = None - else: - address = MPI._addressof(intracomm) - intracomm = c_void_p(address) - - _dll.openmc_init(argc, argv, intracomm) - - -def is_statepoint_batch(): - """Return whether statepoint will be written in current batch or not. - - Returns - ------- - bool - Whether is statepoint batch or not - - """ - return _dll.openmc_is_statepoint_batch() - - -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.lib.simulation_init` and - :func:`openmc.lib.simulation_finalize`. For example: - - .. code-block:: Python - - with openmc.lib.run_in_memory(): - openmc.lib.simulation_init() - for _ in openmc.lib.iter_batches(): - # Look at convergence of tallies, for example - ... - openmc.lib.simulation_finalize() - - See Also - -------- - openmc.lib.next_batch - - """ - while True: - # Run next batch - status = next_batch() - - # Provide opportunity for user to perform action between batches - yield - - # End the iteration - if status != 0: - break - - -def keff(): - """Return the calculated k-eigenvalue and its standard deviation. - - Returns - ------- - tuple - Mean k-eigenvalue and standard deviation of the mean - - """ - k = (c_double*2)() - _dll.openmc_get_keff(k) - return tuple(k) - - -def master(): - """Return whether processor is master processor or not. - - Returns - ------- - bool - Whether is master processor or not - - """ - return _dll.openmc_master() - - -def next_batch(): - """Run next batch. - - Returns - ------- - int - Status after running a batch (0=normal, 1=reached maximum number of - batches, 2=tally triggers reached) - - """ - status = c_int() - _dll.openmc_next_batch(status) - return status.value - - -def plot_geometry(): - """Plot geometry""" - _dll.openmc_plot_geometry() - - -def reset(): - """Reset tallies and timers.""" - _dll.openmc_reset() - - -def run(): - """Run simulation""" - _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_source=True): - """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. - write_source : bool - Whether or not to include the source bank in the statepoint. - - """ - if filename is not None: - filename = c_char_p(filename.encode()) - _dll.openmc_statepoint_write(filename, c_bool(write_source)) - - -@contextmanager -def run_in_memory(**kwargs): - """Provides context manager for calling OpenMC shared library functions. - - This function is intended to be used in a 'with' statement and ensures that - OpenMC is properly initialized/finalized. At the completion of the 'with' - block, all memory that was allocated during the block is freed. For - example:: - - with openmc.lib.run_in_memory(): - for i in range(n_iters): - openmc.lib.reset() - do_stuff() - openmc.lib.run() - - Parameters - ---------- - **kwargs - All keyword arguments are passed to :func:`init`. - - """ - init(**kwargs) - try: - yield - finally: - finalize() - - -class _DLLGlobal(object): - """Data descriptor that exposes global variables from libopenmc.""" - def __init__(self, ctype, name): - self.ctype = ctype - self.name = name - - def __get__(self, instance, owner): - return self.ctype.in_dll(_dll, self.name).value - - def __set__(self, instance, value): - self.ctype.in_dll(_dll, self.name).value = value - - -class _FortranObject(object): - def __repr__(self): - return "{}[{}]".format(type(self).__name__, self._index) - - -class _FortranObjectWithID(_FortranObject): - def __init__(self, uid=None, new=True, index=None): - # Creating the object has already been handled by __new__. In the - # initializer, all we do is make sure that the object returned has an ID - # assigned. If the array index of the object is out of bounds, an - # OutOfBoundsError will be raised here by virtue of referencing self.id - self.id diff --git a/openmc/lib/error.py b/openmc/lib/error.py deleted file mode 100644 index 89e7b6e39..000000000 --- a/openmc/lib/error.py +++ /dev/null @@ -1,41 +0,0 @@ -from ctypes import c_int, c_char -from warnings import warn - -import openmc.exceptions as exc -from . import _dll - - -def _error_handler(err, func, args): - """Raise exception according to error code.""" - - # Get error code corresponding to global constant. - def errcode(s): - return c_int.in_dll(_dll, s).value - - # Get error message set by OpenMC library - errmsg = (c_char*256).in_dll(_dll, 'openmc_err_msg') - msg = errmsg.value.decode() - - # Raise exception type corresponding to error code - if err == errcode('OPENMC_E_ALLOCATE'): - raise exc.AllocationError(msg) - elif err == errcode('OPENMC_E_OUT_OF_BOUNDS'): - raise exc.OutOfBoundsError(msg) - elif err == errcode('OPENMC_E_INVALID_ARGUMENT'): - raise exc.InvalidArgumentError(msg) - elif err == errcode('OPENMC_E_INVALID_TYPE'): - raise exc.InvalidTypeError(msg) - if err == errcode('OPENMC_E_INVALID_ID'): - raise exc.InvalidIDError(msg) - elif err == errcode('OPENMC_E_GEOMETRY'): - raise exc.GeometryError(msg) - elif err == errcode('OPENMC_E_DATA'): - raise exc.DataError(msg) - elif err == errcode('OPENMC_E_PHYSICS'): - raise exc.PhysicsError(msg) - elif err == errcode('OPENMC_E_WARNING'): - warn(msg) - elif err < 0: - if not msg: - msg = "Unknown error encountered (code {}).".format(err) - raise exc.OpenMCError(msg) diff --git a/openmc/lib/filter.py b/openmc/lib/filter.py deleted file mode 100644 index 92818a2aa..000000000 --- a/openmc/lib/filter.py +++ /dev/null @@ -1,468 +0,0 @@ -from collections.abc import Mapping -from ctypes import c_int, c_int32, c_double, c_char_p, POINTER, \ - create_string_buffer, c_size_t -from weakref import WeakValueDictionary - -import numpy as np -from numpy.ctypeslib import as_array - -from openmc.exceptions import AllocationError, InvalidIDError -from . import _dll -from .core import _FortranObjectWithID -from .error import _error_handler -from .material import Material -from .mesh import RegularMesh - - -__all__ = ['Filter', 'AzimuthalFilter', 'CellFilter', - 'CellbornFilter', 'CellfromFilter', 'DistribcellFilter', - 'DelayedGroupFilter', 'EnergyFilter', 'EnergyoutFilter', - 'EnergyFunctionFilter', 'LegendreFilter', 'MaterialFilter', 'MeshFilter', - 'MeshSurfaceFilter', 'MuFilter', 'PolarFilter', 'SphericalHarmonicsFilter', - 'SpatialLegendreFilter', 'SurfaceFilter', - 'UniverseFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters'] - -# Tally functions -_dll.openmc_cell_filter_get_bins.argtypes = [ - c_int32, POINTER(POINTER(c_int32)), POINTER(c_int32)] -_dll.openmc_cell_filter_get_bins.restype = c_int -_dll.openmc_cell_filter_get_bins.errcheck = _error_handler -_dll.openmc_energy_filter_get_bins.argtypes = [ - c_int32, POINTER(POINTER(c_double)), POINTER(c_size_t)] -_dll.openmc_energy_filter_get_bins.restype = c_int -_dll.openmc_energy_filter_get_bins.errcheck = _error_handler -_dll.openmc_energy_filter_set_bins.argtypes = [c_int32, c_size_t, POINTER(c_double)] -_dll.openmc_energy_filter_set_bins.restype = c_int -_dll.openmc_energy_filter_set_bins.errcheck = _error_handler -_dll.openmc_energyfunc_filter_set_data.restype = c_int -_dll.openmc_energyfunc_filter_set_data.errcheck = _error_handler -_dll.openmc_energyfunc_filter_set_data.argtypes = [ - c_int32, c_size_t, POINTER(c_double), POINTER(c_double)] -_dll.openmc_energyfunc_filter_get_energy.resttpe = c_int -_dll.openmc_energyfunc_filter_get_energy.errcheck = _error_handler -_dll.openmc_energyfunc_filter_get_energy.argtypes = [ - c_int32, POINTER(c_size_t), POINTER(POINTER(c_double))] -_dll.openmc_energyfunc_filter_get_y.resttpe = c_int -_dll.openmc_energyfunc_filter_get_y.errcheck = _error_handler -_dll.openmc_energyfunc_filter_get_y.argtypes = [ - c_int32, POINTER(c_size_t), POINTER(POINTER(c_double))] -_dll.openmc_filter_get_id.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_filter_get_id.restype = c_int -_dll.openmc_filter_get_id.errcheck = _error_handler -_dll.openmc_filter_get_type.argtypes = [c_int32, c_char_p] -_dll.openmc_filter_get_type.restype = c_int -_dll.openmc_filter_get_type.errcheck = _error_handler -_dll.openmc_filter_set_id.argtypes = [c_int32, c_int32] -_dll.openmc_filter_set_id.restype = c_int -_dll.openmc_filter_set_id.errcheck = _error_handler -_dll.openmc_get_filter_index.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_get_filter_index.restype = c_int -_dll.openmc_get_filter_index.errcheck = _error_handler -_dll.openmc_legendre_filter_get_order.argtypes = [c_int32, POINTER(c_int)] -_dll.openmc_legendre_filter_get_order.restype = c_int -_dll.openmc_legendre_filter_get_order.errcheck = _error_handler -_dll.openmc_legendre_filter_set_order.argtypes = [c_int32, c_int] -_dll.openmc_legendre_filter_set_order.restype = c_int -_dll.openmc_legendre_filter_set_order.errcheck = _error_handler -_dll.openmc_material_filter_get_bins.argtypes = [ - c_int32, POINTER(POINTER(c_int32)), POINTER(c_size_t)] -_dll.openmc_material_filter_get_bins.restype = c_int -_dll.openmc_material_filter_get_bins.errcheck = _error_handler -_dll.openmc_material_filter_set_bins.argtypes = [c_int32, c_size_t, POINTER(c_int32)] -_dll.openmc_material_filter_set_bins.restype = c_int -_dll.openmc_material_filter_set_bins.errcheck = _error_handler -_dll.openmc_mesh_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_mesh_filter_get_mesh.restype = c_int -_dll.openmc_mesh_filter_get_mesh.errcheck = _error_handler -_dll.openmc_mesh_filter_set_mesh.argtypes = [c_int32, c_int32] -_dll.openmc_mesh_filter_set_mesh.restype = c_int -_dll.openmc_mesh_filter_set_mesh.errcheck = _error_handler -_dll.openmc_meshsurface_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_meshsurface_filter_get_mesh.restype = c_int -_dll.openmc_meshsurface_filter_get_mesh.errcheck = _error_handler -_dll.openmc_meshsurface_filter_set_mesh.argtypes = [c_int32, c_int32] -_dll.openmc_meshsurface_filter_set_mesh.restype = c_int -_dll.openmc_meshsurface_filter_set_mesh.errcheck = _error_handler -_dll.openmc_new_filter.argtypes = [c_char_p, POINTER(c_int32)] -_dll.openmc_new_filter.restype = c_int -_dll.openmc_new_filter.errcheck = _error_handler -_dll.openmc_spatial_legendre_filter_get_order.argtypes = [c_int32, POINTER(c_int)] -_dll.openmc_spatial_legendre_filter_get_order.restype = c_int -_dll.openmc_spatial_legendre_filter_get_order.errcheck = _error_handler -_dll.openmc_spatial_legendre_filter_set_order.argtypes = [c_int32, c_int] -_dll.openmc_spatial_legendre_filter_set_order.restype = c_int -_dll.openmc_spatial_legendre_filter_set_order.errcheck = _error_handler -_dll.openmc_sphharm_filter_get_order.argtypes = [c_int32, POINTER(c_int)] -_dll.openmc_sphharm_filter_get_order.restype = c_int -_dll.openmc_sphharm_filter_get_order.errcheck = _error_handler -_dll.openmc_sphharm_filter_set_order.argtypes = [c_int32, c_int] -_dll.openmc_sphharm_filter_set_order.restype = c_int -_dll.openmc_sphharm_filter_set_order.errcheck = _error_handler -_dll.openmc_zernike_filter_get_order.argtypes = [c_int32, POINTER(c_int)] -_dll.openmc_zernike_filter_get_order.restype = c_int -_dll.openmc_zernike_filter_get_order.errcheck = _error_handler -_dll.openmc_zernike_filter_set_order.argtypes = [c_int32, c_int] -_dll.openmc_zernike_filter_set_order.restype = c_int -_dll.openmc_zernike_filter_set_order.errcheck = _error_handler -_dll.tally_filters_size.restype = c_size_t - - -class Filter(_FortranObjectWithID): - __instances = WeakValueDictionary() - - def __new__(cls, obj=None, uid=None, new=True, index=None): - mapping = filters - 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 filter with ID={} has already ' - 'been allocated.'.format(uid)) - - # Set the filter type -- note that the filter_type attribute - # only exists on subclasses! - index = c_int32() - _dll.openmc_new_filter(cls.filter_type.encode(), index) - 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): - filter_id = c_int32() - _dll.openmc_filter_get_id(self._index, filter_id) - return filter_id.value - - @id.setter - def id(self, filter_id): - _dll.openmc_filter_set_id(self._index, filter_id) - - -class EnergyFilter(Filter): - filter_type = 'energy' - - def __init__(self, bins=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if bins is not None: - self.bins = bins - - @property - def bins(self): - energies = POINTER(c_double)() - n = c_size_t() - _dll.openmc_energy_filter_get_bins(self._index, energies, n) - return as_array(energies, (n.value,)) - - @bins.setter - def bins(self, bins): - # Get numpy array as a double* - energies = np.asarray(bins) - energies_p = energies.ctypes.data_as(POINTER(c_double)) - - _dll.openmc_energy_filter_set_bins( - self._index, len(energies), energies_p) - - -class EnergyoutFilter(EnergyFilter): - filter_type = 'energyout' - - -class AzimuthalFilter(Filter): - filter_type = 'azimuthal' - - -class CellFilter(Filter): - filter_type = 'cell' - - @property - def bins(self): - cells = POINTER(c_int32)() - n = c_int32() - _dll.openmc_cell_filter_get_bins(self._index, cells, n) - return as_array(cells, (n.value,)) - - -class CellbornFilter(Filter): - filter_type = 'cellborn' - - -class CellfromFilter(Filter): - filter_type = 'cellfrom' - - -class DelayedGroupFilter(Filter): - filter_type = 'delayedgroup' - - -class DistribcellFilter(Filter): - filter_type = 'distribcell' - - -class EnergyFunctionFilter(Filter): - filter_type = 'energyfunction' - - def __new__(cls, energy=None, y=None, uid=None, new=True, index=None): - return super().__new__(cls, uid=uid, new=new, index=index) - - def __init__(self, energy=None, y=None, uid=None, new=True, index=None): - if (energy is None) != (y is None): - raise AttributeError("Need both energy and y or neither") - super().__init__(uid, new, index) - if energy is not None: - self.set_data(energy, y) - - def set_data(self, energy, y): - """Set the interpolation information for the filter - - Parameters - ---------- - energy : numpy.ndarray - Independent variable for the interpolation - y : numpy.ndarray - Dependent variable for the interpolation - """ - energy_array = np.asarray(energy) - y_array = np.asarray(y) - energy_p = energy_array.ctypes.data_as(POINTER(c_double)) - y_p = y_array.ctypes.data_as(POINTER(c_double)) - - _dll.openmc_energyfunc_filter_set_data( - self._index, len(energy_array), energy_p, y_p) - - @property - def energy(self): - return self._get_attr(_dll.openmc_energyfunc_filter_get_energy) - - @property - def y(self): - return self._get_attr(_dll.openmc_energyfunc_filter_get_y) - - def _get_attr(self, cfunc): - array_p = POINTER(c_double)() - n = c_size_t() - cfunc(self._index, n, array_p) - return as_array(array_p, (n.value, )) - - -class LegendreFilter(Filter): - filter_type = 'legendre' - - def __init__(self, order=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if order is not None: - self.order = order - - @property - def order(self): - temp_order = c_int() - _dll.openmc_legendre_filter_get_order(self._index, temp_order) - return temp_order.value - - @order.setter - def order(self, order): - _dll.openmc_legendre_filter_set_order(self._index, order) - - -class MaterialFilter(Filter): - filter_type = 'material' - - def __init__(self, bins=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if bins is not None: - self.bins = bins - - @property - def bins(self): - materials = POINTER(c_int32)() - n = c_size_t() - _dll.openmc_material_filter_get_bins(self._index, materials, n) - return [Material(index=materials[i]) for i in range(n.value)] - - @bins.setter - def bins(self, materials): - # Get material indices as int32_t[] - n = len(materials) - bins = (c_int32*n)(*(m._index for m in materials)) - _dll.openmc_material_filter_set_bins(self._index, n, bins) - - -class MeshFilter(Filter): - filter_type = 'mesh' - - def __init__(self, mesh=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if mesh is not None: - self.mesh = mesh - - @property - def mesh(self): - index_mesh = c_int32() - _dll.openmc_mesh_filter_get_mesh(self._index, index_mesh) - return RegularMesh(index=index_mesh.value) - - @mesh.setter - def mesh(self, mesh): - _dll.openmc_mesh_filter_set_mesh(self._index, mesh._index) - - -class MeshSurfaceFilter(Filter): - filter_type = 'meshsurface' - - def __init__(self, mesh=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if mesh is not None: - self.mesh = mesh - - @property - def mesh(self): - index_mesh = c_int32() - _dll.openmc_meshsurface_filter_get_mesh(self._index, index_mesh) - return RegularMesh(index=index_mesh.value) - - @mesh.setter - def mesh(self, mesh): - _dll.openmc_meshsurface_filter_set_mesh(self._index, mesh._index) - - -class MuFilter(Filter): - filter_type = 'mu' - - -class PolarFilter(Filter): - filter_type = 'polar' - - -class SphericalHarmonicsFilter(Filter): - filter_type = 'sphericalharmonics' - - def __init__(self, order=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if order is not None: - self.order = order - - @property - def order(self): - temp_order = c_int() - _dll.openmc_sphharm_filter_get_order(self._index, temp_order) - return temp_order.value - - @order.setter - def order(self, order): - _dll.openmc_sphharm_filter_set_order(self._index, order) - - -class SpatialLegendreFilter(Filter): - filter_type = 'spatiallegendre' - - def __init__(self, order=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if order is not None: - self.order = order - - @property - def order(self): - temp_order = c_int() - _dll.openmc_spatial_legendre_filter_get_order(self._index, temp_order) - return temp_order.value - - @order.setter - def order(self, order): - _dll.openmc_spatial_legendre_filter_set_order(self._index, order) - - -class SurfaceFilter(Filter): - filter_type = 'surface' - - -class UniverseFilter(Filter): - filter_type = 'universe' - - -class ZernikeFilter(Filter): - filter_type = 'zernike' - - def __init__(self, order=None, uid=None, new=True, index=None): - super().__init__(uid, new, index) - if order is not None: - self.order = order - - @property - def order(self): - temp_order = c_int() - _dll.openmc_zernike_filter_get_order(self._index, temp_order) - return temp_order.value - - @order.setter - def order(self, order): - _dll.openmc_zernike_filter_set_order(self._index, order) - - -class ZernikeRadialFilter(ZernikeFilter): - filter_type = 'zernikeradial' - - -_FILTER_TYPE_MAP = { - 'azimuthal': AzimuthalFilter, - 'cell': CellFilter, - 'cellborn': CellbornFilter, - 'cellfrom': CellfromFilter, - 'delayedgroup': DelayedGroupFilter, - 'distribcell': DistribcellFilter, - 'energy': EnergyFilter, - 'energyout': EnergyoutFilter, - 'energyfunction': EnergyFunctionFilter, - 'legendre': LegendreFilter, - 'material': MaterialFilter, - 'mesh': MeshFilter, - 'meshsurface': MeshSurfaceFilter, - 'mu': MuFilter, - 'polar': PolarFilter, - 'sphericalharmonics': SphericalHarmonicsFilter, - 'spatiallegendre': SpatialLegendreFilter, - 'surface': SurfaceFilter, - 'universe': UniverseFilter, - 'zernike': ZernikeFilter, - 'zernikeradial': ZernikeRadialFilter -} - - -def _get_filter(index): - filter_type = create_string_buffer(20) - _dll.openmc_filter_get_type(index, filter_type) - filter_type = filter_type.value.decode() - return _FILTER_TYPE_MAP[filter_type](index=index) - - -class _FilterMapping(Mapping): - def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_filter_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return _get_filter(index.value) - - def __iter__(self): - for i in range(len(self)): - yield _get_filter(i).id - - def __len__(self): - return _dll.tally_filters_size() - - def __repr__(self): - return repr(dict(self)) - -filters = _FilterMapping() diff --git a/openmc/lib/material.py b/openmc/lib/material.py deleted file mode 100644 index 0fbce7245..000000000 --- a/openmc/lib/material.py +++ /dev/null @@ -1,267 +0,0 @@ -from collections.abc import Mapping -from ctypes import c_int, c_int32, c_double, c_char_p, POINTER, c_size_t -from weakref import WeakValueDictionary - -import numpy as np -from numpy.ctypeslib import as_array - -from openmc.exceptions import AllocationError, InvalidIDError, OpenMCError -from . import _dll, Nuclide -from .core import _FortranObjectWithID -from .error import _error_handler - - -__all__ = ['Material', 'materials'] - -# Material functions -_dll.openmc_extend_materials.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)] -_dll.openmc_extend_materials.restype = c_int -_dll.openmc_extend_materials.errcheck = _error_handler -_dll.openmc_get_material_index.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_get_material_index.restype = c_int -_dll.openmc_get_material_index.errcheck = _error_handler -_dll.openmc_material_add_nuclide.argtypes = [ - c_int32, c_char_p, c_double] -_dll.openmc_material_add_nuclide.restype = c_int -_dll.openmc_material_add_nuclide.errcheck = _error_handler -_dll.openmc_material_get_id.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_material_get_id.restype = c_int -_dll.openmc_material_get_id.errcheck = _error_handler -_dll.openmc_material_get_densities.argtypes = [ - c_int32, POINTER(POINTER(c_int)), POINTER(POINTER(c_double)), - POINTER(c_int)] -_dll.openmc_material_get_densities.restype = c_int -_dll.openmc_material_get_densities.errcheck = _error_handler -_dll.openmc_material_get_density.argtypes = [c_int32, POINTER(c_double)] -_dll.openmc_material_get_density.restype = c_int -_dll.openmc_material_get_density.errcheck = _error_handler -_dll.openmc_material_get_volume.argtypes = [c_int32, POINTER(c_double)] -_dll.openmc_material_get_volume.restype = c_int -_dll.openmc_material_get_volume.errcheck = _error_handler -_dll.openmc_material_set_density.argtypes = [c_int32, c_double, c_char_p] -_dll.openmc_material_set_density.restype = c_int -_dll.openmc_material_set_density.errcheck = _error_handler -_dll.openmc_material_set_densities.argtypes = [ - c_int32, c_int, POINTER(c_char_p), POINTER(c_double)] -_dll.openmc_material_set_densities.restype = c_int -_dll.openmc_material_set_densities.errcheck = _error_handler -_dll.openmc_material_set_id.argtypes = [c_int32, c_int32] -_dll.openmc_material_set_id.restype = c_int -_dll.openmc_material_set_id.errcheck = _error_handler -_dll.openmc_material_get_name.argtypes = [c_int32, POINTER(c_char_p)] -_dll.openmc_material_get_name.restype = c_int -_dll.openmc_material_get_name.errcheck = _error_handler -_dll.openmc_material_set_name.argtypes = [c_int32, c_char_p] -_dll.openmc_material_set_name.restype = c_int -_dll.openmc_material_set_name.errcheck = _error_handler -_dll.openmc_material_set_volume.argtypes = [c_int32, c_double] -_dll.openmc_material_set_volume.restype = c_int -_dll.openmc_material_set_volume.errcheck = _error_handler -_dll.n_materials.argtypes = [] -_dll.n_materials.restype = c_size_t - - -class Material(_FortranObjectWithID): - """Material stored internally. - - This class exposes a material that is stored internally in the OpenMC - library. To obtain a view of a material with a given ID, use the - :data:`openmc.lib.materials` mapping. - - Parameters - ---------- - uid : int or None - Unique ID of the tally - new : bool - When `index` is None, this argument controls whether a new object is - created or a view to an existing object is returned. - index : int or None - Index in the `materials` array. - - Attributes - ---------- - id : int - ID of the material - nuclides : list of str - List of nuclides in the material - densities : numpy.ndarray - Array of densities in atom/b-cm - - """ - __instances = WeakValueDictionary() - - def __new__(cls, uid=None, new=True, index=None): - mapping = materials - 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 material with ID={} has already ' - 'been allocated.'.format(uid)) - - index = c_int32() - _dll.openmc_extend_materials(1, index, None) - index = index.value - else: - index = mapping[uid]._index - elif index == -1: - # Special value indicates void material - return None - - if index not in cls.__instances: - instance = super(Material, cls).__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): - mat_id = c_int32() - _dll.openmc_material_get_id(self._index, mat_id) - return mat_id.value - - @id.setter - def id(self, mat_id): - _dll.openmc_material_set_id(self._index, mat_id) - - @property - def name(self): - name = c_char_p() - _dll.openmc_material_get_name(self._index, name) - return name.value.decode() - - @name.setter - def name(self, name): - name_ptr = c_char_p(name.encode()) - _dll.openmc_material_set_name(self._index, name_ptr) - - @property - def volume(self): - volume = c_double() - try: - _dll.openmc_material_get_volume(self._index, volume) - except OpenMCError: - return None - return volume.value - - @volume.setter - def volume(self, volume): - _dll.openmc_material_set_volume(self._index, volume) - - @property - def nuclides(self): - return self._get_densities()[0] - return nuclides - - @property - def density(self): - density = c_double() - try: - _dll.openmc_material_get_density(self._index, density) - except OpenMCError: - return None - return density.value - - @property - def densities(self): - return self._get_densities()[1] - - def _get_densities(self): - """Get atom densities in a material. - - Returns - ------- - list of string - List of nuclide names - numpy.ndarray - Array of densities in atom/b-cm - - """ - # Allocate memory for arguments that are written to - nuclides = POINTER(c_int)() - densities = POINTER(c_double)() - n = c_int() - - # Get nuclide names and densities - _dll.openmc_material_get_densities(self._index, nuclides, densities, n) - - # Convert to appropriate types and return - nuclide_list = [Nuclide(nuclides[i]).name for i in range(n.value)] - density_array = as_array(densities, (n.value,)) - return nuclide_list, density_array - - def add_nuclide(self, name, density): - """Add a nuclide to a material. - - Parameters - ---------- - name : str - Name of nuclide, e.g. 'U235' - density : float - Density in atom/b-cm - - """ - _dll.openmc_material_add_nuclide(self._index, name.encode(), density) - - def set_density(self, density, units='atom/b-cm'): - """Set density of a material. - - Parameters - ---------- - density : float - Density - units : {'atom/b-cm', 'g/cm3'} - Units for density - - """ - _dll.openmc_material_set_density(self._index, density, units.encode()) - - def set_densities(self, nuclides, densities): - """Set the densities of a list of nuclides in a material - - Parameters - ---------- - nuclides : iterable of str - Nuclide names - densities : iterable of float - Corresponding densities in atom/b-cm - - """ - # Convert strings to an array of char* - nucs = (c_char_p * len(nuclides))() - nucs[:] = [x.encode() for x in nuclides] - - # Get numpy array as a double* - d = np.asarray(densities) - dp = d.ctypes.data_as(POINTER(c_double)) - - _dll.openmc_material_set_densities(self._index, len(nuclides), nucs, dp) - - -class _MaterialMapping(Mapping): - def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_material_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return Material(index=index.value) - - def __iter__(self): - for i in range(len(self)): - yield Material(index=i).id - - def __len__(self): - return _dll.n_materials() - - def __repr__(self): - return repr(dict(self)) - -materials = _MaterialMapping() diff --git a/openmc/lib/math.py b/openmc/lib/math.py deleted file mode 100644 index 1baa9cf64..000000000 --- a/openmc/lib/math.py +++ /dev/null @@ -1,300 +0,0 @@ -from ctypes import (c_int, c_double, POINTER) - -import numpy as np -from numpy.ctypeslib import ndpointer - -from . import _dll - - -_dll.t_percentile.restype = c_double -_dll.t_percentile.argtypes = [c_double, c_int] - -_dll.calc_pn_c.restype = None -_dll.calc_pn_c.argtypes = [c_int, c_double, ndpointer(c_double)] - -_dll.evaluate_legendre.restype = c_double -_dll.evaluate_legendre.argtypes = [c_int, POINTER(c_double), c_double] - -_dll.calc_rn_c.restype = None -_dll.calc_rn_c.argtypes = [c_int, ndpointer(c_double), ndpointer(c_double)] - -_dll.calc_zn.restype = None -_dll.calc_zn.argtypes = [c_int, c_double, c_double, ndpointer(c_double)] - -_dll.calc_zn_rad.restype = None -_dll.calc_zn_rad.argtypes = [c_int, c_double, ndpointer(c_double)] - -_dll.rotate_angle_c.restype = None -_dll.rotate_angle_c.argtypes = [ndpointer(c_double), c_double, - POINTER(c_double)] -_dll.maxwell_spectrum.restype = c_double -_dll.maxwell_spectrum.argtypes = [c_double] - -_dll.watt_spectrum.restype = c_double -_dll.watt_spectrum.argtypes = [c_double, c_double] - -_dll.broaden_wmp_polynomials.restype = None -_dll.broaden_wmp_polynomials.argtypes = [c_double, c_double, c_int, - ndpointer(c_double)] - -_dll.normal_variate.restype = c_double -_dll.normal_variate.argtypes = [c_double, c_double] - -def t_percentile(p, df): - """ Calculate the percentile of the Student's t distribution with a - specified probability level and number of degrees of freedom - - Parameters - ---------- - p : float - Probability level - df : int - Degrees of freedom - - Returns - ------- - float - Corresponding t-value - - """ - - return _dll.t_percentile(p, df) - - -def calc_pn(n, x): - """ Calculate the n-th order Legendre polynomial at the value of x. - - Parameters - ---------- - n : int - Legendre order - x : float - Independent variable to evaluate the Legendre at - - Returns - ------- - float - Corresponding Legendre polynomial result - - """ - - pnx = np.empty(n + 1, dtype=np.float64) - _dll.calc_pn_c(n, x, pnx) - return pnx - - -def evaluate_legendre(data, x): - """ Finds the value of f(x) given a set of Legendre coefficients - and the value of x. - - Parameters - ---------- - data : iterable of float - Legendre coefficients - x : float - Independent variable to evaluate the Legendre at - - Returns - ------- - float - Corresponding Legendre expansion result - - """ - - data_arr = np.array(data, dtype=np.float64) - return _dll.evaluate_legendre(len(data), - data_arr.ctypes.data_as(POINTER(c_double)), x) - - -def calc_rn(n, uvw): - """ Calculate the n-th order real Spherical Harmonics for a given angle; - all Rn,m values are provided for all n (where -n <= m <= n). - - Parameters - ---------- - n : int - Harmonics order - uvw : iterable of float - Independent variable to evaluate the Legendre at - - Returns - ------- - numpy.ndarray - Corresponding real harmonics value - - """ - - num_nm = (n + 1) * (n + 1) - rn = np.empty(num_nm, dtype=np.float64) - uvw_arr = np.array(uvw, dtype=np.float64) - _dll.calc_rn_c(n, uvw_arr, rn) - return rn - - -def calc_zn(n, rho, phi): - """ Calculate the n-th order modified Zernike polynomial moment for a - given angle (rho, theta) location in the unit disk. The normalization of - the polynomials is such that the integral of Z_pq*Z_pq over the unit disk - is exactly pi - - Parameters - ---------- - n : int - Maximum order - rho : float - Radial location in the unit disk - phi : float - Theta (radians) location in the unit disk - - Returns - ------- - numpy.ndarray - Corresponding resulting list of coefficients - - """ - - num_bins = ((n + 1) * (n + 2)) // 2 - zn = np.zeros(num_bins, dtype=np.float64) - _dll.calc_zn(n, rho, phi, zn) - return zn - - -def calc_zn_rad(n, rho): - """ Calculate the even orders in n-th order modified Zernike polynomial - moment with no azimuthal dependency (m=0) for a given radial location in - the unit disk. The normalization of the polynomials is such that the - integral of Z_pq*Z_pq over the unit disk is exactly pi. - - Parameters - ---------- - n : int - Maximum order - rho : float - Radial location in the unit disk - - Returns - ------- - numpy.ndarray - Corresponding resulting list of coefficients - - """ - - num_bins = n // 2 + 1 - zn_rad = np.zeros(num_bins, dtype=np.float64) - _dll.calc_zn_rad(n, rho, zn_rad) - return zn_rad - - -def rotate_angle(uvw0, mu, phi=None): - """ Rotates direction cosines through a polar angle whose cosine is - mu and through an azimuthal angle sampled uniformly. - - Parameters - ---------- - uvw0 : iterable of float - Original direction cosine - mu : float - Polar angle cosine to rotate - phi : float, optional - Azimuthal angle; if None, one will be sampled uniformly - - Returns - ------- - numpy.ndarray - Rotated direction cosine - - """ - - uvw0_arr = np.array(uvw0, dtype=np.float64) - - if phi is None: - _dll.rotate_angle_c(uvw0_arr, mu, None) - else: - _dll.rotate_angle_c(uvw0_arr, mu, c_double(phi)) - uvw = uvw0_arr - - return uvw - - -def maxwell_spectrum(T): - """ Samples an energy from the Maxwell fission distribution based - on a direct sampling scheme. - - Parameters - ---------- - T : float - Spectrum parameter - - Returns - ------- - float - Sampled outgoing energy - - """ - - return _dll.maxwell_spectrum(T) - - -def watt_spectrum(a, b): - """ Samples an energy from the Watt energy-dependent fission spectrum. - - Parameters - ---------- - a : float - Spectrum parameter a - b : float - Spectrum parameter b - - Returns - ------- - float - Sampled outgoing energy - - """ - - return _dll.watt_spectrum(a, b) - - -def normal_variate(mean_value, std_dev): - """ Samples an energy from the Normal distribution. - - Parameters - ---------- - mean_value : float - Mean of the Normal distribution - std_dev : float - Standard deviation of the normal distribution - - Returns - ------- - float - Sampled outgoing normally distributed value - - """ - - return _dll.normal_variate(mean_value, std_dev) - - -def broaden_wmp_polynomials(E, dopp, n): - """ Doppler broadens the windowed multipole curvefit. The curvefit is a - polynomial of the form a/E + b/sqrt(E) + c + d sqrt(E) ... - - Parameters - ---------- - E : float - Energy to evaluate at - dopp : float - sqrt(atomic weight ratio / kT), with kT given in eV - n : int - Number of components to the polynomial - - Returns - ------- - numpy.ndarray - Resultant leading coefficients - - """ - - factors = np.zeros(n, dtype=np.float64) - _dll.broaden_wmp_polynomials(E, dopp, n, factors) - return factors diff --git a/openmc/lib/mesh.py b/openmc/lib/mesh.py deleted file mode 100644 index bf51bdfe9..000000000 --- a/openmc/lib/mesh.py +++ /dev/null @@ -1,185 +0,0 @@ -from collections.abc import Mapping, Iterable -from ctypes import c_int, c_int32, c_double, POINTER -from weakref import WeakValueDictionary - -import numpy as np -from numpy.ctypeslib import as_array - -from openmc.exceptions import AllocationError, InvalidIDError -from . import _dll -from .core import _FortranObjectWithID -from .error import _error_handler -from .material import Material - -__all__ = ['RegularMesh', 'meshes'] - -# Mesh functions -_dll.openmc_extend_meshes.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)] -_dll.openmc_extend_meshes.restype = c_int -_dll.openmc_extend_meshes.errcheck = _error_handler -_dll.openmc_mesh_get_id.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_mesh_get_id.restype = c_int -_dll.openmc_mesh_get_id.errcheck = _error_handler -_dll.openmc_mesh_get_dimension.argtypes = [c_int32, POINTER(POINTER(c_int)), POINTER(c_int)] -_dll.openmc_mesh_get_dimension.restype = c_int -_dll.openmc_mesh_get_dimension.errcheck = _error_handler -_dll.openmc_mesh_get_params.argtypes = [ - c_int32, POINTER(POINTER(c_double)), POINTER(POINTER(c_double)), - POINTER(POINTER(c_double)), POINTER(c_int)] -_dll.openmc_mesh_get_params.restype = c_int -_dll.openmc_mesh_get_params.errcheck = _error_handler -_dll.openmc_mesh_set_id.argtypes = [c_int32, c_int32] -_dll.openmc_mesh_set_id.restype = c_int -_dll.openmc_mesh_set_id.errcheck = _error_handler -_dll.openmc_mesh_set_dimension.argtypes = [c_int32, c_int, POINTER(c_int)] -_dll.openmc_mesh_set_dimension.restype = c_int -_dll.openmc_mesh_set_dimension.errcheck = _error_handler -_dll.openmc_mesh_set_params.argtypes = [ - c_int32, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)] -_dll.openmc_mesh_set_params.restype = c_int -_dll.openmc_mesh_set_params.errcheck = _error_handler -_dll.openmc_get_mesh_index.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_get_mesh_index.restype = c_int -_dll.openmc_get_mesh_index.errcheck = _error_handler -_dll.n_meshes.argtypes = [] -_dll.n_meshes.restype = c_int - - -class RegularMesh(_FortranObjectWithID): - """RegularMesh stored internally. - - This class exposes a mesh that is stored internally in the OpenMC - library. To obtain a view of a mesh with a given ID, use the - :data:`openmc.lib.meshes` mapping. - - Parameters - ---------- - index : int - Index in the `meshes` array. - - Attributes - ---------- - id : int - ID of the mesh - dimension : iterable of int - The number of mesh cells in each direction. - lower_left : numpy.ndarray - The lower-left corner of the structured mesh. If only two coordinate are - given, it is assumed that the mesh is an x-y mesh. - upper_right : numpy.ndarray - The upper-right corner of the structrued mesh. If only two coordinate - are given, it is assumed that the mesh is an x-y mesh. - width : numpy.ndarray - The width of mesh cells in each direction. - - """ - __instances = WeakValueDictionary() - - def __new__(cls, uid=None, new=True, index=None): - mapping = meshes - 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 mesh with ID={} has already ' - 'been allocated.'.format(uid)) - - index = c_int32() - _dll.openmc_extend_meshes(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): - mesh_id = c_int32() - _dll.openmc_mesh_get_id(self._index, mesh_id) - return mesh_id.value - - @id.setter - def id(self, mesh_id): - _dll.openmc_mesh_set_id(self._index, mesh_id) - - @property - def dimension(self): - dims = POINTER(c_int)() - n = c_int() - _dll.openmc_mesh_get_dimension(self._index, dims, n) - return tuple(as_array(dims, (n.value,))) - - @dimension.setter - def dimension(self, dimension): - n = len(dimension) - dimension = (c_int*n)(*dimension) - _dll.openmc_mesh_set_dimension(self._index, n, dimension) - - @property - def lower_left(self): - return self._get_parameters()[0] - - @property - def upper_right(self): - return self._get_parameters()[1] - - @property - def width(self): - return self._get_parameters()[2] - - def _get_parameters(self): - ll = POINTER(c_double)() - ur = POINTER(c_double)() - w = POINTER(c_double)() - n = c_int() - _dll.openmc_mesh_get_params(self._index, ll, ur, w, n) - return ( - as_array(ll, (n.value,)), - as_array(ur, (n.value,)), - as_array(w, (n.value,)) - ) - - def set_parameters(self, lower_left=None, upper_right=None, width=None): - if lower_left is not None: - n = len(lower_left) - lower_left = (c_double*n)(*lower_left) - if upper_right is not None: - n = len(upper_right) - upper_right = (c_double*n)(*upper_right) - if width is not None: - n = len(width) - width = (c_double*n)(*width) - _dll.openmc_mesh_set_params(self._index, n, lower_left, upper_right, width) - - -class _MeshMapping(Mapping): - def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_mesh_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return RegularMesh(index=index.value) - - def __iter__(self): - for i in range(len(self)): - yield RegularMesh(index=i).id - - def __len__(self): - return _dll.n_meshes() - - def __repr__(self): - return repr(dict(self)) - -meshes = _MeshMapping() diff --git a/openmc/lib/nuclide.py b/openmc/lib/nuclide.py deleted file mode 100644 index 81ef7e648..000000000 --- a/openmc/lib/nuclide.py +++ /dev/null @@ -1,98 +0,0 @@ -from collections.abc import Mapping -from ctypes import c_int, c_char_p, POINTER, c_size_t -from weakref import WeakValueDictionary - -import numpy as np -from numpy.ctypeslib import as_array - -from openmc.exceptions import DataError, AllocationError -from . import _dll -from .core import _FortranObject -from .error import _error_handler - - -__all__ = ['Nuclide', 'nuclides', 'load_nuclide'] - -# Nuclide functions -_dll.openmc_get_nuclide_index.argtypes = [c_char_p, POINTER(c_int)] -_dll.openmc_get_nuclide_index.restype = c_int -_dll.openmc_get_nuclide_index.errcheck = _error_handler -_dll.openmc_load_nuclide.argtypes = [c_char_p] -_dll.openmc_load_nuclide.restype = c_int -_dll.openmc_load_nuclide.errcheck = _error_handler -_dll.openmc_nuclide_name.argtypes = [c_int, POINTER(c_char_p)] -_dll.openmc_nuclide_name.restype = c_int -_dll.openmc_nuclide_name.errcheck = _error_handler -_dll.nuclides_size.restype = c_size_t - - -def load_nuclide(name): - """Load cross section data for a nuclide. - - Parameters - ---------- - name : str - Name of the nuclide, e.g. 'U235' - - """ - _dll.openmc_load_nuclide(name.encode()) - - -class Nuclide(_FortranObject): - """Nuclide stored internally. - - This class exposes a nuclide that is stored internally in the OpenMC - solver. To obtain a view of a nuclide with a given name, use the - :data:`openmc.lib.nuclides` mapping. - - Parameters - ---------- - index : int - Index in the `nuclides` array. - - Attributes - ---------- - name : str - Name of the nuclide, e.g. 'U235' - - """ - __instances = WeakValueDictionary() - - def __new__(cls, *args): - if args not in cls.__instances: - instance = super().__new__(cls) - cls.__instances[args] = instance - return cls.__instances[args] - - def __init__(self, index): - self._index = index - - @property - def name(self): - name = c_char_p() - _dll.openmc_nuclide_name(self._index, name) - return name.value.decode() - - -class _NuclideMapping(Mapping): - """Provide mapping from nuclide name to index in nuclides array.""" - def __getitem__(self, key): - index = c_int() - try: - _dll.openmc_get_nuclide_index(key.encode(), index) - except (DataError, AllocationError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return Nuclide(index.value) - - def __iter__(self): - for i in range(len(self)): - yield Nuclide(i).name - - def __len__(self): - return _dll.nuclides_size() - - def __repr__(self): - return repr(dict(self)) - -nuclides = _NuclideMapping() diff --git a/openmc/lib/plot.py b/openmc/lib/plot.py deleted file mode 100644 index c51000e0d..000000000 --- a/openmc/lib/plot.py +++ /dev/null @@ -1,265 +0,0 @@ -from ctypes import (c_bool, c_int, c_size_t, c_int32, - c_double, Structure, POINTER) - -from . import _dll -from .error import _error_handler - -import numpy as np - - -class _Position(Structure): - """Definition of an xyz location in space with underlying c-types - - C-type Attributes - ----------------- - x : c_double - Position's x value (default: 0.0) - y : c_double - Position's y value (default: 0.0) - z : c_double - Position's z value (default: 0.0) - """ - _fields_ = [('x', c_double), - ('y', c_double), - ('z', c_double)] - - def __getitem__(self, idx): - if idx == 0: - return self.x - elif idx == 1: - return self.y - elif idx == 2: - return self.z - else: - raise IndexError("{} index is invalid for _Position".format(idx)) - - def __setitem__(self, idx, val): - if idx == 0: - self.x = val - elif idx == 1: - self.y = val - elif idx == 2: - self.z = val - else: - raise IndexError("{} index is invalid for _Position".format(idx)) - - def __repr__(self): - return "({}, {}, {})".format(self.x, self.y, self.z) - - -class _PlotBase(Structure): - """A structure defining a 2-D geometry slice with underlying c-types - - C-Type Attributes - ----------------- - origin : openmc.lib.plot._Position - A position defining the origin of the plot. - width_ : openmc.lib.plot._Position - The width of the plot along the x, y, and z axes, respectively - basis_ : c_int - The axes basis of the plot view. - pixels_ : c_size_t[3] - The resolution of the plot in the horizontal and vertical dimensions - level_ : c_int - The universe level for the plot view - - Attributes - ---------- - origin : tuple or list of ndarray - Origin (center) of the plot - width : float - The horizontal dimension of the plot in geometry units (cm) - height : float - The vertical dimension of the plot in geometry units (cm) - basis : string - One of {'xy', 'xz', 'yz'} indicating the horizontal and vertical - axes of the plot. - h_res : int - The horizontal resolution of the plot in pixels - v_res : int - The vertical resolution of the plot in pixels - level : int - The universe level for the plot (default: -1 -> all universes shown) - """ - _fields_ = [('origin_', _Position), - ('width_', _Position), - ('basis_', c_int), - ('pixels_', 3*c_size_t), - ('color_overlaps_', c_bool), - ('level_', c_int)] - - def __init__(self): - self.level_ = -1 - self.color_overlaps_ = False - - @property - def origin(self): - return self.origin_ - - @property - def width(self): - return self.width_.x - - @property - def height(self): - return self.width_.y - - @property - def basis(self): - if self.basis_ == 1: - return 'xy' - elif self.basis_ == 2: - return 'xz' - elif self.basis_ == 3: - return 'yz' - - raise ValueError("Plot basis {} is invalid".format(self.basis_)) - - @basis.setter - def basis(self, basis): - if isinstance(basis, str): - valid_bases = ('xy', 'xz', 'yz') - basis = basis.lower() - if basis not in valid_bases: - raise ValueError("{} is not a valid plot basis.".format(basis)) - - if basis == 'xy': - self.basis_ = 1 - elif basis == 'xz': - self.basis_ = 2 - elif basis == 'yz': - self.basis_ = 3 - return - - if isinstance(basis, int): - valid_bases = (1, 2, 3) - if basis not in valid_bases: - raise ValueError("{} is not a valid plot basis.".format(basis)) - self.basis_ = basis - return - - raise ValueError("{} of type {} is an" - " invalid plot basis".format(basis, type(basis))) - - @property - def h_res(self): - return self.pixels_[0] - - @property - def v_res(self): - return self.pixels_[1] - - @property - def level(self): - return int(self.level_) - - @property - def color_overlaps(self): - return self.color_overlaps_ - - @color_overlaps.setter - def color_overlaps(self, color_overlaps): - self.color_overlaps_ = color_overlaps - - @origin.setter - def origin(self, origin): - self.origin_.x = origin[0] - self.origin_.y = origin[1] - self.origin_.z = origin[2] - - @width.setter - def width(self, width): - self.width_.x = width - - @height.setter - def height(self, height): - self.width_.y = height - - @h_res.setter - def h_res(self, h_res): - self.pixels_[0] = h_res - - @v_res.setter - def v_res(self, v_res): - self.pixels_[1] = v_res - - @level.setter - def level(self, level): - self.level_ = level - - @property - def color_overlaps(self): - return self.color_overlaps_ - - @color_overlaps.setter - def color_overlaps(self, val): - self.color_overlaps_ = val - - def __repr__(self): - out_str = ["-----", - "Plot:", - "-----", - "Origin: {}".format(self.origin), - "Width: {}".format(self.width), - "Height: {}".format(self.height), - "Basis: {}".format(self.basis), - "HRes: {}".format(self.h_res), - "VRes: {}".format(self.v_res), - "Color Overlaps: {}".format(self.color_overlaps), - "Level: {}".format(self.level)] - return '\n'.join(out_str) - - -_dll.openmc_id_map.argtypes = [POINTER(_PlotBase), POINTER(c_int32)] -_dll.openmc_id_map.restype = c_int -_dll.openmc_id_map.errcheck = _error_handler - - -def id_map(plot): - """ - Generate a 2-D map of cell and material IDs. Used for in-memory image - generation. - - Parameters - ---------- - plot : openmc.lib.plot._PlotBase - Object describing the slice of the model to be generated - - Returns - ------- - id_map : numpy.ndarray - A NumPy array with shape (vertical pixels, horizontal pixels, 2) of - OpenMC property ids with dtype int32 - - """ - img_data = np.zeros((plot.v_res, plot.h_res, 2), - dtype=np.dtype('int32')) - _dll.openmc_id_map(plot, img_data.ctypes.data_as(POINTER(c_int32))) - return img_data - - -_dll.openmc_property_map.argtypes = [POINTER(_PlotBase), POINTER(c_double)] -_dll.openmc_property_map.restype = c_int -_dll.openmc_property_map.errcheck = _error_handler - - -def property_map(plot): - """ - Generate a 2-D map of cell temperatures and material densities. Used for - in-memory image generation. - - Parameters - ---------- - plot : openmc.lib.plot._PlotBase - Object describing the slice of the model to be generated - - Returns - ------- - property_map : numpy.ndarray - A NumPy array with shape (vertical pixels, horizontal pixels, 2) of - OpenMC property ids with dtype float - - """ - prop_data = np.zeros((plot.v_res, plot.h_res, 2)) - _dll.openmc_property_map(plot, prop_data.ctypes.data_as(POINTER(c_double))) - return prop_data diff --git a/openmc/lib/settings.py b/openmc/lib/settings.py deleted file mode 100644 index 78794d856..000000000 --- a/openmc/lib/settings.py +++ /dev/null @@ -1,62 +0,0 @@ -from ctypes import (c_int, c_int32, c_int64, c_double, c_char_p, c_bool, - POINTER) - -from . import _dll -from .core import _DLLGlobal -from .error import _error_handler - -_RUN_MODES = {1: 'fixed source', - 2: 'eigenvalue', - 3: 'plot', - 4: 'particle restart', - 5: 'volume'} - -_dll.openmc_set_seed.argtypes = [c_int64] -_dll.openmc_get_seed.restype = c_int64 - - -class _Settings(object): - # Attributes that are accessed through a descriptor - batches = _DLLGlobal(c_int32, 'n_batches') - cmfd_run = _DLLGlobal(c_bool, 'cmfd_run') - entropy_on = _DLLGlobal(c_bool, 'entropy_on') - generations_per_batch = _DLLGlobal(c_int32, 'gen_per_batch') - inactive = _DLLGlobal(c_int32, 'n_inactive') - particles = _DLLGlobal(c_int64, 'n_particles') - restart_run = _DLLGlobal(c_bool, 'restart_run') - run_CE = _DLLGlobal(c_bool, 'run_CE') - verbosity = _DLLGlobal(c_int, 'verbosity') - - @property - def run_mode(self): - i = c_int.in_dll(_dll, 'run_mode').value - try: - return _RUN_MODES[i] - except KeyError: - return None - - @run_mode.setter - def run_mode(self, mode): - current_idx = c_int.in_dll(_dll, 'run_mode') - for idx, mode_value in _RUN_MODES.items(): - if mode_value == mode: - current_idx.value = idx - break - else: - raise ValueError('Invalid run mode: {}'.format(mode)) - - @property - def path_statepoint(self): - path = c_char_p.in_dll(_dll, 'path_statepoint').value - return path.decode() - - @property - def seed(self): - return _dll.openmc_get_seed() - - @seed.setter - def seed(self, seed): - _dll.openmc_set_seed(seed) - - -settings = _Settings() diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py deleted file mode 100644 index 2e8d43ae8..000000000 --- a/openmc/lib/tally.py +++ /dev/null @@ -1,408 +0,0 @@ -from collections.abc import Mapping -from ctypes import c_int, c_int32, c_size_t, c_double, c_char_p, c_bool, POINTER -from weakref import WeakValueDictionary - -import numpy as np -from numpy.ctypeslib import as_array -import scipy.stats - -from openmc.exceptions import AllocationError, InvalidIDError -from openmc.data.reaction import REACTION_NAME -from . import _dll, Nuclide -from .core import _FortranObjectWithID -from .error import _error_handler -from .filter import _get_filter - - -__all__ = ['Tally', 'tallies', 'global_tallies', 'num_realizations'] - -# Tally functions -_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_active.argtypes = [c_int32, POINTER(c_bool)] -_dll.openmc_tally_get_active.restype = c_int -_dll.openmc_tally_get_active.errcheck = _error_handler -_dll.openmc_tally_get_estimator.argtypes = [c_int32, POINTER(c_int)] -_dll.openmc_tally_get_estimator.restype = c_int -_dll.openmc_tally_get_estimator.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 -_dll.openmc_tally_get_filters.argtypes = [ - c_int32, POINTER(POINTER(c_int32)), POINTER(c_size_t)] -_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_get_type.argtypes = [c_int32, POINTER(c_int32)] -_dll.openmc_tally_get_type.restype = c_int -_dll.openmc_tally_get_type.errcheck = _error_handler -_dll.openmc_tally_get_writable.argtypes = [c_int32, POINTER(c_bool)] -_dll.openmc_tally_get_writable.restype = c_int -_dll.openmc_tally_get_writable.errcheck = _error_handler -_dll.openmc_tally_reset.argtypes = [c_int32] -_dll.openmc_tally_reset.restype = c_int -_dll.openmc_tally_reset.errcheck = _error_handler -_dll.openmc_tally_results.argtypes = [ - c_int32, POINTER(POINTER(c_double)), POINTER(c_size_t*3)] -_dll.openmc_tally_results.restype = c_int -_dll.openmc_tally_results.errcheck = _error_handler -_dll.openmc_tally_set_active.argtypes = [c_int32, c_bool] -_dll.openmc_tally_set_active.restype = c_int -_dll.openmc_tally_set_active.errcheck = _error_handler -_dll.openmc_tally_set_filters.argtypes = [c_int32, c_size_t, POINTER(c_int32)] -_dll.openmc_tally_set_filters.restype = c_int -_dll.openmc_tally_set_filters.errcheck = _error_handler -_dll.openmc_tally_set_estimator.argtypes = [c_int32, c_char_p] -_dll.openmc_tally_set_estimator.restype = c_int -_dll.openmc_tally_set_estimator.errcheck = _error_handler -_dll.openmc_tally_set_id.argtypes = [c_int32, c_int32] -_dll.openmc_tally_set_id.restype = c_int -_dll.openmc_tally_set_id.errcheck = _error_handler -_dll.openmc_tally_set_nuclides.argtypes = [c_int32, c_int, POINTER(c_char_p)] -_dll.openmc_tally_set_nuclides.restype = c_int -_dll.openmc_tally_set_nuclides.errcheck = _error_handler -_dll.openmc_tally_set_scores.argtypes = [c_int32, c_int, POINTER(c_char_p)] -_dll.openmc_tally_set_scores.restype = c_int -_dll.openmc_tally_set_scores.errcheck = _error_handler -_dll.openmc_tally_set_type.argtypes = [c_int32, c_char_p] -_dll.openmc_tally_set_type.restype = c_int -_dll.openmc_tally_set_type.errcheck = _error_handler -_dll.openmc_tally_set_writable.argtypes = [c_int32, c_bool] -_dll.openmc_tally_set_writable.restype = c_int -_dll.openmc_tally_set_writable.errcheck = _error_handler -_dll.tallies_size.restype = c_size_t - - -_SCORES = { - -1: 'flux', -2: 'total', -3: 'scatter', -4: 'nu-scatter', - -5: 'absorption', -6: 'fission', -7: 'nu-fission', -8: 'kappa-fission', - -9: 'current', -10: 'events', -11: 'delayed-nu-fission', - -12: 'prompt-nu-fission', -13: 'inverse-velocity', -14: 'fission-q-prompt', - -15: 'fission-q-recoverable', -16: 'decay-rate' -} -_ESTIMATORS = { - 1: 'analog', 2: 'tracklength', 3: 'collision' -} -_TALLY_TYPES = { - 1: 'volume', 2: 'mesh-surface', 3: 'surface' -} - - -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. - - This class exposes a tally that is stored internally in the OpenMC - library. To obtain a view of a tally with a given ID, use the - :data:`openmc.lib.tallies` mapping. - - Parameters - ---------- - uid : int or None - Unique ID of the tally - new : bool - When `index` is None, this argument controls whether a new object is - created or a view of an existing object is returned. - index : int or None - Index in the `tallies` array. - - Attributes - ---------- - id : int - ID of the tally - estimator: str - Estimator type of tally (analog, tracklength, collision) - 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 - type : str - Type of tally (volume, mesh_surface, surface) - - """ - __instances = WeakValueDictionary() - - def __new__(cls, uid=None, new=True, index=None): - mapping = tallies - 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 tally with ID={} has already ' - 'been allocated.'.format(uid)) - - index = c_int32() - _dll.openmc_extend_tallies(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 active(self): - active = c_bool() - _dll.openmc_tally_get_active(self._index, active) - return active.value - - @property - def type(self): - type = c_int32() - _dll.openmc_tally_get_type(self._index, type) - return _TALLY_TYPES[type.value] - - @type.setter - def type(self, type): - _dll.openmc_tally_set_type(self._index, type.encode()) - - @property - def estimator(self): - estimator = c_int() - _dll.openmc_tally_get_estimator(self._index, estimator) - return _ESTIMATORS[estimator.value] - - @estimator.setter - def estimator(self, estimator): - _dll.openmc_tally_set_estimator(self._index, estimator.encode()) - - @active.setter - def active(self, active): - _dll.openmc_tally_set_active(self._index, active) - - @property - def id(self): - tally_id = c_int32() - _dll.openmc_tally_get_id(self._index, tally_id) - return tally_id.value - - @id.setter - def id(self, tally_id): - _dll.openmc_tally_set_id(self._index, tally_id) - - @property - def filters(self): - filt_idx = POINTER(c_int32)() - n = c_size_t() - _dll.openmc_tally_get_filters(self._index, filt_idx, n) - return [_get_filter(filt_idx[i]) for i in range(n.value)] - - @filters.setter - def filters(self, filters): - # Get filter indices as int32_t[] - n = len(filters) - indices = (c_int32*n)(*(f._index for f in filters)) - - _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_size_t*3)() - _dll.openmc_tally_results(self._index, data, shape) - return as_array(data, tuple(shape)) - - @property - def scores(self): - 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): - scores_ = (c_char_p * len(scores))() - scores_[:] = [x.encode() for x in scores] - _dll.openmc_tally_set_scores(self._index, len(scores), scores_) - - @property - def std_dev(self): - results = self.results - std_dev = np.empty(results.shape[:2]) - std_dev.fill(np.inf) - - 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 - - @property - def writable(self): - writable = c_bool() - _dll.openmc_tally_get_writable(self._index, writable) - return writable.value - - @writable.setter - def writable(self, writable): - _dll.openmc_tally_set_writable(self._index, writable) - - def reset(self): - """Reset results and num_realizations of tally""" - _dll.openmc_tally_reset(self._index) - - 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): - def __getitem__(self, key): - index = c_int32() - try: - _dll.openmc_get_tally_index(key, index) - except (AllocationError, InvalidIDError) as e: - # __contains__ expects a KeyError to work correctly - raise KeyError(str(e)) - return Tally(index=index.value) - - def __iter__(self): - for i in range(len(self)): - yield Tally(index=i).id - - def __len__(self): - return _dll.tallies_size() - - def __repr__(self): - return repr(dict(self)) - -tallies = _TallyMapping() diff --git a/openmc/macroscopic.py b/openmc/macroscopic.py deleted file mode 100644 index 2a5a22752..000000000 --- a/openmc/macroscopic.py +++ /dev/null @@ -1,25 +0,0 @@ -from openmc.checkvalue import check_type - - -class Macroscopic(str): - """A Macroscopic object that can be used in a material. - - Parameters - ---------- - name : str - Name of the macroscopic data, e.g. UO2 - - Attributes - ---------- - name : str - Name of the nuclide, e.g. UO2 - - """ - - def __new__(cls, name): - check_type('name', name, str) - return super().__new__(cls, name) - - @property - def name(self): - return self diff --git a/openmc/material.py b/openmc/material.py deleted file mode 100644 index 375e1dca1..000000000 --- a/openmc/material.py +++ /dev/null @@ -1,1109 +0,0 @@ -from collections import OrderedDict -from copy import deepcopy -from numbers import Real, Integral -from pathlib import Path -import warnings -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc -import openmc.data -import openmc.checkvalue as cv -from openmc._xml import clean_indentation -from .mixin import IDManagerMixin - - -# Units for density supported by OpenMC -DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3', 'sum', - 'macro'] - - -class Material(IDManagerMixin): - """A material composed of a collection of nuclides/elements. - - To create a material, one should create an instance of this class, add - nuclides or elements with :meth:`Material.add_nuclide` or - `Material.add_element`, respectively, and set the total material density - with `Material.set_density()`. The material can then be assigned to a cell - using the :attr:`Cell.fill` attribute. - - Parameters - ---------- - material_id : int, optional - Unique identifier for the material. If not specified, an identifier will - automatically be assigned. - name : str, optional - Name of the material. If not specified, the name will be the empty - string. - temperature : float, optional - Temperature of the material in Kelvin. If not specified, the material - inherits the default temperature applied to the model. - - Attributes - ---------- - id : int - Unique identifier for the material - temperature : float - Temperature of the material in Kelvin. - density : float - Density of the material (units defined separately) - density_units : str - Units used for `density`. Can be one of 'g/cm3', 'g/cc', 'kg/m3', - 'atom/b-cm', 'atom/cm3', 'sum', or 'macro'. The 'macro' unit only - applies in the case of a multi-group calculation. - depletable : bool - Indicate whether the material is depletable. - nuclides : list of tuple - List in which each item is a 3-tuple consisting of a nuclide string, the - percent density, and the percent type ('ao' or 'wo'). - isotropic : list of str - Nuclides for which elastic scattering should be treated as though it - were isotropic in the laboratory system. - average_molar_mass : float - The average molar mass of nuclides in the material in units of grams per - mol. For example, UO2 with 3 nuclides will have an average molar mass - of 270 / 3 = 90 g / mol. - volume : float - Volume of the material in cm^3. This can either be set manually or - calculated in a stochastic volume calculation and added via the - :meth:`Material.add_volume_information` method. - paths : list of str - The paths traversed through the CSG tree to reach each material - instance. This property is initialized by calling the - :meth:`Geometry.determine_paths` method. - num_instances : int - The number of instances of this material throughout the geometry. - fissionable_mass : float - Mass of fissionable nuclides in the material in [g]. Requires that the - :attr:`volume` attribute is set. - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, material_id=None, name='', temperature=None): - # Initialize class attributes - self.id = material_id - self.name = name - self.temperature = temperature - self._density = None - self._density_units = 'sum' - self._depletable = False - self._paths = None - self._num_instances = None - self._volume = None - self._atoms = {} - self._isotropic = [] - - # A list of tuples (nuclide, percent, percent type) - self._nuclides = [] - - # The single instance of Macroscopic data present in this material - # (only one is allowed, hence this is different than _nuclides, etc) - self._macroscopic = None - - # If specified, a list of table names - self._sab = [] - - # If true, the material will be initialized as distributed - self._convert_to_distrib_comps = False - - # If specified, this file will be used instead of composition values - self._distrib_otf_file = None - - def __repr__(self): - string = 'Material\n' - string += '{: <16}=\t{}\n'.format('\tID', self._id) - string += '{: <16}=\t{}\n'.format('\tName', self._name) - string += '{: <16}=\t{}\n'.format('\tTemperature', self._temperature) - - string += '{: <16}=\t{}'.format('\tDensity', self._density) - string += ' [{}]\n'.format(self._density_units) - - string += '{: <16}\n'.format('\tS(a,b) Tables') - - for sab in self._sab: - string += '{: <16}=\t{}\n'.format('\tS(a,b)', sab) - - string += '{: <16}\n'.format('\tNuclides') - - for nuclide, percent, percent_type in self._nuclides: - string += '{: <16}'.format('\t{}'.format(nuclide)) - string += '=\t{: <12} [{}]\n'.format(percent, percent_type) - - if self._macroscopic is not None: - string += '{: <16}\n'.format('\tMacroscopic Data') - string += '{: <16}'.format('\t{}'.format(self._macroscopic)) - - return string - - @property - def name(self): - return self._name - - @property - def temperature(self): - return self._temperature - - @property - def density(self): - return self._density - - @property - def density_units(self): - return self._density_units - - @property - def depletable(self): - return self._depletable - - @property - def paths(self): - if self._paths is None: - raise ValueError('Material instance paths have not been determined. ' - 'Call the Geometry.determine_paths() method.') - return self._paths - - @property - def num_instances(self): - if self._num_instances is None: - raise ValueError( - 'Number of material instances have not been determined. Call ' - 'the Geometry.determine_paths() method.') - return self._num_instances - - @property - def nuclides(self): - return self._nuclides - - @property - def isotropic(self): - return self._isotropic - - @property - def convert_to_distrib_comps(self): - return self._convert_to_distrib_comps - - @property - def distrib_otf_file(self): - return self._distrib_otf_file - - @property - def average_molar_mass(self): - - # Get a list of all the nuclides, with elements expanded - nuclide_densities = self.get_nuclide_densities() - - # Using the sum of specified atomic or weight amounts as a basis, sum - # the mass and moles of the material - mass = 0. - moles = 0. - for nuc, vals in nuclide_densities.items(): - if vals[2] == 'ao': - mass += vals[1] * openmc.data.atomic_mass(nuc) - moles += vals[1] - else: - moles += vals[1] / openmc.data.atomic_mass(nuc) - mass += vals[1] - - # Compute and return the molar mass - return mass / moles - - @property - def volume(self): - return self._volume - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('name for Material ID="{}"'.format(self._id), - name, str) - self._name = name - else: - self._name = '' - - @temperature.setter - def temperature(self, temperature): - cv.check_type('Temperature for Material ID="{}"'.format(self._id), - temperature, (Real, type(None))) - self._temperature = temperature - - @depletable.setter - def depletable(self, depletable): - cv.check_type('Depletable flag for Material ID="{}"'.format(self.id), - depletable, bool) - self._depletable = depletable - - @volume.setter - def volume(self, volume): - if volume is not None: - cv.check_type('material volume', volume, Real) - self._volume = volume - - @isotropic.setter - def isotropic(self, isotropic): - cv.check_iterable_type('Isotropic scattering nuclides', isotropic, - str) - self._isotropic = list(isotropic) - - @property - def fissionable_mass(self): - if self.volume is None: - raise ValueError("Volume must be set in order to determine mass.") - density = 0.0 - for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values(): - Z = openmc.data.zam(nuc)[0] - if Z >= 90: - density += 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \ - / openmc.data.AVOGADRO - return density*self.volume - - @classmethod - def from_hdf5(cls, group): - """Create material from HDF5 group - - Parameters - ---------- - group : h5py.Group - Group in HDF5 file - - Returns - ------- - openmc.Material - Material instance - - """ - mat_id = int(group.name.split('/')[-1].lstrip('material ')) - - name = group['name'][()].decode() if 'name' in group else '' - density = group['atom_density'][()] - if 'nuclide_densities' in group: - nuc_densities = group['nuclide_densities'][()] - - # Create the Material - material = cls(mat_id, name) - material.depletable = bool(group.attrs['depletable']) - if 'volume' in group.attrs: - material.volume = group.attrs['volume'] - if "temperature" in group.attrs: - material.temperature = group.attrs["temperature"] - - # Read the names of the S(a,b) tables for this Material and add them - if 'sab_names' in group: - sab_tables = group['sab_names'][()] - for sab_table in sab_tables: - name = sab_table.decode() - material.add_s_alpha_beta(name) - - # Set the Material's density to atom/b-cm as used by OpenMC - material.set_density(density=density, units='atom/b-cm') - - if 'nuclides' in group: - nuclides = group['nuclides'][()] - # Add all nuclides to the Material - for fullname, density in zip(nuclides, nuc_densities): - name = fullname.decode().strip() - material.add_nuclide(name, percent=density, percent_type='ao') - if 'macroscopics' in group: - macroscopics = group['macroscopics'][()] - # Add all macroscopics to the Material - for fullname in macroscopics: - name = fullname.decode().strip() - material.add_macroscopic(name) - - return material - - def add_volume_information(self, volume_calc): - """Add volume information to a material. - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if volume_calc.domain_type == 'material': - if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id].n - self._atoms = volume_calc.atoms[self.id] - else: - raise ValueError('No volume information found for this material.') - else: - raise ValueError('No volume information found for this material.') - - def set_density(self, units, density=None): - """Set the density of the material - - Parameters - ---------- - units : {'g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3', 'sum', 'macro'} - Physical units of density. - density : float, optional - Value of the density. Must be specified unless units is given as - 'sum'. - - """ - - cv.check_value('density units', units, DENSITY_UNITS) - self._density_units = units - - if units == 'sum': - if density is not None: - msg = 'Density "{}" for Material ID="{}" is ignored ' \ - 'because the unit is "sum"'.format(density, self.id) - warnings.warn(msg) - else: - if density is None: - msg = 'Unable to set the density for Material ID="{}" ' \ - 'because a density value must be given when not using ' \ - '"sum" unit'.format(self.id) - raise ValueError(msg) - - cv.check_type('the density for Material ID="{}"'.format(self.id), - density, Real) - self._density = density - - @distrib_otf_file.setter - def distrib_otf_file(self, filename): - # TODO: remove this when distributed materials are merged - warnings.warn('This feature is not yet implemented in a release ' - 'version of openmc') - - if not isinstance(filename, str) and filename is not None: - msg = 'Unable to add OTF material file to Material ID="{}" with a ' \ - 'non-string name "{}"'.format(self._id, filename) - raise ValueError(msg) - - self._distrib_otf_file = filename - - @convert_to_distrib_comps.setter - def convert_to_distrib_comps(self): - # TODO: remove this when distributed materials are merged - warnings.warn('This feature is not yet implemented in a release ' - 'version of openmc') - - self._convert_to_distrib_comps = True - - def add_nuclide(self, nuclide, percent, percent_type='ao'): - """Add a nuclide to the material - - Parameters - ---------- - nuclide : str - Nuclide to add, e.g., 'Mo95' - percent : float - Atom or weight percent - percent_type : {'ao', 'wo'} - 'ao' for atom percent and 'wo' for weight percent - - """ - cv.check_type('nuclide', nuclide, str) - cv.check_type('percent', percent, Real) - cv.check_value('percent type', percent_type, {'ao', 'wo'}) - - if self._macroscopic is not None: - msg = 'Unable to add a Nuclide to Material ID="{}" as a ' \ - 'macroscopic data-set has already been added'.format(self._id) - raise ValueError(msg) - - # If nuclide name doesn't look valid, give a warning - try: - Z, _, _ = openmc.data.zam(nuclide) - except ValueError as e: - warnings.warn(str(e)) - else: - # For actinides, have the material be depletable by default - if Z >= 89: - self.depletable = True - - self._nuclides.append((nuclide, percent, percent_type)) - - def remove_nuclide(self, nuclide): - """Remove a nuclide from the material - - Parameters - ---------- - nuclide : str - Nuclide to remove - - """ - cv.check_type('nuclide', nuclide, str) - - # If the Material contains the Nuclide, delete it - for nuc in self._nuclides: - if nuclide == nuc[0]: - self._nuclides.remove(nuc) - break - - def add_macroscopic(self, macroscopic): - """Add a macroscopic to the material. This will also set the - density of the material to 1.0, unless it has been otherwise set, - as a default for Macroscopic cross sections. - - Parameters - ---------- - macroscopic : str - Macroscopic to add - - """ - - # Ensure no nuclides, elements, or sab are added since these would be - # incompatible with macroscopics - if self._nuclides or self._sab: - msg = 'Unable to add a Macroscopic data set to Material ID="{}" ' \ - 'with a macroscopic value "{}" as an incompatible data ' \ - 'member (i.e., nuclide or S(a,b) table) ' \ - 'has already been added'.format(self._id, macroscopic) - raise ValueError(msg) - - if not isinstance(macroscopic, str): - msg = 'Unable to add a Macroscopic to Material ID="{}" with a ' \ - 'non-string value "{}"'.format(self._id, macroscopic) - raise ValueError(msg) - - if self._macroscopic is None: - self._macroscopic = macroscopic - else: - msg = 'Unable to add a Macroscopic to Material ID="{}". ' \ - 'Only one Macroscopic allowed per ' \ - 'Material.'.format(self._id) - raise ValueError(msg) - - # Generally speaking, the density for a macroscopic object will - # be 1.0. Therefore, lets set density to 1.0 so that the user - # doesnt need to set it unless its needed. - # Of course, if the user has already set a value of density, - # then we will not override it. - if self._density is None: - self.set_density('macro', 1.0) - - def remove_macroscopic(self, macroscopic): - """Remove a macroscopic from the material - - Parameters - ---------- - macroscopic : str - Macroscopic to remove - - """ - - if not isinstance(macroscopic, str): - msg = 'Unable to remove a Macroscopic "{}" in Material ID="{}" ' \ - 'since it is not a string'.format(self._id, macroscopic) - raise ValueError(msg) - - # If the Material contains the Macroscopic, delete it - if macroscopic == self._macroscopic: - self._macroscopic = None - - def add_element(self, element, percent, percent_type='ao', enrichment=None): - """Add a natural element to the material - - Parameters - ---------- - element : str - Element to add, e.g., 'Zr' - percent : float - Atom or weight percent - percent_type : {'ao', 'wo'}, optional - 'ao' for atom percent and 'wo' for weight percent. Defaults to atom - percent. - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - - """ - cv.check_type('nuclide', element, str) - cv.check_type('percent', percent, Real) - cv.check_value('percent type', percent_type, {'ao', 'wo'}) - - if self._macroscopic is not None: - msg = 'Unable to add an Element to Material ID="{}" as a ' \ - 'macroscopic data-set has already been added'.format(self._id) - raise ValueError(msg) - - if enrichment is not None: - if not isinstance(enrichment, Real): - msg = 'Unable to add an Element to Material ID="{}" with a ' \ - 'non-floating point enrichment value "{}"'\ - .format(self._id, enrichment) - raise ValueError(msg) - - elif element != 'U': - msg = 'Unable to use enrichment for element {} which is not ' \ - 'uranium for Material ID="{}"'.format(element, self._id) - raise ValueError(msg) - - # Check that the enrichment is in the valid range - cv.check_less_than('enrichment', enrichment, 100./1.008) - cv.check_greater_than('enrichment', enrichment, 0., equality=True) - - if enrichment > 5.0: - msg = 'A uranium enrichment of {} was given for Material ID='\ - '"{}". OpenMC assumes the U234/U235 mass ratio is '\ - 'constant at 0.008, which is only valid at low ' \ - 'enrichments. Consider setting the isotopic ' \ - 'composition manually for enrichments over 5%.'.\ - format(enrichment, self._id) - warnings.warn(msg) - - # Make sure element name is just that - if not element.isalpha(): - raise ValueError("Element name should be given by the " - "element's symbol, e.g., 'Zr'") - - # Add naturally-occuring isotopes - element = openmc.Element(element) - for nuclide in element.expand(percent, percent_type, enrichment): - self.add_nuclide(*nuclide) - - def add_s_alpha_beta(self, name, fraction=1.0): - r"""Add an :math:`S(\alpha,\beta)` table to the material - - Parameters - ---------- - name : str - Name of the :math:`S(\alpha,\beta)` table - fraction : float - The fraction of relevant nuclei that are affected by the - :math:`S(\alpha,\beta)` table. For example, if the material is a - block of carbon that is 60% graphite and 40% amorphous then add a - graphite :math:`S(\alpha,\beta)` table with fraction=0.6. - - """ - - if self._macroscopic is not None: - msg = 'Unable to add an S(a,b) table to Material ID="{}" as a ' \ - 'macroscopic data-set has already been added'.format(self._id) - raise ValueError(msg) - - if not isinstance(name, str): - msg = 'Unable to add an S(a,b) table to Material ID="{}" with a ' \ - 'non-string table name "{}"'.format(self._id, name) - raise ValueError(msg) - - cv.check_type('S(a,b) fraction', fraction, Real) - cv.check_greater_than('S(a,b) fraction', fraction, 0.0, True) - cv.check_less_than('S(a,b) fraction', fraction, 1.0, True) - - new_name = openmc.data.get_thermal_name(name) - if new_name != name: - msg = 'OpenMC S(a,b) tables follow the GND naming convention. ' \ - 'Table "{}" is being renamed as "{}".'.format(name, new_name) - warnings.warn(msg) - - self._sab.append((new_name, fraction)) - - def make_isotropic_in_lab(self): - self.isotropic = [x[0] for x in self._nuclides] - - def get_nuclides(self): - """Returns all nuclides in the material - - Returns - ------- - nuclides : list of str - List of nuclide names - - """ - return [x[0] for x in self._nuclides] - - def get_nuclide_densities(self): - """Returns all nuclides in the material and their densities - - Returns - ------- - nuclides : dict - Dictionary whose keys are nuclide names and values are 3-tuples of - (nuclide, density percent, density percent type) - - """ - - nuclides = OrderedDict() - - for nuclide, density, density_type in self._nuclides: - nuclides[nuclide] = (nuclide, density, density_type) - - return nuclides - - def get_nuclide_atom_densities(self): - """Returns all nuclides in the material and their atomic densities in - units of atom/b-cm - - Returns - ------- - nuclides : dict - Dictionary whose keys are nuclide names and values are tuples of - (nuclide, density in atom/b-cm) - - """ - - # Expand elements in to nuclides - nuclides = self.get_nuclide_densities() - - sum_density = False - if self.density_units == 'sum': - sum_density = True - density = 0. - elif self.density_units == 'macro': - density = self.density - elif self.density_units == 'g/cc' or self.density_units == 'g/cm3': - density = -self.density - elif self.density_units == 'kg/m3': - density = -0.001 * self.density - elif self.density_units == 'atom/b-cm': - density = self.density - elif self.density_units == 'atom/cm3' or self.density_units == 'atom/cc': - density = 1.E-24 * self.density - - # For ease of processing split out nuc, nuc_density, - # and nuc_density_type in to separate arrays - nucs = [] - nuc_densities = [] - nuc_density_types = [] - - for nuclide in nuclides.items(): - nuc, nuc_density, nuc_density_type = nuclide[1] - nucs.append(nuc) - nuc_densities.append(nuc_density) - nuc_density_types.append(nuc_density_type) - - nucs = np.array(nucs) - nuc_densities = np.array(nuc_densities) - nuc_density_types = np.array(nuc_density_types) - - if sum_density: - density = np.sum(nuc_densities) - - percent_in_atom = np.all(nuc_density_types == 'ao') - density_in_atom = density > 0. - sum_percent = 0. - - # Convert the weight amounts to atomic amounts - if not percent_in_atom: - for n, nuc in enumerate(nucs): - nuc_densities[n] *= self.average_molar_mass / \ - openmc.data.atomic_mass(nuc) - - # Now that we have the atomic amounts, lets finish calculating densities - sum_percent = np.sum(nuc_densities) - nuc_densities = nuc_densities / sum_percent - - # Convert the mass density to an atom density - if not density_in_atom: - density = -density / self.average_molar_mass * 1.E-24 \ - * openmc.data.AVOGADRO - - nuc_densities = density * nuc_densities - - nuclides = OrderedDict() - for n, nuc in enumerate(nucs): - nuclides[nuc] = (nuc, nuc_densities[n]) - - return nuclides - - def get_mass_density(self, nuclide=None): - """Return mass density of one or all nuclides - - Parameters - ---------- - nuclides : str, optional - Nuclide for which density is desired. If not specified, the density - for the entire material is given. - - Returns - ------- - float - Density of the nuclide/material in [g/cm^3] - - """ - mass_density = 0.0 - for nuc, atoms_per_cc in self.get_nuclide_atom_densities().values(): - if nuclide is None or nuclide == nuc: - density_i = 1e24 * atoms_per_cc * openmc.data.atomic_mass(nuc) \ - / openmc.data.AVOGADRO - mass_density += density_i - return mass_density - - def get_mass(self, nuclide=None): - """Return mass of one or all nuclides. - - Note that this method requires that the :attr:`Material.volume` has - already been set. - - Parameters - ---------- - nuclides : str, optional - Nuclide for which mass is desired. If not specified, the density - for the entire material is given. - - Returns - ------- - float - Mass of the nuclide/material in [g] - - """ - if self.volume is None: - raise ValueError("Volume must be set in order to determine mass.") - return self.volume*self.get_mass_density(nuclide) - - def clone(self, memo=None): - """Create a copy of this material with a new unique ID. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Material - The clone of this material - - """ - - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - # Temporarily remove paths -- this is done so that when the clone is - # made, it doesn't create a copy of the paths (which are specific to - # an instance) - paths = self._paths - self._paths = None - - clone = deepcopy(self) - clone.id = None - clone._num_instances = None - - # Restore paths on original instance - self._paths = paths - - # Memoize the clone - memo[self] = clone - - return memo[self] - - def _get_nuclide_xml(self, nuclide, distrib=False): - xml_element = ET.Element("nuclide") - xml_element.set("name", nuclide[0]) - - if not distrib: - if nuclide[2] == 'ao': - xml_element.set("ao", str(nuclide[1])) - else: - xml_element.set("wo", str(nuclide[1])) - - return xml_element - - def _get_macroscopic_xml(self, macroscopic): - xml_element = ET.Element("macroscopic") - xml_element.set("name", macroscopic) - - return xml_element - - def _get_nuclides_xml(self, nuclides, distrib=False): - xml_elements = [] - for nuclide in nuclides: - xml_elements.append(self._get_nuclide_xml(nuclide, distrib)) - return xml_elements - - def to_xml_element(self, cross_sections=None): - """Return XML representation of the material - - Parameters - ---------- - cross_sections : str - Path to an XML cross sections listing file - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing material data - - """ - - # Create Material XML element - element = ET.Element("material") - element.set("id", str(self._id)) - - if len(self._name) > 0: - element.set("name", str(self._name)) - - if self._depletable: - element.set("depletable", "true") - - if self._volume: - element.set("volume", str(self._volume)) - - # Create temperature XML subelement - if self.temperature is not None: - element.set("temperature", str(self.temperature)) - - # Create density XML subelement - if self._density is not None or self._density_units == 'sum': - subelement = ET.SubElement(element, "density") - if self._density_units != 'sum': - subelement.set("value", str(self._density)) - subelement.set("units", self._density_units) - else: - raise ValueError('Density has not been set for material {}!' - .format(self.id)) - - if not self._convert_to_distrib_comps: - if self._macroscopic is None: - # Create nuclide XML subelements - subelements = self._get_nuclides_xml(self._nuclides) - for subelement in subelements: - element.append(subelement) - else: - # Create macroscopic XML subelements - subelement = self._get_macroscopic_xml(self._macroscopic) - element.append(subelement) - - else: - subelement = ET.SubElement(element, "compositions") - - comps = [] - allnucs = self._nuclides - dist_per_type = allnucs[0][2] - for nuc in allnucs: - if nuc[2] != dist_per_type: - msg = 'All nuclides and elements in a distributed ' \ - 'material must have the same type, either ao or wo' - raise ValueError(msg) - comps.append(nuc[1]) - - if self._distrib_otf_file is None: - # Create values and units subelements - subsubelement = ET.SubElement(subelement, "values") - subsubelement.text = ' '.join([str(c) for c in comps]) - subsubelement = ET.SubElement(subelement, "units") - subsubelement.text = dist_per_type - else: - # Specify the materials file - subsubelement = ET.SubElement(subelement, "otf_file_path") - subsubelement.text = self._distrib_otf_file - - if self._macroscopic is None: - # Create nuclide XML subelements - subelements = self._get_nuclides_xml(self._nuclides, - distrib=True) - for subelement_nuc in subelements: - subelement.append(subelement_nuc) - else: - # Create macroscopic XML subelements - subsubelement = self._get_macroscopic_xml(self._macroscopic) - subelement.append(subsubelement) - - if self._sab: - for sab in self._sab: - subelement = ET.SubElement(element, "sab") - subelement.set("name", sab[0]) - if sab[1] != 1.0: - subelement.set("fraction", str(sab[1])) - - if self._isotropic: - subelement = ET.SubElement(element, "isotropic") - subelement.text = ' '.join(self._isotropic) - - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate material from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.Material - Material generated from XML element - - """ - mat_id = int(elem.get('id')) - mat = cls(mat_id) - mat.name = elem.get('name') - - if "temperature" in elem.attrib: - mat.temperature = float(elem.get("temperature")) - - if 'volume' in elem.attrib: - mat.volume = float(elem.get('volume')) - mat.depletable = bool(elem.get('depletable')) - - # Get each nuclide - for nuclide in elem.findall('nuclide'): - name = nuclide.attrib['name'] - if 'ao' in nuclide.attrib: - mat.add_nuclide(name, float(nuclide.attrib['ao'])) - elif 'wo' in nuclide.attrib: - mat.add_nuclide(name, float(nuclide.attrib['wo']), 'wo') - - # Get each S(a,b) table - for sab in elem.findall('sab'): - fraction = float(sab.get('fraction', 1.0)) - mat.add_s_alpha_beta(sab.get('name'), fraction) - - # Get total material density - density = elem.find('density') - units = density.get('units') - if units == 'sum': - mat.set_density(units) - else: - value = float(density.get('value')) - mat.set_density(units, value) - - # Check for isotropic scattering nuclides - isotropic = elem.find('isotropic') - if isotropic is not None: - mat.isotropic = isotropic.text.split() - - return mat - - -class Materials(cv.CheckedList): - """Collection of Materials used for an OpenMC simulation. - - This class corresponds directly to the materials.xml input file. It can be - thought of as a normal Python list where each member is a - :class:`Material`. It behaves like a list as the following example - demonstrates: - - >>> fuel = openmc.Material() - >>> clad = openmc.Material() - >>> water = openmc.Material() - >>> m = openmc.Materials([fuel]) - >>> m.append(water) - >>> m += [clad] - - Parameters - ---------- - materials : Iterable of openmc.Material - Materials to add to the collection - cross_sections : str - Indicates the path to an XML cross section listing file (usually named - cross_sections.xml). If it is not set, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for - continuous-energy calculations and - :envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group - calculations to find the path to the HDF5 cross section file. - - """ - - def __init__(self, materials=None): - super().__init__(Material, 'materials collection') - self._cross_sections = None - - if materials is not None: - self += materials - - @property - def cross_sections(self): - return self._cross_sections - - @cross_sections.setter - def cross_sections(self, cross_sections): - cv.check_type('cross sections', cross_sections, str) - self._cross_sections = cross_sections - - def append(self, material): - """Append material to collection - - Parameters - ---------- - material : openmc.Material - Material to append - - """ - super().append(material) - - def insert(self, index, material): - """Insert material before index - - Parameters - ---------- - index : int - Index in list - material : openmc.Material - Material to insert - - """ - super().insert(index, material) - - def make_isotropic_in_lab(self): - for material in self: - material.make_isotropic_in_lab() - - def _create_material_subelements(self, root_element): - for material in sorted(self, key=lambda x: x.id): - root_element.append(material.to_xml_element(self.cross_sections)) - - def _create_cross_sections_subelement(self, root_element): - if self._cross_sections is not None: - element = ET.SubElement(root_element, "cross_sections") - element.text = str(self._cross_sections) - - def export_to_xml(self, path='materials.xml'): - """Export material collection to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'materials.xml'. - - """ - - root_element = ET.Element("materials") - self._create_cross_sections_subelement(root_element) - self._create_material_subelements(root_element) - - # Clean the indentation in the file to be user-readable - clean_indentation(root_element) - - # Check if path is a directory - p = Path(path) - if p.is_dir(): - p /= 'materials.xml' - - # Write the XML Tree to the materials.xml file - tree = ET.ElementTree(root_element) - tree.write(str(p), xml_declaration=True, encoding='utf-8') - - @classmethod - def from_xml(cls, path='materials.xml'): - """Generate materials collection from XML file - - Parameters - ---------- - path : str, optional - Path to materials XML file - - Returns - ------- - openmc.Materials - Materials collection - - """ - tree = ET.parse(path) - root = tree.getroot() - - # Generate each material - materials = cls() - for material in root.findall('material'): - materials.append(Material.from_xml_element(material)) - - # Check for cross sections settings - xs = tree.find('cross_sections') - if xs is not None: - materials.cross_sections = xs.text - - return materials diff --git a/openmc/mesh.py b/openmc/mesh.py deleted file mode 100644 index 0a8b51c5f..000000000 --- a/openmc/mesh.py +++ /dev/null @@ -1,560 +0,0 @@ -from abc import ABCMeta -from collections.abc import Iterable -from numbers import Real, Integral -from xml.etree import ElementTree as ET -import sys -import warnings - -import numpy as np - -import openmc.checkvalue as cv -import openmc -from openmc._xml import get_text -from openmc.mixin import EqualityMixin, IDManagerMixin - - -class MeshBase(IDManagerMixin, metaclass=ABCMeta): - """A mesh that partitions geometry for tallying purposes. - - Parameters - ---------- - mesh_id : int - Unique identifier for the mesh - name : str - Name of the mesh - - Attributes - ---------- - id : int - Unique identifier for the mesh - name : str - Name of the mesh - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, mesh_id=None, name=''): - # Initialize Mesh class attributes - self.id = mesh_id - self.name = name - - @property - def name(self): - return self._name - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('name for mesh ID="{0}"'.format(self._id), - name, str) - self._name = name - else: - self._name = '' - - @classmethod - def from_hdf5(cls, group): - """Create mesh from HDF5 group - - Parameters - ---------- - group : h5py.Group - Group in HDF5 file - - Returns - ------- - openmc.MeshBase - Instance of a MeshBase subclass - - """ - - mesh_type = group['type'][()].decode() - if mesh_type == 'regular': - return RegularMesh.from_hdf5(group) - elif mesh_type == 'rectilinear': - return RectilinearMesh.from_hdf5(group) - else: - raise ValueError('Unrecognized mesh type: "' + mesh_type + '"') - - -class RegularMesh(MeshBase): - """A regular Cartesian mesh in one, two, or three dimensions - - Parameters - ---------- - mesh_id : int - Unique identifier for the mesh - name : str - Name of the mesh - - Attributes - ---------- - id : int - Unique identifier for the mesh - name : str - Name of the mesh - dimension : Iterable of int - The number of mesh cells in each direction. - n_dimension : int - Number of mesh dimensions. - lower_left : Iterable of float - The lower-left corner of the structured mesh. If only two coordinate are - given, it is assumed that the mesh is an x-y mesh. - upper_right : Iterable of float - The upper-right corner of the structrued mesh. If only two coordinate - are given, it is assumed that the mesh is an x-y mesh. - width : Iterable of float - The width of mesh cells in each direction. - indices : Iterable of tuple - An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), - (2, 1, 1), ...] - - """ - - def __init__(self, mesh_id=None, name=''): - super().__init__(mesh_id, name) - - self._dimension = None - self._lower_left = None - self._upper_right = None - self._width = None - - @property - def dimension(self): - return self._dimension - - @property - def n_dimension(self): - return len(self._dimension) - - @property - def lower_left(self): - return self._lower_left - - @property - def upper_right(self): - return self._upper_right - - @property - def width(self): - return self._width - - @property - def num_mesh_cells(self): - return np.prod(self._dimension) - - @property - def indices(self): - ndim = len(self._dimension) - if ndim == 3: - nx, ny, nz = self.dimension - return ((x, y, z) - for z in range(1, nz + 1) - for y in range(1, ny + 1) - for x in range(1, nx + 1)) - elif ndim == 2: - nx, ny = self.dimension - return ((x, y) - for y in range(1, ny + 1) - for x in range(1, nx + 1)) - else: - nx, = self.dimension - return ((x,) for x in range(1, nx + 1)) - - @dimension.setter - def dimension(self, dimension): - cv.check_type('mesh dimension', dimension, Iterable, Integral) - cv.check_length('mesh dimension', dimension, 1, 3) - self._dimension = dimension - - @lower_left.setter - def lower_left(self, lower_left): - cv.check_type('mesh lower_left', lower_left, Iterable, Real) - cv.check_length('mesh lower_left', lower_left, 1, 3) - self._lower_left = lower_left - - @upper_right.setter - def upper_right(self, upper_right): - cv.check_type('mesh upper_right', upper_right, Iterable, Real) - cv.check_length('mesh upper_right', upper_right, 1, 3) - self._upper_right = upper_right - - @width.setter - def width(self, width): - cv.check_type('mesh width', width, Iterable, Real) - cv.check_length('mesh width', width, 1, 3) - self._width = width - - def __repr__(self): - string = 'RegularMesh\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type) - string += '{0: <16}{1}{2}\n'.format('\tBasis', '=\t', self._dimension) - string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._lower_left) - string += '{0: <16}{1}{2}\n'.format('\tOrigin', '=\t', self._upper_right) - string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._width) - return string - - @classmethod - def from_hdf5(cls, group): - mesh_id = int(group.name.split('/')[-1].lstrip('mesh ')) - - # Read and assign mesh properties - mesh = cls(mesh_id) - mesh.dimension = group['dimension'][()] - mesh.lower_left = group['lower_left'][()] - mesh.upper_right = group['upper_right'][()] - mesh.width = group['width'][()] - - return mesh - - @classmethod - def from_rect_lattice(cls, lattice, division=1, mesh_id=None, name=''): - """Create mesh from an existing rectangular lattice - - Parameters - ---------- - lattice : openmc.RectLattice - Rectangular lattice used as a template for this mesh - division : int - Number of mesh cells per lattice cell. - If not specified, there will be 1 mesh cell per lattice cell. - mesh_id : int - Unique identifier for the mesh - name : str - Name of the mesh - - Returns - ------- - openmc.RegularMesh - RegularMesh instance - - """ - cv.check_type('rectangular lattice', lattice, openmc.RectLattice) - - shape = np.array(lattice.shape) - width = lattice.pitch*shape - - mesh = cls(mesh_id, name) - mesh.lower_left = lattice.lower_left - mesh.upper_right = lattice.lower_left + width - mesh.dimension = shape*division - - return mesh - - def to_xml_element(self): - """Return XML representation of the mesh - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing mesh data - - """ - - element = ET.Element("mesh") - element.set("id", str(self._id)) - - if self._dimension is not None: - subelement = ET.SubElement(element, "dimension") - subelement.text = ' '.join(map(str, self._dimension)) - - subelement = ET.SubElement(element, "lower_left") - subelement.text = ' '.join(map(str, self._lower_left)) - - if self._upper_right is not None: - subelement = ET.SubElement(element, "upper_right") - subelement.text = ' '.join(map(str, self._upper_right)) - - if self._width is not None: - subelement = ET.SubElement(element, "width") - subelement.text = ' '.join(map(str, self._width)) - - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate mesh from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.Mesh - Mesh generated from XML element - - """ - mesh_id = int(get_text(elem, 'id')) - mesh = cls(mesh_id) - - mesh_type = get_text(elem, 'type') - if mesh_type is not None: - mesh.type = mesh_type - - dimension = get_text(elem, 'dimension') - if dimension is not None: - mesh.dimension = [int(x) for x in dimension.split()] - - lower_left = get_text(elem, 'lower_left') - if lower_left is not None: - mesh.lower_left = [float(x) for x in lower_left.split()] - - upper_right = get_text(elem, 'upper_right') - if upper_right is not None: - mesh.upper_right = [float(x) for x in upper_right.split()] - - width = get_text(elem, 'width') - if width is not None: - mesh.width = [float(x) for x in width.split()] - - return mesh - - def build_cells(self, bc=['reflective'] * 6): - """Generates a lattice of universes with the same dimensionality - as the mesh object. The individual cells/universes produced - will not have material definitions applied and so downstream code - will have to apply that information. - - Parameters - ---------- - bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'} - Boundary conditions for each of the four faces of a rectangle - (if aplying to a 2D mesh) or six faces of a parallelepiped - (if applying to a 3D mesh) provided in the following order: - [x min, x max, y min, y max, z min, z max]. 2-D cells do not - contain the z min and z max entries. - - Returns - ------- - root_cell : openmc.Cell - The cell containing the lattice representing the mesh geometry; - this cell is a single parallelepiped with boundaries matching - the outermost mesh boundary with the boundary conditions from bc - applied. - cells : iterable of openmc.Cell - The list of cells within each lattice position mimicking the mesh - geometry. - - """ - - cv.check_length('bc', bc, length_min=4, length_max=6) - for entry in bc: - cv.check_value('bc', entry, ['transmission', 'vacuum', - 'reflective', 'periodic']) - - n_dim = len(self.dimension) - - # Build the cell which will contain the lattice - xplanes = [openmc.XPlane(self.lower_left[0], bc[0]), - openmc.XPlane(self.upper_right[0], bc[1])] - if n_dim == 1: - yplanes = [openmc.YPlane(-1e10, 'reflective'), - openmc.YPlane(1e10, 'reflective')] - else: - yplanes = [openmc.YPlane(self.lower_left[1], bc[2]), - openmc.YPlane(self.upper_right[1], bc[3])] - - if n_dim <= 2: - # Would prefer to have the z ranges be the max supported float, but - # these values are apparently different between python and Fortran. - # Choosing a safe and sane default. - # Values of +/-1e10 are used here as there seems to be an - # inconsistency between what numpy uses as the max float and what - # Fortran expects for a real(8), so this avoids code complication - # and achieves the same goal. - zplanes = [openmc.ZPlane(-1e10, 'reflective'), - openmc.ZPlane(1e10, 'reflective')] - else: - zplanes = [openmc.ZPlane(self.lower_left[2], bc[4]), - openmc.ZPlane(self.upper_right[2], bc[5])] - root_cell = openmc.Cell() - root_cell.region = ((+xplanes[0] & -xplanes[1]) & - (+yplanes[0] & -yplanes[1]) & - (+zplanes[0] & -zplanes[1])) - - # Build the universes which will be used for each of the (i,j,k) - # locations within the mesh. - # We will concurrently build cells to assign to these universes - cells = [] - universes = [] - for index in self.indices: - cells.append(openmc.Cell()) - universes.append(openmc.Universe()) - universes[-1].add_cell(cells[-1]) - - lattice = openmc.RectLattice() - lattice.lower_left = self.lower_left - - # Assign the universe and rotate to match the indexing expected for - # the lattice - if n_dim == 1: - universe_array = np.array([universes]) - elif n_dim == 2: - universe_array = np.empty(self.dimension[::-1], - dtype=openmc.Universe) - i = 0 - for y in range(self.dimension[1] - 1, -1, -1): - for x in range(self.dimension[0]): - universe_array[y][x] = universes[i] - i += 1 - else: - universe_array = np.empty(self.dimension[::-1], - dtype=openmc.Universe) - i = 0 - for z in range(self.dimension[2]): - for y in range(self.dimension[1] - 1, -1, -1): - for x in range(self.dimension[0]): - universe_array[z][y][x] = universes[i] - i += 1 - lattice.universes = universe_array - - if self.width is not None: - lattice.pitch = self.width - else: - dx = ((self.upper_right[0] - self.lower_left[0]) / - self.dimension[0]) - - if n_dim == 1: - lattice.pitch = [dx] - elif n_dim == 2: - dy = ((self.upper_right[1] - self.lower_left[1]) / - self.dimension[1]) - lattice.pitch = [dx, dy] - else: - dy = ((self.upper_right[1] - self.lower_left[1]) / - self.dimension[1]) - dz = ((self.upper_right[2] - self.lower_left[2]) / - self.dimension[2]) - lattice.pitch = [dx, dy, dz] - - # Fill Cell with the Lattice - root_cell.fill = lattice - - return root_cell, cells - - -def Mesh(*args, **kwargs): - warnings.warn("Mesh has been renamed RegularMesh. Future versions of " - "OpenMC will not accept the name Mesh.") - return RegularMesh(*args, **kwargs) - - -class RectilinearMesh(MeshBase): - """A 3D rectilinear Cartesian mesh - - Parameters - ---------- - mesh_id : int - Unique identifier for the mesh - name : str - Name of the mesh - - Attributes - ---------- - id : int - Unique identifier for the mesh - name : str - Name of the mesh - n_dimension : int - Number of mesh dimensions (always 3 for a RectilinearMesh). - x_grid : Iterable of float - Mesh boundary points along the x-axis. - y_grid : Iterable of float - Mesh boundary points along the y-axis. - z_grid : Iterable of float - Mesh boundary points along the z-axis. - indices : Iterable of tuple - An iterable of mesh indices for each mesh element, e.g. [(1, 1, 1), - (2, 1, 1), ...] - - """ - - def __init__(self, mesh_id=None, name=''): - super().__init__(mesh_id, name) - - self._x_grid = None - self._y_grid = None - self._z_grid = None - - @property - def n_dimension(self): - return 3 - - @property - def x_grid(self): - return self._x_grid - - @property - def y_grid(self): - return self._y_grid - - @property - def z_grid(self): - return self._z_grid - - @property - def indices(self): - nx = len(self.x_grid) - 1 - ny = len(self.y_grid) - 1 - nz = len(self.z_grid) - 1 - return ((x, y, z) - for z in range(1, nz + 1) - for y in range(1, ny + 1) - for x in range(1, nx + 1)) - - @x_grid.setter - def x_grid(self, grid): - cv.check_type('mesh x_grid', grid, Iterable, Real) - self._x_grid = grid - - @y_grid.setter - def y_grid(self, grid): - cv.check_type('mesh y_grid', grid, Iterable, Real) - self._y_grid = grid - - @z_grid.setter - def z_grid(self, grid): - cv.check_type('mesh z_grid', grid, Iterable, Real) - self._z_grid = grid - - @classmethod - def from_hdf5(cls, group): - mesh_id = int(group.name.split('/')[-1].lstrip('mesh ')) - - # Read and assign mesh properties - mesh = cls(mesh_id) - mesh.x_grid = group['x_grid'][()] - mesh.y_grid = group['y_grid'][()] - mesh.z_grid = group['z_grid'][()] - - return mesh - - def to_xml_element(self): - """Return XML representation of the mesh - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing mesh data - - """ - - element = ET.Element("mesh") - element.set("id", str(self._id)) - element.set("type", "rectilinear") - - subelement = ET.SubElement(element, "x_grid") - subelement.text = ' '.join(map(str, self.x_grid)) - - subelement = ET.SubElement(element, "y_grid") - subelement.text = ' '.join(map(str, self.y_grid)) - - subelement = ET.SubElement(element, "z_grid") - subelement.text = ' '.join(map(str, self.z_grid)) - - return element diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py deleted file mode 100644 index 1b1ad0dce..000000000 --- a/openmc/mgxs/__init__.py +++ /dev/null @@ -1,625 +0,0 @@ -import numpy as np - -from openmc.mgxs.groups import EnergyGroups -from openmc.mgxs.library import Library -from openmc.mgxs.mgxs import * -from openmc.mgxs.mdgxs import * - -GROUP_STRUCTURES = {} -"""Dictionary of commonly used energy group structures: - -- "CASMO-X" (where X is 2, 4, 8, 16, 25, 40 or 70) from the CASMO_ lattice - physics code -- "XMAS-172_" designed for LWR analysis ([SAR1990]_, [SAN2004]_) -- "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations - of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) -- activation_ energy group structures "VITAMIN-J-175", "TRIPOLI-315", - "CCFE-709_" and "UKAEA-1102_" - -.. _CASMO: https://www.studsvik.com/SharepointFiles/CASMO-5%20Development%20and%20Applications.pdf -.. _XMAS-172: https://www-nds.iaea.org/wimsd/energy.htm -.. _SHEM-361: https://www.polymtl.ca/merlin/downloads/FP214.pdf -.. _activation: https://fispact.ukaea.uk/wiki/Keyword:GETXS -.. _CCFE-709: https://fispact.ukaea.uk/wiki/CCFE-709_group_structure -.. _UKAEA-1102: https://fispact.ukaea.uk/wiki/UKAEA-1102_group_structure -.. [SAR1990] Sartori, E., OECD/NEA Data Bank: Standard Energy Group Structures - of Cross Section Libraries for Reactor Shielding, Reactor Cell and Fusion - Neutronics Applications: VITAMIN-J, ECCO-33, ECCO-2000 and XMAS JEF/DOC-315 - Revision 3 - DRAFT (December 11, 1990). -.. [SAN2004] Santamarina, A., Collignon, C., & Garat, C. (2004). French - calculation schemes for light water reactor analysis. United States: - American Nuclear Society - ANS. -.. [HFA2005] Hfaiedh, N. & Santamarina, A., "Determination of the Optimized - SHEM Mesh for Neutron Transport Calculations," Proc. Top. Mtg. in - Mathematics & Computations, Supercomputing, Reactor Physics and Nuclear and - Biological Applications, September 12-15, Avignon, France, 2005. -.. [SAN2007] Santamarina, A. & Hfaiedh, N. (2007). The SHEM energy mesh for - accurate fuel depletion and BUC calculations. Proceedings of the International - Conference on Safety Criticality ICNC 2007, St Peterburg (Russia), Vol. I pp. - 446-452. -.. [HEB2008] Hébert, Alain & Santamarina, Alain. (2008). Refinement of the - Santamarina-Hfaiedh energy mesh between 22.5 eV and 11.4 keV. International - Conference on the Physics of Reactors 2008, PHYSOR 08. 2. 929-938. -""" - -GROUP_STRUCTURES['CASMO-2'] = np.array([ - 0., 6.25e-1, 2.e7]) -GROUP_STRUCTURES['CASMO-4'] = np.array([ - 0., 6.25e-1, 5.53e3, 8.21e5, 2.e7]) -GROUP_STRUCTURES['CASMO-8'] = np.array([ - 0., 5.8e-2, 1.4e-1, 2.8e-1, 6.25e-1, 4., 5.53e3, 8.21e5, 2.e7]) -GROUP_STRUCTURES['CASMO-16'] = np.array([ - 0., 3.e-2, 5.8e-2, 1.4e-1, 2.8e-1, 3.5e-1, 6.25e-1, 8.5e-1, - 9.72e-1, 1.02, 1.097, 1.15, 1.3, 4., 5.53e3, 8.21e5, 2.e7]) -GROUP_STRUCTURES['CASMO-25'] = np.array([ - 0., 3.e-2, 5.8e-2, 1.4e-1, 2.8e-1, 3.5e-1, 6.25e-1, 9.72e-1, 1.02, 1.097, - 1.15, 1.855, 4., 9.877, 1.5968e1, 1.4873e2, 5.53e3, 9.118e3, 1.11e5, 5.e5, - 8.21e5, 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2.e7]) -GROUP_STRUCTURES['CASMO-40'] = np.array([ - 0., 1.5e-2, 3.e-2, 4.2e-2, 5.8e-2, 8.e-2, 1.e-1, 1.4e-1, - 1.8e-1, 2.2e-1, 2.8e-1, 3.5e-1, 6.25e-1, 8.5e-1, 9.5e-1, - 9.72e-1, 1.02, 1.097, 1.15, 1.3, 1.5, 1.855, 2.1, 2.6, 3.3, 4., - 9.877, 1.5968e1, 2.77e1, 4.8052e1, 1.4873e2, 5.53e3, 9.118e3, - 1.11e5, 5.e5, 8.21e5, 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2.e7]) -GROUP_STRUCTURES['CASMO-70'] = np.array([ - 0., 5.e-3, 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 3.5e-2, 4.2e-2, - 5.e-2, 5.8e-2, 6.7e-2, 8.e-2, 1.e-1, 1.4e-1, 1.8e-1, 2.2e-1, - 2.5e-1, 2.8e-1, 3.e-1, 3.2e-1, 3.5e-1, 4.e-1, 5.e-1, 6.25e-1, - 7.8e-1, 8.5e-1, 9.1e-1, 9.5e-1, 9.72e-1, 9.96e-1, 1.02, 1.045, - 1.071, 1.097, 1.123, 1.15, 1.3, 1.5, 1.855, 2.1, 2.6, 3.3, 4., - 9.877, 1.5968e1, 2.77e1, 4.8052e1, 7.5501e1, 1.4873e2, - 3.6726e2, 9.069e2, 1.4251e3, 2.2395e3, 3.5191e3, 5.53e3, - 9.118e3, 1.503e4, 2.478e4, 4.085e4, 6.734e4, 1.11e5, 1.83e5, - 3.025e5, 5.e5, 8.21e5, 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2.e7]) -GROUP_STRUCTURES['XMAS-172'] = np.array([ - 1.00001e-05, 3.00000e-03, 5.00000e-03, 6.90000e-03, 1.00000e-02, - 1.50000e-02, 2.00000e-02, 2.50000e-02, 3.00000e-02, 3.50000e-02, - 4.20000e-02, 5.00000e-02, 5.80000e-02, 6.70000e-02, 7.70000e-02, - 8.00000e-02, 9.50000e-02, 1.00001e-01, 1.15000e-01, 1.34000e-01, - 1.40000e-01, 1.60000e-01, 1.80000e-01, 1.89000e-01, 2.20000e-01, - 2.48000e-01, 2.80000e-01, 3.00000e-01, 3.14500e-01, 3.20000e-01, - 3.50000e-01, 3.91000e-01, 4.00000e-01, 4.33000e-01, 4.85000e-01, - 5.00000e-01, 5.40000e-01, 6.25000e-01, 7.05000e-01, 7.80000e-01, - 7.90000e-01, 8.50000e-01, 8.60000e-01, 9.10000e-01, 9.30000e-01, - 9.50000e-01, 9.72000e-01, 9.86000e-01, 9.96000e-01, 1.02000e+00, - 1.03500e+00, 1.04500e+00, 1.07100e+00, 1.09700e+00, 1.11000e+00, - 1.12535e+00, 1.15000e+00, 1.17000e+00, 1.23500e+00, 1.30000e+00, - 1.33750e+00, 1.37000e+00, 1.44498e+00, 1.47500e+00, 1.50000e+00, - 1.59000e+00, 1.67000e+00, 1.75500e+00, 1.84000e+00, 1.93000e+00, - 2.02000e+00, 2.10000e+00, 2.13000e+00, 2.36000e+00, 2.55000e+00, - 2.60000e+00, 2.72000e+00, 2.76792e+00, 3.30000e+00, 3.38075e+00, - 4.00000e+00, 4.12925e+00, 5.04348e+00, 5.34643e+00, 6.16012e+00, - 7.52398e+00, 8.31529e+00, 9.18981e+00, 9.90555e+00, 1.12245e+01, - 1.37096e+01, 1.59283e+01, 1.94548e+01, 2.26033e+01, 2.49805e+01, - 2.76077e+01, 3.05113e+01, 3.37201e+01, 3.72665e+01, 4.01690e+01, - 4.55174e+01, 4.82516e+01, 5.15780e+01, 5.55951e+01, 6.79041e+01, - 7.56736e+01, 9.16609e+01, 1.36742e+02, 1.48625e+02, 2.03995e+02, - 3.04325e+02, 3.71703e+02, 4.53999e+02, 6.77287e+02, 7.48518e+02, - 9.14242e+02, 1.01039e+03, 1.23410e+03, 1.43382e+03, 1.50733e+03, - 2.03468e+03, 2.24867e+03, 3.35463e+03, 3.52662e+03, 5.00451e+03, - 5.53084e+03, 7.46586e+03, 9.11882e+03, 1.11378e+04, 1.50344e+04, - 1.66156e+04, 2.47875e+04, 2.73944e+04, 2.92830e+04, 3.69786e+04, - 4.08677e+04, 5.51656e+04, 6.73795e+04, 8.22975e+04, 1.11090e+05, - 1.22773e+05, 1.83156e+05, 2.47235e+05, 2.73237e+05, 3.01974e+05, - 4.07622e+05, 4.50492e+05, 4.97871e+05, 5.50232e+05, 6.08101e+05, - 8.20850e+05, 9.07180e+05, 1.00259e+06, 1.10803e+06, 1.22456e+06, - 1.35335e+06, 1.65299e+06, 2.01897e+06, 2.23130e+06, 2.46597e+06, - 3.01194e+06, 3.67879e+06, 4.49329e+06, 5.48812e+06, 6.06531e+06, - 6.70320e+06, 8.18731e+06, 1.00000e+07, 1.16183e+07, 1.38403e+07, - 1.49182e+07, 1.73325e+07, 1.96403e+07]) -GROUP_STRUCTURES['VITAMIN-J-175'] = np.array([ - 1.0000e-5, 1.0000e-1, 4.1399e-1, 5.3158e-1, 6.8256e-1, - 8.7643e-1, 1.1253, 1.4450, 1.8554, 2.3824, 3.0590, - 3.9279, 5.0435, 6.4759, 8.3153, 1.0677e1, 1.3710e1, - 1.7604e1, 2.2603e1, 2.9023e1, 3.7266e1, 4.7851e1, 6.1442e1, - 7.8893e1, 1.0130e2, 1.3007e2, 1.6702e2, 2.1445e2, 2.7536e2, - 3.5358e2, 4.5400e2, 5.8295e2, 7.4852e2, 9.6112e2, 1.2341e3, - 1.5846e3, 2.0347e3, 2.2487e3, 2.4852e3, 2.6126e3, 2.7465e3, - 3.0354e3, 3.3546e3, 3.7074e3, 4.3074e3, 5.5308e3, 7.1017e3, - 9.1188e3, 1.0595e4, 1.1709e4, 1.5034e4, 1.9304e4, 2.1875e4, - 2.3579e4, 2.4176e4, 2.4788e4, 2.6058e4, 2.7000e4, 2.8501e4, - 3.1828e4, 3.4307e4, 4.0868e4, 4.6309e4, 5.2475e4, 5.6562e4, - 6.7380e4, 7.2024e4, 7.9499e4, 8.2503e4, 8.6517e4, 9.8036e4, - 1.1109e5, 1.1679e5, 1.2277e5, 1.2907e5, 1.3569e5, 1.4264e5, - 1.4996e5, 1.5764e5, 1.6573e5, 1.7422e5, 1.8316e5, 1.9255e5, - 2.0242e5, 2.1280e5, 2.2371e5, 2.3518e5, 2.4724e5, 2.7324e5, - 2.8725e5, 2.9452e5, 2.9721e5, 2.9849e5, 3.0197e5, 3.3373e5, - 3.6883e5, 3.8774e5, 4.0762e5, 4.5049e5, 4.9787e5, 5.2340e5, - 5.5023e5, 5.7844e5, 6.0810e5, 6.3928e5, 6.7206e5, 7.0651e5, - 7.4274e5, 7.8082e5, 8.2085e5, 8.6294e5, 9.0718e5, 9.6167e5, - 1.0026e6, 1.1080e6, 1.1648e6, 1.2246e6, 1.2874e6, 1.3534e6, - 1.4227e6, 1.4957e6, 1.5724e6, 1.6530e6, 1.7377e6, 1.8268e6, - 1.9205e6, 2.0190e6, 2.1225e6, 2.2313e6, 2.3069e6, 2.3457e6, - 2.3653e6, 2.3851e6, 2.4660e6, 2.5924e6, 2.7253e6, 2.8650e6, - 3.0119e6, 3.1664e6, 3.3287e6, 3.6788e6, 4.0657e6, 4.4933e6, - 4.7237e6, 4.9658e6, 5.2205e6, 5.4881e6, 5.7695e6, 6.0653e6, - 6.3763e6, 6.5924e6, 6.7032e6, 7.0469e6, 7.4082e6, 7.7880e6, - 8.1873e6, 8.6071e6, 9.0484e6, 9.5123e6, 1.0000e7, 1.0513e7, - 1.1052e7, 1.1618e7, 1.2214e7, 1.2523e7, 1.2840e7, 1.3499e7, - 1.3840e7, 1.4191e7, 1.4550e7, 1.4918e7, 1.5683e7, 1.6487e7, - 1.6905e7, 1.7332e7, 1.9640e7]) -GROUP_STRUCTURES['TRIPOLI-315,'] = np.array([ - 1.0e-5, 1.1e-4, 3.000e-3, 5.500e-3, 1.000e-2, 1.500e-2, 2.000e-2, 3.000e-2, - 3.200e-2, 3.238e-2, 4.300e-2, 5.900e-2, 7.700e-2, 9.500e-2, 1.000e-1, - 1.150e-1, 1.340e-1, 1.600e-1, 1.890e-1, 2.200e-1, 2.480e-1, 2.825e-1, - 3.145e-1, 3.520e-1, 3.910e-1, 4.140e-1, 4.330e-1, 4.850e-1, 5.316e-1, - 5.400e-1, 6.250e-1, 6.826e-1, 7.050e-1, 7.900e-1, 8.600e-1, 8.764e-1, - 9.300e-1, 9.860e-1, 1.010, 1.035, 1.070, 1.080, 1.090, - 1.110, 1.125, 1.170, 1.235, 1.305, 1.370, 1.440, - 1.445, 1.510, 1.590, 1.670, 1.755, 1.840, 1.855, - 1.930, 2.020, 2.130, 2.360, 2.372, 2.768, 3.059, - 3.381, 3.928, 4.129, 4.470, 4.670, 5.043, 5.623, - 6.160, 6.476, 7.079, 7.524, 7.943, 8.315, 8.913, - 9.190, 1.000e1, 1.068e1, 1.122e1, 1.259e1, 1.371e1, 1.523e1, - 1.674e1, 1.760e1, 1.903e1, 2.045e1, 2.260e1, 2.498e1, 2.792e1, - 2.920e1, 3.051e1, 3.389e1, 3.727e1, 3.981e1, 4.552e1, 4.785e1, - 5.012e1, 5.559e1, 6.144e1, 6.310e1, 6.790e1, 7.079e1, 7.889e1, - 8.528e1, 9.166e1, 1.013e2, 1.122e2, 1.301e2, 1.367e2, 1.585e2, - 1.670e2, 1.778e2, 2.040e2, 2.145e2, 2.430e2, 2.754e2, 3.043e2, - 3.536e2, 3.981e2, 4.540e2, 5.145e2, 5.830e2, 6.310e2, 6.773e2, - 7.079e2, 7.485e2, 8.482e2, 9.611e2, 1.010e3, 1.117e3, 1.234e3, - 1.364e3, 1.507e3, 1.585e3, 1.796e3, 2.035e3, 2.113e3, 2.249e3, - 2.371e3, 2.485e3, 2.613e3, 2.661e3, 2.747e3, 2.818e3, 3.035e3, - 3.162e3, 3.355e3, 3.548e3, 3.707e3, 3.981e3, 4.307e3, 4.643e3, - 5.004e3, 5.531e3, 6.267e3, 7.102e3, 7.466e3, 8.251e3, 9.119e3, - 1.008e4, 1.114e4, 1.171e4, 1.273e4, 1.383e4, 1.503e4, 1.585e4, - 1.662e4, 1.778e4, 1.931e4, 1.995e4, 2.054e4, 2.113e4, 2.187e4, - 2.239e4, 2.304e4, 2.358e4, 2.418e4, 2.441e4, 2.479e4, 2.512e4, - 2.585e4, 2.606e4, 2.661e4, 2.700e4, 2.738e4, 2.818e4, 2.850e4, - 2.901e4, 2.985e4, 3.073e4, 3.162e4, 3.183e4, 3.431e4, 3.698e4, - 4.087e4, 4.359e4, 4.631e4, 4.939e4, 5.248e4, 5.517e4, 5.656e4, - 6.173e4, 6.738e4, 7.200e4, 7.499e4, 7.950e4, 8.230e4, 8.250e4, - 8.652e4, 9.804e4, 1.111e5, 1.168e5, 1.228e5, 1.291e5, 1.357e5, - 1.426e5, 1.500e5, 1.576e5, 1.657e5, 1.742e5, 1.832e5, 1.925e5, - 2.024e5, 2.128e5, 2.237e5, 2.352e5, 2.472e5, 2.732e5, 2.873e5, - 2.945e5, 2.972e5, 2.985e5, 3.020e5, 3.337e5, 3.688e5, 3.877e5, - 4.076e5, 4.505e5, 5.234e5, 5.502e5, 5.784e5, 6.081e5, 6.393e5, - 6.721e5, 7.065e5, 7.427e5, 7.808e5, 8.209e5, 8.629e5, 9.072e5, - 9.616e5, 1.003e6, 1.108e6, 1.165e6, 1.225e6, 1.287e6, 1.353e6, - 1.423e6, 1.496e6, 1.572e6, 1.653e6, 1.738e6, 1.827e6, 1.921e6, - 2.019e6, 2.122e6, 2.231e6, 2.307e6, 2.346e6, 2.365e6, 2.385e6, - 2.466e6, 2.592e6, 2.725e6, 2.865e6, 3.012e6, 3.166e6, 3.329e6, - 3.679e6, 4.066e6, 4.493e6, 4.724e6, 4.966e6, 5.220e6, 5.488e6, - 5.769e6, 6.065e6, 6.376e6, 6.592e6, 6.703e6, 7.047e6, 7.408e6, - 7.788e6, 8.187e6, 8.607e6, 9.048e6, 9.512e6, 1.000e7, 1.051e7, - 1.105e7, 1.162e7, 1.221e7, 1.284e7, 1.350e7, 1.384e7, 1.419e7, - 1.455e7, 1.492e7, 1.568e7, 1.649e7, 1.691e7, 1.733e7, 1.964e7]) -GROUP_STRUCTURES['SHEM-361'] = np.array([ - 0.00000e+00, 2.49990e-03, 4.55602e-03, 7.14526e-03, 1.04505e-02, - 1.48300e-02, 2.00104e-02, 2.49394e-02, 2.92989e-02, 3.43998e-02, - 4.02999e-02, 4.73019e-02, 5.54982e-02, 6.51999e-02, 7.64969e-02, - 8.97968e-02, 1.04298e-01, 1.19995e-01, 1.37999e-01, 1.61895e-01, - 1.90005e-01, 2.09610e-01, 2.31192e-01, 2.54997e-01, 2.79989e-01, - 3.05012e-01, 3.25008e-01, 3.52994e-01, 3.90001e-01, 4.31579e-01, - 4.75017e-01, 5.20011e-01, 5.54990e-01, 5.94993e-01, 6.24999e-01, - 7.19999e-01, 8.00371e-01, 8.80024e-01, 9.19978e-01, 9.44022e-01, - 9.63960e-01, 9.81959e-01, 9.96501e-01, 1.00904e+00, 1.02101e+00, - 1.03499e+00, 1.07799e+00, 1.09198e+00, 1.10395e+00, 1.11605e+00, - 1.12997e+00, 1.14797e+00, 1.16999e+00, 1.21397e+00, 1.25094e+00, - 1.29304e+00, 1.33095e+00, 1.38098e+00, 1.41001e+00, 1.44397e+00, - 1.51998e+00, 1.58803e+00, 1.66895e+00, 1.77997e+00, 1.90008e+00, - 1.98992e+00, 2.07010e+00, 2.15695e+00, 2.21709e+00, 2.27299e+00, - 2.33006e+00, 2.46994e+00, 2.55000e+00, 2.59009e+00, 2.62005e+00, - 2.64004e+00, 2.70012e+00, 2.71990e+00, 2.74092e+00, 2.77512e+00, - 2.88405e+00, 3.14211e+00, 3.54307e+00, 3.71209e+00, 3.88217e+00, - 4.00000e+00, 4.21983e+00, 4.30981e+00, 4.41980e+00, 4.76785e+00, - 4.93323e+00, 5.10997e+00, 5.21008e+00, 5.32011e+00, 5.38003e+00, - 5.41025e+00, 5.48817e+00, 5.53004e+00, 5.61979e+00, 5.72015e+00, - 5.80021e+00, 5.96014e+00, 6.05991e+00, 6.16011e+00, 6.28016e+00, - 6.35978e+00, 6.43206e+00, 6.48178e+00, 6.51492e+00, 6.53907e+00, - 6.55609e+00, 6.57184e+00, 6.58829e+00, 6.60611e+00, 6.63126e+00, - 6.71668e+00, 6.74225e+00, 6.75981e+00, 6.77605e+00, 6.79165e+00, - 6.81070e+00, 6.83526e+00, 6.87021e+00, 6.91778e+00, 6.99429e+00, - 7.13987e+00, 7.38015e+00, 7.60035e+00, 7.73994e+00, 7.83965e+00, - 7.97008e+00, 8.13027e+00, 8.30032e+00, 8.52407e+00, 8.67369e+00, - 8.80038e+00, 8.97995e+00, 9.14031e+00, 9.50002e+00, 1.05793e+01, - 1.08038e+01, 1.10529e+01, 1.12694e+01, 1.15894e+01, 1.17094e+01, - 1.18153e+01, 1.19795e+01, 1.21302e+01, 1.23086e+01, 1.24721e+01, - 1.26000e+01, 1.33297e+01, 1.35460e+01, 1.40496e+01, 1.42505e+01, - 1.44702e+01, 1.45952e+01, 1.47301e+01, 1.48662e+01, 1.57792e+01, - 1.60498e+01, 1.65501e+01, 1.68305e+01, 1.74457e+01, 1.75648e+01, - 1.77590e+01, 1.79591e+01, 1.90848e+01, 1.91997e+01, 1.93927e+01, - 1.95974e+01, 2.00734e+01, 2.02751e+01, 2.04175e+01, 2.05199e+01, - 2.06021e+01, 2.06847e+01, 2.07676e+01, 2.09763e+01, 2.10604e+01, - 2.11448e+01, 2.12296e+01, 2.13360e+01, 2.14859e+01, 2.17018e+01, - 2.20011e+01, 2.21557e+01, 2.23788e+01, 2.25356e+01, 2.46578e+01, - 2.78852e+01, 3.16930e+01, 3.30855e+01, 3.45392e+01, 3.56980e+01, - 3.60568e+01, 3.64191e+01, 3.68588e+01, 3.73038e+01, 3.77919e+01, - 3.87874e+01, 3.97295e+01, 4.12270e+01, 4.21441e+01, 4.31246e+01, - 4.41721e+01, 4.52904e+01, 4.62053e+01, 4.75173e+01, 4.92591e+01, - 5.17847e+01, 5.29895e+01, 5.40600e+01, 5.70595e+01, 5.99250e+01, - 6.23083e+01, 6.36306e+01, 6.45923e+01, 6.50460e+01, 6.55029e+01, - 6.58312e+01, 6.61612e+01, 6.64929e+01, 6.68261e+01, 6.90682e+01, - 7.18869e+01, 7.35595e+01, 7.63322e+01, 7.93679e+01, 8.39393e+01, - 8.87741e+01, 9.33256e+01, 9.73287e+01, 1.00594e+02, 1.01098e+02, - 1.01605e+02, 1.02115e+02, 1.03038e+02, 1.05646e+02, 1.10288e+02, - 1.12854e+02, 1.15480e+02, 1.16524e+02, 1.17577e+02, 1.20554e+02, - 1.26229e+02, 1.32701e+02, 1.39504e+02, 1.46657e+02, 1.54176e+02, - 1.63056e+02, 1.67519e+02, 1.75229e+02, 1.83295e+02, 1.84952e+02, - 1.86251e+02, 1.87559e+02, 1.88877e+02, 1.90204e+02, 1.93078e+02, - 1.95996e+02, 2.00958e+02, 2.12108e+02, 2.24325e+02, 2.35590e+02, - 2.41796e+02, 2.56748e+02, 2.68297e+02, 2.76468e+02, 2.84888e+02, - 2.88327e+02, 2.95922e+02, 3.19928e+02, 3.35323e+02, 3.53575e+02, - 3.71703e+02, 3.90760e+02, 4.19094e+02, 4.53999e+02, 5.01746e+02, - 5.39204e+02, 5.77146e+02, 5.92941e+02, 6.00099e+02, 6.12834e+02, - 6.46837e+02, 6.77287e+02, 7.48517e+02, 8.32218e+02, 9.09681e+02, - 9.82494e+02, 1.06432e+03, 1.13467e+03, 1.34358e+03, 1.58620e+03, - 1.81183e+03, 2.08410e+03, 2.39729e+03, 2.70024e+03, 2.99618e+03, - 3.48107e+03, 4.09735e+03, 5.00451e+03, 6.11252e+03, 7.46585e+03, - 9.11881e+03, 1.11377e+04, 1.36037e+04, 1.48997e+04, 1.62005e+04, - 1.85847e+04, 2.26994e+04, 2.49991e+04, 2.61001e+04, 2.73944e+04, - 2.92810e+04, 3.34596e+04, 3.69786e+04, 4.08677e+04, 4.99159e+04, - 5.51656e+04, 6.73794e+04, 8.22974e+04, 9.46645e+04, 1.15624e+05, - 1.22773e+05, 1.40000e+05, 1.64999e+05, 1.95008e+05, 2.30014e+05, - 2.67826e+05, 3.20646e+05, 3.83884e+05, 4.12501e+05, 4.56021e+05, - 4.94002e+05, 5.78443e+05, 7.06511e+05, 8.60006e+05, 9.51119e+05, - 1.05115e+06, 1.16205e+06, 1.28696e+06, 1.33694e+06, 1.40577e+06, - 1.63654e+06, 1.90139e+06, 2.23130e+06, 2.72531e+06, 3.32871e+06, - 4.06569e+06, 4.96585e+06, 6.06530e+06, 6.70319e+06, 7.40817e+06, - 8.18730e+06, 9.04836e+06, 9.99999e+06, 1.16183e+07, 1.38403e+07, - 1.49182e+07, 1.96403e+07]) -GROUP_STRUCTURES['CCFE-709'] = np.array([ - 1.e-5, 1.0471e-5, 1.0965e-5, 1.1482e-5, 1.2023e-5, - 1.2589e-5, 1.3183e-5, 1.3804e-5, 1.4454e-5, 1.5136e-5, - 1.5849e-5, 1.6596e-5, 1.7378e-5, 1.8197e-5, 1.9055e-5, - 1.9953e-5, 2.0893e-5, 2.1878e-5, 2.2909e-5, 2.3988e-5, - 2.5119e-5, 2.6303e-5, 2.7542e-5, 2.8840e-5, 3.0200e-5, - 3.1623e-5, 3.3113e-5, 3.4674e-5, 3.6308e-5, 3.8019e-5, - 3.9811e-5, 4.1687e-5, 4.3652e-5, 4.5709e-5, 4.7863e-5, - 5.0119e-5, 5.2481e-5, 5.4954e-5, 5.7544e-5, 6.0256e-5, - 6.3096e-5, 6.6069e-5, 6.9183e-5, 7.2444e-5, 7.5858e-5, - 7.9433e-5, 8.3176e-5, 8.7096e-5, 9.1201e-5, 9.5499e-5, - 1.0000e-4, 1.0471e-4, 1.0965e-4, 1.1482e-4, 1.2023e-4, - 1.2589e-4, 1.3183e-4, 1.3804e-4, 1.4454e-4, 1.5136e-4, - 1.5849e-4, 1.6596e-4, 1.7378e-4, 1.8197e-4, 1.9055e-4, - 1.9953e-4, 2.0893e-4, 2.1878e-4, 2.2909e-4, 2.3988e-4, - 2.5119e-4, 2.6303e-4, 2.7542e-4, 2.8840e-4, 3.0200e-4, - 3.1623e-4, 3.3113e-4, 3.4674e-4, 3.6308e-4, 3.8019e-4, - 3.9811e-4, 4.1687e-4, 4.3652e-4, 4.5709e-4, 4.7863e-4, - 5.0119e-4, 5.2481e-4, 5.4954e-4, 5.7544e-4, 6.0256e-4, - 6.3096e-4, 6.6069e-4, 6.9183e-4, 7.2444e-4, 7.5858e-4, - 7.9433e-4, 8.3176e-4, 8.7096e-4, 9.1201e-4, 9.5499e-4, - 1.0000e-3, 1.0471e-3, 1.0965e-3, 1.1482e-3, 1.2023e-3, - 1.2589e-3, 1.3183e-3, 1.3804e-3, 1.4454e-3, 1.5136e-3, - 1.5849e-3, 1.6596e-3, 1.7378e-3, 1.8197e-3, 1.9055e-3, - 1.9953e-3, 2.0893e-3, 2.1878e-3, 2.2909e-3, 2.3988e-3, - 2.5119e-3, 2.6303e-3, 2.7542e-3, 2.8840e-3, 3.0200e-3, - 3.1623e-3, 3.3113e-3, 3.4674e-3, 3.6308e-3, 3.8019e-3, - 3.9811e-3, 4.1687e-3, 4.3652e-3, 4.5709e-3, 4.7863e-3, - 5.0119e-3, 5.2481e-3, 5.4954e-3, 5.7544e-3, 6.0256e-3, - 6.3096e-3, 6.6069e-3, 6.9183e-3, 7.2444e-3, 7.5858e-3, - 7.9433e-3, 8.3176e-3, 8.7096e-3, 9.1201e-3, 9.5499e-3, - 1.0000e-2, 1.0471e-2, 1.0965e-2, 1.1482e-2, 1.2023e-2, - 1.2589e-2, 1.3183e-2, 1.3804e-2, 1.4454e-2, 1.5136e-2, - 1.5849e-2, 1.6596e-2, 1.7378e-2, 1.8197e-2, 1.9055e-2, - 1.9953e-2, 2.0893e-2, 2.1878e-2, 2.2909e-2, 2.3988e-2, - 2.5119e-2, 2.6303e-2, 2.7542e-2, 2.8840e-2, 3.0200e-2, - 3.1623e-2, 3.3113e-2, 3.4674e-2, 3.6308e-2, 3.8019e-2, - 3.9811e-2, 4.1687e-2, 4.3652e-2, 4.5709e-2, 4.7863e-2, - 5.0119e-2, 5.2481e-2, 5.4954e-2, 5.7544e-2, 6.0256e-2, - 6.3096e-2, 6.6069e-2, 6.9183e-2, 7.2444e-2, 7.5858e-2, - 7.9433e-2, 8.3176e-2, 8.7096e-2, 9.1201e-2, 9.5499e-2, - 1.0000e-1, 1.0471e-1, 1.0965e-1, 1.1482e-1, 1.2023e-1, - 1.2589e-1, 1.3183e-1, 1.3804e-1, 1.4454e-1, 1.5136e-1, - 1.5849e-1, 1.6596e-1, 1.7378e-1, 1.8197e-1, 1.9055e-1, - 1.9953e-1, 2.0893e-1, 2.1878e-1, 2.2909e-1, 2.3988e-1, - 2.5119e-1, 2.6303e-1, 2.7542e-1, 2.8840e-1, 3.0200e-1, - 3.1623e-1, 3.3113e-1, 3.4674e-1, 3.6308e-1, 3.8019e-1, - 3.9811e-1, 4.1687e-1, 4.3652e-1, 4.5709e-1, 4.7863e-1, - 5.0119e-1, 5.2481e-1, 5.4954e-1, 5.7544e-1, 6.0256e-1, - 6.3096e-1, 6.6069e-1, 6.9183e-1, 7.2444e-1, 7.5858e-1, - 7.9433e-1, 8.3176e-1, 8.7096e-1, 9.1201e-1, 9.5499e-1, - 1.0000e0, 1.0471e0, 1.0965e0, 1.1482e0, 1.2023e0, - 1.2589e0, 1.3183e0, 1.3804e0, 1.4454e0, 1.5136e0, - 1.5849e0, 1.6596e0, 1.7378e0, 1.8197e0, 1.9055e0, - 1.9953e0, 2.0893e0, 2.1878e0, 2.2909e0, 2.3988e0, - 2.5119e0, 2.6303e0, 2.7542e0, 2.8840e0, 3.0200e0, - 3.1623e0, 3.3113e0, 3.4674e0, 3.6308e0, 3.8019e0, - 3.9811e0, 4.1687e0, 4.3652e0, 4.5709e0, 4.7863e0, - 5.0119e0, 5.2481e0, 5.4954e0, 5.7544e0, 6.0256e0, - 6.3096e0, 6.6069e0, 6.9183e0, 7.2444e0, 7.5858e0, - 7.9433e0, 8.3176e0, 8.7096e0, 9.1201e0, 9.5499e0, - 1.0000e1, 1.0471e1, 1.0965e1, 1.1482e1, 1.2023e1, - 1.2589e1, 1.3183e1, 1.3804e1, 1.4454e1, 1.5136e1, - 1.5849e1, 1.6596e1, 1.7378e1, 1.8197e1, 1.9055e1, - 1.9953e1, 2.0893e1, 2.1878e1, 2.2909e1, 2.3988e1, - 2.5119e1, 2.6303e1, 2.7542e1, 2.8840e1, 3.0200e1, - 3.1623e1, 3.3113e1, 3.4674e1, 3.6308e1, 3.8019e1, - 3.9811e1, 4.1687e1, 4.3652e1, 4.5709e1, 4.7863e1, - 5.0119e1, 5.2481e1, 5.4954e1, 5.7544e1, 6.0256e1, - 6.3096e1, 6.6069e1, 6.9183e1, 7.2444e1, 7.5858e1, - 7.9433e1, 8.3176e1, 8.7096e1, 9.1201e1, 9.5499e1, - 1.0000e2, 1.0471e2, 1.0965e2, 1.1482e2, 1.2023e2, - 1.2589e2, 1.3183e2, 1.3804e2, 1.4454e2, 1.5136e2, - 1.5849e2, 1.6596e2, 1.7378e2, 1.8197e2, 1.9055e2, - 1.9953e2, 2.0893e2, 2.1878e2, 2.2909e2, 2.3988e2, - 2.5119e2, 2.6303e2, 2.7542e2, 2.8840e2, 3.0200e2, - 3.1623e2, 3.3113e2, 3.4674e2, 3.6308e2, 3.8019e2, - 3.9811e2, 4.1687e2, 4.3652e2, 4.5709e2, 4.7863e2, - 5.0119e2, 5.2481e2, 5.4954e2, 5.7544e2, 6.0256e2, - 6.3096e2, 6.6069e2, 6.9183e2, 7.2444e2, 7.5858e2, - 7.9433e2, 8.3176e2, 8.7096e2, 9.1201e2, 9.5499e2, - 1.0000e3, 1.0471e3, 1.0965e3, 1.1482e3, 1.2023e3, - 1.2589e3, 1.3183e3, 1.3804e3, 1.4454e3, 1.5136e3, - 1.5849e3, 1.6596e3, 1.7378e3, 1.8197e3, 1.9055e3, - 1.9953e3, 2.0893e3, 2.1878e3, 2.2909e3, 2.3988e3, - 2.5119e3, 2.6303e3, 2.7542e3, 2.8840e3, 3.0200e3, - 3.1623e3, 3.3113e3, 3.4674e3, 3.6308e3, 3.8019e3, - 3.9811e3, 4.1687e3, 4.3652e3, 4.5709e3, 4.7863e3, - 5.0119e3, 5.2481e3, 5.4954e3, 5.7544e3, 6.0256e3, - 6.3096e3, 6.6069e3, 6.9183e3, 7.2444e3, 7.5858e3, - 7.9433e3, 8.3176e3, 8.7096e3, 9.1201e3, 9.5499e3, - 1.0000e4, 1.0471e4, 1.0965e4, 1.1482e4, 1.2023e4, - 1.2589e4, 1.3183e4, 1.3804e4, 1.4454e4, 1.5136e4, - 1.5849e4, 1.6596e4, 1.7378e4, 1.8197e4, 1.9055e4, - 1.9953e4, 2.0893e4, 2.1878e4, 2.2909e4, 2.3988e4, - 2.5119e4, 2.6303e4, 2.7542e4, 2.8840e4, 3.0200e4, - 3.1623e4, 3.3113e4, 3.4674e4, 3.6308e4, 3.8019e4, - 3.9811e4, 4.1687e4, 4.3652e4, 4.5709e4, 4.7863e4, - 5.0119e4, 5.2481e4, 5.4954e4, 5.7544e4, 6.0256e4, - 6.3096e4, 6.6069e4, 6.9183e4, 7.2444e4, 7.5858e4, - 7.9433e4, 8.3176e4, 8.7096e4, 9.1201e4, 9.5499e4, - 1.0000e5, 1.0471e5, 1.0965e5, 1.1482e5, 1.2023e5, - 1.2589e5, 1.3183e5, 1.3804e5, 1.4454e5, 1.5136e5, - 1.5849e5, 1.6596e5, 1.7378e5, 1.8197e5, 1.9055e5, - 1.9953e5, 2.0893e5, 2.1878e5, 2.2909e5, 2.3988e5, - 2.5119e5, 2.6303e5, 2.7542e5, 2.8840e5, 3.0200e5, - 3.1623e5, 3.3113e5, 3.4674e5, 3.6308e5, 3.8019e5, - 3.9811e5, 4.1687e5, 4.3652e5, 4.5709e5, 4.7863e5, - 5.0119e5, 5.2481e5, 5.4954e5, 5.7544e5, 6.0256e5, - 6.3096e5, 6.6069e5, 6.9183e5, 7.2444e5, 7.5858e5, - 7.9433e5, 8.3176e5, 8.7096e5, 9.1201e5, 9.5499e5, - 1.0000e6, 1.0471e6, 1.0965e6, 1.1482e6, 1.2023e6, - 1.2589e6, 1.3183e6, 1.3804e6, 1.4454e6, 1.5136e6, - 1.5849e6, 1.6596e6, 1.7378e6, 1.8197e6, 1.9055e6, - 1.9953e6, 2.0893e6, 2.1878e6, 2.2909e6, 2.3988e6, - 2.5119e6, 2.6303e6, 2.7542e6, 2.8840e6, 3.0200e6, - 3.1623e6, 3.3113e6, 3.4674e6, 3.6308e6, 3.8019e6, - 3.9811e6, 4.1687e6, 4.3652e6, 4.5709e6, 4.7863e6, - 5.0119e6, 5.2481e6, 5.4954e6, 5.7544e6, 6.0256e6, - 6.3096e6, 6.6069e6, 6.9183e6, 7.2444e6, 7.5858e6, - 7.9433e6, 8.3176e6, 8.7096e6, 9.1201e6, 9.5499e6, - 1.0000e7, 1.0200e7, 1.0400e7, 1.0600e7, 1.0800e7, - 1.1000e7, 1.1200e7, 1.1400e7, 1.1600e7, 1.1800e7, - 1.2000e7, 1.2200e7, 1.2400e7, 1.2600e7, 1.2800e7, - 1.3000e7, 1.3200e7, 1.3400e7, 1.3600e7, 1.3800e7, - 1.4000e7, 1.4200e7, 1.4400e7, 1.4600e7, 1.4800e7, - 1.5000e7, 1.5200e7, 1.5400e7, 1.5600e7, 1.5800e7, - 1.6000e7, 1.6200e7, 1.6400e7, 1.6600e7, 1.6800e7, - 1.7000e7, 1.7200e7, 1.7400e7, 1.7600e7, 1.7800e7, - 1.8000e7, 1.8200e7, 1.8400e7, 1.8600e7, 1.8800e7, - 1.9000e7, 1.9200e7, 1.9400e7, 1.9600e7, 1.9800e7, - 2.0000e7, 2.1000e7, 2.2000e7, 2.3000e7, 2.4000e7, - 2.5000e7, 2.6000e7, 2.7000e7, 2.8000e7, 2.9000e7, - 3.0000e7, 3.2000e7, 3.4000e7, 3.6000e7, 3.8000e7, - 4.0000e7, 4.2000e7, 4.4000e7, 4.6000e7, 4.8000e7, - 5.0000e7, 5.2000e7, 5.4000e7, 5.6000e7, 5.8000e7, - 6.0000e7, 6.5000e7, 7.0000e7, 7.5000e7, 8.0000e7, - 9.0000e7, 1.0000e8, 1.1000e8, 1.2000e8, 1.3000e8, - 1.4000e8, 1.5000e8, 1.6000e8, 1.8000e8, 2.0000e8, - 2.4000e8, 2.8000e8, 3.2000e8, 3.6000e8, 4.0000e8, - 4.4000e8, 4.8000e8, 5.2000e8, 5.6000e8, 6.0000e8, - 6.4000e8, 6.8000e8, 7.2000e8, 7.6000e8, 8.0000e8, - 8.4000e8, 8.8000e8, 9.2000e8, 9.6000e8, 1.0000e9,]) -GROUP_STRUCTURES['UKAEA-1102'] = np.array([ - 1.0000e-5, 1.0471e-5, 1.0965e-5, 1.1482e-5, 1.2023e-5, - 1.2589e-5, 1.3183e-5, 1.3804e-5, 1.4454e-5, 1.5136e-5, - 1.5849e-5, 1.6596e-5, 1.7378e-5, 1.8197e-5, 1.9055e-5, - 1.9953e-5, 2.0893e-5, 2.1878e-5, 2.2909e-5, 2.3988e-5, - 2.5119e-5, 2.6303e-5, 2.7542e-5, 2.8840e-5, 3.0200e-5, - 3.1623e-5, 3.3113e-5, 3.4674e-5, 3.6308e-5, 3.8019e-5, - 3.9811e-5, 4.1687e-5, 4.3652e-5, 4.5709e-5, 4.7863e-5, - 5.0119e-5, 5.2481e-5, 5.4954e-5, 5.7544e-5, 6.0256e-5, - 6.3096e-5, 6.6069e-5, 6.9183e-5, 7.2444e-5, 7.5858e-5, - 7.9433e-5, 8.3176e-5, 8.7096e-5, 9.1201e-5, 9.5499e-5, - 1.0000e-4, 1.0471e-4, 1.0965e-4, 1.1482e-4, 1.2023e-4, - 1.2589e-4, 1.3183e-4, 1.3804e-4, 1.4454e-4, 1.5136e-4, - 1.5849e-4, 1.6596e-4, 1.7378e-4, 1.8197e-4, 1.9055e-4, - 1.9953e-4, 2.0893e-4, 2.1878e-4, 2.2909e-4, 2.3988e-4, - 2.5119e-4, 2.6303e-4, 2.7542e-4, 2.8840e-4, 3.0200e-4, - 3.1623e-4, 3.3113e-4, 3.4674e-4, 3.6308e-4, 3.8019e-4, - 3.9811e-4, 4.1687e-4, 4.3652e-4, 4.5709e-4, 4.7863e-4, - 5.0119e-4, 5.2481e-4, 5.4954e-4, 5.7544e-4, 6.0256e-4, - 6.3096e-4, 6.6069e-4, 6.9183e-4, 7.2444e-4, 7.5858e-4, - 7.9433e-4, 8.3176e-4, 8.7096e-4, 9.1201e-4, 9.5499e-4, - 1.0000e-3, 1.0471e-3, 1.0965e-3, 1.1482e-3, 1.2023e-3, - 1.2589e-3, 1.3183e-3, 1.3804e-3, 1.4454e-3, 1.5136e-3, - 1.5849e-3, 1.6596e-3, 1.7378e-3, 1.8197e-3, 1.9055e-3, - 1.9953e-3, 2.0893e-3, 2.1878e-3, 2.2909e-3, 2.3988e-3, - 2.5119e-3, 2.6303e-3, 2.7542e-3, 2.8840e-3, 3.0200e-3, - 3.1623e-3, 3.3113e-3, 3.4674e-3, 3.6308e-3, 3.8019e-3, - 3.9811e-3, 4.1687e-3, 4.3652e-3, 4.5709e-3, 4.7863e-3, - 5.0119e-3, 5.2481e-3, 5.4954e-3, 5.7544e-3, 6.0256e-3, - 6.3096e-3, 6.6069e-3, 6.9183e-3, 7.2444e-3, 7.5858e-3, - 7.9433e-3, 8.3176e-3, 8.7096e-3, 9.1201e-3, 9.5499e-3, - 1.0000e-2, 1.0471e-2, 1.0965e-2, 1.1482e-2, 1.2023e-2, - 1.2589e-2, 1.3183e-2, 1.3804e-2, 1.4454e-2, 1.5136e-2, - 1.5849e-2, 1.6596e-2, 1.7378e-2, 1.8197e-2, 1.9055e-2, - 1.9953e-2, 2.0893e-2, 2.1878e-2, 2.2909e-2, 2.3988e-2, - 2.5119e-2, 2.6303e-2, 2.7542e-2, 2.8840e-2, 3.0200e-2, - 3.1623e-2, 3.3113e-2, 3.4674e-2, 3.6308e-2, 3.8019e-2, - 3.9811e-2, 4.1687e-2, 4.3652e-2, 4.5709e-2, 4.7863e-2, - 5.0119e-2, 5.2481e-2, 5.4954e-2, 5.7544e-2, 6.0256e-2, - 6.3096e-2, 6.6069e-2, 6.9183e-2, 7.2444e-2, 7.5858e-2, - 7.9433e-2, 8.3176e-2, 8.7096e-2, 9.1201e-2, 9.5499e-2, - 1.0000e-1, 1.0471e-1, 1.0965e-1, 1.1482e-1, 1.2023e-1, - 1.2589e-1, 1.3183e-1, 1.3804e-1, 1.4454e-1, 1.5136e-1, - 1.5849e-1, 1.6596e-1, 1.7378e-1, 1.8197e-1, 1.9055e-1, - 1.9953e-1, 2.0893e-1, 2.1878e-1, 2.2909e-1, 2.3988e-1, - 2.5119e-1, 2.6303e-1, 2.7542e-1, 2.8840e-1, 3.0200e-1, - 3.1623e-1, 3.3113e-1, 3.4674e-1, 3.6308e-1, 3.8019e-1, - 3.9811e-1, 4.1687e-1, 4.3652e-1, 4.5709e-1, 4.7863e-1, - 5.0119e-1, 5.2481e-1, 5.5000e-1, 5.7500e-1, 6.0000e-1, - 6.2500e-1, 6.5000e-1, 6.7500e-1, 7.0000e-1, 7.2500e-1, - 7.5000e-1, 7.7500e-1, 8.0000e-1, 8.2500e-1, 8.5000e-1, - 8.7500e-1, 9.0000e-1, 9.2500e-1, 9.5000e-1, 9.7500e-1, - 1.0000, 1.0250, 1.0500, 1.0750, 1.1000, - 1.1250, 1.1500, 1.1750, 1.2000, 1.2250, - 1.2500, 1.2750, 1.3000, 1.3250, 1.3500, - 1.3750, 1.4000, 1.4250, 1.4500, 1.4750, - 1.5000, 1.5250, 1.5500, 1.5750, 1.6000, - 1.6250, 1.6500, 1.6750, 1.7000, 1.7250, - 1.7500, 1.7750, 1.8000, 1.8250, 1.8500, - 1.8750, 1.9000, 1.9250, 1.9500, 1.9750, - 2.0000, 2.0250, 2.0500, 2.0750, 2.1000, - 2.1250, 2.1500, 2.1750, 2.2000, 2.2250, - 2.2500, 2.2750, 2.3000, 2.3250, 2.3500, - 2.3750, 2.4000, 2.4250, 2.4500, 2.4750, - 2.5000, 2.5250, 2.5500, 2.5750, 2.6000, - 2.6250, 2.6500, 2.6750, 2.7000, 2.7250, - 2.7500, 2.7750, 2.8000, 2.8250, 2.8500, - 2.8750, 2.9000, 2.9250, 2.9500, 2.9750, - 3.0000, 3.0250, 3.0500, 3.0750, 3.1000, - 3.1250, 3.1500, 3.1750, 3.2000, 3.2250, - 3.2500, 3.2750, 3.3000, 3.3250, 3.3500, - 3.3750, 3.4000, 3.4250, 3.4500, 3.4750, - 3.5000, 3.5250, 3.5500, 3.5750, 3.6000, - 3.6250, 3.6500, 3.6750, 3.7000, 3.7250, - 3.7500, 3.7750, 3.8000, 3.8250, 3.8500, - 3.8750, 3.9000, 3.9250, 3.9500, 3.9750, - 4.0000, 4.0250, 4.0500, 4.0750, 4.1000, - 4.1250, 4.1500, 4.1750, 4.2000, 4.2250, - 4.2500, 4.2750, 4.3000, 4.3250, 4.3500, - 4.3750, 4.4000, 4.4250, 4.4500, 4.4750, - 4.5000, 4.5250, 4.5500, 4.5750, 4.6000, - 4.6250, 4.6500, 4.6750, 4.7000, 4.7250, - 4.7500, 4.7750, 4.8000, 4.8250, 4.8500, - 4.8750, 4.9000, 4.9250, 4.9500, 4.9750, - 5.0000, 5.0250, 5.0500, 5.0750, 5.1000, - 5.1250, 5.1500, 5.1750, 5.2000, 5.2250, - 5.2500, 5.2750, 5.3000, 5.3250, 5.3500, - 5.3750, 5.4000, 5.4250, 5.4500, 5.4750, - 5.5000, 5.5250, 5.5500, 5.5750, 5.6000, - 5.6250, 5.6500, 5.6750, 5.7000, 5.7250, - 5.7500, 5.7750, 5.8000, 5.8250, 5.8500, - 5.8750, 5.9000, 5.9250, 5.9500, 5.9750, - 6.0000, 6.0250, 6.0500, 6.0750, 6.1000, - 6.1250, 6.1500, 6.1750, 6.2000, 6.2250, - 6.2500, 6.2750, 6.3000, 6.3250, 6.3500, - 6.3750, 6.4000, 6.4250, 6.4500, 6.4750, - 6.5000, 6.5250, 6.5500, 6.5750, 6.6000, - 6.6250, 6.6500, 6.6750, 6.7000, 6.7250, - 6.7500, 6.7750, 6.8000, 6.8250, 6.8500, - 6.8750, 6.9000, 6.9250, 6.9500, 6.9750, - 7.0000, 7.0250, 7.0500, 7.0750, 7.1000, - 7.1250, 7.1500, 7.1750, 7.2000, 7.2250, - 7.2500, 7.2750, 7.3000, 7.3250, 7.3500, - 7.3750, 7.4000, 7.4250, 7.4500, 7.4750, - 7.5000, 7.5250, 7.5500, 7.5750, 7.6000, - 7.6250, 7.6500, 7.6750, 7.7000, 7.7250, - 7.7500, 7.7750, 7.8000, 7.8250, 7.8500, - 7.8750, 7.9000, 7.9250, 7.9500, 7.9750, - 8.0000, 8.0250, 8.0500, 8.0750, 8.1000, - 8.1250, 8.1500, 8.1750, 8.2000, 8.2250, - 8.2500, 8.2750, 8.3000, 8.3250, 8.3500, - 8.3750, 8.4000, 8.4250, 8.4500, 8.4750, - 8.5000, 8.5250, 8.5500, 8.5750, 8.6000, - 8.6250, 8.6500, 8.6750, 8.7000, 8.7250, - 8.7500, 8.7750, 8.8000, 8.8250, 8.8500, - 8.8750, 8.9000, 8.9250, 8.9500, 8.9750, - 9.0000, 9.0250, 9.0500, 9.0750, 9.1000, - 9.1250, 9.1500, 9.1750, 9.2000, 9.2250, - 9.2500, 9.2750, 9.3000, 9.3250, 9.3500, - 9.3750, 9.4000, 9.4250, 9.4500, 9.4750, - 9.5000, 9.5250, 9.5500, 9.5750, 9.6000, - 9.6250, 9.6500, 9.6750, 9.7000, 9.7250, - 9.7500, 9.7750, 9.8000, 9.8250, 9.8500, - 9.8750, 9.9000, 9.9250, 9.9500, 9.9750, - 1.0000e1, 1.0471e1, 1.0965e1, 1.1482e1, 1.2023e1, - 1.2589e1, 1.3183e1, 1.3804e1, 1.4454e1, 1.5136e1, - 1.5849e1, 1.6596e1, 1.7378e1, 1.8197e1, 1.9055e1, - 1.9953e1, 2.0893e1, 2.1878e1, 2.2909e1, 2.3988e1, - 2.5119e1, 2.6303e1, 2.7542e1, 2.8840e1, 3.0200e1, - 3.1623e1, 3.3113e1, 3.4674e1, 3.6308e1, 3.8019e1, - 3.9811e1, 4.1687e1, 4.3652e1, 4.5709e1, 4.7863e1, - 5.0119e1, 5.2481e1, 5.4954e1, 5.7544e1, 6.0256e1, - 6.3096e1, 6.6069e1, 6.9183e1, 7.2444e1, 7.5858e1, - 7.9433e1, 8.3176e1, 8.7096e1, 9.1201e1, 9.5499e1, - 1.0000e2, 1.0471e2, 1.0965e2, 1.1482e2, 1.2023e2, - 1.2589e2, 1.3183e2, 1.3804e2, 1.4454e2, 1.5136e2, - 1.5849e2, 1.6596e2, 1.7378e2, 1.8197e2, 1.9055e2, - 1.9953e2, 2.0893e2, 2.1878e2, 2.2909e2, 2.3988e2, - 2.5119e2, 2.6303e2, 2.7542e2, 2.8840e2, 3.0200e2, - 3.1623e2, 3.3113e2, 3.4674e2, 3.6308e2, 3.8019e2, - 3.9811e2, 4.1687e2, 4.3652e2, 4.5709e2, 4.7863e2, - 5.0119e2, 5.2481e2, 5.4954e2, 5.7544e2, 6.0256e2, - 6.3096e2, 6.6069e2, 6.9183e2, 7.2444e2, 7.5858e2, - 7.9433e2, 8.3176e2, 8.7096e2, 9.1201e2, 9.5499e2, - 1.0000e3, 1.0471e3, 1.0965e3, 1.1482e3, 1.2023e3, - 1.2589e3, 1.3183e3, 1.3804e3, 1.4454e3, 1.5136e3, - 1.5849e3, 1.6596e3, 1.7378e3, 1.8197e3, 1.9055e3, - 1.9953e3, 2.0893e3, 2.1878e3, 2.2909e3, 2.3988e3, - 2.5119e3, 2.6303e3, 2.7542e3, 2.8840e3, 3.0200e3, - 3.1623e3, 3.3113e3, 3.4674e3, 3.6308e3, 3.8019e3, - 3.9811e3, 4.1687e3, 4.3652e3, 4.5709e3, 4.7863e3, - 5.0119e3, 5.2481e3, 5.4954e3, 5.7544e3, 6.0256e3, - 6.3096e3, 6.6069e3, 6.9183e3, 7.2444e3, 7.5858e3, - 7.9433e3, 8.3176e3, 8.7096e3, 9.1201e3, 9.5499e3, - 1.0000e4, 1.0471e4, 1.0965e4, 1.1482e4, 1.2023e4, - 1.2589e4, 1.3183e4, 1.3804e4, 1.4454e4, 1.5136e4, - 1.5849e4, 1.6596e4, 1.7378e4, 1.8197e4, 1.9055e4, - 1.9953e4, 2.0893e4, 2.1878e4, 2.2909e4, 2.3988e4, - 2.5119e4, 2.6303e4, 2.7542e4, 2.8840e4, 3.0200e4, - 3.1623e4, 3.3113e4, 3.4674e4, 3.6308e4, 3.8019e4, - 3.9811e4, 4.1687e4, 4.3652e4, 4.5709e4, 4.7863e4, - 5.0119e4, 5.2481e4, 5.4954e4, 5.7544e4, 6.0256e4, - 6.3096e4, 6.6069e4, 6.9183e4, 7.2444e4, 7.5858e4, - 7.9433e4, 8.3176e4, 8.7096e4, 9.1201e4, 9.5499e4, - 1.0000e5, 1.0471e5, 1.0965e5, 1.1482e5, 1.2023e5, - 1.2589e5, 1.3183e5, 1.3804e5, 1.4454e5, 1.5136e5, - 1.5849e5, 1.6596e5, 1.7378e5, 1.8197e5, 1.9055e5, - 1.9953e5, 2.0893e5, 2.1878e5, 2.2909e5, 2.3988e5, - 2.5119e5, 2.6303e5, 2.7542e5, 2.8840e5, 3.0200e5, - 3.1623e5, 3.3113e5, 3.4674e5, 3.6308e5, 3.8019e5, - 3.9811e5, 4.1687e5, 4.3652e5, 4.5709e5, 4.7863e5, - 5.0119e5, 5.2481e5, 5.4954e5, 5.7544e5, 6.0256e5, - 6.3096e5, 6.6069e5, 6.9183e5, 7.2444e5, 7.5858e5, - 7.9433e5, 8.3176e5, 8.7096e5, 9.1201e5, 9.5499e5, - 1.0000e6, 1.0471e6, 1.0965e6, 1.1482e6, 1.2023e6, - 1.2589e6, 1.3183e6, 1.3804e6, 1.4454e6, 1.5136e6, - 1.5849e6, 1.6596e6, 1.7378e6, 1.8197e6, 1.9055e6, - 1.9953e6, 2.0893e6, 2.1878e6, 2.2909e6, 2.3988e6, - 2.5119e6, 2.6303e6, 2.7542e6, 2.8840e6, 3.0200e6, - 3.1623e6, 3.3113e6, 3.4674e6, 3.6308e6, 3.8019e6, - 3.9811e6, 4.1687e6, 4.3652e6, 4.5709e6, 4.7863e6, - 5.0000e6, 5.2000e6, 5.4000e6, 5.6000e6, 5.8000e6, - 6.0000e6, 6.2000e6, 6.4000e6, 6.6000e6, 6.8000e6, - 7.0000e6, 7.2000e6, 7.4000e6, 7.6000e6, 7.8000e6, - 8.0000e6, 8.2000e6, 8.4000e6, 8.6000e6, 8.8000e6, - 9.0000e6, 9.2000e6, 9.4000e6, 9.6000e6, 9.8000e6, - 1.0000e7, 1.0200e7, 1.0400e7, 1.0600e7, 1.0800e7, - 1.1000e7, 1.1200e7, 1.1400e7, 1.1600e7, 1.1800e7, - 1.2000e7, 1.2200e7, 1.2400e7, 1.2600e7, 1.2800e7, - 1.3000e7, 1.3200e7, 1.3400e7, 1.3600e7, 1.3800e7, - 1.4000e7, 1.4200e7, 1.4400e7, 1.4600e7, 1.4800e7, - 1.5000e7, 1.5200e7, 1.5400e7, 1.5600e7, 1.5800e7, - 1.6000e7, 1.6200e7, 1.6400e7, 1.6600e7, 1.6800e7, - 1.7000e7, 1.7200e7, 1.7400e7, 1.7600e7, 1.7800e7, - 1.8000e7, 1.8200e7, 1.8400e7, 1.8600e7, 1.8800e7, - 1.9000e7, 1.9200e7, 1.9400e7, 1.9600e7, 1.9800e7, - 2.0000e7, 2.0200e7, 2.0400e7, 2.0600e7, 2.0800e7, - 2.1000e7, 2.1200e7, 2.1400e7, 2.1600e7, 2.1800e7, - 2.2000e7, 2.2200e7, 2.2400e7, 2.2600e7, 2.2800e7, - 2.3000e7, 2.3200e7, 2.3400e7, 2.3600e7, 2.3800e7, - 2.4000e7, 2.4200e7, 2.4400e7, 2.4600e7, 2.4800e7, - 2.5000e7, 2.5200e7, 2.5400e7, 2.5600e7, 2.5800e7, - 2.6000e7, 2.6200e7, 2.6400e7, 2.6600e7, 2.6800e7, - 2.7000e7, 2.7200e7, 2.7400e7, 2.7600e7, 2.7800e7, - 2.8000e7, 2.8200e7, 2.8400e7, 2.8600e7, 2.8800e7, - 2.9000e7, 2.9200e7, 2.9400e7, 2.9600e7, 2.9800e7, - 3.0000e7, 3.0200e7, 3.1623e7, 3.3113e7, 3.4674e7, - 3.6308e7, 3.8019e7, 3.9811e7, 4.1687e7, 4.3652e7, - 4.5709e7, 4.7863e7, 5.0119e7, 5.2481e7, 5.4954e7, - 5.7544e7, 6.0256e7, 6.3096e7, 6.6069e7, 6.9183e7, - 7.2444e7, 7.5858e7, 7.9433e7, 8.3176e7, 8.7096e7, - 9.1201e7, 9.5499e7, 1.0000e8, 1.0471e8, 1.0965e8, - 1.1482e8, 1.2023e8, 1.2589e8, 1.3183e8, 1.3804e8, - 1.4454e8, 1.5136e8, 1.5849e8, 1.6596e8, 1.7378e8, - 1.8197e8, 1.9055e8, 1.9953e8, 2.0893e8, 2.1878e8, - 2.2909e8, 2.3988e8, 2.5119e8, 2.6303e8, 2.7542e8, - 2.8840e8, 3.0200e8, 3.1623e8, 3.3113e8, 3.4674e8, - 3.6308e8, 3.8019e8, 3.9811e8, 4.1687e8, 4.3652e8, - 4.5709e8, 4.7863e8, 5.0119e8, 5.2481e8, 5.4954e8, - 5.7544e8, 6.0256e8, 6.3096e8, 6.6069e8, 6.9183e8, - 7.2444e8, 7.5858e8, 7.9433e8, 8.3176e8, 8.7096e8, - 9.1201e8, 9.5499e8, 1.e9]) diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py deleted file mode 100644 index 338bc4b00..000000000 --- a/openmc/mgxs/groups.py +++ /dev/null @@ -1,297 +0,0 @@ -from collections.abc import Iterable -from numbers import Real -import copy -import sys - -import numpy as np - -import openmc.checkvalue as cv - - -class EnergyGroups(object): - """An energy groups structure used for multi-group cross-sections. - - Parameters - ---------- - group_edges : Iterable of Real - The energy group boundaries [eV] - - Attributes - ---------- - group_edges : Iterable of Real - The energy group boundaries [eV] - num_groups : int - The number of energy groups - - """ - - def __init__(self, group_edges=None): - self._group_edges = None - - if group_edges is not None: - self.group_edges = group_edges - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy object, create copy - if existing is None: - clone = type(self).__new__(type(self)) - clone._group_edges = copy.deepcopy(self.group_edges, memo) - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - def __eq__(self, other): - if not isinstance(other, EnergyGroups): - return False - elif self.num_groups != other.num_groups: - return False - elif np.allclose(self.group_edges, other.group_edges): - return True - else: - return False - - def __ne__(self, other): - return not self == other - - def __hash__(self): - return hash(tuple(self.group_edges)) - - @property - def group_edges(self): - return self._group_edges - - @property - def num_groups(self): - return len(self.group_edges) - 1 - - @group_edges.setter - def group_edges(self, edges): - cv.check_type('group edges', edges, Iterable, Real) - cv.check_greater_than('number of group edges', len(edges), 1) - self._group_edges = np.array(edges) - - def get_group(self, energy): - """Returns the energy group in which the given energy resides. - - Parameters - ---------- - energy : float - The energy of interest in eV - - Returns - ------- - Integral - The energy group index, starting at 1 for the highest energies - - Raises - ------ - ValueError - If the group edges have not yet been set. - - """ - - if self.group_edges is None: - msg = 'Unable to get energy group for energy "{0}" eV since ' \ - 'the group edges have not yet been set'.format(energy) - raise ValueError(msg) - - index = np.where(self.group_edges > energy)[0][0] - group = self.num_groups - index + 1 - return group - - def get_group_bounds(self, group): - """Returns the energy boundaries for the energy group of interest. - - Parameters - ---------- - group : int - The energy group index, starting at 1 for the highest energies - - Returns - ------- - 2-tuple - The low and high energy bounds for the group in eV - - Raises - ------ - ValueError - If the group edges have not yet been set. - - """ - - if self.group_edges is None: - msg = 'Unable to get energy group bounds for group "{0}" since ' \ - 'the group edges have not yet been set'.format(group) - raise ValueError(msg) - - cv.check_greater_than('group', group, 0) - cv.check_less_than('group', group, self.num_groups, equality=True) - - lower = self.group_edges[self.num_groups-group] - upper = self.group_edges[self.num_groups-group+1] - return lower, upper - - def get_group_indices(self, groups='all'): - """Returns the array indices for one or more energy groups. - - Parameters - ---------- - groups : str, tuple - The energy groups of interest - a tuple of the energy group indices, - starting at 1 for the highest energies (default is 'all') - - Returns - ------- - numpy.ndarray - The ndarray array indices for each energy group of interest - - Raises - ------ - ValueError - If the group edges have not yet been set, or if a group is requested - that is outside the bounds of the number of energy groups. - - """ - - if self.group_edges is None: - msg = 'Unable to get energy group indices for groups "{0}" since ' \ - 'the group edges have not yet been set'.format(groups) - raise ValueError(msg) - - if groups == 'all': - return np.arange(self.num_groups) - else: - indices = np.zeros(len(groups), dtype=np.int) - - for i, group in enumerate(groups): - cv.check_greater_than('group', group, 0) - cv.check_less_than('group', group, self.num_groups, equality=True) - indices[i] = group - 1 - - return indices - - def get_condensed_groups(self, coarse_groups): - """Return a coarsened version of this EnergyGroups object. - - This method merges together energy groups in this object into wider - energy groups as defined by the list of groups specified by the user, - and returns a new, coarse EnergyGroups object. - - Parameters - ---------- - coarse_groups : Iterable of 2-tuple - The energy groups of interest - a list of 2-tuples, each directly - corresponding to one of the new coarse groups. The values in the - 2-tuples are upper/lower energy groups used to construct a new - coarse group. For example, if [(1,2), (3,4)] was used as the coarse - groups, fine groups 1 and 2 would be merged into coarse group 1 - while fine groups 3 and 4 would be merged into coarse group 2. - - Returns - ------- - openmc.mgxs.EnergyGroups - A coarsened version of this EnergyGroups object. - - Raises - ------ - ValueError - If the group edges have not yet been set. - """ - - cv.check_type('group edges', coarse_groups, Iterable) - for group in coarse_groups: - cv.check_type('group edges', group, Iterable) - cv.check_length('group edges', group, 2) - cv.check_greater_than('lower group', group[0], 1, True) - cv.check_less_than('lower group', group[0], self.num_groups, True) - cv.check_greater_than('upper group', group[0], 1, True) - cv.check_less_than('upper group', group[0], self.num_groups, True) - cv.check_less_than('lower group', group[0], group[1], False) - - # Compute the group indices into the coarse group - group_bounds = [group[1] for group in coarse_groups] - group_bounds.insert(0, coarse_groups[0][0]) - - # Determine the indices mapping the fine-to-coarse energy groups - group_bounds = np.asarray(group_bounds) - group_indices = np.flipud(self.num_groups - group_bounds) - group_indices[-1] += 1 - - # Determine the edges between coarse energy groups and sort - # in increasing order in case the user passed in unordered groups - group_edges = self.group_edges[group_indices] - group_edges = np.sort(group_edges) - - # Create a new condensed EnergyGroups object - condensed_groups = EnergyGroups() - condensed_groups.group_edges = group_edges - - return condensed_groups - - def can_merge(self, other): - """Determine if energy groups can be merged with another. - - Parameters - ---------- - other : openmc.mgxs.EnergyGroups - EnergyGroups to compare with - - Returns - ------- - bool - Whether the energy groups can be merged - - """ - - if not isinstance(other, EnergyGroups): - return False - - # If the energy group structures match then groups are mergeable - if self == other: - return True - - # This low energy edge coincides with other's high energy edge - if self.group_edges[0] == other.group_edges[-1]: - return True - # This high energy edge coincides with other's low energy edge - elif self.group_edges[-1] == other.group_edges[0]: - return True - else: - return False - - def merge(self, other): - """Merge this energy groups with another. - - Parameters - ---------- - other : openmc.mgxs.EnergyGroups - EnergyGroups to merge with - - Returns - ------- - merged_groups : openmc.mgxs.EnergyGroups - EnergyGroups resulting from the merge - - """ - - if not self.can_merge(other): - raise ValueError('Unable to merge energy groups') - - # Create deep copy to return as merged energy groups - merged_groups = copy.deepcopy(self) - - # Merge unique filter bins - merged_edges = np.concatenate((self.group_edges, other.group_edges)) - merged_edges = np.unique(merged_edges) - merged_edges = sorted(merged_edges) - - # Assign merged edges to merged groups - merged_groups.group_edges = list(merged_edges) - return merged_groups diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py deleted file mode 100644 index fbf08f85f..000000000 --- a/openmc/mgxs/library.py +++ /dev/null @@ -1,1469 +0,0 @@ -import sys -import os -import copy -import pickle -from numbers import Integral -from collections import OrderedDict -from collections.abc import Iterable -from warnings import warn - -import numpy as np - -import openmc -import openmc.mgxs -import openmc.checkvalue as cv -from openmc.tallies import ESTIMATOR_TYPES - - -class Library(object): - """A multi-energy-group and multi-delayed-group cross section library for - some energy group structure. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for deterministic neutronics calculations. - - This class helps automate the generation of MGXS and MDGXS objects for some - energy group structure and domain type. The Library serves as a collection - for MGXS and MDGXS objects with routines to automate the initialization of - tallies for input files, the loading of tally data from statepoint files, - data storage, energy group condensation and more. - - Parameters - ---------- - geometry : openmc.Geometry - A geometry which has been initialized with a root universe - by_nuclide : bool - If true, computes cross sections for each nuclide in each domain - mgxs_types : Iterable of str - The types of cross sections in the library (e.g., ['total', 'scatter']) - name : str, optional - Name of the multi-group cross section library. Used as a label to - identify tallies in OpenMC 'tallies.xml' file. - - Attributes - ---------- - geometry : openmc.Geometry - An geometry which has been initialized with a root universe - by_nuclide : bool - If true, computes cross sections for each nuclide in each domain - mgxs_types : Iterable of str - The types of cross sections in the library (e.g., ['total', 'scatter']) - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - domains : Iterable of openmc.Material, openmc.Cell, openmc.Universe or openmc.RegularMesh - The spatial domain(s) for which MGXS in the Library are computed - correction : {'P0', None} - Apply the P0 correction to scattering matrices if set to 'P0' - scatter_format : {'legendre', 'histogram'} - Representation of the angular scattering distribution (default is - 'legendre') - legendre_order : int - The highest Legendre moment in the scattering matrix; this is used if - :attr:`ScatterMatrixXS.scatter_format` is 'legendre'. (default is 0) - histogram_bins : int - The number of equally-spaced bins for the histogram representation of - the angular scattering distribution; this is used if - :attr:`ScatterMatrixXS.scatter_format` is 'histogram'. (default is 16) - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_delayed_groups : int - Number of delayed groups - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - estimator : str or None - The tally estimator used to compute multi-group cross sections. - If None, the default for each MGXS type is used. - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - all_mgxs : collections.OrderedDict - MGXS objects keyed by domain ID and cross section type - sp_filename : str - The filename of the statepoint with tally data used to the - compute cross sections - keff : Real or None - The combined keff from the statepoint file with tally data used to - compute cross sections (for eigenvalue calculations only) - name : str, optional - Name of the multi-group cross section library. Used as a label to - identify tallies in OpenMC 'tallies.xml' file. - sparse : bool - Whether or not the Library's tallies use SciPy's LIL sparse matrix - format for compressed data storage - - """ - - def __init__(self, geometry, by_nuclide=False, - mgxs_types=None, name=''): - - self._name = '' - self._geometry = None - self._by_nuclide = None - self._mgxs_types = [] - self._domain_type = None - self._domains = 'all' - self._energy_groups = None - self._num_polar = 1 - self._num_azimuthal = 1 - self._num_delayed_groups = 0 - self._correction = 'P0' - self._scatter_format = 'legendre' - self._legendre_order = 0 - self._histogram_bins = 16 - self._tally_trigger = None - self._all_mgxs = OrderedDict() - self._sp_filename = None - self._keff = None - self._sparse = False - self._estimator = None - - self.name = name - self.geometry = geometry - self.by_nuclide = by_nuclide - - if mgxs_types is not None: - self.mgxs_types = mgxs_types - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, copy it - if existing is None: - clone = type(self).__new__(type(self)) - clone._name = self.name - clone._geometry = self.geometry - clone._by_nuclide = self.by_nuclide - clone._mgxs_types = self.mgxs_types - clone._domain_type = self.domain_type - clone._domains = copy.deepcopy(self.domains) - clone._correction = self.correction - clone._scatter_format = self.scatter_format - clone._legendre_order = self.legendre_order - clone._histogram_bins = self.histogram_bins - clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._num_polar = self.num_polar - clone._num_azimuthal = self.num_azimuthal - clone._num_delayed_groups = self.num_delayed_groups - clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) - clone._all_mgxs = copy.deepcopy(self.all_mgxs) - clone._sp_filename = self._sp_filename - clone._keff = self._keff - clone._sparse = self.sparse - - clone._all_mgxs = OrderedDict() - for domain in self.domains: - clone.all_mgxs[domain.id] = OrderedDict() - for mgxs_type in self.mgxs_types: - mgxs = copy.deepcopy(self.all_mgxs[domain.id][mgxs_type]) - clone.all_mgxs[domain.id][mgxs_type] = mgxs - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - @property - def geometry(self): - return self._geometry - - @property - def name(self): - return self._name - - @property - def mgxs_types(self): - return self._mgxs_types - - @property - def by_nuclide(self): - return self._by_nuclide - - @property - def domain_type(self): - return self._domain_type - - @property - def domains(self): - if self._domains == 'all': - if self.domain_type == 'material': - return list(self.geometry.get_all_materials().values()) - elif self.domain_type in ['cell', 'distribcell']: - return list(self.geometry.get_all_material_cells().values()) - elif self.domain_type == 'universe': - return list(self.geometry.get_all_universes().values()) - elif self.domain_type == 'mesh': - raise ValueError('Unable to get domains for Mesh domain type') - else: - raise ValueError('Unable to get domains without a domain type') - else: - return self._domains - - @property - def energy_groups(self): - return self._energy_groups - - @property - def num_delayed_groups(self): - return self._num_delayed_groups - - @property - def num_polar(self): - return self._num_polar - - @property - def num_azimuthal(self): - return self._num_azimuthal - - @property - def correction(self): - return self._correction - - @property - def scatter_format(self): - return self._scatter_format - - @property - def legendre_order(self): - return self._legendre_order - - @property - def histogram_bins(self): - return self._histogram_bins - - @property - def tally_trigger(self): - return self._tally_trigger - - @property - def estimator(self): - return self._estimator - - @property - def num_groups(self): - return self.energy_groups.num_groups - - @property - def all_mgxs(self): - return self._all_mgxs - - @property - def sp_filename(self): - return self._sp_filename - - @property - def keff(self): - return self._keff - - @property - def sparse(self): - return self._sparse - - @geometry.setter - def geometry(self, geometry): - cv.check_type('geometry', geometry, openmc.Geometry) - self._geometry = geometry - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @mgxs_types.setter - def mgxs_types(self, mgxs_types): - all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES - if mgxs_types == 'all': - self._mgxs_types = all_mgxs_types - else: - cv.check_iterable_type('mgxs_types', mgxs_types, str) - for mgxs_type in mgxs_types: - cv.check_value('mgxs_type', mgxs_type, all_mgxs_types) - self._mgxs_types = mgxs_types - - @by_nuclide.setter - def by_nuclide(self, by_nuclide): - cv.check_type('by_nuclide', by_nuclide, bool) - - if by_nuclide and self.domain_type == 'mesh': - raise ValueError('Unable to create MGXS library by nuclide with ' - 'mesh domain') - - self._by_nuclide = by_nuclide - - @domain_type.setter - def domain_type(self, domain_type): - cv.check_value('domain type', domain_type, openmc.mgxs.DOMAIN_TYPES) - - if self.by_nuclide and domain_type == 'mesh': - raise ValueError('Unable to create MGXS library by nuclide with ' - 'mesh domain') - - self._domain_type = domain_type - - @domains.setter - def domains(self, domains): - - # Use all materials, cells or universes in the geometry as domains - if domains == 'all': - self._domains = domains - - # User specified a list of material, cell or universe domains - else: - if self.domain_type == 'material': - cv.check_type('domain', domains, Iterable, openmc.Material) - all_domains = self.geometry.get_all_materials().values() - elif self.domain_type in ['cell', 'distribcell']: - cv.check_type('domain', domains, Iterable, openmc.Cell) - all_domains = self.geometry.get_all_material_cells().values() - elif self.domain_type == 'universe': - cv.check_type('domain', domains, Iterable, openmc.Universe) - all_domains = self.geometry.get_all_universes().values() - elif self.domain_type == 'mesh': - cv.check_type('domain', domains, Iterable, openmc.RegularMesh) - - # The mesh and geometry are independent, so set all_domains - # to the input domains - all_domains = domains - else: - raise ValueError('Unable to set domains with domain ' - 'type "{}"'.format(self.domain_type)) - - # Check that each domain can be found in the geometry - for domain in domains: - if domain not in all_domains: - raise ValueError('Domain "{}" could not be found in the ' - 'geometry.'.format(domain)) - - self._domains = list(domains) - - @energy_groups.setter - def energy_groups(self, energy_groups): - cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) - self._energy_groups = energy_groups - - @num_delayed_groups.setter - def num_delayed_groups(self, num_delayed_groups): - - cv.check_less_than('num delayed groups', num_delayed_groups, - openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) - cv.check_greater_than('num delayed groups', num_delayed_groups, 0, - equality=True) - self._num_delayed_groups = num_delayed_groups - - @num_polar.setter - def num_polar(self, num_polar): - cv.check_type('num_polar', num_polar, Integral) - cv.check_greater_than('num_polar', num_polar, 0) - self._num_polar = num_polar - - @num_azimuthal.setter - def num_azimuthal(self, num_azimuthal): - cv.check_type('num_azimuthal', num_azimuthal, Integral) - cv.check_greater_than('num_azimuthal', num_azimuthal, 0) - self._num_azimuthal = num_azimuthal - - @correction.setter - def correction(self, correction): - cv.check_value('correction', correction, ('P0', None)) - - if self.scatter_format == 'legendre': - if correction == 'P0' and self.legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(self.legendre_order) - warn(msg) - elif self.scatter_format == 'histogram': - msg = 'The P0 correction will be ignored since the ' \ - 'scatter format is set to histogram' - warn(msg) - - self._correction = correction - - @scatter_format.setter - def scatter_format(self, scatter_format): - cv.check_value('scatter_format', scatter_format, - openmc.mgxs.MU_TREATMENTS) - - if scatter_format == 'histogram' and self.correction == 'P0': - msg = 'The P0 correction will be ignored since the ' \ - 'scatter format is set to histogram' - warn(msg) - self.correction = None - - self._scatter_format = scatter_format - - @legendre_order.setter - def legendre_order(self, legendre_order): - cv.check_type('legendre_order', legendre_order, Integral) - cv.check_greater_than('legendre_order', legendre_order, 0, - equality=True) - cv.check_less_than('legendre_order', legendre_order, 10, equality=True) - - if self.scatter_format == 'legendre': - if self.correction == 'P0' and legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(self.legendre_order) - warn(msg, RuntimeWarning) - self.correction = None - elif self.scatter_format == 'histogram': - msg = 'The legendre order will be ignored since the ' \ - 'scatter format is set to histogram' - warn(msg) - - self._legendre_order = legendre_order - - @histogram_bins.setter - def histogram_bins(self, histogram_bins): - cv.check_type('histogram_bins', histogram_bins, Integral) - cv.check_greater_than('histogram_bins', histogram_bins, 0) - - if self.scatter_format == 'legendre': - msg = 'The histogram bins will be ignored since the ' \ - 'scatter format is set to legendre' - warn(msg) - elif self.scatter_format == 'histogram': - if self.correction == 'P0': - msg = 'The P0 correction will be ignored since ' \ - 'a histogram representation of the scattering '\ - 'kernel is requested' - warn(msg, RuntimeWarning) - self.correction = None - - self._histogram_bins = histogram_bins - - @tally_trigger.setter - def tally_trigger(self, tally_trigger): - cv.check_type('tally trigger', tally_trigger, openmc.Trigger) - self._tally_trigger = tally_trigger - - @estimator.setter - def estimator(self, estimator): - cv.check_value('estimator', estimator, ESTIMATOR_TYPES) - self._estimator = estimator - - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within the Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - - # Sparsify or densify each MGXS in the Library - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = self.get_mgxs(domain, mgxs_type) - mgxs.sparse = self.sparse - - self._sparse = sparse - - def build_library(self): - """Initialize MGXS objects in each domain and for each reaction type - in the library. - - This routine will populate the all_mgxs instance attribute dictionary - with MGXS subclass objects keyed by each domain ID (e.g., Material IDs) - and cross section type (e.g., 'nu-fission', 'total', etc.). - - """ - - # Initialize MGXS for each domain and mgxs type and store in dictionary - for domain in self.domains: - self.all_mgxs[domain.id] = OrderedDict() - for mgxs_type in self.mgxs_types: - if mgxs_type in openmc.mgxs.MDGXS_TYPES: - mgxs = openmc.mgxs.MDGXS.get_mgxs( - mgxs_type, name=self.name, num_polar=self.num_polar, - num_azimuthal=self.num_azimuthal) - else: - mgxs = openmc.mgxs.MGXS.get_mgxs( - mgxs_type, name=self.name, num_polar=self.num_polar, - num_azimuthal=self.num_azimuthal) - - mgxs.domain = domain - mgxs.domain_type = self.domain_type - mgxs.energy_groups = self.energy_groups - mgxs.by_nuclide = self.by_nuclide - if self.estimator is not None: - mgxs.estimator = self.estimator - - if mgxs_type in openmc.mgxs.MDGXS_TYPES: - if self.num_delayed_groups == 0: - mgxs.delayed_groups = None - else: - delayed_groups \ - = list(range(1, self.num_delayed_groups + 1)) - mgxs.delayed_groups = delayed_groups - - # If a tally trigger was specified, add it to the MGXS - if self.tally_trigger is not None: - mgxs.tally_trigger = self.tally_trigger - - # Specify whether to use a transport ('P0') correction - if isinstance(mgxs, openmc.mgxs.ScatterMatrixXS): - mgxs.correction = self.correction - mgxs.scatter_format = self.scatter_format - mgxs.legendre_order = self.legendre_order - mgxs.histogram_bins = self.histogram_bins - - self.all_mgxs[domain.id][mgxs_type] = mgxs - - def add_to_tallies_file(self, tallies_file, merge=True): - """Add all tallies from all MGXS objects to a tallies file. - - NOTE: This assumes that :meth:`Library.build_library` has been called - - Parameters - ---------- - tallies_file : openmc.Tallies - A Tallies collection to add each MGXS' tallies to generate a - 'tallies.xml' input file for OpenMC - merge : bool - Indicate whether tallies should be merged when possible. Defaults - to True. - - """ - - cv.check_type('tallies_file', tallies_file, openmc.Tallies) - - # Add tallies from each MGXS for each domain and mgxs type - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = self.get_mgxs(domain, mgxs_type) - - if mgxs_type in openmc.mgxs.MDGXS_TYPES: - if self.num_delayed_groups == 0: - mgxs.delayed_groups = None - else: - mgxs.delayed_groups \ - = list(range(1, self.num_delayed_groups + 1)) - - for tally in mgxs.tallies.values(): - tallies_file.append(tally, merge=merge) - - def load_from_statepoint(self, statepoint): - """Extracts tallies in an OpenMC StatePoint with the data needed to - compute multi-group cross sections. - - This method is needed to compute cross section data from tallies - in an OpenMC StatePoint object. - - NOTE: The statepoint must first be linked with an OpenMC Summary object. - - Parameters - ---------- - statepoint : openmc.StatePoint - An OpenMC StatePoint object with tally data - - Raises - ------ - ValueError - When this method is called with a statepoint that has not been - linked with a summary object. - - """ - - cv.check_type('statepoint', statepoint, openmc.StatePoint) - - if statepoint.summary is None: - msg = 'Unable to load data from a statepoint which has not been ' \ - 'linked with a summary file' - raise ValueError(msg) - - self._sp_filename = statepoint._f.filename - self._geometry = statepoint.summary.geometry - self._nuclides = statepoint.summary.nuclides - - if statepoint.run_mode == 'eigenvalue': - self._keff = statepoint.k_combined.n - - # Load tallies for each MGXS for each domain and mgxs type - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = self.get_mgxs(domain, mgxs_type) - mgxs.load_from_statepoint(statepoint) - mgxs.sparse = self.sparse - - def get_mgxs(self, domain, mgxs_type): - """Return the MGXS object for some domain and reaction rate type. - - This routine searches the library for an MGXS object for the spatial - domain and reaction rate type requested by the user. - - NOTE: This routine must be called after the build_library() routine. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh or Integral - The material, cell, or universe object of interest (or its ID) - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix', 'delayed-nu-fission', 'delayed-nu-fission matrix', 'chi-delayed', 'beta'} - The type of multi-group cross section object to return - - Returns - ------- - openmc.mgxs.MGXS - The MGXS object for the requested domain and reaction rate type - - Raises - ------ - ValueError - If no MGXS object can be found for the requested domain or - multi-group cross section type - - """ - - if self.domain_type == 'material': - cv.check_type('domain', domain, (openmc.Material, Integral)) - elif self.domain_type == 'cell' or self.domain_type == 'distribcell': - cv.check_type('domain', domain, (openmc.Cell, Integral)) - elif self.domain_type == 'universe': - cv.check_type('domain', domain, (openmc.Universe, Integral)) - elif self.domain_type == 'mesh': - cv.check_type('domain', domain, (openmc.RegularMesh, Integral)) - - # Check that requested domain is included in library - if isinstance(domain, Integral): - domain_id = domain - for domain in self.domains: - if domain_id == domain.id: - break - else: - msg = 'Unable to find MGXS for "{0}" "{1}" in ' \ - 'library'.format(self.domain_type, domain_id) - raise ValueError(msg) - else: - domain_id = domain.id - - # Check that requested domain is included in library - if mgxs_type not in self.mgxs_types: - msg = 'Unable to find MGXS type "{0}"'.format(mgxs_type) - raise ValueError(msg) - - return self.all_mgxs[domain_id][mgxs_type] - - def get_condensed_library(self, coarse_groups): - """Construct an energy-condensed version of this library. - - This routine condenses each of the multi-group cross sections in the - library to a coarse energy group structure. NOTE: This routine must - be called after the load_from_statepoint(...) routine loads the tallies - from the statepoint into each of the cross sections. - - Parameters - ---------- - coarse_groups : openmc.mgxs.EnergyGroups - The coarse energy group structure of interest - - Returns - ------- - openmc.mgxs.Library - A new multi-group cross section library condensed to the group - structure of interest - - Raises - ------ - ValueError - When this method is called before a statepoint has been loaded - - See also - -------- - MGXS.get_condensed_xs(coarse_groups) - - """ - - if self.sp_filename is None: - msg = 'Unable to get a condensed coarse group cross section ' \ - 'library since the statepoint has not yet been loaded' - raise ValueError(msg) - - cv.check_type('coarse_groups', coarse_groups, openmc.mgxs.EnergyGroups) - cv.check_less_than('coarse groups', coarse_groups.num_groups, - self.num_groups, equality=True) - cv.check_value('upper coarse energy', coarse_groups.group_edges[-1], - [self.energy_groups.group_edges[-1]]) - cv.check_value('lower coarse energy', coarse_groups.group_edges[0], - [self.energy_groups.group_edges[0]]) - - # Clone this Library to initialize the condensed version - condensed_library = copy.deepcopy(self) - condensed_library.energy_groups = coarse_groups - - # Condense the MGXS for each domain and mgxs type - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = condensed_library.get_mgxs(domain, mgxs_type) - condensed_mgxs = mgxs.get_condensed_xs(coarse_groups) - condensed_library.all_mgxs[domain.id][mgxs_type] = condensed_mgxs - - return condensed_library - - def get_subdomain_avg_library(self): - """Construct a subdomain-averaged version of this library. - - This routine averages each multi-group cross section across distribcell - instances. The method performs spatial homogenization to compute the - scalar flux-weighted average cross section across the subdomains. - - NOTE: This method is only relevant for distribcell domain types and - simplys returns a deep copy of the library for all other domains types. - - Returns - ------- - openmc.mgxs.Library - A new multi-group cross section library averaged across subdomains - - Raises - ------ - ValueError - When this method is called before a statepoint has been loaded - - See also - -------- - MGXS.get_subdomain_avg_xs(subdomains) - - """ - - if self.sp_filename is None: - msg = 'Unable to get a subdomain-averaged cross section ' \ - 'library since the statepoint has not yet been loaded' - raise ValueError(msg) - - # Clone this Library to initialize the subdomain-averaged version - subdomain_avg_library = copy.deepcopy(self) - - if subdomain_avg_library.domain_type == 'distribcell': - subdomain_avg_library.domain_type = 'cell' - else: - return subdomain_avg_library - - # Subdomain average the MGXS for each domain and mgxs type - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = subdomain_avg_library.get_mgxs(domain, mgxs_type) - if mgxs.domain_type == 'distribcell': - avg_mgxs = mgxs.get_subdomain_avg_xs() - subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs - - return subdomain_avg_library - - def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs', - subdomains='all', nuclides='all', xs_type='macro', - row_column='inout', libver='earliest'): - """Export the multi-group cross section library to an HDF5 binary file. - - This method constructs an HDF5 file which stores the library's - multi-group cross section data. The data is stored in a hierarchy of - HDF5 groups from the domain type, domain id, subdomain id (for - distribcell domains), nuclides and cross section types. Two datasets for - the mean and standard deviation are stored for each subdomain entry in - the HDF5 file. The number of groups is stored as a file attribute. - - NOTE: This requires the h5py Python package. - - Parameters - ---------- - filename : str - Filename for the HDF5 file. Defaults to 'mgxs.h5'. - directory : str - Directory for the HDF5 file. Defaults to 'mgxs'. - subdomains : {'all', 'avg'} - Report all subdomains or the average of all subdomain cross sections - in the report. Defaults to 'all'. - nuclides : {'all', 'sum'} - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will report - the cross sections summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Store the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - row_column: {'inout', 'outin'} - Store scattering matrices indexed first by incoming group and - second by outgoing group ('inout'), or vice versa ('outin'). - Defaults to 'inout'. - libver : {'earliest', 'latest'} - Compatibility mode for the HDF5 file. 'latest' will produce files - that are less backwards compatible but have performance benefits. - - Raises - ------ - ValueError - When this method is called before a statepoint has been loaded - - See also - -------- - MGXS.build_hdf5_store(filename, directory, xs_type) - - """ - - if self.sp_filename is None: - msg = 'Unable to export multi-group cross section library ' \ - 'since a statepoint has not yet been loaded' - raise ValueError(msg) - - cv.check_type('filename', filename, str) - cv.check_type('directory', directory, str) - - import h5py - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Add an attribute for the number of energy groups to the HDF5 file - full_filename = os.path.join(directory, filename) - full_filename = full_filename.replace(' ', '-') - f = h5py.File(full_filename, 'w', libver=libver) - f.attrs['# groups'] = self.num_groups - f.close() - - # Export MGXS for each domain and mgxs type to an HDF5 file - for domain in self.domains: - for mgxs_type in self.mgxs_types: - mgxs = self.all_mgxs[domain.id][mgxs_type] - - if subdomains == 'avg': - mgxs = mgxs.get_subdomain_avg_xs() - - mgxs.build_hdf5_store(filename, directory, xs_type=xs_type, - nuclides=nuclides, row_column=row_column) - - def dump_to_file(self, filename='mgxs', directory='mgxs'): - """Store this Library object in a pickle binary file. - - Parameters - ---------- - filename : str - Filename for the pickle file. Defaults to 'mgxs'. - directory : str - Directory for the pickle file. Defaults to 'mgxs'. - - See also - -------- - Library.load_from_file(filename, directory) - - """ - - cv.check_type('filename', filename, str) - cv.check_type('directory', directory, str) - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - full_filename = os.path.join(directory, filename + '.pkl') - full_filename = full_filename.replace(' ', '-') - - # Load and return pickled Library object - pickle.dump(self, open(full_filename, 'wb')) - - @staticmethod - def load_from_file(filename='mgxs', directory='mgxs'): - """Load a Library object from a pickle binary file. - - Parameters - ---------- - filename : str - Filename for the pickle file. Defaults to 'mgxs'. - directory : str - Directory for the pickle file. Defaults to 'mgxs'. - - Returns - ------- - openmc.mgxs.Library - A Library object loaded from the pickle binary file - - See also - -------- - Library.dump_to_file(mgxs_lib, filename, directory) - - """ - - cv.check_type('filename', filename, str) - cv.check_type('directory', directory, str) - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - full_filename = os.path.join(directory, filename + '.pkl') - full_filename = full_filename.replace(' ', '-') - - # Load and return pickled Library object - return pickle.load(open(full_filename, 'rb')) - - def get_xsdata(self, domain, xsdata_name, nuclide='total', xs_type='macro', - subdomain=None): - """Generates an openmc.XSdata object describing a multi-group cross section - dataset for writing to an openmc.MGXSLibrary object. - - Note that this method does not build an XSdata - object with nested temperature tables. The temperature of each - XSdata object will be left at the default value of 294K. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - xsdata_name : str - Name to apply to the "xsdata" entry produced by this method - nuclide : str - A nuclide name string (e.g., 'U235'). Defaults to 'total' to - obtain a material-wise macroscopic cross section. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. If the Library object is not tallied by - nuclide this will be set to 'macro' regardless. - subdomain : iterable of int - This parameter is not used unless using a mesh domain. In that - case, the subdomain is an [i,j,k] index (1-based indexing) of the - mesh cell of interest in the openmc.RegularMesh object. Note: - this parameter currently only supports subdomains within a mesh, - and not the subdomains of a distribcell. - - Returns - ------- - xsdata : openmc.XSdata - Multi-Group Cross Section dataset object. - - Raises - ------ - ValueError - When the Library object is initialized with insufficient types of - cross sections for the Library. - - See also - -------- - Library.create_mg_library() - - """ - - cv.check_type('domain', domain, (openmc.Material, openmc.Cell, - openmc.Universe, openmc.RegularMesh)) - cv.check_type('xsdata_name', xsdata_name, str) - cv.check_type('nuclide', nuclide, str) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - if subdomain is not None: - cv.check_iterable_type('subdomain', subdomain, Integral, - max_depth=3) - - # Make sure statepoint has been loaded - if self._sp_filename is None: - msg = 'A StatePoint must be loaded before calling ' \ - 'the create_mg_library() function' - raise ValueError(msg) - - # If gathering material-specific data, set the xs_type to macro - if not self.by_nuclide: - xs_type = 'macro' - - # Build & add metadata to XSdata object - name = xsdata_name - if nuclide != 'total': - name += '_' + nuclide - if self.num_polar > 1 or self.num_azimuthal > 1: - representation = 'angle' - else: - representation = 'isotropic' - xsdata = openmc.XSdata(name, self.energy_groups, - representation=representation) - xsdata.num_delayed_groups = self.num_delayed_groups - if self.num_polar > 1 or self.num_azimuthal > 1: - xsdata.num_polar = self.num_polar - xsdata.num_azimuthal = self.num_azimuthal - - if nuclide != 'total': - xsdata.atomic_weight_ratio = self._nuclides[nuclide][1] - - if subdomain is None: - subdomain = 'all' - else: - subdomain = [subdomain] - - # Now get xs data itself - if 'nu-transport' in self.mgxs_types and self.correction == 'P0': - mymgxs = self.get_mgxs(domain, 'nu-transport') - xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], - subdomain=subdomain) - - elif 'total' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'total') - xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], - subdomain=subdomain) - - if 'absorption' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'absorption') - xsdata.set_absorption_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'fission' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'fission') - xsdata.set_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], subdomain=subdomain) - - if 'kappa-fission' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'kappa-fission') - xsdata.set_kappa_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'inverse-velocity' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'inverse-velocity') - xsdata.set_inverse_velocity_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'nu-fission matrix' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'nu-fission matrix') - xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'chi' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'chi') - xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], - subdomain=subdomain) - - if 'chi-prompt' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'chi-prompt') - xsdata.set_chi_prompt_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], subdomain=subdomain) - - if 'chi-delayed' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'chi-delayed') - xsdata.set_chi_delayed_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], subdomain=subdomain) - - if 'nu-fission' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'nu-fission') - xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'prompt-nu-fission' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'prompt-nu-fission') - xsdata.set_prompt_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'prompt-nu-fission matrix' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'prompt-nu-fission matrix') - xsdata.set_prompt_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'delayed-nu-fission' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'delayed-nu-fission') - xsdata.set_delayed_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'delayed-nu-fission matrix' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'delayed-nu-fission matrix') - xsdata.set_delayed_nu_fission_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - if 'beta' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'nu-fission') - xsdata.set_beta_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], - subdomain=subdomain) - - # If multiplicity matrix is available, prefer that - if 'multiplicity matrix' in self.mgxs_types: - mymgxs = self.get_mgxs(domain, 'multiplicity matrix') - xsdata.set_multiplicity_matrix_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - using_multiplicity = True - - # multiplicity will fall back to using scatter and nu-scatter - elif 'scatter matrix' in self.mgxs_types and \ - 'nu-scatter matrix' in self.mgxs_types: - scatt_mgxs = self.get_mgxs(domain, 'scatter matrix') - nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') - xsdata.set_multiplicity_matrix_mgxs(nuscatt_mgxs, scatt_mgxs, - xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - using_multiplicity = True - - # multiplicity will fall back to using scatter and nu-scatter - elif 'consistent scatter matrix' in self.mgxs_types and \ - 'consistent nu-scatter matrix' in self.mgxs_types: - scatt_mgxs = self.get_mgxs(domain, 'consistent scatter matrix') - nuscatt_mgxs = \ - self.get_mgxs(domain, 'consistent nu-scatter matrix') - xsdata.set_multiplicity_matrix_mgxs(nuscatt_mgxs, scatt_mgxs, - xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - using_multiplicity = True - - else: - using_multiplicity = False - - if using_multiplicity: - if 'nu-scatter matrix' in self.mgxs_types: - nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') - else: - nuscatt_mgxs = \ - self.get_mgxs(domain, 'consistent nu-scatter matrix') - xsdata.set_scatter_matrix_mgxs(nuscatt_mgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - else: - if 'nu-scatter matrix' in self.mgxs_types or \ - 'consistent nu-scatter matrix' in self.mgxs_types: - if 'nu-scatter matrix' in self.mgxs_types: - nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') - else: - nuscatt_mgxs = \ - self.get_mgxs(domain, 'consistent nu-scatter matrix') - xsdata.set_scatter_matrix_mgxs(nuscatt_mgxs, xs_type=xs_type, - nuclide=[nuclide], - subdomain=subdomain) - - # Since we are not using multiplicity, then - # scattering multiplication (nu-scatter) must be - # accounted for approximately by using an adjusted - # absorption cross section. - if 'total' in self.mgxs_types or 'transport' in self.mgxs_types: - if xsdata.scatter_format == 'legendre': - for i in range(len(xsdata.temperatures)): - if representation == 'isotropic': - xsdata._absorption[i] = \ - np.subtract(xsdata._total[i], np.sum( - xsdata._scatter_matrix[i][:, :, 0], - axis=1)) - elif representation == 'angle': - xsdata._absorption[i] = \ - np.subtract(xsdata._total[i], np.sum( - xsdata._scatter_matrix[i][:, :, :, :, 0], - axis=3)) - elif xsdata.scatter_format == 'histogram': - for i in range(len(xsdata.temperatures)): - if representation == 'isotropic': - xsdata._absorption[i] = \ - np.subtract(xsdata._total[i], np.sum(np.sum( - xsdata._scatter_matrix[i][:, :, :], - axis=2), axis=1)) - elif representation == 'angle': - xsdata._absorption[i] = \ - np.subtract(xsdata._total[i], np.sum(np.sum( - xsdata._scatter_matrix[i][:, :, :, :, :], - axis=4), axis=3)) - - return xsdata - - def create_mg_library(self, xs_type='macro', xsdata_names=None): - """Creates an openmc.MGXSLibrary object to contain the MGXS data for the - Multi-Group mode of OpenMC. - - Note that this library will not make use of nested temperature tables. - Every dataset in the library will be treated as if it was at the same - default temperature. - - Parameters - ---------- - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. If the Library object is not tallied by - nuclide this will be set to 'macro' regardless. - xsdata_names : Iterable of str - List of names to apply to the "xsdata" entries in the - resultant mgxs data file. Defaults to 'set1', 'set2', ... - - Returns - ------- - mgxs_file : openmc.MGXSLibrary - Multi-Group Cross Section File that is ready to be printed to the - file of choice by the user. - - Raises - ------ - ValueError - When the Library object is initialized with insufficient types of - cross sections for the Library. - - See also - -------- - Library.dump_to_file() - Library.create_mg_mode() - - """ - - # Check to ensure the Library contains the correct - # multi-group cross section types - self.check_library_for_openmc_mgxs() - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - if xsdata_names is not None: - cv.check_iterable_type('xsdata_names', xsdata_names, str) - - # If gathering material-specific data, set the xs_type to macro - if not self.by_nuclide: - xs_type = 'macro' - - # Initialize file - mgxs_file = openmc.MGXSLibrary( - self.energy_groups, num_delayed_groups=self.num_delayed_groups) - - if self.domain_type == 'mesh': - # Create the xsdata objects and add to the mgxs_file - i = 0 - for domain in self.domains: - if self.by_nuclide: - raise NotImplementedError("Mesh domains do not currently " - "support nuclidic tallies") - for subdomain in domain.indices: - # Build & add metadata to XSdata object - if xsdata_names is None: - xsdata_name = 'set' + str(i + 1) - else: - xsdata_name = xsdata_names[i] - - # Create XSdata and Macroscopic for this domain - xsdata = self.get_xsdata(domain, xsdata_name, - subdomain=subdomain) - mgxs_file.add_xsdata(xsdata) - i += 1 - - else: - # Create the xsdata object and add it to the mgxs_file - for i, domain in enumerate(self.domains): - if self.by_nuclide: - nuclides = domain.get_nuclides() - else: - nuclides = ['total'] - for nuclide in nuclides: - # Build & add metadata to XSdata object - if xsdata_names is None: - xsdata_name = 'set' + str(i + 1) - else: - xsdata_name = xsdata_names[i] - if nuclide != 'total': - xsdata_name += '_' + nuclide - - xsdata = self.get_xsdata(domain, xsdata_name, - nuclide=nuclide, xs_type=xs_type) - - mgxs_file.add_xsdata(xsdata) - - return mgxs_file - - def create_mg_mode(self, xsdata_names=None, bc=['reflective'] * 6): - """Creates an openmc.MGXSLibrary object to contain the MGXS data for the - Multi-Group mode of OpenMC as well as the associated openmc.Materials - and openmc.Geometry objects. - - The created Geometry is the same as that used to generate the MGXS - data, with the only differences being modifications to point to - newly-created Materials which point to the multi-group data. This - method only creates a macroscopic MGXS Library even if nuclidic tallies - are specified in the Library. Note that this library will not make - use of nested temperature tables. Every dataset in the library will - be treated as if it was at the same default temperature. - - Parameters - ---------- - xsdata_names : Iterable of str - List of names to apply to the "xsdata" entries in the - resultant mgxs data file. Defaults to 'set1', 'set2', ... - bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'} - Boundary conditions for each of the four faces of a rectangle - (if applying to a 2D mesh) or six faces of a parallelepiped - (if applying to a 3D mesh) provided in the following order: - [x min, x max, y min, y max, z min, z max]. 2-D cells do not - contain the z min and z max entries. - - Returns - ------- - mgxs_file : openmc.MGXSLibrary - Multi-Group Cross Section File that is ready to be printed to the - file of choice by the user. - materials : openmc.Materials - Materials file ready to be printed with all the macroscopic data - present within this Library. - geometry : openmc.Geometry - Materials file ready to be printed with all the macroscopic data - present within this Library. - - Raises - ------ - ValueError - When the Library object is initialized with insufficient types of - cross sections for the Library. - - See also - -------- - Library.create_mg_library() - Library.dump_to_file() - - """ - - # Check to ensure the Library contains the correct - # multi-group cross section types - self.check_library_for_openmc_mgxs() - - # If the domain type is a mesh, then there can only be one domain for - # this method. This is because we can build a model automatically if - # the user provided multiple mesh domains for library generation since - # the multiple meshes could be overlapping or in disparate regions - # of the continuous energy model. The next step makes sure there is - # only one before continuing. - if self.domain_type == 'mesh': - cv.check_length("domains", self.domains, 1, 1) - - # Get the MGXS File Data - mgxs_file = self.create_mg_library('macro', xsdata_names) - - # Now move on the creating the geometry and assigning materials - if self.domain_type == 'mesh': - root = openmc.Universe(name='root', universe_id=0) - - # Add cells representative of the mesh with reflective BC - root_cell, cells = \ - self.domains[0].build_cells(bc) - root.add_cell(root_cell) - - geometry = openmc.Geometry() - geometry.root_universe = root - materials = openmc.Materials() - - for i, subdomain in enumerate(self.domains[0].indices): - xsdata = mgxs_file.xsdatas[i] - - # Build the macroscopic and assign it to the cell of - # interest - macroscopic = openmc.Macroscopic(name=xsdata.name) - - # Create Material and add to collection - material = openmc.Material(name=xsdata.name) - material.add_macroscopic(macroscopic) - materials.append(material) - - # Set the materials for each of the universes - cells[i].fill = materials[i] - - else: - # Create a copy of the Geometry for these Macroscopics - geometry = copy.deepcopy(self.geometry) - materials = openmc.Materials() - - # Get all Cells from the Geometry for differentiation - all_cells = geometry.get_all_material_cells().values() - - # Create the xsdata object and add it to the mgxs_file - for i, domain in enumerate(self.domains): - xsdata = mgxs_file.xsdatas[i] - - macroscopic = openmc.Macroscopic(name=xsdata.name) - - # Create Material and add to collection - material = openmc.Material(name=xsdata.name) - material.add_macroscopic(macroscopic) - materials.append(material) - - # Differentiate Geometry with new Material - if self.domain_type == 'material': - # Fill all appropriate Cells with new Material - for cell in all_cells: - if cell.fill.id == domain.id: - cell.fill = material - - elif self.domain_type == 'cell': - for cell in all_cells: - if cell.id == domain.id: - cell.fill = material - - return mgxs_file, materials, geometry - - def check_library_for_openmc_mgxs(self): - """This routine will check the MGXS Types within a Library - to ensure the MGXS types provided can be used to create - a MGXS Library for OpenMC's Multi-Group mode. - - The rules to check include: - - - Either total or transport must be present. - - - Both can be available if one wants, but we should - use whatever corresponds to Library.correction (if P0: transport) - - - Absorption is required. - - A nu-fission cross section and chi values are not required as a - fixed source problem could be the target. - - Fission and kappa-fission are not required as they are only - needed to support tallies the user may wish to request. - - See also - -------- - Library.create_mg_library() - Library.create_mg_mode() - - """ - - error_flag = False - - # if correction is 'P0', then transport must be provided - # otherwise total must be provided - if self.correction == 'P0': - if ('transport' not in self.mgxs_types and - 'nu-transport' not in self.mgxs_types): - error_flag = True - warn('If the "correction" parameter is "P0", then a ' - '"transport" or "nu-transport" MGXS type is required.') - else: - if 'total' not in self.mgxs_types: - error_flag = True - warn('If the "correction" parameter is None, then a ' - '"total" MGXS type is required.') - - # Check consistency of "nu-transport" and "nu-scatter" - if 'nu-transport' in self.mgxs_types: - if not ('nu-scatter matrix' in self.mgxs_types or - 'consistent nu-scatter matrix' in self.mgxs_types): - error_flag = True - warn('If a "nu-transport" MGXS type is used then a ' - '"nu-scatter matrix" or "consistent nu-scatter matrix" ' - 'must also be used.') - elif 'transport' in self.mgxs_types: - if not ('scatter matrix' in self.mgxs_types or - 'consistent scatter matrix' in self.mgxs_types): - error_flag = True - warn('If a "transport" MGXS type is used then a ' - '"scatter matrix" or "consistent scatter matrix" ' - 'must also be used.') - - # Make sure there is some kind of a scattering matrix data - if 'nu-scatter matrix' not in self.mgxs_types and \ - 'consistent nu-scatter matrix' not in self.mgxs_types and \ - 'scatter matrix' not in self.mgxs_types and \ - 'consistent scatter matrix' not in self.mgxs_types: - error_flag = True - warn('A "nu-scatter matrix", "consistent nu-scatter matrix", ' - '"scatter matrix", or "consistent scatter matrix" MGXS ' - 'type is required.') - - # Ensure absorption is present - if 'absorption' not in self.mgxs_types: - error_flag = True - warn('An "absorption" MGXS type is required but not provided.') - - if error_flag: - raise ValueError('Invalid MGXS configuration encountered.') diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py deleted file mode 100644 index 2d1e75e81..000000000 --- a/openmc/mgxs/mdgxs.py +++ /dev/null @@ -1,2619 +0,0 @@ -from collections import OrderedDict -from collections.abc import Iterable -import itertools -from numbers import Integral -import warnings -import os -import sys -import copy -from abc import ABCMeta - -import numpy as np - -import openmc -from openmc.mgxs import MGXS -from openmc.mgxs.mgxs import _DOMAIN_TO_FILTER -import openmc.checkvalue as cv - - -# Supported cross section types -MDGXS_TYPES = ['delayed-nu-fission', - 'chi-delayed', - 'beta', - 'decay-rate', - 'delayed-nu-fission matrix'] - -# Maximum number of delayed groups, from src/constants.F90 -MAX_DELAYED_GROUPS = 8 - - -class MDGXS(MGXS): - """An abstract multi-delayed-group cross section for some energy and delayed - group structures within some spatial domain. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group and multi-delayed-group cross sections for downstream - neutronics calculations. - - NOTE: Users should instantiate the subclasses of this abstract class. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'chi-delayed', 'beta', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell', and 'universe' - domain types. This is equal to the number of cell instances for - 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, by_nuclide, name, - num_polar, num_azimuthal) - - self._delayed_groups = None - - if delayed_groups is not None: - self.delayed_groups = delayed_groups - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, copy it - if existing is None: - clone = type(self).__new__(type(self)) - clone._name = self.name - clone._rxn_type = self.rxn_type - clone._by_nuclide = self.by_nuclide - clone._nuclides = copy.deepcopy(self._nuclides) - clone._domain = self.domain - clone._domain_type = self.domain_type - clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._delayed_groups = copy.deepcopy(self.delayed_groups, memo) - clone._num_polar = self.num_polar - clone._num_azimuthal = self.num_azimuthal - clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) - clone._rxn_rate_tally = copy.deepcopy(self._rxn_rate_tally, memo) - clone._xs_tally = copy.deepcopy(self._xs_tally, memo) - clone._sparse = self.sparse - clone._derived = self.derived - - clone._tallies = OrderedDict() - for tally_type, tally in self.tallies.items(): - clone.tallies[tally_type] = copy.deepcopy(tally, memo) - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - return (0, 1, 3, 4) - else: - return (1, 2) - - @property - def delayed_groups(self): - return self._delayed_groups - - @property - def num_delayed_groups(self): - if self.delayed_groups is None: - return 1 - else: - return len(self.delayed_groups) - - @delayed_groups.setter - def delayed_groups(self, delayed_groups): - - if delayed_groups is not None: - - cv.check_type('delayed groups', delayed_groups, list, int) - cv.check_greater_than('num delayed groups', len(delayed_groups), 0) - - # Check that the groups are within [1, MAX_DELAYED_GROUPS] - for group in delayed_groups: - cv.check_greater_than('delayed group', group, 0) - cv.check_less_than('delayed group', group, MAX_DELAYED_GROUPS, - equality=True) - - self._delayed_groups = delayed_groups - - @property - def filters(self): - - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy_filter = openmc.EnergyFilter(group_edges) - - if self.delayed_groups != None: - delayed_filter = openmc.DelayedGroupFilter(self.delayed_groups) - filters = [[energy_filter], [delayed_filter, energy_filter]] - else: - filters = [[energy_filter], [energy_filter]] - return self._add_angle_filters(filters) - - @staticmethod - def get_mgxs(mdgxs_type, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - """Return a MDGXS subclass object for some energy group structure within - some spatial domain for some reaction type. - - This is a factory method which can be used to quickly create MDGXS - subclass objects for various reaction types. - - Parameters - ---------- - mdgxs_type : {'delayed-nu-fission', 'chi-delayed', 'beta', 'decay-rate', 'delayed-nu-fission matrix'} - The type of multi-delayed-group cross section object to return - domain : openmc.Material or openmc.Cell or openmc.Universe or - openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain. - Defaults to False - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. Defaults to the empty string. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - Returns - ------- - openmc.mgxs.MDGXS - A subclass of the abstract MDGXS class for the multi-delayed-group - cross section type requested by the user - - """ - - cv.check_value('mdgxs_type', mdgxs_type, MDGXS_TYPES) - - if mdgxs_type == 'delayed-nu-fission': - mdgxs = DelayedNuFissionXS(domain, domain_type, energy_groups, - delayed_groups) - elif mdgxs_type == 'chi-delayed': - mdgxs = ChiDelayed(domain, domain_type, energy_groups, - delayed_groups) - elif mdgxs_type == 'beta': - mdgxs = Beta(domain, domain_type, energy_groups, delayed_groups) - elif mdgxs_type == 'decay-rate': - mdgxs = DecayRate(domain, domain_type, energy_groups, delayed_groups) - elif mdgxs_type == 'delayed-nu-fission matrix': - mdgxs = DelayedNuFissionMatrixXS(domain, domain_type, energy_groups, - delayed_groups) - - mdgxs.by_nuclide = by_nuclide - mdgxs.name = name - mdgxs.num_polar = num_polar - mdgxs.num_azimuthal = num_azimuthal - return mdgxs - - def get_xs(self, groups='all', subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - value='mean', delayed_groups='all', squeeze=True, **kwargs): - """Returns an array of multi-delayed-group cross sections. - - This method constructs a 4D NumPy array for the requested - multi-delayed-group cross section data for one or more - subdomains (1st dimension), delayed groups (2nd demension), - energy groups (3rd dimension), and nuclides (4th dimension). - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U-235', 'U-238']). The - special string 'all' will return the cross sections for all nuclides - in the spatial domain. The special string 'sum' will return the - cross section summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - delayed_groups : list of int or 'all' - Delayed groups of interest. Defaults to 'all'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group, subdomain and nuclide is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-delayed-group cross - section is computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - for subdomain in subdomains: - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - filter_bins.append((subdomain,)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - for group in groups: - filters.append(openmc.EnergyFilter) - filter_bins.append( - (self.energy_groups.get_group_bounds(group),)) - - # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, str): - cv.check_type('delayed groups', delayed_groups, list, int) - for delayed_group in delayed_groups: - filters.append(openmc.DelayedGroupFilter) - filter_bins.append((delayed_group,)) - - # Construct a collection of the nuclides to retrieve from the xs tally - if self.by_nuclide: - if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: - query_nuclides = self.get_nuclides() - else: - query_nuclides = nuclides - else: - query_nuclides = ['total'] - - # If user requested the sum for all nuclides, use tally summation - if nuclides == 'sum' or nuclides == ['sum']: - xs_tally = self.xs_tally.summation(nuclides=query_nuclides) - xs = xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=query_nuclides, value=value) - - # Divide by atom number densities for microscopic cross sections - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - if value == 'mean' or value == 'std_dev': - xs /= densities[np.newaxis, :, np.newaxis] - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - if groups == 'all': - num_groups = self.num_groups - else: - num_groups = len(groups) - - if delayed_groups == 'all': - num_delayed_groups = self.num_delayed_groups - else: - num_delayed_groups = len(delayed_groups) - - # Reshape tally data array with separate axes for domain, - # energy groups, delayed groups, and nuclides - # Accommodate the polar and azimuthal bins if needed - num_subdomains = \ - int(xs.shape[0] / (num_groups * num_delayed_groups * - self.num_polar * self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_delayed_groups, num_groups) - else: - new_shape = (num_subdomains, num_delayed_groups, num_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # delayed group, and energy group data. - xs = self._squeeze_xs(xs) - - return xs - - def get_slice(self, nuclides=[], groups=[], delayed_groups=[]): - """Build a sliced MDGXS for the specified nuclides, energy groups, - and delayed groups. - - This method constructs a new MDGXS to encapsulate a subset of the data - represented by this MDGXS. The subset of data to include in the tally - slice is determined by the nuclides, energy groups, delayed groups - specified in the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U-235', 'U-238']; default is []) - groups : list of int - A list of energy group indices starting at 1 for the high energies - (e.g., [1, 2, 3]; default is []) - delayed_groups : list of int - A list of delayed group indices - (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MDGXS - A new MDGXS object which encapsulates the subset of data requested - for the nuclide(s) and/or energy group(s) and/or delayed group(s) - requested in the parameters. - - """ - - cv.check_iterable_type('nuclides', nuclides, str) - cv.check_iterable_type('energy_groups', groups, Integral) - cv.check_type('delayed groups', delayed_groups, list, int) - - # Build lists of filters and filter bins to slice - filters = [] - filter_bins = [] - - if len(groups) != 0: - energy_bins = [] - for group in groups: - group_bounds = self.energy_groups.get_group_bounds(group) - energy_bins.append(group_bounds) - filter_bins.append(tuple(energy_bins)) - filters.append(openmc.EnergyFilter) - - if len(delayed_groups) != 0: - filter_bins.append(tuple(delayed_groups)) - filters.append(openmc.DelayedGroupFilter) - - # Clone this MGXS to initialize the sliced version - slice_xs = copy.deepcopy(self) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice each of the tallies across nuclides and energy groups - for tally_type, tally in slice_xs.tallies.items(): - slice_nuclides = [nuc for nuc in nuclides if nuc in tally.nuclides] - if filters != []: - tally_slice = tally.get_slice(filters=filters, - filter_bins=filter_bins, - nuclides=slice_nuclides) - else: - tally_slice = tally.get_slice(nuclides=slice_nuclides) - slice_xs.tallies[tally_type] = tally_slice - - # Assign sliced energy group structure to sliced MDGXS - if groups: - new_group_edges = [] - for group in groups: - group_edges = self.energy_groups.get_group_bounds(group) - new_group_edges.extend(group_edges) - new_group_edges = np.unique(new_group_edges) - slice_xs.energy_groups.group_edges = sorted(new_group_edges) - - # Assign sliced delayed group structure to sliced MDGXS - if delayed_groups: - slice_xs.delayed_groups = delayed_groups - - # Assign sliced nuclides to sliced MGXS - if nuclides: - slice_xs.nuclides = nuclides - - slice_xs.sparse = self.sparse - return slice_xs - - def merge(self, other): - """Merge another MGXS with this one - - MGXS are only mergeable if their energy groups and nuclides are either - identical or mutually exclusive. If results have been loaded from a - statepoint, then MGXS are only mergeable along one and only one of - energy groups or nuclides. - - Parameters - ---------- - other : openmc.mgxs.MDGXS - MDGXS to merge with this one - - Returns - ------- - merged_mdgxs : openmc.mgxs.MDGXS - Merged MDGXS - - """ - - merged_mdgxs = super().merge(other) - - # Merge delayed groups - if self.delayed_groups != other.delayed_groups: - merged_mdgxs.delayed_groups = list(set(self.delayed_groups + - other.delayed_groups)) - - return merged_mdgxs - - def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): - """Print a string representation for the multi-group cross section. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will report - the cross sections summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - - """ - - if self.delayed_groups is None: - super().print_xs(subdomains, nuclides, xs_type) - return - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'mesh': - xyz = [range(1, x + 1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - elif nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Build header for string with type and domain info - string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) - - # Generate the header for an individual XS - xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) - - # If cross section data has not been computed, only print string header - if self.tallies is None: - print(string) - return - - # Set polar/azimuthal bins - if self.num_polar > 1 or self.num_azimuthal > 1: - polar_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azimuthal_bins = np.linspace(-np.pi, np.pi, - num=self.num_azimuthal + 1, - endpoint=True) - - # Loop over all subdomains - for subdomain in subdomains: - - if self.domain_type == 'distribcell' or self.domain_type == 'mesh': - string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) - - # Loop over all Nuclides - for nuclide in nuclides: - - # Build header for nuclide type - if nuclide != 'sum': - string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) - - # Add the cross section header - string += '{0: <16}\n'.format(xs_header) - - for delayed_group in self.delayed_groups: - - template = '{0: <12}Delayed Group {1}:\t' - string += template.format('', delayed_group) - string += '\n' - - template = '{0: <12}Group {1} [{2: <10} - {3: <10}eV]:\t' - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean', - delayed_groups=[delayed_group]) - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='rel_err', - delayed_groups=[delayed_group]) - rel_err_xs = rel_err_xs * 100. - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azimuthal, and energy group ranges - for pol in range(len(polar_bins) - 1): - pol_low, pol_high = polar_bins[pol: pol + 2] - for azi in range(len(azimuthal_bins) - 1): - azi_low, azi_high = azimuthal_bins[azi: azi + 2] - string += '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - for group in range(1, self.num_groups + 1): - bounds = \ - self.energy_groups.get_group_bounds(group) - string += '\t' + template.format('', group, - bounds[0], - bounds[1]) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[pol, azi, group - 1], - rel_err_xs[pol, azi, group - 1]) - string += '\n' - string += '\n' - else: - # Loop over energy groups ranges - for group in range(1, self.num_groups+1): - bounds = self.energy_groups.get_group_bounds(group) - string += template.format('', group, bounds[0], bounds[1]) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[group - 1], rel_err_xs[group - 1]) - string += '\n' - string += '\n' - string += '\n' - - print(string) - - def export_xs_data(self, filename='mgxs', directory='mgxs', - format='csv', groups='all', xs_type='macro', - delayed_groups='all'): - """Export the multi-delayed-group cross section data to a file. - - This method leverages the functionality in the Pandas library to export - the multi-group cross section data in a variety of output file formats - for storage and/or post-processing. - - Parameters - ---------- - filename : str - Filename for the exported file. Defaults to 'mgxs'. - directory : str - Directory for the exported file. Defaults to 'mgxs'. - format : {'csv', 'excel', 'pickle', 'latex'} - The format for the exported data file. Defaults to 'csv'. - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Store the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - delayed_groups : list of int or 'all' - Delayed groups of interest. Defaults to 'all'. - - """ - - cv.check_type('filename', filename, str) - cv.check_type('directory', directory, str) - cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - filename = os.path.join(directory, filename) - filename = filename.replace(' ', '-') - - # Get a Pandas DataFrame for the data - df = self.get_pandas_dataframe(groups=groups, xs_type=xs_type, - delayed_groups=delayed_groups) - - # Export the data using Pandas IO API - if format == 'csv': - df.to_csv(filename + '.csv', index=False) - elif format == 'excel': - if self.domain_type == 'mesh': - df.to_excel(filename + '.xls') - else: - df.to_excel(filename + '.xls', index=False) - elif format == 'pickle': - df.to_pickle(filename + '.pkl') - elif format == 'latex': - if self.domain_type == 'distribcell': - msg = 'Unable to export distribcell multi-group cross section' \ - 'data to a LaTeX table' - raise NotImplementedError(msg) - - df.to_latex(filename + '.tex', bold_rows=True, - longtable=True, index=False) - - # Surround LaTeX table with code needed to run pdflatex - with open(filename + '.tex','r') as original: - data = original.read() - with open(filename + '.tex','w') as modified: - modified.write( - '\\documentclass[preview, 12pt, border=1mm]{standalone}\n') - modified.write('\\usepackage{caption}\n') - modified.write('\\usepackage{longtable}\n') - modified.write('\\usepackage{booktabs}\n') - modified.write('\\begin{document}\n\n') - modified.write(data) - modified.write('\n\\end{document}') - - def get_pandas_dataframe(self, groups='all', nuclides='all', - xs_type='macro', paths=True, - delayed_groups='all'): - """Build a Pandas DataFrame for the MDGXS data. - - This method leverages :meth:`openmc.Tally.get_pandas_dataframe`, but - renames the columns with terminology appropriate for cross section data. - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U-235', 'U-238']). - The special string 'all' will include the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - include the cross sections summed over all nuclides. Defaults - to 'all'. - xs_type: {'macro', 'micro'} - Return macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into - a Multi-index column with a geometric "path" to each distribcell - instance. - delayed_groups : list of int or 'all' - Delayed groups of interest. Defaults to 'all'. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame for the cross section data. - - Raises - ------ - ValueError - When this method is called before the multi-delayed-group cross - section is computed from tally data. - - """ - - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - if nuclides != 'all' and nuclides != 'sum': - cv.check_iterable_type('nuclides', nuclides, str) - if not isinstance(delayed_groups, str): - cv.check_type('delayed groups', delayed_groups, list, int) - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Get a Pandas DataFrame from the derived xs tally - if self.by_nuclide and nuclides == 'sum': - - # Use tally summation to sum across all nuclides - xs_tally = self.xs_tally.summation(nuclides=self.get_nuclides()) - df = xs_tally.get_pandas_dataframe(paths=paths) - - # Remove nuclide column since it is homogeneous and redundant - if self.domain_type == 'mesh': - df.drop('sum(nuclide)', axis=1, level=0, inplace=True) - else: - df.drop('sum(nuclide)', axis=1, inplace=True) - - # If the user requested a specific set of nuclides - elif self.by_nuclide and nuclides != 'all': - xs_tally = self.xs_tally.get_slice(nuclides=nuclides) - df = xs_tally.get_pandas_dataframe(paths=paths) - - # If the user requested all nuclides, keep nuclide column in dataframe - else: - df = self.xs_tally.get_pandas_dataframe(paths=paths) - - # Remove the score column since it is homogeneous and redundant - if self.domain_type == 'mesh': - df = df.drop('score', axis=1, level=0) - else: - df = df.drop('score', axis=1) - - # Convert azimuthal, polar, energy in and energy out bin values in to - # bin indices - columns = self._df_convert_columns_to_bins(df) - - # Select out those groups the user requested - if not isinstance(groups, str): - if 'group in' in df: - df = df[df['group in'].isin(groups)] - if 'group out' in df: - df = df[df['group out'].isin(groups)] - - # If user requested micro cross sections, divide out the atom densities - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - densities = np.repeat(densities, len(self.rxn_rate_tally.scores)) - tile_factor = int(df.shape[0] / len(densities)) - df['mean'] /= np.tile(densities, tile_factor) - df['std. dev.'] /= np.tile(densities, tile_factor) - - # Sort the dataframe by domain type id (e.g., distribcell id) and - # energy groups such that data is from fast to thermal - if self.domain_type == 'mesh': - mesh_str = 'mesh {0}'.format(self.domain.id) - df.sort_values(by=[(mesh_str, 'x'), (mesh_str, 'y'), - (mesh_str, 'z')] + columns, inplace=True) - else: - df.sort_values(by=[self.domain_type] + columns, inplace=True) - - return df - - -class ChiDelayed(MDGXS): - r"""The delayed fission spectrum. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group and multi-delayed-group cross sections for multi-group - neutronics calculations. At a minimum, one needs to set the - :attr:`ChiDelayed.energy_groups` and :attr:`ChiDelayed.domain` properties. - Tallies for the flux and appropriate reaction rates over the specified - domain are generated automatically via the :attr:`ChiDelayed.tallies` - property, which can then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross - section can then be obtained from the :attr:`ChiDelayed.xs_tally` property. - - For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and - delayed group :math:`d`, the delayed fission spectrum is calculated as: - - .. math:: - - \begin{aligned} - \langle \nu^d \sigma_{f,g' \rightarrow g} \phi \rangle &= \int_{r \in V} - dr \int_{4\pi} d\Omega' \int_0^\infty dE' \int_{E_g}^{E_{g-1}} dE \; - \chi(E) \nu^d \sigma_f (r, E') \psi(r, E', \Omega')\\ - \langle \nu^d \sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu^d \sigma_f (r, - E') \psi(r, E', \Omega') \\ - \chi_g^d &= \frac{\langle \nu^d \sigma_{f,g' \rightarrow g} \phi \rangle} - {\langle \nu^d \sigma_f \phi \rangle} - \end{aligned} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`ChiDelayed.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. When the This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, delayed_groups, - by_nuclide, name, num_polar, num_azimuthal) - self._rxn_type = 'chi-delayed' - self._estimator = 'analog' - - @property - def scores(self): - return ['delayed-nu-fission', 'delayed-nu-fission'] - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energyout = openmc.EnergyoutFilter(group_edges) - energyin = openmc.EnergyFilter([group_edges[0], group_edges[-1]]) - if self.delayed_groups is not None: - delayed_filter = openmc.DelayedGroupFilter(self.delayed_groups) - filters = [[delayed_filter, energyin], [delayed_filter, energyout]] - else: - filters = [[energyin], [energyout]] - - return self._add_angle_filters(filters) - - @property - def tally_keys(self): - return ['delayed-nu-fission-in', 'delayed-nu-fission-out'] - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies['delayed-nu-fission-out'] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - @property - def xs_tally(self): - - if self._xs_tally is None: - delayed_nu_fission_in = self.tallies['delayed-nu-fission-in'] - - # Remove coarse energy filter to keep it out of tally arithmetic - energy_filter = delayed_nu_fission_in.find_filter( - openmc.EnergyFilter) - delayed_nu_fission_in.remove_filter(energy_filter) - - # Compute chi - self._xs_tally = self.rxn_rate_tally / delayed_nu_fission_in - super()._compute_xs() - - # Add the coarse energy filter back to the nu-fission tally - delayed_nu_fission_in.filters.append(energy_filter) - - return self._xs_tally - - def get_homogenized_mgxs(self, other_mgxs): - """Construct a homogenized MGXS with other MGXS objects. - - This method constructs a new MGXS object that is the flux-weighted - combination of two MGXS objects. It is equivalent to what one would - obtain if the tally spatial domain were designed to encompass the - individual domains for both MGXS objects. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - return self._get_homogenized_mgxs(other_mgxs, 'delayed-nu-fission-in') - - - def get_slice(self, nuclides=[], groups=[], delayed_groups=[]): - """Build a sliced ChiDelayed for the specified nuclides and energy - groups. - - This method constructs a new MGXS to encapsulate a subset of the data - represented by this MGXS. The subset of data to include in the tally - slice is determined by the nuclides and energy groups specified in - the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U-235', 'U-238']; default is []) - groups : list of Integral - A list of energy group indices starting at 1 for the high energies - (e.g., [1, 2, 3]; default is []) - delayed_groups : list of int - A list of delayed group indices - (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MDGXS - A new MDGXS which encapsulates the subset of data requested - for the nuclide(s) and/or energy group(s) and/or delayed group(s) - requested in the parameters. - - """ - - # Temporarily remove energy filter from delayed-nu-fission-in since its - # group structure will work in super MGXS.get_slice(...) method - delayed_nu_fission_in = self.tallies['delayed-nu-fission-in'] - energy_filter = delayed_nu_fission_in.find_filter(openmc.EnergyFilter) - delayed_nu_fission_in.remove_filter(energy_filter) - - # Call super class method and null out derived tallies - slice_xs = super().get_slice(nuclides, groups, delayed_groups) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice energy groups if needed - filters = [] - filter_bins = [] - - if len(groups) != 0: - energy_bins = [] - for group in groups: - group_bounds = self.energy_groups.get_group_bounds(group) - energy_bins.append(group_bounds) - filter_bins.append(tuple(energy_bins)) - filters.append(openmc.EnergyoutFilter) - - if len(delayed_groups) != 0: - filter_bins.append(tuple(delayed_groups)) - filters.append(openmc.DelayedGroupFilter) - - if filters != []: - - # Slice nu-fission-out tally along energyout filter - delayed_nu_fission_out = slice_xs.tallies['delayed-nu-fission-out'] - tally_slice = delayed_nu_fission_out.get_slice \ - (filters=filters, filter_bins=filter_bins) - slice_xs._tallies['delayed-nu-fission-out'] = tally_slice - - # Add energy filter back to nu-fission-in tallies - self.tallies['delayed-nu-fission-in'].add_filter(energy_filter) - slice_xs._tallies['delayed-nu-fission-in'].add_filter(energy_filter) - - slice_xs.sparse = self.sparse - return slice_xs - - def merge(self, other): - """Merge another ChiDelayed with this one - - If results have been loaded from a statepoint, then ChiDelayed are only - mergeable along one and only one of energy groups or nuclides. - - Parameters - ---------- - other : openmc.mdgxs.MGXS - MGXS to merge with this one - - Returns - ------- - merged_mdgxs : openmc.mgxs.MDGXS - Merged MDGXS - """ - - if not self.can_merge(other): - raise ValueError('Unable to merge ChiDelayed') - - # Create deep copy of tally to return as merged tally - merged_mdgxs = copy.deepcopy(self) - merged_mdgxs._derived = True - merged_mdgxs._rxn_rate_tally = None - merged_mdgxs._xs_tally = None - - # Merge energy groups - if self.energy_groups != other.energy_groups: - merged_groups = self.energy_groups.merge(other.energy_groups) - merged_mdgxs.energy_groups = merged_groups - - # Merge delayed groups - if self.delayed_groups != other.delayed_groups: - merged_mdgxs.delayed_groups = list(set(self.delayed_groups + - other.delayed_groups)) - - # Merge nuclides - if self.nuclides != other.nuclides: - - # The nuclides must be mutually exclusive - for nuclide in self.nuclides: - if nuclide in other.nuclides: - msg = 'Unable to merge Chi Delayed with shared nuclides' - raise ValueError(msg) - - # Concatenate lists of nuclides for the merged MGXS - merged_mdgxs.nuclides = self.nuclides + other.nuclides - - # Merge tallies - for tally_key in self.tallies: - merged_tally = self.tallies[tally_key].merge\ - (other.tallies[tally_key]) - merged_mdgxs.tallies[tally_key] = merged_tally - - return merged_mdgxs - - def get_xs(self, groups='all', subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - value='mean', delayed_groups='all', squeeze=True, **kwargs): - """Returns an array of the delayed fission spectrum. - - This method constructs a 4D NumPy array for the requested - multi-delayed-group cross section data for one or more - subdomains (1st dimension), delayed groups (2nd demension), - energy groups (3rd dimension), and nuclides (4th dimension). - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - delayed_groups : list of int or 'all' - Delayed groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U-235', 'U-238']). The - special string 'all' will return the cross sections for all nuclides - in the spatial domain. The special string 'sum' will return the - cross section summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - This parameter is not relevant for chi but is included here to - mirror the parent MGXS.get_xs(...) class method - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group and multi-delayed-group cross - section indexed in the order each group, subdomain and nuclide is - listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - for subdomain in subdomains: - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - filter_bins.append((subdomain,)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - for group in groups: - filters.append(openmc.EnergyoutFilter) - filter_bins.append( - (self.energy_groups.get_group_bounds(group),)) - - # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, str): - cv.check_type('delayed groups', delayed_groups, list, int) - for delayed_group in delayed_groups: - filters.append(openmc.DelayedGroupFilter) - filter_bins.append((delayed_group,)) - - # If chi delayed was computed for each nuclide in the domain - if self.by_nuclide: - - # Get the sum as the fission source weighted average chi for all - # nuclides in the domain - if nuclides == 'sum' or nuclides == ['sum']: - - # Retrieve the fission production tallies - delayed_nu_fission_in = self.tallies['delayed-nu-fission-in'] - delayed_nu_fission_out = self.tallies['delayed-nu-fission-out'] - - # Sum out all nuclides - nuclides = self.get_nuclides() - delayed_nu_fission_in = delayed_nu_fission_in.summation\ - (nuclides=nuclides) - delayed_nu_fission_out = delayed_nu_fission_out.summation\ - (nuclides=nuclides) - - # Remove coarse energy filter to keep it out of tally arithmetic - energy_filter = delayed_nu_fission_in.find_filter( - openmc.EnergyFilter) - delayed_nu_fission_in.remove_filter(energy_filter) - - # Compute chi and store it as the xs_tally attribute so we can - # use the generic get_xs(...) method - xs_tally = delayed_nu_fission_out / delayed_nu_fission_in - - # Add the coarse energy filter back to the nu-fission tally - delayed_nu_fission_in.filters.append(energy_filter) - - xs = xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - - # Get chi delayed for all nuclides in the domain - elif nuclides == 'all': - nuclides = self.get_nuclides() - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=nuclides, value=value) - - # Get chi delayed for user-specified nuclides in the domain - else: - cv.check_iterable_type('nuclides', nuclides, str) - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=nuclides, value=value) - - # If chi delayed was computed as an average of nuclides in the domain - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - # Reshape tally data array with separate axes for domain and energy - if groups == 'all': - num_groups = self.num_groups - else: - num_groups = len(groups) - - if delayed_groups == 'all': - num_delayed_groups = self.num_delayed_groups - else: - num_delayed_groups = len(delayed_groups) - - # Reshape tally data array with separate axes for domain, energy - # groups, and accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_delayed_groups * - num_groups * self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_delayed_groups, num_groups) - else: - new_shape = (num_subdomains, num_delayed_groups, num_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # and energy group data. - xs = self._squeeze_xs(xs) - - return xs - - -class DelayedNuFissionXS(MDGXS): - r"""A fission delayed neutron production multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group fission neutron production cross sections for multi-group - neutronics calculations. At a minimum, one needs to set the - :attr:`DelayedNuFissionXS.energy_groups` and :attr:`DelayedNuFissionXS.domain` - properties. Tallies for the flux and appropriate reaction rates over the - specified domain are generated automatically via the - :attr:`DelayedNuFissionXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`DelayedNuFissionXS.xs_tally` property. - - For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and - delayed group :math:`d`, the fission delayed neutron production cross - section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \nu^d \sigma_f (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`DelayedNuFissionXS.tally_keys` property - and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. When the This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, delayed_groups, - by_nuclide, name, num_polar, num_azimuthal) - self._rxn_type = 'delayed-nu-fission' - - -class Beta(MDGXS): - r"""The delayed neutron fraction. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group and multi-delayed group cross sections for multi-group - neutronics calculations. At a minimum, one needs to set the - :attr:`Beta.energy_groups` and :attr:`Beta.domain` properties. Tallies for - the flux and appropriate reaction rates over the specified domain are - generated automatically via the :attr:`Beta.tallies` property, which can - then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`Beta.xs_tally` property. - - For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and - delayed group :math:`d`, the delayed neutron fraction is calculated as: - - .. math:: - - \begin{aligned} - \langle \nu^d \sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu^d - \sigma_f (r, E') \psi(r, E', \Omega') \\ - \langle \nu \sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu - \sigma_f (r, E') \psi(r, E', \Omega') \\ - \beta_{d,g} &= \frac{\langle \nu^d \sigma_f \phi \rangle} - {\langle \nu \sigma_f \phi \rangle} - \end{aligned} - - NOTE: The Beta MGXS is the delayed neutron fraction computed directly from - the nuclear data. Often the delayed neutron fraction is - "importance-weighted" by the adjoint flux and called "beta-effective". It - is important to make clear that this Beta is not importance-weighted. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`Beta.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. When the This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, delayed_groups, - by_nuclide, name, num_polar, num_azimuthal) - self._rxn_type = 'beta' - - @property - def scores(self): - return ['nu-fission', 'delayed-nu-fission'] - - @property - def tally_keys(self): - return ['nu-fission', 'delayed-nu-fission'] - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies['delayed-nu-fission'] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - @property - def xs_tally(self): - - if self._xs_tally is None: - nu_fission = self.tallies['nu-fission'] - - # Compute beta - self._xs_tally = self.rxn_rate_tally / nu_fission - super()._compute_xs() - - return self._xs_tally - - def get_homogenized_mgxs(self, other_mgxs): - """Construct a homogenized MGXS with other MGXS objects. - - This method constructs a new MGXS object that is the flux-weighted - combination of two MGXS objects. It is equivalent to what one would - obtain if the tally spatial domain were designed to encompass the - individual domains for both MGXS objects. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - return self._get_homogenized_mgxs(other_mgxs, 'nu-fission') - - -class DecayRate(MDGXS): - r"""The decay rate for delayed neutron precursors. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group and multi-delayed group cross sections for multi-group - neutronics calculations. At a minimum, one needs to set the - :attr:`DecayRate.energy_groups` and :attr:`DecayRate.domain` properties. - Tallies for the flux and appropriate reaction rates over the specified - domain are generated automatically via the :attr:`DecayRate.tallies` - property, which can then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`DecayRate.xs_tally` property. - - For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and - delayed group :math:`d`, the decay rate is calculated as: - - .. math:: - - \begin{aligned} - \langle \lambda_d \nu^d \sigma_f \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \lambda_d \nu^d - \sigma_f (r, E') \psi(r, E', \Omega') \\ - \langle \nu^d \sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu^d - \sigma_f (r, E') \psi(r, E', \Omega') \\ - \lambda_d &= \frac{\langle \lambda_d \nu^d \sigma_f \phi \rangle} - {\langle \nu^d \sigma_f \phi \rangle} - \end{aligned} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`DecayRate.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. When the This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, delayed_groups, - by_nuclide, name, num_polar, num_azimuthal) - self._rxn_type = 'decay-rate' - - @property - def scores(self): - return ['delayed-nu-fission', 'decay-rate'] - - @property - def tally_keys(self): - return ['delayed-nu-fission', 'decay-rate'] - - @property - def filters(self): - - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy_filter = openmc.EnergyFilter(group_edges) - - if self.delayed_groups is not None: - delayed_filter = openmc.DelayedGroupFilter(self.delayed_groups) - filters = [[delayed_filter, energy_filter], [delayed_filter, - energy_filter]] - else: - filters = [[energy_filter], [energy_filter]] - - return self._add_angle_filters(filters) - - @property - def xs_tally(self): - - if self._xs_tally is None: - delayed_nu_fission = self.tallies['delayed-nu-fission'] - - # Compute the decay rate - self._xs_tally = self.rxn_rate_tally / delayed_nu_fission - super()._compute_xs() - - return self._xs_tally - - def get_homogenized_mgxs(self, other_mgxs): - """Construct a homogenized MGXS with other MGXS objects. - - This method constructs a new MGXS object that is the flux-weighted - combination of two MGXS objects. It is equivalent to what one would - obtain if the tally spatial domain were designed to encompass the - individual domains for both MGXS objects. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - return self._get_homogenized_mgxs(other_mgxs, 'delayed-nu-fission') - - -class MatrixMDGXS(MDGXS): - """An abstract multi-delayed-group cross section for some energy group and - delayed group structure within some spatial domain. This class is - specifically intended for cross sections which depend on both the incoming - and outgoing energy groups and are therefore represented by matrices. - An example of this is the delayed-nu-fission matrix. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group and multi-delayed-group cross sections for downstream neutronics - calculations. - - NOTE: Users should instantiate the subclasses of this abstract class. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - return (0, 1, 3, 4, 5) - else: - return (1, 2, 3) - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - - if self.delayed_groups is not None: - delayed = openmc.DelayedGroupFilter(self.delayed_groups) - filters = [[energy], [delayed, energy, energyout]] - else: - filters = [[energy], [energy, energyout]] - - return self._add_angle_filters(filters) - - def get_xs(self, in_groups='all', out_groups='all', - subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - row_column='inout', value='mean', delayed_groups='all', - squeeze=True, **kwargs): - """Returns an array of multi-group cross sections. - - This method constructs a 4D NumPy array for the requested - multi-group cross section data for one or more subdomains - (1st dimension), delayed groups (2nd dimension), energy groups in - (3rd dimension), energy groups out (4th dimension), and nuclides - (5th dimension). - - Parameters - ---------- - in_groups : Iterable of Integral or 'all' - Incoming energy groups of interest. Defaults to 'all'. - out_groups : Iterable of Integral or 'all' - Outgoing energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - return the cross section summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - row_column: {'inout', 'outin'} - Return the cross section indexed first by incoming group and - second by outgoing group ('inout'), or vice versa ('outin'). - Defaults to 'inout'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - delayed_groups : list of int or 'all' - Delayed groups of interest. Defaults to 'all'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group and subdomain is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - for subdomain in subdomains: - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - filter_bins.append((subdomain,)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, str): - cv.check_iterable_type('groups', in_groups, Integral) - for group in in_groups: - filters.append(openmc.EnergyFilter) - filter_bins.append(( - self.energy_groups.get_group_bounds(group),)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, str): - cv.check_iterable_type('groups', out_groups, Integral) - for group in out_groups: - filters.append(openmc.EnergyoutFilter) - filter_bins.append(( - self.energy_groups.get_group_bounds(group),)) - - # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, str): - cv.check_type('delayed groups', delayed_groups, list, int) - for delayed_group in delayed_groups: - filters.append(openmc.DelayedGroupFilter) - filter_bins.append((delayed_group,)) - - # Construct a collection of the nuclides to retrieve from the xs tally - if self.by_nuclide: - if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: - query_nuclides = self.get_nuclides() - else: - query_nuclides = nuclides - else: - query_nuclides = ['total'] - - # Use tally summation if user requested the sum for all nuclides - if nuclides == 'sum' or nuclides == ['sum']: - xs_tally = self.xs_tally.summation(nuclides=query_nuclides) - xs = xs_tally.get_values(filters=filters, filter_bins=filter_bins, - value=value) - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=query_nuclides, value=value) - - # Divide by atom number densities for microscopic cross sections - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - if value == 'mean' or value == 'std_dev': - xs /= densities[np.newaxis, :, np.newaxis] - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - if in_groups == 'all': - num_in_groups = self.num_groups - else: - num_in_groups = len(in_groups) - - if out_groups == 'all': - num_out_groups = self.num_groups - else: - num_out_groups = len(out_groups) - - if delayed_groups == 'all': - num_delayed_groups = self.num_delayed_groups - else: - num_delayed_groups = len(delayed_groups) - - # Reshape tally data array with separate axes for domain and energy - # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_delayed_groups * - num_in_groups * num_out_groups * - self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_delayed_groups, num_in_groups, num_out_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 4, 5) - else: - new_shape = (num_subdomains, num_delayed_groups, num_in_groups, - num_out_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 2, 3) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # and in/out energy group data. - xs = self._squeeze_xs(xs) - - return xs - - def get_slice(self, nuclides=[], in_groups=[], out_groups=[], - delayed_groups=[]): - """Build a sliced MatrixMDGXS object for the specified nuclides and - energy groups. - - This method constructs a new MdGXS to encapsulate a subset of the data - represented by this MdGXS. The subset of data to include in the tally - slice is determined by the nuclides, energy groups, and delayed groups - specified in the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - in_groups : list of int - A list of incoming energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - out_groups : list of int - A list of outgoing energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - delayed_groups : list of int - A list of delayed group indices - (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MatrixMDGXS - A new MatrixMDGXS object which encapsulates the subset of data - requested for the nuclide(s) and/or energy group(s) requested in - the parameters. - - """ - - # Call super class method and null out derived tallies - slice_xs = super().get_slice(nuclides, in_groups, delayed_groups) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice outgoing energy groups if needed - if len(out_groups) != 0: - filter_bins = [] - for group in out_groups: - group_bounds = self.energy_groups.get_group_bounds(group) - filter_bins.append(group_bounds) - filter_bins = [tuple(filter_bins)] - - # Slice each of the tallies across energyout groups - for tally_type, tally in slice_xs.tallies.items(): - if tally.contains_filter(openmc.EnergyoutFilter): - tally_slice = tally.get_slice( - filters=[openmc.EnergyoutFilter], - filter_bins=filter_bins) - slice_xs.tallies[tally_type] = tally_slice - - slice_xs.sparse = self.sparse - return slice_xs - - def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): - """Prints a string representation for the multi-group cross section. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - report the cross sections summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - - """ - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'mesh': - xyz = [range(1, x + 1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - if nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Build header for string with type and domain info - string = 'Multi-Delayed-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) - - # Generate the header for an individual XS - xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) - - # If cross section data has not been computed, only print string header - if self.tallies is None: - print(string) - return - - string += '{0: <16}\n'.format('\tEnergy Groups:') - template = '{0: <12}Group {1} [{2: <10} - {3: <10}eV]\n' - - # Loop over energy groups ranges - for group in range(1, self.num_groups + 1): - bounds = self.energy_groups.get_group_bounds(group) - string += template.format('', group, bounds[0], bounds[1]) - - # Set polar and azimuthal bins if necessary - if self.num_polar > 1 or self.num_azimuthal > 1: - pol_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azi_bins = np.linspace(-np.pi, np.pi, num=self.num_azimuthal + 1, - endpoint=True) - - # Loop over all subdomains - for subdomain in subdomains: - - if self.domain_type == 'distribcell': - string += '{: <16}=\t{}\n'.format('\tSubdomain', subdomain) - - # Loop over all Nuclides - for nuclide in nuclides: - - # Build header for nuclide type - if xs_type != 'sum': - string += '{: <16}=\t{}\n'.format('\tNuclide', nuclide) - - # Build header for cross section type - string += '{: <16}\n'.format(xs_header) - - if self.delayed_groups is not None: - - for delayed_group in self.delayed_groups: - - template = '{0: <12}Delayed Group {1}:\t' - string += template.format('', delayed_group) - string += '\n' - - template = '{0: <12}Group {1} -> Group {2}:\t\t' - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean', - delayed_groups=[delayed_group]) - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, - value='rel_err', - delayed_groups=[delayed_group]) - rel_err_xs = rel_err_xs * 100. - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azi, and in/out group ranges - for pol in range(len(pol_bins) - 1): - pol_low, pol_high = pol_bins[pol: pol + 2] - for azi in range(len(azi_bins) - 1): - azi_low, azi_high = azi_bins[azi: azi + 2] - string += '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += '\t' + template.format( - '', in_group, out_group) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[pol, azi, in_group - 1, - out_group - 1], - rel_err_xs[pol, azi, in_group - 1, - out_group - 1]) - string += '\n' - string += '\n' - string += '\n' - else: - # Loop over incoming/outgoing energy groups ranges - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += template.format( - '', in_group, out_group) - string += '{:.2e} +/- {:.2e}%'.format( - average_xs[in_group-1, out_group-1], - rel_err_xs[in_group-1, out_group-1]) - string += '\n' - string += '\n' - string += '\n' - else: - - template = '{0: <12}Group {1} -> Group {2}:\t\t' - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean') - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='rel_err') - rel_err_xs = rel_err_xs * 100. - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azi, and in/out energy group ranges - for pol in range(len(pol_bins) - 1): - pol_low, pol_high = pol_bins[pol: pol + 2] - for azi in range(len(azi_bins) - 1): - azi_low, azi_high = azi_bins[azi: azi + 2] - string += '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += '\t' + template.format( - '', in_group, out_group) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[pol, azi, in_group - 1, - out_group - 1], - rel_err_xs[pol, azi, in_group - 1, - out_group - 1]) - string += '\n' - string += '\n' - string += '\n' - else: - # Loop over incoming/outgoing energy groups ranges - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += template.format('', in_group, - out_group) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[in_group - 1, out_group - 1], - rel_err_xs[in_group - 1, out_group - 1]) - string += '\n' - string += '\n' - string += '\n' - string += '\n' - string += '\n' - - print(string) - - -class DelayedNuFissionMatrixXS(MatrixMDGXS): - r"""A fission delayed neutron production matrix multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group fission neutron production cross sections for multi-group - neutronics calculations. At a minimum, one needs to set the - :attr:`DelayedNuFissionMatrixXS.energy_groups` and - :attr:`DelayedNuFissionMatrixXS.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`DelayedNuFissionMatrixXS.tallies` property, - which can then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`DelayedNuFissionMatrixXS.xs_tally` - property. - - For a spatial domain :math:`V`, energy group :math:`[E_g,E_{g-1}]`, and - delayed group :math:`d`, the fission delayed neutron production cross - section is calculated as: - - .. math:: - - \begin{aligned} - \langle \nu\sigma_{f,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{E_g}^{E_{g-1}} dE - \; \chi(E) \nu\sigma_f^d (r, E') \psi(r, E', \Omega')\\ - \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ - \nu\sigma_{f,g'\rightarrow g} &= \frac{\langle \nu\sigma_{f,g'\rightarrow - g}^d \phi \rangle}{\langle \phi \rangle} - \end{aligned} - - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`DelayedNuFissionXS.tally_keys` property - and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. When the This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, energy_groups=None, - delayed_groups=None, by_nuclide=False, name='', - num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, energy_groups, delayed_groups, - by_nuclide, name, num_polar, num_azimuthal) - self._rxn_type = 'delayed-nu-fission' - self._hdf5_key = 'delayed-nu-fission matrix' - self._estimator = 'analog' - self._valid_estimators = ['analog'] diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py deleted file mode 100644 index e9fee5a2f..000000000 --- a/openmc/mgxs/mgxs.py +++ /dev/null @@ -1,5909 +0,0 @@ -from collections import OrderedDict -from numbers import Integral -import warnings -import os -import copy -from abc import ABCMeta - -import numpy as np -import h5py - -import openmc -import openmc.checkvalue as cv -from openmc.tallies import ESTIMATOR_TYPES -from openmc.mgxs import EnergyGroups - - -# Supported cross section types -MGXS_TYPES = ['total', - 'transport', - 'nu-transport', - 'absorption', - 'capture', - 'fission', - 'nu-fission', - 'kappa-fission', - 'scatter', - 'nu-scatter', - 'scatter matrix', - 'nu-scatter matrix', - 'multiplicity matrix', - 'nu-fission matrix', - 'scatter probability matrix', - 'consistent scatter matrix', - 'consistent nu-scatter matrix', - 'chi', - 'chi-prompt', - 'inverse-velocity', - 'prompt-nu-fission', - 'prompt-nu-fission matrix'] - -# Supported domain types -DOMAIN_TYPES = ['cell', - 'distribcell', - 'universe', - 'material', - 'mesh'] - -# Filter types corresponding to each domain -_DOMAIN_TO_FILTER = {'cell': openmc.CellFilter, - 'distribcell': openmc.DistribcellFilter, - 'universe': openmc.UniverseFilter, - 'material': openmc.MaterialFilter, - 'mesh': openmc.MeshFilter} - -# Supported domain classes -_DOMAINS = (openmc.Cell, - openmc.Universe, - openmc.Material, - openmc.RegularMesh) - -# Supported ScatterMatrixXS angular distribution types -MU_TREATMENTS = ('legendre', 'histogram') - -# Maximum Legendre order supported by OpenMC -_MAX_LEGENDRE = 10 - - -def _df_column_convert_to_bin(df, current_name, new_name, values_to_bin, - reverse_order=False): - """Convert a Pandas DataFrame column from the bin edges to an index for - each bin. This method operates on the DataFrame, df, in-place. - - Parameters - ---------- - df : pandas.DataFrame - A Pandas DataFrame containing the cross section data. - current_name : str - Name of the column to replace with bins - new_name : str - New name for column after the data is replaced with bins - values_to_bin : Iterable of Real - Values of the bin edges to be used for identifying the bins - reverse_order : bool - Whether the bin indices should be reversed - - """ - - # Get the current values - df_bins = np.asarray(df[current_name]) - new_vals = np.zeros_like(df_bins, dtype=int) - # Replace the values with the index of the closest entry in values_to_bin - # The closest is used because it is expected that the values in df could - # have lost precision along the way - for i, df_val in enumerate(df_bins): - idx = np.searchsorted(values_to_bin, df_val) - # Check to make sure if the value is just above the search result - if idx > 0 and np.isclose(values_to_bin[idx - 1], df_val): - idx -= 1 - # If it is just below the search result then we are done - new_vals[i] = idx - # Switch to a one-based indexing - new_vals += 1 - - # Reverse the ordering if requested (this is for energy group ordering) - if reverse_order: - new_vals = (len(values_to_bin) - 1) - new_vals + 1 - - # Assign the values - df[current_name] = new_vals[:] - - # And rename the column - df.rename(columns={current_name: new_name}, inplace=True) - - -class MGXS(metaclass=ABCMeta): - """An abstract multi-group cross section for some energy group structure - within some spatial domain. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. - - .. note:: Users should instantiate the subclasses of this abstract class. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, - energy_groups=None, by_nuclide=False, name='', num_polar=1, - num_azimuthal=1): - self._name = '' - self._rxn_type = None - self._by_nuclide = None - self._nuclides = None - self._estimator = 'tracklength' - self._domain = None - self._domain_type = None - self._energy_groups = None - self._num_polar = 1 - self._num_azimuthal = 1 - self._tally_trigger = None - self._tallies = None - self._rxn_rate_tally = None - self._xs_tally = None - self._sparse = False - self._loaded_sp = False - self._derived = False - self._hdf5_key = None - self._valid_estimators = ESTIMATOR_TYPES - - self.name = name - self.by_nuclide = by_nuclide - - if domain_type is not None: - self.domain_type = domain_type - if domain is not None: - self.domain = domain - if energy_groups is not None: - self.energy_groups = energy_groups - self.num_polar = num_polar - self.num_azimuthal = num_azimuthal - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, copy it - if existing is None: - clone = type(self).__new__(type(self)) - clone._name = self.name - clone._rxn_type = self.rxn_type - clone._by_nuclide = self.by_nuclide - clone._nuclides = copy.deepcopy(self._nuclides, memo) - clone._domain = self.domain - clone._domain_type = self.domain_type - clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._num_polar = self._num_polar - clone._num_azimuthal = self._num_azimuthal - clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) - clone._rxn_rate_tally = copy.deepcopy(self._rxn_rate_tally, memo) - clone._xs_tally = copy.deepcopy(self._xs_tally, memo) - clone._sparse = self.sparse - clone._loaded_sp = self._loaded_sp - clone._derived = self.derived - clone._hdf5_key = self._hdf5_key - - clone._tallies = OrderedDict() - for tally_type, tally in self.tallies.items(): - clone.tallies[tally_type] = copy.deepcopy(tally, memo) - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - def _add_angle_filters(self, filters): - """Add the azimuthal and polar bins to the MGXS filters if needed. - Filters will be provided as a ragged 2D list of openmc.Filter objects. - - Parameters - ---------- - filters : Iterable of Iterable of openmc.Filter - Ragged 2D list of openmc.Filter objects for the energy and spatial - domains. The angle filters will be added to the list. - - Returns - ------- - Iterable of Iterable of openmc.Filter - Ragged 2D list of openmc.Filter objects for the energy and spatial - domains with the angle filters added to the list. - - """ - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Then the user has requested angular data, so create the bins - pol_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azi_bins = np.linspace(-np.pi, np.pi, num=self.num_azimuthal + 1, - endpoint=True) - - for filt in filters: - filt.insert(0, openmc.PolarFilter(pol_bins)) - filt.insert(1, openmc.AzimuthalFilter(azi_bins)) - - return filters - - def _squeeze_xs(self, xs): - """Remove dimensions which are not needed from a cross section array - due to user options. This is used by the openmc.Mgxs.get_xs(...) method - - Parameters - ---------- - xs : np.ndarray - Cross sections array with dimensions to be squeezed - - Returns - ------- - np.ndarray - Squeezed array of cross sections - - """ - - # numpy.squeeze will return a ValueError if the axis has a size - # greater than 1, to avoid this we will try each axis one at a - # time to preclude the ValueError. - initial_shape = len(xs.shape) - for axis in range(initial_shape - 1, -1, -1): - if axis not in self._dont_squeeze and xs.shape[axis] == 1: - xs = np.squeeze(xs, axis=axis) - return xs - - def _df_convert_columns_to_bins(self, df): - """This method converts all relevant and present DataFrame columns from - their bin boundaries to the index for each bin. This method operates on - the DataFrame, df, in place. The method returns a list of the columns - in which it has operated on. - - Parameters - ---------- - df : pandas.DataFrame - A Pandas DataFrame containing the cross section data. - - Returns - ------- - columns : Iterable of str - Names of the re-named and re-valued columns - - """ - # Override polar and azimuthal bounds with indices - if self.num_polar > 1 or self.num_azimuthal > 1: - # First for polar - bins = np.linspace(0., np.pi, self.num_polar + 1, True) - _df_column_convert_to_bin(df, 'polar low', 'polar bin', bins) - del df['polar high'] - - # Second for azimuthal - bins = np.linspace(-np.pi, np.pi, self.num_azimuthal + 1, True) - _df_column_convert_to_bin(df, 'azimuthal low', 'azimuthal bin', - bins) - del df['azimuthal high'] - columns = ['polar bin', 'azimuthal bin'] - else: - columns = [] - - # Override energy groups bounds with indices - if 'energy low [eV]' in df: - _df_column_convert_to_bin(df, 'energy low [eV]', 'group in', - self.energy_groups.group_edges, - reverse_order=True) - del df['energy high [eV]'] - columns += ['group in'] - if 'energyout low [eV]' in df: - _df_column_convert_to_bin(df, 'energyout low [eV]', 'group out', - self.energy_groups.group_edges, - reverse_order=True) - del df['energyout high [eV]'] - columns += ['group out'] - - if 'mu low' in df and hasattr(self, 'histogram_bins'): - # Only the ScatterMatrix class has the histogram_bins attribute - bins = np.linspace(-1., 1., self.histogram_bins + 1, True) - _df_column_convert_to_bin(df, 'mu low', 'mu bin', bins) - del df['mu high'] - columns += ['mu bin'] - - return columns - - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - return (0, 1, 3) - else: - return (1, ) - - @property - def name(self): - return self._name - - @property - def rxn_type(self): - return self._rxn_type - - @property - def by_nuclide(self): - return self._by_nuclide - - @property - def domain(self): - return self._domain - - @property - def domain_type(self): - return self._domain_type - - @property - def energy_groups(self): - return self._energy_groups - - @property - def num_polar(self): - return self._num_polar - - @property - def num_azimuthal(self): - return self._num_azimuthal - - @property - def tally_trigger(self): - return self._tally_trigger - - @property - def num_groups(self): - return self.energy_groups.num_groups - - @property - def scores(self): - return ['flux', self.rxn_type] - - @property - def filters(self): - group_edges = self.energy_groups.group_edges - energy_filter = openmc.EnergyFilter(group_edges) - filters = [] - for i in range(len(self.scores)): - filters.append([energy_filter]) - - return self._add_angle_filters(filters) - - @property - def tally_keys(self): - return self.scores - - @property - def estimator(self): - return self._estimator - - @property - def tallies(self): - - # Instantiate tallies if they do not exist - if self._tallies is None: - - # Initialize a collection of Tallies - self._tallies = OrderedDict() - - # Create a domain Filter object - filter_type = _DOMAIN_TO_FILTER[self.domain_type] - if self.domain_type == 'mesh': - domain_filter = filter_type(self.domain) - else: - domain_filter = filter_type(self.domain.id) - - if isinstance(self.estimator, str): - estimators = [self.estimator] * len(self.scores) - else: - estimators = self.estimator - - # Create each Tally needed to compute the multi group cross section - tally_metadata = \ - zip(self.scores, self.tally_keys, self.filters, estimators) - for score, key, filters, estimator in tally_metadata: - self._tallies[key] = openmc.Tally(name=self.name) - self._tallies[key].scores = [score] - self._tallies[key].estimator = estimator - self._tallies[key].filters = [domain_filter] - - # If a tally trigger was specified, add it to each tally - if self.tally_trigger: - trigger_clone = copy.deepcopy(self.tally_trigger) - trigger_clone.scores = [score] - self._tallies[key].triggers.append(trigger_clone) - - # Add non-domain specific Filters (e.g., 'energy') to the Tally - for add_filter in filters: - self._tallies[key].filters.append(add_filter) - - # If this is a by-nuclide cross-section, add nuclides to Tally - if self.by_nuclide and score != 'flux': - self._tallies[key].nuclides += self.get_nuclides() - else: - self._tallies[key].nuclides.append('total') - - return self._tallies - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies[self.rxn_type] - self._rxn_rate_tally.sparse = self.sparse - - return self._rxn_rate_tally - - @property - def xs_tally(self): - if self._xs_tally is None: - if self.tallies is None: - msg = 'Unable to get xs_tally since tallies have ' \ - 'not been loaded from a statepoint' - raise ValueError(msg) - - self._xs_tally = self.rxn_rate_tally / self.tallies['flux'] - self._compute_xs() - - return self._xs_tally - - @property - def sparse(self): - return self._sparse - - @property - def num_subdomains(self): - if self.domain_type.startswith('sum('): - domain_type = self.domain_type[4:-1] - else: - domain_type = self.domain_type - filter_type = _DOMAIN_TO_FILTER[domain_type] - domain_filter = self.xs_tally.find_filter(filter_type) - return domain_filter.num_bins - - @property - def num_nuclides(self): - if self.by_nuclide: - return len(self.get_nuclides()) - else: - return 1 - - @property - def nuclides(self): - if self.by_nuclide: - return self.get_nuclides() - else: - return ['sum'] - - @property - def loaded_sp(self): - return self._loaded_sp - - @property - def derived(self): - return self._derived - - @property - def hdf5_key(self): - if self._hdf5_key is not None: - return self._hdf5_key - else: - return self._rxn_type - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @by_nuclide.setter - def by_nuclide(self, by_nuclide): - cv.check_type('by_nuclide', by_nuclide, bool) - self._by_nuclide = by_nuclide - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, str) - self._nuclides = nuclides - - @estimator.setter - def estimator(self, estimator): - cv.check_value('estimator', estimator, self._valid_estimators) - self._estimator = estimator - - @domain.setter - def domain(self, domain): - cv.check_type('domain', domain, _DOMAINS) - self._domain = domain - - # Assign a domain type - if self.domain_type is None: - if isinstance(domain, openmc.Material): - self._domain_type = 'material' - elif isinstance(domain, openmc.Cell): - self._domain_type = 'cell' - elif isinstance(domain, openmc.Universe): - self._domain_type = 'universe' - elif isinstance(domain, openmc.RegularMesh): - self._domain_type = 'mesh' - - @domain_type.setter - def domain_type(self, domain_type): - cv.check_value('domain type', domain_type, DOMAIN_TYPES) - self._domain_type = domain_type - - @energy_groups.setter - def energy_groups(self, energy_groups): - cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) - self._energy_groups = energy_groups - - @num_polar.setter - def num_polar(self, num_polar): - cv.check_type('num_polar', num_polar, Integral) - cv.check_greater_than('num_polar', num_polar, 0) - self._num_polar = num_polar - - @num_azimuthal.setter - def num_azimuthal(self, num_azimuthal): - cv.check_type('num_azimuthal', num_azimuthal, Integral) - cv.check_greater_than('num_azimuthal', num_azimuthal, 0) - self._num_azimuthal = num_azimuthal - - @tally_trigger.setter - def tally_trigger(self, tally_trigger): - cv.check_type('tally trigger', tally_trigger, openmc.Trigger) - self._tally_trigger = tally_trigger - - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within the Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - - # Sparsify or densify the derived MGXS tallies and the base tallies - if self._xs_tally: - self.xs_tally.sparse = sparse - if self._rxn_rate_tally: - self.rxn_rate_tally.sparse = sparse - - for tally_name in self.tallies: - self.tallies[tally_name].sparse = sparse - - self._sparse = sparse - - @staticmethod - def get_mgxs(mgxs_type, domain=None, domain_type=None, - energy_groups=None, by_nuclide=False, name='', num_polar=1, - num_azimuthal=1): - """Return a MGXS subclass object for some energy group structure within - some spatial domain for some reaction type. - - This is a factory method which can be used to quickly create MGXS - subclass objects for various reaction types. - - Parameters - ---------- - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix'} - The type of multi-group cross section object to return - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain. - Defaults to False - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. Defaults to the empty string. - num_polar : Integral, optional - Number of equi-width polar angles for angle discretization; - defaults to no discretization - num_azimuthal : Integral, optional - Number of equi-width azimuthal angles for angle discretization; - defaults to no discretization - - Returns - ------- - openmc.mgxs.MGXS - A subclass of the abstract MGXS class for the multi-group cross - section type requested by the user - - """ - - cv.check_value('mgxs_type', mgxs_type, MGXS_TYPES) - - if mgxs_type == 'total': - mgxs = TotalXS(domain, domain_type, energy_groups) - elif mgxs_type == 'transport': - mgxs = TransportXS(domain, domain_type, energy_groups) - elif mgxs_type == 'nu-transport': - mgxs = TransportXS(domain, domain_type, energy_groups, nu=True) - elif mgxs_type == 'absorption': - mgxs = AbsorptionXS(domain, domain_type, energy_groups) - elif mgxs_type == 'capture': - mgxs = CaptureXS(domain, domain_type, energy_groups) - elif mgxs_type == 'fission': - mgxs = FissionXS(domain, domain_type, energy_groups) - elif mgxs_type == 'nu-fission': - mgxs = FissionXS(domain, domain_type, energy_groups, nu=True) - elif mgxs_type == 'kappa-fission': - mgxs = KappaFissionXS(domain, domain_type, energy_groups) - elif mgxs_type == 'scatter': - mgxs = ScatterXS(domain, domain_type, energy_groups) - elif mgxs_type == 'nu-scatter': - mgxs = ScatterXS(domain, domain_type, energy_groups, nu=True) - elif mgxs_type == 'scatter matrix': - mgxs = ScatterMatrixXS(domain, domain_type, energy_groups) - elif mgxs_type == 'nu-scatter matrix': - mgxs = ScatterMatrixXS(domain, domain_type, energy_groups, nu=True) - elif mgxs_type == 'multiplicity matrix': - mgxs = MultiplicityMatrixXS(domain, domain_type, energy_groups) - elif mgxs_type == 'scatter probability matrix': - mgxs = ScatterProbabilityMatrix(domain, domain_type, energy_groups) - elif mgxs_type == 'consistent scatter matrix': - mgxs = ScatterMatrixXS(domain, domain_type, energy_groups) - mgxs.formulation = 'consistent' - elif mgxs_type == 'consistent nu-scatter matrix': - mgxs = ScatterMatrixXS(domain, domain_type, energy_groups, nu=True) - mgxs.formulation = 'consistent' - elif mgxs_type == 'nu-fission matrix': - mgxs = NuFissionMatrixXS(domain, domain_type, energy_groups) - elif mgxs_type == 'chi': - mgxs = Chi(domain, domain_type, energy_groups) - elif mgxs_type == 'chi-prompt': - mgxs = Chi(domain, domain_type, energy_groups, prompt=True) - elif mgxs_type == 'inverse-velocity': - mgxs = InverseVelocity(domain, domain_type, energy_groups) - elif mgxs_type == 'prompt-nu-fission': - mgxs = FissionXS(domain, domain_type, energy_groups, prompt=True) - elif mgxs_type == 'prompt-nu-fission matrix': - mgxs = NuFissionMatrixXS(domain, domain_type, energy_groups, - prompt=True) - - mgxs.by_nuclide = by_nuclide - mgxs.name = name - mgxs.num_polar = num_polar - mgxs.num_azimuthal = num_azimuthal - return mgxs - - def get_nuclides(self): - """Get all nuclides in the cross section's spatial domain. - - Returns - ------- - list of str - A list of the string names for each nuclide in the spatial domain - (e.g., ['U235', 'U238', 'O16']) - - Raises - ------ - ValueError - When this method is called before the spatial domain has been set. - - """ - - if self.domain is None: - raise ValueError('Unable to get all nuclides without a domain') - - # If the user defined nuclides, return them - if self._nuclides: - return self._nuclides - - # Otherwise, return all nuclides in the spatial domain - else: - return self.domain.get_nuclides() - - def get_nuclide_density(self, nuclide): - """Get the atomic number density in units of atoms/b-cm for a nuclide - in the cross section's spatial domain. - - Parameters - ---------- - nuclide : str - A nuclide name string (e.g., 'U235') - - Returns - ------- - float - The atomic number density (atom/b-cm) for the nuclide of interest - - """ - - cv.check_type('nuclide', nuclide, str) - - # Get list of all nuclides in the spatial domain - nuclides = self.domain.get_nuclide_densities() - - return nuclides[nuclide][1] if nuclide in nuclides else 0.0 - - def get_nuclide_densities(self, nuclides='all'): - """Get an array of atomic number densities in units of atom/b-cm for all - nuclides in the cross section's spatial domain. - - Parameters - ---------- - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the atom densities for all nuclides - in the spatial domain. The special string 'sum' will return the atom - density summed across all nuclides in the spatial domain. Defaults - to 'all'. - - Returns - ------- - numpy.ndarray of float - An array of the atomic number densities (atom/b-cm) for each of the - nuclides in the spatial domain - - Raises - ------ - ValueError - When this method is called before the spatial domain has been set. - - """ - - if self.domain is None: - raise ValueError('Unable to get nuclide densities without a domain') - - # Sum the atomic number densities for all nuclides - if nuclides == 'sum': - nuclides = self.get_nuclides() - densities = np.zeros(1, dtype=np.float) - for nuclide in nuclides: - densities[0] += self.get_nuclide_density(nuclide) - - # Tabulate the atomic number densities for all nuclides - elif nuclides == 'all': - nuclides = self.get_nuclides() - densities = np.zeros(self.num_nuclides, dtype=np.float) - for i, nuclide in enumerate(nuclides): - densities[i] += self.get_nuclide_density(nuclide) - - # Tabulate the atomic number densities for each specified nuclide - else: - densities = np.zeros(len(nuclides), dtype=np.float) - for i, nuclide in enumerate(nuclides): - densities[i] = self.get_nuclide_density(nuclide) - - return densities - - def _compute_xs(self): - """Performs generic cleanup after a subclass' uses tally arithmetic to - compute a multi-group cross section as a derived tally. - - This method replaces CrossNuclides generated by tally arithmetic with - the original Nuclide objects in the xs_tally instance attribute. The - simple Nuclides allow for cleaner output through Pandas DataFrames as - well as simpler data access through the get_xs(...) class method. - - In addition, this routine resets NaNs in the multi group cross section - array to 0.0. This may be needed occur if no events were scored in - certain tally bins, which will lead to a divide-by-zero situation. - - """ - - # If computing xs for each nuclide, replace CrossNuclides with originals - if self.by_nuclide: - self.xs_tally._nuclides = [] - nuclides = self.get_nuclides() - for nuclide in nuclides: - self.xs_tally.nuclides.append(openmc.Nuclide(nuclide)) - - # Remove NaNs which may have resulted from divide-by-zero operations - self.xs_tally._mean = np.nan_to_num(self.xs_tally.mean) - self.xs_tally._std_dev = np.nan_to_num(self.xs_tally.std_dev) - self.xs_tally.sparse = self.sparse - - def load_from_statepoint(self, statepoint): - """Extracts tallies in an OpenMC StatePoint with the data needed to - compute multi-group cross sections. - - This method is needed to compute cross section data from tallies - in an OpenMC StatePoint object. - - .. note:: The statepoint must be linked with an OpenMC Summary object. - - Parameters - ---------- - statepoint : openmc.StatePoint - An OpenMC StatePoint object with tally data - - Raises - ------ - ValueError - When this method is called with a statepoint that has not been - linked with a summary object. - - """ - - cv.check_type('statepoint', statepoint, openmc.StatePoint) - - if statepoint.summary is None: - msg = 'Unable to load data from a statepoint which has not been ' \ - 'linked with a summary file' - raise ValueError(msg) - - # Override the domain object that loaded from an OpenMC summary file - # NOTE: This is necessary for micro cross-sections which require - # the isotopic number densities as computed by OpenMC - su = statepoint.summary - if self.domain_type in ('cell', 'distribcell'): - self.domain = su._fast_cells[self.domain.id] - elif self.domain_type == 'universe': - self.domain = su._fast_universes[self.domain.id] - elif self.domain_type == 'material': - self.domain = su._fast_materials[self.domain.id] - elif self.domain_type == 'mesh': - self.domain = statepoint.meshes[self.domain.id] - else: - msg = 'Unable to load data from a statepoint for domain type {0} ' \ - 'which is not yet supported'.format(self.domain_type) - raise ValueError(msg) - - # Use tally "slicing" to ensure that tallies correspond to our domain - # NOTE: This is important if tally merging was used - if self.domain_type == 'mesh': - filters = [_DOMAIN_TO_FILTER[self.domain_type]] - filter_bins = [tuple(self.domain.indices)] - elif self.domain_type != 'distribcell': - filters = [_DOMAIN_TO_FILTER[self.domain_type]] - filter_bins = [(self.domain.id,)] - # Distribcell filters only accept single cell - neglect it when slicing - else: - filters = [] - filter_bins = [] - - # Clear any tallies previously loaded from a statepoint - if self.loaded_sp: - self._tallies = None - self._xs_tally = None - self._rxn_rate_tally = None - self._loaded_sp = False - - # Find, slice and store Tallies from StatePoint - # The tally slicing is needed if tally merging was used - for tally_type, tally in self.tallies.items(): - sp_tally = statepoint.get_tally( - tally.scores, tally.filters, tally.nuclides, - estimator=tally.estimator, exact_filters=True) - sp_tally = sp_tally.get_slice( - tally.scores, filters, filter_bins, tally.nuclides) - sp_tally.sparse = self.sparse - self.tallies[tally_type] = sp_tally - - self._loaded_sp = True - - def get_xs(self, groups='all', subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - value='mean', squeeze=True, **kwargs): - r"""Returns an array of multi-group cross sections. - - This method constructs a 3D NumPy array for the requested - multi-group cross section data for one or more subdomains - (1st dimension), energy groups (2nd dimension), and nuclides - (3rd dimension). - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the cross sections for all nuclides - in the spatial domain. The special string 'sum' will return the - cross section summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group, subdomain and nuclide is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - subdomain_bins = [] - for subdomain in subdomains: - subdomain_bins.append(subdomain) - filter_bins.append(tuple(subdomain_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - filters.append(openmc.EnergyFilter) - energy_bins = [] - for group in groups: - energy_bins.append( - (self.energy_groups.get_group_bounds(group),)) - filter_bins.append(tuple(energy_bins)) - - # Construct a collection of the nuclides to retrieve from the xs tally - if self.by_nuclide: - if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: - query_nuclides = self.get_nuclides() - else: - query_nuclides = nuclides - else: - query_nuclides = ['total'] - - # If user requested the sum for all nuclides, use tally summation - if nuclides == 'sum' or nuclides == ['sum']: - xs_tally = self.xs_tally.summation(nuclides=query_nuclides) - xs = xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=query_nuclides, value=value) - - # Divide by atom number densities for microscopic cross sections - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - if value == 'mean' or value == 'std_dev': - xs /= densities[np.newaxis, :, np.newaxis] - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - if groups == 'all': - num_groups = self.num_groups - else: - num_groups = len(groups) - - # Reshape tally data array with separate axes for domain and energy - # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_groups * self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_groups) - else: - new_shape = (num_subdomains, num_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # and energy group data. - xs = self._squeeze_xs(xs) - - return xs - - def get_condensed_xs(self, coarse_groups): - """Construct an energy-condensed version of this cross section. - - Parameters - ---------- - coarse_groups : openmc.mgxs.EnergyGroups - The coarse energy group structure of interest - - Returns - ------- - MGXS - A new MGXS condensed to the group structure of interest - - """ - - cv.check_type('coarse_groups', coarse_groups, EnergyGroups) - cv.check_less_than('coarse groups', coarse_groups.num_groups, - self.num_groups, equality=True) - cv.check_value('upper coarse energy', coarse_groups.group_edges[-1], - [self.energy_groups.group_edges[-1]]) - cv.check_value('lower coarse energy', coarse_groups.group_edges[0], - [self.energy_groups.group_edges[0]]) - - # Clone this MGXS to initialize the condensed version - condensed_xs = copy.deepcopy(self) - condensed_xs._rxn_rate_tally = None - condensed_xs._xs_tally = None - condensed_xs._sparse = False - condensed_xs._energy_groups = coarse_groups - - # Build energy indices to sum across - energy_indices = [] - for group in range(coarse_groups.num_groups, 0, -1): - low, high = coarse_groups.get_group_bounds(group) - low_index = np.where(self.energy_groups.group_edges == low)[0][0] - energy_indices.append(low_index) - - fine_edges = self.energy_groups.group_edges - - # Condense each of the tallies to the coarse group structure - for tally in condensed_xs.tallies.values(): - - # Make condensed tally derived and null out sum, sum_sq - tally._derived = True - tally._sum = None - tally._sum_sq = None - - # Get tally data arrays reshaped with one dimension per filter - mean = tally.get_reshaped_data(value='mean') - std_dev = tally.get_reshaped_data(value='std_dev') - - # Sum across all applicable fine energy group filters - for i, tally_filter in enumerate(tally.filters): - if not isinstance(tally_filter, (openmc.EnergyFilter, - openmc.EnergyoutFilter)): - continue - elif len(tally_filter.bins) != len(fine_edges) - 1: - continue - elif not np.allclose(tally_filter.bins[:, 0], fine_edges[:-1]): - continue - else: - cedge = coarse_groups.group_edges - tally_filter.values = cedge - tally_filter.bins = np.vstack((cedge[:-1], cedge[1:])).T - mean = np.add.reduceat(mean, energy_indices, axis=i) - std_dev = np.add.reduceat(std_dev**2, energy_indices, - axis=i) - std_dev = np.sqrt(std_dev) - - # Reshape condensed data arrays with one dimension for all filters - mean = np.reshape(mean, tally.shape) - std_dev = np.reshape(std_dev, tally.shape) - - # Override tally's data with the new condensed data - tally._mean = mean - tally._std_dev = std_dev - - # Compute the energy condensed multi-group cross section - condensed_xs.sparse = self.sparse - return condensed_xs - - def get_subdomain_avg_xs(self, subdomains='all'): - """Construct a subdomain-averaged version of this cross section. - - This method is useful for averaging cross sections across distribcell - instances. The method performs spatial homogenization to compute the - scalar flux-weighted average cross section across the subdomains. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs to average across. Defaults to 'all'. - - Returns - ------- - openmc.mgxs.MGXS - A new MGXS averaged across the subdomains of interest - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - # Construct a collection of the subdomain filter bins to average across - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - subdomains = [(subdomain,) for subdomain in subdomains] - subdomains = [tuple(subdomains)] - elif self.domain_type == 'distribcell': - subdomains = [i for i in range(self.num_subdomains)] - subdomains = [tuple(subdomains)] - else: - subdomains = None - - # Clone this MGXS to initialize the subdomain-averaged version - avg_xs = copy.deepcopy(self) - avg_xs._rxn_rate_tally = None - avg_xs._xs_tally = None - - # Average each of the tallies across subdomains - for tally_type, tally in avg_xs.tallies.items(): - filt_type = _DOMAIN_TO_FILTER[self.domain_type] - tally_avg = tally.summation(filter_type=filt_type, - filter_bins=subdomains) - avg_xs.tallies[tally_type] = tally_avg - - avg_xs._domain_type = 'sum({0})'.format(self.domain_type) - avg_xs.sparse = self.sparse - return avg_xs - - def _get_homogenized_mgxs(self, other_mgxs, denom_score='flux'): - """Construct a homogenized MGXS with other MGXS objects. - - This method constructs a new MGXS object that is the flux-weighted - combination of two MGXS objects. It is equivalent to what one would - obtain if the tally spatial domain were designed to encompass the - individual domains for both MGXS objects. This is accomplished by - summing the rxn rate (numerator) tally and the denominator tally - (often a tally of the flux over the spatial domain) that are used to - compute a multi-group cross-section. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - denom_score : str - The denominator score in the denominator of computing the MGXS. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - # Check type of denom score - cv.check_type('denom_score', denom_score, str) - - # Construct a collection of the subdomain filter bins to homogenize - # across - if isinstance(other_mgxs, openmc.mgxs.MGXS): - other_mgxs = [other_mgxs] - - cv.check_iterable_type('other_mgxs', other_mgxs, openmc.mgxs.MGXS) - for mgxs in other_mgxs: - if mgxs.rxn_type != self.rxn_type: - msg = 'Not able to homogenize two MGXS with different rxn types' - raise ValueError(msg) - - # Clone this MGXS to initialize the homogenized version - homogenized_mgxs = copy.deepcopy(self) - homogenized_mgxs._derived = True - name = 'hom({}, '.format(self.domain.name) - - # Get the domain filter - filter_type = _DOMAIN_TO_FILTER[self.domain_type] - self_filter = self.rxn_rate_tally.find_filter(filter_type) - - # Get the rxn rate and denom tallies - rxn_rate_tally = self.rxn_rate_tally - denom_tally = self.tallies[denom_score] - - for mgxs in other_mgxs: - - # Swap the domain filter bins for the other mgxs rxn rate tally - other_rxn_rate_tally = copy.deepcopy(mgxs.rxn_rate_tally) - other_filter = other_rxn_rate_tally.find_filter(filter_type) - other_filter._bins = self_filter._bins - - # Swap the domain filter bins for the denom tally - other_denom_tally = copy.deepcopy(mgxs.tallies[denom_score]) - other_filter = other_denom_tally.find_filter(filter_type) - other_filter._bins = self_filter._bins - - # Add the rxn rate and denom tallies - rxn_rate_tally += other_rxn_rate_tally - denom_tally += other_denom_tally - - # Update the name for the homogenzied MGXS - name += '{}, '.format(mgxs.domain.name) - - # Set the properties of the homogenized MGXS - homogenized_mgxs._rxn_rate_tally = rxn_rate_tally - homogenized_mgxs.tallies[denom_score] = denom_tally - homogenized_mgxs._domain.name = name[:-2] + ')' - - return homogenized_mgxs - - def get_homogenized_mgxs(self, other_mgxs): - """Construct a homogenized mgxs with other MGXS objects. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - return self._get_homogenized_mgxs(other_mgxs, 'flux') - - def get_slice(self, nuclides=[], groups=[]): - """Build a sliced MGXS for the specified nuclides and energy groups. - - This method constructs a new MGXS to encapsulate a subset of the data - represented by this MGXS. The subset of data to include in the tally - slice is determined by the nuclides and energy groups specified in - the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - groups : list of int - A list of energy group indices starting at 1 for the high energies - (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MGXS - A new MGXS object which encapsulates the subset of data requested - for the nuclide(s) and/or energy group(s) requested in the - parameters. - - """ - - cv.check_iterable_type('nuclides', nuclides, str) - cv.check_iterable_type('energy_groups', groups, Integral) - - # Build lists of filters and filter bins to slice - filters = [] - filter_bins = [] - - if len(groups) != 0: - energy_bins = [] - for group in groups: - group_bounds = self.energy_groups.get_group_bounds(group) - energy_bins.append(group_bounds) - filter_bins.append(tuple(energy_bins)) - filters.append(openmc.EnergyFilter) - - # Clone this MGXS to initialize the sliced version - slice_xs = copy.deepcopy(self) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice each of the tallies across nuclides and energy groups - for tally_type, tally in slice_xs.tallies.items(): - slice_nuclides = [nuc for nuc in nuclides if nuc in tally.nuclides] - if len(groups) != 0 and tally.contains_filter(openmc.EnergyFilter): - tally_slice = tally.get_slice(filters=filters, - filter_bins=filter_bins, - nuclides=slice_nuclides) - else: - tally_slice = tally.get_slice(nuclides=slice_nuclides) - slice_xs.tallies[tally_type] = tally_slice - - # Assign sliced energy group structure to sliced MGXS - if groups: - new_group_edges = [] - for group in groups: - group_edges = self.energy_groups.get_group_bounds(group) - new_group_edges.extend(group_edges) - new_group_edges = np.unique(new_group_edges) - slice_xs.energy_groups.group_edges = sorted(new_group_edges) - - # Assign sliced nuclides to sliced MGXS - if nuclides: - slice_xs.nuclides = nuclides - - slice_xs.sparse = self.sparse - return slice_xs - - def can_merge(self, other): - """Determine if another MGXS can be merged with this one - - If results have been loaded from a statepoint, then MGXS are only - mergeable along one and only one of enegy groups or nuclides. - - Parameters - ---------- - other : openmc.mgxs.MGXS - MGXS to check for merging - - """ - - if not isinstance(other, type(self)): - return False - - # Compare reaction type, energy groups, nuclides, domain type - if self.rxn_type != other.rxn_type: - return False - elif not self.energy_groups.can_merge(other.energy_groups): - return False - elif self.by_nuclide != other.by_nuclide: - return False - elif self.domain_type != other.domain_type: - return False - elif 'distribcell' not in self.domain_type and self.domain != other.domain: - return False - elif not self.xs_tally.can_merge(other.xs_tally): - return False - elif not self.rxn_rate_tally.can_merge(other.rxn_rate_tally): - return False - - # If all conditionals pass then MGXS are mergeable - return True - - def merge(self, other): - """Merge another MGXS with this one - - MGXS are only mergeable if their energy groups and nuclides are either - identical or mutually exclusive. If results have been loaded from a - statepoint, then MGXS are only mergeable along one and only one of - energy groups or nuclides. - - Parameters - ---------- - other : openmc.mgxs.MGXS - MGXS to merge with this one - - Returns - ------- - merged_mgxs : openmc.mgxs.MGXS - Merged MGXS - - """ - - if not self.can_merge(other): - raise ValueError('Unable to merge MGXS') - - # Create deep copy of tally to return as merged tally - merged_mgxs = copy.deepcopy(self) - merged_mgxs._derived = True - - # Merge energy groups - if self.energy_groups != other.energy_groups: - merged_groups = self.energy_groups.merge(other.energy_groups) - merged_mgxs.energy_groups = merged_groups - - # Merge nuclides - if self.nuclides != other.nuclides: - - # The nuclides must be mutually exclusive - for nuclide in self.nuclides: - if nuclide in other.nuclides: - msg = 'Unable to merge MGXS with shared nuclides' - raise ValueError(msg) - - # Concatenate lists of nuclides for the merged MGXS - merged_mgxs.nuclides = self.nuclides + other.nuclides - - # Null base tallies but merge reaction rate and cross section tallies - merged_mgxs._tallies = OrderedDict() - merged_mgxs._rxn_rate_tally = self.rxn_rate_tally.merge(other.rxn_rate_tally) - merged_mgxs._xs_tally = self.xs_tally.merge(other.xs_tally) - - return merged_mgxs - - def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): - """Print a string representation for the multi-group cross section. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will report - the cross sections summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - - """ - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'mesh': - subdomains = list(self.domain.indices) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - elif nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Build header for string with type and domain info - string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) - - # Generate the header for an individual XS - xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) - - # If cross section data has not been computed, only print string header - if self.tallies is None: - print(string) - return - - # Set polar/azimuthal bins - if self.num_polar > 1 or self.num_azimuthal > 1: - pol_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azi_bins = np.linspace(-np.pi, np.pi, num=self.num_azimuthal + 1, - endpoint=True) - - # Loop over all subdomains - for subdomain in subdomains: - - if self.domain_type == 'distribcell' or self.domain_type == 'mesh': - string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) - - # Loop over all Nuclides - for nuclide in nuclides: - - # Build header for nuclide type - if nuclide != 'sum': - string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) - - # Build header for cross section type - string += '{0: <16}\n'.format(xs_header) - template = '{0: <12}Group {1} [{2: <10} - {3: <10}eV]:\t' - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean') - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='rel_err') - rel_err_xs = rel_err_xs * 100. - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azimuthal, and energy group ranges - for pol in range(len(pol_bins) - 1): - pol_low, pol_high = pol_bins[pol: pol + 2] - for azi in range(len(azi_bins) - 1): - azi_low, azi_high = azi_bins[azi: azi + 2] - string += '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - for group in range(1, self.num_groups + 1): - bounds = \ - self.energy_groups.get_group_bounds(group) - string += '\t' + template.format('', group, - bounds[0], - bounds[1]) - - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[pol, azi, group - 1], - rel_err_xs[pol, azi, group - 1]) - string += '\n' - string += '\n' - else: - # Loop over energy groups - for group in range(1, self.num_groups + 1): - bounds = self.energy_groups.get_group_bounds(group) - string += template.format('', group, bounds[0], - bounds[1]) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[group - 1], rel_err_xs[group - 1]) - string += '\n' - string += '\n' - string += '\n' - - print(string) - - def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs', - subdomains='all', nuclides='all', - xs_type='macro', row_column='inout', append=True, - libver='earliest'): - """Export the multi-group cross section data to an HDF5 binary file. - - This method constructs an HDF5 file which stores the multi-group - cross section data. The data is stored in a hierarchy of HDF5 groups - from the domain type, domain id, subdomain id (for distribcell domains), - nuclides and cross section type. Two datasets for the mean and standard - deviation are stored for each subdomain entry in the HDF5 file. - - .. note:: This requires the h5py Python package. - - Parameters - ---------- - filename : str - Filename for the HDF5 file. Defaults to 'mgxs.h5'. - directory : str - Directory for the HDF5 file. Defaults to 'mgxs'. - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will report - the cross sections summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Store the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - row_column: {'inout', 'outin'} - Store scattering matrices indexed first by incoming group and - second by outgoing group ('inout'), or vice versa ('outin'). - Defaults to 'inout'. - append : bool - If true, appends to an existing HDF5 file with the same filename - directory (if one exists). Defaults to True. - libver : {'earliest', 'latest'} - Compatibility mode for the HDF5 file. 'latest' will produce files - that are less backwards compatible but have performance benefits. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - filename = os.path.join(directory, filename) - filename = filename.replace(' ', '-') - - if append and os.path.isfile(filename): - xs_results = h5py.File(filename, 'a') - else: - xs_results = h5py.File(filename, 'w', libver=libver) - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'sum(distribcell)': - domain_filter = self.xs_tally.find_filter('sum(distribcell)') - subdomains = domain_filter.bins - elif self.domain_type == 'mesh': - subdomains = list(self.domain.indices) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - densities = np.zeros(len(nuclides), dtype=np.float) - elif nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Create an HDF5 group within the file for the domain - domain_type_group = xs_results.require_group(self.domain_type) - domain_group = domain_type_group.require_group(str(self.domain.id)) - - # Determine number of digits to pad subdomain group keys - num_digits = len(str(self.num_subdomains)) - - # Create a separate HDF5 group for each subdomain - for subdomain in subdomains: - - # Create an HDF5 group for the subdomain - if self.domain_type == 'distribcell': - group_name = ''.zfill(num_digits) - subdomain_group = domain_group.require_group(group_name) - else: - subdomain_group = domain_group - - # Create a separate HDF5 group for this cross section - rxn_group = subdomain_group.require_group(self.hdf5_key) - - # Create a separate HDF5 group for each nuclide - for j, nuclide in enumerate(nuclides): - - if nuclide != 'sum': - density = densities[j] - nuclide_group = rxn_group.require_group(nuclide) - nuclide_group.require_dataset('density', dtype=np.float64, - data=[density], shape=(1,)) - else: - nuclide_group = rxn_group - - # Extract the cross section for this subdomain and nuclide - average = self.get_xs(subdomains=[subdomain], nuclides=[nuclide], - xs_type=xs_type, value='mean', - row_column=row_column) - std_dev = self.get_xs(subdomains=[subdomain], nuclides=[nuclide], - xs_type=xs_type, value='std_dev', - row_column=row_column) - - # Add MGXS results data to the HDF5 group - nuclide_group.require_dataset('average', dtype=np.float64, - shape=average.shape, data=average) - nuclide_group.require_dataset('std. dev.', dtype=np.float64, - shape=std_dev.shape, data=std_dev) - - # Close the results HDF5 file - xs_results.close() - - def export_xs_data(self, filename='mgxs', directory='mgxs', - format='csv', groups='all', xs_type='macro'): - """Export the multi-group cross section data to a file. - - This method leverages the functionality in the Pandas library to export - the multi-group cross section data in a variety of output file formats - for storage and/or post-processing. - - Parameters - ---------- - filename : str - Filename for the exported file. Defaults to 'mgxs'. - directory : str - Directory for the exported file. Defaults to 'mgxs'. - format : {'csv', 'excel', 'pickle', 'latex'} - The format for the exported data file. Defaults to 'csv'. - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - xs_type: {'macro', 'micro'} - Store the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - - """ - - cv.check_type('filename', filename, str) - cv.check_type('directory', directory, str) - cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - filename = os.path.join(directory, filename) - filename = filename.replace(' ', '-') - - # Get a Pandas DataFrame for the data - df = self.get_pandas_dataframe(groups=groups, xs_type=xs_type) - - # Export the data using Pandas IO API - if format == 'csv': - df.to_csv(filename + '.csv', index=False) - elif format == 'excel': - if self.domain_type == 'mesh': - df.to_excel(filename + '.xls') - else: - df.to_excel(filename + '.xls', index=False) - elif format == 'pickle': - df.to_pickle(filename + '.pkl') - elif format == 'latex': - if self.domain_type == 'distribcell': - msg = 'Unable to export distribcell multi-group cross section' \ - 'data to a LaTeX table' - raise NotImplementedError(msg) - - df.to_latex(filename + '.tex', bold_rows=True, - longtable=True, index=False) - - # Surround LaTeX table with code needed to run pdflatex - with open(filename + '.tex', 'r') as original: - data = original.read() - with open(filename + '.tex', 'w') as modified: - modified.write( - '\\documentclass[preview, 12pt, border=1mm]{standalone}\n') - modified.write('\\usepackage{caption}\n') - modified.write('\\usepackage{longtable}\n') - modified.write('\\usepackage{booktabs}\n') - modified.write('\\begin{document}\n\n') - modified.write(data) - modified.write('\n\\end{document}') - - def get_pandas_dataframe(self, groups='all', nuclides='all', - xs_type='macro', paths=True): - """Build a Pandas DataFrame for the MGXS data. - - This method leverages :meth:`openmc.Tally.get_pandas_dataframe`, but - renames the columns with terminology appropriate for cross section data. - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will include the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - include the cross sections summed over all nuclides. Defaults - to 'all'. - xs_type: {'macro', 'micro'} - Return macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into - a Multi-index column with a geometric "path" to each distribcell - instance. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame for the cross section data. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - if nuclides != 'all' and nuclides != 'sum': - cv.check_iterable_type('nuclides', nuclides, str) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Get a Pandas DataFrame from the derived xs tally - if self.by_nuclide and nuclides == 'sum': - - # Use tally summation to sum across all nuclides - xs_tally = self.xs_tally.summation(nuclides=self.get_nuclides()) - df = xs_tally.get_pandas_dataframe(paths=paths) - - # Remove nuclide column since it is homogeneous and redundant - if self.domain_type == 'mesh': - df.drop('sum(nuclide)', axis=1, level=0, inplace=True) - else: - df.drop('sum(nuclide)', axis=1, inplace=True) - - # If the user requested a specific set of nuclides - elif self.by_nuclide and nuclides != 'all': - xs_tally = self.xs_tally.get_slice(nuclides=nuclides) - df = xs_tally.get_pandas_dataframe(paths=paths) - - # If the user requested all nuclides, keep nuclide column in dataframe - else: - df = self.xs_tally.get_pandas_dataframe(paths=paths) - - # Remove the score column since it is homogeneous and redundant - if self.domain_type == 'mesh': - df = df.drop('score', axis=1, level=0) - else: - df = df.drop('score', axis=1) - - # Convert azimuthal, polar, energy in and energy out bin values in to - # bin indices - columns = self._df_convert_columns_to_bins(df) - - # Select out those groups the user requested - if not isinstance(groups, str): - if 'group in' in df: - df = df[df['group in'].isin(groups)] - if 'group out' in df: - df = df[df['group out'].isin(groups)] - - # If user requested micro cross sections, divide out the atom densities - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - densities = np.repeat(densities, len(self.rxn_rate_tally.scores)) - tile_factor = int(df.shape[0] / len(densities)) - df['mean'] /= np.tile(densities, tile_factor) - df['std. dev.'] /= np.tile(densities, tile_factor) - - # Replace NaNs by zeros (happens if nuclide density is zero) - df['mean'].replace(np.nan, 0.0, inplace=True) - df['std. dev.'].replace(np.nan, 0.0, inplace=True) - - # Sort the dataframe by domain type id (e.g., distribcell id) and - # energy groups such that data is from fast to thermal - if self.domain_type == 'mesh': - mesh_str = 'mesh {0}'.format(self.domain.id) - df.sort_values(by=[(mesh_str, 'x'), (mesh_str, 'y'), - (mesh_str, 'z')] + columns, inplace=True) - else: - df.sort_values(by=[self.domain_type] + columns, inplace=True) - - return df - - def get_units(self, xs_type='macro'): - """This method returns the units of a MGXS based on a desired xs_type. - - Parameters - ---------- - xs_type: {'macro', 'micro'} - Return the macro or micro cross section units. - Defaults to 'macro'. - - Returns - ------- - str - A string representing the units of the MGXS. - - """ - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - return 'cm^-1' if xs_type == 'macro' else 'barns' - - -class MatrixMGXS(MGXS): - """An abstract multi-group cross section for some energy group structure - within some spatial domain. This class is specifically intended for - cross sections which depend on both the incoming and outgoing energy groups - and are therefore represented by matrices. Examples of this include the - scattering and nu-fission matrices. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. - - .. note:: Users should instantiate the subclasses of this abstract class. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - return (0, 1, 3, 4) - else: - return (1, 2) - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - filters = [[energy], [energy, energyout]] - - return self._add_angle_filters(filters) - - def get_xs(self, in_groups='all', out_groups='all', - subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - row_column='inout', value='mean', squeeze=True, **kwargs): - """Returns an array of multi-group cross sections. - - This method constructs a 4D NumPy array for the requested - multi-group cross section data for one or more subdomains - (1st dimension), energy groups in (2nd dimension), energy groups out - (3rd dimension), and nuclides (4th dimension). - - Parameters - ---------- - in_groups : Iterable of Integral or 'all' - Incoming energy groups of interest. Defaults to 'all'. - out_groups : Iterable of Integral or 'all' - Outgoing energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - return the cross section summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - row_column: {'inout', 'outin'} - Return the cross section indexed first by incoming group and - second by outgoing group ('inout'), or vice versa ('outin'). - Defaults to 'inout'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group and subdomain is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - subdomain_bins = [] - for subdomain in subdomains: - subdomain_bins.append(subdomain) - filter_bins.append(tuple(subdomain_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, str): - cv.check_iterable_type('groups', in_groups, Integral) - filters.append(openmc.EnergyFilter) - for group in in_groups: - energy_bins.append((self.energy_groups.get_group_bounds(group),)) - filter_bins.append(tuple(energy_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, str): - cv.check_iterable_type('groups', out_groups, Integral) - for group in out_groups: - filters.append(openmc.EnergyoutFilter) - filter_bins.append(( - self.energy_groups.get_group_bounds(group),)) - - # Construct a collection of the nuclides to retrieve from the xs tally - if self.by_nuclide: - if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: - query_nuclides = self.get_nuclides() - else: - query_nuclides = nuclides - else: - query_nuclides = ['total'] - - # Use tally summation if user requested the sum for all nuclides - if nuclides == 'sum' or nuclides == ['sum']: - xs_tally = self.xs_tally.summation(nuclides=query_nuclides) - xs = xs_tally.get_values(filters=filters, filter_bins=filter_bins, - value=value) - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=query_nuclides, value=value) - - # Divide by atom number densities for microscopic cross sections - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - if value == 'mean' or value == 'std_dev': - xs /= densities[np.newaxis, :, np.newaxis] - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - if in_groups == 'all': - num_in_groups = self.num_groups - else: - num_in_groups = len(in_groups) - - if out_groups == 'all': - num_out_groups = self.num_groups - else: - num_out_groups = len(out_groups) - - # Reshape tally data array with separate axes for domain and energy - # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_in_groups * num_out_groups * - self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_in_groups, num_out_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 3, 4) - else: - new_shape = (num_subdomains, num_in_groups, num_out_groups) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 1, 2) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # and in/out energy group data. - xs = self._squeeze_xs(xs) - - return xs - - def get_slice(self, nuclides=[], in_groups=[], out_groups=[]): - """Build a sliced MatrixMGXS object for the specified nuclides and - energy groups. - - This method constructs a new MGXS to encapsulate a subset of the data - represented by this MGXS. The subset of data to include in the tally - slice is determined by the nuclides and energy groups specified in - the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - in_groups : list of int - A list of incoming energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - out_groups : list of int - A list of outgoing energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MatrixMGXS - A new MatrixMGXS object which encapsulates the subset of data - requested for the nuclide(s) and/or energy group(s) requested in - the parameters. - - """ - - # Call super class method and null out derived tallies - slice_xs = super().get_slice(nuclides, in_groups) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice outgoing energy groups if needed - if len(out_groups) != 0: - filter_bins = [] - for group in out_groups: - group_bounds = self.energy_groups.get_group_bounds(group) - filter_bins.append(group_bounds) - filter_bins = [tuple(filter_bins)] - - # Slice each of the tallies across energyout groups - for tally_type, tally in slice_xs.tallies.items(): - if tally.contains_filter(openmc.EnergyoutFilter): - tally_slice = tally.get_slice( - filters=[openmc.EnergyoutFilter], - filter_bins=filter_bins) - slice_xs.tallies[tally_type] = tally_slice - - slice_xs.sparse = self.sparse - return slice_xs - - def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'): - """Prints a string representation for the multi-group cross section. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - report the cross sections summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - - """ - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'mesh': - subdomains = list(self.domain.indices) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - if nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Build header for string with type and domain info - string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) - - # Generate the header for an individual XS - xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) - - # If cross section data has not been computed, only print string header - if self.tallies is None: - print(string) - return - - string += '{0: <16}\n'.format('\tEnergy Groups:') - template = '{0: <12}Group {1} [{2: <10} - {3: <10}eV]\n' - - # Loop over energy groups ranges - for group in range(1, self.num_groups + 1): - bounds = self.energy_groups.get_group_bounds(group) - string += template.format('', group, bounds[0], bounds[1]) - - # Set polar and azimuthal bins if necessary - if self.num_polar > 1 or self.num_azimuthal > 1: - pol_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azi_bins = np.linspace(-np.pi, np.pi, num=self.num_azimuthal + 1, - endpoint=True) - - # Loop over all subdomains - for subdomain in subdomains: - - if self.domain_type == 'distribcell' or self.domain_type == 'mesh': - string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) - - # Loop over all Nuclides - for nuclide in nuclides: - - # Build header for nuclide type - if xs_type != 'sum': - string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) - - # Build header for cross section type - string += '{0: <16}\n'.format(xs_header) - template = '{0: <12}Group {1} -> Group {2}:\t\t' - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean') - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='rel_err') - rel_err_xs = rel_err_xs * 100. - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azi, and in/out energy group ranges - for pol in range(len(pol_bins) - 1): - pol_low, pol_high = pol_bins[pol: pol + 2] - for azi in range(len(azi_bins) - 1): - azi_low, azi_high = azi_bins[azi: azi + 2] - string += '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += '\t' + template.format('', - in_group, - out_group) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[pol, azi, in_group - 1, - out_group - 1], - rel_err_xs[pol, azi, in_group - 1, - out_group - 1]) - string += '\n' - string += '\n' - string += '\n' - else: - # Loop over incoming/outgoing energy groups ranges - for in_group in range(1, self.num_groups + 1): - for out_group in range(1, self.num_groups + 1): - string += template.format('', in_group, out_group) - string += '{0:.2e} +/- {1:.2e}%'.format( - average_xs[in_group - 1, out_group - 1], - rel_err_xs[in_group - 1, out_group - 1]) - string += '\n' - string += '\n' - string += '\n' - string += '\n' - - print(string) - - -class TotalXS(MGXS): - r"""A total multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group total cross sections for multi-group neutronics calculations. At - a minimum, one needs to set the :attr:`TotalXS.energy_groups` and - :attr:`TotalXS.domain` properties. Tallies for the flux and appropriate - reaction rates over the specified domain are generated automatically via the - :attr:`TotalXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`TotalXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - total cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \sigma_t (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`TotalXS.tally_keys` property and values - are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'total' - - -class TransportXS(MGXS): - r"""A transport-corrected total multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`TransportXS.energy_groups` and - :attr:`TransportXS.domain` properties. Tallies for the flux and appropriate - reaction rates over the specified domain are generated automatically via the - :attr:`TransportXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`TransportXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - transport-corrected total cross section is calculated as: - - .. math:: - - \begin{aligned} - \langle \sigma_t \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \sigma_t (r, E) \psi - (r, E, \Omega) \\ - \langle \sigma_{s1} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_{-1}^1 d\mu \; \mu \sigma_s - (r, E' \rightarrow E, \Omega' \cdot \Omega) - \phi (r, E', \Omega) \\ - \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ - \sigma_{tr} &= \frac{\langle \sigma_t \phi \rangle - \langle \sigma_{s1} - \phi \rangle}{\langle \phi \rangle} - \end{aligned} - - To incorporate the effect of scattering multiplication in the above - relation, the `nu` parameter can be set to `True`. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - nu : bool - If True, the cross section data will include neutron multiplication; - defaults to True. - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - nu : bool - If True, the cross section data will include neutron multiplication - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`TransportXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, nu=False, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - - # Use tracklength estimators for the total MGXS term, and - # analog estimators for the transport correction term - self._estimator = ['tracklength', 'tracklength', 'analog', 'analog'] - self._valid_estimators = ['analog'] - self.nu = nu - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._nu = self.nu - return clone - - @property - def scores(self): - if not self.nu: - return ['flux', 'total', 'flux', 'scatter'] - else: - return ['flux', 'total', 'flux', 'nu-scatter'] - - @property - def tally_keys(self): - return ['flux (tracklength)', 'total', 'flux (analog)', 'scatter-1'] - - @property - def filters(self): - group_edges = self.energy_groups.group_edges - energy_filter = openmc.EnergyFilter(group_edges) - energyout_filter = openmc.EnergyoutFilter(group_edges) - p1_filter = openmc.LegendreFilter(1) - filters = [[energy_filter], [energy_filter], - [energy_filter], [energyout_filter, p1_filter]] - - return self._add_angle_filters(filters) - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - # Switch EnergyoutFilter to EnergyFilter. - p1_tally = self.tallies['scatter-1'] - old_filt = p1_tally.filters[-2] - new_filt = openmc.EnergyFilter(old_filt.values) - p1_tally.filters[-2] = new_filt - - # Slice Legendre expansion filter and change name of score - p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], - filter_bins=[('P1',)], - squeeze=True) - p1_tally._scores = ['scatter-1'] - - self._rxn_rate_tally = self.tallies['total'] - p1_tally - self._rxn_rate_tally.sparse = self.sparse - - return self._rxn_rate_tally - - @property - def xs_tally(self): - if self._xs_tally is None: - if self.tallies is None: - msg = 'Unable to get xs_tally since tallies have ' \ - 'not been loaded from a statepoint' - raise ValueError(msg) - - # Switch EnergyoutFilter to EnergyFilter. - p1_tally = self.tallies['scatter-1'] - old_filt = p1_tally.filters[-2] - new_filt = openmc.EnergyFilter(old_filt.values) - p1_tally.filters[-2] = new_filt - - # Slice Legendre expansion filter and change name of score - p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], - filter_bins=[('P1',)], - squeeze=True) - p1_tally._scores = ['scatter-1'] - - # Compute total cross section - total_xs = self.tallies['total'] / self.tallies['flux (tracklength)'] - - # Compute transport correction term - trans_corr = p1_tally / self.tallies['flux (analog)'] - - # Compute the transport-corrected total cross section - self._xs_tally = total_xs - trans_corr - self._compute_xs() - - return self._xs_tally - - @property - def nu(self): - return self._nu - - @nu.setter - def nu(self, nu): - cv.check_type('nu', nu, bool) - self._nu = nu - if not nu: - self._rxn_type = 'transport' - else: - self._rxn_type = 'nu-transport' - - -class AbsorptionXS(MGXS): - r"""An absorption multi-group cross section. - - Absorption is defined as all reactions that do not produce secondary - neutrons (disappearance) plus fission reactions. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group absorption cross sections for multi-group neutronics - calculations. At a minimum, one needs to set the - :attr:`AbsorptionXS.energy_groups` and :attr:`AbsorptionXS.domain` - properties. Tallies for the flux and appropriate reaction rates over the - specified domain are generated automatically via the - :attr:`AbsorptionXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`AbsorptionXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - absorption cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \sigma_a (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`AbsorptionXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'absorption' - - -class CaptureXS(MGXS): - r"""A capture multi-group cross section. - - The neutron capture reaction rate is defined as the difference between - OpenMC's 'absorption' and 'fission' reaction rate score types. This includes - not only radiative capture, but all forms of neutron disappearance aside - from fission (i.e., MT > 100). - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group capture cross sections for multi-group neutronics - calculations. At a minimum, one needs to set the - :attr:`CaptureXS.energy_groups` and :attr:`CaptureXS.domain` - properties. Tallies for the flux and appropriate reaction rates over the - specified domain are generated automatically via the - :attr:`CaptureXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`CaptureXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - capture cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \left [ \sigma_a (r, E) \psi (r, E, \Omega) - \sigma_f (r, E) \psi (r, E, - \Omega) \right ]}{\int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`CaptureXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'capture' - - @property - def scores(self): - return ['flux', 'absorption', 'fission'] - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = \ - self.tallies['absorption'] - self.tallies['fission'] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - -class FissionXS(MGXS): - r"""A fission multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group fission cross sections for multi-group neutronics - calculations. At a minimum, one needs to set the - :attr:`FissionXS.energy_groups` and :attr:`FissionXS.domain` - properties. Tallies for the flux and appropriate reaction rates over the - specified domain are generated automatically via the - :attr:`FissionXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`FissionXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - fission cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \sigma_f (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - To incorporate the effect of neutron multiplication in the above - relation, the `nu` parameter can be set to `True`. - - This class can also be used to gather a prompt-nu-fission cross section - (which only includes the contributions from prompt neutrons). This is - accomplished by setting the :attr:`FissionXS.prompt` attribute to `True`. - Since the prompt-nu-fission cross section requires neutron multiplication, - the `nu` parameter will automatically be set to `True` if `prompt` is also - `True`. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - nu : bool - If True, the cross section data will include neutron multiplication; - defaults to False - prompt : bool - If true, computes cross sections which only includes prompt neutrons; - defaults to False which includes prompt and delayed in total. Setting - this to True will also set nu to True - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - nu : bool - If True, the cross section data will include neutron multiplication - prompt : bool - If true, computes cross sections which only includes prompt neutrons - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`FissionXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, nu=False, - prompt=False, by_nuclide=False, name='', num_polar=1, - num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._nu = False - self._prompt = False - self.nu = nu - self.prompt = prompt - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._nu = self.nu - clone._prompt = self.prompt - return clone - - @property - def nu(self): - return self._nu - - @property - def prompt(self): - return self._prompt - - @nu.setter - def nu(self, nu): - cv.check_type('nu', nu, bool) - self._nu = nu - if not self.prompt: - if not self.nu: - self._rxn_type = 'fission' - else: - self._rxn_type = 'nu-fission' - else: - self._rxn_type = 'prompt-nu-fission' - - @prompt.setter - def prompt(self, prompt): - cv.check_type('prompt', prompt, bool) - self._prompt = prompt - if not self.prompt: - if not self.nu: - self._rxn_type = 'fission' - else: - self._rxn_type = 'nu-fission' - else: - self._rxn_type = 'prompt-nu-fission' - - -class KappaFissionXS(MGXS): - r"""A recoverable fission energy production rate multi-group cross section. - - The recoverable energy per fission, :math:`\kappa`, is defined as the - fission product kinetic energy, prompt and delayed neutron kinetic energies, - prompt and delayed :math:`\gamma`-ray total energies, and the total energy - released by the delayed :math:`\beta` particles. The neutrino energy does - not contribute to this response. The prompt and delayed :math:`\gamma`-rays - are assumed to deposit their energy locally. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`KappaFissionXS.energy_groups` and - :attr:`KappaFissionXS.domain` properties. Tallies for the flux and appropriate - reaction rates over the specified domain are generated automatically via the - :attr:`KappaFissionXS.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`KappaFissionXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - recoverable fission energy production rate cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \kappa\sigma_f (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`KappaFissionXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'kappa-fission' - - -class ScatterXS(MGXS): - r"""A scattering multi-group cross section. - - The scattering cross section is defined as the difference between the total - and absorption cross sections. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`ScatterXS.energy_groups` and - :attr:`ScatterXS.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`ScatterXS.tallies` property, which can - then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`ScatterXS.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - scattering cross section is calculated as: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \left [ \sigma_t (r, E) \psi (r, E, \Omega) - \sigma_a (r, E) \psi (r, E, - \Omega) \right ]}{\int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}. - - To incorporate the effect of scattering multiplication from (n,xn) - reactions in the above relation, the `nu` parameter can be set to `True`. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - nu : bool - If True, the cross section data will include neutron multiplication; - defaults to False - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - nu : bool - If True, the cross section data will include neutron multiplication - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`ScatterXS.tally_keys` property and - values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, - num_azimuthal=1, nu=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self.nu = nu - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._nu = self.nu - return clone - - @property - def nu(self): - return self._nu - - @nu.setter - def nu(self, nu): - cv.check_type('nu', nu, bool) - self._nu = nu - if not nu: - self._rxn_type = 'scatter' - else: - self._rxn_type = 'nu-scatter' - self._estimator = 'analog' - self._valid_estimators = ['analog'] - - -class ScatterMatrixXS(MatrixMGXS): - r"""A scattering matrix multi-group cross section with the cosine of the - change-in-angle represented as one or more Legendre moments or a histogram. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`ScatterMatrixXS.energy_groups` and - :attr:`ScatterMatrixXS.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`ScatterMatrixXS.tallies` property, which can - then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`ScatterMatrixXS.xs_tally` property. - - For a spatial domain :math:`V`, incoming energy group - :math:`[E_{g'},E_{g'-1}]`, and outgoing energy group :math:`[E_g,E_{g-1}]`, - the Legendre scattering moments are calculated as: - - .. math:: - - \begin{aligned} - \langle \sigma_{s,\ell,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; P_\ell (\Omega \cdot \Omega') \sigma_s (r, E' - \rightarrow E, \Omega' \cdot \Omega) \psi(r, E', \Omega')\\ - \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ - \sigma_{s,\ell,g'\rightarrow g} &= \frac{\langle - \sigma_{s,\ell,g'\rightarrow g} \phi \rangle}{\langle \phi \rangle} - \end{aligned} - - If the order is zero and a :math:`P_0` transport-correction is applied - (default), the scattering matrix elements are: - - .. math:: - - \sigma_{s,g'\rightarrow g} = \frac{\langle \sigma_{s,0,g'\rightarrow g} - \phi \rangle - \delta_{gg'} \sum_{g''} \langle \sigma_{s,1,g''\rightarrow - g} \phi \rangle}{\langle \phi \rangle} - - To incorporate the effect of neutron multiplication from (n,xn) reactions - in the above relation, the `nu` parameter can be set to `True`. - - An alternative form of the scattering matrix is computed when the - `formulation` property is set to 'consistent' rather than the default - of 'simple'. This formulation computes the scattering matrix multi-group - cross section as the product of the scatter cross section and - group-to-group scattering probabilities. - - Unlike the default 'simple' formulation, the 'consistent' formulation - is computed from the groupwise scattering cross section which uses a - tracklength estimator. This ensures that reaction rate balance is exactly - preserved with a :class:`TotalXS` computed using a tracklength estimator. - - For a scattering probability matrix :math:`P_{s,\ell,g'\rightarrow g}` and - scattering cross section :math:`\sigma_s (r, E)` for incoming energy group - :math:`[E_{g'},E_{g'-1}]` and outgoing energy group :math:`[E_g,E_{g-1}]`, - the Legendre scattering moments are calculated as: - - .. math:: - - \sigma_{s,\ell,g'\rightarrow g} = \sigma_s (r, E) \times - P_{s,\ell,g'\rightarrow g} - - To incorporate the effect of neutron multiplication from (n,xn) reactions - in the 'consistent' scattering matrix, the `nu` parameter can be set to `True` - such that the Legendre scattering moments are calculated as: - - .. math:: - - \sigma_{s,\ell,g'\rightarrow g} = \upsilon_{g'\rightarrow g} \times - \sigma_s (r, E) \times P_{s,\ell,g'\rightarrow g} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : int, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : int, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - nu : bool - If True, the cross section data will include neutron multiplication; - defaults to False - - Attributes - ---------- - formulation : 'simple' or 'consistent' - The calculation approach to use ('simple' by default). The 'simple' - formulation simply divides the group-to-group scattering rates by - the groupwise flux, each computed from analog tally estimators. The - 'consistent' formulation multiplies the groupwise scattering rates - by the group-to-group scatter probability matrix, the former computed - from tracklength tallies and the latter computed from analog tallies. - The 'consistent' formulation is designed to better conserve reaction - rate balance with the total and absorption cross sections computed - using tracklength tally estimators. - correction : 'P0' or None - Apply the P0 correction to scattering matrices if set to 'P0'; this is - used only if :attr:`ScatterMatrixXS.scatter_format` is 'legendre' - scatter_format : {'legendre', or 'histogram'} - Representation of the angular scattering distribution (default is - 'legendre') - legendre_order : int - The highest Legendre moment in the scattering matrix; this is used if - :attr:`ScatterMatrixXS.scatter_format` is 'legendre'. (default is 0) - histogram_bins : int - The number of equally-spaced bins for the histogram representation of - the angular scattering distribution; this is used if - :attr:`ScatterMatrixXS.scatter_format` is 'histogram'. (default is 16) - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - nu : bool - If True, the cross section data will include neutron multiplication - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : int - Number of equi-width polar angle bins for angle discretization - num_azimuthal : int - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`ScatterMatrixXS.tally_keys` property - and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, - num_azimuthal=1, nu=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._formulation = 'simple' - self._correction = 'P0' - self._scatter_format = 'legendre' - self._legendre_order = 0 - self._histogram_bins = 16 - self._estimator = 'analog' - self._valid_estimators = ['analog'] - self.nu = nu - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._formulation = self.formulation - clone._correction = self.correction - clone._scatter_format = self.scatter_format - clone._legendre_order = self.legendre_order - clone._histogram_bins = self.histogram_bins - clone._nu = self.nu - return clone - - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - if self.scatter_format == 'histogram': - return (0, 1, 3, 4, 5) - else: - return (0, 1, 3, 4) - else: - if self.scatter_format == 'histogram': - return (1, 2, 3) - else: - return (1, 2) - - @property - def formulation(self): - return self._formulation - - @property - def correction(self): - return self._correction - - @property - def scatter_format(self): - return self._scatter_format - - @property - def legendre_order(self): - return self._legendre_order - - @property - def histogram_bins(self): - return self._histogram_bins - - @property - def nu(self): - return self._nu - - @property - def scores(self): - - if self.formulation == 'simple': - scores = ['flux', self.rxn_type] - - else: - # Add scores for groupwise scattering cross section - scores = ['flux', 'scatter'] - - # Add scores for group-to-group scattering probability matrix - # these scores also contain the angular information, whether it be - # Legendre expansion or histogram bins - scores.append('scatter') - - # Add scores for multiplicity matrix; scatter info for the - # denominator will come from the previous score - if self.nu: - scores.append('nu-scatter') - - # Add scores for transport correction - if self.correction == 'P0' and self.legendre_order == 0: - scores.extend([self.rxn_type, 'flux']) - - return scores - - @property - def tally_keys(self): - if self.formulation == 'simple': - return super().tally_keys - else: - # Add keys for groupwise scattering cross section - tally_keys = ['flux (tracklength)', 'scatter'] - - # Add keys for group-to-group scattering probability matrix - tally_keys.append('scatter matrix') - - # Add keys for multiplicity matrix - if self.nu: - tally_keys.extend(['nu-scatter']) - - # Add keys for transport correction - if self.correction == 'P0' and self.legendre_order == 0: - tally_keys.extend(['correction', 'flux (analog)']) - - return tally_keys - - @property - def estimator(self): - if self.formulation == 'simple': - return self._estimator - else: - # Add estimators for groupwise scattering cross section - estimators = ['tracklength', 'tracklength'] - - # Add estimators for group-to-group scattering probabilities - estimators.append('analog') - - # Add estimators for multiplicity matrix - if self.nu: - estimators.extend(['analog']) - - # Add estimators for transport correction - if self.correction == 'P0' and self.legendre_order == 0: - estimators.extend(['analog', 'analog']) - - return estimators - - @property - def filters(self): - if self.formulation == 'simple': - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - - if self.scatter_format == 'legendre': - if self.correction == 'P0' and self.legendre_order == 0: - angle_filter = openmc.LegendreFilter(order=1) - else: - angle_filter = \ - openmc.LegendreFilter(order=self.legendre_order) - elif self.scatter_format == 'histogram': - bins = np.linspace(-1., 1., num=self.histogram_bins + 1, - endpoint=True) - angle_filter = openmc.MuFilter(bins) - filters = [[energy], [energy, energyout, angle_filter]] - - else: - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - - # Groupwise scattering cross section - filters = [[energy], [energy]] - - # Group-to-group scattering probability matrix - if self.scatter_format == 'legendre': - angle_filter = openmc.LegendreFilter(order=self.legendre_order) - elif self.scatter_format == 'histogram': - bins = np.linspace(-1., 1., num=self.histogram_bins + 1, - endpoint=True) - angle_filter = openmc.MuFilter(bins) - filters.append([energy, energyout, angle_filter]) - - # Multiplicity matrix - if self.nu: - filters.extend([[energy, energyout]]) - - # Add filters for transport correction - if self.correction == 'P0' and self.legendre_order == 0: - filters.extend([[energyout, openmc.LegendreFilter(1)], - [energy]]) - - return self._add_angle_filters(filters) - - @property - def rxn_rate_tally(self): - - if self._rxn_rate_tally is None: - - if self.formulation == 'simple': - if self.scatter_format == 'legendre': - # If using P0 correction subtract P1 scatter from the diag. - if self.correction == 'P0' and self.legendre_order == 0: - scatter_p0 = self.tallies[self.rxn_type].get_slice( - filters=[openmc.LegendreFilter], - filter_bins=[('P0',)]) - scatter_p1 = self.tallies[self.rxn_type].get_slice( - filters=[openmc.LegendreFilter], - filter_bins=[('P1',)]) - - # Set the Legendre order of these tallies to be 0 - # so they can be subtracted - legendre = openmc.LegendreFilter(order=0) - scatter_p0.filters[-1] = legendre - scatter_p1.filters[-1] = legendre - - scatter_p1 = scatter_p1.summation( - filter_type=openmc.EnergyFilter, - remove_filter=True) - - energy_filter = \ - scatter_p0.find_filter(openmc.EnergyFilter) - - # Transform scatter-p1 into an energyin/out matrix - # to match scattering matrix shape for tally arithmetic - energy_filter = copy.deepcopy(energy_filter) - scatter_p1 = \ - scatter_p1.diagonalize_filter(energy_filter, 1) - - self._rxn_rate_tally = scatter_p0 - scatter_p1 - - # Otherwise, extract scattering moment reaction rate Tally - else: - self._rxn_rate_tally = self.tallies[self.rxn_type] - elif self.scatter_format == 'histogram': - # Extract scattering rate distribution tally - self._rxn_rate_tally = self.tallies[self.rxn_type] - - self._rxn_rate_tally.sparse = self.sparse - - else: - msg = 'The reaction rate tally is poorly defined' \ - ' for the consistent formulation' - raise NotImplementedError(msg) - - return self._rxn_rate_tally - - @property - def xs_tally(self): - if self._xs_tally is None: - if self.tallies is None: - msg = 'Unable to get xs_tally since tallies have ' \ - 'not been loaded from a statepoint' - raise ValueError(msg) - - # Use super class method - if self.formulation == 'simple': - self._xs_tally = MGXS.xs_tally.fget(self) - - else: - # Compute scattering probability matrixS - tally_key = 'scatter matrix' - - # Compute normalization factor summed across outgoing energies - if self.scatter_format == 'legendre': - norm = self.tallies[tally_key].get_slice( - scores=['scatter'], - filters=[openmc.LegendreFilter], - filter_bins=[('P0',)], squeeze=True) - - # Compute normalization factor summed across outgoing mu bins - elif self.scatter_format == 'histogram': - norm = self.tallies[tally_key].get_slice( - scores=['scatter']) - norm = norm.summation( - filter_type=openmc.MuFilter, remove_filter=True) - norm = norm.summation(filter_type=openmc.EnergyoutFilter, - remove_filter=True) - - # Compute groupwise scattering cross section - self._xs_tally = self.tallies['scatter'] * \ - self.tallies[tally_key] / norm / \ - self.tallies['flux (tracklength)'] - - # Override the nuclides for tally arithmetic - self._xs_tally.nuclides = self.tallies['scatter'].nuclides - - # Multiply by the multiplicity matrix - if self.nu: - numer = self.tallies['nu-scatter'] - # Get the denominator - if self.scatter_format == 'legendre': - denom = self.tallies[tally_key].get_slice( - scores=['scatter'], - filters=[openmc.LegendreFilter], - filter_bins=[('P0',)], squeeze=True) - - # Compute normalization factor summed across mu bins - elif self.scatter_format == 'histogram': - denom = self.tallies[tally_key].get_slice( - scores=['scatter']) - - # Sum across all mu bins - denom = denom.summation( - filter_type=openmc.MuFilter, remove_filter=True) - - self._xs_tally *= (numer / denom) - - # If using P0 correction subtract scatter-1 from the diagonal - if self.correction == 'P0' and self.legendre_order == 0: - scatter_p1 = self.tallies['correction'].get_slice( - filters=[openmc.LegendreFilter], filter_bins=[('P1',)]) - flux = self.tallies['flux (analog)'] - - # Set the Legendre order of the P1 tally to be P0 - # so it can be subtracted - legendre = openmc.LegendreFilter(order=0) - scatter_p1.filters[-1] = legendre - - # Transform scatter-p1 tally into an energyin/out matrix - # to match scattering matrix shape for tally arithmetic - energy_filter = flux.find_filter(openmc.EnergyFilter) - energy_filter = copy.deepcopy(energy_filter) - scatter_p1 = scatter_p1.diagonalize_filter(energy_filter, 1) - - # Compute the trasnport correction term - correction = scatter_p1 / flux - - # Override the nuclides for tally arithmetic - correction.nuclides = scatter_p1.nuclides - - # Set xs_tally to be itself with only P0 data - self._xs_tally = self._xs_tally.get_slice( - filters=[openmc.LegendreFilter], filter_bins=[('P0',)]) - # Tell xs_tally that it is P0 - legendre_xs_tally = \ - self._xs_tally.find_filter(openmc.LegendreFilter) - legendre_xs_tally.order = 0 - - # And subtract the P1 correction from the P0 matrix - self._xs_tally -= correction - - self._compute_xs() - - # Force the angle filter to be the last filter - if self.scatter_format == 'histogram': - angle_filter = self._xs_tally.find_filter(openmc.MuFilter) - else: - angle_filter = \ - self._xs_tally.find_filter(openmc.LegendreFilter) - angle_filter_index = self._xs_tally.filters.index(angle_filter) - # If the angle filter index is not last, then make it last - if angle_filter_index != len(self._xs_tally.filters) - 1: - energyout_filter = \ - self._xs_tally.find_filter(openmc.EnergyoutFilter) - self._xs_tally._swap_filters(energyout_filter, - angle_filter) - - return self._xs_tally - - @nu.setter - def nu(self, nu): - cv.check_type('nu', nu, bool) - self._nu = nu - - if self.formulation == 'simple': - if not nu: - self._rxn_type = 'scatter' - self._hdf5_key = 'scatter matrix' - else: - self._rxn_type = 'nu-scatter' - self._hdf5_key = 'nu-scatter matrix' - else: - if not nu: - self._rxn_type = 'scatter' - self._hdf5_key = 'consistent scatter matrix' - else: - self._rxn_type = 'nu-scatter' - self._hdf5_key = 'consistent nu-scatter matrix' - - @formulation.setter - def formulation(self, formulation): - cv.check_value('formulation', formulation, ('simple', 'consistent')) - self._formulation = formulation - - if self.formulation == 'simple': - self._valid_estimators = ['analog'] - if not self.nu: - self._hdf5_key = 'scatter matrix' - else: - self._hdf5_key = 'nu-scatter matrix' - else: - self._valid_estimators = ['tracklength'] - if not self.nu: - self._hdf5_key = 'consistent scatter matrix' - else: - self._hdf5_key = 'consistent nu-scatter matrix' - - @correction.setter - def correction(self, correction): - cv.check_value('correction', correction, ('P0', None)) - - if self.scatter_format == 'legendre': - if correction == 'P0' and self.legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(self.legendre_order) - warnings.warn(msg) - elif self.scatter_format == 'histogram': - msg = 'The P0 correction will be ignored since the ' \ - 'scatter format is set to histogram' - warnings.warn(msg) - - self._correction = correction - - @scatter_format.setter - def scatter_format(self, scatter_format): - cv.check_value('scatter_format', scatter_format, MU_TREATMENTS) - self._scatter_format = scatter_format - - @legendre_order.setter - def legendre_order(self, legendre_order): - cv.check_type('legendre_order', legendre_order, Integral) - cv.check_greater_than('legendre_order', legendre_order, 0, - equality=True) - cv.check_less_than('legendre_order', legendre_order, _MAX_LEGENDRE, - equality=True) - - if self.scatter_format == 'legendre': - if self.correction == 'P0' and legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(self.legendre_order) - warnings.warn(msg, RuntimeWarning) - self.correction = None - elif self.scatter_format == 'histogram': - msg = 'The legendre order will be ignored since the ' \ - 'scatter format is set to histogram' - warnings.warn(msg) - - self._legendre_order = legendre_order - - @histogram_bins.setter - def histogram_bins(self, histogram_bins): - cv.check_type('histogram_bins', histogram_bins, Integral) - cv.check_greater_than('histogram_bins', histogram_bins, 0) - - self._histogram_bins = histogram_bins - - def load_from_statepoint(self, statepoint): - """Extracts tallies in an OpenMC StatePoint with the data needed to - compute multi-group cross sections. - - This method is needed to compute cross section data from tallies - in an OpenMC StatePoint object. - - .. note:: The statepoint must be linked with an OpenMC Summary object. - - Parameters - ---------- - statepoint : openmc.StatePoint - An OpenMC StatePoint object with tally data - - Raises - ------ - ValueError - When this method is called with a statepoint that has not been - linked with a summary object. - - """ - - # Clear any tallies previously loaded from a statepoint - if self.loaded_sp: - self._tallies = None - self._xs_tally = None - self._rxn_rate_tally = None - self._loaded_sp = False - - super().load_from_statepoint(statepoint) - - def get_slice(self, nuclides=[], in_groups=[], out_groups=[], - legendre_order='same'): - """Build a sliced ScatterMatrix for the specified nuclides and - energy groups. - - This method constructs a new MGXS to encapsulate a subset of the data - represented by this MGXS. The subset of data to include in the tally - slice is determined by the nuclides and energy groups specified in - the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - in_groups : list of int - A list of incoming energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - out_groups : list of int - A list of outgoing energy group indices starting at 1 for the high - energies (e.g., [1, 2, 3]; default is []) - legendre_order : int or 'same' - The highest Legendre moment in the sliced MGXS. If order is 'same' - then the sliced MGXS will have the same Legendre moments as the - original MGXS (default). If order is an integer less than the - original MGXS' order, then only those Legendre moments up to that - order will be included in the sliced MGXS. - - Returns - ------- - openmc.mgxs.MatrixMGXS - A new MatrixMGXS which encapsulates the subset of data requested - for the nuclide(s) and/or energy group(s) requested in the - parameters. - - """ - - # Call super class method and null out derived tallies - slice_xs = super().get_slice(nuclides, in_groups) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice the Legendre order if needed - if legendre_order != 'same' and self.scatter_format == 'legendre': - cv.check_type('legendre_order', legendre_order, Integral) - cv.check_less_than('legendre_order', legendre_order, - self.legendre_order, equality=True) - slice_xs.legendre_order = legendre_order - - # Slice the scattering tally - filter_bins = [tuple(['P{}'.format(i) - for i in range(self.legendre_order + 1)])] - slice_xs.tallies[self.rxn_type] = \ - slice_xs.tallies[self.rxn_type].get_slice( - filters=[openmc.LegendreFilter], filter_bins=filter_bins) - - # Slice outgoing energy groups if needed - if len(out_groups) != 0: - filter_bins = [] - for group in out_groups: - group_bounds = self.energy_groups.get_group_bounds(group) - filter_bins.append(group_bounds) - filter_bins = [tuple(filter_bins)] - - # Slice each of the tallies across energyout groups - for tally_type, tally in slice_xs.tallies.items(): - if tally.contains_filter(openmc.EnergyoutFilter): - tally_slice = tally.get_slice( - filters=[openmc.EnergyoutFilter], - filter_bins=filter_bins) - slice_xs.tallies[tally_type] = tally_slice - - slice_xs.sparse = self.sparse - return slice_xs - - def get_xs(self, in_groups='all', out_groups='all', - subdomains='all', nuclides='all', moment='all', - xs_type='macro', order_groups='increasing', - row_column='inout', value='mean', squeeze=True): - r"""Returns an array of multi-group cross sections. - - This method constructs a 5D NumPy array for the requested - multi-group cross section data for one or more subdomains - (1st dimension), energy groups in (2nd dimension), energy groups out - (3rd dimension), nuclides (4th dimension), and moments/histograms - (5th dimension). - - .. note:: The scattering moments are not multiplied by the - :math:`(2\ell+1)/2` prefactor in the expansion of the - scattering source into Legendre moments in the neutron - transport equation. - - Parameters - ---------- - in_groups : Iterable of Integral or 'all' - Incoming energy groups of interest. Defaults to 'all'. - out_groups : Iterable of Integral or 'all' - Outgoing energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the cross sections for all nuclides - in the spatial domain. The special string 'sum' will return the - cross section summed over all nuclides. Defaults to 'all'. - moment : int or 'all' - The scattering matrix moment to return. All moments will be - returned if the moment is 'all' (default); otherwise, a specific - moment will be returned. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - row_column: {'inout', 'outin'} - Return the cross section indexed first by incoming group and - second by outgoing group ('inout'), or vice versa ('outin'). - Defaults to 'inout'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group and subdomain is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - subdomain_bins = [] - for subdomain in subdomains: - subdomain_bins.append(subdomain) - filter_bins.append(tuple(subdomain_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, str): - cv.check_iterable_type('groups', in_groups, Integral) - filters.append(openmc.EnergyFilter) - energy_bins = [] - for group in in_groups: - energy_bins.append( - (self.energy_groups.get_group_bounds(group),)) - filter_bins.append(tuple(energy_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, str): - cv.check_iterable_type('groups', out_groups, Integral) - for group in out_groups: - filters.append(openmc.EnergyoutFilter) - filter_bins.append((self.energy_groups.get_group_bounds(group),)) - - # Construct CrossScore for requested scattering moment - if self.scatter_format == 'legendre': - if moment != 'all': - cv.check_type('moment', moment, Integral) - cv.check_greater_than('moment', moment, 0, equality=True) - cv.check_less_than( - 'moment', moment, self.legendre_order, equality=True) - filters.append(openmc.LegendreFilter) - filter_bins.append(('P{}'.format(moment),)) - num_angle_bins = 1 - else: - num_angle_bins = self.legendre_order + 1 - else: - num_angle_bins = self.histogram_bins - - # Construct a collection of the nuclides to retrieve from the xs tally - if self.by_nuclide: - if nuclides == 'all' or nuclides == 'sum' or nuclides == ['sum']: - query_nuclides = self.get_nuclides() - else: - query_nuclides = nuclides - else: - query_nuclides = ['total'] - - # Use tally summation if user requested the sum for all nuclides - scores = self.xs_tally.scores - if nuclides == 'sum' or nuclides == ['sum']: - xs_tally = self.xs_tally.summation(nuclides=query_nuclides) - xs = xs_tally.get_values(scores=scores, filters=filters, - filter_bins=filter_bins, value=value) - else: - xs = self.xs_tally.get_values(scores=scores, filters=filters, - filter_bins=filter_bins, - nuclides=query_nuclides, value=value) - - # Divide by atom number densities for microscopic cross sections - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - if value == 'mean' or value == 'std_dev': - xs /= densities[np.newaxis, :, np.newaxis] - - # Convert and nans to zero - xs = np.nan_to_num(xs) - - if in_groups == 'all': - num_in_groups = self.num_groups - else: - num_in_groups = len(in_groups) - - if out_groups == 'all': - num_out_groups = self.num_groups - else: - num_out_groups = len(out_groups) - - # Reshape tally data array with separate axes for domain and energy - # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_angle_bins * num_in_groups * - num_out_groups * self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, - num_subdomains, num_in_groups, num_out_groups, - num_angle_bins) - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the scattering matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 3, 4) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[:, :, :, ::-1, ::-1, ...] - else: - new_shape = (num_subdomains, num_in_groups, num_out_groups, - num_angle_bins) - - new_shape += xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Transpose the scattering matrix if requested by user - if row_column == 'outin': - xs = np.swapaxes(xs, 1, 2) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[:, ::-1, ::-1, ...] - - if squeeze: - # We want to squeeze out everything but the angles, in_groups, - # out_groups, and, if needed, num_angle_bins dimension. These must - # not be squeezed so 1-group, 1-angle problems have the correct - # shape. - xs = self._squeeze_xs(xs) - return xs - - def get_pandas_dataframe(self, groups='all', nuclides='all', - xs_type='macro', paths=False): - """Build a Pandas DataFrame for the MGXS data. - - This method leverages :meth:`openmc.Tally.get_pandas_dataframe`, but - renames the columns with terminology appropriate for cross section data. - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will include the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - include the cross sections summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into - a Multi-index column with a geometric "path" to each distribcell - instance. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame for the cross section data. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - # Build the dataframe using the parent class method - df = super().get_pandas_dataframe(groups, nuclides, xs_type, - paths=paths) - - # If the matrix is P0, remove the legendre column - if self.scatter_format == 'legendre' and self.legendre_order == 0: - df = df.drop(axis=1, labels=['legendre']) - - return df - - def print_xs(self, subdomains='all', nuclides='all', - xs_type='macro', moment=0): - """Prints a string representation for the multi-group cross section. - - Parameters - ---------- - subdomains : Iterable of Integral or 'all' - The subdomain IDs of the cross sections to include in the report. - Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the report. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - report the cross sections summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return the macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - moment : int - The scattering moment to print (default is 0) - - """ - - # Construct a collection of the subdomains to report - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral) - elif self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - elif self.domain_type == 'mesh': - subdomains = list(self.domain.indices) - else: - subdomains = [self.domain.id] - - # Construct a collection of the nuclides to report - if self.by_nuclide: - if nuclides == 'all': - nuclides = self.get_nuclides() - if nuclides == 'sum': - nuclides = ['sum'] - else: - cv.check_iterable_type('nuclides', nuclides, str) - else: - nuclides = ['sum'] - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - if self.correction != 'P0' and self.scatter_format == 'legendre': - rxn_type = '{0} (P{1})'.format(self.rxn_type, moment) - else: - rxn_type = self.rxn_type - - # Build header for string with type and domain info - string = 'Multi-Group XS\n' - string += '{0: <16}=\t{1}\n'.format('\tReaction Type', rxn_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type) - string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id) - - # Generate the header for an individual XS - xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type)) - - # If cross section data has not been computed, only print string header - if self.tallies is None: - print(string) - return - - string += '{0: <16}\n'.format('\tEnergy Groups:') - template = '{0: <12}Group {1} [{2: <10} - {3: <10}eV]\n' - - # Loop over energy groups ranges - for group in range(1, self.num_groups + 1): - bounds = self.energy_groups.get_group_bounds(group) - string += template.format('', group, bounds[0], bounds[1]) - - # Set polar and azimuthal bins if necessary - if self.num_polar > 1 or self.num_azimuthal > 1: - pol_bins = np.linspace(0., np.pi, num=self.num_polar + 1, - endpoint=True) - azi_bins = np.linspace(-np.pi, np.pi, num=self.num_azimuthal + 1, - endpoint=True) - - # Loop over all subdomains - for subdomain in subdomains: - - if self.domain_type == 'distribcell' or self.domain_type == 'mesh': - string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain) - - # Loop over all Nuclides - for nuclide in nuclides: - - # Build header for nuclide type - if xs_type != 'sum': - string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide) - - # Build header for cross section type - string += '{0: <16}\n'.format(xs_header) - - average_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='mean', - moment=moment) - rel_err_xs = self.get_xs(nuclides=[nuclide], - subdomains=[subdomain], - xs_type=xs_type, value='rel_err', - moment=moment) - rel_err_xs = rel_err_xs * 100. - - # Create a function for printing group and histogram data - def print_groups_and_histogram(avg_xs, err_xs, num_groups, - num_histogram_bins): - template = '{0: <12}Group {1} -> Group {2}:\t\t' - to_print = "" - # Loop over incoming/outgoing energy groups ranges - for in_group in range(1, num_groups + 1): - for out_group in range(1, num_groups + 1): - to_print += template.format('', in_group, - out_group) - if num_histogram_bins > 0: - for i in range(num_histogram_bins): - to_print += \ - '\n{0: <16}Histogram Bin {1}:{2: <6}'.format( - '', i + 1, '') - to_print += '{0:.2e} +/- {1:.2e}%'.format( - avg_xs[in_group - 1, out_group - 1, i], - err_xs[in_group - 1, out_group - 1, i]) - to_print += '\n' - else: - to_print += '{0:.2e} +/- {1:.2e}%'.format( - avg_xs[in_group - 1, out_group - 1], - err_xs[in_group - 1, out_group - 1]) - to_print += '\n' - to_print += '\n' - return to_print - - # Set the number of histogram bins - if self.scatter_format == 'histogram': - num_mu_bins = self.histogram_bins - else: - num_mu_bins = 0 - - if self.num_polar > 1 or self.num_azimuthal > 1: - # Loop over polar, azi, and in/out energy group ranges - for pol in range(len(pol_bins) - 1): - pol_low, pol_high = pol_bins[pol: pol + 2] - for azi in range(len(azi_bins) - 1): - azi_low, azi_high = azi_bins[azi: azi + 2] - string += \ - '\t\tPolar Angle: [{0:5f} - {1:5f}]'.format( - pol_low, pol_high) + \ - '\tAzimuthal Angle: [{0:5f} - {1:5f}]'.format( - azi_low, azi_high) + '\n' - string += print_groups_and_histogram( - average_xs[pol, azi, ...], - rel_err_xs[pol, azi, ...], self.num_groups, - num_mu_bins) - string += '\n' - else: - string += print_groups_and_histogram( - average_xs, rel_err_xs, self.num_groups, num_mu_bins) - string += '\n' - string += '\n' - string += '\n' - - print(string) - - -class MultiplicityMatrixXS(MatrixMGXS): - r"""The scattering multiplicity matrix. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`MultiplicityMatrixXS.energy_groups` and - :attr:`MultiplicityMatrixXS.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`MultiplicityMatrixXS.tallies` property, which - can then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`MultiplicityMatrixXS.xs_tally` - property. - - For a spatial domain :math:`V`, incoming energy group - :math:`[E_{g'},E_{g'-1}]`, and outgoing energy group :math:`[E_g,E_{g-1}]`, - the multiplicity is calculated as: - - .. math:: - - \begin{aligned} - \langle \upsilon \sigma_{s,g'\rightarrow g} \phi \rangle &= \int_{r \in - D} dr \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \sum_i \upsilon_i \sigma_i (r, E' \rightarrow - E, \Omega' \cdot \Omega) \psi(r, E', \Omega') \\ - \langle \sigma_{s,g'\rightarrow g} \phi \rangle &= \int_{r \in - D} dr \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \sum_i \upsilon_i \sigma_i (r, E' \rightarrow - E, \Omega' \cdot \Omega) \psi(r, E', \Omega') \\ - \upsilon_{g'\rightarrow g} &= \frac{\langle \upsilon - \sigma_{s,g'\rightarrow g} \rangle}{\langle \sigma_{s,g'\rightarrow g} - \rangle} - \end{aligned} - - where :math:`\upsilon_i` is the multiplicity for the :math:`i`-th reaction. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`MultiplicityMatrixXS.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'multiplicity matrix' - self._estimator = 'analog' - self._valid_estimators = ['analog'] - - @property - def scores(self): - scores = ['nu-scatter', 'scatter'] - return scores - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - filters = [[energy, energyout], [energy, energyout]] - - return self._add_angle_filters(filters) - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies['nu-scatter'] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - @property - def xs_tally(self): - - if self._xs_tally is None: - scatter = self.tallies['scatter'] - - # Compute the multiplicity - self._xs_tally = self.rxn_rate_tally / scatter - super()._compute_xs() - - return self._xs_tally - - -class ScatterProbabilityMatrix(MatrixMGXS): - r"""The group-to-group scattering probability matrix. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`ScatterProbabilityMatrix.energy_groups` - and :attr:`ScatterProbabilityMatrix.domain` properties. Tallies for the - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`ScatterProbabilityMatrix.tallies` property, - which can then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`ScatterProbabilityMatrix.xs_tally` - property. - - For a spatial domain :math:`V`, incoming energy group - :math:`[E_{g'},E_{g'-1}]`, and outgoing energy group :math:`[E_g,E_{g-1}]`, - the group-to-group scattering probabilities are calculated as: - - .. math:: - - \begin{aligned} - \langle \sigma_{s,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \sigma_{s} (r, E' \rightarrow E, \Omega' - \cdot \Omega) \psi(r, E', \Omega')\\ - \langle \sigma_{s,0,g'} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{4\pi} d\Omega - \int_{0}^{\infty} dE \; \sigma_s (r, E' - \rightarrow E, \Omega' \cdot \Omega) \psi(r, E', \Omega')\\ - P_{s,g'\rightarrow g} &= \frac{\langle - \sigma_{s,g'\rightarrow g} \phi \rangle}{\langle - \sigma_{s,g'} \phi \rangle} - \end{aligned} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`ScatterProbabilityMatrix.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, - name, num_polar, num_azimuthal) - - self._rxn_type = 'scatter' - self._hdf5_key = 'scatter probability matrix' - self._estimator = 'analog' - self._valid_estimators = ['analog'] - - @property - def scores(self): - return [self.rxn_type] - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energy = openmc.EnergyFilter(group_edges) - energyout = openmc.EnergyoutFilter(group_edges) - filters = [[energy, energyout]] - return self._add_angle_filters(filters) - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies[self.rxn_type] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - @property - def xs_tally(self): - - if self._xs_tally is None: - norm = self.rxn_rate_tally.get_slice(scores=[self.rxn_type]) - norm = norm.summation( - filter_type=openmc.EnergyoutFilter, remove_filter=True) - - # Compute the group-to-group probabilities - self._xs_tally = self.tallies[self.rxn_type] / norm - super()._compute_xs() - - return self._xs_tally - - -class NuFissionMatrixXS(MatrixMGXS): - r"""A fission production matrix multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`NuFissionMatrixXS.energy_groups` and - :attr:`NuFissionMatrixXS.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`NuFissionMatrixXS.tallies` property, which can - then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`NuFissionMatrixXS.xs_tally` property. - - For a spatial domain :math:`V`, incoming energy group - :math:`[E_{g'},E_{g'-1}]`, and outgoing energy group :math:`[E_g,E_{g-1}]`, - the fission production is calculated as: - - .. math:: - - \begin{aligned} - \langle \nu\sigma_{f,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{E_g}^{E_{g-1}} dE - \; \chi(E) \nu\sigma_f (r, E') \psi(r, E', \Omega')\\ - \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega - \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ - \nu\sigma_{f,g'\rightarrow g} &= \frac{\langle \nu\sigma_{f,g'\rightarrow - g} \phi \rangle}{\langle \phi \rangle} - \end{aligned} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - prompt : bool - If true, computes cross sections which only includes prompt neutrons; - defaults to False which includes prompt and delayed in total - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - prompt : bool - If true, computes cross sections which only includes prompt neutrons - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`NuFissionMatrixXS.tally_keys` - property and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, - num_azimuthal=1, prompt=False): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - if not prompt: - self._rxn_type = 'nu-fission' - self._hdf5_key = 'nu-fission matrix' - else: - self._rxn_type = 'prompt-nu-fission' - self._hdf5_key = 'prompt-nu-fission matrix' - self._estimator = 'analog' - self._valid_estimators = ['analog'] - self.prompt = prompt - - @property - def prompt(self): - return self._prompt - - @prompt.setter - def prompt(self, prompt): - cv.check_type('prompt', prompt, bool) - self._prompt = prompt - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._prompt = self.prompt - return clone - - -class Chi(MGXS): - r"""The fission spectrum. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group cross sections for multi-group neutronics calculations. At a - minimum, one needs to set the :attr:`Chi.energy_groups` and - :attr:`Chi.domain` properties. Tallies for the flux and appropriate reaction - rates over the specified domain are generated automatically via the - :attr:`Chi.tallies` property, which can then be appended to a - :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`Chi.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - fission spectrum is calculated as: - - .. math:: - - \begin{aligned} - \langle \nu\sigma_{f,g' \rightarrow g} \phi \rangle &= \int_{r \in V} dr - \int_{4\pi} d\Omega' \int_0^\infty dE' \int_{E_g}^{E_{g-1}} dE \; \chi(E) - \nu\sigma_f (r, E') \psi(r, E', \Omega')\\ - \langle \nu\sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi} - d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu\sigma_f (r, - E') \psi(r, E', \Omega') \\ - \chi_g &= \frac{\langle \nu\sigma_{f,g' \rightarrow g} \phi \rangle} - {\langle \nu\sigma_f \phi \rangle} - \end{aligned} - - This class can also be used to gather a prompt-chi (which only includes the - outgoing energy spectrum of prompt neutrons). This is accomplished by - setting the :attr:`Chi.prompt` attribute to `True`. - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - prompt : bool - If true, computes cross sections which only includes prompt neutrons; - defaults to False which includes prompt and delayed in total - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - prompt : bool - If true, computes cross sections which only includes prompt neutrons - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : 'analog' - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`Chi.tally_keys` property and values are - instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file). - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - prompt=False, by_nuclide=False, name='', num_polar=1, - num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - if not prompt: - self._rxn_type = 'chi' - else: - self._rxn_type = 'chi-prompt' - self._estimator = 'analog' - self._valid_estimators = ['analog'] - self.prompt = prompt - - def __deepcopy__(self, memo): - clone = super().__deepcopy__(memo) - clone._prompt = self.prompt - return clone - - @property - def prompt(self): - return self._prompt - - @property - def _dont_squeeze(self): - """Create a tuple of axes which should not be removed during the get_xs - process - """ - if self.num_polar > 1 or self.num_azimuthal > 1: - return (0, 1, 3) - else: - return (1,) - - @property - def scores(self): - if not self.prompt: - return ['nu-fission', 'nu-fission'] - else: - return ['prompt-nu-fission', 'prompt-nu-fission'] - - @property - def filters(self): - # Create the non-domain specific Filters for the Tallies - group_edges = self.energy_groups.group_edges - energyout = openmc.EnergyoutFilter(group_edges) - energyin = openmc.EnergyFilter([group_edges[0], group_edges[-1]]) - filters = [[energyin], [energyout]] - - return self._add_angle_filters(filters) - - @property - def tally_keys(self): - return ['nu-fission-in', 'nu-fission-out'] - - @property - def rxn_rate_tally(self): - if self._rxn_rate_tally is None: - self._rxn_rate_tally = self.tallies['nu-fission-out'] - self._rxn_rate_tally.sparse = self.sparse - return self._rxn_rate_tally - - @property - def xs_tally(self): - - if self._xs_tally is None: - nu_fission_in = self.tallies['nu-fission-in'] - - # Remove coarse energy filter to keep it out of tally arithmetic - energy_filter = nu_fission_in.find_filter(openmc.EnergyFilter) - nu_fission_in.remove_filter(energy_filter) - - # Compute chi - self._xs_tally = self.rxn_rate_tally / nu_fission_in - - # Add the coarse energy filter back to the nu-fission tally - nu_fission_in.filters.append(energy_filter) - - return self._xs_tally - - @prompt.setter - def prompt(self, prompt): - cv.check_type('prompt', prompt, bool) - self._prompt = prompt - if not self.prompt: - self._rxn_type = 'nu-fission' - self._hdf5_key = 'chi' - else: - self._rxn_type = 'prompt-nu-fission' - self._hdf5_key = 'chi-prompt' - - def get_homogenized_mgxs(self, other_mgxs): - """Construct a homogenized mgxs with other MGXS objects. - - Parameters - ---------- - other_mgxs : openmc.mgxs.MGXS or Iterable of openmc.mgxs.MGXS - The MGXS to homogenize with this one. - - Returns - ------- - openmc.mgxs.MGXS - A new homogenized MGXS - - Raises - ------ - ValueError - If the other_mgxs is of a different type. - - """ - - return self._get_homogenized_mgxs(other_mgxs, 'nu-fission-in') - - def get_slice(self, nuclides=[], groups=[]): - """Build a sliced Chi for the specified nuclides and energy groups. - - This method constructs a new MGXS to encapsulate a subset of the data - represented by this MGXS. The subset of data to include in the tally - slice is determined by the nuclides and energy groups specified in - the input parameters. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - groups : list of Integral - A list of energy group indices starting at 1 for the high energies - (e.g., [1, 2, 3]; default is []) - - Returns - ------- - openmc.mgxs.MGXS - A new MGXS which encapsulates the subset of data requested - for the nuclide(s) and/or energy group(s) requested in the - parameters. - - """ - - # Temporarily remove energy filter from nu-fission-in since its - # group structure will work in super MGXS.get_slice(...) method - nu_fission_in = self.tallies['nu-fission-in'] - energy_filter = nu_fission_in.find_filter(openmc.EnergyFilter) - nu_fission_in.remove_filter(energy_filter) - - # Call super class method and null out derived tallies - slice_xs = super().get_slice(nuclides, groups) - slice_xs._rxn_rate_tally = None - slice_xs._xs_tally = None - - # Slice energy groups if needed - if len(groups) != 0: - filter_bins = [] - for group in groups: - group_bounds = self.energy_groups.get_group_bounds(group) - filter_bins.append(group_bounds) - filter_bins = [tuple(filter_bins)] - - # Slice nu-fission-out tally along energyout filter - nu_fission_out = slice_xs.tallies['nu-fission-out'] - tally_slice = nu_fission_out.get_slice( - filters=[openmc.EnergyoutFilter], filter_bins=filter_bins) - slice_xs._tallies['nu-fission-out'] = tally_slice - - # Add energy filter back to nu-fission-in tallies - self.tallies['nu-fission-in'].add_filter(energy_filter) - slice_xs._tallies['nu-fission-in'].add_filter(energy_filter) - - slice_xs.sparse = self.sparse - return slice_xs - - def merge(self, other): - """Merge another Chi with this one - - If results have been loaded from a statepoint, then Chi are only - mergeable along one and only one of energy groups or nuclides. - - Parameters - ---------- - other : openmc.mgxs.MGXS - MGXS to merge with this one - - Returns - ------- - merged_mgxs : openmc.mgxs.MGXS - Merged MGXS - """ - - if not self.can_merge(other): - raise ValueError('Unable to merge a Chi MGXS') - - # Create deep copy of tally to return as merged tally - merged_mgxs = copy.deepcopy(self) - merged_mgxs._derived = True - merged_mgxs._rxn_rate_tally = None - merged_mgxs._xs_tally = None - - # Merge energy groups - if self.energy_groups != other.energy_groups: - merged_groups = self.energy_groups.merge(other.energy_groups) - merged_mgxs.energy_groups = merged_groups - - # Merge nuclides - if self.nuclides != other.nuclides: - - # The nuclides must be mutually exclusive - for nuclide in self.nuclides: - if nuclide in other.nuclides: - msg = 'Unable to merge a Chi MGXS with shared nuclides' - raise ValueError(msg) - - # Concatenate lists of nuclides for the merged MGXS - merged_mgxs.nuclides = self.nuclides + other.nuclides - - # Merge tallies - for tally_key in self.tallies: - merged_tally = self.tallies[tally_key].merge(other.tallies[tally_key]) - merged_mgxs.tallies[tally_key] = merged_tally - - return merged_mgxs - - def get_xs(self, groups='all', subdomains='all', nuclides='all', - xs_type='macro', order_groups='increasing', - value='mean', squeeze=True, **kwargs): - """Returns an array of the fission spectrum. - - This method constructs a 3D NumPy array for the requested - multi-group cross section data for one or more subdomains - (1st dimension), energy groups (2nd dimension), and nuclides - (3rd dimension). - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - subdomains : Iterable of Integral or 'all' - Subdomain IDs of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - A list of nuclide name strings (e.g., ['U235', 'U238']). The - special string 'all' will return the cross sections for all nuclides - in the spatial domain. The special string 'sum' will return the - cross section summed over all nuclides. Defaults to 'all'. - xs_type: {'macro', 'micro'} - This parameter is not relevant for chi but is included here to - mirror the parent MGXS.get_xs(...) class method - order_groups: {'increasing', 'decreasing'} - Return the cross section indexed according to increasing or - decreasing energy groups (decreasing or increasing energies). - Defaults to 'increasing'. - value : {'mean', 'std_dev', 'rel_err'} - A string for the type of value to return. Defaults to 'mean'. - squeeze : bool - A boolean representing whether to eliminate the extra dimensions - of the multi-dimensional array to be returned. Defaults to True. - - Returns - ------- - numpy.ndarray - A NumPy array of the multi-group cross section indexed in the order - each group, subdomain and nuclide is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # FIXME: Unable to get microscopic xs for mesh domain because the mesh - # cells do not know the nuclide densities in each mesh cell. - if self.domain_type == 'mesh' and xs_type == 'micro': - msg = 'Unable to get micro xs for mesh domain since the mesh ' \ - 'cells do not know the nuclide densities in each mesh cell.' - raise ValueError(msg) - - filters = [] - filter_bins = [] - - # Construct a collection of the domain filter bins - if not isinstance(subdomains, str): - cv.check_iterable_type('subdomains', subdomains, Integral, - max_depth=3) - filters.append(_DOMAIN_TO_FILTER[self.domain_type]) - subdomain_bins = [] - for subdomain in subdomains: - subdomain_bins.append(subdomain) - filter_bins.append(tuple(subdomain_bins)) - - # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, str): - cv.check_iterable_type('groups', groups, Integral) - filters.append(openmc.EnergyoutFilter) - energy_bins = [] - for group in groups: - energy_bins.append( - (self.energy_groups.get_group_bounds(group),)) - filter_bins.append(tuple(energy_bins)) - - # If chi was computed for each nuclide in the domain - if self.by_nuclide: - - # Get the sum as the fission source weighted average chi for all - # nuclides in the domain - if nuclides == 'sum' or nuclides == ['sum']: - - # Retrieve the fission production tallies - nu_fission_in = self.tallies['nu-fission-in'] - nu_fission_out = self.tallies['nu-fission-out'] - - # Sum out all nuclides - nuclides = self.get_nuclides() - nu_fission_in = nu_fission_in.summation(nuclides=nuclides) - nu_fission_out = nu_fission_out.summation(nuclides=nuclides) - - # Remove coarse energy filter to keep it out of tally arithmetic - energy_filter = nu_fission_in.find_filter(openmc.EnergyFilter) - nu_fission_in.remove_filter(energy_filter) - - # Compute chi and store it as the xs_tally attribute so we can - # use the generic get_xs(...) method - xs_tally = nu_fission_out / nu_fission_in - - # Add the coarse energy filter back to the nu-fission tally - nu_fission_in.filters.append(energy_filter) - - xs = xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - - # Get chi for all nuclides in the domain - elif nuclides == 'all': - nuclides = self.get_nuclides() - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=nuclides, value=value) - - # Get chi for user-specified nuclides in the domain - else: - cv.check_iterable_type('nuclides', nuclides, str) - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, - nuclides=nuclides, value=value) - - # If chi was computed as an average of nuclides in the domain - else: - xs = self.xs_tally.get_values(filters=filters, - filter_bins=filter_bins, value=value) - - # Eliminate the trivial score dimension - xs = np.squeeze(xs, axis=len(xs.shape) - 1) - xs = np.nan_to_num(xs) - - if groups == 'all': - num_groups = self.num_groups - else: - num_groups = len(groups) - - # Reshape tally data array with separate axes for domain and energy - # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_groups * self.num_polar * - self.num_azimuthal)) - if self.num_polar > 1 or self.num_azimuthal > 1: - new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, - num_groups) + xs.shape[1:] - else: - new_shape = (num_subdomains, num_groups) + xs.shape[1:] - xs = np.reshape(xs, new_shape) - - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, :] - - if squeeze: - # We want to squeeze out everything but the polar, azimuthal, - # and energy group data. - xs = self._squeeze_xs(xs) - - return xs - - def get_pandas_dataframe(self, groups='all', nuclides='all', - xs_type='macro', paths=False): - """Build a Pandas DataFrame for the MGXS data. - - This method leverages :meth:`openmc.Tally.get_pandas_dataframe`, but - renames the columns with terminology appropriate for cross section data. - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will include the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - include the cross sections summed over all nuclides. Defaults to - 'all'. - xs_type: {'macro', 'micro'} - Return macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into - a Multi-index column with a geometric "path" to each distribcell - instance. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame for the cross section data. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - # Build the dataframe using the parent class method - df = super().get_pandas_dataframe(groups, nuclides, xs_type, paths=paths) - - # If user requested micro cross sections, multiply by the atom - # densities to cancel out division made by the parent class method - if xs_type == 'micro': - if self.by_nuclide: - densities = self.get_nuclide_densities(nuclides) - else: - densities = self.get_nuclide_densities('sum') - tile_factor = int(df.shape[0] / len(densities)) - df['mean'] *= np.tile(densities, tile_factor) - df['std. dev.'] *= np.tile(densities, tile_factor) - - return df - - def get_units(self, xs_type='macro'): - """Returns the units of Chi. - - This method returns the units of Chi, which is "%" for both macro - and micro xs types. - - Parameters - ---------- - xs_type: {'macro', 'micro'} - Return the macro or micro cross section units. - Defaults to 'macro'. - - Returns - ------- - str - A string representing the units of Chi. - - """ - - cv.check_value('xs_type', xs_type, ['macro', 'micro']) - - # Chi has the same units (%) for both macro and micro - return '%' - - -class InverseVelocity(MGXS): - r"""An inverse velocity multi-group cross section. - - This class can be used for both OpenMC input generation and tally data - post-processing to compute spatially-homogenized and energy-integrated - multi-group neutron inverse velocities for multi-group neutronics - calculations. The units of inverse velocity are seconds per centimeter. At a - minimum, one needs to set the :attr:`InverseVelocity.energy_groups` and - :attr:`InverseVelocity.domain` properties. Tallies for the flux and - appropriate reaction rates over the specified domain are generated - automatically via the :attr:`InverseVelocity.tallies` property, which can - then be appended to a :class:`openmc.Tallies` instance. - - For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the - necessary data to compute multi-group cross sections from a - :class:`openmc.StatePoint` instance. The derived multi-group cross section - can then be obtained from the :attr:`InverseVelocity.xs_tally` property. - - For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the - neutron inverse velocities are calculated by tallying the flux-weighted - inverse velocity and the flux. The inverse velocity is then the - flux-weighted inverse velocity divided by the flux: - - .. math:: - - \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; - \frac{\psi (r, E, \Omega)}{v (r, E)}}{\int_{r \in V} dr \int_{4\pi} - d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)} - - Parameters - ---------- - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - The domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - The domain type for spatial homogenization - groups : openmc.mgxs.EnergyGroups - The energy group structure for energy condensation - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - name : str, optional - Name of the multi-group cross section. Used as a label to identify - tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional - Number of equi-width polar angle bins for angle discretization; - defaults to one bin - num_azimuthal : Integral, optional - Number of equi-width azimuthal angle bins for angle discretization; - defaults to one bin - - Attributes - ---------- - name : str, optional - Name of the multi-group cross section - rxn_type : str - Reaction type (e.g., 'total', 'nu-fission', etc.) - by_nuclide : bool - If true, computes cross sections for each nuclide in domain - domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh - Domain for spatial homogenization - domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} - Domain type for spatial homogenization - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure for energy condensation - num_polar : Integral - Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral - Number of equi-width azimuthal angle bins for angle discretization - tally_trigger : openmc.Trigger - An (optional) tally precision trigger given to each tally used to - compute the cross section - scores : list of str - The scores in each tally used to compute the multi-group cross section - filters : list of openmc.Filter - The filters in each tally used to compute the multi-group cross section - tally_keys : list of str - The keys into the tallies dictionary for each tally used to compute - the multi-group cross section - estimator : {'tracklength', 'collision', 'analog'} - The tally estimator used to compute the multi-group cross section - tallies : collections.OrderedDict - OpenMC tallies needed to compute the multi-group cross section. The keys - are strings listed in the :attr:`InverseVelocity.tally_keys` property - and values are instances of :class:`openmc.Tally`. - rxn_rate_tally : openmc.Tally - Derived tally for the reaction rate tally used in the numerator to - compute the multi-group cross section. This attribute is None - unless the multi-group cross section has been computed. - xs_tally : openmc.Tally - Derived tally for the multi-group cross section. This attribute - is None unless the multi-group cross section has been computed. - num_subdomains : int - The number of subdomains is unity for 'material', 'cell' and 'universe' - domain types. This is equal to the number of cell instances - for 'distribcell' domain types (it is equal to unity prior to loading - tally data from a statepoint file) and the number of mesh cells for - 'mesh' domain types. - num_nuclides : int - The number of nuclides for which the multi-group cross section is - being tracked. This is unity if the by_nuclide attribute is False. - nuclides : Iterable of str or 'sum' - The optional user-specified nuclides for which to compute cross - sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides - are not specified by the user, all nuclides in the spatial domain - are included. This attribute is 'sum' if by_nuclide is false. - sparse : bool - Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format - for compressed data storage - loaded_sp : bool - Whether or not a statepoint file has been loaded with tally data - derived : bool - Whether or not the MGXS is merged from one or more other MGXS - hdf5_key : str - The key used to index multi-group cross sections in an HDF5 data store - - """ - - def __init__(self, domain=None, domain_type=None, groups=None, - by_nuclide=False, name='', num_polar=1, num_azimuthal=1): - super().__init__(domain, domain_type, groups, by_nuclide, name, - num_polar, num_azimuthal) - self._rxn_type = 'inverse-velocity' - - def get_units(self, xs_type='macro'): - """Returns the units of InverseVelocity. - - This method returns the units of an InverseVelocity based on a desired - xs_type. - - Parameters - ---------- - xs_type: {'macro', 'micro'} - Return the macro or micro cross section units. - Defaults to 'macro'. - - Returns - ------- - str - A string representing the units of the InverseVelocity. - - """ - - if xs_type == 'macro': - return 'second/cm' - else: - raise ValueError('Unable to return the units of InverseVelocity' - ' for xs_type other than "macro"') diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py deleted file mode 100644 index b98902030..000000000 --- a/openmc/mgxs_library.py +++ /dev/null @@ -1,2577 +0,0 @@ -import copy -from numbers import Real, Integral -import os - -import numpy as np -import h5py -from scipy.interpolate import interp1d -from scipy.integrate import simps -from scipy.special import eval_legendre - -import openmc -import openmc.mgxs -from openmc.checkvalue import check_type, check_value, check_greater_than, \ - check_iterable_type, check_less_than, check_filetype_version - - -# Supported incoming particle MGXS angular treatment representations -_REPRESENTATIONS = ['isotropic', 'angle'] - -# Supported scattering angular distribution representations -_SCATTER_TYPES = ['tabular', 'legendre', 'histogram'] - -# List of MGXS indexing schemes -_XS_SHAPES = ["[G][G'][Order]", "[G]", "[G']", "[G][G']", "[DG]", "[DG][G]", - "[DG][G']", "[DG][G][G']"] - -# Number of mu points for conversion between scattering formats -_NMU = 257 - -# Filetype name of the MGXS Library -_FILETYPE_MGXS_LIBRARY = 'mgxs' - -# Current version of the MGXS Library Format -_VERSION_MGXS_LIBRARY = 1 - - -class XSdata(object): - """A multi-group cross section data set providing all the - multi-group data necessary for a multi-group OpenMC calculation. - - Parameters - ---------- - name : str - Name of the mgxs data set. - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure - representation : {'isotropic', 'angle'}, optional - Method used in generating the MGXS (isotropic or angle-dependent flux - weighting). Defaults to 'isotropic' - temperatures : Iterable of float - Temperatures (in units of Kelvin) of the provided datasets. Defaults - to a single temperature at 294K. - num_delayed_groups : int - Number of delayed groups - - Attributes - ---------- - name : str - Unique identifier for the xsdata object - atomic_weight_ratio : float - Atomic weight ratio of an isotope. That is, the ratio of the mass - of the isotope to the mass of a single neutron. - temperatures : numpy.ndarray - Temperatures (in units of Kelvin) of the provided datasets. Defaults - to a single temperature at 294K. - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure - num_delayed_groups : int - Num delayed groups - fissionable : bool - Whether or not this is a fissionable data set. - scatter_format : {'legendre', 'histogram', or 'tabular'} - Angular distribution representation (legendre, histogram, or tabular) - order : int - Either the Legendre order, number of bins, or number of points used to - describe the angular distribution associated with each group-to-group - transfer probability. - representation : {'isotropic', 'angle'} - Method used in generating the MGXS (isotropic or angle-dependent flux - weighting). - num_azimuthal : int - Number of equal width angular bins that the azimuthal angular domain is - subdivided into. This only applies when :attr:`XSdata.representation` - is "angle". - num_polar : int - Number of equal width angular bins that the polar angular domain is - subdivided into. This only applies when :attr:`XSdata.representation` - is "angle". - total : list of numpy.ndarray - Group-wise total cross section. - absorption : list of numpy.ndarray - Group-wise absorption cross section. - scatter_matrix : list of numpy.ndarray - Scattering moment matrices presented with the columns representing - incoming group and rows representing the outgoing group. That is, - down-scatter will be above the diagonal of the resultant matrix. - multiplicity_matrix : list of numpy.ndarray - Ratio of neutrons produced in scattering collisions to the neutrons - which undergo scattering collisions; that is, the multiplicity provides - the code with a scaling factor to account for neutrons produced in - (n,xn) reactions. - fission : list of numpy.ndarray - Group-wise fission cross section. - kappa_fission : list of numpy.ndarray - Group-wise kappa_fission cross section. - chi : list of numpy.ndarray - Group-wise fission spectra ordered by increasing group index (i.e., - fast to thermal). This attribute should be used if making the common - approximation that the fission spectra does not depend on incoming - energy. If the user does not wish to make this approximation, then - this should not be provided and this information included in the - :attr:`XSdata.nu_fission` attribute instead. - chi_prompt : list of numpy.ndarray - Group-wise prompt fission spectra ordered by increasing group index - (i.e., fast to thermal). This attribute should be used if chi from - prompt and delayed neutrons is being set separately. - chi_delayed : list of numpy.ndarray - Group-wise delayed fission spectra ordered by increasing group index - (i.e., fast to thermal). This attribute should be used if chi from - prompt and delayed neutrons is being set separately. - nu_fission : list of numpy.ndarray - Group-wise fission production cross section vector (i.e., if ``chi`` is - provided), or is the group-wise fission production matrix. - prompt_nu_fission : list of numpy.ndarray - Group-wise prompt fission production cross section vector. - delayed_nu_fission : list of numpy.ndarray - Group-wise delayed fission production cross section vector. - beta : list of numpy.ndarray - Delayed-group-wise delayed neutron fraction cross section vector. - decay_rate : list of numpy.ndarray - Delayed-group-wise decay rate vector. - inverse_velocity : list of numpy.ndarray - Inverse of velocity, in units of sec/cm. - xs_shapes : dict of iterable of int - Dictionary with keys of _XS_SHAPES and iterable of int values with the - corresponding shapes where "Order" corresponds to the pn scattering - order, "G" corresponds to incoming energy group, "G'" corresponds to - outgoing energy group, and "DG" corresponds to delayed group. - - Notes - ----- - The parameters containing cross section data have dimensionalities which - depend upon the value of :attr:`XSdata.representation` as well as the - number of Legendre or other angular dimensions as described by - :attr:`XSdata.order`. The :attr:`XSdata.xs_shapes` are provided to obtain - the dimensionality of the data for each temperature. - - The following are cross sections which should use each of the properties. - Note that some cross sections can be input in more than one shape so they - are listed multiple times: - - [G][G'][Order]: scatter_matrix - - [G]: total, absorption, fission, kappa_fission, nu_fission, - prompt_nu_fission, delayed_nu_fission, inverse_velocity - - [G']: chi, chi_prompt, chi_delayed - - [G][G']: multiplicity_matrix, nu_fission, prompt_nu_fission - - [DG]: beta, decay_rate - - [DG][G]: delayed_nu_fission, beta, decay_rate - - [DG][G']: chi_delayed - - [DG][G][G']: delayed_nu_fission - - """ - - def __init__(self, name, energy_groups, temperatures=[294.], - representation='isotropic', num_delayed_groups=0): - - # Initialize class attributes - self.name = name - self.energy_groups = energy_groups - self.num_delayed_groups = num_delayed_groups - self.temperatures = temperatures - self.representation = representation - self._atomic_weight_ratio = None - self._fissionable = False - self._scatter_format = 'legendre' - self._order = None - self._num_polar = None - self._num_azimuthal = None - self._total = len(temperatures) * [None] - self._absorption = len(temperatures) * [None] - self._scatter_matrix = len(temperatures) * [None] - self._multiplicity_matrix = len(temperatures) * [None] - self._fission = len(temperatures) * [None] - self._nu_fission = len(temperatures) * [None] - self._prompt_nu_fission = len(temperatures) * [None] - self._delayed_nu_fission = len(temperatures) * [None] - self._kappa_fission = len(temperatures) * [None] - self._chi = len(temperatures) * [None] - self._chi_prompt = len(temperatures) * [None] - self._chi_delayed = len(temperatures) * [None] - self._beta = len(temperatures) * [None] - self._decay_rate = len(temperatures) * [None] - self._inverse_velocity = len(temperatures) * [None] - self._xs_shapes = None - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, copy it - if existing is None: - clone = type(self).__new__(type(self)) - clone._name = self.name - clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._num_delayed_groups = self.num_delayed_groups - clone._temperatures = copy.deepcopy(self.temperatures, memo) - clone._representation = self.representation - clone._atomic_weight_ratio = self._atomic_weight_ratio - clone._fissionable = self._fissionable - clone._scatter_format = self._scatter_format - clone._order = self._order - clone._num_polar = self._num_polar - clone._num_azimuthal = self._num_azimuthal - clone._total = copy.deepcopy(self._total, memo) - clone._absorption = copy.deepcopy(self._absorption, memo) - clone._scatter_matrix = copy.deepcopy(self._scatter_matrix, memo) - clone._multiplicity_matrix = \ - copy.deepcopy(self._multiplicity_matrix, memo) - clone._fission = copy.deepcopy(self._fission, memo) - clone._nu_fission = copy.deepcopy(self._nu_fission, memo) - clone._prompt_nu_fission = \ - copy.deepcopy(self._prompt_nu_fission, memo) - clone._delayed_nu_fission = \ - copy.deepcopy(self._delayed_nu_fission, memo) - clone._kappa_fission = copy.deepcopy(self._kappa_fission, memo) - clone._chi = copy.deepcopy(self._chi, memo) - clone._chi_prompt = copy.deepcopy(self._chi_prompt, memo) - clone._chi_delayed = copy.deepcopy(self._chi_delayed, memo) - clone._beta = copy.deepcopy(self._beta, memo) - clone._decay_rate = copy.deepcopy(self._decay_rate, memo) - clone._inverse_velocity = \ - copy.deepcopy(self._inverse_velocity, memo) - clone._xs_shapes = copy.deepcopy(self._xs_shapes, memo) - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - @property - def name(self): - return self._name - - @property - def energy_groups(self): - return self._energy_groups - - @property - def num_delayed_groups(self): - return self._num_delayed_groups - - @property - def representation(self): - return self._representation - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @property - def fissionable(self): - return self._fissionable - - @property - def temperatures(self): - return self._temperatures - - @property - def scatter_format(self): - return self._scatter_format - - @property - def order(self): - return self._order - - @property - def num_polar(self): - return self._num_polar - - @property - def num_azimuthal(self): - return self._num_azimuthal - - @property - def total(self): - return self._total - - @property - def absorption(self): - return self._absorption - - @property - def scatter_matrix(self): - return self._scatter_matrix - - @property - def multiplicity_matrix(self): - return self._multiplicity_matrix - - @property - def fission(self): - return self._fission - - @property - def nu_fission(self): - return self._nu_fission - - @property - def prompt_nu_fission(self): - return self._prompt_nu_fission - - @property - def delayed_nu_fission(self): - return self._delayed_nu_fission - - @property - def kappa_fission(self): - return self._kappa_fission - - @property - def chi(self): - return self._chi - - @property - def chi_prompt(self): - return self._chi_prompt - - @property - def chi_delayed(self): - return self._chi_delayed - - @property - def num_orders(self): - if self._order is not None: - if self._scatter_format in (None, 'legendre'): - return self._order + 1 - else: - return self._order - - @property - def xs_shapes(self): - - if self._xs_shapes is None: - - self._xs_shapes = {} - self._xs_shapes["[G]"] = (self.energy_groups.num_groups,) - self._xs_shapes["[G']"] = (self.energy_groups.num_groups,) - self._xs_shapes["[G][G']"] = (self.energy_groups.num_groups, - self.energy_groups.num_groups) - self._xs_shapes["[DG]"] = (self.num_delayed_groups,) - self._xs_shapes["[DG][G]"] = (self.num_delayed_groups, - self.energy_groups.num_groups) - self._xs_shapes["[DG][G']"] = (self.num_delayed_groups, - self.energy_groups.num_groups) - self._xs_shapes["[DG][G][G']"] = (self.num_delayed_groups, - self.energy_groups.num_groups, - self.energy_groups.num_groups) - - self._xs_shapes["[G][G'][Order]"] \ - = (self.energy_groups.num_groups, - self.energy_groups.num_groups, self.num_orders) - - # If representation is by angle prepend num polar and num azim - if self.representation == 'angle': - for key, shapes in self._xs_shapes.items(): - self._xs_shapes[key] \ - = (self.num_polar, self.num_azimuthal) + shapes - - return self._xs_shapes - - @name.setter - def name(self, name): - - check_type('name for XSdata', name, str) - self._name = name - - @energy_groups.setter - def energy_groups(self, energy_groups): - - check_type('energy_groups', energy_groups, openmc.mgxs.EnergyGroups) - if energy_groups.group_edges is None: - msg = 'Unable to assign an EnergyGroups object ' \ - 'with uninitialized group edges' - raise ValueError(msg) - - self._energy_groups = energy_groups - - @num_delayed_groups.setter - def num_delayed_groups(self, num_delayed_groups): - - check_type('num_delayed_groups', num_delayed_groups, Integral) - check_less_than('num_delayed_groups', num_delayed_groups, - openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) - check_greater_than('num_delayed_groups', num_delayed_groups, 0, - equality=True) - self._num_delayed_groups = num_delayed_groups - - @representation.setter - def representation(self, representation): - - check_value('representation', representation, _REPRESENTATIONS) - self._representation = representation - - @atomic_weight_ratio.setter - def atomic_weight_ratio(self, atomic_weight_ratio): - - check_type('atomic_weight_ratio', atomic_weight_ratio, Real) - check_greater_than('atomic_weight_ratio', atomic_weight_ratio, 0.0) - self._atomic_weight_ratio = atomic_weight_ratio - - @temperatures.setter - def temperatures(self, temperatures): - - check_iterable_type('temperatures', temperatures, Real) - self._temperatures = np.array(temperatures) - - @scatter_format.setter - def scatter_format(self, scatter_format): - - check_value('scatter_format', scatter_format, _SCATTER_TYPES) - self._scatter_format = scatter_format - - @order.setter - def order(self, order): - - check_type('order', order, Integral) - check_greater_than('order', order, 0, equality=True) - self._order = order - - @num_polar.setter - def num_polar(self, num_polar): - - check_type('num_polar', num_polar, Integral) - check_greater_than('num_polar', num_polar, 0) - self._num_polar = num_polar - - @num_azimuthal.setter - def num_azimuthal(self, num_azimuthal): - - check_type('num_azimuthal', num_azimuthal, Integral) - check_greater_than('num_azimuthal', num_azimuthal, 0) - self._num_azimuthal = num_azimuthal - - def add_temperature(self, temperature): - """This method re-sizes the attributes of this XSdata object so that it - can accomodate an additional temperature. Note that the set_* methods - will still need to be executed. - - Parameters - ---------- - temperature : float - Temperature (in units of Kelvin) of the provided dataset. - - """ - - check_type('temperature', temperature, Real) - - temp_store = self.temperatures.tolist().append(temperature) - self.temperatures = temp_store - - self._total.append(None) - self._absorption.append(None) - self._scatter_matrix.append(None) - self._multiplicity_matrix.append(None) - self._fission.append(None) - self._nu_fission.append(None) - self._prompt_nu_fission.append(None) - self._delayed_nu_fission.append(None) - self._kappa_fission.append(None) - self._chi.append(None) - self._chi_prompt.append(None) - self._chi_delayed.append(None) - self._beta.append(None) - self._decay_rate.append(None) - self._inverse_velocity.append(None) - - def set_total(self, total, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - total: np.ndarray - Total Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_total_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - total = np.asarray(total) - check_value('total shape', total.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._total[i] = total - - def set_absorption(self, absorption, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - absorption: np.ndarray - Absorption Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_absorption_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - absorption = np.asarray(absorption) - check_value('absorption shape', absorption.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._absorption[i] = absorption - - def set_fission(self, fission, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - fission: np.ndarray - Fission Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_fission_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - fission = np.asarray(fission) - check_value('fission shape', fission.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._fission[i] = fission - - if np.sum(fission) > 0.0: - self._fissionable = True - - def set_kappa_fission(self, kappa_fission, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - kappa_fission: np.ndarray - Kappa-Fission Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_kappa_fission_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - kappa_fission = np.asarray(kappa_fission) - check_value('kappa fission shape', kappa_fission.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._kappa_fission[i] = kappa_fission - - if np.sum(kappa_fission) > 0.0: - self._fissionable = True - - def set_chi(self, chi, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - chi: np.ndarray - Fission Spectrum - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_chi_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - chi = np.asarray(chi) - check_value('chi shape', chi.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi[i] = chi - - def set_chi_prompt(self, chi_prompt, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - chi_prompt : np.ndarray - Prompt fission Spectrum - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_chi_prompt_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - chi_prompt = np.asarray(chi_prompt) - check_value('chi prompt shape', chi_prompt.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi_prompt[i] = chi_prompt - - def set_chi_delayed(self, chi_delayed, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - chi_delayed : np.ndarray - Delayed fission Spectrum - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_chi_delayed_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G']"], self.xs_shapes["[DG][G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - chi_delayed = np.asarray(chi_delayed) - check_value('chi delayed shape', chi_delayed.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi_delayed[i] = chi_delayed - - def set_beta(self, beta, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - beta : np.ndarray - Delayed fission spectrum - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_beta_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[DG]"], self.xs_shapes["[DG][G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - beta = np.asarray(beta) - check_value('beta shape', beta.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._beta[i] = beta - - def set_decay_rate(self, decay_rate, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - decay_rate : np.ndarray - Delayed neutron precursor decay rate - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_decay_rate_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[DG]"], self.xs_shapes["[DG][G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - decay_rate = np.asarray(decay_rate) - check_value('decay rate shape', decay_rate.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._decay_rate[i] = decay_rate - - def set_scatter_matrix(self, scatter, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - scatter: np.ndarray - Scattering Matrix Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_scatter_matrix_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G][G'][Order]"]] - - # Convert to a numpy array so we can easily get the shape for checking - scatter = np.asarray(scatter) - check_iterable_type('scatter', scatter, Real, - max_depth=len(scatter.shape)) - check_value('scatter shape', scatter.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._scatter_matrix[i] = scatter - - def set_multiplicity_matrix(self, multiplicity, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - multiplicity: np.ndarray - Multiplicity Matrix Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_multiplicity_matrix_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G][G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - multiplicity = np.asarray(multiplicity) - check_iterable_type('multiplicity', multiplicity, Real, - max_depth=len(multiplicity.shape)) - check_value('multiplicity shape', multiplicity.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._multiplicity_matrix[i] = multiplicity - - def set_nu_fission(self, nu_fission, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - nu_fission: np.ndarray - Nu-fission Cross Section - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - See also - -------- - openmc.mgxs_library.set_nu_fission_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"], self.xs_shapes["[G][G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - nu_fission = np.asarray(nu_fission) - check_value('nu_fission shape', nu_fission.shape, shapes) - check_iterable_type('nu_fission', nu_fission, Real, - max_depth=len(nu_fission.shape)) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._nu_fission[i] = nu_fission - if np.sum(nu_fission) > 0.0: - self._fissionable = True - - def set_prompt_nu_fission(self, prompt_nu_fission, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - prompt_nu_fission: np.ndarray - Prompt-nu-fission Cross Section - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_prompt_nu_fission_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"], self.xs_shapes["[G][G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - prompt_nu_fission = np.asarray(prompt_nu_fission) - check_value('prompt_nu_fission shape', prompt_nu_fission.shape, shapes) - check_iterable_type('prompt_nu_fission', prompt_nu_fission, Real, - max_depth=len(prompt_nu_fission.shape)) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._prompt_nu_fission[i] = prompt_nu_fission - if np.sum(prompt_nu_fission) > 0.0: - self._fissionable = True - - def set_delayed_nu_fission(self, delayed_nu_fission, temperature=294.): - """This method sets the cross section for this XSdata object at the - provided temperature. - - Parameters - ---------- - delayed_nu_fission: np.ndarray - Delayed-nu-fission Cross Section - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - - See also - -------- - openmc.mgxs_library.set_delayed_nu_fission_mgxs() - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[DG][G]"], self.xs_shapes["[DG][G][G']"]] - - # Convert to a numpy array so we can easily get the shape for checking - delayed_nu_fission = np.asarray(delayed_nu_fission) - check_value('delayed_nu_fission shape', delayed_nu_fission.shape, - shapes) - check_iterable_type('delayed_nu_fission', delayed_nu_fission, Real, - max_depth=len(delayed_nu_fission.shape)) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._delayed_nu_fission[i] = delayed_nu_fission - if np.sum(delayed_nu_fission) > 0.0: - self._fissionable = True - - def set_inverse_velocity(self, inv_vel, temperature=294.): - """This method sets the inverse velocity for this XSdata object at the - provided temperature. - - Parameters - ---------- - inv_vel: np.ndarray - Inverse velocity in units of sec/cm. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - - """ - - # Get the accepted shapes for this xs - shapes = [self.xs_shapes["[G]"]] - - # Convert to a numpy array so we can easily get the shape for checking - inv_vel = np.asarray(inv_vel) - check_value('inverse_velocity shape', inv_vel.shape, shapes) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._inverse_velocity[i] = inv_vel - - def set_total_mgxs(self, total, temperature=294., nuclide='total', - xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.TotalXS or - openmc.mgxs.TransportXS to be used to set the total cross section for - this XSdata object. - - Parameters - ---------- - total: openmc.mgxs.TotalXS or openmc.mgxs.TransportXS - MGXS Object containing the total, transport or nu-transport cross - section for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('total', total, (openmc.mgxs.TotalXS, - openmc.mgxs.TransportXS)) - check_value('energy_groups', total.energy_groups, [self.energy_groups]) - check_value('domain_type', total.domain_type, openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._total[i] = total.get_xs(nuclides=nuclide, xs_type=xs_type, - subdomains=subdomain) - - def set_absorption_mgxs(self, absorption, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.AbsorptionXS - to be used to set the absorption cross section for this XSdata object. - - Parameters - ---------- - absorption: openmc.mgxs.AbsorptionXS - MGXS Object containing the absorption cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('absorption', absorption, openmc.mgxs.AbsorptionXS) - check_value('energy_groups', absorption.energy_groups, - [self.energy_groups]) - check_value('domain_type', absorption.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._absorption[i] = absorption.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_fission_mgxs(self, fission, temperature=294., nuclide='total', - xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.FissionXS - to be used to set the fission cross section for this XSdata object. - - Parameters - ---------- - fission: openmc.mgxs.FissionXS - MGXS Object containing the fission cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('fission', fission, openmc.mgxs.FissionXS) - check_value('energy_groups', fission.energy_groups, - [self.energy_groups]) - check_value('domain_type', fission.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._fission[i] = fission.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_nu_fission_mgxs(self, nu_fission, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.FissionXS - to be used to set the nu-fission cross section for this XSdata object. - - Parameters - ---------- - nu_fission: openmc.mgxs.FissionXS - MGXS Object containing the nu-fission cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('nu_fission', nu_fission, (openmc.mgxs.FissionXS, - openmc.mgxs.NuFissionMatrixXS)) - if isinstance(nu_fission, openmc.mgxs.FissionXS): - check_value('nu', nu_fission.nu, [True]) - check_value('energy_groups', nu_fission.energy_groups, - [self.energy_groups]) - check_value('domain_type', nu_fission.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._nu_fission[i] = nu_fission.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - if np.sum(self._nu_fission) > 0.0: - self._fissionable = True - - def set_prompt_nu_fission_mgxs(self, prompt_nu_fission, temperature=294., - nuclide='total', xs_type='macro', - subdomain=None): - """Sets the prompt-nu-fission cross section. - - This method allows for an openmc.mgxs.FissionXS or - openmc.mgxs.NuFissionMatrixXS to be used to set the prompt-nu-fission - cross section for this XSdata object. - - Parameters - ---------- - prompt_nu_fission: openmc.mgxs.FissionXS or openmc.mgxs.NuFissionMatrixXS - MGXS Object containing the prompt-nu-fission cross section - for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('prompt_nu_fission', prompt_nu_fission, - (openmc.mgxs.FissionXS, openmc.mgxs.NuFissionMatrixXS)) - check_value('prompt', prompt_nu_fission.prompt, [True]) - check_value('energy_groups', prompt_nu_fission.energy_groups, - [self.energy_groups]) - check_value('domain_type', prompt_nu_fission.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._prompt_nu_fission[i] = prompt_nu_fission.get_xs( - nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - - if np.sum(self._prompt_nu_fission) > 0.0: - self._fissionable = True - - def set_delayed_nu_fission_mgxs(self, delayed_nu_fission, temperature=294., - nuclide='total', xs_type='macro', - subdomain=None): - """This method allows for an openmc.mgxs.DelayedNuFissionXS or - openmc.mgxs.DelayedNuFissionMatrixXS to be used to set the - delayed-nu-fission cross section for this XSdata object. - - Parameters - ---------- - delayed_nu_fission: openmc.mgxs.DelayedNuFissionXS or openmc.mgxs.DelayedNuFissionMatrixXS - MGXS Object containing the delayed-nu-fission cross section - for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('delayed_nu_fission', delayed_nu_fission, - (openmc.mgxs.DelayedNuFissionXS, - openmc.mgxs.DelayedNuFissionMatrixXS)) - check_value('energy_groups', delayed_nu_fission.energy_groups, - [self.energy_groups]) - check_value('num_delayed_groups', delayed_nu_fission.num_delayed_groups, - [self.num_delayed_groups]) - check_value('domain_type', delayed_nu_fission.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._delayed_nu_fission[i] = delayed_nu_fission.get_xs( - nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - - if np.sum(self._delayed_nu_fission) > 0.0: - self._fissionable = True - - def set_kappa_fission_mgxs(self, k_fission, temperature=294., - nuclide='total', xs_type='macro', - subdomain=None): - """This method allows for an openmc.mgxs.KappaFissionXS - to be used to set the kappa-fission cross section for this XSdata - object. - - Parameters - ---------- - kappa_fission: openmc.mgxs.KappaFissionXS - MGXS Object containing the kappa-fission cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('kappa_fission', k_fission, openmc.mgxs.KappaFissionXS) - check_value('energy_groups', k_fission.energy_groups, - [self.energy_groups]) - check_value('domain_type', k_fission.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._kappa_fission[i] = k_fission.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_chi_mgxs(self, chi, temperature=294., nuclide='total', - xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.Chi - to be used to set chi for this XSdata object. - - Parameters - ---------- - chi: openmc.mgxs.Chi - MGXS Object containing chi for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('chi', chi, openmc.mgxs.Chi) - check_value('energy_groups', chi.energy_groups, [self.energy_groups]) - check_value('domain_type', chi.domain_type, openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi[i] = chi.get_xs(nuclides=nuclide, xs_type=xs_type, - subdomains=subdomain) - - def set_chi_prompt_mgxs(self, chi_prompt, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.Chi to be used to set - chi-prompt for this XSdata object. - - Parameters - ---------- - chi_prompt: openmc.mgxs.Chi - MGXS Object containing chi-prompt for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('chi_prompt', chi_prompt, openmc.mgxs.Chi) - check_value('prompt', chi_prompt.prompt, [True]) - check_value('energy_groups', chi_prompt.energy_groups, - [self.energy_groups]) - check_value('domain_type', chi_prompt.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi_prompt[i] = chi_prompt.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_chi_delayed_mgxs(self, chi_delayed, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.ChiDelayed - to be used to set chi-delayed for this XSdata object. - - Parameters - ---------- - chi_delayed: openmc.mgxs.ChiDelayed - MGXS Object containing chi-delayed for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('chi_delayed', chi_delayed, openmc.mgxs.ChiDelayed) - check_value('energy_groups', chi_delayed.energy_groups, - [self.energy_groups]) - check_value('num_delayed_groups', chi_delayed.num_delayed_groups, - [self.num_delayed_groups]) - check_value('domain_type', chi_delayed.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._chi_delayed[i] = chi_delayed.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_beta_mgxs(self, beta, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.Beta - to be used to set beta for this XSdata object. - - Parameters - ---------- - beta : openmc.mgxs.Beta - MGXS Object containing beta for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('beta', beta, openmc.mgxs.Beta) - check_value('num_delayed_groups', beta.num_delayed_groups, - [self.num_delayed_groups]) - check_value('domain_type', beta.domain_type, openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._beta[i] = beta.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_decay_rate_mgxs(self, decay_rate, temperature=294., - nuclide='total', xs_type='macro', subdomain=None): - """This method allows for an openmc.mgxs.DecayRate - to be used to set decay rate for this XSdata object. - - Parameters - ---------- - decay_rate : openmc.mgxs.DecayRate - MGXS Object containing decay rate for the domain of interest. - temperature : float - Temperature (in units of Kelvin) of the provided dataset. Defaults - to 294K - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('decay_rate', decay_rate, openmc.mgxs.DecayRate) - check_value('num_delayed_groups', decay_rate.num_delayed_groups, - [self.num_delayed_groups]) - check_value('domain_type', decay_rate.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._decay_rate[i] = decay_rate.get_xs(nuclides=nuclide, - xs_type=xs_type, - subdomains=subdomain) - - def set_scatter_matrix_mgxs(self, scatter, temperature=294., - nuclide='total', xs_type='macro', - subdomain=None): - """This method allows for an openmc.mgxs.ScatterMatrixXS - to be used to set the scatter matrix cross section for this XSdata - object. If the XSdata.order attribute has not yet been set, then - it will be set based on the properties of scatter. - - Parameters - ---------- - scatter: openmc.mgxs.ScatterMatrixXS - MGXS Object containing the scatter matrix cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS) - check_value('energy_groups', scatter.energy_groups, - [self.energy_groups]) - check_value('domain_type', scatter.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - # Set the value of scatter_format based on the same value within - # scatter - self.scatter_format = scatter.scatter_format - - # If the user has not defined XSdata.order, then we will set - # the order based on the data within scatter. - # Otherwise, we will check to see that XSdata.order matches - # the order of scatter - if self.scatter_format == 'legendre': - if self.order is None: - self.order = scatter.legendre_order - else: - check_value('legendre_order', scatter.legendre_order, - [self.order]) - elif self.scatter_format == 'histogram': - if self.order is None: - self.order = scatter.histogram_bins - else: - check_value('histogram_bins', scatter.histogram_bins, - [self.order]) - - i = np.where(self.temperatures == temperature)[0][0] - if self.scatter_format == 'legendre': - self._scatter_matrix[i] = \ - np.zeros(self.xs_shapes["[G][G'][Order]"]) - # Get the scattering orders in the outermost dimension - if self.representation == 'isotropic': - for moment in range(self.num_orders): - self._scatter_matrix[i][:, :, moment] = \ - scatter.get_xs(nuclides=nuclide, xs_type=xs_type, - moment=moment, subdomains=subdomain) - elif self.representation == 'angle': - for moment in range(self.num_orders): - self._scatter_matrix[i][:, :, :, :, moment] = \ - scatter.get_xs(nuclides=nuclide, xs_type=xs_type, - moment=moment, subdomains=subdomain) - else: - self._scatter_matrix[i] = \ - scatter.get_xs(nuclides=nuclide, xs_type=xs_type, - subdomains=subdomain) - - def set_multiplicity_matrix_mgxs(self, nuscatter, scatter=None, - temperature=294., nuclide='total', - xs_type='macro', subdomain=None): - """This method allows for either the direct use of only an - openmc.mgxs.MultiplicityMatrixXS or an openmc.mgxs.ScatterMatrixXS and - openmc.mgxs.ScatterMatrixXS to be used to set the scattering - multiplicity for this XSdata object. Multiplicity, in OpenMC parlance, - is a factor used to account for the production of neutrons introduced by - scattering multiplication reactions, i.e., (n,xn) events. In this sense, - the multiplication matrix is simply defined as the ratio of the - nu-scatter and scatter matrices. - - Parameters - ---------- - nuscatter: openmc.mgxs.ScatterMatrixXS or openmc.mgxs.MultiplicityMatrixXS - MGXS Object containing the matrix cross section for the domain - of interest. - scatter: openmc.mgxs.ScatterMatrixXS - MGXS Object containing the scattering matrix cross section - for the domain of interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('nuscatter', nuscatter, (openmc.mgxs.ScatterMatrixXS, - openmc.mgxs.MultiplicityMatrixXS)) - check_value('energy_groups', nuscatter.energy_groups, - [self.energy_groups]) - check_value('domain_type', nuscatter.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - if scatter is not None: - check_type('scatter', scatter, openmc.mgxs.ScatterMatrixXS) - if isinstance(nuscatter, openmc.mgxs.MultiplicityMatrixXS): - msg = 'Either an MultiplicityMatrixXS object must be passed ' \ - 'for "nuscatter" or the "scatter" argument must be ' \ - 'provided.' - raise ValueError(msg) - check_value('energy_groups', scatter.energy_groups, - [self.energy_groups]) - check_value('domain_type', scatter.domain_type, - openmc.mgxs.DOMAIN_TYPES) - i = np.where(self.temperatures == temperature)[0][0] - nuscatt = nuscatter.get_xs(nuclides=nuclide, - xs_type=xs_type, moment=0, - subdomains=subdomain) - if isinstance(nuscatter, openmc.mgxs.MultiplicityMatrixXS): - self._multiplicity_matrix[i] = nuscatt - else: - scatt = scatter.get_xs(nuclides=nuclide, - xs_type=xs_type, moment=0, - subdomains=subdomain) - if scatter.scatter_format == 'histogram': - scatt = np.sum(scatt, axis=0) - if nuscatter.scatter_format == 'histogram': - nuscatt = np.sum(nuscatt, axis=0) - self._multiplicity_matrix[i] = np.divide(nuscatt, scatt) - - self._multiplicity_matrix[i] = \ - np.nan_to_num(self._multiplicity_matrix[i]) - - def set_inverse_velocity_mgxs(self, inverse_velocity, temperature=294., - nuclide='total', xs_type='macro', - subdomain=None): - """This method allows for an openmc.mgxs.InverseVelocity - to be used to set the inverse velocity for this XSdata object. - - Parameters - ---------- - inverse_velocity : openmc.mgxs.InverseVelocity - MGXS object containing the inverse velocity for the domain of - interest. - temperature : float - Temperature (in Kelvin) of the data. Defaults to room temperature - (294K). - nuclide : str - Individual nuclide (or 'total' if obtaining material-wise data) - to gather data for. Defaults to 'total'. - xs_type: {'macro', 'micro'} - Provide the macro or micro cross section in units of cm^-1 or - barns. Defaults to 'macro'. - subdomain : iterable of int - If the MGXS contains a mesh domain type, the subdomain parameter - specifies which mesh cell (i.e., [i, j, k] index) to use. - - See also - -------- - openmc.mgxs.Library.create_mg_library() - openmc.mgxs.Library.get_xsdata() - - """ - - check_type('inverse_velocity', inverse_velocity, - openmc.mgxs.InverseVelocity) - check_value('energy_groups', inverse_velocity.energy_groups, - [self.energy_groups]) - check_value('domain_type', inverse_velocity.domain_type, - openmc.mgxs.DOMAIN_TYPES) - check_type('temperature', temperature, Real) - check_value('temperature', temperature, self.temperatures) - - i = np.where(self.temperatures == temperature)[0][0] - self._inverse_velocity[i] = inverse_velocity.get_xs( - nuclides=nuclide, xs_type=xs_type, subdomains=subdomain) - - def convert_representation(self, target_representation, num_polar=None, - num_azimuthal=None): - """Produce a new XSdata object with the same data, but converted to the - new representation (isotropic or angle-dependent). - - This method cannot be used to change the number of polar or - azimuthal bins of an XSdata object that already uses an angular - representation. Finally, this method simply uses an arithmetic mean to - convert from an angular to isotropic representation; no flux-weighting - is applied and therefore reaction rates will not be preserved. - - Parameters - ---------- - target_representation : {'isotropic', 'angle'} - Representation of the MGXS (isotropic or angle-dependent flux - weighting). - num_polar : int, optional - Number of equal width angular bins that the polar angular domain is - subdivided into. This is required when `target_representation` is - "angle". - - num_azimuthal : int, optional - Number of equal width angular bins that the azimuthal angular domain - is subdivided into. This is required when `target_representation` is - "angle". - - Returns - ------- - openmc.XSdata - - Multi-group cross section data with the same data as self, but - represented as specified in `target_representation`. - - """ - - check_value('target_representation', target_representation, - _REPRESENTATIONS) - if target_representation == 'angle': - check_type('num_polar', num_polar, Integral) - check_type('num_azimuthal', num_azimuthal, Integral) - check_greater_than('num_polar', num_polar, 0) - check_greater_than('num_azimuthal', num_azimuthal, 0) - - xsdata = copy.deepcopy(self) - - # First handle the case where the current and requested - # representations are the same - if target_representation == self.representation: - # Check to make sure the num_polar and num_azimuthal values match - if target_representation == 'angle': - if num_polar != self.num_polar or num_azimuthal != self.num_azimuthal: - raise ValueError("Cannot translate between `angle`" - " representations with different angle" - " bin structures") - # Nothing to do as the same structure was requested - return xsdata - - xsdata.representation = target_representation - # We have different actions depending on the representation conversion - if target_representation == 'isotropic': - # This is not needed for the correct functionality, but these - # values are changed back to None for clarity - xsdata._num_polar = None - xsdata._num_azimuthal = None - - elif target_representation == 'angle': - xsdata.num_polar = num_polar - xsdata.num_azimuthal = num_azimuthal - - # Reset xs_shapes so it is recalculated the next time it is needed - xsdata._xs_shapes = None - - for i, temp in enumerate(xsdata.temperatures): - for xs in ['total', 'absorption', 'fission', 'nu_fission', - 'scatter_matrix', 'multiplicity_matrix', - 'prompt_nu_fission', 'delayed_nu_fission', - 'kappa_fission', 'chi', 'chi_prompt', 'chi_delayed', - 'beta', 'decay_rate', 'inverse_velocity']: - # Get the original data - orig_data = getattr(self, '_' + xs)[i] - if orig_data is not None: - - if target_representation == 'isotropic': - # Since we are going from angle to isotropic, the - # current data is just the average over the angle bins - new_data = orig_data.mean(axis=(0, 1)) - - elif target_representation == 'angle': - # Since we are going from isotropic to angle, the - # current data is just copied for every angle bin - new_shape = (num_polar, num_azimuthal) + \ - orig_data.shape - new_data = np.resize(orig_data, new_shape) - - setter = getattr(xsdata, 'set_' + xs) - setter(new_data, temp) - - return xsdata - - def convert_scatter_format(self, target_format, target_order=None): - """Produce a new MGXSLibrary object with the same data, but converted - to the new scatter format and order - - Parameters - ---------- - target_format : {'tabular', 'legendre', 'histogram'} - Representation of the scattering angle distribution - target_order : int - Either the Legendre target_order, number of bins, or number of - points used to describe the angular distribution associated with - each group-to-group transfer probability - - Returns - ------- - openmc.XSdata - Multi-group cross section data with the same data as in self, but - represented as specified in `target_format`. - - """ - - check_value('target_format', target_format, _SCATTER_TYPES) - check_type('target_order', target_order, Integral) - if target_format == 'legendre': - check_greater_than('target_order', target_order, 0, equality=True) - else: - check_greater_than('target_order', target_order, 0) - - xsdata = copy.deepcopy(self) - xsdata.scatter_format = target_format - xsdata.order = target_order - - # Reset and re-generate XSdata.xs_shapes with the new scattering format - xsdata._xs_shapes = None - - for i, temp in enumerate(xsdata.temperatures): - orig_data = self._scatter_matrix[i] - new_shape = orig_data.shape[:-1] + (xsdata.num_orders,) - new_data = np.zeros(new_shape) - - if self.scatter_format == 'legendre': - if target_format == 'legendre': - # Then we are changing orders and only need to change - # dimensionality of the mu data and pad/truncate as needed - order = min(xsdata.num_orders, self.num_orders) - new_data[..., :order] = orig_data[..., :order] - - elif target_format == 'tabular': - mu = np.linspace(-1, 1, xsdata.num_orders) - # Evaluate the legendre on the mu grid - for imu in range(len(mu)): - for l in range(self.num_orders): - new_data[..., imu] += ( - (l + 0.5) * eval_legendre(l, mu[imu]) * - orig_data[..., l]) - - elif target_format == 'histogram': - # This code uses the vectorized integration capabilities - # instead of having an isotropic and angle representation - # path. - # Set the histogram mu grid - mu = np.linspace(-1, 1, xsdata.num_orders + 1) - # For every bin perform simpson integration of a finely - # sampled orig_data - for h_bin in range(xsdata.num_orders): - mu_fine = np.linspace(mu[h_bin], mu[h_bin + 1], _NMU) - table_fine = np.zeros(new_data.shape[:-1] + (_NMU,)) - for imu in range(len(mu_fine)): - for l in range(self.num_orders): - table_fine[..., imu] += ((l + 0.5) - * eval_legendre(l, mu_fine[imu]) * - orig_data[..., l]) - new_data[..., h_bin] = simps(table_fine, mu_fine) - - elif self.scatter_format == 'tabular': - # Calculate the mu points of the current data - mu_self = np.linspace(-1, 1, self.num_orders) - - if target_format == 'legendre': - # Find the Legendre coefficients via integration. To best - # use the vectorized integration capabilities of scipy, - # this is done with fixed sample integration routines. - mu_fine = np.linspace(-1, 1, _NMU) - y = [interp1d(mu_self, orig_data)(mu_fine) * - eval_legendre(l, mu_fine) - for l in range(xsdata.num_orders)] - for l in range(xsdata.num_orders): - new_data[..., l] = simps(y[l], mu_fine) - - elif target_format == 'tabular': - # Simply use an interpolating function to get the new data - mu = np.linspace(-1, 1, xsdata.num_orders) - new_data[..., :] = interp1d(mu_self, orig_data)(mu) - - elif target_format == 'histogram': - # Use an interpolating function to do the bin-wise - # integrals - mu = np.linspace(-1, 1, xsdata.num_orders + 1) - - # Like the tabular -> legendre path above, this code will - # be written to utilize the vectorized integration - # capabilities instead of having an isotropic and - # angle representation path. - interp = interp1d(mu_self, orig_data) - for h_bin in range(xsdata.num_orders): - mu_fine = np.linspace(mu[h_bin], mu[h_bin + 1], _NMU) - new_data[..., h_bin] = simps(interp(mu_fine), mu_fine) - - elif self.scatter_format == 'histogram': - # The histogram format does not have enough information to - # convert to the other forms without inducing some amount of - # error. We will make the assumption that the center of the bin - # has the value of the bin. The mu=-1 and 1 points will be - # extrapolated from the shape. - mu_midpoint = np.linspace(-1, 1, self.num_orders, - endpoint=False) - mu_midpoint += (mu_midpoint[1] - mu_midpoint[0]) * 0.5 - interp = interp1d(mu_midpoint, orig_data, - fill_value='extrapolate') - # Now get the distribution normalization factor to take from - # an integral quantity to a point-wise quantity - norm = float(self.num_orders) / 2.0 - - # We now have a tabular distribution in tab_data on mu_self. - # We now proceed just like the tabular branch above. - if target_format == 'legendre': - # find the legendre coefficients via integration. To best - # use the vectorized integration capabilities of scipy, - # this will be done with fixed sample integration routines. - mu_fine = np.linspace(-1, 1, _NMU) - y = [interp(mu_fine) * norm * eval_legendre(l, mu_fine) - for l in range(xsdata.num_orders)] - for l in range(xsdata.num_orders): - new_data[..., l] = simps(y[l], mu_fine) - - elif target_format == 'tabular': - # Simply use an interpolating function to get the new data - mu = np.linspace(-1, 1, xsdata.num_orders) - new_data[..., :] = interp(mu) * norm - - elif target_format == 'histogram': - # Use an interpolating function to do the bin-wise - # integrals - mu = np.linspace(-1, 1, xsdata.num_orders + 1) - - # Like the tabular -> legendre path above, this code will - # be written to utilize the vectorized integration - # capabilities instead of having an isotropic and - # angle representation path. - for h_bin in range(xsdata.num_orders): - mu_fine = np.linspace(mu[h_bin], mu[h_bin + 1], _NMU) - new_data[..., h_bin] = \ - norm * simps(interp(mu_fine), mu_fine) - - # Remove small values resulting from numerical precision issues - new_data[..., np.abs(new_data) < 1.E-10] = 0. - - xsdata.set_scatter_matrix(new_data, temp) - - return xsdata - - def to_hdf5(self, file): - """Write XSdata to an HDF5 file - - Parameters - ---------- - file : h5py.File - HDF5 File (a root Group) to write to - - """ - - grp = file.create_group(self.name) - if self.atomic_weight_ratio is not None: - grp.attrs['atomic_weight_ratio'] = self.atomic_weight_ratio - if self.fissionable is not None: - grp.attrs['fissionable'] = self.fissionable - - if self.representation is not None: - grp.attrs['representation'] = np.string_(self.representation) - if self.representation == 'angle': - if self.num_azimuthal is not None: - grp.attrs['num_azimuthal'] = self.num_azimuthal - - if self.num_polar is not None: - grp.attrs['num_polar'] = self.num_polar - - grp.attrs['scatter_shape'] = np.string_("[G][G'][Order]") - if self.scatter_format is not None: - grp.attrs['scatter_format'] = np.string_(self.scatter_format) - if self.order is not None: - grp.attrs['order'] = self.order - - ktg = grp.create_group('kTs') - for temperature in self.temperatures: - temp_label = str(int(np.round(temperature))) + "K" - kT = temperature * openmc.data.K_BOLTZMANN - ktg.create_dataset(temp_label, data=kT) - - # Create the temperature datasets - for i, temperature in enumerate(self.temperatures): - - xs_grp = grp.create_group(str(int(np.round(temperature))) + "K") - - if self._total[i] is None: - raise ValueError('total data must be provided when writing ' - 'the HDF5 library') - - xs_grp.create_dataset("total", data=self._total[i]) - - if self._absorption[i] is None: - raise ValueError('absorption data must be provided when ' - 'writing the HDF5 library') - - xs_grp.create_dataset("absorption", data=self._absorption[i]) - - if self.fissionable: - if self._fission[i] is not None: - xs_grp.create_dataset("fission", data=self._fission[i]) - - if self._kappa_fission[i] is not None: - xs_grp.create_dataset("kappa-fission", - data=self._kappa_fission[i]) - - if self._chi[i] is not None: - xs_grp.create_dataset("chi", data=self._chi[i]) - - if self._chi_prompt[i] is not None: - xs_grp.create_dataset("chi-prompt", - data=self._chi_prompt[i]) - - if self._chi_delayed[i] is not None: - xs_grp.create_dataset("chi-delayed", - data=self._chi_delayed[i]) - - if self._nu_fission[i] is None and \ - (self._delayed_nu_fission[i] is None or \ - self._prompt_nu_fission[i] is None): - raise ValueError('nu-fission or prompt-nu-fission and ' - 'delayed-nu-fission data must be ' - 'provided when writing the HDF5 library') - - if self._nu_fission[i] is not None: - xs_grp.create_dataset("nu-fission", - data=self._nu_fission[i]) - - if self._prompt_nu_fission[i] is not None: - xs_grp.create_dataset("prompt-nu-fission", - data=self._prompt_nu_fission[i]) - - if self._delayed_nu_fission[i] is not None: - xs_grp.create_dataset("delayed-nu-fission", - data=self._delayed_nu_fission[i]) - - if self._beta[i] is not None: - xs_grp.create_dataset("beta", data=self._beta[i]) - - if self._decay_rate[i] is not None: - xs_grp.create_dataset("decay rate", - data=self._decay_rate[i]) - - if self._scatter_matrix[i] is None: - raise ValueError('Scatter matrix must be provided when ' - 'writing the HDF5 library') - - # Get the sparse scattering data to print to the library - G = self.energy_groups.num_groups - if self.representation == 'isotropic': - Np = 1 - Na = 1 - elif self.representation == 'angle': - Np = self.num_polar - Na = self.num_azimuthal - - g_out_bounds = np.zeros((Np, Na, G, 2), dtype=np.int) - for p in range(Np): - for a in range(Na): - for g_in in range(G): - if self.scatter_format == 'legendre': - if self.representation == 'isotropic': - matrix = \ - self._scatter_matrix[i][g_in, :, 0] - elif self.representation == 'angle': - matrix = \ - self._scatter_matrix[i][p, a, g_in, :, 0] - else: - if self.representation == 'isotropic': - matrix = \ - np.sum(self._scatter_matrix[i][g_in, :, :], - axis=1) - elif self.representation == 'angle': - matrix = \ - np.sum(self._scatter_matrix[i][p, a, g_in, :, :], - axis=1) - nz = np.nonzero(matrix) - # It is possible that there only zeros in matrix - # and therefore nz will be empty, in that case set - # g_out_bounds to 0s - if len(nz[0]) == 0: - g_out_bounds[p, a, g_in, :] = 0 - else: - g_out_bounds[p, a, g_in, 0] = nz[0][0] - g_out_bounds[p, a, g_in, 1] = nz[0][-1] - - # Now create the flattened scatter matrix array - flat_scatt = [] - for p in range(Np): - for a in range(Na): - if self.representation == 'isotropic': - matrix = self._scatter_matrix[i][:, :, :] - elif self.representation == 'angle': - matrix = self._scatter_matrix[i][p, a, :, :, :] - for g_in in range(G): - for g_out in range(g_out_bounds[p, a, g_in, 0], - g_out_bounds[p, a, g_in, 1] + 1): - for l in range(len(matrix[g_in, g_out, :])): - flat_scatt.append(matrix[g_in, g_out, l]) - - # And write it. - scatt_grp = xs_grp.create_group('scatter_data') - scatt_grp.create_dataset("scatter_matrix", - data=np.array(flat_scatt)) - - # Repeat for multiplicity - if self._multiplicity_matrix[i] is not None: - - # Now create the flattened scatter matrix array - flat_mult = [] - for p in range(Np): - for a in range(Na): - if self.representation == 'isotropic': - matrix = self._multiplicity_matrix[i][:, :] - elif self.representation == 'angle': - matrix = self._multiplicity_matrix[i][p, a, :, :] - for g_in in range(G): - for g_out in range(g_out_bounds[p, a, g_in, 0], - g_out_bounds[p, a, g_in, 1] + 1): - flat_mult.append(matrix[g_in, g_out]) - - # And write it. - scatt_grp.create_dataset("multiplicity_matrix", - data=np.array(flat_mult)) - - # And finally, adjust g_out_bounds for 1-based group counting - # and write it. - g_out_bounds[:, :, :, :] += 1 - if self.representation == 'isotropic': - scatt_grp.create_dataset("g_min", data=g_out_bounds[0, 0, :, 0]) - scatt_grp.create_dataset("g_max", data=g_out_bounds[0, 0, :, 1]) - elif self.representation == 'angle': - scatt_grp.create_dataset("g_min", data=g_out_bounds[:, :, :, 0]) - scatt_grp.create_dataset("g_max", data=g_out_bounds[:, :, :, 1]) - - # Add the kinetics data - if self._inverse_velocity[i] is not None: - xs_grp.create_dataset("inverse-velocity", - data=self._inverse_velocity[i]) - - @classmethod - def from_hdf5(cls, group, name, energy_groups, num_delayed_groups): - """Generate XSdata object from an HDF5 group - - Parameters - ---------- - group : h5py.Group - HDF5 group to read from - name : str - Name of the mgxs data set. - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure - num_delayed_groups : int - Number of delayed groups - - Returns - ------- - openmc.XSdata - Multi-group cross section data - - """ - - # Get a list of all the subgroups which will contain our temperature - # strings - subgroups = group.keys() - temperatures = [] - for subgroup in subgroups: - if subgroup != 'kTs': - temperatures.append(subgroup) - - # To ensure the actual floating point temperature used when creating - # the new library is consistent with that used when originally creating - # the file, get the floating point temperatures straight from the kTs - # group. - kTs_group = group['kTs'] - float_temperatures = [] - for temperature in temperatures: - kT = kTs_group[temperature][()] - float_temperatures.append(kT / openmc.data.K_BOLTZMANN) - - attrs = group.attrs.keys() - if 'representation' in attrs: - representation = group.attrs['representation'].decode() - else: - representation = 'isotropic' - - data = cls(name, energy_groups, float_temperatures, representation, - num_delayed_groups) - - if 'scatter_format' in attrs: - data.scatter_format = group.attrs['scatter_format'].decode() - - # Get the remaining optional attributes - if 'atomic_weight_ratio' in attrs: - data.atomic_weight_ratio = group.attrs['atomic_weight_ratio'] - if 'order' in attrs: - data.order = group.attrs['order'] - if data.representation == 'angle': - data.num_azimuthal = group.attrs['num_azimuthal'] - data.num_polar = group.attrs['num_polar'] - - # Read the temperature-dependent datasets - for temp, float_temp in zip(temperatures, float_temperatures): - xs_types = ['total', 'absorption', 'fission', 'kappa-fission', - 'chi', 'chi-prompt', 'chi-delayed', 'nu-fission', - 'prompt-nu-fission', 'delayed-nu-fission', 'beta', - 'decay rate', 'inverse-velocity'] - - temperature_group = group[temp] - - for xs_type in xs_types: - set_func = 'set_' + xs_type.replace(' ', '_').replace('-', '_') - if xs_type in temperature_group: - getattr(data, set_func)(temperature_group[xs_type][()], - float_temp) - - scatt_group = temperature_group['scatter_data'] - - # Get scatter matrix and 'un-flatten' it - g_max = scatt_group['g_max'] - g_min = scatt_group['g_min'] - flat_scatter = scatt_group['scatter_matrix'][()] - scatter_matrix = np.zeros(data.xs_shapes["[G][G'][Order]"]) - G = data.energy_groups.num_groups - if data.representation == 'isotropic': - Np = 1 - Na = 1 - elif data.representation == 'angle': - Np = data.num_polar - Na = data.num_azimuthal - flat_index = 0 - for p in range(Np): - for a in range(Na): - for g_in in range(G): - if data.representation == 'isotropic': - g_mins = g_min[g_in] - g_maxs = g_max[g_in] - elif data.representation == 'angle': - g_mins = g_min[p, a, g_in] - g_maxs = g_max[p, a, g_in] - for g_out in range(g_mins - 1, g_maxs): - for ang in range(data.num_orders): - if data.representation == 'isotropic': - scatter_matrix[g_in, g_out, ang] = \ - flat_scatter[flat_index] - elif data.representation == 'angle': - scatter_matrix[p, a, g_in, g_out, ang] = \ - flat_scatter[flat_index] - flat_index += 1 - data.set_scatter_matrix(scatter_matrix, float_temp) - - # Repeat for multiplicity - if 'multiplicity_matrix' in scatt_group: - flat_mult = scatt_group['multiplicity_matrix'][()] - mult_matrix = np.zeros(data.xs_shapes["[G][G']"]) - flat_index = 0 - for p in range(Np): - for a in range(Na): - for g_in in range(G): - if data.representation == 'isotropic': - g_mins = g_min[g_in] - g_maxs = g_max[g_in] - elif data.representation == 'angle': - g_mins = g_min[p, a, g_in] - g_maxs = g_max[p, a, g_in] - for g_out in range(g_mins - 1, g_maxs): - if data.representation == 'isotropic': - mult_matrix[g_in, g_out] = \ - flat_mult[flat_index] - elif data.representation == 'angle': - mult_matrix[p, a, g_in, g_out] = \ - flat_mult[flat_index] - flat_index += 1 - data.set_multiplicity_matrix(mult_matrix, float_temp) - - return data - - -class MGXSLibrary(object): - """Multi-Group Cross Sections file used for an OpenMC simulation. - Corresponds directly to the MG version of the cross_sections.xml input - file. - - Parameters - ---------- - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure - num_delayed_groups : int - Num delayed groups - - Attributes - ---------- - energy_groups : openmc.mgxs.EnergyGroups - Energy group structure. - num_delayed_groups : int - Num delayed groups - xsdatas : Iterable of openmc.XSdata - Iterable of multi-Group cross section data objects - """ - - def __init__(self, energy_groups, num_delayed_groups=0): - self.energy_groups = energy_groups - self.num_delayed_groups = num_delayed_groups - self._xsdatas = [] - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, copy it - if existing is None: - clone = type(self).__new__(type(self)) - clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._num_delayed_groups = self.num_delayed_groups - clone._xsdatas = copy.deepcopy(self.xsdatas, memo) - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - @property - def energy_groups(self): - return self._energy_groups - - @property - def num_delayed_groups(self): - return self._num_delayed_groups - - @property - def xsdatas(self): - return self._xsdatas - - @property - def names(self): - return [xsdata.name for xsdata in self.xsdatas] - - @energy_groups.setter - def energy_groups(self, energy_groups): - check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) - self._energy_groups = energy_groups - - @num_delayed_groups.setter - def num_delayed_groups(self, num_delayed_groups): - check_type('num_delayed_groups', num_delayed_groups, Integral) - check_greater_than('num_delayed_groups', num_delayed_groups, 0, - equality=True) - check_less_than('num_delayed_groups', num_delayed_groups, - openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) - self._num_delayed_groups = num_delayed_groups - - def add_xsdata(self, xsdata): - """Add an XSdata entry to the file. - - Parameters - ---------- - xsdata : openmc.XSdata - MGXS information to add - - """ - - if not isinstance(xsdata, XSdata): - msg = 'Unable to add a non-XSdata "{0}" to the ' \ - 'MGXSLibrary instance'.format(xsdata) - raise ValueError(msg) - - if xsdata.energy_groups != self._energy_groups: - msg = 'Energy groups of XSdata do not match that of MGXSLibrary.' - raise ValueError(msg) - - self._xsdatas.append(xsdata) - - def add_xsdatas(self, xsdatas): - """Add multiple XSdatas to the file. - - Parameters - ---------- - xsdatas : tuple or list of openmc.XSdata - XSdatas to add - - """ - - check_iterable_type('xsdatas', xsdatas, XSdata) - - for xsdata in xsdatas: - self.add_xsdata(xsdata) - - def remove_xsdata(self, xsdata): - """Remove a xsdata from the file - - Parameters - ---------- - xsdata : openmc.XSdata - XSdata to remove - - """ - - if not isinstance(xsdata, XSdata): - msg = 'Unable to remove a non-XSdata "{0}" from the ' \ - 'MGXSLibrary instance'.format(xsdata) - raise ValueError(msg) - - self._xsdatas.remove(xsdata) - - def get_by_name(self, name): - """Access the XSdata objects by name - - Parameters - ---------- - name : str - Name of openmc.XSdata object to obtain - - Returns - ------- - result : openmc.XSdata or None - Provides the matching XSdata object or None, if not found - - """ - check_type("name", name, str) - result = None - for xsdata in self.xsdatas: - if name == xsdata.name: - result = xsdata - return result - - def convert_representation(self, target_representation, num_polar=None, - num_azimuthal=None): - """Produce a new XSdata object with the same data, but converted to the - new representation (isotropic or angle-dependent). - - This method cannot be used to change the number of polar or - azimuthal bins of an XSdata object that already uses an angular - representation. Finally, this method simply uses an arithmetic mean to - convert from an angular to isotropic representation; no flux-weighting - is applied and therefore the reaction rates will not be preserved. - - Parameters - ---------- - target_representation : {'isotropic', 'angle'} - Representation of the MGXS (isotropic or angle-dependent flux - weighting). - num_polar : int, optional - Number of equal width angular bins that the polar angular domain is - subdivided into. This is required when `target_representation` is - "angle". - num_azimuthal : int, optional - Number of equal width angular bins that the azimuthal angular domain - is subdivided into. This is required when `target_representation` is - "angle". - - Returns - ------- - openmc.MGXSLibrary - Multi-group Library with the same data as self, but represented as - specified in `target_representation`. - - """ - - library = copy.deepcopy(self) - for i, xsdata in enumerate(self.xsdatas): - library.xsdatas[i] = \ - xsdata.convert_representation(target_representation, - num_polar, num_azimuthal) - return library - - def convert_scatter_format(self, target_format, target_order): - """Produce a new MGXSLibrary object with the same data, but converted - to the new scatter format and order - - Parameters - ---------- - target_format : {'tabular', 'legendre', 'histogram'} - Representation of the scattering angle distribution - target_order : int - Either the Legendre target_order, number of bins, or number of - points used to describe the angular distribution associated with - each group-to-group transfer probability - - Returns - ------- - openmc.MGXSLibrary - Multi-group Library with the same data as self, but with the scatter - format represented as specified in `target_format` and - `target_order`. - - """ - - library = copy.deepcopy(self) - for i, xsdata in enumerate(self.xsdatas): - library.xsdatas[i] = \ - xsdata.convert_scatter_format(target_format, target_order) - - return library - - def export_to_hdf5(self, filename='mgxs.h5', libver='earliest'): - """Create an hdf5 file that can be used for a simulation. - - Parameters - ---------- - filename : str - Filename of file, default is mgxs.h5. - libver : {'earliest', 'latest'} - Compatibility mode for the HDF5 file. 'latest' will produce files - that are less backwards compatible but have performance benefits. - - """ - - check_type('filename', filename, str) - - # Create and write to the HDF5 file - file = h5py.File(filename, "w", libver=libver) - file.attrs['filetype'] = np.string_(_FILETYPE_MGXS_LIBRARY) - file.attrs['version'] = [_VERSION_MGXS_LIBRARY, 0] - file.attrs['energy_groups'] = self.energy_groups.num_groups - file.attrs['delayed_groups'] = self.num_delayed_groups - file.attrs['group structure'] = self.energy_groups.group_edges - - for xsdata in self._xsdatas: - xsdata.to_hdf5(file) - - file.close() - - @classmethod - def from_hdf5(cls, filename=None): - """Generate an MGXS Library from an HDF5 group or file - - Parameters - ---------- - filename : str, optional - Name of HDF5 file containing MGXS data. Default is None. - If not provided, the value of the OPENMC_MG_CROSS_SECTIONS - environmental variable will be used - - Returns - ------- - openmc.MGXSLibrary - Multi-group cross section data object. - - """ - # If filename is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable - if filename is None: - filename = os.environ.get('OPENMC_MG_CROSS_SECTIONS') - - # Check to make sure there was an environmental variable. - if filename is None: - raise ValueError("Either path or OPENMC_MG_CROSS_SECTIONS " - "environmental variable must be set") - - check_type('filename', filename, str) - file = h5py.File(filename, 'r') - - # Check filetype and version - check_filetype_version(file, _FILETYPE_MGXS_LIBRARY, - _VERSION_MGXS_LIBRARY) - - group_structure = file.attrs['group structure'] - num_delayed_groups = file.attrs['delayed_groups'] - energy_groups = openmc.mgxs.EnergyGroups(group_structure) - data = cls(energy_groups, num_delayed_groups) - - for group_name, group in file.items(): - data.add_xsdata(openmc.XSdata.from_hdf5(group, group_name, - energy_groups, - num_delayed_groups)) - - return data diff --git a/openmc/mixin.py b/openmc/mixin.py deleted file mode 100644 index 09a63ae4e..000000000 --- a/openmc/mixin.py +++ /dev/null @@ -1,113 +0,0 @@ -from numbers import Integral -from warnings import warn - -import numpy as np - -import openmc.checkvalue as cv - - -class EqualityMixin(object): - """A Class which provides generic __eq__ and __ne__ functionality which - can easily be inherited by downstream classes. - """ - - def __eq__(self, other): - if isinstance(other, type(self)): - for key, value in self.__dict__.items(): - if not np.array_equal(value, other.__dict__.get(key)): - return False - else: - return False - - return True - - def __ne__(self, other): - return not self.__eq__(other) - - -class IDWarning(UserWarning): - pass - - -class IDManagerMixin(object): - """A Class which automatically manages unique IDs. - - This mixin gives any subclass the ability to assign unique IDs through an - 'id' property and keeps track of which ones have already been - assigned. Crucially, each subclass must define class variables 'next_id' and - 'used_ids' as they are used in the 'id' property that is supplied here. - - """ - - @property - def id(self): - return self._id - - @id.setter - def id(self, uid): - # The first time this is called for a class, we search through the MRO - # to determine which class actually holds next_id and used_ids. Since - # next_id is an integer (immutable), we can't modify it directly through - # the instance without just creating a new attribute - try: - cls = self._id_class - except AttributeError: - for cls in self.__class__.__mro__: - if 'next_id' in cls.__dict__: - break - - if uid is None: - while cls.next_id in cls.used_ids: - cls.next_id += 1 - self._id = cls.next_id - cls.used_ids.add(cls.next_id) - else: - name = cls.__name__ - cv.check_type('{} ID'.format(name), uid, Integral) - cv.check_greater_than('{} ID'.format(name), uid, 0, equality=True) - if uid in cls.used_ids: - msg = 'Another {} instance already exists with id={}.'.format( - name, uid) - warn(msg, IDWarning) - else: - cls.used_ids.add(uid) - self._id = uid - - -def reset_auto_ids(): - """Reset counters for all auto-generated IDs""" - for cls in IDManagerMixin.__subclasses__(): - cls.used_ids.clear() - cls.next_id = 1 - - -def reserve_ids(ids, cls=None): - """Reserve a set of IDs that won't be used for auto-generated IDs. - - Parameters - ---------- - ids : iterable of int - IDs to reserve - cls : type or None - Class for which IDs should be reserved (e.g., :class:`openmc.Cell`). If - None, all classes that have auto-generated IDs will be used. - - """ - if cls is None: - for cls in IDManagerMixin.__subclasses__(): - cls.used_ids |= set(ids) - else: - cls.used_ids |= set(ids) - - -def set_auto_id(next_id): - """Set the next ID for auto-generated IDs. - - Parameters - ---------- - next_id : int - The next ID to assign to objects with auto-generated IDs. - - """ - for cls in IDManagerMixin.__subclasses__(): - cls.next_id = next_id diff --git a/openmc/model/__init__.py b/openmc/model/__init__.py deleted file mode 100644 index 9fa999dd4..000000000 --- a/openmc/model/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .triso import * -from .model import * -from .funcs import * diff --git a/openmc/model/funcs.py b/openmc/model/funcs.py deleted file mode 100644 index 3ee505240..000000000 --- a/openmc/model/funcs.py +++ /dev/null @@ -1,578 +0,0 @@ -from collections.abc import Iterable -from math import sqrt -from numbers import Real -from functools import partial -from warnings import warn -from operator import attrgetter - -from openmc import ( - XPlane, YPlane, Plane, ZCylinder, Quadric, Cylinder, XCylinder, - YCylinder, Material, Universe, Cell) -from openmc.checkvalue import ( - check_type, check_value, check_length, check_less_than, - check_iterable_type) -import openmc.data - - -def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K', - press_unit='MPa', density=None, **kwargs): - """Return a Material with the composition of boron dissolved in water. - - The water density can be determined from a temperature and pressure, or it - can be set directly. - - The concentration of boron has no effect on the stoichiometric ratio of H - and O---they are fixed at 2-1. - - Parameters - ---------- - boron_ppm : float - The weight fraction in parts-per-million of elemental boron in the - water. - temperature : float - Temperature in [K] used to compute water density. - pressure : float - Pressure in [MPa] used to compute water density. - temp_unit : {'K', 'C', 'F'} - The units used for the `temperature` argument. - press_unit : {'MPa', 'psi'} - The units used for the `pressure` argument. - density : float - Water density in [g / cm^3]. If specified, this value overrides the - temperature and pressure arguments. - **kwargs - All keyword arguments are passed to the created Material object. - - Returns - ------- - openmc.Material - - """ - # Perform any necessary unit conversions. - check_value('temperature unit', temp_unit, ('K', 'C', 'F')) - if temp_unit == 'K': - T = temperature - elif temp_unit == 'C': - T = temperature + 273.15 - elif temp_unit == 'F': - T = (temperature + 459.67) * 5.0 / 9.0 - check_value('pressure unit', press_unit, ('MPa', 'psi')) - if press_unit == 'MPa': - P = pressure - elif press_unit == 'psi': - P = pressure * 0.006895 - - # Set the density of water, either from an explicitly given density or from - # temperature and pressure. - if density is not None: - water_density = density - else: - water_density = openmc.data.water_density(T, P) - - # Compute the density of the solution. - solution_density = water_density / (1 - boron_ppm * 1e-6) - - # Compute the molar mass of pure water. - hydrogen = openmc.Element('H') - oxygen = openmc.Element('O') - M_H2O = 0.0 - for iso_name, frac, junk in hydrogen.expand(2.0, 'ao'): - M_H2O += frac * openmc.data.atomic_mass(iso_name) - for iso_name, frac, junk in oxygen.expand(1.0, 'ao'): - M_H2O += frac * openmc.data.atomic_mass(iso_name) - - # Compute the molar mass of boron. - boron = openmc.Element('B') - M_B = 0.0 - for iso_name, frac, junk in boron.expand(1.0, 'ao'): - M_B += frac * openmc.data.atomic_mass(iso_name) - - # Compute the number fractions of each element. - frac_H2O = (1 - boron_ppm * 1e-6) / M_H2O - frac_H = 2 * frac_H2O - frac_O = frac_H2O - frac_B = boron_ppm * 1e-6 / M_B - - # Build the material. - if density is None: - out = openmc.Material(temperature=T, **kwargs) - else: - out = openmc.Material(**kwargs) - out.add_element('H', frac_H, 'ao') - out.add_element('O', frac_O, 'ao') - out.add_element('B', frac_B, 'ao') - out.set_density('g/cc', solution_density) - out.add_s_alpha_beta('c_H_in_H2O') - return out - - -def rectangular_prism(width, height, axis='z', origin=(0., 0.), - boundary_type='transmission', corner_radius=0.): - """Get an infinite rectangular prism from four planar surfaces. - - .. versionchanged:: 0.11 - This function was renamed from `get_rectangular_prism` to - `rectangular_prism`. - - Parameters - ---------- - width: float - Prism width in units of cm. The width is aligned with the y, x, - or x axes for prisms parallel to the x, y, or z axis, respectively. - height: float - Prism height in units of cm. The height is aligned with the z, z, - or y axes for prisms parallel to the x, y, or z axis, respectively. - axis : {'x', 'y', 'z'} - Axis with which the infinite length of the prism should be aligned. - Defaults to 'z'. - origin: Iterable of two floats - Origin of the prism. The two floats correspond to (y,z), (x,z) or - (x,y) for prisms parallel to the x, y or z axis, respectively. - Defaults to (0., 0.). - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic'} - Boundary condition that defines the behavior for particles hitting the - surfaces comprising the rectangular prism (default is 'transmission'). - corner_radius: float - Prism corner radius in units of cm. Defaults to 0. - - Returns - ------- - openmc.Region - The inside of a rectangular prism - - """ - - check_type('width', width, Real) - check_type('height', height, Real) - check_type('corner_radius', corner_radius, Real) - check_value('axis', axis, ['x', 'y', 'z']) - check_type('origin', origin, Iterable, Real) - - # Define function to create a plane on given axis - def plane(axis, name, value): - cls = globals()['{}Plane'.format(axis.upper())] - return cls(name='{} {}'.format(name, axis), - boundary_type=boundary_type, - **{axis + '0': value}) - - if axis == 'x': - x1, x2 = 'y', 'z' - elif axis == 'y': - x1, x2 = 'x', 'z' - else: - x1, x2 = 'x', 'y' - - # Get cylinder class corresponding to given axis - cyl = globals()['{}Cylinder'.format(axis.upper())] - - # Create rectangular region - min_x1 = plane(x1, 'minimum', -width/2 + origin[0]) - max_x1 = plane(x1, 'maximum', width/2 + origin[0]) - min_x2 = plane(x2, 'minimum', -height/2 + origin[1]) - max_x2 = plane(x2, 'maximum', height/2 + origin[1]) - prism = +min_x1 & -max_x1 & +min_x2 & -max_x2 - - # Handle rounded corners if given - if corner_radius > 0.: - args = {'R': corner_radius, 'boundary_type': boundary_type} - - args[x1 + '0'] = origin[0] - width/2 + corner_radius - args[x2 + '0'] = origin[1] - height/2 + corner_radius - x1_min_x2_min = cyl(name='{} min {} min'.format(x1, x2), **args) - - args[x1 + '0'] = origin[0] - width/2 + corner_radius - args[x2 + '0'] = origin[1] - height/2 + corner_radius - x1_min_x2_min = cyl(name='{} min {} min'.format(x1, x2), **args) - - args[x1 + '0'] = origin[0] - width/2 + corner_radius - args[x2 + '0'] = origin[1] + height/2 - corner_radius - x1_min_x2_max = cyl(name='{} min {} max'.format(x1, x2), **args) - - args[x1 + '0'] = origin[0] + width/2 - corner_radius - args[x2 + '0'] = origin[1] - height/2 + corner_radius - x1_max_x2_min = cyl(name='{} max {} min'.format(x1, x2), **args) - - args[x1 + '0'] = origin[0] + width/2 - corner_radius - args[x2 + '0'] = origin[1] + height/2 - corner_radius - x1_max_x2_max = cyl(name='{} max {} max'.format(x1, x2), **args) - - x1_min = plane(x1, 'min', -width/2 + origin[0] + corner_radius) - x1_max = plane(x1, 'max', width/2 + origin[0] - corner_radius) - x2_min = plane(x2, 'min', -height/2 + origin[1] + corner_radius) - x2_max = plane(x2, 'max', height/2 + origin[1] - corner_radius) - - corners = (+x1_min_x2_min & -x1_min & -x2_min) | \ - (+x1_min_x2_max & -x1_min & +x2_max) | \ - (+x1_max_x2_min & +x1_max & -x2_min) | \ - (+x1_max_x2_max & +x1_max & +x2_max) - - prism = prism & ~corners - - return prism - - -def get_rectangular_prism(*args, **kwargs): - warn("get_rectangular_prism(...) has been renamed rectangular_prism(...). " - "Future versions of OpenMC will not accept get_rectangular_prism.", - FutureWarning) - return rectangular_prism(*args, **kwargs) - - -def hexagonal_prism(edge_length=1., orientation='y', origin=(0., 0.), - boundary_type='transmission', corner_radius=0.): - """Create a hexagon region from six surface planes. - - .. versionchanged:: 0.11 - This function was renamed from `get_hexagonal_prism` to - `hexagonal_prism`. - - Parameters - ---------- - edge_length : float - Length of a side of the hexagon in cm - orientation : {'x', 'y'} - An 'x' orientation means that two sides of the hexagon are parallel to - the x-axis and a 'y' orientation means that two sides of the hexagon are - parallel to the y-axis. - origin: Iterable of two floats - Origin of the prism. Defaults to (0., 0.). - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic'} - Boundary condition that defines the behavior for particles hitting the - surfaces comprising the hexagonal prism (default is 'transmission'). - corner_radius: float - Prism corner radius in units of cm. Defaults to 0. - - Returns - ------- - openmc.Region - The inside of a hexagonal prism - - """ - - l = edge_length - x, y = origin - - if orientation == 'y': - right = XPlane(x + sqrt(3.)/2*l, boundary_type) - left = XPlane(x - sqrt(3.)/2*l, boundary_type) - c = sqrt(3.)/3. - - # y = -x/sqrt(3) + a - upper_right = Plane(a=c, b=1., d=l+x*c+y, boundary_type=boundary_type) - - # y = x/sqrt(3) + a - upper_left = Plane(a=-c, b=1., d=l-x*c+y, boundary_type=boundary_type) - - # y = x/sqrt(3) - a - lower_right = Plane(a=-c, b=1., d=-l-x*c+y, boundary_type=boundary_type) - - # y = -x/sqrt(3) - a - lower_left = Plane(a=c, b=1., d=-l+x*c+y, boundary_type=boundary_type) - - prism = -right & +left & -upper_right & -upper_left & \ - +lower_right & +lower_left - - if boundary_type == 'periodic': - right.periodic_surface = left - upper_right.periodic_surface = lower_left - lower_right.periodic_surface = upper_left - - elif orientation == 'x': - top = YPlane(y0=y + sqrt(3.)/2*l, boundary_type=boundary_type) - bottom = YPlane(y0=y - sqrt(3.)/2*l, boundary_type=boundary_type) - c = sqrt(3.) - - # y = -sqrt(3)*(x - a) - upper_right = Plane(a=c, b=1., d=c*l+x*c+y, boundary_type=boundary_type) - - # y = sqrt(3)*(x + a) - lower_right = Plane(a=-c, b=1., d=-c*l-x*c+y, - boundary_type=boundary_type) - - # y = -sqrt(3)*(x + a) - lower_left = Plane(a=c, b=1., d=-c*l+x*c+y, boundary_type=boundary_type) - - # y = sqrt(3)*(x + a) - upper_left = Plane(a=-c, b=1., d=c*l-x*c+y, boundary_type=boundary_type) - - prism = -top & +bottom & -upper_right & +lower_right & \ - +lower_left & -upper_left - - if boundary_type == 'periodic': - top.periodic_surface = bottom - upper_right.periodic_surface = lower_left - lower_right.periodic_surface = upper_left - - # Handle rounded corners if given - if corner_radius > 0.: - if boundary_type == 'periodic': - raise ValueError('Periodic boundary conditions not permitted when ' - 'rounded corners are used.') - - c = sqrt(3.)/2 - t = l - corner_radius/c - - # Cylinder with corner radius and boundary type pre-applied - cyl1 = partial(ZCylinder, r=corner_radius, boundary_type=boundary_type) - cyl2 = partial(ZCylinder, r=corner_radius/(2*c), - boundary_type=boundary_type) - - if orientation == 'x': - x_min_y_min_in = cyl1(name='x min y min in', x0=x-t/2, y0=y-c*t) - x_min_y_max_in = cyl1(name='x min y max in', x0=x+t/2, y0=y-c*t) - x_max_y_min_in = cyl1(name='x max y min in', x0=x-t/2, y0=y+c*t) - x_max_y_max_in = cyl1(name='x max y max in', x0=x+t/2, y0=y+c*t) - x_min_in = cyl1(name='x min in', x0=x-t, y0=y) - x_max_in = cyl1(name='x max in', x0=x+t, y0=y) - - x_min_y_min_out = cyl2(name='x min y min out', x0=x-l/2, y0=y-c*l) - x_min_y_max_out = cyl2(name='x min y max out', x0=x+l/2, y0=y-c*l) - x_max_y_min_out = cyl2(name='x max y min out', x0=x-l/2, y0=y+c*l) - x_max_y_max_out = cyl2(name='x max y max out', x0=x+l/2, y0=y+c*l) - x_min_out = cyl2(name='x min out', x0=x-l, y0=y) - x_max_out = cyl2(name='x max out', x0=x+l, y0=y) - - corners = (+x_min_y_min_in & -x_min_y_min_out | - +x_min_y_max_in & -x_min_y_max_out | - +x_max_y_min_in & -x_max_y_min_out | - +x_max_y_max_in & -x_max_y_max_out | - +x_min_in & -x_min_out | - +x_max_in & -x_max_out) - - elif orientation == 'y': - x_min_y_min_in = cyl1(name='x min y min in', x0=x-c*t, y0=y-t/2) - x_min_y_max_in = cyl1(name='x min y max in', x0=x-c*t, y0=y+t/2) - x_max_y_min_in = cyl1(name='x max y min in', x0=x+c*t, y0=y-t/2) - x_max_y_max_in = cyl1(name='x max y max in', x0=x+c*t, y0=y+t/2) - y_min_in = cyl1(name='y min in', x0=x, y0=y-t) - y_max_in = cyl1(name='y max in', x0=x, y0=y+t) - - x_min_y_min_out = cyl2(name='x min y min out', x0=x-c*l, y0=y-l/2) - x_min_y_max_out = cyl2(name='x min y max out', x0=x-c*l, y0=y+l/2) - x_max_y_min_out = cyl2(name='x max y min out', x0=x+c*l, y0=y-l/2) - x_max_y_max_out = cyl2(name='x max y max out', x0=x+c*l, y0=y+l/2) - y_min_out = cyl2(name='y min out', x0=x, y0=y-l) - y_max_out = cyl2(name='y max out', x0=x, y0=y+l) - - corners = (+x_min_y_min_in & -x_min_y_min_out | - +x_min_y_max_in & -x_min_y_max_out | - +x_max_y_min_in & -x_max_y_min_out | - +x_max_y_max_in & -x_max_y_max_out | - +y_min_in & -y_min_out | - +y_max_in & -y_max_out) - - prism = prism & ~corners - - return prism - - -def get_hexagonal_prism(*args, **kwargs): - warn("get_hexagonal_prism(...) has been renamed hexagonal_prism(...). " - "Future versions of OpenMC will not accept get_hexagonal_prism.", - FutureWarning) - return hexagonal_prism(*args, **kwargs) - - -def cylinder_from_points(p1, p2, r, **kwargs): - """Return cylinder defined by two points passing through its center. - - Parameters - ---------- - p1, p2 : 3-tuples - Coordinates of two points that pass through the center of the cylinder - r : float - Radius of the cylinder - kwargs : dict - Keyword arguments passed to the :class:`openmc.Quadric` constructor - - Returns - ------- - openmc.Quadric - Quadric surface representing the cylinder. - - """ - # Get x, y, z coordinates of two points - x1, y1, z1 = p1 - x2, y2, z2 = p2 - - # Define intermediate terms - dx = x2 - x1 - dy = y2 - y1 - dz = z2 - z1 - cx = y1*z2 - y2*z1 - cy = x2*z1 - x1*z2 - cz = x1*y2 - x2*y1 - - # Given p=(x,y,z), p1=(x1, y1, z1), p2=(x2, y2, z2), the equation for the - # cylinder can be derived as r = |(p - p1) ⨯ (p - p2)| / |p2 - p1|. - # Expanding out all terms and grouping according to what Quadric expects - # gives the following coefficients. - kwargs['a'] = dy*dy + dz*dz - kwargs['b'] = dx*dx + dz*dz - kwargs['c'] = dx*dx + dy*dy - kwargs['d'] = -2*dx*dy - kwargs['e'] = -2*dy*dz - kwargs['f'] = -2*dx*dz - kwargs['g'] = 2*(cy*dz - cz*dy) - kwargs['h'] = 2*(cz*dx - cx*dz) - kwargs['j'] = 2*(cx*dy - cy*dx) - kwargs['k'] = cx*cx + cy*cy + cz*cz - (dx*dx + dy*dy + dz*dz)*r*r - - return Quadric(**kwargs) - - -def subdivide(surfaces): - """Create regions separated by a series of surfaces. - - This function allows regions to be constructed from a set of a surfaces that - are "in order". For example, if you had four instances of - :class:`openmc.ZPlane` at z=-10, z=-5, z=5, and z=10, this function would - return a list of regions corresponding to z < -10, -10 < z < -5, -5 < z < 5, - 5 < z < 10, and 10 < z. That is, for n surfaces, n+1 regions are returned. - - Parameters - ---------- - surfaces : sequence of openmc.Surface - Surfaces separating regions - - Returns - ------- - list of openmc.Region - Regions formed by the given surfaces - - """ - regions = [-surfaces[0]] - for s0, s1 in zip(surfaces[:-1], surfaces[1:]): - regions.append(+s0 & -s1) - regions.append(+surfaces[-1]) - return regions - - -def pin(surfaces, items, subdivisions=None, divide_vols=True, - **kwargs): - """Convenience function for building a fuel pin - - Parameters - ---------- - surfaces : iterable of :class:`openmc.Cylinder` - Cylinders used to define boundaries - between items. All cylinders must be - concentric and of the same orientation, e.g. - all :class:`openmc.ZCylinder` - items : iterable - Objects to go between ``surfaces``. These can be anything - that can fill a :class:`openmc.Cell`, including - :class:`openmc.Material`, or other :class:`openmc.Universe` - objects. There must be one more item than surfaces, - which will span all space outside the final ring. - subdivisions : None or dict of int to int - Dictionary describing which rings to subdivide and how - many times. Keys are indexes of the annular rings - to be divided. Will construct equal area rings - divide_vols : bool - If this evaluates to ``True``, then volumes of subdivided - :class:`openmc.Material` instances will also be divided by the - number of divisions. Otherwise the volume of the - original material will not be modified before subdivision - kwargs: - Additional key-word arguments to be passed to - :class:`openmc.Universe`, like ``name="Fuel pin"`` - - Returns - ------- - :class:`openmc.Universe` - Universe of concentric cylinders filled with the desired - items - """ - if "cells" in kwargs: - raise SyntaxError( - "Cells will be set by this function, not from input arguments.") - check_type("items", items, Iterable) - check_length("surfaces", surfaces, len(items) - 1, len(items) - 1) - # Check that all surfaces are of similar orientation - check_type("surface", surfaces[0], Cylinder) - surf_type = type(surfaces[0]) - check_iterable_type("surfaces", surfaces[1:], surf_type) - - # Check for increasing radii and equal centers - if surf_type is ZCylinder: - center_getter = attrgetter("x0", "y0") - elif surf_type is YCylinder: - center_getter = attrgetter("x0", "z0") - elif surf_type is XCylinder: - center_getter = attrgetter("z0", "y0") - else: - raise TypeError( - "Not configured to interpret {} surfaces".format( - surf_type.__name__)) - - centers = set() - prev_rad = 0 - for ix, surf in enumerate(surfaces): - cur_rad = surf.r - if cur_rad <= prev_rad: - raise ValueError( - "Surfaces do not appear to be increasing in radius. " - "Surface {} at index {} has radius {:7.3e} compared to " - "previous radius of {:7.5e}".format( - surf.id, ix, cur_rad, prev_rad)) - prev_rad = cur_rad - centers.add(center_getter(surf)) - - if len(centers) > 1: - raise ValueError( - "Surfaces do not appear to be concentric. The following " - "centers were found: {}".format(centers)) - - if subdivisions is not None: - check_length("subdivisions", subdivisions, 1, len(surfaces)) - orig_indexes = list(subdivisions.keys()) - check_iterable_type("ring indexes", orig_indexes, int) - check_iterable_type( - "number of divisions", list(subdivisions.values()), int) - for ix in orig_indexes: - if ix < 0: - subdivisions[len(surfaces) + ix] = subdivisions.pop(ix) - # Dissallow subdivision on outer most, infinite region - check_less_than( - "outer ring", max(subdivisions), len(surfaces), equality=True) - - # ensure ability to concatenate - if not isinstance(items, list): - items = list(items) - if not isinstance(surfaces, list): - surfaces = list(surfaces) - - # generate equal area divisions - # Adding N - 1 new regions - # N - 2 surfaces are made - # Original cell is not removed, but not occupies last ring - for ring_index in reversed(sorted(subdivisions.keys())): - nr = subdivisions[ring_index] - new_surfs = [] - - lower_rad = 0.0 if ring_index == 0 else surfaces[ring_index - 1].r - - upper_rad = surfaces[ring_index].r - - area_term = (upper_rad ** 2 - lower_rad ** 2) / nr - - for new_index in range(nr - 1): - lower_rad = sqrt(area_term + lower_rad ** 2) - new_surfs.append(surf_type(r=lower_rad)) - - surfaces = ( - surfaces[:ring_index] + new_surfs + surfaces[ring_index:]) - - filler = items[ring_index] - if (divide_vols and hasattr(filler, "volume") - and filler.volume is not None): - filler.volume /= nr - - items[ring_index:ring_index] = [ - filler.clone() for _i in range(nr - 1)] - - # Build the universe - regions = subdivide(surfaces) - cells = [Cell(fill=f, region=r) for r, f in zip(regions, items)] - return Universe(cells=cells, **kwargs) diff --git a/openmc/model/model.py b/openmc/model/model.py deleted file mode 100644 index 33a38ef22..000000000 --- a/openmc/model/model.py +++ /dev/null @@ -1,223 +0,0 @@ -from collections.abc import Iterable -from pathlib import Path - -import openmc -from openmc.checkvalue import check_type, check_value - - -class Model(object): - """Model container. - - This class can be used to store instances of :class:`openmc.Geometry`, - :class:`openmc.Materials`, :class:`openmc.Settings`, - :class:`openmc.Tallies`, :class:`openmc.Plots`, and :class:`openmc.CMFD`, - thus making a complete model. The :meth:`Model.export_to_xml` method will - export XML files for all attributes that have been set. If the - :meth:`Model.materials` attribute is not set, it will attempt to create a - ``materials.xml`` file based on all materials appearing in the geometry. - - Parameters - ---------- - geometry : openmc.Geometry, optional - Geometry information - materials : openmc.Materials, optional - Materials information - settings : openmc.Settings, optional - Settings information - tallies : openmc.Tallies, optional - Tallies information - plots : openmc.Plots, optional - Plot information - - Attributes - ---------- - geometry : openmc.Geometry - Geometry information - materials : openmc.Materials - Materials information - settings : openmc.Settings - Settings information - tallies : openmc.Tallies - Tallies information - plots : openmc.Plots - Plot information - - """ - - def __init__(self, geometry=None, materials=None, settings=None, - tallies=None, plots=None): - self.geometry = openmc.Geometry() - self.materials = openmc.Materials() - self.settings = openmc.Settings() - self.tallies = openmc.Tallies() - self.plots = openmc.Plots() - - if geometry is not None: - self.geometry = geometry - if materials is not None: - self.materials = materials - if settings is not None: - self.settings = settings - if tallies is not None: - self.tallies = tallies - if plots is not None: - self.plots = plots - - @property - def geometry(self): - return self._geometry - - @property - def materials(self): - return self._materials - - @property - def settings(self): - return self._settings - - @property - def tallies(self): - return self._tallies - - @property - def plots(self): - return self._plots - - @geometry.setter - def geometry(self, geometry): - check_type('geometry', geometry, openmc.Geometry) - self._geometry = geometry - - @materials.setter - def materials(self, materials): - check_type('materials', materials, Iterable, openmc.Material) - if isinstance(materials, openmc.Materials): - self._materials = materials - else: - del self._materials[:] - for mat in materials: - self._materials.append(mat) - - @settings.setter - def settings(self, settings): - check_type('settings', settings, openmc.Settings) - self._settings = settings - - @tallies.setter - def tallies(self, tallies): - check_type('tallies', tallies, Iterable, openmc.Tally) - if isinstance(tallies, openmc.Tallies): - self._tallies = tallies - else: - del self._tallies[:] - for tally in tallies: - self._tallies.append(tally) - - @plots.setter - def plots(self, plots): - check_type('plots', plots, Iterable, openmc.Plot) - if isinstance(plots, openmc.Plots): - self._plots = plots - else: - del self._plots[:] - for plot in plots: - self._plots.append(plot) - - def deplete(self, timesteps, chain_file=None, method='cecm', - fission_q=None, **kwargs): - """Deplete model using specified timesteps/power - - Parameters - ---------- - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - chain_file : str, optional - Path to the depletion chain XML file. Defaults to the chain - found under the ``depletion_chain`` in the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable if it exists. - method : str - Integration method used for depletion (e.g., 'cecm', 'predictor') - fission_q : dict, optional - Dictionary of nuclides and their fission Q values [eV]. - If not given, values will be pulled from the ``chain_file``. - **kwargs - Keyword arguments passed to integration function (e.g., - :func:`openmc.deplete.integrator.cecm`) - - """ - # Import the depletion module. This is done here rather than the module - # header to delay importing openmc.lib (through openmc.deplete) which - # can be tough to install properly. - import openmc.deplete as dep - - # Create OpenMC transport operator - op = dep.Operator( - self.geometry, self.settings, chain_file, - fission_q=fission_q, - ) - - # Perform depletion - check_value('method', method, ('cecm', 'predictor', 'cf4', 'epc_rk4', - 'si_celi', 'si_leqi', 'celi', 'leqi')) - getattr(dep.integrator, method)(op, timesteps, **kwargs) - - def export_to_xml(self, directory='.'): - """Export model to XML files. - - Parameters - ---------- - directory : str - Directory to write XML files to. If it doesn't exist already, it - will be created. - - """ - # Create directory if - d = Path(directory) - if not d.is_dir(): - d.mkdir(parents=True) - - self.settings.export_to_xml(d) - if not self.settings.dagmc: - self.geometry.export_to_xml(d) - - # If a materials collection was specified, export it. Otherwise, look - # for all materials in the geometry and use that to automatically build - # a collection. - if self.materials: - self.materials.export_to_xml(d) - else: - materials = openmc.Materials(self.geometry.get_all_materials() - .values()) - materials.export_to_xml(d) - - if self.tallies: - self.tallies.export_to_xml(d) - if self.plots: - self.plots.export_to_xml(d) - - def run(self, **kwargs): - """Creates the XML files, runs OpenMC, and returns k-effective - - Parameters - ---------- - **kwargs - All keyword arguments are passed to :func:`openmc.run` - - Returns - ------- - uncertainties.UFloat - Combined estimator of k-effective from the statepoint - - """ - self.export_to_xml() - - openmc.run(**kwargs) - - n = self.settings.batches - if self.settings.statepoint is not None: - if 'batches' in self.settings.statepoint: - n = self.settings.statepoint['batches'][-1] - - with openmc.StatePoint('statepoint.{}.h5'.format(n)) as sp: - return sp.k_combined diff --git a/openmc/model/triso.py b/openmc/model/triso.py deleted file mode 100644 index 2afc88d64..000000000 --- a/openmc/model/triso.py +++ /dev/null @@ -1,1335 +0,0 @@ -import copy -import warnings -import itertools -import random -from abc import ABCMeta, abstractproperty, abstractmethod -from collections import Counter, defaultdict -from collections.abc import Iterable -from heapq import heappush, heappop -from math import pi, sin, cos, floor, log10, sqrt -from numbers import Real -from random import uniform, gauss - -import numpy as np -import scipy.spatial - -import openmc -from openmc.checkvalue import check_type - - -MAX_PF_RSP = 0.38 -MAX_PF_CRP = 0.64 - - -class TRISO(openmc.Cell): - """Tristructural-isotopic (TRISO) micro fuel particle - - Parameters - ---------- - outer_radius : float - Outer radius of TRISO particle - fill : openmc.Universe - Universe which contains all layers of the TRISO particle - center : Iterable of float - Cartesian coordinates of the center of the TRISO particle in cm - - Attributes - ---------- - id : int - Unique identifier for the TRISO cell - name : str - Name of the TRISO cell - center : numpy.ndarray - Cartesian coordinates of the center of the TRISO particle in cm - fill : openmc.Universe - Universe that contains the TRISO layers - region : openmc.Region - Region of space within the TRISO particle - - """ - - def __init__(self, outer_radius, fill, center=(0., 0., 0.)): - self._surface = openmc.Sphere(r=outer_radius) - super().__init__(fill=fill, region=-self._surface) - self.center = np.asarray(center) - - @property - def center(self): - return self._center - - @center.setter - def center(self, center): - check_type('TRISO center', center, Iterable, Real) - self._surface.x0 = center[0] - self._surface.y0 = center[1] - self._surface.z0 = center[2] - self.translation = center - self._center = center - - def classify(self, lattice): - """Determine lattice element indices which might contain the TRISO particle. - - Parameters - ---------- - lattice : openmc.RectLattice - Lattice to check - - Returns - ------- - list of tuple - (z,y,x) lattice element indices which might contain the TRISO - particle. - - """ - - ll, ur = self.region.bounding_box - if lattice.ndim == 2: - (i_min, j_min), p = lattice.find_element(ll) - (i_max, j_max), p = lattice.find_element(ur) - return list(np.broadcast(*np.ogrid[ - j_min:j_max+1, i_min:i_max+1])) - else: - (i_min, j_min, k_min), p = lattice.find_element(ll) - (i_max, j_max, k_max), p = lattice.find_element(ur) - return list(np.broadcast(*np.ogrid[ - k_min:k_max+1, j_min:j_max+1, i_min:i_max+1])) - - -class _Container(metaclass=ABCMeta): - """Container in which to pack spheres. - - Parameters - ---------- - sphere_radius : float - Radius of spheres to be packed in container. - center : Iterable of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - - Attributes - ---------- - sphere_radius : float - Radius of spheres to be packed in container. - center : list of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - cell_length : list of float - Length in x-, y-, and z- directions of each cell in mesh overlaid on - domain. - limits : list of float - Constraint on where sphere center can be placed. - volume : float - Volume of the container. - - """ - def __init__(self, sphere_radius, center=(0., 0., 0.)): - self._cell_length = None - self._limits = None - - self.sphere_radius = sphere_radius - self.center = center - - @property - def sphere_radius(self): - return self._sphere_radius - - @property - def center(self): - return self._center - - @abstractproperty - def limits(self): - pass - - @abstractproperty - def cell_length(self): - pass - - @abstractproperty - def volume(self): - pass - - @sphere_radius.setter - def sphere_radius(self, sphere_radius): - self._sphere_radius = float(sphere_radius) - self._limits = None - self._cell_length = None - - @center.setter - def center(self, center): - self._center = center - - def mesh_cell(self, p): - """Calculate the index of the cell in a mesh overlaid on the domain in - which the given sphere center falls. - - Parameters - ---------- - p : Iterable of float - Cartesian coordinates of sphere center. - - Returns - ------- - tuple of int - Indices of mesh cell. - - """ - return tuple(int(p[i]/self.cell_length[i]) for i in range(3)) - - def nearby_mesh_cells(self, p): - """Calculates the indices of all cells in a mesh overlaid on the domain - within one diameter of the given sphere. - - Parameters - ---------- - p : Iterable of float - Cartesian coordinates of sphere center. - - Returns - ------- - list of tuple of int - Indices of mesh cells. - - """ - d = 2*self.sphere_radius - r = [[a/self.cell_length[i] for a in [p[i]-d, p[i], p[i]+d]] - for i in range(3)] - return list(itertools.product(*({int(x) for x in y} for y in r))) - - @abstractmethod - def from_region(self, region, sphere_radius): - """Create a container to pack spheres in based on a region. - - Parameters - ---------- - region : openmc.Region - Region to create container from. - sphere_radius : float - Outer radius of spheres. - - """ - pass - - @abstractmethod - def random_point(self): - """Generate Cartesian coordinates of center of a sphere that is - contained entirely within the domain with uniform probability. - - Returns - ------- - list of float - Cartesian coordinates of sphere center. - - """ - pass - - @abstractmethod - def repel_spheres(self, p, q, d, d_new): - """Move spheres p and q apart according to the following - transformation (accounting for boundary conditions on domain): - - r_i^(n+1) = r_i^(n) + 1/2(d_out^(n+1) - d^(n)) - r_j^(n+1) = r_j^(n) - 1/2(d_out^(n+1) - d^(n)) - - Parameters - ---------- - p, q : numpy.ndarray - Cartesian coordinates of sphere center. - d : float - distance between centers of spheres i and j. - d_new : float - final distance between centers of spheres i and j. - - """ - pass - - -class _RectangularPrism(_Container): - """Rectangular prism container in which to pack spheres. - - Parameters - ---------- - width : float - Prism length along the x-axis - depth : float - Prism length along the y-axis - height : float - Prism length along the z-axis - sphere_radius : float - Radius of spheres to be packed in container. - center : Iterable of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - - Attributes - ---------- - width : float - Prism length along the x-axis - depth : float - Prism length along the y-axis - height : float - Prism length along the z-axis - sphere_radius : float - Radius of spheres to be packed in container. - center : list of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - cell_length : list of float - Length in x-, y-, and z- directions of each cell in mesh overlaid on - domain. - limits : list of float - Minimum and maximum distance in x-, y-, and z-direction where sphere - center can be placed. - volume : float - Volume of the container. - - """ - - def __init__(self, width, depth, height, sphere_radius, center=(0., 0., 0.)): - super().__init__(sphere_radius, center) - self.width = width - self.depth = depth - self.height = height - - @property - def width(self): - return self._width - - @property - def depth(self): - return self._depth - - @property - def height(self): - return self._height - - @property - def limits(self): - if self._limits is None: - c = self.center - r = self.sphere_radius - x, y, z = self.width/2, self.depth/2, self.height/2 - self._limits = [[c[0] - x + r, c[1] - y + r, c[2] - z + r], - [c[0] + x - r, c[1] + y - r, c[2] + z - r]] - return self._limits - - @property - def cell_length(self): - if self._cell_length is None: - mesh_length = [self.width, self.depth, self.height] - self._cell_length = [x/int(x/(4*self.sphere_radius)) - for x in mesh_length] - return self._cell_length - - @property - def volume(self): - return self.width*self.depth*self.height - - @width.setter - def width(self, width): - self._width = float(width) - self._limits = None - self._cell_length = None - - @depth.setter - def depth(self, depth): - self._depth = float(depth) - self._limits = None - self._cell_length = None - - @height.setter - def height(self, height): - self._height = float(height) - self._limits = None - self._cell_length = None - - @limits.setter - def limits(self, limits): - self._limits = limits - - @classmethod - def from_region(self, region, sphere_radius): - check_type('region', region, openmc.Region) - - # Assume the simplest case where the prism volume is the intersection - # of the half-spaces of six planes - if not isinstance(region, openmc.Intersection): - raise ValueError - - if any(not isinstance(node, openmc.Halfspace) for node in region): - raise ValueError - - if len(region) != 6: - raise ValueError - - # Sort half-spaces by surface type - px1, px2, py1, py2, pz1, pz2 = sorted(region, key=lambda x: x.surface.type) - - # Make sure the region consists of the correct surfaces - if (not isinstance(px1.surface, openmc.XPlane) or - not isinstance(px2.surface, openmc.XPlane) or - not isinstance(py1.surface, openmc.YPlane) or - not isinstance(py2.surface, openmc.YPlane) or - not isinstance(pz1.surface, openmc.ZPlane) or - not isinstance(pz2.surface, openmc.ZPlane)): - raise ValueError - - # Make sure the half-spaces are on the correct side of the surfaces - ll, ur = region.bounding_box - if any(x in ll or x in ur for x in (-np.inf, np.inf)): - raise ValueError - - # Calculate the parameters for the container - width, depth, height = ur - ll - center = ll + [width/2, depth/2, height/2] - - # The region is the volume of a rectangular prism, so create container - return _RectangularPrism(width, depth, height, sphere_radius, center) - - def random_point(self): - ll, ul = self.limits - return [uniform(ll[0], ul[0]), - uniform(ll[1], ul[1]), - uniform(ll[2], ul[2])] - - def repel_spheres(self, p, q, d, d_new): - # Moving each sphere distance 's' away from the other along the line - # joining the sphere centers will ensure their final distance is - # equal to the outer diameter - s = (d_new - d)/2 - - v = (p - q)/d - p += s*v - q -= s*v - - # Enforce the rigid boundary by moving each sphere back along the - # surface normal until it is completely within the container if it - # overlaps the surface - p[:] = np.clip(p, self.limits[0], self.limits[1]) - q[:] = np.clip(q, self.limits[0], self.limits[1]) - - -class _Cylinder(_Container): - """Cylindrical container in which to pack spheres. - - Parameters - ---------- - length : float - Length of the cylindrical container. - radius : float - Radius of the cylindrical container. - axis : string - Axis along which the length of the cylinder is aligned. - sphere_radius : float - Radius of spheres to be packed in container. - center : Iterable of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - - Attributes - ---------- - length : float - Length of the cylindrical container. - radius : float - Radius of the cylindrical container. - axis : string - Axis along which the length of the cylinder is aligned. - sphere_radius : float - Radius of spheres to be packed in container. - center : list of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - shift : list of int - Rolled indices of the x-, y-, and z- coordinates of a sphere so the - configuration is aligned with the correct axis. No shift corresponds to - a cylinder along the z-axis. - cell_length : list of float - Length in x-, y-, and z- directions of each cell in mesh overlaid on - domain. - limits : list of float - Maximum radial distance and minimum and maximum distance in the - direction parallel to the axis where sphere center can be placed. - volume : float - Volume of the container. - - """ - - def __init__(self, length, radius, axis, sphere_radius, center=(0., 0., 0.)): - super().__init__(sphere_radius, center) - self._shift = None - self.length = length - self.radius = radius - self.axis = axis - - @property - def length(self): - return self._length - - @property - def radius(self): - return self._radius - - @property - def axis(self): - return self._axis - - @property - def shift(self): - if self._shift is None: - if self.axis == 'x': - self._shift = [1, 2, 0] - elif self.axis == 'y': - self._shift = [2, 0, 1] - else: - self._shift = [0, 1, 2] - return self._shift - - @property - def limits(self): - if self._limits is None: - z0 = self.center[self.shift[2]] - z = self.length/2 - r = self.sphere_radius - self._limits = [[z0 - z + r], [z0 + z - r, self.radius - r]] - return self._limits - - @property - def cell_length(self): - if self._cell_length is None: - h = 4*self.sphere_radius - i, j, k = self.shift - self._cell_length = [None]*3 - self._cell_length[i] = 2*self.radius/int(2*self.radius/h) - self._cell_length[j] = 2*self.radius/int(2*self.radius/h) - self._cell_length[k] = self.length/int(self.length/h) - return self._cell_length - - @property - def volume(self): - return self.length*pi*self.radius**2 - - @length.setter - def length(self, length): - self._length = float(length) - self._limits = None - self._cell_length = None - - @radius.setter - def radius(self, radius): - self._radius = float(radius) - self._limits = None - self._cell_length = None - - @axis.setter - def axis(self, axis): - self._axis = axis - self._shift = None - - @limits.setter - def limits(self, limits): - self._limits = limits - - @classmethod - def from_region(self, region, sphere_radius): - check_type('region', region, openmc.Region) - - # Assume the simplest case where the cylinder volume is the - # intersection of the half-spaces of a cylinder and two planes - if not isinstance(region, openmc.Intersection): - raise ValueError - - if any(not isinstance(node, openmc.Halfspace) for node in region): - raise ValueError - - if len(region) != 3: - raise ValueError - - # Identify the axis that the cylinder lies along - axis = region[0].surface.type[0] - - # Make sure the region is composed of a cylinder and two planes on the - # same axis - count = Counter(node.surface.type for node in region) - if count[axis + '-cylinder'] != 1 or count[axis + '-plane'] != 2: - raise ValueError - - # Sort the half-spaces by surface type - cyl, p1, p2 = sorted(region, key=lambda x: x.surface.type) - - # Calculate the parameters for a cylinder along the x-axis - if axis == 'x': - if p1.surface.x0 > p2.surface.x0: - p1, p2 = p2, p1 - length = p2.surface.x0 - p1.surface.x0 - center = (p1.surface.x0 + length/2, cyl.surface.y0, cyl.surface.z0) - - # Calculate the parameters for a cylinder along the y-axis - elif axis == 'y': - if p1.surface.y0 > p2.surface.y0: - p1, p2 = p2, p1 - length = p2.surface.y0 - p1.surface.y0 - center = (cyl.surface.x0, p1.surface.y0 + length/2, cyl.surface.z0) - - # Calculate the parameters for a cylinder along the z-axis - else: - if p1.surface.z0 > p2.surface.z0: - p1, p2 = p2, p1 - length = p2.surface.z0 - p1.surface.z0 - center = (cyl.surface.x0, cyl.surface.y0, p1.surface.z0 + length/2) - - # Make sure the half-spaces are on the correct side of the surfaces - if cyl.side != '-' or p1.side != '+' or p2.side != '-': - raise ValueError - - radius = cyl.surface.r - - # The region is the volume of a cylinder, so create container - return _Cylinder(length, radius, axis, sphere_radius, center) - - def random_point(self): - ll, ul = self.limits - r = sqrt(uniform(0, ul[1]**2)) - t = uniform(0, 2*pi) - i, j, k = self.shift - p = [None]*3 - p[i] = r*cos(t) + self.center[i] - p[j] = r*sin(t) + self.center[j] - p[k] = uniform(ll[0], ul[0]) - return p - - def repel_spheres(self, p, q, d, d_new): - # Moving each sphere distance 's' away from the other along the line - # joining the sphere centers will ensure their final distance is - # equal to the outer diameter - s = (d_new - d)/2 - - v = (p - q)/d - p += s*v - q -= s*v - - # Enforce the rigid boundary by moving each sphere back along the - # surface normal until it is completely within the container if it - # overlaps the surface - ll, ul = self.limits - c = self.center - i, j, k = self.shift - - r = sqrt((p[i] - c[i])**2 + (p[j] - c[j])**2) - if r > ul[1]: - p[i] = (p[i] - c[i])*ul[1]/r + c[i] - p[j] = (p[j] - c[j])*ul[1]/r + c[j] - p[k] = np.clip(p[k], ll[0], ul[0]) - - r = sqrt((q[i] - c[i])**2 + (q[j] - c[j])**2) - if r > ul[1]: - q[i] = (q[i] - c[i])*ul[1]/r + c[i] - q[j] = (q[j] - c[j])*ul[1]/r + c[j] - q[k] = np.clip(q[k], ll[0], ul[0]) - - -class _SphericalShell(_Container): - """Spherical shell container in which to pack spheres. - - Parameters - ---------- - radius : float - Outer radius of the spherical shell container. - inner_radius : float - Inner radius of the spherical shell container. - center : Iterable of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - - Attributes - ---------- - radius : float - Outer radius of the spherical shell container. - inner_radius : float - Inner radius of the spherical shell container. - sphere_radius : float - Radius of spheres to be packed in container. - center : list of float - Cartesian coordinates of the center of the container. Default is - (0., 0., 0.) - cell_length : list of float - Length in x-, y-, and z- directions of each cell in mesh overlaid on - domain. - limits : list of float - Minimum and maximum radial distance where sphere center can be placed. - volume : float - Volume of the container. - - """ - - def __init__(self, radius, inner_radius, sphere_radius, - center=(0., 0., 0.)): - super().__init__(sphere_radius, center) - self.radius = radius - self.inner_radius = inner_radius - - @property - def radius(self): - return self._radius - - @property - def inner_radius(self): - return self._inner_radius - - @property - def limits(self): - if self._limits is None: - r_max = self.radius - self.sphere_radius - if self.inner_radius == 0: - r_min = 0 - else: - r_min = self.inner_radius + self.sphere_radius - self._limits = [[r_min], [r_max]] - return self._limits - - @property - def cell_length(self): - if self._cell_length is None: - mesh_length = 3*[2*self.radius] - self._cell_length = [x/int(x/(4*self.sphere_radius)) - for x in mesh_length] - return self._cell_length - - @property - def volume(self): - return 4/3*pi*(self.radius**3 - self.inner_radius**3) - - @radius.setter - def radius(self, radius): - self._radius = float(radius) - self._limits = None - self._cell_length = None - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = float(inner_radius) - self._limits = None - - @limits.setter - def limits(self, limits): - self._limits = limits - - @classmethod - def from_region(self, region, sphere_radius): - check_type('region', region, openmc.Region) - - # First check if the region is the volume inside a sphere. Assume the - # simplest case where the sphere volume is the negative half-space of a - # sphere. - if (isinstance(region, openmc.Halfspace) - and isinstance(region.surface, openmc.Sphere) - and region.side == '-'): - - # The region is the volume of a sphere, so create container - radius = region.surface.r - center = (region.surface.x0, region.surface.y0, region.surface.z0) - - return _SphericalShell(radius, 0., sphere_radius, center) - - # Next check for a spherical shell volume. Assume the simplest case - # where the spherical shell volume is the intersection of the - # half-spaces of two spheres. - if not isinstance(region, openmc.Intersection): - raise ValueError - - if any(not isinstance(node, openmc.Halfspace) for node in region): - raise ValueError - - if len(region) != 2: - raise ValueError - - if any(not isinstance(node.surface, openmc.Sphere) for node in region): - raise ValueError - - s1, s2 = sorted(region, key=lambda x: x.surface.r) - radius = s2.surface.r - inner_radius = s1.surface.r - center = (s1.surface.x0, s1.surface.y0, s1.surface.z0) - - if center != (s2.surface.x0, s2.surface.y0, s2.surface.z0): - raise ValueError - - if s1.side != '+' or s2.side != '-': - raise ValueError - - # The region is the volume of a spherical shell, so create container - return _SphericalShell(radius, inner_radius, sphere_radius, center) - - def random_point(self): - c = self.center - ll, ul = self.limits - x, y, z = (gauss(0, 1), gauss(0, 1), gauss(0, 1)) - r = (uniform(ll[0]**3, ul[0]**3)**(1/3)/sqrt(x**2 + y**2 + z**2)) - return [r*x + c[0], r*y + c[1], r*z + c[2]] - - def repel_spheres(self, p, q, d, d_new): - # Moving each sphere distance 's' away from the other along the line - # joining the sphere centers will ensure their final distance is - # equal to the outer diameter - s = (d_new - d)/2 - - v = (p - q)/d - p += s*v - q -= s*v - - # Enforce the rigid boundary by moving each sphere back along the - # surface normal until it is completely within the container if it - # overlaps the surface - c = self.center - ll, ul = self.limits - - r = sqrt((p[0] - c[0])**2 + (p[1] - c[1])**2 + (p[2] - c[2])**2) - if r > ul[0]: - p[:] = (p - c)*ul[0]/r + c - elif r < ll[0]: - p[:] = (p - c)*ll[0]/r + c - - r = sqrt((q[0] - c[0])**2 + (q[1] - c[1])**2 + (q[2] - c[2])**2) - if r > ul[0]: - q[:] = (q - c)*ul[0]/r + c - elif r < ll[0]: - q[:] = (q - c)*ll[0]/r + c - - -def create_triso_lattice(trisos, lower_left, pitch, shape, background): - """Create a lattice containing TRISO particles for optimized tracking. - - Parameters - ---------- - trisos : list of openmc.model.TRISO - List of TRISO particles to put in lattice - lower_left : Iterable of float - Lower-left Cartesian coordinates of the lattice - pitch : Iterable of float - Pitch of the lattice elements in the x-, y-, and z-directions - shape : Iterable of float - Number of lattice elements in the x-, y-, and z-directions - background : openmc.Material - A background material that is used anywhere within the lattice but - outside a TRISO particle - - Returns - ------- - lattice : openmc.RectLattice - A lattice containing the TRISO particles - - """ - - lattice = openmc.RectLattice() - lattice.lower_left = lower_left - lattice.pitch = pitch - - indices = list(np.broadcast(*np.ogrid[:shape[2], :shape[1], :shape[0]])) - triso_locations = {idx: [] for idx in indices} - for t in trisos: - for idx in t.classify(lattice): - if idx in sorted(triso_locations): - # Create copy of TRISO particle with materials preserved and - # different cell/surface IDs - t_copy = copy.deepcopy(t) - t_copy.id = None - t_copy.fill = t.fill - t_copy._surface.id = None - triso_locations[idx].append(t_copy) - else: - warnings.warn('TRISO particle is partially or completely ' - 'outside of the lattice.') - - # Create universes - universes = np.empty(shape[::-1], dtype=openmc.Universe) - for idx, triso_list in sorted(triso_locations.items()): - if len(triso_list) > 0: - outside_trisos = openmc.Intersection(~t.region for t in triso_list) - background_cell = openmc.Cell(fill=background, region=outside_trisos) - else: - background_cell = openmc.Cell(fill=background) - - u = openmc.Universe() - u.add_cell(background_cell) - for t in triso_list: - u.add_cell(t) - iz, iy, ix = idx - t.center = lattice.get_local_coordinates(t.center, (ix, iy, iz)) - - if len(shape) == 2: - universes[-1 - idx[0], idx[1]] = u - else: - universes[idx[0], -1 - idx[1], idx[2]] = u - lattice.universes = universes - - # Set outer universe - background_cell = openmc.Cell(fill=background) - lattice.outer = openmc.Universe(cells=[background_cell]) - - return lattice - - -def _random_sequential_pack(domain, num_spheres): - """Random sequential packing of spheres within a container. - - Parameters - ---------- - domain : openmc.model._Container - Container in which to pack spheres. - num_spheres : int - Number of spheres to pack. - - Returns - ------ - numpy.ndarray - Cartesian coordinates of centers of spheres. - - """ - - sqd = (2*domain.sphere_radius)**2 - spheres = [] - mesh = defaultdict(list) - - for i in range(num_spheres): - # Randomly sample new center coordinates while there are any overlaps - while True: - p = domain.random_point() - idx = domain.mesh_cell(p) - if any((p[0]-q[0])**2 + (p[1]-q[1])**2 + (p[2]-q[2])**2 < sqd - for q in mesh[idx]): - continue - else: - break - spheres.append(p) - - for idx in domain.nearby_mesh_cells(p): - mesh[idx].append(p) - - return np.array(spheres) - - -def _close_random_pack(domain, spheres, contraction_rate): - """Close random packing of spheres using the Jodrey-Tory algorithm. - - Parameters - ---------- - domain : openmc.model._Container - Container in which to pack spheres. - spheres : numpy.ndarray - Initial Cartesian coordinates of centers of spheres. - contraction_rate : float - Contraction rate of outer diameter. - - """ - - def add_rod(d, i, j): - """Add a new rod to the priority queue. - - Parameters - ---------- - d : float - distance between centers of spheres i and j. - i, j : int - Index of spheres in spheres array. - - """ - - rod = [d, i, j] - rods_map[i] = (j, rod) - rods_map[j] = (i, rod) - heappush(rods, rod) - - def remove_rod(i): - """Mark the rod containing sphere i as removed. - - Parameters - ---------- - i : int - Index of sphere in spheres array. - - """ - - if i in rods_map: - j, rod = rods_map.pop(i) - del rods_map[j] - rod[1] = removed - rod[2] = removed - - def pop_rod(): - """Remove and return the shortest rod. - - Returns - ------- - d : float - distance between centers of spheres i and j. - i, j : int - Index of spheres in spheres array. - - """ - - while rods: - d, i, j = heappop(rods) - if i != removed and j != removed: - del rods_map[i] - del rods_map[j] - return d, i, j - return None, None, None - - def create_rod_list(): - """Generate sorted list of rods (distances between sphere centers). - - Rods are arranged in a heap where each element contains the rod length - and the sphere indices. A rod between spheres p and q is only - included if the distance between p and q could not be changed by the - elimination of a greater overlap, i.e. q has no nearer neighbors than p. - - A mapping of sphere ids to rods is maintained in 'rods_map'. Each key - in the dict is the id of a sphere that is in the rod list, and the - value is the id of its nearest neighbor and the rod that contains them. - The dict is used to find rods in the priority queue and to mark removed - rods so rods can be "removed" without breaking the heap structure - invariant. - - """ - - # Create KD tree for quick nearest neighbor search - tree = scipy.spatial.cKDTree(spheres) - - # Find distance to nearest neighbor and index of nearest neighbor for - # all spheres - d, n = tree.query(spheres, k=2) - d = d[:, 1] - n = n[:, 1] - - # Array of sphere indices, indices of nearest neighbors, and - # distances to nearest neighbors - a = np.vstack((list(range(n.size)), n, d)).T - - # Sort along second column and swap first and second columns to create - # array of nearest neighbor indices, indices of spheres they are - # nearest neighbors of, and distances between them - b = a[a[:, 1].argsort()] - b[:, [0, 1]] = b[:, [1, 0]] - - # Find the intersection between 'a' and 'b': a list of spheres who - # are each other's nearest neighbors and the distance between them - r = list({tuple(x) for x in a} & {tuple(x) for x in b}) - - # Remove duplicate rods and sort by distance - r = map(list, set([(x[2], int(min(x[0:2])), int(max(x[0:2]))) - for x in r])) - - # Clear priority queue and add rods - del rods[:] - rods_map.clear() - for d, i, j in r: - if d < outer_diameter and not np.isclose(d, outer_diameter, atol=1.0e-14): - add_rod(d, i, j) - - def update_mesh(i): - """Update which mesh cells the sphere is in based on new sphere - center coordinates. - - 'mesh'/'mesh_map' is a two way dictionary used to look up which - spheres are located within one diameter of a given mesh cell and - which mesh cells a given sphere center is within one diameter of. - This is used to speed up the nearest neighbor search. - - Parameters - ---------- - i : int - Index of sphere in spheres array. - - """ - - # Determine which mesh cells the sphere is in and remove the - # sphere id from those cells - for idx in mesh_map[i]: - mesh[idx].remove(i) - del mesh_map[i] - - # Determine which mesh cells are within one diameter of sphere's - # center and add this sphere to the list of spheres in those cells - for idx in domain.nearby_mesh_cells(spheres[i]): - mesh[idx].add(i) - mesh_map[i].add(idx) - - def reduce_outer_diameter(): - """Reduce the outer diameter so that at the (i+1)-st iteration it is: - - d_out^(i+1) = d_out^(i) - (1/2)^(j) * d_out0 * k / n, - - where k is the contraction rate, n is the number of spheres, and - - j = floor(-log10(pf_out - pf_in)). - - Returns - ------- - float - New outer diameter - - """ - - inner_pf = 4/3*pi*(inner_diameter/2)**3*num_spheres/domain.volume - outer_pf = 4/3*pi*(outer_diameter/2)**3*num_spheres/domain.volume - - j = floor(-log10(outer_pf - inner_pf)) - return (outer_diameter - 0.5**j * contraction_rate * - initial_outer_diameter / num_spheres) - - def nearest(i): - """Find index of nearest neighbor of sphere i. - - Parameters - ---------- - i : int - Index in spheres array of sphere for which to find nearest - neighbor. - - Returns - ------- - int - Index in spheres array of nearest neighbor of i - float - distance between i and nearest neighbor. - - """ - - # Need the second nearest neighbor of i since the nearest neighbor - # will be itself. Using argpartition, the k-th nearest neighbor is - # placed at index k. - idx = list(mesh[domain.mesh_cell(spheres[i])]) - dists = scipy.spatial.distance.cdist([spheres[i]], spheres[idx])[0] - if dists.size > 1: - j = dists.argpartition(1)[1] - return idx[j], dists[j] - else: - return None, None - - def update_rod_list(i): - """Update the rod list with the new nearest neighbors of sphere since - its overlap was eliminated. - - Parameters - ---------- - i : int - Index of sphere in spheres array. - - """ - - # If the nearest neighbor k of sphere i has no nearer neighbors, - # remove the rod currently containing k from the rod list and add rod - # k-i, keeping the rod list sorted - k, d_ik = nearest(i) - if (k and nearest(k)[0] == i and d_ik < outer_diameter - and not np.isclose(d, outer_diameter, atol=1.0e-14)): - remove_rod(k) - add_rod(d_ik, i, k) - - num_spheres = len(spheres) - diameter = 2*domain.sphere_radius - - # Flag for marking rods that have been removed from priority queue - removed = -1 - - # Outer diameter initially set to arbitrary value that yields pf of 1 - initial_outer_diameter = 2*(domain.volume/(num_spheres*4/3*pi))**(1/3) - - # Inner and outer diameter of spheres will change during packing - outer_diameter = initial_outer_diameter - inner_diameter = 0. - - # List of rods arranged in a heap and mapping of sphere ids to rods - rods = [] - rods_map = {} - - # Initialize two-way dictionary that identifies which spheres are near a - # given mesh cell and which mesh cells a sphere is near - mesh = defaultdict(set) - mesh_map = defaultdict(set) - for i in range(num_spheres): - for idx in domain.nearby_mesh_cells(spheres[i]): - mesh[idx].add(i) - mesh_map[i].add(idx) - - while True: - # Rebuild the sorted list of rods according to the current sphere - # configuration - create_rod_list() - - # Set the inner diameter to the shortest center-to-center distance - # between any two spheres - if rods: - inner_diameter = rods[0][0] - - # Reached the desired sphere radius - if inner_diameter >= diameter: - break - - # The algorithm converged before reaching the desired sphere radius. - # This can happen when the desired packing fraction is close to the - # packing fraction limit. The packing fraction is a random variable - # that is determined by the sphere locations and the contraction - # rate. A higher packing fraction can be achieved with a smaller - # contraction rate, though at the cost of a longer simulation time -- - # the number of iterations needed to remove all overlaps is inversely - # proportional to the contraction rate. - if inner_diameter >= outer_diameter or not rods: - warnings.warn('Close random pack converged before reaching true ' - 'sphere radius; some spheres may overlap. Try ' - 'reducing contraction rate or packing fraction.') - break - - while True: - d, i, j = pop_rod() - if not d: - break - outer_diameter = reduce_outer_diameter() - domain.repel_spheres(spheres[i], spheres[j], d, outer_diameter) - update_mesh(i) - update_mesh(j) - update_rod_list(i) - update_rod_list(j) - if not rods: - break - inner_diameter = rods[0][0] - if inner_diameter >= diameter or inner_diameter >= outer_diameter: - break - - -def pack_spheres(radius, region, pf=None, num_spheres=None, initial_pf=0.3, - contraction_rate=1.e-3, seed=1): - """Generate a random, non-overlapping configuration of spheres within a - container. - - Parameters - ---------- - radius : float - Outer radius of spheres. - region : openmc.Region - Container in which the spheres are packed. Supported shapes are - rectangular prism, cylinder, sphere, and spherical shell. - pf : float - Packing fraction of the spheres. One of 'pf' and 'num_spheres' must - be specified; the other will be calculated. If both are specified, 'pf' - takes precedence over 'num_spheres'. - num_spheres : int - Number of spheres to pack in the domain. One of 'num_spheres' and 'pf' - must be specified; the other will be calculated. - initial_pf : float, optional - Packing fraction used to initialize the configuration of spheres in - the domain. Default value is 0.3. It is not recommended to set the - initial packing fraction much higher than 0.3 as the random sequential - packing algorithm becomes prohibitively slow as it approaches its limit - (~0.38). - contraction_rate : float, optional - Contraction rate of the outer diameter. Higher packing fractions can be - reached using a smaller contraction rate, but the algorithm will take - longer to converge. - seed : int, optional - RNG seed. - - Returns - ------ - numpy.ndarray - Cartesian coordinates of sphere centers. - - Notes - ----- - The sphere configuration is generated using a combination of random - sequential packing (RSP) and close random packing (CRP). RSP performs - better than CRP for lower packing fractions (pf), but it becomes - prohibitively slow as it approaches its packing limit (~0.38). CRP can - achieve higher pf of up to ~0.64 and scales better with increasing pf. - - If the desired pf is below some threshold for which RSP will be faster than - CRP ('initial_packing_fraction'), only RSP is used. If a higher pf is - required, spheres with a radius smaller than the desired final radius - (and therefore with a smaller pf) are initialized within the domain using - RSP. This initial configuration of spheres is then used as a starting - point for CRP using Jodrey and Tory's algorithm [1]_. - - In RSP, sphere centers are placed one by one at random, and placement - attempts for a sphere are made until the sphere is not overlapping any - others. This implementation of the algorithm uses a mesh over the domain - to speed up the nearest neighbor search by only searching for a sphere's - neighbors within that mesh cell. - - In CRP, each sphere is assigned two diameters, an inner and an outer, - which approach each other during the simulation. The inner diameter, - defined as the minimum center-to-center distance, is the true diameter of - the spheres and defines the pf. At each iteration the worst overlap - between spheres based on outer diameter is eliminated by moving the - spheres apart along the line joining their centers. Iterations continue - until the two diameters converge or until the desired pf is reached. - - References - ---------- - .. [1] W. S. Jodrey and E. M. Tory, "Computer simulation of close random - packing of equal spheres", Phys. Rev. A 32 (1985) 2347-2351. - - """ - # Seed RNG - random.seed(seed) - - # Create container with the correct shape based on the supplied region - domain = None - for cls in _Container.__subclasses__(): - try: - domain = cls.from_region(region, radius) - except ValueError: - pass - - if not domain: - raise ValueError('Could not map region {} to a container: supported ' - 'container shapes are rectangular prism, cylinder, ' - 'sphere, and spherical shell.'.format(region)) - - # Determine the packing fraction/number of spheres - volume = 4/3*pi*radius**3 - if pf is None and num_spheres is None: - raise ValueError('`pf` or `num_spheres` must be specified.') - elif pf is None: - num_spheres = int(num_spheres) - pf = volume*num_spheres/domain.volume - else: - pf = float(pf) - num_spheres = int(pf*domain.volume//volume) - - # Make sure initial packing fraction is less than packing fraction - if initial_pf > pf: - initial_pf = pf - - # Check packing fraction for close random packing - if pf > MAX_PF_CRP: - raise ValueError('Packing fraction {0} is greater than the limit for ' - 'close random packing, {1}'.format(pf, MAX_PF_CRP)) - - # Check packing fraction for random sequential packing - if initial_pf > MAX_PF_RSP: - raise ValueError('Initial packing fraction {0} is greater than the ' - 'limit for random sequential packing, ' - '{1}'.format(initial_pf, MAX_PF_RSP)) - - # Calculate the sphere radius used in the initial random sequential - # packing from the initial packing fraction - initial_radius = (3/4*initial_pf*domain.volume/(pi*num_spheres))**(1/3) - domain.sphere_radius = initial_radius - - # Recalculate the limits for the initial random sequential packing using - # the desired final sphere radius to ensure spheres are fully contained - # within the domain during the close random pack - domain.limits = [[x - initial_radius + radius for x in domain.limits[0]], - [x + initial_radius - radius for x in domain.limits[1]]] - - # Generate non-overlapping spheres for an initial inner radius using - # random sequential packing algorithm - spheres = _random_sequential_pack(domain, num_spheres) - - # Use the sphere configuration produced in random sequential packing as a - # starting point for close random pack with the desired final sphere - # radius - if initial_pf != pf: - domain.sphere_radius = radius - _close_random_pack(domain, spheres, contraction_rate) - - return spheres diff --git a/openmc/nuclide.py b/openmc/nuclide.py deleted file mode 100644 index f7c725040..000000000 --- a/openmc/nuclide.py +++ /dev/null @@ -1,39 +0,0 @@ -import warnings - -import openmc.checkvalue as cv - - -class Nuclide(str): - """A nuclide that can be used in a material. - - Parameters - ---------- - name : str - Name of the nuclide, e.g. 'U235' - - Attributes - ---------- - name : str - Name of the nuclide, e.g. 'U235' - - """ - - def __new__(cls, name): - # Initialize class attributes - orig_name = name - - if '-' in name: - name = name.replace('-', '') - name = name.replace('Nat', '0') - if name.endswith('m'): - name = name[:-1] + '_m1' - - msg = 'OpenMC nuclides follow the GND naming convention. Nuclide ' \ - '"{}" is being renamed as "{}".'.format(orig_name, name) - warnings.warn(msg) - - return super().__new__(cls, name) - - @property - def name(self): - return self diff --git a/openmc/openmoc_compatible.py b/openmc/openmoc_compatible.py deleted file mode 100644 index d18070740c..000000000 --- a/openmc/openmoc_compatible.py +++ /dev/null @@ -1,825 +0,0 @@ -import copy -import operator - -import numpy as np - -import openmoc -import openmc -import openmc.checkvalue as cv - - -# A dictionary of all OpenMC Materials created -# Keys - Material IDs -# Values - Materials -OPENMC_MATERIALS = {} - -# A dictionary of all OpenMOC Materials created -# Keys - Material IDs -# Values - Materials -OPENMOC_MATERIALS = {} - -# A dictionary of all OpenMC Surfaces created -# Keys - Surface IDs -# Values - Surfaces -OPENMC_SURFACES = {} - -# A dictionary of all OpenMOC Surfaces created -# Keys - Surface IDs -# Values - Surfaces -OPENMOC_SURFACES = {} - -# A dictionary of all OpenMC Cells created -# Keys - Cell IDs -# Values - Cells -OPENMC_CELLS = {} - -# A dictionary of all OpenMOC Cells created -# Keys - Cell IDs -# Values - Cells -OPENMOC_CELLS = {} - -# A dictionary of all OpenMC Universes created -# Keys - Universes IDs -# Values - Universes -OPENMC_UNIVERSES = {} - -# A dictionary of all OpenMOC Universes created -# Keys - Universes IDs -# Values - Universes -OPENMOC_UNIVERSES = {} - -# A dictionary of all OpenMC Lattices created -# Keys - Lattice IDs -# Values - Lattices -OPENMC_LATTICES = {} - -# A dictionary of all OpenMOC Lattices created -# Keys - Lattice IDs -# Values - Lattices -OPENMOC_LATTICES = {} - - -def get_openmoc_material(openmc_material): - """Return an OpenMOC material corresponding to an OpenMC material. - - Parameters - ---------- - openmc_material : openmc.Material - OpenMC material - - Returns - ------- - openmoc_material : openmoc.Material - Equivalent OpenMOC material - - """ - - cv.check_type('openmc_material', openmc_material, openmc.Material) - - material_id = openmc_material.id - - # If this Material was already created, use it - if material_id in OPENMOC_MATERIALS: - return OPENMOC_MATERIALS[material_id] - - # Create an OpenMOC Material to represent this OpenMC Material - name = str(openmc_material.name) - openmoc_material = openmoc.Material(id=material_id, name=name) - - # Add the OpenMC Material to the global collection of all OpenMC Materials - OPENMC_MATERIALS[material_id] = openmc_material - - # Add the OpenMOC Material to the global collection of all OpenMOC Materials - OPENMOC_MATERIALS[material_id] = openmoc_material - - return openmoc_material - - -def get_openmc_material(openmoc_material): - """Return an OpenMC material corresponding to an OpenMOC material. - - Parameters - ---------- - openmoc_material : openmoc.Material - OpenMOC material - - Returns - ------- - openmc_material : openmc.Material - Equivalent OpenMC material - - """ - - cv.check_type('openmoc_material', openmoc_material, openmoc.Material) - - material_id = openmoc_material.getId() - - # If this Material was already created, use it - if material_id in OPENMC_MATERIALS: - return OPENMC_MATERIALS[material_id] - - # Create an OpenMC Material to represent this OpenMOC Material - name = openmoc_material.getName() - openmc_material = openmc.Material(material_id=material_id, name=name) - - # Add the OpenMOC Material to the global collection of all OpenMOC Materials - OPENMOC_MATERIALS[material_id] = openmoc_material - - # Add the OpenMC Material to the global collection of all OpenMC Materials - OPENMC_MATERIALS[material_id] = openmc_material - - return openmc_material - - -def get_openmoc_surface(openmc_surface): - """Return an OpenMOC surface corresponding to an OpenMC surface. - - Parameters - ---------- - openmc_surface : openmc.Surface - OpenMC surface - - Returns - ------- - openmoc_surface : openmoc.Surface - Equivalent OpenMOC surface - - """ - - cv.check_type('openmc_surface', openmc_surface, openmc.Surface) - - surface_id = openmc_surface.id - - # If this Material was already created, use it - if surface_id in OPENMOC_SURFACES: - return OPENMOC_SURFACES[surface_id] - - # Create an OpenMOC Surface to represent this OpenMC Surface - name = openmc_surface.name - - # Determine the type of boundary conditions applied to the Surface - if openmc_surface.boundary_type == 'vacuum': - boundary = openmoc.VACUUM - elif openmc_surface.boundary_type == 'reflective': - boundary = openmoc.REFLECTIVE - elif openmc_surface.boundary_type == 'periodic': - boundary = openmoc.PERIODIC - else: - boundary = openmoc.BOUNDARY_NONE - - if openmc_surface.type == 'plane': - A = openmc_surface.a - B = openmc_surface.b - C = openmc_surface.c - D = openmc_surface.d - - # OpenMOC uses the opposite sign on D - openmoc_surface = openmoc.Plane(A, B, C, -D, surface_id, name) - - elif openmc_surface.type == 'x-plane': - x0 = openmc_surface.x0 - openmoc_surface = openmoc.XPlane(x0, surface_id, name) - - elif openmc_surface.type == 'y-plane': - y0 = openmc_surface.y0 - openmoc_surface = openmoc.YPlane(y0, surface_id, name) - - elif openmc_surface.type == 'z-plane': - z0 = openmc_surface.z0 - openmoc_surface = openmoc.ZPlane(z0, surface_id, name) - - elif openmc_surface.type == 'z-cylinder': - x0 = openmc_surface.x0 - y0 = openmc_surface.y0 - R = openmc_surface.r - openmoc_surface = openmoc.ZCylinder(x0, y0, R, surface_id, name) - - else: - msg = 'Unable to create an OpenMOC Surface from an OpenMC ' \ - 'Surface of type "{}" since it is not a compatible ' \ - 'Surface type in OpenMOC'.format(type(openmc_surface)) - raise ValueError(msg) - - # Set the boundary condition for this Surface - openmoc_surface.setBoundaryType(boundary) - - # Add the OpenMC Surface to the global collection of all OpenMC Surfaces - OPENMC_SURFACES[surface_id] = openmc_surface - - # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces - OPENMOC_SURFACES[surface_id] = openmoc_surface - - return openmoc_surface - - -def get_openmc_surface(openmoc_surface): - """Return an OpenMC surface corresponding to an OpenMOC surface. - - Parameters - ---------- - openmoc_surface : openmoc.Surface - OpenMOC surface - - Returns - ------- - openmc_surface : openmc.Surface - Equivalent OpenMC surface - - """ - - cv.check_type('openmoc_surface', openmoc_surface, openmoc.Surface) - - surface_id = openmoc_surface.getId() - - # If this Surface was already created, use it - if surface_id in OPENMC_SURFACES: - return OPENMC_SURFACES[surface_id] - - # Create an OpenMC Surface to represent this OpenMOC Surface - name = openmoc_surface.getName() - - # Correct for OpenMC's syntax for Surfaces dividing Cells - boundary = openmoc_surface.getBoundaryType() - if boundary == openmoc.VACUUM: - boundary = 'vacuum' - elif boundary == openmoc.REFLECTIVE: - boundary = 'reflective' - elif boundary == openmoc.PERIODIC: - boundary = 'periodic' - else: - boundary = 'transmission' - - if openmoc_surface.getSurfaceType() == openmoc.PLANE: - openmoc_surface = openmoc.castSurfaceToPlane(openmoc_surface) - A = openmoc_surface.getA() - B = openmoc_surface.getB() - C = openmoc_surface.getC() - D = openmoc_surface.getD() - - # OpenMOC uses the opposite sign on D - openmc_surface = openmc.Plane(surface_id, boundary, A, B, C, -D, name) - - elif openmoc_surface.getSurfaceType() == openmoc.XPLANE: - openmoc_surface = openmoc.castSurfaceToXPlane(openmoc_surface) - x0 = openmoc_surface.getX() - openmc_surface = openmc.XPlane(surface_id, boundary, x0, name) - - elif openmoc_surface.getSurfaceType() == openmoc.YPLANE: - openmoc_surface = openmoc.castSurfaceToYPlane(openmoc_surface) - y0 = openmoc_surface.getY() - openmc_surface = openmc.YPlane(surface_id, boundary, y0, name) - - elif openmoc_surface.getSurfaceType() == openmoc.ZPLANE: - openmoc_surface = openmoc.castSurfaceToZPlane(openmoc_surface) - z0 = openmoc_surface.getZ() - openmc_surface = openmc.ZPlane(surface_id, boundary, z0, name) - - elif openmoc_surface.getSurfaceType() == openmoc.ZCYLINDER: - openmoc_surface = openmoc.castSurfaceToZCylinder(openmoc_surface) - x0 = openmoc_surface.getX0() - y0 = openmoc_surface.getY0() - R = openmoc_surface.getRadius() - openmc_surface = openmc.ZCylinder(surface_id, boundary, x0, y0, R, name) - - # Add the OpenMC Surface to the global collection of all OpenMC Surfaces - OPENMC_SURFACES[surface_id] = openmc_surface - - # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces - OPENMOC_SURFACES[surface_id] = openmoc_surface - - return openmc_surface - - -def get_openmoc_cell(openmc_cell): - """Return an OpenMOC cell corresponding to an OpenMC cell. - - Parameters - ---------- - openmc_cell : openmc.Cell - OpenMC cell - - Returns - ------- - openmoc_cell : openmoc.Cell - Equivalent OpenMOC cell - - """ - - cv.check_type('openmc_cell', openmc_cell, openmc.Cell) - - cell_id = openmc_cell.id - - # If this Cell was already created, use it - if cell_id in OPENMOC_CELLS: - return OPENMOC_CELLS[cell_id] - - # Create an OpenMOC Cell to represent this OpenMC Cell - name = openmc_cell.name - openmoc_cell = openmoc.Cell(cell_id, name) - - fill = openmc_cell.fill - - if openmc_cell.fill_type == 'material': - openmoc_cell.setFill(get_openmoc_material(fill)) - elif openmc_cell.fill_type == 'universe': - openmoc_cell.setFill(get_openmoc_universe(fill)) - else: - openmoc_cell.setFill(get_openmoc_lattice(fill)) - - if openmc_cell.rotation is not None: - rotation = np.asarray(openmc_cell.rotation, dtype=np.float64) - openmoc_cell.setRotation(rotation) - if openmc_cell.translation is not None: - translation = np.asarray(openmc_cell.translation, dtype=np.float64) - openmoc_cell.setTranslation(translation) - - # Convert OpenMC's cell region to an equivalent OpenMOC region - if openmc_cell.region is not None: - openmoc_cell.setRegion(get_openmoc_region(openmc_cell.region)) - - # Add the OpenMC Cell to the global collection of all OpenMC Cells - OPENMC_CELLS[cell_id] = openmc_cell - - # Add the OpenMOC Cell to the global collection of all OpenMOC Cells - OPENMOC_CELLS[cell_id] = openmoc_cell - - return openmoc_cell - - -def get_openmoc_region(openmc_region): - """Return an OpenMOC region corresponding to an OpenMC region. - - Parameters - ---------- - openmc_region : openmc.Region - OpenMC region - - Returns - ------- - openmoc_region : openmoc.Region - Equivalent OpenMOC region - - """ - - cv.check_type('openmc_region', openmc_region, openmc.Region) - - # Recursively instantiate a region of the appropriate type - if isinstance(openmc_region, openmc.Halfspace): - surface = openmc_region.surface - halfspace = -1 if openmc_region.side == '-' else 1 - openmoc_region = \ - openmoc.Halfspace(halfspace, get_openmoc_surface(surface)) - elif isinstance(openmc_region, openmc.Intersection): - openmoc_region = openmoc.Intersection() - for openmc_node in openmc_region: - openmoc_region.addNode(get_openmoc_region(openmc_node)) - elif isinstance(openmc_region, openmc.Union): - openmoc_region = openmoc.Union() - for openmc_node in openmc_region: - openmoc_region.addNode(get_openmoc_region(openmc_node)) - elif isinstance(openmc_region, openmc.Complement): - openmoc_region = openmoc.Complement() - openmoc_region.addNode(get_openmoc_region(openmc_region.node)) - - return openmoc_region - - -def get_openmc_region(openmoc_region): - """Return an OpenMC region corresponding to an OpenMOC region. - - Parameters - ---------- - openmoc_region : openmoc.Region - OpenMOC region - - Returns - ------- - openmc_region : openmc.Region - Equivalent OpenMC region - - """ - - cv.check_type('openmoc_region', openmoc_region, openmoc.Region) - - # Recursively instantiate a region of the appropriate type - if openmoc_region.getRegionType() == openmoc.HALFSPACE: - openmoc_region = openmoc.castRegionToHalfspace(openmoc_region) - surface = get_openmc_surface(openmoc_region.getSurface()) - side = '-' if openmoc_region.getHalfspace() == -1 else '+' - openmc_region = openmc.Halfspace(surface, side) - elif openmoc_region.getRegionType() == openmoc.INTERSECTION: - openmc_region = openmc.Intersection() - for openmoc_node in openmoc_region.getNodes(): - openmc_node = get_openmc_region(openmoc_node) - openmc_region.append(openmc_node) - elif openmoc_region.getRegionType() == openmoc.UNION: - openmc_region = openmc.Union() - for openmoc_node in openmoc_region.getNodes(): - openmc_node = get_openmc_region(openmoc_node) - openmc_region.append(openmc_node) - elif openmoc_region.getRegionType() == openmoc.COMPLEMENT: - openmoc_nodes = openmoc_region.getNodes() - openmc_node = get_openmc_region(openmoc_nodes[0]) - openmc_region = openmc.Complement(openmc_node) - - return openmc_region - - -def get_openmc_cell(openmoc_cell): - """Return an OpenMC cell corresponding to an OpenMOC cell. - - Parameters - ---------- - openmoc_cell : openmoc.Cell - OpenMOC cell - - Returns - ------- - openmc_cell : openmc.Cell - Equivalent OpenMC cell - - """ - - cv.check_type('openmoc_cell', openmoc_cell, openmoc.Cell) - - cell_id = openmoc_cell.getId() - - # If this Cell was already created, use it - if cell_id in OPENMC_CELLS: - return OPENMC_CELLS[cell_id] - - # Create an OpenMOC Cell to represent this OpenMC Cell - name = openmoc_cell.getName() - openmc_cell = openmc.Cell(cell_id, name) - - if (openmoc_cell.getType() == openmoc.MATERIAL): - fill = openmoc_cell.getFillMaterial() - openmc_cell.fill = get_openmc_material(fill) - elif (openmoc_cell.getType() == openmoc.FILL): - fill = openmoc_cell.getFillUniverse() - if fill.getType() == openmoc.LATTICE: - fill = openmoc.castUniverseToLattice(fill) - openmc_cell.fill = get_openmc_lattice(fill) - else: - openmc_cell.fill = get_openmc_universe(fill) - - if openmoc_cell.isRotated(): - rotation = openmoc_cell.retrieveRotation(3) - openmc_cell.rotation = rotation - if openmoc_cell.isTranslated(): - translation = openmoc_cell.retrieveTranslation(3) - openmc_cell.translation = translation - - # Convert OpenMC's cell region to an equivalent OpenMOC region - openmoc_region = openmoc_cell.getRegion() - if openmoc_region is not None: - openmc_cell.region = get_openmc_region(openmoc_region) - - # Add the OpenMC Cell to the global collection of all OpenMC Cells - OPENMC_CELLS[cell_id] = openmc_cell - - # Add the OpenMOC Cell to the global collection of all OpenMOC Cells - OPENMOC_CELLS[cell_id] = openmoc_cell - - return openmc_cell - - -def get_openmoc_universe(openmc_universe): - """Return an OpenMOC universe corresponding to an OpenMC universe. - - Parameters - ---------- - openmc_universe : openmc.Universe - OpenMC universe - - Returns - ------- - openmoc_universe : openmoc.Universe - Equivalent OpenMOC universe - - """ - - cv.check_type('openmc_universe', openmc_universe, openmc.Universe) - - universe_id = openmc_universe.id - - # If this Universe was already created, use it - if universe_id in OPENMOC_UNIVERSES: - return OPENMOC_UNIVERSES[universe_id] - - # Create an OpenMOC Universe to represent this OpenMC Universe - name = openmc_universe.name - openmoc_universe = openmoc.Universe(universe_id, name) - - # Convert all OpenMC Cells in this Universe to OpenMOC Cells - openmc_cells = openmc_universe.cells - - for openmc_cell in openmc_cells.values(): - openmoc_cell = get_openmoc_cell(openmc_cell) - openmoc_universe.addCell(openmoc_cell) - - # Add the OpenMC Universe to the global collection of all OpenMC Universes - OPENMC_UNIVERSES[universe_id] = openmc_universe - - # Add the OpenMOC Universe to the global collection of all OpenMOC Universes - OPENMOC_UNIVERSES[universe_id] = openmoc_universe - - return openmoc_universe - - -def get_openmc_universe(openmoc_universe): - """Return an OpenMC universe corresponding to an OpenMOC universe. - - Parameters - ---------- - openmoc_universe : openmoc.Universe - OpenMOC universe - - Returns - ------- - openmc_universe : openmc.Universe - Equivalent OpenMC universe - - """ - - cv.check_type('openmoc_universe', openmoc_universe, openmoc.Universe) - - universe_id = openmoc_universe.getId() - - # If this Universe was already created, use it - if universe_id in OPENMC_UNIVERSES: - return OPENMC_UNIVERSES[universe_id] - - # Create an OpenMC Universe to represent this OpenMOC Universe - name = openmoc_universe.getName() - openmc_universe = openmc.Universe(universe_id, name) - - # Convert all OpenMOC Cells in this Universe to OpenMC Cells - for openmoc_cell in openmoc_universe.getCells().values(): - openmc_cell = get_openmc_cell(openmoc_cell) - openmc_universe.add_cell(openmc_cell) - - # Add the OpenMC Universe to the global collection of all OpenMC Universes - OPENMC_UNIVERSES[universe_id] = openmc_universe - - # Add the OpenMOC Universe to the global collection of all OpenMOC Universes - OPENMOC_UNIVERSES[universe_id] = openmoc_universe - - return openmc_universe - - -def get_openmoc_lattice(openmc_lattice): - """Return an OpenMOC lattice corresponding to an OpenMOC lattice. - - Parameters - ---------- - openmc_lattice : openmc.RectLattice - OpenMC lattice - - Returns - ------- - openmoc_lattice : openmoc.Lattice - Equivalent OpenMOC lattice - - """ - - cv.check_type('openmc_lattice', openmc_lattice, openmc.RectLattice) - - lattice_id = openmc_lattice.id - - # If this Lattice was already created, use it - if lattice_id in OPENMOC_LATTICES: - return OPENMOC_LATTICES[lattice_id] - - # Create an OpenMOC Lattice to represent this OpenMC Lattice - name = openmc_lattice.name - dimension = openmc_lattice.shape - pitch = openmc_lattice.pitch - lower_left = openmc_lattice.lower_left - universes = openmc_lattice.universes - - # Convert 2D dimension to 3D for OpenMOC - if len(dimension) == 2: - new_dimension = np.ones(3, dtype=int) - new_dimension[:2] = dimension - dimension = new_dimension - - # Convert 2D pitch to 3D for OpenMOC - if len(pitch) == 2: - new_pitch = np.ones(3, dtype=np.float64) * np.finfo(np.float64).max - new_pitch[:2] = pitch - pitch = new_pitch - - # Convert 2D lower left to 3D for OpenMOC - if len(lower_left) == 2: - new_lower_left = np.ones(3, dtype=np.float64) - new_lower_left *= np.finfo(np.float64).min / 2. - new_lower_left[:2] = lower_left - lower_left = new_lower_left - - # Convert 2D universes array to 3D for OpenMOC - if len(universes.shape) == 2: - new_universes = universes.copy() - new_universes.shape = (1,) + universes.shape - universes = new_universes - - # Initialize an empty array for the OpenMOC nested Universes in this Lattice - universe_array = np.ndarray(tuple(dimension[::-1]), dtype=openmoc.Universe) - - # Create OpenMOC Universes for each unique nested Universe in this Lattice - unique_universes = openmc_lattice.get_unique_universes() - - for universe_id, universe in unique_universes.items(): - unique_universes[universe_id] = get_openmoc_universe(universe) - - # Build the nested Universe array - for z in range(dimension[2]): - for y in range(dimension[1]): - for x in range(dimension[0]): - universe_id = universes[z][y][x].id - universe_array[z][y][x] = unique_universes[universe_id] - - openmoc_lattice = openmoc.Lattice(lattice_id, name) - openmoc_lattice.setWidth(pitch[0], pitch[1], pitch[2]) - openmoc_lattice.setUniverses(universe_array.tolist()) - - offset = np.array(lower_left, dtype=np.float64) - \ - ((np.array(pitch, dtype=np.float64) * - np.array(dimension, dtype=np.float64))) / -2.0 - openmoc_lattice.setOffset(offset[0], offset[1], offset[2]) - - # Add the OpenMC Lattice to the global collection of all OpenMC Lattices - OPENMC_LATTICES[lattice_id] = openmc_lattice - - # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices - OPENMOC_LATTICES[lattice_id] = openmoc_lattice - - return openmoc_lattice - - -def get_openmc_lattice(openmoc_lattice): - """Return an OpenMC lattice corresponding to an OpenMOC lattice. - - Parameters - ---------- - openmoc_lattice : openmoc.Lattice - OpenMOC lattice - - Returns - ------- - openmc_lattice : openmc.RectLattice - Equivalent OpenMC lattice - - """ - - cv.check_type('openmoc_lattice', openmoc_lattice, openmoc.Lattice) - - lattice_id = openmoc_lattice.getId() - - # If this Lattice was already created, use it - if lattice_id in OPENMC_LATTICES: - return OPENMC_LATTICES[lattice_id] - - name = openmoc_lattice.getName() - dimension = [openmoc_lattice.getNumX(), - openmoc_lattice.getNumY(), - openmoc_lattice.getNumZ()] - width = [openmoc_lattice.getWidthX(), - openmoc_lattice.getWidthY(), - openmoc_lattice.getWidthZ()] - offset = openmoc_lattice.getOffset() - offset = [offset.getX(), offset.getY(), offset.getZ()] - lower_left = np.array(offset, dtype=np.float64) + \ - ((np.array(width, dtype=np.float64) * - np.array(dimension, dtype=np.float64))) / -2.0 - - # Initialize an empty array for the OpenMOC nested Universes in this Lattice - universe_array = np.ndarray(tuple(np.array(dimension)), - dtype=openmoc.Universe) - - # Create OpenMOC Universes for each unique nested Universe in this Lattice - unique_universes = openmoc_lattice.getUniqueUniverses() - - for universe_id, universe in unique_universes.items(): - unique_universes[universe_id] = get_openmc_universe(universe) - - # Build the nested Universe array - for x in range(dimension[0]): - for y in range(dimension[1]): - for z in range(dimension[2]): - universe = openmoc_lattice.getUniverse(x, y, z) - universe_id = universe.getId() - universe_array[x][y][z] = \ - unique_universes[universe_id] - - universe_array = np.swapaxes(universe_array, 0, 2) - - # Convert axially infinite 3D OpenMOC lattice to a 2D OpenMC lattice - if width[2] == np.finfo(np.float64).max: - dimension = dimension[:2] - width = width[:2] - offset = offset[:2] - lower_left = lower_left[:2] - universe_array = np.squeeze(universe_array, 2) - - openmc_lattice = openmc.RectLattice(lattice_id=lattice_id, name=name) - openmc_lattice.pitch = width - openmc_lattice.lower_left = lower_left - openmc_lattice.universes = universe_array - - # Add the OpenMC Lattice to the global collection of all OpenMC Lattices - OPENMC_LATTICES[lattice_id] = openmc_lattice - - # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices - OPENMOC_LATTICES[lattice_id] = openmoc_lattice - - return openmc_lattice - - -def get_openmoc_geometry(openmc_geometry): - """Return an OpenMC geometry corresponding to an OpenMOC geometry. - - Parameters - ---------- - openmc_geometry : openmc.Geometry - OpenMC geometry - - Returns - ------- - openmoc_geometry : openmoc.Geometry - Equivalent OpenMOC geometry - - """ - - cv.check_type('openmc_geometry', openmc_geometry, openmc.Geometry) - - # Clear dictionaries and auto-generated IDs - OPENMC_SURFACES.clear() - OPENMOC_SURFACES.clear() - OPENMC_CELLS.clear() - OPENMOC_CELLS.clear() - OPENMC_UNIVERSES.clear() - OPENMOC_UNIVERSES.clear() - OPENMC_LATTICES.clear() - OPENMOC_LATTICES.clear() - - openmc_root_universe = openmc_geometry.root_universe - openmoc_root_universe = get_openmoc_universe(openmc_root_universe) - - openmoc_geometry = openmoc.Geometry() - openmoc_geometry.setRootUniverse(openmoc_root_universe) - - # Update OpenMOC's auto-generated object IDs (e.g., Surface, Material) - # with the maximum of those created from the OpenMC objects - all_materials = openmoc_geometry.getAllMaterials() - all_surfaces = openmoc_geometry.getAllSurfaces() - all_cells = openmoc_geometry.getAllCells() - all_universes = openmoc_geometry.getAllUniverses() - - max_material_id = max(all_materials.keys()) - max_surface_id = max(all_surfaces.keys()) - max_cell_id = max(all_cells.keys()) - max_universe_id = max(all_universes.keys()) - - openmoc.maximize_material_id(max_material_id+1) - openmoc.maximize_surface_id(max_surface_id+1) - openmoc.maximize_cell_id(max_cell_id+1) - openmoc.maximize_universe_id(max_universe_id+1) - - return openmoc_geometry - - -def get_openmc_geometry(openmoc_geometry): - """Return an OpenMC geometry corresponding to an OpenMOC geometry. - - Parameters - ---------- - openmoc_geometry : openmoc.Geometry - OpenMOC geometry - - Returns - ------- - openmc_geometry : openmc.Geometry - Equivalent OpenMC geometry - - """ - - cv.check_type('openmoc_geometry', openmoc_geometry, openmoc.Geometry) - - # Clear dictionaries and auto-generated ID - OPENMC_SURFACES.clear() - OPENMOC_SURFACES.clear() - OPENMC_CELLS.clear() - OPENMOC_CELLS.clear() - OPENMC_UNIVERSES.clear() - OPENMOC_UNIVERSES.clear() - OPENMC_LATTICES.clear() - OPENMOC_LATTICES.clear() - - openmoc_root_universe = openmoc_geometry.getRootUniverse() - openmc_root_universe = get_openmc_universe(openmoc_root_universe) - - openmc_geometry = openmc.Geometry() - openmc_geometry.root_universe = openmc_root_universe - - return openmc_geometry diff --git a/openmc/particle_restart.py b/openmc/particle_restart.py deleted file mode 100644 index 68a761458..000000000 --- a/openmc/particle_restart.py +++ /dev/null @@ -1,92 +0,0 @@ -import h5py - -import openmc.checkvalue as cv - -_VERSION_PARTICLE_RESTART = 2 - -class Particle(object): - """Information used to restart a specific particle that caused a simulation to - fail. - - Parameters - ---------- - filename : str - Path to the particle restart file - - Attributes - ---------- - current_batch : int - The batch containing the particle - generations_per_batch : int - Number of generations per batch - current_generation : int - The generation containing the particle - n_particles : int - Number of particles per generation - run_mode : int - Type of simulation (criticality or fixed source) - id : long - Identifier of the particle - type : int - Particle type (1 = neutron, 2 = photon, 3 = electron, 4 = positron) - weight : float - Weight of the particle - energy : float - Energy of the particle in eV - xyz : list of float - Position of the particle - uvw : list of float - Directional cosines of the particle - - """ - - def __init__(self, filename): - self._f = h5py.File(filename, 'r') - - # Ensure filetype and version are correct - cv.check_filetype_version(self._f, 'particle restart', - _VERSION_PARTICLE_RESTART) - - @property - def current_batch(self): - return self._f['current_batch'][()] - - @property - def current_generation(self): - return self._f['current_generation'][()] - - @property - def energy(self): - return self._f['energy'][()] - - @property - def generations_per_batch(self): - return self._f['generations_per_batch'][()] - - @property - def id(self): - return self._f['id'][()] - - @property - def type(self): - return self._f['type'][()] - - @property - def n_particles(self): - return self._f['n_particles'][()] - - @property - def run_mode(self): - return self._f['run_mode'][()].decode() - - @property - def uvw(self): - return self._f['uvw'][()] - - @property - def weight(self): - return self._f['weight'][()] - - @property - def xyz(self): - return self._f['xyz'][()] diff --git a/openmc/plots.py b/openmc/plots.py deleted file mode 100644 index 10d773868..000000000 --- a/openmc/plots.py +++ /dev/null @@ -1,850 +0,0 @@ -from collections.abc import Iterable, Mapping -from numbers import Real, Integral -from pathlib import Path -import subprocess -import sys -import warnings -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc -import openmc.checkvalue as cv -from openmc._xml import clean_indentation -from openmc.mixin import IDManagerMixin - - -_BASES = ['xy', 'xz', 'yz'] - -_SVG_COLORS = { - 'aliceblue': (240, 248, 255), - 'antiquewhite': (250, 235, 215), - 'aqua': (0, 255, 255), - 'aquamarine': (127, 255, 212), - 'azure': (240, 255, 255), - 'beige': (245, 245, 220), - 'bisque': (255, 228, 196), - 'black': (0, 0, 0), - 'blanchedalmond': (255, 235, 205), - 'blue': (0, 0, 255), - 'blueviolet': (138, 43, 226), - 'brown': (165, 42, 42), - 'burlywood': (222, 184, 135), - 'cadetblue': (95, 158, 160), - 'chartreuse': (127, 255, 0), - 'chocolate': (210, 105, 30), - 'coral': (255, 127, 80), - 'cornflowerblue': (100, 149, 237), - 'cornsilk': (255, 248, 220), - 'crimson': (220, 20, 60), - 'cyan': (0, 255, 255), - 'darkblue': (0, 0, 139), - 'darkcyan': (0, 139, 139), - 'darkgoldenrod': (184, 134, 11), - 'darkgray': (169, 169, 169), - 'darkgreen': (0, 100, 0), - 'darkgrey': (169, 169, 169), - 'darkkhaki': (189, 183, 107), - 'darkmagenta': (139, 0, 139), - 'darkolivegreen': (85, 107, 47), - 'darkorange': (255, 140, 0), - 'darkorchid': (153, 50, 204), - 'darkred': (139, 0, 0), - 'darksalmon': (233, 150, 122), - 'darkseagreen': (143, 188, 143), - 'darkslateblue': (72, 61, 139), - 'darkslategray': (47, 79, 79), - 'darkslategrey': (47, 79, 79), - 'darkturquoise': (0, 206, 209), - 'darkviolet': (148, 0, 211), - 'deeppink': (255, 20, 147), - 'deepskyblue': (0, 191, 255), - 'dimgray': (105, 105, 105), - 'dimgrey': (105, 105, 105), - 'dodgerblue': (30, 144, 255), - 'firebrick': (178, 34, 34), - 'floralwhite': (255, 250, 240), - 'forestgreen': (34, 139, 34), - 'fuchsia': (255, 0, 255), - 'gainsboro': (220, 220, 220), - 'ghostwhite': (248, 248, 255), - 'gold': (255, 215, 0), - 'goldenrod': (218, 165, 32), - 'gray': (128, 128, 128), - 'green': (0, 128, 0), - 'greenyellow': (173, 255, 47), - 'grey': (128, 128, 128), - 'honeydew': (240, 255, 240), - 'hotpink': (255, 105, 180), - 'indianred': (205, 92, 92), - 'indigo': (75, 0, 130), - 'ivory': (255, 255, 240), - 'khaki': (240, 230, 140), - 'lavender': (230, 230, 250), - 'lavenderblush': (255, 240, 245), - 'lawngreen': (124, 252, 0), - 'lemonchiffon': (255, 250, 205), - 'lightblue': (173, 216, 230), - 'lightcoral': (240, 128, 128), - 'lightcyan': (224, 255, 255), - 'lightgoldenrodyellow': (250, 250, 210), - 'lightgray': (211, 211, 211), - 'lightgreen': (144, 238, 144), - 'lightgrey': (211, 211, 211), - 'lightpink': (255, 182, 193), - 'lightsalmon': (255, 160, 122), - 'lightseagreen': (32, 178, 170), - 'lightskyblue': (135, 206, 250), - 'lightslategray': (119, 136, 153), - 'lightslategrey': (119, 136, 153), - 'lightsteelblue': (176, 196, 222), - 'lightyellow': (255, 255, 224), - 'lime': (0, 255, 0), - 'limegreen': (50, 205, 50), - 'linen': (250, 240, 230), - 'magenta': (255, 0, 255), - 'maroon': (128, 0, 0), - 'mediumaquamarine': (102, 205, 170), - 'mediumblue': (0, 0, 205), - 'mediumorchid': (186, 85, 211), - 'mediumpurple': (147, 112, 219), - 'mediumseagreen': (60, 179, 113), - 'mediumslateblue': (123, 104, 238), - 'mediumspringgreen': (0, 250, 154), - 'mediumturquoise': (72, 209, 204), - 'mediumvioletred': (199, 21, 133), - 'midnightblue': (25, 25, 112), - 'mintcream': (245, 255, 250), - 'mistyrose': (255, 228, 225), - 'moccasin': (255, 228, 181), - 'navajowhite': (255, 222, 173), - 'navy': (0, 0, 128), - 'oldlace': (253, 245, 230), - 'olive': (128, 128, 0), - 'olivedrab': (107, 142, 35), - 'orange': (255, 165, 0), - 'orangered': (255, 69, 0), - 'orchid': (218, 112, 214), - 'palegoldenrod': (238, 232, 170), - 'palegreen': (152, 251, 152), - 'paleturquoise': (175, 238, 238), - 'palevioletred': (219, 112, 147), - 'papayawhip': (255, 239, 213), - 'peachpuff': (255, 218, 185), - 'peru': (205, 133, 63), - 'pink': (255, 192, 203), - 'plum': (221, 160, 221), - 'powderblue': (176, 224, 230), - 'purple': (128, 0, 128), - 'red': (255, 0, 0), - 'rosybrown': (188, 143, 143), - 'royalblue': (65, 105, 225), - 'saddlebrown': (139, 69, 19), - 'salmon': (250, 128, 114), - 'sandybrown': (244, 164, 96), - 'seagreen': (46, 139, 87), - 'seashell': (255, 245, 238), - 'sienna': (160, 82, 45), - 'silver': (192, 192, 192), - 'skyblue': (135, 206, 235), - 'slateblue': (106, 90, 205), - 'slategray': (112, 128, 144), - 'slategrey': (112, 128, 144), - 'snow': (255, 250, 250), - 'springgreen': (0, 255, 127), - 'steelblue': (70, 130, 180), - 'tan': (210, 180, 140), - 'teal': (0, 128, 128), - 'thistle': (216, 191, 216), - 'tomato': (255, 99, 71), - 'turquoise': (64, 224, 208), - 'violet': (238, 130, 238), - 'wheat': (245, 222, 179), - 'white': (255, 255, 255), - 'whitesmoke': (245, 245, 245), - 'yellow': (255, 255, 0), - 'yellowgreen': (154, 205, 50) -} - - -class Plot(IDManagerMixin): - """Definition of a finite region of space to be plotted. - - OpenMC is capable of generating two-dimensional slice plots and - three-dimensional voxel plots. Colors that are used in plots can be given as - RGB tuples, e.g. (255, 255, 255) would be white, or by a string indicating a - valid `SVG color `_. - - Parameters - ---------- - plot_id : int - Unique identifier for the plot - name : str - Name of the plot - - Attributes - ---------- - id : int - Unique identifier - name : str - Name of the plot - width : Iterable of float - Width of the plot in each basis direction - pixels : Iterable of int - Number of pixels to use in each basis direction - origin : tuple or list of ndarray - Origin (center) of the plot - filename : - Path to write the plot to - color_by : {'cell', 'material'} - Indicate whether the plot should be colored by cell or by material - type : {'slice', 'voxel'} - The type of the plot - basis : {'xy', 'xz', 'yz'} - The basis directions for the plot - background : Iterable of int or str - Color of the background - mask_components : Iterable of openmc.Cell or openmc.Material - The cells or materials to plot - mask_background : Iterable of int or str - Color to apply to all cells/materials not listed in mask_components - show_overlaps : bool - Inidicate whether or not overlapping regions are shown - overlap_color : Iterable of int or str - Color to apply to overlapping regions - colors : dict - Dictionary indicating that certain cells/materials (keys) should be - displayed with a particular color. - level : int - Universe depth to plot at - meshlines : dict - Dictionary defining type, id, linewidth and color of a mesh to be - plotted on top of a plot - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, plot_id=None, name=''): - # Initialize Plot class attributes - self.id = plot_id - self.name = name - self._width = [4.0, 4.0] - self._pixels = [400, 400] - self._origin = [0., 0., 0.] - self._filename = None - self._color_by = 'cell' - self._type = 'slice' - self._basis = 'xy' - self._background = None - self._mask_components = None - self._mask_background = None - self._show_overlaps = False - self._overlap_color = None - self._colors = {} - self._level = None - self._meshlines = None - - @property - def name(self): - return self._name - - @property - def width(self): - return self._width - - @property - def pixels(self): - return self._pixels - - @property - def origin(self): - return self._origin - - @property - def filename(self): - return self._filename - - @property - def color_by(self): - return self._color_by - - @property - def type(self): - return self._type - - @property - def basis(self): - return self._basis - - @property - def background(self): - return self._background - - @property - def mask_components(self): - return self._mask_components - - @property - def mask_background(self): - return self._mask_background - - @property - def show_overlaps(self): - return self._show_overlaps - - @property - def overlap_color(self): - return self._overlap_color - - @property - def colors(self): - return self._colors - - @property - def level(self): - return self._level - - @property - def meshlines(self): - return self._meshlines - - @name.setter - def name(self, name): - cv.check_type('plot name', name, str) - self._name = name - - @width.setter - def width(self, width): - cv.check_type('plot width', width, Iterable, Real) - cv.check_length('plot width', width, 2, 3) - self._width = width - - @origin.setter - def origin(self, origin): - cv.check_type('plot origin', origin, Iterable, Real) - cv.check_length('plot origin', origin, 3) - self._origin = origin - - @pixels.setter - def pixels(self, pixels): - cv.check_type('plot pixels', pixels, Iterable, Integral) - cv.check_length('plot pixels', pixels, 2, 3) - for dim in pixels: - cv.check_greater_than('plot pixels', dim, 0) - self._pixels = pixels - - @filename.setter - def filename(self, filename): - cv.check_type('filename', filename, str) - self._filename = filename - - @color_by.setter - def color_by(self, color_by): - cv.check_value('plot color_by', color_by, ['cell', 'material']) - self._color_by = color_by - - @type.setter - def type(self, plottype): - cv.check_value('plot type', plottype, ['slice', 'voxel']) - self._type = plottype - - @basis.setter - def basis(self, basis): - cv.check_value('plot basis', basis, _BASES) - self._basis = basis - - @background.setter - def background(self, background): - self._check_color('plot background', background) - self._background = background - - @colors.setter - def colors(self, colors): - cv.check_type('plot colors', colors, Mapping) - for key, value in colors.items(): - cv.check_type('plot color key', key, (openmc.Cell, openmc.Material)) - self._check_color('plot color value', value) - self._colors = colors - - @mask_components.setter - def mask_components(self, mask_components): - cv.check_type('plot mask components', mask_components, Iterable, - (openmc.Cell, openmc.Material)) - self._mask_components = mask_components - - @mask_background.setter - def mask_background(self, mask_background): - self._check_color('plot mask background', mask_background) - self._mask_background = mask_background - - @show_overlaps.setter - def show_overlaps(self, show_overlaps): - cv.check_type('Show overlaps flag for Plot ID="{}"'.format(self.id), - show_overlaps, bool) - self._show_overlaps = show_overlaps - - @overlap_color.setter - def overlap_color(self, overlap_color): - self._check_color('plot overlap color', overlap_color) - self._overlap_color = overlap_color - - @level.setter - def level(self, plot_level): - cv.check_type('plot level', plot_level, Integral) - cv.check_greater_than('plot level', plot_level, 0, equality=True) - self._level = plot_level - - @meshlines.setter - def meshlines(self, meshlines): - cv.check_type('plot meshlines', meshlines, dict) - if 'type' not in meshlines: - msg = 'Unable to set on plot the meshlines "{0}" which ' \ - 'does not have a "type" key'.format(meshlines) - raise ValueError(msg) - - elif meshlines['type'] not in ['tally', 'entropy', 'ufs', 'cmfd']: - msg = 'Unable to set the meshlines with ' \ - 'type "{0}"'.format(meshlines['type']) - raise ValueError(msg) - - if 'id' in meshlines: - cv.check_type('plot meshlines id', meshlines['id'], Integral) - cv.check_greater_than('plot meshlines id', meshlines['id'], 0, - equality=True) - - if 'linewidth' in meshlines: - cv.check_type('plot mesh linewidth', meshlines['linewidth'], Integral) - cv.check_greater_than('plot mesh linewidth', meshlines['linewidth'], - 0, equality=True) - - if 'color' in meshlines: - self._check_color('plot meshlines color', meshlines['color']) - - self._meshlines = meshlines - - @staticmethod - def _check_color(err_string, color): - cv.check_type(err_string, color, Iterable) - if isinstance(color, str): - if color.lower() not in _SVG_COLORS: - raise ValueError("'{}' is not a valid color.".format(color)) - else: - cv.check_length(err_string, color, 3) - for rgb in color: - cv.check_type(err_string, rgb, Real) - cv.check_greater_than('RGB component', rgb, 0, True) - cv.check_less_than('RGB component', rgb, 256) - - def __repr__(self): - string = 'Plot\n' - string += '{: <16}=\t{}\n'.format('\tID', self._id) - string += '{: <16}=\t{}\n'.format('\tName', self._name) - string += '{: <16}=\t{}\n'.format('\tFilename', self._filename) - string += '{: <16}=\t{}\n'.format('\tType', self._type) - string += '{: <16}=\t{}\n'.format('\tBasis', self._basis) - string += '{: <16}=\t{}\n'.format('\tWidth', self._width) - string += '{: <16}=\t{}\n'.format('\tOrigin', self._origin) - string += '{: <16}=\t{}\n'.format('\tPixels', self._pixels) - string += '{: <16}=\t{}\n'.format('\tColor by', self._color_by) - string += '{: <16}=\t{}\n'.format('\tBackground', self._background) - string += '{: <16}=\t{}\n'.format('\tMask components', - self._mask_components) - string += '{: <16}=\t{}\n'.format('\tMask background', - self._mask_background) - string += '{: <16}=\t{}\n'.format('\Overlap Color', - self._overlap_color) - string += '{: <16}=\t{}\n'.format('\tColors', self._colors) - string += '{: <16}=\t{}\n'.format('\tLevel', self._level) - string += '{: <16}=\t{}\n'.format('\tMeshlines', self._meshlines) - return string - - @classmethod - def from_geometry(cls, geometry, basis='xy', slice_coord=0.): - """Return plot that encompasses a geometry. - - Parameters - ---------- - geometry : openmc.Geometry - The geometry the base the plot off of - basis : {'xy', 'xz', 'yz'} - The basis directions for the plot - slice_coord : float - The level at which the slice plot should be plotted. For example, if - the basis is 'xy', this would indicate the z value used in the - origin. - - """ - cv.check_type('geometry', geometry, openmc.Geometry) - cv.check_value('basis', basis, _BASES) - - # Decide which axes to keep - if basis == 'xy': - pick_index = (0, 1) - slice_index = 2 - elif basis == 'yz': - pick_index = (1, 2) - slice_index = 0 - elif basis == 'xz': - pick_index = (0, 2) - slice_index = 1 - - # Get lower-left and upper-right coordinates for desired axes - lower_left, upper_right = geometry.bounding_box - lower_left = lower_left[np.array(pick_index)] - upper_right = upper_right[np.array(pick_index)] - - if np.any(np.isinf((lower_left, upper_right))): - raise ValueError('The geometry does not appear to be bounded ' - 'in the {} plane.'.format(basis)) - - plot = cls() - plot.origin = np.insert((lower_left + upper_right)/2, - slice_index, slice_coord) - plot.width = upper_right - lower_left - return plot - - def colorize(self, geometry, seed=1): - """Generate a color scheme for each domain in the plot. - - This routine may be used to generate random, reproducible color schemes. - The colors generated are based upon cell/material IDs in the geometry. - - Parameters - ---------- - geometry : openmc.Geometry - The geometry for which the plot is defined - seed : Integral - The random number seed used to generate the color scheme - - """ - - cv.check_type('geometry', geometry, openmc.Geometry) - cv.check_type('seed', seed, Integral) - cv.check_greater_than('seed', seed, 1, equality=True) - - # Get collections of the domains which will be plotted - if self.color_by == 'material': - domains = geometry.get_all_materials().values() - else: - domains = geometry.get_all_cells().values() - - # Set the seed for the random number generator - np.random.seed(seed) - - # Generate random colors for each feature - for domain in domains: - self.colors[domain] = np.random.randint(0, 256, (3,)) - - def highlight_domains(self, geometry, domains, seed=1, - alpha=0.5, background='gray'): - """Use alpha compositing to highlight one or more domains in the plot. - - This routine generates a color scheme and applies alpha compositing to - make all domains except the highlighted ones appear partially - transparent. - - Parameters - ---------- - geometry : openmc.Geometry - The geometry for which the plot is defined - domains : Iterable of openmc.Cell or openmc.Material - A collection of the domain IDs to highlight in the plot - seed : int - The random number seed used to generate the color scheme - alpha : float - The value between 0 and 1 to apply in alpha compisiting - background : 3-tuple of int or str - The background color to apply in alpha compisiting - - """ - - cv.check_type('domains', domains, Iterable, - (openmc.Cell, openmc.Material)) - cv.check_type('alpha', alpha, Real) - cv.check_greater_than('alpha', alpha, 0., equality=True) - cv.check_less_than('alpha', alpha, 1., equality=True) - cv.check_type('background', background, Iterable) - - # Get a background (R,G,B) tuple to apply in alpha compositing - if isinstance(background, str): - if background.lower() not in _SVG_COLORS: - raise ValueError("'{}' is not a valid color.".format(background)) - background = _SVG_COLORS[background.lower()] - - # Generate a color scheme - self.colorize(geometry, seed) - - # Apply alpha compositing to the colors for all domains - # other than those the user wishes to highlight - for domain, color in self.colors.items(): - if domain not in domains: - if isinstance(color, str): - color = _SVG_COLORS[color.lower()] - r, g, b = color - r = int(((1-alpha) * background[0]) + (alpha * r)) - g = int(((1-alpha) * background[1]) + (alpha * g)) - b = int(((1-alpha) * background[2]) + (alpha * b)) - self._colors[domain] = (r, g, b) - - def to_xml_element(self): - """Return XML representation of the plot - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing plot data - - """ - - element = ET.Element("plot") - element.set("id", str(self._id)) - if self._filename is not None: - element.set("filename", self._filename) - element.set("color_by", self._color_by) - element.set("type", self._type) - - if self._type is 'slice': - element.set("basis", self._basis) - - subelement = ET.SubElement(element, "origin") - subelement.text = ' '.join(map(str, self._origin)) - - subelement = ET.SubElement(element, "width") - subelement.text = ' '.join(map(str, self._width)) - - subelement = ET.SubElement(element, "pixels") - subelement.text = ' '.join(map(str, self._pixels)) - - if self._background is not None: - subelement = ET.SubElement(element, "background") - color = self._background - if isinstance(color, str): - color = _SVG_COLORS[color.lower()] - subelement.text = ' '.join(str(x) for x in color) - - if self._colors: - for domain, color in sorted(self._colors.items(), - key=lambda x: x[0].id): - subelement = ET.SubElement(element, "color") - subelement.set("id", str(domain.id)) - if isinstance(color, str): - color = _SVG_COLORS[color.lower()] - subelement.set("rgb", ' '.join(str(x) for x in color)) - - if self._mask_components is not None: - subelement = ET.SubElement(element, "mask") - subelement.set("components", ' '.join( - str(d.id) for d in self._mask_components)) - color = self._mask_background - if color is not None: - if isinstance(color, str): - color = _SVG_COLORS[color.lower()] - subelement.set("background", ' '.join( - str(x) for x in color)) - - if self._show_overlaps: - subelement = ET.SubElement(element, "show_overlaps") - subelement.text = "true" - - if self._overlap_color is not None: - color = self._overlap_color - if isinstance(color, str): - color = _SVG_COLORS[color.lower()] - subelement = ET.SubElement(element, "overlap_color") - subelement.text = ' '.join(str(x) for x in color) - - - if self._level is not None: - subelement = ET.SubElement(element, "level") - subelement.text = str(self._level) - - if self._meshlines is not None: - subelement = ET.SubElement(element, "meshlines") - subelement.set("meshtype", self._meshlines['type']) - if self._meshlines['id'] is not None: - subelement.set("id", str(self._meshlines['id'])) - if self._meshlines['linewidth'] is not None: - subelement.set("linewidth", str(self._meshlines['linewidth'])) - if self._meshlines['color'] is not None: - subelement.set("color", ' '.join(map( - str, self._meshlines['color']))) - - return element - - def to_ipython_image(self, openmc_exec='openmc', cwd='.', - convert_exec='convert'): - """Render plot as an image - - This method runs OpenMC in plotting mode to produce a bitmap image which - is then converted to a .png file and loaded in as an - :class:`IPython.display.Image` object. As such, it requires that your - model geometry, materials, and settings have already been exported to - XML. - - Parameters - ---------- - openmc_exec : str - Path to OpenMC executable - cwd : str, optional - Path to working directory to run in - convert_exec : str, optional - Command that can convert PPM files into PNG files - - Returns - ------- - IPython.display.Image - Image generated - - """ - from IPython.display import Image - - # Create plots.xml - Plots([self]).export_to_xml() - - # Run OpenMC in geometry plotting mode - openmc.plot_geometry(False, openmc_exec, cwd) - - # Convert to .png - if self.filename is not None: - ppm_file = '{}.ppm'.format(self.filename) - else: - ppm_file = 'plot_{}.ppm'.format(self.id) - png_file = ppm_file.replace('.ppm', '.png') - subprocess.check_call([convert_exec, ppm_file, png_file]) - - return Image(png_file) - - -class Plots(cv.CheckedList): - """Collection of Plots used for an OpenMC simulation. - - This class corresponds directly to the plots.xml input file. It can be - thought of as a normal Python list where each member is a :class:`Plot`. It - behaves like a list as the following example demonstrates: - - >>> xz_plot = openmc.Plot() - >>> big_plot = openmc.Plot() - >>> small_plot = openmc.Plot() - >>> p = openmc.Plots((xz_plot, big_plot)) - >>> p.append(small_plot) - >>> small_plot = p.pop() - - Parameters - ---------- - plots : Iterable of openmc.Plot - Plots to add to the collection - - """ - - def __init__(self, plots=None): - super().__init__(Plot, 'plots collection') - self._plots_file = ET.Element("plots") - if plots is not None: - self += plots - - def append(self, plot): - """Append plot to collection - - Parameters - ---------- - plot : openmc.Plot - Plot to append - - """ - super().append(plot) - - def insert(self, index, plot): - """Insert plot before index - - Parameters - ---------- - index : int - Index in list - plot : openmc.Plot - Plot to insert - - """ - super().insert(index, plot) - - def colorize(self, geometry, seed=1): - """Generate a consistent color scheme for each domain in each plot. - - This routine may be used to generate random, reproducible color schemes. - The colors generated are based upon cell/material IDs in the geometry. - The color schemes will be consistent for all plots in "plots.xml". - - Parameters - ---------- - geometry : openmc.Geometry - The geometry for which the plots are defined - seed : Integral - The random number seed used to generate the color scheme - - """ - - for plot in self: - plot.colorize(geometry, seed) - - - def highlight_domains(self, geometry, domains, seed=1, - alpha=0.5, background='gray'): - """Use alpha compositing to highlight one or more domains in the plot. - - This routine generates a color scheme and applies alpha compositing to - make all domains except the highlighted ones appear partially - transparent. - - Parameters - ---------- - geometry : openmc.Geometry - The geometry for which the plot is defined - domains : Iterable of openmc.Cell or openmc.Material - A collection of the domain IDs to highlight in the plot - seed : int - The random number seed used to generate the color scheme - alpha : float - The value between 0 and 1 to apply in alpha compisiting - background : 3-tuple of int or str - The background color to apply in alpha compisiting - - """ - - for plot in self: - plot.highlight_domains(geometry, domains, seed, alpha, background) - - def _create_plot_subelements(self): - for plot in self: - xml_element = plot.to_xml_element() - - if len(plot.name) > 0: - self._plots_file.append(ET.Comment(plot.name)) - - self._plots_file.append(xml_element) - - def export_to_xml(self, path='plots.xml'): - """Export plot specifications to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'plots.xml'. - - """ - # Reset xml element tree - self._plots_file.clear() - - self._create_plot_subelements() - - # Clean the indentation in the file to be user-readable - clean_indentation(self._plots_file) - - # Check if path is a directory - p = Path(path) - if p.is_dir(): - p /= 'plots.xml' - - # Write the XML Tree to the plots.xml file - tree = ET.ElementTree(self._plots_file) - tree.write(str(p), xml_declaration=True, encoding='utf-8') diff --git a/openmc/plotter.py b/openmc/plotter.py deleted file mode 100644 index 597a87750..000000000 --- a/openmc/plotter.py +++ /dev/null @@ -1,910 +0,0 @@ -from numbers import Integral, Real -from itertools import chain -import string - -import numpy as np - -import openmc.checkvalue as cv -import openmc.data - -# Supported keywords for continuous-energy cross section plotting -PLOT_TYPES = ['total', 'scatter', 'elastic', 'inelastic', 'fission', - 'absorption', 'capture', 'nu-fission', 'nu-scatter', 'unity', - 'slowing-down power', 'damage'] - -# Supported keywoards for multi-group cross section plotting -PLOT_TYPES_MGXS = ['total', 'absorption', 'scatter', 'fission', - 'kappa-fission', 'nu-fission', 'prompt-nu-fission', - 'deleyed-nu-fission', 'chi', 'chi-prompt', 'chi-delayed', - 'inverse-velocity', 'beta', 'decay rate', 'unity'] -# Create a dictionary which can be used to convert PLOT_TYPES_MGXS to the -# openmc.XSdata attribute name needed to access the data -_PLOT_MGXS_ATTR = {line: line.replace(' ', '_').replace('-', '_') - for line in PLOT_TYPES_MGXS} -_PLOT_MGXS_ATTR['scatter'] = 'scatter_matrix' - -# Special MT values -UNITY_MT = -1 -XI_MT = -2 - -# MTs to combine to generate associated plot_types -_INELASTIC = [mt for mt in openmc.data.SUM_RULES[3] if mt != 27] -PLOT_TYPES_MT = {'total': openmc.data.SUM_RULES[1], - 'scatter': [2] + _INELASTIC, - 'elastic': [2], - 'inelastic': _INELASTIC, - 'fission': [18], - 'absorption': [27], 'capture': [101], - 'nu-fission': [18], - 'nu-scatter': [2] + _INELASTIC, - 'unity': [UNITY_MT], - 'slowing-down power': [2] + _INELASTIC + [XI_MT], - 'damage': [444]} -# Operations to use when combining MTs the first np.add is used in reference -# to zero -PLOT_TYPES_OP = {'total': (np.add,), - 'scatter': (np.add,) * (len(PLOT_TYPES_MT['scatter']) - 1), - 'elastic': (), - 'inelastic': (np.add,) * (len(PLOT_TYPES_MT['inelastic']) - 1), - 'fission': (), 'absorption': (), - 'capture': (), 'nu-fission': (), - 'nu-scatter': (np.add,) * (len(PLOT_TYPES_MT['nu-scatter']) - 1), - 'unity': (), - 'slowing-down power': - (np.add,) * (len(PLOT_TYPES_MT['slowing-down power']) - 2) + (np.multiply,), - 'damage': ()} - -# Types of plots to plot linearly in y -PLOT_TYPES_LINEAR = {'nu-fission / fission', 'nu-scatter / scatter', - 'nu-fission / absorption', 'fission / absorption'} - -# Minimum and maximum energies for plotting (units of eV) -_MIN_E = 1.e-5 -_MAX_E = 20.e6 - - -def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, - axis=None, sab_name=None, ce_cross_sections=None, - mg_cross_sections=None, enrichment=None, plot_CE=True, orders=None, - divisor_orders=None, **kwargs): - """Creates a figure of continuous-energy cross sections for this item. - - Parameters - ---------- - this : str or openmc.Material - Object to source data from - types : Iterable of values of PLOT_TYPES - The type of cross sections to include in the plot. - divisor_types : Iterable of values of PLOT_TYPES, optional - Cross section types which will divide those produced by types - before plotting. A type of 'unity' can be used to effectively not - divide some types. - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - data_type : {'nuclide', 'element', 'material', 'macroscopic'}, optional - Type of object to plot. If not specified, a guess is made based on the - `this` argument. - axis : matplotlib.axes, optional - A previously generated axis to use for plotting. If not specified, - a new axis and figure will be generated. - sab_name : str, optional - Name of S(a,b) library to apply to MT=2 data when applicable; only used - for items which are instances of openmc.Element or openmc.Nuclide - ce_cross_sections : str, optional - Location of cross_sections.xml file. Default is None. - mg_cross_sections : str, optional - Location of MGXS HDF5 Library file. Default is None. - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None. This is only used for - items which are instances of openmc.Element - plot_CE : bool, optional - Denotes whether or not continuous-energy will be plotted. Defaults to - plotting the continuous-energy data. - orders : Iterable of Integral, optional - The scattering order or delayed group index to use for the - corresponding entry in types. Defaults to the 0th order for scattering - and the total delayed neutron data. This only applies to plots of - multi-group data. - divisor_orders : Iterable of Integral, optional - Same as orders, but for divisor_types - **kwargs - All keyword arguments are passed to - :func:`matplotlib.pyplot.figure`. - - Returns - ------- - fig : matplotlib.figure.Figure - If axis is None, then a Matplotlib Figure of the generated - cross section will be returned. Otherwise, a value of - None will be returned as the figure and axes have already been - generated. - - """ - import matplotlib.pyplot as plt - - cv.check_type("plot_CE", plot_CE, bool) - - if data_type is None: - if isinstance(this, openmc.Nuclide): - data_type = 'nuclide' - elif isinstance(this, openmc.Element): - data_type = 'element' - elif isinstance(this, openmc.Material): - data_type = 'material' - elif isinstance(this, openmc.Macroscopic): - data_type = 'macroscopic' - elif isinstance(this, str): - if this[-1] in string.digits: - data_type = 'nuclide' - else: - data_type = 'element' - else: - raise TypeError("Invalid type for plotting") - - if plot_CE: - # Calculate for the CE cross sections - E, data = calculate_cexs(this, data_type, types, temperature, sab_name, - ce_cross_sections, enrichment) - if divisor_types: - cv.check_length('divisor types', divisor_types, len(types)) - Ediv, data_div = calculate_cexs(this, divisor_types, temperature, - sab_name, ce_cross_sections, - enrichment) - - # Create a new union grid, interpolate data and data_div on to that - # grid, and then do the actual division - Enum = E[:] - E = np.union1d(Enum, Ediv) - data_new = np.zeros((len(types), len(E))) - - for line in range(len(types)): - data_new[line, :] = \ - np.divide(np.interp(E, Enum, data[line, :]), - np.interp(E, Ediv, data_div[line, :])) - if divisor_types[line] != 'unity': - types[line] = types[line] + ' / ' + divisor_types[line] - data = data_new - else: - # Calculate for MG cross sections - E, data = calculate_mgxs(this, data_type, types, orders, temperature, - mg_cross_sections, ce_cross_sections, - enrichment) - - if divisor_types: - cv.check_length('divisor types', divisor_types, len(types)) - Ediv, data_div = calculate_mgxs(this, data_type, divisor_types, - divisor_orders, temperature, - mg_cross_sections, - ce_cross_sections, enrichment) - - # Perform the division - for line in range(len(types)): - data[line, :] /= data_div[line, :] - if divisor_types[line] != 'unity': - types[line] += ' / ' + divisor_types[line] - - # Generate the plot - if axis is None: - fig = plt.figure(**kwargs) - ax = fig.add_subplot(111) - else: - fig = None - ax = axis - # Set to loglog or semilogx depending on if we are plotting a data - # type which we expect to vary linearly - if set(types).issubset(PLOT_TYPES_LINEAR): - plot_func = ax.semilogx - else: - plot_func = ax.loglog - - # Plot the data - for i in range(len(data)): - data[i, :] = np.nan_to_num(data[i, :]) - if np.sum(data[i, :]) > 0.: - plot_func(E, data[i, :], label=types[i]) - - ax.set_xlabel('Energy [eV]') - if plot_CE: - ax.set_xlim(_MIN_E, _MAX_E) - else: - ax.set_xlim(E[-1], E[0]) - if divisor_types: - if data_type == 'nuclide': - ylabel = 'Nuclidic Microscopic Data' - elif data_type == 'element': - ylabel = 'Elemental Microscopic Data' - elif data_type == 'material' or data_type == 'macroscopic': - ylabel = 'Macroscopic Data' - else: - if data_type == 'nuclide': - ylabel = 'Microscopic Cross Section [b]' - elif data_type == 'element': - ylabel = 'Elemental Cross Section [b]' - elif data_type == 'material' or data_type == 'macroscopic': - ylabel = 'Macroscopic Cross Section [1/cm]' - ax.set_ylabel(ylabel) - ax.legend(loc='best') - name = this.name if data_type == 'material' else this - if len(types) > 1: - ax.set_title('Cross Sections for ' + name) - else: - ax.set_title('Cross Section for ' + name) - - return fig - - -def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, - cross_sections=None, enrichment=None): - """Calculates continuous-energy cross sections of a requested type. - - Parameters - ---------- - this : {str, openmc.Nuclide, openmc.Element, openmc.Material} - Object to source data from - data_type : {'nuclide', 'element', material'} - Type of object to plot - types : Iterable of values of PLOT_TYPES - The type of cross sections to calculate - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - sab_name : str, optional - Name of S(a,b) library to apply to MT=2 data when applicable. - cross_sections : str, optional - Location of cross_sections.xml file. Default is None. - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - - Returns - ------- - energy_grid : numpy.ndarray - Energies at which cross sections are calculated, in units of eV - data : numpy.ndarray - Cross sections calculated at the energy grid described by energy_grid - - """ - - # Check types - cv.check_type('temperature', temperature, Real) - if sab_name: - cv.check_type('sab_name', sab_name, str) - if enrichment: - cv.check_type('enrichment', enrichment, Real) - - if data_type == 'nuclide': - if isinstance(this, str): - nuc = openmc.Nuclide(this) - else: - nuc = this - energy_grid, xs = _calculate_cexs_nuclide(nuc, types, temperature, - sab_name, cross_sections) - # Convert xs (Iterable of Callable) to a grid of cross section values - # calculated on @ the points in energy_grid for consistency with the - # element and material functions. - data = np.zeros((len(types), len(energy_grid))) - for line in range(len(types)): - data[line, :] = xs[line](energy_grid) - elif data_type == 'element': - if isinstance(this, str): - elem = openmc.Element(this) - else: - elem = this - energy_grid, data = _calculate_cexs_elem_mat(elem, types, temperature, - cross_sections, sab_name, - enrichment) - elif data_type == 'material': - cv.check_type('this', this, openmc.Material) - energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, - cross_sections) - else: - raise TypeError("Invalid type") - - return energy_grid, data - - -def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, - cross_sections=None): - """Calculates continuous-energy cross sections of a requested type. - - Parameters - ---------- - this : openmc.Nuclide - Nuclide object to source data from - types : Iterable of str or Integral - The type of cross sections to calculate; values can either be those - in openmc.PLOT_TYPES or integers which correspond to reaction - channel (MT) numbers. - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - sab_name : str, optional - Name of S(a,b) library to apply to MT=2 data when applicable. - cross_sections : str, optional - Location of cross_sections.xml file. Default is None. - - Returns - ------- - energy_grid : numpy.ndarray - Energies at which cross sections are calculated, in units of eV - data : Iterable of Callable - Requested cross section functions - - """ - - # Parse the types - mts = [] - ops = [] - yields = [] - for line in types: - if line in PLOT_TYPES: - mts.append(PLOT_TYPES_MT[line]) - if line.startswith('nu'): - yields.append(True) - else: - yields.append(False) - ops.append(PLOT_TYPES_OP[line]) - else: - # Not a built-in type, we have to parse it ourselves - cv.check_type('MT in types', line, Integral) - cv.check_greater_than('MT in types', line, 0) - mts.append((line,)) - ops.append(()) - yields.append(False) - - # Load the library - library = openmc.data.DataLibrary.from_xml(cross_sections) - - # Convert temperature to format needed for access in the library - strT = "{}K".format(int(round(temperature))) - T = temperature - - # Now we can create the data sets to be plotted - energy_grid = [] - xs = [] - lib = library.get_by_material(this) - if lib is not None: - nuc = openmc.data.IncidentNeutron.from_hdf5(lib['path']) - # Obtain the nearest temperature - if strT in nuc.temperatures: - nucT = strT - else: - delta_T = np.array(nuc.kTs) - T * openmc.data.K_BOLTZMANN - closest_index = np.argmin(np.abs(delta_T)) - nucT = nuc.temperatures[closest_index] - - # Prep S(a,b) data if needed - if sab_name: - sab = openmc.data.ThermalScattering.from_hdf5(sab_name) - # Obtain the nearest temperature - if strT in sab.temperatures: - sabT = strT - else: - delta_T = np.array(sab.kTs) - T * openmc.data.K_BOLTZMANN - closest_index = np.argmin(np.abs(delta_T)) - sabT = sab.temperatures[closest_index] - - # Create an energy grid composed the S(a,b) and the nuclide's grid - grid = nuc.energy[nucT] - sab_Emax = 0. - sab_funcs = [] - if sab.elastic_xs: - elastic = sab.elastic_xs[sabT] - if isinstance(elastic, openmc.data.CoherentElastic): - grid = np.union1d(grid, elastic.bragg_edges) - if elastic.bragg_edges[-1] > sab_Emax: - sab_Emax = elastic.bragg_edges[-1] - elif isinstance(elastic, openmc.data.Tabulated1D): - grid = np.union1d(grid, elastic.x) - if elastic.x[-1] > sab_Emax: - sab_Emax = elastic.x[-1] - sab_funcs.append(elastic) - if sab.inelastic_xs: - inelastic = sab.inelastic_xs[sabT] - grid = np.union1d(grid, inelastic.x) - if inelastic.x[-1] > sab_Emax: - sab_Emax = inelastic.x[-1] - sab_funcs.append(inelastic) - energy_grid = grid - else: - energy_grid = nuc.energy[nucT] - - for i, mt_set in enumerate(mts): - # Get the reaction xs data from the nuclide - funcs = [] - op = ops[i] - for mt in mt_set: - if mt == 2: - if sab_name: - # Then we need to do a piece-wise function of - # The S(a,b) and non-thermal data - sab_sum = openmc.data.Sum(sab_funcs) - pw_funcs = openmc.data.Regions1D( - [sab_sum, nuc[mt].xs[nucT]], - [sab_Emax]) - funcs.append(pw_funcs) - else: - funcs.append(nuc[mt].xs[nucT]) - elif mt in nuc: - if yields[i]: - # Get the total yield first if available. This will be - # used primarily for fission. - for prod in chain(nuc[mt].products, - nuc[mt].derived_products): - if prod.particle == 'neutron' and \ - prod.emission_mode == 'total': - func = openmc.data.Combination( - [nuc[mt].xs[nucT], prod.yield_], - [np.multiply]) - funcs.append(func) - break - else: - # Total doesn't exist so we have to create from - # prompt and delayed. This is used for scatter - # multiplication. - func = None - for prod in chain(nuc[mt].products, - nuc[mt].derived_products): - if prod.particle == 'neutron' and \ - prod.emission_mode != 'total': - if func: - func = openmc.data.Combination( - [prod.yield_, func], [np.add]) - else: - func = prod.yield_ - if func: - funcs.append(openmc.data.Combination( - [func, nuc[mt].xs[nucT]], [np.multiply])) - else: - # If func is still None, then there were no - # products. In that case, assume the yield is - # one as its not provided for some summed - # reactions like MT=4 - funcs.append(nuc[mt].xs[nucT]) - else: - funcs.append(nuc[mt].xs[nucT]) - elif mt == UNITY_MT: - funcs.append(lambda x: 1.) - elif mt == XI_MT: - awr = nuc.atomic_weight_ratio - alpha = ((awr - 1.) / (awr + 1.))**2 - xi = 1. + alpha * np.log(alpha) / (1. - alpha) - funcs.append(lambda x: xi) - else: - funcs.append(lambda x: 0.) - xs.append(openmc.data.Combination(funcs, op)) - else: - raise ValueError(this + " not in library") - - return energy_grid, xs - - -def _calculate_cexs_elem_mat(this, types, temperature=294., - cross_sections=None, sab_name=None, - enrichment=None): - """Calculates continuous-energy cross sections of a requested type. - - Parameters - ---------- - this : openmc.Material or openmc.Element - Object to source data from - types : Iterable of values of PLOT_TYPES - The type of cross sections to calculate - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - cross_sections : str, optional - Location of cross_sections.xml file. Default is None. - sab_name : str, optional - Name of S(a,b) library to apply to MT=2 data when applicable. - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - - Returns - ------- - energy_grid : numpy.ndarray - Energies at which cross sections are calculated, in units of eV - data : numpy.ndarray - Cross sections calculated at the energy grid described by energy_grid - - """ - - if isinstance(this, openmc.Material): - if this.temperature is not None: - T = this.temperature - else: - T = temperature - else: - T = temperature - - # Load the library - library = openmc.data.DataLibrary.from_xml(cross_sections) - - if isinstance(this, openmc.Material): - # Expand elements in to nuclides with atomic densities - nuclides = this.get_nuclide_atom_densities() - # For ease of processing split out the nuclide and its fraction - nuc_fractions = {nuclide[1][0]: nuclide[1][1] - for nuclide in nuclides.items()} - # Create a dict of [nuclide name] = nuclide object to carry forward - # with a common nuclides format between openmc.Material and - # openmc.Element objects - nuclides = {nuclide[1][0]: nuclide[1][0] - for nuclide in nuclides.items()} - else: - # Expand elements in to nuclides with atomic densities - nuclides = this.expand(1., 'ao', enrichment=enrichment, - cross_sections=cross_sections) - # For ease of processing split out the nuclide and its fraction - nuc_fractions = {nuclide[0]: nuclide[1] for nuclide in nuclides} - # Create a dict of [nuclide name] = nuclide object to carry forward - # with a common nuclides format between openmc.Material and - # openmc.Element objects - nuclides = {nuclide[0]: nuclide[0] for nuclide in nuclides} - - # Identify the nuclides which have S(a,b) data - sabs = {} - for nuclide in nuclides.items(): - sabs[nuclide[0]] = None - if isinstance(this, openmc.Material): - for sab_name in this._sab: - sab = openmc.data.ThermalScattering.from_hdf5( - library.get_by_material(sab_name)['path']) - for nuc in sab.nuclides: - sabs[nuc] = library.get_by_material(sab_name)['path'] - else: - if sab_name: - sab = openmc.data.ThermalScattering.from_hdf5(sab_name) - for nuc in sab.nuclides: - sabs[nuc] = library.get_by_material(sab_name)['path'] - - # Now we can create the data sets to be plotted - xs = {} - E = [] - for nuclide in nuclides.items(): - name = nuclide[0] - nuc = nuclide[1] - sab_tab = sabs[name] - temp_E, temp_xs = calculate_cexs(nuc, 'nuclide', types, T, sab_tab, - cross_sections) - E.append(temp_E) - # Since the energy grids are different, store the cross sections as - # a tabulated function so they can be calculated on any grid needed. - xs[name] = [openmc.data.Tabulated1D(temp_E, temp_xs[line]) - for line in range(len(types))] - - # Condense the data for every nuclide - # First create a union energy grid - energy_grid = E[0] - for grid in E[1:]: - energy_grid = np.union1d(energy_grid, grid) - - # Now we can combine all the nuclidic data - data = np.zeros((len(types), len(energy_grid))) - for line in range(len(types)): - if types[line] == 'unity': - data[line, :] = 1. - else: - for nuclide in nuclides.items(): - name = nuclide[0] - data[line, :] += (nuc_fractions[name] * - xs[name][line](energy_grid)) - - return energy_grid, data - - -def calculate_mgxs(this, data_type, types, orders=None, temperature=294., - cross_sections=None, ce_cross_sections=None, - enrichment=None): - """Calculates multi-group cross sections of a requested type. - - If the data for the nuclide or macroscopic object in the library is - represented as angle-dependent data then this method will return the - geometric average cross section over all angles. - - Parameters - ---------- - this : str or openmc.Material - Object to source data from - data_type : {'nuclide', 'element', material', 'macroscopic'} - Type of object to plot - types : Iterable of values of PLOT_TYPES_MGXS - The type of cross sections to calculate - orders : Iterable of Integral, optional - The scattering order or delayed group index to use for the - corresponding entry in types. Defaults to the 0th order for scattering - and the total delayed neutron data. - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - cross_sections : str, optional - Location of MGXS HDF5 Library file. Default is None. - ce_cross_sections : str, optional - Location of continuous-energy cross_sections.xml file. Default is None. - This is used only for expanding an openmc.Element object passed as this - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - - Returns - ------- - energy_grid : numpy.ndarray - Energies at which cross sections are calculated, in units of eV - data : numpy.ndarray - Cross sections calculated at the energy grid described by energy_grid - - """ - - # Check types - cv.check_type('temperature', temperature, Real) - if enrichment: - cv.check_type('enrichment', enrichment, Real) - cv.check_iterable_type('types', types, str) - - cv.check_type("cross_sections", cross_sections, str) - library = openmc.MGXSLibrary.from_hdf5(cross_sections) - - if data_type in ('nuclide', 'macroscopic'): - mgxs = _calculate_mgxs_nuc_macro(this, types, library, orders, - temperature) - elif data_type in ('element', 'material'): - mgxs = _calculate_mgxs_elem_mat(this, types, library, orders, - temperature, ce_cross_sections, - enrichment) - else: - raise TypeError("Invalid type") - - # Convert the data to the format needed - data = np.zeros((len(types), 2 * library.energy_groups.num_groups)) - energy_grid = np.zeros(2 * library.energy_groups.num_groups) - for g in range(library.energy_groups.num_groups): - energy_grid[g * 2: g * 2 + 2] = \ - library.energy_groups.group_edges[g: g + 2] - # Ensure the energy will show on a log-axis by replacing 0s with a - # sufficiently small number - energy_grid[0] = max(energy_grid[0], _MIN_E) - - for line in range(len(types)): - for g in range(library.energy_groups.num_groups): - data[line, g * 2: g * 2 + 2] = mgxs[line, g] - - return energy_grid[::-1], data - - -def _calculate_mgxs_nuc_macro(this, types, library, orders=None, - temperature=294.): - """Determines the multi-group cross sections of a nuclide or macroscopic - object. - - If the data for the nuclide or macroscopic object in the library is - represented as angle-dependent data then this method will return the - geometric average cross section over all angles. - - Parameters - ---------- - this : openmc.Nuclide or openmc.Macroscopic - Object to source data from - types : Iterable of str - The type of cross sections to calculate; values can either be those - in openmc.PLOT_TYPES_MGXS - library : openmc.MGXSLibrary - MGXS Library containing the data of interest - orders : Iterable of Integral, optional - The scattering order or delayed group index to use for the - corresponding entry in types. Defaults to the 0th order for scattering - and the total delayed neutron data. - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - - Returns - ------- - data : numpy.ndarray - Cross sections calculated at the energy grid described by energy_grid - - """ - - # Check the parameters and grab order/delayed groups - if orders: - cv.check_iterable_type('orders', orders, Integral, - min_depth=len(types), max_depth=len(types)) - else: - orders = [None] * len(types) - for i, line in enumerate(types): - cv.check_type("line", line, str) - cv.check_value("line", line, PLOT_TYPES_MGXS) - if orders[i]: - cv.check_greater_than("order value", orders[i], 0, equality=True) - - xsdata = library.get_by_name(this) - - if xsdata is not None: - # Obtain the nearest temperature - t = np.abs(xsdata.temperatures - temperature).argmin() - - # Get the data - data = np.zeros((len(types), library.energy_groups.num_groups)) - for i, line in enumerate(types): - if 'fission' in line and not xsdata.fissionable: - continue - elif line == 'unity': - data[i, :] = 1. - else: - # Now we have to get the cross section data and properly - # treat it depending on the requested type. - # First get the data in a generic fashion - temp_data = getattr(xsdata, _PLOT_MGXS_ATTR[line])[t] - shape = temp_data.shape[:] - # If we have angular data, then want the geometric - # average over all provided angles. Since the angles are - # equi-distant, un-weighted averaging will suffice - if xsdata.representation == 'angle': - temp_data = np.mean(temp_data, axis=(0, 1)) - - # Now we can look at the shape of the data to identify how - # it should be modified to produce an array of values - # with groups. - if shape in (xsdata.xs_shapes["[G']"], - xsdata.xs_shapes["[G]"]): - # Then the data is already an array vs groups so copy - # and move along - data[i, :] = temp_data - elif shape == xsdata.xs_shapes["[G][G']"]: - # Sum the data over outgoing groups to create our array vs - # groups - data[i, :] = np.sum(temp_data, axis=1) - elif shape == xsdata.xs_shapes["[DG]"]: - # Then we have a constant vs groups with a value for each - # delayed group. The user-provided value of orders tells us - # which delayed group we want. If none are provided, then - # we sum all the delayed groups together. - if orders[i]: - if orders[i] < len(shape[0]): - data[i, :] = temp_data[orders[i]] - else: - data[i, :] = np.sum(temp_data[:]) - elif shape in (xsdata.xs_shapes["[DG][G']"], - xsdata.xs_shapes["[DG][G]"]): - # Then we have an array vs groups with values for each - # delayed group. The user-provided value of orders tells us - # which delayed group we want. If none are provided, then - # we sum all the delayed groups together. - if orders[i]: - if orders[i] < len(shape[0]): - data[i, :] = temp_data[orders[i], :] - else: - data[i, :] = np.sum(temp_data[:, :], axis=0) - elif shape == xsdata.xs_shapes["[DG][G][G']"]: - # Then we have a delayed group matrix. We will first - # remove the outgoing group dependency - temp_data = np.sum(temp_data, axis=-1) - # And then proceed in exactly the same manner as the - # "[DG][G']" or "[DG][G]" shapes in the previous block. - if orders[i]: - if orders[i] < len(shape[0]): - data[i, :] = temp_data[orders[i], :] - else: - data[i, :] = np.sum(temp_data[:, :], axis=0) - elif shape == xsdata.xs_shapes["[G][G'][Order]"]: - # This is a scattering matrix with angular data - # First remove the outgoing group dependence - temp_data = np.sum(temp_data, axis=1) - # The user either provided a specific order or we resort - # to the default 0th order - if orders[i]: - order = orders[i] - else: - order = 0 - # If the order is available, store the data for that order - # if it is not available, then the expansion coefficient - # is zero and thus we already have the correct value. - if order < shape[1]: - data[i, :] = temp_data[:, order] - else: - raise ValueError("{} not present in provided MGXS " - "library".format(this)) - - return data - - -def _calculate_mgxs_elem_mat(this, types, library, orders=None, - temperature=294., ce_cross_sections=None, - enrichment=None): - """Determines the multi-group cross sections of an element or material - object. - - If the data for the nuclide or macroscopic object in the library is - represented as angle-dependent data then this method will return the - geometric average cross section over all angles. - - Parameters - ---------- - this : openmc.Element or openmc.Material - Object to source data from - types : Iterable of str - The type of cross sections to calculate; values can either be those - in openmc.PLOT_TYPES_MGXS - library : openmc.MGXSLibrary - MGXS Library containing the data of interest - orders : Iterable of Integral, optional - The scattering order or delayed group index to use for the - corresponding entry in types. Defaults to the 0th order for scattering - and the total delayed neutron data. - temperature : float, optional - Temperature in Kelvin to plot. If not specified, a default - temperature of 294K will be plotted. Note that the nearest - temperature in the library for each nuclide will be used as opposed - to using any interpolation. - ce_cross_sections : str, optional - Location of continuous-energy cross_sections.xml file. Default is None. - This is used only for expanding the elements - enrichment : float, optional - Enrichment for U235 in weight percent. For example, input 4.95 for - 4.95 weight percent enriched U. Default is None - (natural composition). - - Returns - ------- - data : numpy.ndarray - Cross sections calculated at the energy grid described by energy_grid - - """ - - if isinstance(this, openmc.Material): - if this.temperature is not None: - T = this.temperature - else: - T = temperature - - # Check to see if we have nuclides/elements or a macrocopic object - if this._macroscopic is not None: - # We have macroscopics - nuclides = {this._macroscopic: (this._macroscopic, this.density)} - else: - # Expand elements in to nuclides with atomic densities - nuclides = this.get_nuclide_atom_densities() - - # For ease of processing split out nuc and nuc_density - nuc_fraction = [nuclide[1][1] for nuclide in nuclides.items()] - else: - T = temperature - # Expand elements in to nuclides with atomic densities - nuclides = this.expand(100., 'ao', enrichment=enrichment, - cross_sections=ce_cross_sections) - - # For ease of processing split out nuc and nuc_fractions - nuc_fraction = [nuclide[1] for nuclide in nuclides] - - nuc_data = [] - for nuclide in nuclides.items(): - nuc_data.append(_calculate_mgxs_nuc_macro(nuclide[0], types, library, - orders, T)) - - # Combine across the nuclides - data = np.zeros((len(types), library.energy_groups.num_groups)) - for line in range(len(types)): - if types[line] == 'unity': - data[line, :] = 1. - else: - for n in range(len(nuclides)): - data[line, :] += nuc_fraction[n] * nuc_data[n][line, :] - - return data diff --git a/openmc/polynomial.py b/openmc/polynomial.py deleted file mode 100644 index abcfd8057..000000000 --- a/openmc/polynomial.py +++ /dev/null @@ -1,81 +0,0 @@ -import numpy as np -import openmc -from collections.abc import Iterable - - -def legendre_from_expcoef(coef, domain=(-1, 1)): - """Return a Legendre series object based on expansion coefficients. - - Given a list of coefficients from FET tally and a array of down, return - the numpy Legendre object. - - Parameters - ---------- - coef : Iterable of float - A list of coefficients of each term in Legendre polynomials - domain : (2,) List of float - Domain of the Legendre polynomial - - Returns - ------- - numpy.polynomial.Legendre - A numpy Legendre series class - - """ - - n = np.arange(len(coef)) - c = (2*n + 1) * np.asarray(coef) / (domain[1] - domain[0]) - return np.polynomial.Legendre(c, domain) - - -class Polynomial(object): - """Abstract Polynomial Class for creating polynomials. - """ - def __init__(self, coef): - self.coef = np.asarray(coef) - - -class ZernikeRadial(Polynomial): - """Create radial only Zernike polynomials given coefficients and domain. - - The radial only Zernike polynomials are defined as in - :class:`ZernikeRadialFilter`. - - Parameters - ---------- - coef : Iterable of float - A list of coefficients of each term in radial only Zernike polynomials - radius : float - Domain of Zernike polynomials to be applied on. Default is 1. - r : float - Position to be evaluated, normalized on radius [0,1] - - Attributes - ---------- - order : int - The maximum (even) order of Zernike polynomials. - radius : float - Domain of Zernike polynomials to be applied on. Default is 1. - norm_coef : iterable of float - The list of coefficients of each term in the polynomials after - normailization. - - """ - def __init__(self, coef, radius=1): - super().__init__(coef) - self._order = 2 * (len(self.coef) - 1) - self.radius = radius - norm_vec = (2 * np.arange(len(self.coef)) + 1) / (np.pi * radius**2) - self._norm_coef = norm_vec * self.coef - - @property - def order(self): - return self._order - - def __call__(self, r): - import openmc.lib as lib - if isinstance(r, Iterable): - return [np.sum(self._norm_coef * lib.calc_zn_rad(self.order, r_i)) - for r_i in r] - else: - return np.sum(self._norm_coef * lib.calc_zn_rad(self.order, r)) diff --git a/openmc/region.py b/openmc/region.py deleted file mode 100644 index a751e1ebf..000000000 --- a/openmc/region.py +++ /dev/null @@ -1,663 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections import OrderedDict -from collections.abc import Iterable, MutableSequence -from copy import deepcopy - -import numpy as np - -from openmc.checkvalue import check_type - - -class Region(metaclass=ABCMeta): - """Region of space that can be assigned to a cell. - - Region is an abstract base class that is inherited by - :class:`openmc.Halfspace`, :class:`openmc.Intersection`, - :class:`openmc.Union`, and :class:`openmc.Complement`. Each of those - respective classes are typically not instantiated directly but rather are - created through operators of the Surface and Region classes. - - """ - def __and__(self, other): - return Intersection((self, other)) - - def __or__(self, other): - return Union((self, other)) - - def __invert__(self): - return Complement(self) - - @abstractmethod - def __contains__(self, point): - pass - - @abstractmethod - def __str__(self): - pass - - def __eq__(self, other): - if not isinstance(other, type(self)): - return False - else: - return str(self) == str(other) - - def __ne__(self, other): - return not self == other - - def get_surfaces(self, surfaces=None): - """ - Recursively find all the surfaces referenced by a region and return them - - Parameters - ---------- - surfaces: collections.OrderedDict, optional - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - Returns - ------- - surfaces: collections.OrderedDict - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - """ - if surfaces is None: - surfaces = OrderedDict() - for region in self: - surfaces = region.get_surfaces(surfaces) - return surfaces - - @staticmethod - def from_expression(expression, surfaces): - """Generate a region given an infix expression. - - Parameters - ---------- - expression : str - Boolean expression relating surface half-spaces. The possible - operators are union '|', intersection ' ', and complement '~'. For - example, '(1 -2) | 3 ~(4 -5)'. - surfaces : dict - Dictionary whose keys are suface IDs that appear in the Boolean - expression and whose values are Surface objects. - - """ - - # Strip leading and trailing whitespace - expression = expression.strip() - - # Convert the string expression into a list of tokens, i.e., operators - # and surface half-spaces, representing the expression in infix - # notation. - i = 0 - i_start = -1 - tokens = [] - while i < len(expression): - if expression[i] in '()|~ ': - # If special character appears immediately after a non-operator, - # create a token with the apporpriate half-space - if i_start >= 0: - j = int(expression[i_start:i]) - if j < 0: - tokens.append(-surfaces[abs(j)]) - else: - tokens.append(+surfaces[abs(j)]) - - if expression[i] in '()|~': - # For everything other than intersection, add the operator - # to the list of tokens - tokens.append(expression[i]) - else: - # Find next non-space character - while expression[i+1] == ' ': - i += 1 - - # If previous token is a halfspace or right parenthesis and next token - # is not a left parenthese or union operator, that implies that the - # whitespace is to be interpreted as an intersection operator - if (i_start >= 0 or tokens[-1] == ')') and \ - expression[i+1] not in ')|': - tokens.append(' ') - - i_start = -1 - else: - # Check for invalid characters - if expression[i] not in '-+0123456789': - raise SyntaxError("Invalid character '{}' in expression" - .format(expression[i])) - - # If we haven't yet reached the start of a word, start one - if i_start < 0: - i_start = i - i += 1 - - # If we've reached the end and we're still in a word, create a - # half-space token and add it to the list - if i_start >= 0: - j = int(expression[i_start:]) - if j < 0: - tokens.append(-surfaces[abs(j)]) - else: - tokens.append(+surfaces[abs(j)]) - - # The functions below are used to apply an operator to operands on the - # output queue during the shunting yard algorithm. - def can_be_combined(region): - return isinstance(region, Complement) or hasattr(region, 'surface') - - def apply_operator(output, operator): - r2 = output.pop() - if operator == ' ': - r1 = output.pop() - if isinstance(r1, Intersection): - r1 &= r2 - output.append(r1) - elif isinstance(r2, Intersection) and can_be_combined(r1): - r2.insert(0, r1) - output.append(r2) - else: - output.append(r1 & r2) - elif operator == '|': - r1 = output.pop() - if isinstance(r1, Union): - r1 |= r2 - output.append(r1) - elif isinstance(r2, Union) and can_be_combined(r1): - r2.insert(0, r1) - output.append(r2) - else: - output.append(r1 | r2) - elif operator == '~': - output.append(~r2) - - # The following is an implementation of the shunting yard algorithm to - # generate an abstract syntax tree for the region expression. - output = [] - stack = [] - precedence = {'|': 1, ' ': 2, '~': 3} - associativity = {'|': 'left', ' ': 'left', '~': 'right'} - for token in tokens: - if token in (' ', '|', '~'): - # Normal operators - while stack: - op = stack[-1] - if (op not in ('(', ')') and - ((associativity[token] == 'right' and - precedence[token] < precedence[op]) or - (associativity[token] == 'left' and - precedence[token] <= precedence[op]))): - apply_operator(output, stack.pop()) - else: - break - stack.append(token) - elif token == '(': - # Left parentheses - stack.append(token) - elif token == ')': - # Right parentheses - while stack[-1] != '(': - apply_operator(output, stack.pop()) - if len(stack) == 0: - raise SyntaxError('Mismatched parentheses in ' - 'region specification.') - stack.pop() - else: - # Surface halfspaces - output.append(token) - while stack: - if stack[-1] in '()': - raise SyntaxError('Mismatched parentheses in region ' - 'specification.') - apply_operator(output, stack.pop()) - - # Since we are generating an abstract syntax tree rather than a reverse - # Polish notation expression, the output queue should have a single item - # at the end - return output[0] - - @abstractmethod - def clone(self, memo=None): - """Create a copy of this region - each of the surfaces in the - region's nodes will be cloned and will have new unique IDs. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Region - The clone of this region - - """ - pass - - @abstractmethod - def translate(self, vector, memo=None): - """Translate region in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which region should be translated - memo : dict or None - Dictionary used for memoization. This parameter is used internally - and should not be specified by the user. - - Returns - ------- - openmc.Region - Translated region - - """ - pass - - -class Intersection(Region, MutableSequence): - r"""Intersection of two or more regions. - - Instances of Intersection are generally created via the & operator applied - to two instances of :class:`openmc.Region`. This is illustrated in the - following example: - - >>> equator = openmc.ZPlane(z0=0.0) - >>> earth = openmc.Sphere(r=637.1e6) - >>> northern_hemisphere = -earth & +equator - >>> southern_hemisphere = -earth & -equator - >>> type(northern_hemisphere) - - - Instances of this class behave like a mutable sequence, e.g., they can be - indexed and have an append() method. - - Parameters - ---------- - nodes : iterable of openmc.Region - Regions to take the intersection of - - Attributes - ---------- - bounding_box : tuple of numpy.array - Lower-left and upper-right coordinates of an axis-aligned bounding box - - """ - - def __init__(self, nodes): - self._nodes = list(nodes) - - def __and__(self, other): - new = Intersection(self) - new &= other - return new - - def __iand__(self, other): - if isinstance(other, Intersection): - self.extend(other) - else: - self.append(other) - return self - - # Implement mutable sequence protocol by delegating to list - def __getitem__(self, key): - return self._nodes[key] - - def __setitem__(self, key, value): - self._nodes[key] = value - - def __delitem__(self, key): - del self._nodes[key] - - def __len__(self): - return len(self._nodes) - - def insert(self, index, value): - self._nodes.insert(index, value) - - def __contains__(self, point): - """Check whether a point is contained in the region. - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates, :math:`(x',y',z')`, of the point - - Returns - ------- - bool - Whether the point is in the region - - """ - return all(point in n for n in self) - - def __str__(self): - return '(' + ' '.join(map(str, self)) + ')' - - @property - def bounding_box(self): - lower_left = np.array([-np.inf, -np.inf, -np.inf]) - upper_right = np.array([np.inf, np.inf, np.inf]) - for n in self: - lower_left_n, upper_right_n = n.bounding_box - lower_left[:] = np.maximum(lower_left, lower_left_n) - upper_right[:] = np.minimum(upper_right, upper_right_n) - return lower_left, upper_right - - def clone(self, memo=None): - """Create a copy of this region - each of the surfaces in the - intersection's nodes will be cloned and will have new unique IDs. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Intersection - The clone of this intersection - - """ - - if memo is None: - memo = {} - - clone = deepcopy(self) - clone[:] = [n.clone(memo) for n in self] - return clone - - def translate(self, vector, memo=None): - """Translate region in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which region should be translated - memo : dict or None - Dictionary used for memoization. This parameter is used internally - and should not be specified by the user. - - Returns - ------- - openmc.Intersection - Translated region - - """ - if memo is None: - memo = {} - return type(self)(n.translate(vector, memo) for n in self) - - -class Union(Region, MutableSequence): - r"""Union of two or more regions. - - Instances of Union are generally created via the | operator applied to two - instances of :class:`openmc.Region`. This is illustrated in the following - example: - - >>> s1 = openmc.ZPlane(z0=0.0) - >>> s2 = openmc.Sphere(r=637.1e6) - >>> type(-s2 | +s1) - - - Instances of this class behave like a mutable sequence, e.g., they can be - indexed and have an append() method. - - Parameters - ---------- - nodes : iterable of openmc.Region - Regions to take the union of - - Attributes - ---------- - bounding_box : 2-tuple of numpy.array - Lower-left and upper-right coordinates of an axis-aligned bounding box - - """ - - def __init__(self, nodes): - self._nodes = list(nodes) - - def __or__(self, other): - new = Union(self) - new |= other - return new - - def __ior__(self, other): - if isinstance(other, Union): - self.extend(other) - else: - self.append(other) - return self - - # Implement mutable sequence protocol by delegating to list - def __getitem__(self, key): - return self._nodes[key] - - def __setitem__(self, key, value): - self._nodes[key] = value - - def __delitem__(self, key): - del self._nodes[key] - - def __len__(self): - return len(self._nodes) - - def insert(self, index, value): - self._nodes.insert(index, value) - - def __contains__(self, point): - """Check whether a point is contained in the region. - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates, :math:`(x',y',z')`, of the point - - Returns - ------- - bool - Whether the point is in the region - - """ - return any(point in n for n in self) - - def __str__(self): - return '(' + ' | '.join(map(str, self)) + ')' - - @property - def bounding_box(self): - lower_left = np.array([np.inf, np.inf, np.inf]) - upper_right = np.array([-np.inf, -np.inf, -np.inf]) - for n in self: - lower_left_n, upper_right_n = n.bounding_box - lower_left[:] = np.minimum(lower_left, lower_left_n) - upper_right[:] = np.maximum(upper_right, upper_right_n) - return lower_left, upper_right - - def clone(self, memo=None): - """Create a copy of this region - each of the surfaces in the - union's nodes will be cloned and will have new unique IDs. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Union - The clone of this union - - """ - - if memo is None: - memo = {} - - clone = deepcopy(self) - clone[:] = [n.clone(memo) for n in self] - return clone - - def translate(self, vector, memo=None): - """Translate region in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which region should be translated - memo : dict or None - Dictionary used for memoization. This parameter is used internally - and should not be specified by the user. - - Returns - ------- - openmc.Union - Translated region - - """ - if memo is None: - memo = {} - return type(self)(n.translate(vector, memo) for n in self) - - -class Complement(Region): - """Complement of a region. - - The Complement of an existing :class:`openmc.Region` can be created by using - the ~ operator as the following example demonstrates: - - >>> xl = openmc.XPlane(-10.0) - >>> xr = openmc.XPlane(10.0) - >>> yl = openmc.YPlane(-10.0) - >>> yr = openmc.YPlane(10.0) - >>> inside_box = +xl & -xr & +yl & -yr - >>> outside_box = ~inside_box - >>> type(outside_box) - - - Parameters - ---------- - node : openmc.Region - Region to take the complement of - - Attributes - ---------- - node : openmc.Region - Regions to take the complement of - bounding_box : tuple of numpy.array - Lower-left and upper-right coordinates of an axis-aligned bounding box - - """ - - def __init__(self, node): - self.node = node - - def __contains__(self, point): - """Check whether a point is contained in the region. - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates, :math:`(x',y',z')`, of the point - - Returns - ------- - bool - Whether the point is in the region - - """ - return point not in self.node - - def __str__(self): - return '~' + str(self.node) - - @property - def node(self): - return self._node - - @node.setter - def node(self, node): - check_type('node', node, Region) - self._node = node - - @property - def bounding_box(self): - # Use De Morgan's laws to distribute the complement operator so that it - # only applies to surface half-spaces, thus allowing us to calculate the - # bounding box in the usual recursive manner. - if isinstance(self.node, Union): - temp_region = Intersection(~n for n in self.node) - elif isinstance(self.node, Intersection): - temp_region = Union(~n for n in self.node) - elif isinstance(self.node, Complement): - temp_region = self.node.node - else: - temp_region = ~self.node - return temp_region.bounding_box - - def get_surfaces(self, surfaces=None): - """ - Recursively find and return all the surfaces referenced by the node - - Parameters - ---------- - surfaces: collections.OrderedDict, optional - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - Returns - ------- - surfaces: collections.OrderedDict - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - """ - if surfaces is None: - surfaces = OrderedDict() - for region in self.node: - surfaces = region.get_surfaces(surfaces) - return surfaces - - def clone(self, memo=None): - """Create a copy of this region - each of the surfaces in the - complement's node will be cloned and will have new unique IDs. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Complement - The clone of this complement - - """ - - if memo is None: - memo = {} - - clone = deepcopy(self) - clone.node = self.node.clone(memo) - return clone - - def translate(self, vector, memo=None): - """Translate region in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which region should be translated - memo : dict or None - Dictionary used for memoization. This parameter is used internally - and should not be specified by the user. - - Returns - ------- - openmc.Complement - Translated region - - """ - if memo is None: - memo = {} - return type(self)(self.node.translate(vector, memo)) diff --git a/openmc/search.py b/openmc/search.py deleted file mode 100644 index 6be8a50ea..000000000 --- a/openmc/search.py +++ /dev/null @@ -1,197 +0,0 @@ -from collections.abc import Callable -from numbers import Real - -import scipy.optimize as sopt - -import openmc -import openmc.model -import openmc.checkvalue as cv - - -_SCALAR_BRACKETED_METHODS = ['brentq', 'brenth', 'ridder', 'bisect'] - - -def _search_keff(guess, target, model_builder, model_args, print_iterations, - print_output, guesses, results): - """Function which will actually create our model, run the calculation, and - obtain the result. This function will be passed to the root finding - algorithm - - Parameters - ---------- - guess : Real - Current guess for the parameter to be searched in `model_builder`. - target_keff : Real - Value to search for - model_builder : collections.Callable - Callable function which builds a model according to a passed - parameter. This function must return an openmc.model.Model object. - model_args : dict - Keyword-based arguments to pass to the `model_builder` method. - print_iterations : bool - Whether or not to print the guess and the resultant keff during the - iteration process. - print_output : bool - Whether or not to print the OpenMC output during the iterations. - guesses : Iterable of Real - Running list of guesses thus far, to be updated during the execution of - this function. - results : Iterable of Real - Running list of results thus far, to be updated during the execution of - this function. - - Returns - ------- - float - Value of the model for the current guess compared to the target value. - - """ - - # Build the model - model = model_builder(guess, **model_args) - - # Run the model and obtain keff - keff = model.run(output=print_output) - - # Record the history - guesses.append(guess) - results.append(keff) - - if print_iterations: - text = 'Iteration: {}; Guess of {:.2e} produced a keff of ' + \ - '{:1.5f} +/- {:1.5f}' - print(text.format(len(guesses), guess, keff.n, keff.s)) - - return keff.n - target - - -def search_for_keff(model_builder, initial_guess=None, target=1.0, - bracket=None, model_args=None, tol=None, - bracketed_method='bisect', print_iterations=False, - print_output=False, **kwargs): - """Function to perform a keff search by modifying a model parametrized by a - single independent variable. - - Parameters - ---------- - model_builder : collections.Callable - Callable function which builds a model according to a passed - parameter. This function must return an openmc.model.Model object. - initial_guess : Real, optional - Initial guess for the parameter to be searched in - `model_builder`. One of `guess` or `bracket` must be provided. - target : Real, optional - keff value to search for, defaults to 1.0. - bracket : None or Iterable of Real, optional - Bracketing interval to search for the solution; if not provided, - a generic non-bracketing method is used. If provided, the brackets - are used. Defaults to no brackets provided. One of `guess` or `bracket` - must be provided. If both are provided, the bracket will be - preferentially used. - model_args : dict, optional - Keyword-based arguments to pass to the `model_builder` method. Defaults - to no arguments. - tol : float - Tolerance to pass to the search method - bracketed_method : {'brentq', 'brenth', 'ridder', 'bisect'}, optional - Solution method to use; only applies if - `bracket` is set, otherwise the Secant method is used. - Defaults to 'bisect'. - print_iterations : bool - Whether or not to print the guess and the result during the iteration - process. Defaults to False. - print_output : bool - Whether or not to print the OpenMC output during the iterations. - Defaults to False. - **kwargs - All remaining keyword arguments are passed to the root-finding - method. - - Returns - ------- - zero_value : float - Estimated value of the variable parameter where keff is the - targeted value - guesses : List of Real - List of guesses attempted by the search - results : List of 2-tuple of Real - List of keffs and uncertainties corresponding to the guess attempted by - the search - - """ - - if initial_guess is not None: - cv.check_type('initial_guess', initial_guess, Real) - if bracket is not None: - cv.check_iterable_type('bracket', bracket, Real) - cv.check_length('bracket', bracket, 2) - cv.check_less_than('bracket values', bracket[0], bracket[1]) - if model_args is None: - model_args = {} - else: - cv.check_type('model_args', model_args, dict) - cv.check_type('target', target, Real) - cv.check_type('tol', tol, Real) - cv.check_value('bracketed_method', bracketed_method, - _SCALAR_BRACKETED_METHODS) - cv.check_type('print_iterations', print_iterations, bool) - cv.check_type('print_output', print_output, bool) - cv.check_type('model_builder', model_builder, Callable) - - # Run the model builder function once to make sure it provides the correct - # output type - if bracket is not None: - model = model_builder(bracket[0], **model_args) - elif initial_guess is not None: - model = model_builder(initial_guess, **model_args) - cv.check_type('model_builder return', model, openmc.model.Model) - - # Set the iteration data storage variables - guesses = [] - results = [] - - # Set the searching function (for easy replacement should a later - # generic function be added. - search_function = _search_keff - - if bracket is not None: - # Generate our arguments - args = {'f': search_function, 'a': bracket[0], 'b': bracket[1]} - if tol is not None: - args['rtol'] = tol - - # Set the root finding method - if bracketed_method == 'brentq': - root_finder = sopt.brentq - elif bracketed_method == 'brenth': - root_finder = sopt.brenth - elif bracketed_method == 'ridder': - root_finder = sopt.ridder - elif bracketed_method == 'bisect': - root_finder = sopt.bisect - - elif initial_guess is not None: - - # Generate our arguments - args = {'func': search_function, 'x0': initial_guess} - if tol is not None: - args['tol'] = tol - - # Set the root finding method - root_finder = sopt.newton - - else: - raise ValueError("Either the 'bracket' or 'initial_guess' parameters " - "must be set") - - # Add information to be passed to the searching function - args['args'] = (target, model_builder, model_args, print_iterations, - print_output, guesses, results) - - # Create a new dictionary with the arguments from args and kwargs - args.update(kwargs) - - # Perform the search - zero_value = root_finder(**args) - - return zero_value, guesses, results diff --git a/openmc/settings.py b/openmc/settings.py deleted file mode 100644 index 784c2ac6e..000000000 --- a/openmc/settings.py +++ /dev/null @@ -1,1275 +0,0 @@ -from collections.abc import Iterable, MutableSequence, Mapping -from pathlib import Path -from numbers import Real, Integral -import warnings -from xml.etree import ElementTree as ET -import sys - -import numpy as np - -from openmc._xml import clean_indentation, get_text -import openmc.checkvalue as cv -from openmc import VolumeCalculation, Source, RegularMesh - -_RUN_MODES = ['eigenvalue', 'fixed source', 'plot', 'volume', 'particle restart'] -_RES_SCAT_METHODS = ['dbrc', 'rvs'] - - -class Settings(object): - """Settings used for an OpenMC simulation. - - Attributes - ---------- - batches : int - Number of batches to simulate - confidence_intervals : bool - If True, uncertainties on tally results will be reported as the - half-width of the 95% two-sided confidence interval. If False, - uncertainties on tally results will be reported as the sample standard - deviation. - create_fission_neutrons : bool - Indicate whether fission neutrons should be created or not. - cutoff : dict - Dictionary defining weight cutoff and energy cutoff. The dictionary may - have six keys, 'weight', 'weight_avg', 'energy_neutron', 'energy_photon', - 'energy_electron', and 'energy_positron'. Value for 'weight' - should be a float indicating weight cutoff below which particle undergo - Russian roulette. Value for 'weight_avg' should be a float indicating - weight assigned to particles that are not killed after Russian - roulette. Value of energy should be a float indicating energy in eV - below which particle type will be killed. - dagmc : bool - Indicate that a CAD-based DAGMC geometry will be used. - electron_treatment : {'led', 'ttb'} - Whether to deposit all energy from electrons locally ('led') or create - secondary bremsstrahlung photons ('ttb'). - energy_mode : {'continuous-energy', 'multi-group'} - Set whether the calculation should be continuous-energy or multi-group. - entropy_mesh : openmc.RegularMesh - Mesh to be used to calculate Shannon entropy. If the mesh dimensions are - not specified. OpenMC assigns a mesh such that 20 source sites per mesh - cell are to be expected on average. - generations_per_batch : int - Number of generations per batch - inactive : int - Number of inactive batches - keff_trigger : dict - Dictionary defining a trigger on eigenvalue. The dictionary must have - two keys, 'type' and 'threshold'. Acceptable values corresponding to - type are 'variance', 'std_dev', and 'rel_err'. The threshold value - should be a float indicating the variance, standard deviation, or - relative error used. - log_grid_bins : int - Number of bins for logarithmic energy grid search - max_order : None or int - Maximum scattering order to apply globally when in multi-group mode. - no_reduce : bool - Indicate that all user-defined and global tallies should not be reduced - across processes in a parallel calculation. - output : dict - Dictionary indicating what files to output. Acceptable keys are: - - :path: String indicating a directory where output files should be - written - :summary: Whether the 'summary.h5' file should be written (bool) - :tallies: Whether the 'tallies.out' file should be written (bool) - particles : int - Number of particles per generation - photon_transport : bool - Whether to use photon transport. - ptables : bool - Determine whether probability tables are used. - resonance_scattering : dict - Settings for resonance elastic scattering. Accepted keys are 'enable' - (bool), 'method' (str), 'energy_min' (float), 'energy_max' (float), and - 'nuclides' (list). The 'method' can be set to 'dbrc' (Doppler broadening - rejection correction) or 'rvs' (relative velocity sampling). If not - specified, 'rvs' is the default method. The 'energy_min' and - 'energy_max' values indicate the minimum and maximum energies above and - below which the resonance elastic scattering method is to be - applied. The 'nuclides' list indicates what nuclides the method should - be applied to. In its absence, the method will be applied to all - nuclides with 0 K elastic scattering data present. - run_mode : {'eigenvalue', 'fixed source', 'plot', 'volume', 'particle restart'} - The type of calculation to perform (default is 'eigenvalue') - seed : int - Seed for the linear congruential pseudorandom number generator - source : Iterable of openmc.Source - Distribution of source sites in space, angle, and energy - sourcepoint : dict - Options for writing source points. Acceptable keys are: - - :batches: list of batches at which to write source - :overwrite: bool indicating whether to overwrite - :separate: bool indicating whether the source should be written as a - separate file - :write: bool indicating whether or not to write the source - statepoint : dict - Options for writing state points. Acceptable keys are: - - :batches: list of batches at which to write source - survival_biasing : bool - Indicate whether survival biasing is to be used - tabular_legendre : dict - Determines if a multi-group scattering moment kernel expanded via - Legendre polynomials is to be converted to a tabular distribution or - not. Accepted keys are 'enable' and 'num_points'. The value for - 'enable' is a bool stating whether the conversion to tabular is - performed; the value for 'num_points' sets the number of points to use - in the tabular distribution, should 'enable' be True. - temperature : dict - Defines a default temperature and method for treating intermediate - temperatures at which nuclear data doesn't exist. Accepted keys are - 'default', 'method', 'range', 'tolerance', and 'multipole'. The value - for 'default' should be a float representing the default temperature in - Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. - If the method is 'nearest', 'tolerance' indicates a range of temperature - within which cross sections may be used. The value for 'range' should be - a pair a minimum and maximum temperatures which are used to indicate - that cross sections be loaded at all temperatures within the - range. 'multipole' is a boolean indicating whether or not the windowed - multipole method should be used to evaluate resolved resonance cross - sections. - trace : tuple or list - Show detailed information about a single particle, indicated by three - integers: the batch number, generation number, and particle number - track : tuple or list - Specify particles for which track files should be written. Each particle - is identified by a triplet with the batch number, generation number, and - particle number. - trigger_active : bool - Indicate whether tally triggers are used - trigger_batch_interval : int - Number of batches in between convergence checks - trigger_max_batches : int - Maximum number of batches simulated. If this is set, the number of - batches specified via ``batches`` is interpreted as the minimum number - of batches - ufs_mesh : openmc.RegularMesh - Mesh to be used for redistributing source sites via the uniform fision - site (UFS) method. - verbosity : int - Verbosity during simulation between 1 and 10. Verbosity levels are - described in :ref:`verbosity`. - volume_calculations : VolumeCalculation or iterable of VolumeCalculation - Stochastic volume calculation specifications - - """ - - def __init__(self): - - # Run mode subelement (default is 'eigenvalue') - self._run_mode = 'eigenvalue' - self._batches = None - self._generations_per_batch = None - self._inactive = None - self._particles = None - self._keff_trigger = None - - # Energy mode subelement - self._energy_mode = None - self._max_order = None - - # Source subelement - self._source = cv.CheckedList(Source, 'source distributions') - - self._confidence_intervals = None - self._electron_treatment = None - self._photon_transport = None - self._ptables = None - self._seed = None - self._survival_biasing = None - - # Shannon entropy mesh - self._entropy_mesh = None - - # Trigger subelement - self._trigger_active = None - self._trigger_max_batches = None - self._trigger_batch_interval = None - - self._output = None - - # Output options - self._statepoint = {} - self._sourcepoint = {} - - self._no_reduce = None - - self._verbosity = None - - self._trace = None - self._track = None - - self._tabular_legendre = {} - - self._temperature = {} - - # Cutoff subelement - self._cutoff = None - - # Uniform fission source subelement - self._ufs_mesh = None - - self._resonance_scattering = {} - self._volume_calculations = cv.CheckedList( - VolumeCalculation, 'volume calculations') - - self._create_fission_neutrons = None - self._log_grid_bins = None - - self._dagmc = False - - @property - def run_mode(self): - return self._run_mode - - @property - def batches(self): - return self._batches - - @property - def generations_per_batch(self): - return self._generations_per_batch - - @property - def inactive(self): - return self._inactive - - @property - def particles(self): - return self._particles - - @property - def keff_trigger(self): - return self._keff_trigger - - @property - def energy_mode(self): - return self._energy_mode - - @property - def max_order(self): - return self._max_order - - @property - def source(self): - return self._source - - @property - def confidence_intervals(self): - return self._confidence_intervals - - @property - def electron_treatment(self): - return self._electron_treatment - - @property - def ptables(self): - return self._ptables - - @property - def photon_transport(self): - return self._photon_transport - - @property - def seed(self): - return self._seed - - @property - def survival_biasing(self): - return self._survival_biasing - - @property - def entropy_mesh(self): - return self._entropy_mesh - - @property - def trigger_active(self): - return self._trigger_active - - @property - def trigger_max_batches(self): - return self._trigger_max_batches - - @property - def trigger_batch_interval(self): - return self._trigger_batch_interval - - @property - def output(self): - return self._output - - @property - def sourcepoint(self): - return self._sourcepoint - - @property - def statepoint(self): - return self._statepoint - - @property - def no_reduce(self): - return self._no_reduce - - @property - def verbosity(self): - return self._verbosity - - @property - def tabular_legendre(self): - return self._tabular_legendre - - @property - def temperature(self): - return self._temperature - - @property - def trace(self): - return self._trace - - @property - def track(self): - return self._track - - @property - def cutoff(self): - return self._cutoff - - @property - def ufs_mesh(self): - return self._ufs_mesh - - @property - def resonance_scattering(self): - return self._resonance_scattering - - @property - def volume_calculations(self): - return self._volume_calculations - - @property - def create_fission_neutrons(self): - return self._create_fission_neutrons - - @property - def log_grid_bins(self): - return self._log_grid_bins - - @property - def dagmc(self): - return self._dagmc - - @run_mode.setter - def run_mode(self, run_mode): - cv.check_value('run mode', run_mode, _RUN_MODES) - self._run_mode = run_mode - - @batches.setter - def batches(self, batches): - cv.check_type('batches', batches, Integral) - cv.check_greater_than('batches', batches, 0) - self._batches = batches - - @generations_per_batch.setter - def generations_per_batch(self, generations_per_batch): - cv.check_type('generations per patch', generations_per_batch, Integral) - cv.check_greater_than('generations per batch', generations_per_batch, 0) - self._generations_per_batch = generations_per_batch - - @inactive.setter - def inactive(self, inactive): - cv.check_type('inactive batches', inactive, Integral) - cv.check_greater_than('inactive batches', inactive, 0, True) - self._inactive = inactive - - @particles.setter - def particles(self, particles): - cv.check_type('particles', particles, Integral) - cv.check_greater_than('particles', particles, 0) - self._particles = particles - - @keff_trigger.setter - def keff_trigger(self, keff_trigger): - if not isinstance(keff_trigger, dict): - msg = 'Unable to set a trigger on keff from "{0}" which ' \ - 'is not a Python dictionary'.format(keff_trigger) - raise ValueError(msg) - - elif 'type' not in keff_trigger: - msg = 'Unable to set a trigger on keff from "{0}" which ' \ - 'does not have a "type" key'.format(keff_trigger) - raise ValueError(msg) - - elif keff_trigger['type'] not in ['variance', 'std_dev', 'rel_err']: - msg = 'Unable to set a trigger on keff with ' \ - 'type "{0}"'.format(keff_trigger['type']) - raise ValueError(msg) - - elif 'threshold' not in keff_trigger: - msg = 'Unable to set a trigger on keff from "{0}" which ' \ - 'does not have a "threshold" key'.format(keff_trigger) - raise ValueError(msg) - - elif not isinstance(keff_trigger['threshold'], Real): - msg = 'Unable to set a trigger on keff with ' \ - 'threshold "{0}"'.format(keff_trigger['threshold']) - raise ValueError(msg) - - self._keff_trigger = keff_trigger - - @energy_mode.setter - def energy_mode(self, energy_mode): - cv.check_value('energy mode', energy_mode, - ['continuous-energy', 'multi-group']) - self._energy_mode = energy_mode - - @max_order.setter - def max_order(self, max_order): - if max_order is not None: - cv.check_type('maximum scattering order', max_order, Integral) - cv.check_greater_than('maximum scattering order', max_order, 0, - True) - self._max_order = max_order - - @source.setter - def source(self, source): - if not isinstance(source, MutableSequence): - source = [source] - self._source = cv.CheckedList(Source, 'source distributions', source) - - @output.setter - def output(self, output): - cv.check_type('output', output, Mapping) - for key, value in output.items(): - cv.check_value('output key', key, ('summary', 'tallies', 'path')) - if key in ('summary', 'tallies'): - cv.check_type("output['{}']".format(key), value, bool) - else: - cv.check_type("output['path']", value, str) - self._output = output - - @verbosity.setter - def verbosity(self, verbosity): - cv.check_type('verbosity', verbosity, Integral) - cv.check_greater_than('verbosity', verbosity, 1, True) - cv.check_less_than('verbosity', verbosity, 10, True) - self._verbosity = verbosity - - @sourcepoint.setter - def sourcepoint(self, sourcepoint): - cv.check_type('sourcepoint options', sourcepoint, Mapping) - for key, value in sourcepoint.items(): - if key == 'batches': - cv.check_type('sourcepoint batches', value, Iterable, Integral) - for batch in value: - cv.check_greater_than('sourcepoint batch', batch, 0) - elif key == 'separate': - cv.check_type('sourcepoint separate', value, bool) - elif key == 'write': - cv.check_type('sourcepoint write', value, bool) - elif key == 'overwrite': - cv.check_type('sourcepoint overwrite', value, bool) - else: - raise ValueError("Unknown key '{}' encountered when setting " - "sourcepoint options.".format(key)) - self._sourcepoint = sourcepoint - - @statepoint.setter - def statepoint(self, statepoint): - cv.check_type('statepoint options', statepoint, Mapping) - for key, value in statepoint.items(): - if key == 'batches': - cv.check_type('statepoint batches', value, Iterable, Integral) - for batch in value: - cv.check_greater_than('statepoint batch', batch, 0) - else: - raise ValueError("Unknown key '{}' encountered when setting " - "statepoint options.".format(key)) - self._statepoint = statepoint - - @confidence_intervals.setter - def confidence_intervals(self, confidence_intervals): - cv.check_type('confidence interval', confidence_intervals, bool) - self._confidence_intervals = confidence_intervals - - @electron_treatment.setter - def electron_treatment(self, electron_treatment): - cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) - self._electron_treatment = electron_treatment - - @photon_transport.setter - def photon_transport(self, photon_transport): - cv.check_type('photon transport', photon_transport, bool) - self._photon_transport = photon_transport - - @dagmc.setter - def dagmc(self, dagmc): - cv.check_type('dagmc geometry', dagmc, bool) - self._dagmc = dagmc - - @ptables.setter - def ptables(self, ptables): - cv.check_type('probability tables', ptables, bool) - self._ptables = ptables - - @seed.setter - def seed(self, seed): - cv.check_type('random number generator seed', seed, Integral) - cv.check_greater_than('random number generator seed', seed, 0) - self._seed = seed - - @survival_biasing.setter - def survival_biasing(self, survival_biasing): - cv.check_type('survival biasing', survival_biasing, bool) - self._survival_biasing = survival_biasing - - @cutoff.setter - def cutoff(self, cutoff): - if not isinstance(cutoff, Mapping): - msg = 'Unable to set cutoff from "{0}" which is not a '\ - ' Python dictionary'.format(cutoff) - raise ValueError(msg) - for key in cutoff: - if key == 'weight': - cv.check_type('weight cutoff', cutoff[key], Real) - cv.check_greater_than('weight cutoff', cutoff[key], 0.0) - elif key == 'weight_avg': - cv.check_type('average survival weight', cutoff[key], Real) - cv.check_greater_than('average survival weight', - cutoff[key], 0.0) - elif key in ['energy_neutron', 'energy_photon', 'energy_electron', - 'energy_positron']: - cv.check_type('energy cutoff', cutoff[key], Real) - cv.check_greater_than('energy cutoff', cutoff[key], 0.0) - else: - msg = 'Unable to set cutoff to "{0}" which is unsupported by '\ - 'OpenMC'.format(key) - - self._cutoff = cutoff - - @entropy_mesh.setter - def entropy_mesh(self, entropy): - cv.check_type('entropy mesh', entropy, RegularMesh) - if entropy.dimension: - cv.check_length('entropy mesh dimension', entropy.dimension, 3) - cv.check_length('entropy mesh lower-left corner', entropy.lower_left, 3) - cv.check_length('entropy mesh upper-right corner', entropy.upper_right, 3) - self._entropy_mesh = entropy - - @trigger_active.setter - def trigger_active(self, trigger_active): - cv.check_type('trigger active', trigger_active, bool) - self._trigger_active = trigger_active - - @trigger_max_batches.setter - def trigger_max_batches(self, trigger_max_batches): - cv.check_type('trigger maximum batches', trigger_max_batches, Integral) - cv.check_greater_than('trigger maximum batches', trigger_max_batches, 0) - self._trigger_max_batches = trigger_max_batches - - @trigger_batch_interval.setter - def trigger_batch_interval(self, trigger_batch_interval): - cv.check_type('trigger batch interval', trigger_batch_interval, Integral) - cv.check_greater_than('trigger batch interval', trigger_batch_interval, 0) - self._trigger_batch_interval = trigger_batch_interval - - @no_reduce.setter - def no_reduce(self, no_reduce): - cv.check_type('no reduction option', no_reduce, bool) - self._no_reduce = no_reduce - - @tabular_legendre.setter - def tabular_legendre(self, tabular_legendre): - cv.check_type('tabular_legendre settings', tabular_legendre, Mapping) - for key, value in tabular_legendre.items(): - cv.check_value('tabular_legendre key', key, - ['enable', 'num_points']) - if key == 'enable': - cv.check_type('enable tabular_legendre', value, bool) - elif key == 'num_points': - cv.check_type('num_points tabular_legendre', value, Integral) - cv.check_greater_than('num_points tabular_legendre', value, 0) - self._tabular_legendre = tabular_legendre - - @temperature.setter - def temperature(self, temperature): - - cv.check_type('temperature settings', temperature, Mapping) - for key, value in temperature.items(): - cv.check_value('temperature key', key, - ['default', 'method', 'tolerance', 'multipole', - 'range']) - if key == 'default': - cv.check_type('default temperature', value, Real) - elif key == 'method': - cv.check_value('temperature method', value, - ['nearest', 'interpolation']) - elif key == 'tolerance': - cv.check_type('temperature tolerance', value, Real) - elif key == 'multipole': - cv.check_type('temperature multipole', value, bool) - elif key == 'range': - cv.check_length('temperature range', value, 2) - for T in value: - cv.check_type('temperature', T, Real) - - self._temperature = temperature - - @trace.setter - def trace(self, trace): - cv.check_type('trace', trace, Iterable, Integral) - cv.check_length('trace', trace, 3) - cv.check_greater_than('trace batch', trace[0], 0) - cv.check_greater_than('trace generation', trace[1], 0) - cv.check_greater_than('trace particle', trace[2], 0) - self._trace = trace - - @track.setter - def track(self, track): - cv.check_type('track', track, Iterable, Integral) - if len(track) % 3 != 0: - msg = 'Unable to set the track to "{0}" since its length is ' \ - 'not a multiple of 3'.format(track) - raise ValueError(msg) - for t in zip(track[::3], track[1::3], track[2::3]): - cv.check_greater_than('track batch', t[0], 0) - cv.check_greater_than('track generation', t[0], 0) - cv.check_greater_than('track particle', t[0], 0) - self._track = track - - @ufs_mesh.setter - def ufs_mesh(self, ufs_mesh): - cv.check_type('UFS mesh', ufs_mesh, RegularMesh) - cv.check_length('UFS mesh dimension', ufs_mesh.dimension, 3) - cv.check_length('UFS mesh lower-left corner', ufs_mesh.lower_left, 3) - cv.check_length('UFS mesh upper-right corner', ufs_mesh.upper_right, 3) - self._ufs_mesh = ufs_mesh - - @resonance_scattering.setter - def resonance_scattering(self, res): - cv.check_type('resonance scattering settings', res, Mapping) - keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides') - for key, value in res.items(): - cv.check_value('resonance scattering dictionary key', key, keys) - if key == 'enable': - cv.check_type('resonance scattering enable', value, bool) - elif key == 'method': - cv.check_value('resonance scattering method', value, - _RES_SCAT_METHODS) - elif key == 'energy_min': - name = 'resonance scattering minimum energy' - cv.check_type(name, value, Real) - cv.check_greater_than(name, value, 0) - elif key == 'energy_max': - name = 'resonance scattering minimum energy' - cv.check_type(name, value, Real) - cv.check_greater_than(name, value, 0) - elif key == 'nuclides': - cv.check_type('resonance scattering nuclides', value, - Iterable, str) - self._resonance_scattering = res - - @volume_calculations.setter - def volume_calculations(self, vol_calcs): - if not isinstance(vol_calcs, MutableSequence): - vol_calcs = [vol_calcs] - self._volume_calculations = cv.CheckedList( - VolumeCalculation, 'stochastic volume calculations', vol_calcs) - - @create_fission_neutrons.setter - def create_fission_neutrons(self, create_fission_neutrons): - cv.check_type('Whether create fission neutrons', - create_fission_neutrons, bool) - self._create_fission_neutrons = create_fission_neutrons - - @log_grid_bins.setter - def log_grid_bins(self, log_grid_bins): - cv.check_type('log grid bins', log_grid_bins, Real) - cv.check_greater_than('log grid bins', log_grid_bins, 0) - self._log_grid_bins = log_grid_bins - - def _create_run_mode_subelement(self, root): - elem = ET.SubElement(root, "run_mode") - elem.text = self._run_mode - - def _create_batches_subelement(self, root): - if self._batches is not None: - element = ET.SubElement(root, "batches") - element.text = str(self._batches) - - def _create_generations_per_batch_subelement(self, root): - if self._generations_per_batch is not None: - element = ET.SubElement(root, "generations_per_batch") - element.text = str(self._generations_per_batch) - - def _create_inactive_subelement(self, root): - if self._inactive is not None: - element = ET.SubElement(root, "inactive") - element.text = str(self._inactive) - - def _create_particles_subelement(self, root): - if self._particles is not None: - element = ET.SubElement(root, "particles") - element.text = str(self._particles) - - def _create_keff_trigger_subelement(self, root): - if self._keff_trigger is not None: - element = ET.SubElement(root, "keff_trigger") - - for key in self._keff_trigger: - subelement = ET.SubElement(element, key) - subelement.text = str(self._keff_trigger[key]).lower() - - def _create_energy_mode_subelement(self, root): - if self._energy_mode is not None: - element = ET.SubElement(root, "energy_mode") - element.text = str(self._energy_mode) - - def _create_max_order_subelement(self, root): - if self._max_order is not None: - element = ET.SubElement(root, "max_order") - element.text = str(self._max_order) - - def _create_source_subelement(self, root): - for source in self.source: - root.append(source.to_xml_element()) - - def _create_volume_calcs_subelement(self, root): - for calc in self.volume_calculations: - root.append(calc.to_xml_element()) - - def _create_output_subelement(self, root): - if self._output is not None: - element = ET.SubElement(root, "output") - - for key, value in self._output.items(): - subelement = ET.SubElement(element, key) - if key in ('summary', 'tallies'): - subelement.text = str(value).lower() - else: - subelement.text = value - - def _create_verbosity_subelement(self, root): - if self._verbosity is not None: - element = ET.SubElement(root, "verbosity") - element.text = str(self._verbosity) - - def _create_statepoint_subelement(self, root): - if self._statepoint: - element = ET.SubElement(root, "state_point") - if 'batches' in self._statepoint: - subelement = ET.SubElement(element, "batches") - subelement.text = ' '.join( - str(x) for x in self._statepoint['batches']) - - def _create_sourcepoint_subelement(self, root): - if self._sourcepoint: - element = ET.SubElement(root, "source_point") - - if 'batches' in self._sourcepoint: - subelement = ET.SubElement(element, "batches") - subelement.text = ' '.join( - str(x) for x in self._sourcepoint['batches']) - - if 'separate' in self._sourcepoint: - subelement = ET.SubElement(element, "separate") - subelement.text = str(self._sourcepoint['separate']).lower() - - if 'write' in self._sourcepoint: - subelement = ET.SubElement(element, "write") - subelement.text = str(self._sourcepoint['write']).lower() - - # Overwrite latest subelement - if 'overwrite' in self._sourcepoint: - subelement = ET.SubElement(element, "overwrite_latest") - subelement.text = str(self._sourcepoint['overwrite']).lower() - - def _create_confidence_intervals(self, root): - if self._confidence_intervals is not None: - element = ET.SubElement(root, "confidence_intervals") - element.text = str(self._confidence_intervals).lower() - - def _create_electron_treatment_subelement(self, root): - if self._electron_treatment is not None: - element = ET.SubElement(root, "electron_treatment") - element.text = str(self._electron_treatment) - - def _create_photon_transport_subelement(self, root): - if self._photon_transport is not None: - element = ET.SubElement(root, "photon_transport") - element.text = str(self._photon_transport).lower() - - def _create_ptables_subelement(self, root): - if self._ptables is not None: - element = ET.SubElement(root, "ptables") - element.text = str(self._ptables).lower() - - def _create_seed_subelement(self, root): - if self._seed is not None: - element = ET.SubElement(root, "seed") - element.text = str(self._seed) - - def _create_survival_biasing_subelement(self, root): - if self._survival_biasing is not None: - element = ET.SubElement(root, "survival_biasing") - element.text = str(self._survival_biasing).lower() - - def _create_cutoff_subelement(self, root): - if self._cutoff is not None: - element = ET.SubElement(root, "cutoff") - for key, value in self._cutoff.items(): - subelement = ET.SubElement(element, key) - subelement.text = str(value) - - def _create_entropy_mesh_subelement(self, root): - if self.entropy_mesh is not None: - # See if a element already exists -- if not, add it - path = "./mesh[@id='{}']".format(self.entropy_mesh.id) - if root.find(path) is None: - root.append(self.entropy_mesh.to_xml_element()) - - subelement = ET.SubElement(root, "entropy_mesh") - subelement.text = str(self.entropy_mesh.id) - - def _create_trigger_subelement(self, root): - if self._trigger_active is not None: - trigger_element = ET.SubElement(root, "trigger") - element = ET.SubElement(trigger_element, "active") - element.text = str(self._trigger_active).lower() - - if self._trigger_max_batches is not None: - element = ET.SubElement(trigger_element, "max_batches") - element.text = str(self._trigger_max_batches) - - if self._trigger_batch_interval is not None: - element = ET.SubElement(trigger_element, "batch_interval") - element.text = str(self._trigger_batch_interval) - - def _create_no_reduce_subelement(self, root): - if self._no_reduce is not None: - element = ET.SubElement(root, "no_reduce") - element.text = str(self._no_reduce).lower() - - def _create_tabular_legendre_subelements(self, root): - if self.tabular_legendre: - element = ET.SubElement(root, "tabular_legendre") - subelement = ET.SubElement(element, "enable") - subelement.text = str(self._tabular_legendre['enable']).lower() - if 'num_points' in self._tabular_legendre: - subelement = ET.SubElement(element, "num_points") - subelement.text = str(self._tabular_legendre['num_points']) - - def _create_temperature_subelements(self, root): - if self.temperature: - for key, value in sorted(self.temperature.items()): - element = ET.SubElement(root, - "temperature_{}".format(key)) - if isinstance(value, bool): - element.text = str(value).lower() - elif key == 'range': - element.text = ' '.join(str(T) for T in value) - else: - element.text = str(value) - - def _create_trace_subelement(self, root): - if self._trace is not None: - element = ET.SubElement(root, "trace") - element.text = ' '.join(map(str, self._trace)) - - def _create_track_subelement(self, root): - if self._track is not None: - element = ET.SubElement(root, "track") - element.text = ' '.join(map(str, self._track)) - - def _create_ufs_mesh_subelement(self, root): - if self.ufs_mesh is not None: - # See if a element already exists -- if not, add it - path = "./mesh[@id='{}']".format(self.ufs_mesh.id) - if root.find(path) is None: - root.append(self.ufs_mesh.to_xml_element()) - - subelement = ET.SubElement(root, "ufs_mesh") - subelement.text = str(self.ufs_mesh.id) - - def _create_resonance_scattering_subelement(self, root): - res = self.resonance_scattering - if res: - elem = ET.SubElement(root, 'resonance_scattering') - if 'enable' in res: - subelem = ET.SubElement(elem, 'enable') - subelem.text = str(res['enable']).lower() - if 'method' in res: - subelem = ET.SubElement(elem, 'method') - subelem.text = res['method'] - if 'energy_min' in res: - subelem = ET.SubElement(elem, 'energy_min') - subelem.text = str(res['energy_min']) - if 'energy_max' in res: - subelem = ET.SubElement(elem, 'energy_max') - subelem.text = str(res['energy_max']) - if 'nuclides' in res: - subelem = ET.SubElement(elem, 'nuclides') - subelem.text = ' '.join(res['nuclides']) - - def _create_create_fission_neutrons_subelement(self, root): - if self._create_fission_neutrons is not None: - elem = ET.SubElement(root, "create_fission_neutrons") - elem.text = str(self._create_fission_neutrons).lower() - - def _create_log_grid_bins_subelement(self, root): - if self._log_grid_bins is not None: - elem = ET.SubElement(root, "log_grid_bins") - elem.text = str(self._log_grid_bins) - - def _create_dagmc_subelement(self, root): - if self._dagmc: - elem = ET.SubElement(root, "dagmc") - elem.text = str(self._dagmc).lower() - - def _eigenvalue_from_xml_element(self, root): - elem = root.find('eigenvalue') - if elem is not None: - self._run_mode_from_xml_element(elem) - self._particles_from_xml_element(elem) - self._batches_from_xml_element(elem) - self._inactive_from_xml_element(elem) - self._generations_per_batch_from_xml_element(elem) - - def _run_mode_from_xml_element(self, root): - text = get_text(root, 'run_mode') - if text is not None: - self.run_mode = text - - def _particles_from_xml_element(self, root): - text = get_text(root, 'particles') - if text is not None: - self.particles = int(text) - - def _batches_from_xml_element(self, root): - text = get_text(root, 'batches') - if text is not None: - self.batches = int(text) - - def _inactive_from_xml_element(self, root): - text = get_text(root, 'inactive') - if text is not None: - self.inactive = int(text) - - def _generations_per_batch_from_xml_element(self, root): - text = get_text(root, 'generations_per_batch') - if text is not None: - self.generations_per_batch = int(text) - - def _keff_trigger_from_xml_element(self, root): - elem = root.find('keff_trigger') - if elem is not None: - trigger = get_text(elem, 'type') - threshold = float(get_text(elem, 'threshold')) - self.keff_trigger = {'type': trigger, 'threshold': threshold} - - def _source_from_xml_element(self, root): - for elem in root.findall('source'): - self.source.append(Source.from_xml_element(elem)) - - def _output_from_xml_element(self, root): - elem = root.find('output') - if elem is not None: - self.output = {} - for key in ('summary', 'tallies', 'path'): - value = get_text(elem, key) - if value is not None: - if key in ('summary', 'tallies'): - value = value in ('true', '1') - self.output[key] = value - - def _statepoint_from_xml_element(self, root): - elem = root.find('state_point') - if elem is not None: - text = get_text(elem, 'batches') - if text is not None: - self.statepoint['batches'] = [int(x) for x in text.split()] - - def _sourcepoint_from_xml_element(self, root): - elem = root.find('source_point') - if elem is not None: - for key in ('separate', 'write', 'overwrite_latest', 'batches'): - value = get_text(elem, key) - if value is not None: - if key in ('separate', 'write'): - value = value in ('true', '1') - elif key == 'overwrite_latest': - value = value in ('true', '1') - key = 'overwrite' - else: - value = [int(x) for x in value.split()] - self.sourcepoint[key] = value - - def _confidence_intervals_from_xml_element(self, root): - text = get_text(root, 'confidence_intervals') - if text is not None: - self.confidence_intervals = text in ('true', '1') - - def _electron_treatment_from_xml_element(self, root): - text = get_text(root, 'electron_treatment') - if text is not None: - self.electron_treatment = text - - def _energy_mode_from_xml_element(self, root): - text = get_text(root, 'energy_mode') - if text is not None: - self.energy_mode = text - - def _max_order_from_xml_element(self, root): - text = get_text(root, 'max_order') - if text is not None: - self.max_order = int(text) - - def _photon_transport_from_xml_element(self, root): - text = get_text(root, 'photon_transport') - if text is not None: - self.photon_transport = text in ('true', '1') - - def _ptables_from_xml_element(self, root): - text = get_text(root, 'ptables') - if text is not None: - self.ptables = text in ('true', '1') - - def _seed_from_xml_element(self, root): - text = get_text(root, 'seed') - if text is not None: - self.seed = int(text) - - def _survival_biasing_from_xml_element(self, root): - text = get_text(root, 'survival_biasing') - if text is not None: - self.survival_biasing = text in ('true', '1') - - def _cutoff_from_xml_element(self, root): - elem = root.find('cutoff') - if elem is not None: - self.cutoff = {} - for key in ('energy_neutron', 'energy_photon', 'energy_electron', - 'energy_positron', 'weight', 'weight_avg'): - value = get_text(elem, key) - if value is not None: - self.cutoff[key] = float(value) - - def _entropy_mesh_from_xml_element(self, root): - text = get_text(root, 'entropy_mesh') - if text is not None: - path = "./mesh[@id='{}']".format(int(text)) - elem = root.find(path) - if elem is not None: - self.entropy_mesh = RegularMesh.from_xml_element(elem) - - def _trigger_from_xml_element(self, root): - elem = root.find('trigger') - if elem is not None: - self.trigger_active = get_text(elem, 'active') in ('true', '1') - text = get_text(elem, 'max_batches') - if text is not None: - self.trigger_max_batches = int(text) - text = get_text(elem, 'batch_interval') - if text is not None: - self.trigger_batch_interval = int(text) - - def _no_reduce_from_xml_element(self, root): - text = get_text(root, 'no_reduce') - if text is not None: - self.no_reduce = text in ('true', '1') - - def _verbosity_from_xml_element(self, root): - text = get_text(root, 'verbosity') - if text is not None: - self.verbosity = int(text) - - def _tabular_legendre_from_xml_element(self, root): - elem = root.find('tabular_legendre') - if elem is not None: - text = get_text(elem, 'enable') - self.tabular_legendre['enable'] = text in ('true', '1') - text = get_text(elem, 'num_points') - if text is not None: - self.tabular_legendre['num_points'] = int(text) - - def _temperature_from_xml_element(self, root): - text = get_text(root, 'temperature_default') - if text is not None: - self.temperature['default'] = float(text) - text = get_text(root, 'temperature_tolerance') - if text is not None: - self.temperature['tolerance'] = float(text) - text = get_text(root, 'temperature_method') - if text is not None: - self.temperature['method'] = text - text = get_text(root, 'temperature_range') - if text is not None: - self.temperature['range'] = [float(x) for x in text.split()] - text = get_text(root, 'temperature_multipole') - if text is not None: - self.temperature['multipole'] = text in ('true', '1') - - def _trace_from_xml_element(self, root): - text = get_text(root, 'trace') - if text is not None: - self.trace = [int(x) for x in text.split()] - - def _track_from_xml_element(self, root): - text = get_text(root, 'track') - if text is not None: - self.track = [int(x) for x in text.split()] - - def _ufs_mesh_from_xml_element(self, root): - text = get_text(root, 'ufs_mesh') - if text is not None: - path = "./mesh[@id='{}']".format(int(text)) - elem = root.find(path) - if elem is not None: - self.ufs_mesh = RegularMesh.from_xml_element(elem) - - def _resonance_scattering_from_xml_element(self, root): - elem = root.find('resonance_scattering') - if elem is not None: - keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides') - for key in keys: - value = get_text(elem, key) - if value is not None: - if key == 'enable': - value = value in ('true', '1') - elif key in ('energy_min', 'energy_max'): - value = float(value) - elif key == 'nuclides': - value = value.split() - self.resonance_scattering[key] = value - - def _create_fission_neutrons_from_xml_element(self, root): - text = get_text(root, 'create_fission_neutrons') - if text is not None: - self.create_fission_neutrons = text in ('true', '1') - - def _log_grid_bins_from_xml_element(self, root): - text = get_text(root, 'log_grid_bins') - if text is not None: - self.log_grid_bins = int(text) - - def _dagmc_from_xml_element(self, root): - text = get_text(root, 'dagmc') - if text is not None: - self.dagmc = text in ('true', '1') - - def export_to_xml(self, path='settings.xml'): - """Export simulation settings to an XML file. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'settings.xml'. - - """ - - # Reset xml element tree - root_element = ET.Element("settings") - - self._create_run_mode_subelement(root_element) - self._create_particles_subelement(root_element) - self._create_batches_subelement(root_element) - self._create_inactive_subelement(root_element) - self._create_generations_per_batch_subelement(root_element) - self._create_keff_trigger_subelement(root_element) - self._create_source_subelement(root_element) - self._create_output_subelement(root_element) - self._create_statepoint_subelement(root_element) - self._create_sourcepoint_subelement(root_element) - self._create_confidence_intervals(root_element) - self._create_electron_treatment_subelement(root_element) - self._create_energy_mode_subelement(root_element) - self._create_max_order_subelement(root_element) - self._create_photon_transport_subelement(root_element) - self._create_ptables_subelement(root_element) - self._create_seed_subelement(root_element) - self._create_survival_biasing_subelement(root_element) - self._create_cutoff_subelement(root_element) - self._create_entropy_mesh_subelement(root_element) - self._create_trigger_subelement(root_element) - self._create_no_reduce_subelement(root_element) - self._create_verbosity_subelement(root_element) - self._create_tabular_legendre_subelements(root_element) - self._create_temperature_subelements(root_element) - self._create_trace_subelement(root_element) - self._create_track_subelement(root_element) - self._create_ufs_mesh_subelement(root_element) - self._create_resonance_scattering_subelement(root_element) - self._create_volume_calcs_subelement(root_element) - self._create_create_fission_neutrons_subelement(root_element) - self._create_log_grid_bins_subelement(root_element) - self._create_dagmc_subelement(root_element) - - # Clean the indentation in the file to be user-readable - clean_indentation(root_element) - - # Check if path is a directory - p = Path(path) - if p.is_dir(): - p /= 'settings.xml' - - # Write the XML Tree to the settings.xml file - tree = ET.ElementTree(root_element) - tree.write(str(p), xml_declaration=True, encoding='utf-8') - - @classmethod - def from_xml(cls, path='settings.xml'): - """Generate settings from XML file - - Parameters - ---------- - path : str, optional - Path to settings XML file - - Returns - ------- - openmc.Settings - Settings object - - """ - tree = ET.parse(path) - root = tree.getroot() - - settings = cls() - settings._eigenvalue_from_xml_element(root) - settings._run_mode_from_xml_element(root) - settings._particles_from_xml_element(root) - settings._batches_from_xml_element(root) - settings._inactive_from_xml_element(root) - settings._generations_per_batch_from_xml_element(root) - settings._keff_trigger_from_xml_element(root) - settings._source_from_xml_element(root) - settings._output_from_xml_element(root) - settings._statepoint_from_xml_element(root) - settings._sourcepoint_from_xml_element(root) - settings._confidence_intervals_from_xml_element(root) - settings._electron_treatment_from_xml_element(root) - settings._energy_mode_from_xml_element(root) - settings._max_order_from_xml_element(root) - settings._photon_transport_from_xml_element(root) - settings._ptables_from_xml_element(root) - settings._seed_from_xml_element(root) - settings._survival_biasing_from_xml_element(root) - settings._cutoff_from_xml_element(root) - settings._entropy_mesh_from_xml_element(root) - settings._trigger_from_xml_element(root) - settings._no_reduce_from_xml_element(root) - settings._verbosity_from_xml_element(root) - settings._tabular_legendre_from_xml_element(root) - settings._temperature_from_xml_element(root) - settings._trace_from_xml_element(root) - settings._track_from_xml_element(root) - settings._ufs_mesh_from_xml_element(root) - settings._resonance_scattering_from_xml_element(root) - settings._create_fission_neutrons_from_xml_element(root) - settings._log_grid_bins_from_xml_element(root) - settings._dagmc_from_xml_element(root) - - # TODO: Get volume calculations - - return settings diff --git a/openmc/source.py b/openmc/source.py deleted file mode 100644 index 88c2f8611..000000000 --- a/openmc/source.py +++ /dev/null @@ -1,183 +0,0 @@ -from numbers import Real -import sys -from xml.etree import ElementTree as ET - -from openmc._xml import get_text -from openmc.stats.univariate import Univariate -from openmc.stats.multivariate import UnitSphere, Spatial -import openmc.checkvalue as cv - - -class Source(object): - """Distribution of phase space coordinates for source sites. - - Parameters - ---------- - space : openmc.stats.Spatial, optional - Spatial distribution of source sites - angle : openmc.stats.UnitSphere, optional - Angular distribution of source sites - energy : openmc.stats.Univariate, optional - Energy distribution of source sites - filename : str, optional - Source file from which sites should be sampled - strength : Real - Strength of the source - particle : {'neutron', 'photon'} - Source particle type - - Attributes - ---------- - space : openmc.stats.Spatial or None - Spatial distribution of source sites - angle : openmc.stats.UnitSphere or None - Angular distribution of source sites - energy : openmc.stats.Univariate or None - Energy distribution of source sites - file : str or None - Source file from which sites should be sampled - strength : Real - Strength of the source - particle : {'neutron', 'photon'} - Source particle type - - """ - - def __init__(self, space=None, angle=None, energy=None, filename=None, - strength=1.0, particle='neutron'): - self._space = None - self._angle = None - self._energy = None - self._file = None - - if space is not None: - self.space = space - if angle is not None: - self.angle = angle - if energy is not None: - self.energy = energy - if filename is not None: - self.file = filename - self.strength = strength - self.particle = particle - - @property - def file(self): - return self._file - - @property - def space(self): - return self._space - - @property - def angle(self): - return self._angle - - @property - def energy(self): - return self._energy - - @property - def strength(self): - return self._strength - - @property - def particle(self): - return self._particle - - @file.setter - def file(self, filename): - cv.check_type('source file', filename, str) - self._file = filename - - @space.setter - def space(self, space): - cv.check_type('spatial distribution', space, Spatial) - self._space = space - - @angle.setter - def angle(self, angle): - cv.check_type('angular distribution', angle, UnitSphere) - self._angle = angle - - @energy.setter - def energy(self, energy): - cv.check_type('energy distribution', energy, Univariate) - self._energy = energy - - @strength.setter - def strength(self, strength): - cv.check_type('source strength', strength, Real) - cv.check_greater_than('source strength', strength, 0.0, True) - self._strength = strength - - @particle.setter - def particle(self, particle): - cv.check_value('source particle', particle, ['neutron', 'photon']) - self._particle = particle - - def to_xml_element(self): - """Return XML representation of the source - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing source data - - """ - element = ET.Element("source") - element.set("strength", str(self.strength)) - if self.particle != 'neutron': - element.set("particle", self.particle) - if self.file is not None: - element.set("file", self.file) - if self.space is not None: - element.append(self.space.to_xml_element()) - if self.angle is not None: - element.append(self.angle.to_xml_element()) - if self.energy is not None: - element.append(self.energy.to_xml_element('energy')) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate source from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.Source - Source generated from XML element - - """ - source = cls() - - strength = get_text(elem, 'strength') - if strength is not None: - source.strength = float(strength) - - particle = get_text(elem, 'particle') - if particle is not None: - source.particle = particle - - filename = get_text(elem, 'file') - if filename is not None: - source.file = filename - - space = elem.find('space') - if space is not None: - source.space = Spatial.from_xml_element(space) - - angle = elem.find('angle') - if angle is not None: - source.angle = UnitSphere.from_xml_element(angle) - - energy = elem.find('energy') - if energy is not None: - source.energy = Univariate.from_xml_element(energy) - - return source diff --git a/openmc/statepoint.py b/openmc/statepoint.py deleted file mode 100644 index 5802a74ca..000000000 --- a/openmc/statepoint.py +++ /dev/null @@ -1,689 +0,0 @@ -from datetime import datetime -import re -import os -import warnings -import glob - -import numpy as np -import h5py -from uncertainties import ufloat - -import openmc -import openmc.checkvalue as cv - -_VERSION_STATEPOINT = 17 - - -class StatePoint(object): - """State information on a simulation at a certain point in time (at the end - of a given batch). Statepoints can be used to analyze tally results as well - as restart a simulation. - - Parameters - ---------- - filename : str - Path to file to load - autolink : bool, optional - Whether to automatically link in metadata from a summary.h5 file and - stochastic volume calculation results from volume_*.h5 files. Defaults - to True. - - Attributes - ---------- - cmfd_on : bool - Indicate whether CMFD is active - cmfd_balance : numpy.ndarray - Residual neutron balance for each batch - cmfd_dominance - Dominance ratio for each batch - cmfd_entropy : numpy.ndarray - Shannon entropy of CMFD fission source for each batch - cmfd_indices : numpy.ndarray - Number of CMFD mesh cells and energy groups. The first three indices - correspond to the x-, y-, and z- spatial directions and the fourth index - is the number of energy groups. - cmfd_srccmp : numpy.ndarray - Root-mean-square difference between OpenMC and CMFD fission source for - each batch - cmfd_src : numpy.ndarray - CMFD fission source distribution over all mesh cells and energy groups. - current_batch : int - Number of batches simulated - date_and_time : datetime.datetime - Date and time at which statepoint was written - entropy : numpy.ndarray - Shannon entropy of fission source at each batch - filters : dict - Dictionary whose keys are filter IDs and whose values are Filter - objects - generations_per_batch : int - Number of fission generations per batch - global_tallies : numpy.ndarray of compound datatype - Global tallies for k-effective estimates and leakage. The compound - datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'. - k_combined : uncertainties.UFloat - Combined estimator for k-effective - k_col_abs : float - Cross-product of collision and absorption estimates of k-effective - k_col_tra : float - Cross-product of collision and tracklength estimates of k-effective - k_abs_tra : float - Cross-product of absorption and tracklength estimates of k-effective - k_generation : numpy.ndarray - Estimate of k-effective for each batch/generation - meshes : dict - Dictionary whose keys are mesh IDs and whose values are MeshBase objects - n_batches : int - Number of batches - n_inactive : int - Number of inactive batches - n_particles : int - Number of particles per generation - n_realizations : int - Number of tally realizations - path : str - Working directory for simulation - photon_transport : bool - Indicate whether photon transport is active - run_mode : str - Simulation run mode, e.g. 'eigenvalue' - runtime : dict - Dictionary whose keys are strings describing various runtime metrics - and whose values are time values in seconds. - seed : int - Pseudorandom number generator seed - source : numpy.ndarray of compound datatype - Array of source sites. The compound datatype has fields 'wgt', 'xyz', - 'uvw', and 'E' corresponding to the weight, position, direction, and - energy of the source site. - source_present : bool - Indicate whether source sites are present - sparse : bool - Whether or not the tallies uses SciPy's LIL sparse matrix format for - compressed data storage - tallies : dict - Dictionary whose keys are tally IDs and whose values are Tally objects - tallies_present : bool - Indicate whether user-defined tallies are present - tally_derivatives : dict - Dictionary whose keys are tally derivative IDs and whose values are - TallyDerivative objects - version: tuple of Integral - Version of OpenMC - summary : None or openmc.Summary - A summary object if the statepoint has been linked with a summary file - - """ - - def __init__(self, filename, autolink=True): - self._f = h5py.File(filename, 'r') - self._meshes = {} - self._filters = {} - self._tallies = {} - self._derivs = {} - - # Check filetype and version - cv.check_filetype_version(self._f, 'statepoint', _VERSION_STATEPOINT) - - # Set flags for what data has been read - self._meshes_read = False - self._filters_read = False - self._tallies_read = False - self._summary = None - self._global_tallies = None - self._sparse = False - self._derivs_read = False - - # Automatically link in a summary file if one exists - if autolink: - path_summary = os.path.join(os.path.dirname(filename), 'summary.h5') - if os.path.exists(path_summary): - su = openmc.Summary(path_summary) - self.link_with_summary(su) - - path_volume = os.path.join(os.path.dirname(filename), 'volume_*.h5') - for path_i in glob.glob(path_volume): - if re.search(r'volume_\d+\.h5', path_i): - vol = openmc.VolumeCalculation.from_hdf5(path_i) - self.add_volume_information(vol) - - def __enter__(self): - return self - - def __exit__(self, *exc): - self._f.close() - if self._summary is not None: - self._summary._f.close() - - @property - def cmfd_on(self): - return self._f.attrs['cmfd_on'] > 0 - - @property - def cmfd_balance(self): - return self._f['cmfd/cmfd_balance'][()] if self.cmfd_on else None - - @property - def cmfd_dominance(self): - return self._f['cmfd/cmfd_dominance'][()] if self.cmfd_on else None - - @property - def cmfd_entropy(self): - return self._f['cmfd/cmfd_entropy'][()] if self.cmfd_on else None - - @property - def cmfd_indices(self): - return self._f['cmfd/indices'][()] if self.cmfd_on else None - - @property - def cmfd_src(self): - if self.cmfd_on: - data = self._f['cmfd/cmfd_src'][()] - return np.reshape(data, tuple(self.cmfd_indices), order='F') - else: - return None - - @property - def cmfd_srccmp(self): - return self._f['cmfd/cmfd_srccmp'][()] if self.cmfd_on else None - - @property - def current_batch(self): - return self._f['current_batch'][()] - - @property - def date_and_time(self): - s = self._f.attrs['date_and_time'].decode() - return datetime.strptime(s, '%Y-%m-%d %H:%M:%S') - - @property - def entropy(self): - if self.run_mode == 'eigenvalue': - return self._f['entropy'][()] - else: - return None - - @property - def filters(self): - if not self._filters_read: - filters_group = self._f['tallies/filters'] - - # Iterate over all Filters - for group in filters_group.values(): - new_filter = openmc.Filter.from_hdf5(group, meshes=self.meshes) - self._filters[new_filter.id] = new_filter - - self._filters_read = True - - return self._filters - - @property - def generations_per_batch(self): - if self.run_mode == 'eigenvalue': - return self._f['generations_per_batch'][()] - else: - return None - - @property - def global_tallies(self): - if self._global_tallies is None: - data = self._f['global_tallies'][()] - gt = np.zeros(data.shape[0], dtype=[ - ('name', 'a14'), ('sum', 'f8'), ('sum_sq', 'f8'), - ('mean', 'f8'), ('std_dev', 'f8')]) - gt['name'] = ['k-collision', 'k-absorption', 'k-tracklength', - 'leakage'] - gt['sum'] = data[:,1] - gt['sum_sq'] = data[:,2] - - # Calculate mean and sample standard deviation of mean - n = self.n_realizations - gt['mean'] = gt['sum']/n - gt['std_dev'] = np.sqrt((gt['sum_sq']/n - gt['mean']**2)/(n - 1)) - - self._global_tallies = gt - - return self._global_tallies - - @property - def k_cmfd(self): - if self.cmfd_on: - return self._f['cmfd/k_cmfd'][()] - else: - return None - - @property - def k_generation(self): - if self.run_mode == 'eigenvalue': - return self._f['k_generation'][()] - else: - return None - - @property - def k_combined(self): - if self.run_mode == 'eigenvalue': - return ufloat(*self._f['k_combined'][()]) - else: - return None - - @property - def k_col_abs(self): - if self.run_mode == 'eigenvalue': - return self._f['k_col_abs'][()] - else: - return None - - @property - def k_col_tra(self): - if self.run_mode == 'eigenvalue': - return self._f['k_col_tra'][()] - else: - return None - - @property - def k_abs_tra(self): - if self.run_mode == 'eigenvalue': - return self._f['k_abs_tra'][()] - else: - return None - - @property - def meshes(self): - if not self._meshes_read: - mesh_group = self._f['tallies/meshes'] - - # Iterate over all meshes - for group in mesh_group.values(): - mesh = openmc.MeshBase.from_hdf5(group) - self._meshes[mesh.id] = mesh - - self._meshes_read = True - - return self._meshes - - @property - def n_batches(self): - return self._f['n_batches'][()] - - @property - def n_inactive(self): - if self.run_mode == 'eigenvalue': - return self._f['n_inactive'][()] - else: - return None - - @property - def n_particles(self): - return self._f['n_particles'][()] - - @property - def n_realizations(self): - return self._f['n_realizations'][()] - - @property - def path(self): - return self._f.attrs['path'].decode() - - @property - def photon_transport(self): - return self._f.attrs['photon_transport'] > 0 - - @property - def run_mode(self): - return self._f['run_mode'][()].decode() - - @property - def runtime(self): - return {name: dataset[()] - for name, dataset in self._f['runtime'].items()} - - @property - def seed(self): - return self._f['seed'][()] - - @property - def source(self): - return self._f['source_bank'][()] if self.source_present else None - - @property - def source_present(self): - return self._f.attrs['source_present'] > 0 - - @property - def sparse(self): - return self._sparse - - @property - def tallies(self): - if self.tallies_present and not self._tallies_read: - # Read the number of tallies - tallies_group = self._f['tallies'] - n_tallies = tallies_group.attrs['n_tallies'] - - # Read a list of the IDs for each Tally - if n_tallies > 0: - # Tally user-defined IDs - tally_ids = tallies_group.attrs['ids'] - else: - tally_ids = [] - - # Ignore warnings about duplicate IDs - with warnings.catch_warnings(): - warnings.simplefilter('ignore', openmc.IDWarning) - - # Iterate over all tallies - for tally_id in tally_ids: - group = tallies_group['tally {}'.format(tally_id)] - - # Check if tally is internal and therefore has no data - if group.attrs.get("internal"): - continue - - # Create Tally object and assign basic properties - tally = openmc.Tally(tally_id) - tally._sp_filename = self._f.filename - tally.name = group['name'][()].decode() if 'name' in group else '' - - # Read the number of realizations - n_realizations = group['n_realizations'][()] - - tally.estimator = group['estimator'][()].decode() - tally.num_realizations = n_realizations - - # Read derivative information. - if 'derivative' in group: - deriv_id = group['derivative'][()] - tally.derivative = self.tally_derivatives[deriv_id] - - # Read all filters - n_filters = group['n_filters'][()] - if n_filters > 0: - filter_ids = group['filters'][()] - filters_group = self._f['tallies/filters'] - for filter_id in filter_ids: - filter_group = filters_group['filter {}'.format( - filter_id)] - new_filter = openmc.Filter.from_hdf5( - filter_group, meshes=self.meshes) - tally.filters.append(new_filter) - - # Read nuclide bins - nuclide_names = group['nuclides'][()] - - # Add all nuclides to the Tally - for name in nuclide_names: - nuclide = openmc.Nuclide(name.decode().strip()) - tally.nuclides.append(nuclide) - - scores = group['score_bins'][()] - n_score_bins = group['n_score_bins'][()] - - # Add the scores to the Tally - for j, score in enumerate(scores): - score = score.decode() - - tally.scores.append(score) - - # Add Tally to the global dictionary of all Tallies - tally.sparse = self.sparse - self._tallies[tally_id] = tally - - self._tallies_read = True - - return self._tallies - - @property - def tallies_present(self): - return self._f.attrs['tallies_present'] > 0 - - @property - def tally_derivatives(self): - if not self._derivs_read: - # Populate the dictionary if any derivatives are present. - if 'derivatives' in self._f['tallies']: - # Read the derivative ids. - base = 'tallies/derivatives' - deriv_ids = [int(k.split(' ')[1]) for k in self._f[base]] - - # Create each derivative object and add it to the dictionary. - for d_id in deriv_ids: - group = self._f['tallies/derivatives/derivative {}' - .format(d_id)] - deriv = openmc.TallyDerivative(derivative_id=d_id) - deriv.variable = group['independent variable'][()].decode() - if deriv.variable == 'density': - deriv.material = group['material'][()] - elif deriv.variable == 'nuclide_density': - deriv.material = group['material'][()] - deriv.nuclide = group['nuclide'][()].decode() - elif deriv.variable == 'temperature': - deriv.material = group['material'][()] - self._derivs[d_id] = deriv - - self._derivs_read = True - - return self._derivs - - @property - def version(self): - return tuple(self._f.attrs['openmc_version']) - - @property - def summary(self): - return self._summary - - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within each Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - self._sparse = sparse - - # Update tally sparsities - if self._tallies_read: - for tally_id in self.tallies: - self.tallies[tally_id].sparse = self.sparse - - def add_volume_information(self, volume_calc): - """Add volume information to the geometry within the file - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if self.summary is not None: - self.summary.add_volume_information(volume_calc) - - def get_tally(self, scores=[], filters=[], nuclides=[], - name=None, id=None, estimator=None, exact_filters=False, - exact_nuclides=False, exact_scores=False): - """Finds and returns a Tally object with certain properties. - - This routine searches the list of Tallies and returns the first Tally - found which satisfies all of the input parameters. - - NOTE: If any of the "exact" parameters are False (default), the input - parameters do not need to match the complete Tally specification and - may only represent a subset of the Tally's properties. If an "exact" - parameter is True then number of scores, filters, or nuclides in the - parameters must precisely match those of any matching Tally. - - Parameters - ---------- - scores : list, optional - A list of one or more score strings (default is []). - filters : list, optional - A list of Filter objects (default is []). - nuclides : list, optional - A list of Nuclide objects (default is []). - name : str, optional - The name specified for the Tally (default is None). - id : Integral, optional - The id specified for the Tally (default is None). - estimator: str, optional - The type of estimator ('tracklength', 'analog'; default is None). - exact_filters : bool - If True, the number of filters in the parameters must be identical - to those in the matching Tally. If False (default), the filters in - the parameters may be a subset of those in the matching Tally. - exact_nuclides : bool - If True, the number of nuclides in the parameters must be identical - to those in the matching Tally. If False (default), the nuclides in - the parameters may be a subset of those in the matching Tally. - exact_scores : bool - If True, the number of scores in the parameters must be identical - to those in the matching Tally. If False (default), the scores - in the parameters may be a subset of those in the matching Tally. - - Returns - ------- - tally : openmc.Tally - A tally matching the specified criteria - - Raises - ------ - LookupError - If a Tally meeting all of the input parameters cannot be found in - the statepoint. - - """ - - tally = None - - # Iterate over all tallies to find the appropriate one - for test_tally in self.tallies.values(): - - # Determine if Tally has queried name - if name and name != test_tally.name: - continue - - # Determine if Tally has queried id - if id and id != test_tally.id: - continue - - # Determine if Tally has queried estimator - if estimator and estimator != test_tally.estimator: - continue - - # The number of filters, nuclides and scores must exactly match - if exact_scores and len(scores) != test_tally.num_scores: - continue - if exact_nuclides and len(nuclides) != test_tally.num_nuclides: - continue - if exact_filters and len(filters) != test_tally.num_filters: - continue - - # Determine if Tally has the queried score(s) - if scores: - contains_scores = True - - # Iterate over the scores requested by the user - for score in scores: - if score not in test_tally.scores: - contains_scores = False - break - - if not contains_scores: - continue - - # Determine if Tally has the queried Filter(s) - if filters: - contains_filters = True - - # Iterate over the Filters requested by the user - for outer_filter in filters: - contains_filters = False - - # Test if requested filter is a subset of any of the test - # tally's filters and if so continue to next filter - for inner_filter in test_tally.filters: - if inner_filter.is_subset(outer_filter): - contains_filters = True - break - - if not contains_filters: - break - - if not contains_filters: - continue - - # Determine if Tally has the queried Nuclide(s) - if nuclides: - contains_nuclides = True - - # Iterate over the Nuclides requested by the user - for nuclide in nuclides: - if nuclide not in test_tally.nuclides: - contains_nuclides = False - break - - if not contains_nuclides: - continue - - # If the current Tally met user's request, break loop and return it - tally = test_tally - break - - # If we did not find the Tally, return an error message - if tally is None: - raise LookupError('Unable to get Tally') - - return tally - - def link_with_summary(self, summary): - """Links Tallies and Filters with Summary model information. - - This routine retrieves model information (materials, geometry) from a - Summary object populated with an HDF5 'summary.h5' file and inserts it - into the Tally objects. This can be helpful when viewing and - manipulating large scale Tally data. Note that it is necessary to link - against a summary to populate the Tallies with any user-specified "name" - XML tags. - - Parameters - ---------- - summary : openmc.Summary - A Summary object. - - Raises - ------ - ValueError - An error when the argument passed to the 'summary' parameter is not - an openmc.Summary object. - - """ - - if self.summary is not None: - warnings.warn('A Summary object has already been linked.', - RuntimeWarning) - return - - if not isinstance(summary, openmc.Summary): - msg = 'Unable to link statepoint with "{0}" which ' \ - 'is not a Summary object'.format(summary) - raise ValueError(msg) - - cells = summary.geometry.get_all_cells() - - for tally_id, tally in self.tallies.items(): - tally.with_summary = True - - for tally_filter in tally.filters: - if isinstance(tally_filter, (openmc.DistribcellFilter)): - cell_id = tally_filter.bins[0] - cell = cells[cell_id] - if not cell._paths: - summary.geometry.determine_paths() - tally_filter.paths = cell.paths - - self._summary = summary diff --git a/openmc/stats/__init__.py b/openmc/stats/__init__.py deleted file mode 100644 index 3d7b80b28..000000000 --- a/openmc/stats/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from openmc.stats.univariate import * -from openmc.stats.multivariate import * diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py deleted file mode 100644 index 35afc21dd..000000000 --- a/openmc/stats/multivariate.py +++ /dev/null @@ -1,543 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections.abc import Iterable -from math import pi -from numbers import Real -import sys -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc.checkvalue as cv -from openmc._xml import get_text -from openmc.stats.univariate import Univariate, Uniform - - -class UnitSphere(metaclass=ABCMeta): - """Distribution of points on the unit sphere. - - This abstract class is used for angular distributions, since a direction is - represented as a unit vector (i.e., vector on the unit sphere). - - Parameters - ---------- - reference_uvw : Iterable of float - Direction from which polar angle is measured - - Attributes - ---------- - reference_uvw : Iterable of float - Direction from which polar angle is measured - - """ - def __init__(self, reference_uvw=None): - self._reference_uvw = None - if reference_uvw is not None: - self.reference_uvw = reference_uvw - - @property - def reference_uvw(self): - return self._reference_uvw - - @reference_uvw.setter - def reference_uvw(self, uvw): - cv.check_type('reference direction', uvw, Iterable, Real) - uvw = np.asarray(uvw) - self._reference_uvw = uvw/np.linalg.norm(uvw) - - @abstractmethod - def to_xml_element(self): - return '' - - @classmethod - @abstractmethod - def from_xml_element(cls, elem): - distribution = get_text(elem, 'type') - if distribution == 'mu-phi': - return PolarAzimuthal.from_xml_element(elem) - elif distribution == 'isotropic': - return Isotropic.from_xml_element(elem) - elif distribution == 'monodirectional': - return Monodirectional.from_xml_element(elem) - - -class PolarAzimuthal(UnitSphere): - """Angular distribution represented by polar and azimuthal angles - - This distribution allows one to specify the distribution of the cosine of - the polar angle and the azimuthal angle independently of one another. The - polar angle is measured relative to the reference angle. - - Parameters - ---------- - mu : openmc.stats.Univariate - Distribution of the cosine of the polar angle - phi : openmc.stats.Univariate - Distribution of the azimuthal angle in radians - reference_uvw : Iterable of float - Direction from which polar angle is measured. Defaults to the positive - z-direction. - - Attributes - ---------- - mu : openmc.stats.Univariate - Distribution of the cosine of the polar angle - phi : openmc.stats.Univariate - Distribution of the azimuthal angle in radians - - """ - - def __init__(self, mu=None, phi=None, reference_uvw=[0., 0., 1.]): - super().__init__(reference_uvw) - if mu is not None: - self.mu = mu - else: - self.mu = Uniform(-1., 1.) - - if phi is not None: - self.phi = phi - else: - self.phi = Uniform(0., 2*pi) - - @property - def mu(self): - return self._mu - - @property - def phi(self): - return self._phi - - @mu.setter - def mu(self, mu): - cv.check_type('cosine of polar angle', mu, Univariate) - self._mu = mu - - @phi.setter - def phi(self, phi): - cv.check_type('azimuthal angle', phi, Univariate) - self._phi = phi - - def to_xml_element(self): - """Return XML representation of the angular distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing angular distribution data - - """ - element = ET.Element('angle') - element.set("type", "mu-phi") - if self.reference_uvw is not None: - element.set("reference_uvw", ' '.join(map(str, self.reference_uvw))) - element.append(self.mu.to_xml_element('mu')) - element.append(self.phi.to_xml_element('phi')) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate angular distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.PolarAzimuthal - Angular distribution generated from XML element - - """ - mu_phi = cls() - params = get_text(elem, 'parameters') - if params is not None: - mu_phi.reference_uvw = [float(x) for x in params.split()] - mu_phi.mu = Univariate.from_xml_element(elem.find('mu')) - mu_phi.phi = Univariate.from_xml_element(elem.find('phi')) - return mu_phi - - -class Isotropic(UnitSphere): - """Isotropic angular distribution. - - """ - - def __init__(self): - super().__init__() - - def to_xml_element(self): - """Return XML representation of the isotropic distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing isotropic distribution data - - """ - element = ET.Element('angle') - element.set("type", "isotropic") - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate isotropic distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Isotropic - Isotropic distribution generated from XML element - - """ - return cls() - - -class Monodirectional(UnitSphere): - """Monodirectional angular distribution. - - A monodirectional angular distribution is one for which the polar and - azimuthal angles are always the same. It is completely specified by the - reference direction vector. - - Parameters - ---------- - reference_uvw : Iterable of float - Direction from which polar angle is measured. Defaults to the positive - x-direction. - - """ - - - def __init__(self, reference_uvw=[1., 0., 0.]): - super().__init__(reference_uvw) - - def to_xml_element(self): - """Return XML representation of the monodirectional distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing monodirectional distribution data - - """ - element = ET.Element('angle') - element.set("type", "monodirectional") - if self.reference_uvw is not None: - element.set("reference_uvw", ' '.join(map(str, self.reference_uvw))) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate monodirectional distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Monodirectional - Monodirectional distribution generated from XML element - - """ - monodirectional = cls() - params = get_text(elem, 'parameters') - if params is not None: - monodirectional.reference_uvw = [float(x) for x in params.split()] - return monodirectional - - -class Spatial(metaclass=ABCMeta): - """Distribution of locations in three-dimensional Euclidean space. - - Classes derived from this abstract class can be used for spatial - distributions of source sites. - - """ - def __init__(self): - pass - - @abstractmethod - def to_xml_element(self): - return '' - - @classmethod - @abstractmethod - def from_xml_element(cls, elem): - distribution = get_text(elem, 'type') - if distribution == 'cartesian': - return CartesianIndependent.from_xml_element(elem) - elif distribution == 'box' or distribution == 'fission': - return Box.from_xml_element(elem) - elif distribution == 'point': - return Point.from_xml_element(elem) - - -class CartesianIndependent(Spatial): - """Spatial distribution with independent x, y, and z distributions. - - This distribution allows one to specify a coordinates whose x-, y-, and z- - components are sampled independently from one another. - - Parameters - ---------- - x : openmc.stats.Univariate - Distribution of x-coordinates - y : openmc.stats.Univariate - Distribution of y-coordinates - z : openmc.stats.Univariate - Distribution of z-coordinates - - Attributes - ---------- - x : openmc.stats.Univariate - Distribution of x-coordinates - y : openmc.stats.Univariate - Distribution of y-coordinates - z : openmc.stats.Univariate - Distribution of z-coordinates - - """ - - - def __init__(self, x, y, z): - super().__init__() - self.x = x - self.y = y - self.z = z - - @property - def x(self): - return self._x - - @property - def y(self): - return self._y - - @property - def z(self): - return self._z - - @x.setter - def x(self, x): - cv.check_type('x coordinate', x, Univariate) - self._x = x - - @y.setter - def y(self, y): - cv.check_type('y coordinate', y, Univariate) - self._y = y - - @z.setter - def z(self, z): - cv.check_type('z coordinate', z, Univariate) - self._z = z - - def to_xml_element(self): - """Return XML representation of the spatial distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing spatial distribution data - - """ - element = ET.Element('space') - element.set('type', 'cartesian') - element.append(self.x.to_xml_element('x')) - element.append(self.y.to_xml_element('y')) - element.append(self.z.to_xml_element('z')) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate spatial distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.CartesianIndependent - Spatial distribution generated from XML element - - """ - x = Univariate.from_xml_element(elem.find('x')) - y = Univariate.from_xml_element(elem.find('y')) - z = Univariate.from_xml_element(elem.find('z')) - return cls(x, y, z) - - -class Box(Spatial): - """Uniform distribution of coordinates in a rectangular cuboid. - - Parameters - ---------- - lower_left : Iterable of float - Lower-left coordinates of cuboid - upper_right : Iterable of float - Upper-right coordinates of cuboid - only_fissionable : bool, optional - Whether spatial sites should only be accepted if they occur in - fissionable materials - - Attributes - ---------- - lower_left : Iterable of float - Lower-left coordinates of cuboid - upper_right : Iterable of float - Upper-right coordinates of cuboid - only_fissionable : bool, optional - Whether spatial sites should only be accepted if they occur in - fissionable materials - - """ - - - def __init__(self, lower_left, upper_right, only_fissionable=False): - super().__init__() - self.lower_left = lower_left - self.upper_right = upper_right - self.only_fissionable = only_fissionable - - @property - def lower_left(self): - return self._lower_left - - @property - def upper_right(self): - return self._upper_right - - @property - def only_fissionable(self): - return self._only_fissionable - - @lower_left.setter - def lower_left(self, lower_left): - cv.check_type('lower left coordinate', lower_left, Iterable, Real) - cv.check_length('lower left coordinate', lower_left, 3) - self._lower_left = lower_left - - @upper_right.setter - def upper_right(self, upper_right): - cv.check_type('upper right coordinate', upper_right, Iterable, Real) - cv.check_length('upper right coordinate', upper_right, 3) - self._upper_right = upper_right - - @only_fissionable.setter - def only_fissionable(self, only_fissionable): - cv.check_type('only fissionable', only_fissionable, bool) - self._only_fissionable = only_fissionable - - def to_xml_element(self): - """Return XML representation of the box distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing box distribution data - - """ - element = ET.Element('space') - if self.only_fissionable: - element.set("type", "fission") - else: - element.set("type", "box") - params = ET.SubElement(element, "parameters") - params.text = ' '.join(map(str, self.lower_left)) + ' ' + \ - ' '.join(map(str, self.upper_right)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate box distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Box - Box distribution generated from XML element - - """ - only_fissionable = get_text(elem, 'type') == 'fission' - params = [float(x) for x in get_text(elem, 'parameters').split()] - lower_left = params[:len(params)//2] - upper_right = params[len(params)//2:] - return cls(lower_left, upper_right, only_fissionable) - - -class Point(Spatial): - """Delta function in three dimensions. - - This spatial distribution can be used for a point source where sites are - emitted at a specific location given by its Cartesian coordinates. - - Parameters - ---------- - xyz : Iterable of float, optional - Cartesian coordinates of location. Defaults to (0., 0., 0.). - - Attributes - ---------- - xyz : Iterable of float - Cartesian coordinates of location - - """ - - def __init__(self, xyz=(0., 0., 0.)): - super().__init__() - self.xyz = xyz - - @property - def xyz(self): - return self._xyz - - @xyz.setter - def xyz(self, xyz): - cv.check_type('coordinate', xyz, Iterable, Real) - cv.check_length('coordinate', xyz, 3) - self._xyz = xyz - - def to_xml_element(self): - """Return XML representation of the point distribution - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing point distribution location - - """ - element = ET.Element('space') - element.set("type", "point") - params = ET.SubElement(element, "parameters") - params.text = ' '.join(map(str, self.xyz)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate point distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Point - Point distribution generated from XML element - - """ - xyz = [float(x) for x in get_text(elem, 'parameters').split()] - return cls(xyz) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py deleted file mode 100644 index 363dd2ee3..000000000 --- a/openmc/stats/univariate.py +++ /dev/null @@ -1,827 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections.abc import Iterable -from numbers import Real -import sys -from xml.etree import ElementTree as ET - -import numpy as np - -import openmc.checkvalue as cv -from openmc._xml import get_text -from openmc.mixin import EqualityMixin - - -_INTERPOLATION_SCHEMES = ['histogram', 'linear-linear', 'linear-log', - 'log-linear', 'log-log'] - - -class Univariate(EqualityMixin, metaclass=ABCMeta): - """Probability distribution of a single random variable. - - The Univariate class is an abstract class that can be derived to implement a - specific probability distribution. - - """ - def __init__(self): - pass - - @abstractmethod - def to_xml_element(self, element_name): - return '' - - @abstractmethod - def __len__(self): - return 0 - - @classmethod - @abstractmethod - def from_xml_element(cls, elem): - distribution = get_text(elem, 'type') - if distribution == 'discrete': - return Discrete.from_xml_element(elem) - elif distribution == 'uniform': - return Uniform.from_xml_element(elem) - elif distribution == 'maxwell': - return Maxwell.from_xml_element(elem) - elif distribution == 'watt': - return Watt.from_xml_element(elem) - elif distribution == 'normal': - return Normal.from_xml_element(elem) - elif distribution == 'muir': - return Muir.from_xml_element(elem) - elif distribution == 'tabular': - return Tabular.from_xml_element(elem) - elif distribution == 'legendre': - return Legendre.from_xml_element(elem) - elif distribution == 'mixture': - return Mixture.from_xml_element(elem) - - -class Discrete(Univariate): - """Distribution characterized by a probability mass function. - - The Discrete distribution assigns probability values to discrete values of a - random variable, rather than expressing the distribution as a continuous - random variable. - - Parameters - ---------- - x : Iterable of float - Values of the random variable - p : Iterable of float - Discrete probability for each value - - Attributes - ---------- - x : Iterable of float - Values of the random variable - p : Iterable of float - Discrete probability for each value - - """ - - def __init__(self, x, p): - super().__init__() - self.x = x - self.p = p - - def __len__(self): - return len(self.x) - - @property - def x(self): - return self._x - - @property - def p(self): - return self._p - - @x.setter - def x(self, x): - if isinstance(x, Real): - x = [x] - cv.check_type('discrete values', x, Iterable, Real) - self._x = x - - @p.setter - def p(self, p): - if isinstance(p, Real): - p = [p] - cv.check_type('discrete probabilities', p, Iterable, Real) - for pk in p: - cv.check_greater_than('discrete probability', pk, 0.0, True) - self._p = p - - def to_xml_element(self, element_name): - """Return XML representation of the discrete distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing discrete distribution data - - """ - element = ET.Element(element_name) - element.set("type", "discrete") - - params = ET.SubElement(element, "parameters") - params.text = ' '.join(map(str, self.x)) + ' ' + ' '.join(map(str, self.p)) - - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate discrete distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Discrete - Discrete distribution generated from XML element - - """ - params = [float(x) for x in get_text(elem, 'parameters').split()] - x = params[:len(params)//2] - p = params[len(params)//2:] - return cls(x, p) - - -class Uniform(Univariate): - """Distribution with constant probability over a finite interval [a,b] - - Parameters - ---------- - a : float, optional - Lower bound of the sampling interval. Defaults to zero. - b : float, optional - Upper bound of the sampling interval. Defaults to unity. - - Attributes - ---------- - a : float - Lower bound of the sampling interval - b : float - Upper bound of the sampling interval - - """ - - def __init__(self, a=0.0, b=1.0): - super().__init__() - self.a = a - self.b = b - - def __len__(self): - return 2 - - @property - def a(self): - return self._a - - @property - def b(self): - return self._b - - @a.setter - def a(self, a): - cv.check_type('Uniform a', a, Real) - self._a = a - - @b.setter - def b(self, b): - cv.check_type('Uniform b', b, Real) - self._b = b - - def to_tabular(self): - prob = 1./(self.b - self.a) - t = Tabular([self.a, self.b], [prob, prob], 'histogram') - t.c = [0., 1.] - return t - - def to_xml_element(self, element_name): - """Return XML representation of the uniform distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing uniform distribution data - - """ - element = ET.Element(element_name) - element.set("type", "uniform") - element.set("parameters", '{} {}'.format(self.a, self.b)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate uniform distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Uniform - Uniform distribution generated from XML element - - """ - params = get_text(elem, 'parameters').split() - return cls(*map(float, params)) - - -class Maxwell(Univariate): - """Maxwellian distribution in energy. - - The Maxwellian distribution in energy is characterized by a single parameter - :math:`\theta` and has a density function :math:`p(E) dE = c E e^{-E/\theta} - dE`. - - Parameters - ---------- - theta : float - Effective temperature for distribution in eV - - Attributes - ---------- - theta : float - Effective temperature for distribution in eV - - """ - - def __init__(self, theta): - super().__init__() - self.theta = theta - - def __len__(self): - return 1 - - @property - def theta(self): - return self._theta - - @theta.setter - def theta(self, theta): - cv.check_type('Maxwell temperature', theta, Real) - cv.check_greater_than('Maxwell temperature', theta, 0.0) - self._theta = theta - - def to_xml_element(self, element_name): - """Return XML representation of the Maxwellian distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Maxwellian distribution data - - """ - element = ET.Element(element_name) - element.set("type", "maxwell") - element.set("parameters", str(self.theta)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate Maxwellian distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Maxwell - Maxwellian distribution generated from XML element - - """ - theta = float(get_text(elem, 'parameters')) - return cls(theta) - - -class Watt(Univariate): - r"""Watt fission energy spectrum. - - The Watt fission energy spectrum is characterized by two parameters - :math:`a` and :math:`b` and has density function :math:`p(E) dE = c e^{-E/a} - \sinh \sqrt{b \, E} dE`. - - Parameters - ---------- - a : float - First parameter of distribution in units of eV - b : float - Second parameter of distribution in units of 1/eV - - Attributes - ---------- - a : float - First parameter of distribution in units of eV - b : float - Second parameter of distribution in units of 1/eV - - """ - - def __init__(self, a=0.988e6, b=2.249e-6): - super().__init__() - self.a = a - self.b = b - - def __len__(self): - return 2 - - @property - def a(self): - return self._a - - @property - def b(self): - return self._b - - @a.setter - def a(self, a): - cv.check_type('Watt a', a, Real) - cv.check_greater_than('Watt a', a, 0.0) - self._a = a - - @b.setter - def b(self, b): - cv.check_type('Watt b', b, Real) - cv.check_greater_than('Watt b', b, 0.0) - self._b = b - - def to_xml_element(self, element_name): - """Return XML representation of the Watt distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Watt distribution data - - """ - element = ET.Element(element_name) - element.set("type", "watt") - element.set("parameters", '{} {}'.format(self.a, self.b)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate Watt distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Watt - Watt distribution generated from XML element - - """ - params = get_text(elem, 'parameters').split() - return cls(*map(float, params)) - - -class Normal(Univariate): - r"""Normally distributed sampling. - - The Normal Distribution is characterized by two parameters - :math:`\mu` and :math:`\sigma` and has density function - :math:`p(X) dX = 1/(\sqrt{2\pi}\sigma) e^{-(X-\mu)^2/(2\sigma^2)}` - - Parameters - ---------- - mean_value : float - Mean value of the distribution - std_dev : float - Standard deviation of the Normal distribution - - Attributes - ---------- - mean_value : float - Mean of the Normal distribution - std_dev : float - Standard deviation of the Normal distribution - """ - - def __init__(self, mean_value, std_dev): - super().__init__() - self.mean_value = mean_value - self.std_dev = std_dev - - def __len__(self): - return 2 - - @property - def mean_value(self): - return self._mean_value - - @property - def std_dev(self): - return self._std_dev - - @mean_value.setter - def mean_value(self, mean_value): - cv.check_type('Normal mean_value', mean_value, Real) - cv.check_greater_than('Normal mean_value', mean_value, 0.0) - self._mean_value = mean_value - - @std_dev.setter - def std_dev(self, std_dev): - cv.check_type('Normal std_dev', std_dev, Real) - cv.check_greater_than('Normal std_dev', std_dev, 0.0) - self._std_dev = std_dev - - def to_xml_element(self, element_name): - """Return XML representation of the Normal distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Watt distribution data - - """ - element = ET.Element(element_name) - element.set("type", "normal") - element.set("parameters", '{} {}'.format(self.mean_value, self.std_dev)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate Normal distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Normal - Normal distribution generated from XML element - - """ - params = get_text(elem, 'parameters').split() - return cls(*map(float, params)) - - -class Muir(Univariate): - """Muir energy spectrum. - - The Muir energy spectrum is a Gaussian spectrum, but for - convenience reasons allows the user 3 parameters to define - the distribution, e0 the mean energy of particles, the mass - of reactants m_rat, and the ion temperature kt. - - Parameters - ---------- - e0 : float - Mean of the Muir distribution in units of eV - m_rat : float - Ratio of the sum of the masses of the reaction inputs to an - AMU - kt : float - Ion temperature for the Muir distribution in units of eV - - Attributes - ---------- - e0 : float - Mean of the Muir distribution in units of eV - m_rat : float - Ratio of the sum of the masses of the reaction inputs to an - AMU - kt : float - Ion temperature for the Muir distribution in units of eV - - """ - - def __init__(self, e0=14.08e6, m_rat = 5., kt = 20000.): - super().__init__() - self.e0 = e0 - self.m_rat = m_rat - self.kt = kt - - def __len__(self): - return 3 - - @property - def e0(self): - return self._e0 - - @property - def m_rat(self): - return self._m_rat - - @property - def kt(self): - return self._kt - - @e0.setter - def e0(self, e0): - cv.check_type('Muir e0', e0, Real) - cv.check_greater_than('Muir e0', e0, 0.0) - self._e0 = e0 - - @m_rat.setter - def m_rat(self, m_rat): - cv.check_type('Muir m_rat', m_rat, Real) - cv.check_greater_than('Muir m_rat', m_rat, 0.0) - self._m_rat = m_rat - - @kt.setter - def kt(self, kt): - cv.check_type('Muir kt', kt, Real) - cv.check_greater_than('Muir kt', kt, 0.0) - self._kt = kt - - def to_xml_element(self, element_name): - """Return XML representation of the Watt distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing Watt distribution data - - """ - element = ET.Element(element_name) - element.set("type", "muir") - element.set("parameters", '{} {} {}'.format(self._e0, self._m_rat, self._kt)) - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate Muir distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Muir - Muir distribution generated from XML element - - """ - params = get_text(elem, 'parameters').split() - return cls(*map(float, params)) - - -class Tabular(Univariate): - """Piecewise continuous probability distribution. - - This class is used to represent a probability distribution whose density - function is tabulated at specific values with a specified interpolation - scheme. - - Parameters - ---------- - x : Iterable of float - Tabulated values of the random variable - p : Iterable of float - Tabulated probabilities - interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'}, optional - Indicate whether the density function is constant between tabulated - points or linearly-interpolated. Defaults to 'linear-linear'. - ignore_negative : bool - Ignore negative probabilities - - Attributes - ---------- - x : Iterable of float - Tabulated values of the random variable - p : Iterable of float - Tabulated probabilities - interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'}, optional - Indicate whether the density function is constant between tabulated - points or linearly-interpolated. - - """ - - def __init__(self, x, p, interpolation='linear-linear', - ignore_negative=False): - super().__init__() - self._ignore_negative = ignore_negative - self.x = x - self.p = p - self.interpolation = interpolation - - def __len__(self): - return len(self.x) - - @property - def x(self): - return self._x - - @property - def p(self): - return self._p - - @property - def interpolation(self): - return self._interpolation - - @x.setter - def x(self, x): - cv.check_type('tabulated values', x, Iterable, Real) - self._x = x - - @p.setter - def p(self, p): - cv.check_type('tabulated probabilities', p, Iterable, Real) - if not self._ignore_negative: - for pk in p: - cv.check_greater_than('tabulated probability', pk, 0.0, True) - self._p = p - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_value('interpolation', interpolation, _INTERPOLATION_SCHEMES) - self._interpolation = interpolation - - def to_xml_element(self, element_name): - """Return XML representation of the tabular distribution - - Parameters - ---------- - element_name : str - XML element name - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing tabular distribution data - - """ - element = ET.Element(element_name) - element.set("type", "tabular") - element.set("interpolation", self.interpolation) - - params = ET.SubElement(element, "parameters") - params.text = ' '.join(map(str, self.x)) + ' ' + ' '.join(map(str, self.p)) - - return element - - @classmethod - def from_xml_element(cls, elem): - """Generate tabular distribution from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.stats.Tabular - Tabular distribution generated from XML element - - """ - interpolation = get_text(elem, 'interpolation') - params = [float(x) for x in get_text(elem, 'parameters').split()] - x = params[:len(params)//2] - p = params[len(params)//2:] - return cls(x, p, interpolation) - - -class Legendre(Univariate): - r"""Probability density given by a Legendre polynomial expansion - :math:`\sum\limits_{\ell=0}^N \frac{2\ell + 1}{2} a_\ell P_\ell(\mu)`. - - Parameters - ---------- - coefficients : Iterable of Real - Expansion coefficients :math:`a_\ell`. Note that the :math:`(2\ell + - 1)/2` factor should not be included. - - Attributes - ---------- - coefficients : Iterable of Real - Expansion coefficients :math:`a_\ell`. Note that the :math:`(2\ell + - 1)/2` factor should not be included. - - """ - - def __init__(self, coefficients): - self.coefficients = coefficients - self._legendre_poly = None - - def __call__(self, x): - # Create Legendre polynomial if we haven't yet - if self._legendre_poly is None: - l = np.arange(len(self._coefficients)) - coeffs = (2.*l + 1.)/2. * self._coefficients - self._legendre_poly = np.polynomial.Legendre(coeffs) - - return self._legendre_poly(x) - - def __len__(self): - return len(self._coefficients) - - @property - def coefficients(self): - return self._coefficients - - @coefficients.setter - def coefficients(self, coefficients): - self._coefficients = np.asarray(coefficients) - - def to_xml_element(self, element_name): - raise NotImplementedError - - @classmethod - def from_xml_element(cls, elem): - raise NotImplementedError - - -class Mixture(Univariate): - """Probability distribution characterized by a mixture of random variables. - - Parameters - ---------- - probability : Iterable of Real - Probability of selecting a particular distribution - distribution : Iterable of Univariate - List of distributions with corresponding probabilities - - Attributes - ---------- - probability : Iterable of Real - Probability of selecting a particular distribution - distribution : Iterable of Univariate - List of distributions with corresponding probabilities - - """ - - def __init__(self, probability, distribution): - super().__init__() - self.probability = probability - self.distribution = distribution - - def __len__(self): - return sum(len(d) for d in self.distribution) - - @property - def probability(self): - return self._probability - - @property - def distribution(self): - return self._distribution - - @probability.setter - def probability(self, probability): - cv.check_type('mixture distribution probabilities', probability, - Iterable, Real) - for p in probability: - cv.check_greater_than('mixture distribution probabilities', - p, 0.0, True) - self._probability = probability - - @distribution.setter - def distribution(self, distribution): - cv.check_type('mixture distribution components', distribution, - Iterable, Univariate) - self._distribution = distribution - - def to_xml_element(self, element_name): - raise NotImplementedError - - @classmethod - def from_xml_element(cls, elem): - raise NotImplementedError diff --git a/openmc/summary.py b/openmc/summary.py deleted file mode 100644 index 6b8471977..000000000 --- a/openmc/summary.py +++ /dev/null @@ -1,229 +0,0 @@ -from collections.abc import Iterable -import re -import warnings - -import numpy as np -import h5py - -import openmc -import openmc.checkvalue as cv -from openmc.region import Region - -_VERSION_SUMMARY = 6 - - -class Summary(object): - """Summary of geometry, materials, and tallies used in a simulation. - - Attributes - ---------- - date_and_time : str - Date and time when simulation began - geometry : openmc.Geometry - The geometry reconstructed from the summary file - materials : openmc.Materials - The materials reconstructed from the summary file - nuclides : dict - Dictionary whose keys are nuclide names and values are atomic weight - ratios. - macroscopics : list - Names of macroscopic data sets - version: tuple of int - Version of OpenMC - - """ - - def __init__(self, filename): - if not filename.endswith(('.h5', '.hdf5')): - msg = 'Unable to open "{0}" which is not an HDF5 summary file' - raise ValueError(msg) - - self._f = h5py.File(filename, 'r') - cv.check_filetype_version(self._f, 'summary', _VERSION_SUMMARY) - - self._geometry = openmc.Geometry() - - self._fast_materials = {} - self._fast_surfaces = {} - self._fast_cells = {} - self._fast_universes = {} - self._fast_lattices = {} - - self._materials = openmc.Materials() - self._nuclides = {} - self._macroscopics = [] - - self._read_nuclides() - self._read_macroscopics() - with warnings.catch_warnings(): - warnings.simplefilter("ignore", openmc.IDWarning) - self._read_geometry() - - @property - def date_and_time(self): - return self._f.attrs['date_and_time'].decode() - - @property - def geometry(self): - return self._geometry - - @property - def materials(self): - return self._materials - - @property - def nuclides(self): - return self._nuclides - - @property - def macroscopics(self): - return self._macroscopics - - @property - def version(self): - return tuple(self._f.attrs['openmc_version']) - - def _read_nuclides(self): - if 'nuclides/names' in self._f: - names = self._f['nuclides/names'][()] - awrs = self._f['nuclides/awrs'][()] - for name, awr in zip(names, awrs): - self._nuclides[name.decode()] = awr - - def _read_macroscopics(self): - if 'macroscopics/names' in self._f: - names = self._f['macroscopics/names'][()] - for name in names: - self._macroscopics = name.decode() - - def _read_geometry(self): - - # Read in and initialize the Materials - self._read_materials() - - # Read native geometry only - if "dagmc" not in self._f['geometry'].attrs.keys(): - self._read_surfaces() - cell_fills = self._read_cells() - self._read_universes() - self._read_lattices() - self._finalize_geometry(cell_fills) - - def _read_materials(self): - for group in self._f['materials'].values(): - material = openmc.Material.from_hdf5(group) - - # Add the material to the Materials collection - self.materials.append(material) - - # Store in the dictionary of materials for fast queries - self._fast_materials[material.id] = material - - def _read_surfaces(self): - for group in self._f['geometry/surfaces'].values(): - surface = openmc.Surface.from_hdf5(group) - self._fast_surfaces[surface.id] = surface - - def _read_cells(self): - - # Initialize dictionary for each Cell's fill - cell_fills = {} - - for key, group in self._f['geometry/cells'].items(): - cell_id = int(key.lstrip('cell ')) - name = group['name'][()].decode() if 'name' in group else '' - fill_type = group['fill_type'][()].decode() - - if fill_type == 'material': - fill = group['material'][()] - elif fill_type == 'universe': - fill = group['fill'][()] - else: - fill = group['lattice'][()] - - region = group['region'][()].decode() if 'region' in group else '' - - # Create this Cell - cell = openmc.Cell(cell_id=cell_id, name=name) - - if fill_type == 'universe': - if 'translation' in group: - translation = group['translation'][()] - translation = np.asarray(translation, dtype=np.float64) - cell.translation = translation - - if 'rotation' in group: - rotation = group['rotation'][()] - rotation = np.asarray(rotation, dtype=np.int) - cell._rotation = rotation - - elif fill_type == 'material': - cell.temperature = group['temperature'][()] - - # Store Cell fill information for after Universe/Lattice creation - cell_fills[cell.id] = (fill_type, fill) - - # Generate Region object given infix expression - if region: - cell.region = Region.from_expression(region, self._fast_surfaces) - - # Add the Cell to the global dictionary of all Cells - self._fast_cells[cell.id] = cell - - return cell_fills - - def _read_universes(self): - for group in self._f['geometry/universes'].values(): - universe = openmc.Universe.from_hdf5(group, self._fast_cells) - self._fast_universes[universe.id] = universe - - def _read_lattices(self): - for group in self._f['geometry/lattices'].values(): - lattice = openmc.Lattice.from_hdf5(group, self._fast_universes) - self._fast_lattices[lattice.id] = lattice - - def _finalize_geometry(self, cell_fills): - - # Keep track of universes that are used as fills. That way, we can - # determine which universe is NOT used as a fill (and hence is the root - # universe) - fill_univ_ids = set() - - # Iterate over all Cells and add fill Materials, Universes and Lattices - for cell_id, (fill_type, fill_id) in cell_fills.items(): - # Retrieve the object corresponding to the fill type and ID - if fill_type == 'material': - if isinstance(fill_id, Iterable): - fill = [self._fast_materials[mat] if mat > 0 else None - for mat in fill_id] - else: - fill = self._fast_materials[fill_id] if fill_id > 0 else None - elif fill_type == 'universe': - fill = self._fast_universes[fill_id] - fill_univ_ids.add(fill_id) - else: - fill = self._fast_lattices[fill_id] - for idx in fill._natural_indices: - univ = fill.get_universe(idx) - fill_univ_ids.add(univ.id) - if fill.outer is not None: - fill_univ_ids.add(fill.outer.id) - - # Set the fill for the Cell - self._fast_cells[cell_id].fill = fill - - # Determine root universe for geometry - non_fill = set(self._fast_universes.keys()) - fill_univ_ids - - self.geometry.root_universe = self._fast_universes[non_fill.pop()] - - def add_volume_information(self, volume_calc): - """Add volume information to the geometry within the summary file - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - self.geometry.add_volume_information(volume_calc) diff --git a/openmc/surface.py b/openmc/surface.py deleted file mode 100644 index 2ffbf0722..000000000 --- a/openmc/surface.py +++ /dev/null @@ -1,2261 +0,0 @@ -from abc import ABCMeta, abstractmethod -from collections import OrderedDict -from copy import deepcopy -from numbers import Real, Integral -from xml.etree import ElementTree as ET -from warnings import warn - -import numpy as np - -from openmc.checkvalue import check_type, check_value -from openmc.region import Region, Intersection, Union -from openmc.mixin import IDManagerMixin - - -_BOUNDARY_TYPES = ['transmission', 'vacuum', 'reflective', 'periodic', 'white'] - -_WARNING_UPPER = """\ -"{}(...) accepts an argument named '{}', not '{}'. Future versions of OpenMC \ -will not accept the capitalized version.\ -""" - - -class Surface(IDManagerMixin, metaclass=ABCMeta): - """An implicit surface with an associated boundary condition. - - An implicit surface is defined as the set of zeros of a function of the - three Cartesian coordinates. Surfaces in OpenMC are limited to a set of - algebraic surfaces, i.e., surfaces that are polynomial in x, y, and z. - - Parameters - ---------- - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Note that periodic boundary conditions - can only be applied to x-, y-, and z-planes, and only axis-aligned - periodicity is supported. - name : str, optional - Name of the surface. If not specified, the name will be the empty - string. - - Attributes - ---------- - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, surface_id=None, boundary_type='transmission', name=''): - self.id = surface_id - self.name = name - self.boundary_type = boundary_type - - # A dictionary of the quadratic surface coefficients - # Key - coefficient name - # Value - coefficient value - self._coefficients = {} - - def __neg__(self): - return Halfspace(self, '-') - - def __pos__(self): - return Halfspace(self, '+') - - def __repr__(self): - string = 'Surface\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type) - string += '{0: <16}{1}{2}\n'.format('\tBoundary', '=\t', self._boundary_type) - - coefficients = '{0: <16}'.format('\tCoefficients') + '\n' - - for coeff in self._coefficients: - coefficients += '{0: <16}{1}{2}\n'.format( - coeff, '=\t', self._coefficients[coeff]) - - string += coefficients - - return string - - @property - def name(self): - return self._name - - @property - def type(self): - return self._type - - @property - def boundary_type(self): - return self._boundary_type - - @property - def coefficients(self): - return self._coefficients - - @name.setter - def name(self, name): - if name is not None: - check_type('surface name', name, str) - self._name = name - else: - self._name = '' - - @boundary_type.setter - def boundary_type(self, boundary_type): - check_type('boundary type', boundary_type, str) - check_value('boundary type', boundary_type, _BOUNDARY_TYPES) - self._boundary_type = boundary_type - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. If the half-space is - unbounded in a particular direction, numpy.inf is used to represent - infinity. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def clone(self, memo=None): - """Create a copy of this surface with a new unique ID. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Surface - The clone of this surface - - """ - - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - clone = deepcopy(self) - clone.id = None - - # Memoize the clone - memo[self] = clone - - return memo[self] - - @abstractmethod - def evaluate(self, point): - pass - - @abstractmethod - def translate(self, vector): - pass - - def to_xml_element(self): - """Return XML representation of the surface - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing source data - - """ - element = ET.Element("surface") - element.set("id", str(self._id)) - - if len(self._name) > 0: - element.set("name", str(self._name)) - - element.set("type", self._type) - if self.boundary_type != 'transmission': - element.set("boundary", self.boundary_type) - element.set("coeffs", ' '.join([str(self._coefficients.setdefault(key, 0.0)) - for key in self._coeff_keys])) - - return element - - @staticmethod - def from_xml_element(elem): - """Generate surface from an XML element - - Parameters - ---------- - elem : xml.etree.ElementTree.Element - XML element - - Returns - ------- - openmc.Surface - Instance of a surface subclass - - """ - - # Determine appropriate class - surf_type = elem.get('type') - surface_classes = { - 'plane': Plane, - 'x-plane': XPlane, - 'y-plane': YPlane, - 'z-plane': ZPlane, - 'x-cylinder': XCylinder, - 'y-cylinder': YCylinder, - 'z-cylinder': ZCylinder, - 'sphere': Sphere, - 'x-cone': XCone, - 'y-cone': YCone, - 'z-cone': ZCone, - 'quadric': Quadric, - } - cls = surface_classes[surf_type] - - # Determine ID, boundary type, coefficients - kwargs = {} - kwargs['surface_id'] = int(elem.get('id')) - kwargs['boundary_type'] = elem.get('boundary', 'transmission') - coeffs = [float(x) for x in elem.get('coeffs').split()] - kwargs.update(dict(zip(cls._coeff_keys, coeffs))) - - return cls(**kwargs) - - @staticmethod - def from_hdf5(group): - """Create surface from HDF5 group - - Parameters - ---------- - group : h5py.Group - Group in HDF5 file - - Returns - ------- - openmc.Surface - Instance of surface subclass - - """ - surface_id = int(group.name.split('/')[-1].lstrip('surface ')) - name = group['name'][()].decode() if 'name' in group else '' - surf_type = group['type'][()].decode() - bc = group['boundary_type'][()].decode() - coeffs = group['coefficients'][...] - - # Create the Surface based on its type - if surf_type == 'x-plane': - x0 = coeffs[0] - surface = XPlane(x0, bc, name, surface_id) - - elif surf_type == 'y-plane': - y0 = coeffs[0] - surface = YPlane(y0, bc, name, surface_id) - - elif surf_type == 'z-plane': - z0 = coeffs[0] - surface = ZPlane(z0, bc, name, surface_id) - - elif surf_type == 'plane': - A, B, C, D = coeffs - surface = Plane(A, B, C, D, bc, name, surface_id) - - elif surf_type == 'x-cylinder': - y0, z0, r = coeffs - surface = XCylinder(y0, z0, r, bc, name, surface_id) - - elif surf_type == 'y-cylinder': - x0, z0, r = coeffs - surface = YCylinder(x0, z0, r, bc, name, surface_id) - - elif surf_type == 'z-cylinder': - x0, y0, r = coeffs - surface = ZCylinder(x0, y0, r, bc, name, surface_id) - - elif surf_type == 'sphere': - x0, y0, z0, r = coeffs - surface = Sphere(x0, y0, z0, r, bc, name, surface_id) - - elif surf_type in ['x-cone', 'y-cone', 'z-cone']: - x0, y0, z0, r2 = coeffs - if surf_type == 'x-cone': - surface = XCone(x0, y0, z0, r2, bc, name, surface_id) - elif surf_type == 'y-cone': - surface = YCone(x0, y0, z0, r2, bc, name, surface_id) - elif surf_type == 'z-cone': - surface = ZCone(x0, y0, z0, r2, bc, name, surface_id) - - elif surf_type == 'quadric': - a, b, c, d, e, f, g, h, j, k = coeffs - surface = Quadric(a, b, c, d, e, f, g, h, j, k, bc, name, surface_id) - - return surface - - -class Plane(Surface): - """An arbitrary plane of the form :math:`Ax + By + Cz = D`. - - Parameters - ---------- - a : float, optional - The 'A' parameter for the plane. Defaults to 1. - b : float, optional - The 'B' parameter for the plane. Defaults to 0. - c : float, optional - The 'C' parameter for the plane. Defaults to 0. - d : float, optional - The 'D' parameter for the plane. Defaults to 0. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the plane. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - a : float - The 'A' parameter for the plane - b : float - The 'B' parameter for the plane - c : float - The 'C' parameter for the plane - d : float - The 'D' parameter for the plane - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - periodic_surface : openmc.Surface - If a periodic boundary condition is used, the surface with which this - one is periodic with - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'plane' - _coeff_keys = ('a', 'b', 'c', 'd') - - def __init__(self, a=1., b=0., c=0., d=0., boundary_type='transmission', - name='', surface_id=None, **kwargs): - super().__init__(surface_id, boundary_type, name=name) - self._periodic_surface = None - self.a = a - self.b = b - self.c = c - self.d = d - for k, v in kwargs.items(): - if k in 'ABCD': - warn(_WARNING_UPPER.format(type(self).__name__, k.lower(), k), - FutureWarning) - setattr(self, k.lower(), v) - - @property - def a(self): - return self.coefficients['a'] - - @property - def b(self): - return self.coefficients['b'] - - @property - def c(self): - return self.coefficients['c'] - - @property - def d(self): - return self.coefficients['d'] - - @property - def periodic_surface(self): - return self._periodic_surface - - @a.setter - def a(self, a): - check_type('A coefficient', a, Real) - self._coefficients['a'] = a - - @b.setter - def b(self, b): - check_type('B coefficient', b, Real) - self._coefficients['b'] = b - - @c.setter - def c(self, c): - check_type('C coefficient', c, Real) - self._coefficients['c'] = c - - @d.setter - def d(self, d): - check_type('D coefficient', d, Real) - self._coefficients['d'] = d - - @periodic_surface.setter - def periodic_surface(self, periodic_surface): - check_type('periodic surface', periodic_surface, Plane) - self._periodic_surface = periodic_surface - periodic_surface._periodic_surface = self - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`Ax' + By' + Cz' - D` - - """ - - x, y, z = point - return self.a*x + self.b*y + self.c*z - self.d - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.Plane - Translated surface - - """ - vx, vy, vz = vector - d = self.d + self.a*vx + self.b*vy + self.c*vz - if d == self.d: - return self - else: - return type(self)(a=self.a, b=self.b, c=self.c, d=d) - - def to_xml_element(self): - """Return XML representation of the surface - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing source data - - """ - element = super().to_xml_element() - - # Add periodic surface pair information - if self.boundary_type == 'periodic': - if self.periodic_surface is not None: - element.set("periodic_surface_id", str(self.periodic_surface.id)) - return element - - @classmethod - def from_points(cls, p1, p2, p3, **kwargs): - """Return a plane given three points that pass through it. - - Parameters - ---------- - p1, p2, p3 : 3-tuples - Points that pass through the plane - kwargs : dict - Keyword arguments passed to the :class:`Plane` constructor - - Returns - ------- - Plane - Plane that passes through the three points - - """ - # Convert to numpy arrays - p1 = np.asarray(p1) - p2 = np.asarray(p2) - p3 = np.asarray(p3) - - # Find normal vector to plane by taking cross product of two vectors - # connecting p1->p2 and p1->p3 - n = np.cross(p2 - p1, p3 - p1) - - # The equation of the plane will by n·( - p1) = 0. Determine - # coefficients a, b, c, and d based on that - a, b, c = n - d = np.dot(n, p1) - return cls(a=a, b=b, c=c, d=d, **kwargs) - - -class XPlane(Plane): - """A plane perpendicular to the x axis of the form :math:`x - x_0 = 0` - - Parameters - ---------- - x0 : float, optional - Location of the plane. Defaults to 0. - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. - name : str, optional - Name of the plane. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - Location of the plane - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - periodic_surface : openmc.Surface - If a periodic boundary condition is used, the surface with which this - one is periodic with - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'x-plane' - _coeff_keys = ('x0',) - - def __init__(self, x0=0., boundary_type='transmission', - name='', surface_id=None): - super().__init__(surface_id=surface_id, boundary_type=boundary_type, name=name) - self.x0 = x0 - - @property - def x0(self): - return self.coefficients['x0'] - - @x0.setter - def x0(self, x0): - check_type('x0 coefficient', x0, Real) - self._coefficients['x0'] = x0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the x-plane surface, the - half-spaces are unbounded in their y- and z- directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([self.x0, np.inf, np.inf])) - elif side == '+': - return (np.array([self.x0, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`x' - x_0` - - """ - return point[0] - self.x0 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.XPlane - Translated surface - - """ - vx = vector[0] - if vx == 0: - return self - else: - return type(self)(x0=self.x0 + vx) - - -class YPlane(Plane): - """A plane perpendicular to the y axis of the form :math:`y - y_0 = 0` - - Parameters - ---------- - y0 : float, optional - Location of the plane - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. - name : str, optional - Name of the plane. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - y0 : float - Location of the plane - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - periodic_surface : openmc.Surface - If a periodic boundary condition is used, the surface with which this - one is periodic with - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'y-plane' - _coeff_keys = ('y0',) - - def __init__(self, y0=0., boundary_type='transmission', - name='', surface_id=None): - super().__init__(surface_id=surface_id, boundary_type=boundary_type, name=name) - self.y0 = y0 - - @property - def y0(self): - return self.coefficients['y0'] - - @y0.setter - def y0(self, y0): - check_type('y0 coefficient', y0, Real) - self._coefficients['y0'] = y0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the y-plane surface, the - half-spaces are unbounded in their x- and z- directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, self.y0, np.inf])) - elif side == '+': - return (np.array([-np.inf, self.y0, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`y' - y_0` - - """ - return point[1] - self.y0 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.YPlane - Translated surface - - """ - vy = vector[1] - if vy == 0.0: - return self - else: - return type(self)(y0=self.y0 + vy) - - -class ZPlane(Plane): - """A plane perpendicular to the z axis of the form :math:`z - z_0 = 0` - - Parameters - ---------- - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. - z0 : float, optional - Location of the plane. Defaults to 0. - name : str, optional - Name of the plane. If not specified, the name will be the empty string. - - Attributes - ---------- - z0 : float - Location of the plane - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - periodic_surface : openmc.Surface - If a periodic boundary condition is used, the surface with which this - one is periodic with - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'z-plane' - _coeff_keys = ('z0',) - - def __init__(self, z0=0., boundary_type='transmission', - name='', surface_id=None): - super().__init__(surface_id=surface_id, boundary_type=boundary_type, name=name) - self.z0 = z0 - - @property - def z0(self): - return self.coefficients['z0'] - - @z0.setter - def z0(self, z0): - check_type('z0 coefficient', z0, Real) - self._coefficients['z0'] = z0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the z-plane surface, the - half-spaces are unbounded in their x- and y- directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, self.z0])) - elif side == '+': - return (np.array([-np.inf, -np.inf, self.z0]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`z' - z_0` - - """ - return point[2] - self.z0 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.ZPlane - Translated surface - - """ - vz = vector[2] - if vz == 0.0: - return self - else: - return type(self)(z0=self.z0 + vz) - - -class Cylinder(Surface): - """A cylinder whose length is parallel to the x-, y-, or z-axis. - - Parameters - ---------- - r : float, optional - Radius of the cylinder. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cylinder. If not specified, the name will be the empty - string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - r : float - Radius of the cylinder - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - def __init__(self, r=1., boundary_type='transmission', - name='', surface_id=None): - super().__init__(surface_id, boundary_type, name=name) - self.r = r - - @property - def r(self): - return self.coefficients['r'] - - @r.setter - def r(self, r): - check_type('r coefficient', r, Real) - self._coefficients['r'] = r - - -class XCylinder(Cylinder): - """An infinite cylinder whose length is parallel to the x-axis of the form - :math:`(y - y_0)^2 + (z - z_0)^2 = r^2`. - - Parameters - ---------- - y0 : float, optional - y-coordinate of the center of the cylinder. Defaults to 0. - z0 : float, optional - z-coordinate of the center of the cylinder. Defaults to 0. - r : float, optional - Radius of the cylinder. Defaults to 0. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cylinder. If not specified, the name will be the empty - string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - y0 : float - y-coordinate of the center of the cylinder - z0 : float - z-coordinate of the center of the cylinder - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'x-cylinder' - _coeff_keys = ('y0', 'z0', 'r') - - def __init__(self, y0=0., z0=0., r=1., boundary_type='transmission', - name='', surface_id=None, *, R=None): - if R is not None: - warn(_WARNING_UPPER.format(type(self).__name__, 'r', 'R'), FutureWarning) - r = R - super().__init__(r, boundary_type, name, surface_id) - self.y0 = y0 - self.z0 = z0 - - @property - def y0(self): - return self.coefficients['y0'] - - @property - def z0(self): - return self.coefficients['z0'] - - @y0.setter - def y0(self, y0): - check_type('y0 coefficient', y0, Real) - self._coefficients['y0'] = y0 - - @z0.setter - def z0(self, z0): - check_type('z0 coefficient', z0, Real) - self._coefficients['z0'] = z0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the x-cylinder surface, - the negative half-space is unbounded in the x- direction and the - positive half-space is unbounded in all directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([-np.inf, self.y0 - self.r, self.z0 - self.r]), - np.array([np.inf, self.y0 + self.r, self.z0 + self.r])) - elif side == '+': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(y' - y_0)^2 + (z' - z_0)^2 - r^2` - - """ - y = point[1] - self.y0 - z = point[2] - self.z0 - return y**2 + z**2 - self.r**2 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.XCylinder - Translated surface - - """ - vx, vy, vz = vector - if vy == 0.0 and vz == 0.0: - return self - else: - y0 = self.y0 + vy - z0 = self.z0 + vz - return type(self)(y0=y0, z0=z0, r=self.r) - - -class YCylinder(Cylinder): - """An infinite cylinder whose length is parallel to the y-axis of the form - :math:`(x - x_0)^2 + (z - z_0)^2 = r^2`. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the center of the cylinder. Defaults to 0. - z0 : float, optional - z-coordinate of the center of the cylinder. Defaults to 0. - r : float, optional - Radius of the cylinder. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cylinder. If not specified, the name will be the empty - string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - x-coordinate of the center of the cylinder - z0 : float - z-coordinate of the center of the cylinder - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'y-cylinder' - _coeff_keys = ('x0', 'z0', 'r') - - def __init__(self, x0=0., z0=0., r=1., boundary_type='transmission', - name='', surface_id=None, *, R=None): - if R is not None: - warn(_WARNING_UPPER.format(type(self).__name__, 'r', 'R'), FutureWarning) - r = R - super().__init__(r, boundary_type, name, surface_id) - self.x0 = x0 - self.z0 = z0 - - @property - def x0(self): - return self.coefficients['x0'] - - @property - def z0(self): - return self.coefficients['z0'] - - @x0.setter - def x0(self, x0): - check_type('x0 coefficient', x0, Real) - self._coefficients['x0'] = x0 - - @z0.setter - def z0(self, z0): - check_type('z0 coefficient', z0, Real) - self._coefficients['z0'] = z0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the y-cylinder surface, - the negative half-space is unbounded in the y- direction and the - positive half-space is unbounded in all directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([self.x0 - self.r, -np.inf, self.z0 - self.r]), - np.array([self.x0 + self.r, np.inf, self.z0 + self.r])) - elif side == '+': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(x' - x_0)^2 + (z' - z_0)^2 - r^2` - - """ - x = point[0] - self.x0 - z = point[2] - self.z0 - return x**2 + z**2 - self.r**2 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.YCylinder - Translated surface - - """ - vx, vy, vz = vector - if vx == 0.0 and vz == 0.0: - return self - else: - x0 = self.x0 + vx - z0 = self.z0 + vz - return type(self)(x0=x0, z0=z0, r=self.r) - - -class ZCylinder(Cylinder): - """An infinite cylinder whose length is parallel to the z-axis of the form - :math:`(x - x_0)^2 + (y - y_0)^2 = r^2`. - - Parameters - ---------- - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - x0 : float, optional - x-coordinate of the center of the cylinder. Defaults to 0. - y0 : float, optional - y-coordinate of the center of the cylinder. Defaults to 0. - r : float, optional - Radius of the cylinder. Defaults to 1. - name : str, optional - Name of the cylinder. If not specified, the name will be the empty - string. - - Attributes - ---------- - x0 : float - x-coordinate of the center of the cylinder - y0 : float - y-coordinate of the center of the cylinder - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'z-cylinder' - _coeff_keys = ('x0', 'y0', 'r') - - def __init__(self, x0=0., y0=0., r=1., boundary_type='transmission', - name='', surface_id=None, *, R=None): - if R is not None: - warn(_WARNING_UPPER.format(type(self).__name__, 'r', 'R'), FutureWarning) - r = R - super().__init__(r, boundary_type, name, surface_id) - self.x0 = x0 - self.y0 = y0 - - @property - def x0(self): - return self.coefficients['x0'] - - @property - def y0(self): - return self.coefficients['y0'] - - @x0.setter - def x0(self, x0): - check_type('x0 coefficient', x0, Real) - self._coefficients['x0'] = x0 - - @y0.setter - def y0(self, y0): - check_type('y0 coefficient', y0, Real) - self._coefficients['y0'] = y0 - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. For the z-cylinder surface, - the negative half-space is unbounded in the z- direction and the - positive half-space is unbounded in all directions. To represent - infinity, numpy.inf is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([self.x0 - self.r, self.y0 - self.r, -np.inf]), - np.array([self.x0 + self.r, self.y0 + self.r, np.inf])) - elif side == '+': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(x' - x_0)^2 + (y' - y_0)^2 - r^2` - - """ - x = point[0] - self.x0 - y = point[1] - self.y0 - return x**2 + y**2 - self.r**2 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.ZCylinder - Translated surface - - """ - vx, vy, vz = vector - if vx == 0.0 and vy == 0.0: - return self - else: - x0 = self.x0 + vx - y0 = self.y0 + vy - return type(self)(x0=x0, y0=y0, r=self.r) - - -class Sphere(Surface): - """A sphere of the form :math:`(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = r^2`. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the center of the sphere. Defaults to 0. - y0 : float, optional - y-coordinate of the center of the sphere. Defaults to 0. - z0 : float, optional - z-coordinate of the center of the sphere. Defaults to 0. - r : float, optional - Radius of the sphere. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the sphere. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - x-coordinate of the center of the sphere - y0 : float - y-coordinate of the center of the sphere - z0 : float - z-coordinate of the center of the sphere - r : float - Radius of the sphere - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'sphere' - _coeff_keys = ('x0', 'y0', 'z0', 'r') - - def __init__(self, x0=0., y0=0., z0=0., r=1., boundary_type='transmission', - name='', surface_id=None, *, R=None): - if R is not None: - warn(_WARNING_UPPER.format(type(self).__name__, 'r', 'R'), FutureWarning) - r = R - super().__init__(surface_id, boundary_type, name=name) - self.x0 = x0 - self.y0 = y0 - self.z0 = z0 - self.r = r - - @property - def x0(self): - return self.coefficients['x0'] - - @property - def y0(self): - return self.coefficients['y0'] - - @property - def z0(self): - return self.coefficients['z0'] - - @property - def r(self): - return self.coefficients['r'] - - @x0.setter - def x0(self, x0): - check_type('x0 coefficient', x0, Real) - self._coefficients['x0'] = x0 - - @y0.setter - def y0(self, y0): - check_type('y0 coefficient', y0, Real) - self._coefficients['y0'] = y0 - - @z0.setter - def z0(self, z0): - check_type('z0 coefficient', z0, Real) - self._coefficients['z0'] = z0 - - @r.setter - def r(self, r): - check_type('r coefficient', r, Real) - self._coefficients['r'] = r - - def bounding_box(self, side): - """Determine an axis-aligned bounding box. - - An axis-aligned bounding box for surface half-spaces is represented by - its lower-left and upper-right coordinates. The positive half-space of a - sphere is unbounded in all directions. To represent infinity, numpy.inf - is used. - - Parameters - ---------- - side : {'+', '-'} - Indicates the negative or positive half-space - - Returns - ------- - numpy.ndarray - Lower-left coordinates of the axis-aligned bounding box for the - desired half-space - numpy.ndarray - Upper-right coordinates of the axis-aligned bounding box for the - desired half-space - - """ - - if side == '-': - return (np.array([self.x0 - self.r, self.y0 - self.r, - self.z0 - self.r]), - np.array([self.x0 + self.r, self.y0 + self.r, - self.z0 + self.r])) - elif side == '+': - return (np.array([-np.inf, -np.inf, -np.inf]), - np.array([np.inf, np.inf, np.inf])) - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(x' - x_0)^2 + (y' - y_0)^2 + (z' - z_0)^2 - r^2` - - """ - x = point[0] - self.x0 - y = point[1] - self.y0 - z = point[2] - self.z0 - return x**2 + y**2 + z**2 - self.r**2 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.Sphere - Translated surface - - """ - vx, vy, vz = vector - if vx == 0.0 and vy == 0.0 and vz == 0.0: - return self - else: - x0 = self.x0 + vx - y0 = self.y0 + vy - z0 = self.z0 + vz - return type(self)(x0=x0, y0=y0, z0=z0, r=self.r) - - -class Cone(Surface): - """A conical surface parallel to the x-, y-, or z-axis. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the apex. Defaults to 0. - y0 : float, optional - y-coordinate of the apex. Defaults to 0. - z0 : float, optional - z-coordinate of the apex. Defaults to 0. - r2 : float, optional - Parameter related to the aperature. Defaults to 1. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str - Name of the cone. If not specified, the name will be the empty string. - - Attributes - ---------- - x0 : float - x-coordinate of the apex - y0 : float - y-coordinate of the apex - z0 : float - z-coordinate of the apex - r2 : float - Parameter related to the aperature - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _coeff_keys = ('x0', 'y0', 'z0', 'r2') - - def __init__(self, x0=0., y0=0., z0=0., r2=1., boundary_type='transmission', - name='', surface_id=None, *, R2=None): - if R2 is not None: - warn(_WARNING_UPPER.format(type(self).__name__, 'r2', 'R2'), FutureWarning) - r2 = R2 - super().__init__(surface_id, boundary_type, name=name) - self.x0 = x0 - self.y0 = y0 - self.z0 = z0 - self.r2 = r2 - - @property - def x0(self): - return self.coefficients['x0'] - - @property - def y0(self): - return self.coefficients['y0'] - - @property - def z0(self): - return self.coefficients['z0'] - - @property - def r2(self): - return self.coefficients['r2'] - - @x0.setter - def x0(self, x0): - check_type('x0 coefficient', x0, Real) - self._coefficients['x0'] = x0 - - @y0.setter - def y0(self, y0): - check_type('y0 coefficient', y0, Real) - self._coefficients['y0'] = y0 - - @z0.setter - def z0(self, z0): - check_type('z0 coefficient', z0, Real) - self._coefficients['z0'] = z0 - - @r2.setter - def r2(self, r2): - check_type('r^2 coefficient', r2, Real) - self._coefficients['r2'] = r2 - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.Cone - Translated surface - - """ - vx, vy, vz = vector - if vx == 0.0 and vy == 0.0 and vz == 0.0: - return self - else: - x0 = self.x0 + vx - y0 = self.y0 + vy - z0 = self.z0 + vz - return type(self)(x0=x0, y0=y0, z0=z0, r2=self.r2) - - -class XCone(Cone): - """A cone parallel to the x-axis of the form :math:`(y - y_0)^2 + (z - z_0)^2 = - r^2 (x - x_0)^2`. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the apex. Defaults to 0. - y0 : float, optional - y-coordinate of the apex. Defaults to 0. - z0 : float, optional - z-coordinate of the apex. Defaults to 0. - r2 : float, optional - Parameter related to the aperature. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cone. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - x-coordinate of the apex - y0 : float - y-coordinate of the apex - z0 : float - z-coordinate of the apex - r2 : float - Parameter related to the aperature - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'x-cone' - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(y' - y_0)^2 + (z' - z_0)^2 - r^2(x' - x_0)^2` - - """ - x = point[0] - self.x0 - y = point[1] - self.y0 - z = point[2] - self.z0 - return y**2 + z**2 - self.r2*x**2 - - -class YCone(Cone): - """A cone parallel to the y-axis of the form :math:`(x - x_0)^2 + (z - z_0)^2 = - r^2 (y - y_0)^2`. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the apex. Defaults to 0. - y0 : float, optional - y-coordinate of the apex. Defaults to 0. - z0 : float, optional - z-coordinate of the apex. Defaults to 0. - r2 : float, optional - Parameter related to the aperature. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cone. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - x-coordinate of the apex - y0 : float - y-coordinate of the apex - z0 : float - z-coordinate of the apex - r2 : float - Parameter related to the aperature - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'y-cone' - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(x' - x_0)^2 + (z' - z_0)^2 - r^2(y' - y_0)^2` - - """ - x = point[0] - self.x0 - y = point[1] - self.y0 - z = point[2] - self.z0 - return x**2 + z**2 - self.r2*y**2 - - -class ZCone(Cone): - """A cone parallel to the x-axis of the form :math:`(x - x_0)^2 + (y - y_0)^2 = - r^2 (z - z_0)^2`. - - Parameters - ---------- - x0 : float, optional - x-coordinate of the apex. Defaults to 0. - y0 : float, optional - y-coordinate of the apex. Defaults to 0. - z0 : float, optional - z-coordinate of the apex. Defaults to 0. - r2 : float, optional - Parameter related to the aperature. Defaults to 1. - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the cone. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - x0 : float - x-coordinate of the apex - y0 : float - y-coordinate of the apex - z0 : float - z-coordinate of the apex - r2 : float - Parameter related to the aperature - boundary_type : {'transmission, 'vacuum', 'reflective', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'z-cone' - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`(x' - x_0)^2 + (y' - y_0)^2 - r^2(z' - z_0)^2` - - """ - x = point[0] - self.x0 - y = point[1] - self.y0 - z = point[2] - self.z0 - return x**2 + y**2 - self.r2*z**2 - - -class Quadric(Surface): - """A surface of the form :math:`Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + - Jz + K = 0`. - - Parameters - ---------- - a, b, c, d, e, f, g, h, j, k : float, optional - coefficients for the surface. All default to 0. - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional - Boundary condition that defines the behavior for particles hitting the - surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. - name : str, optional - Name of the surface. If not specified, the name will be the empty string. - surface_id : int, optional - Unique identifier for the surface. If not specified, an identifier will - automatically be assigned. - - Attributes - ---------- - a, b, c, d, e, f, g, h, j, k : float - coefficients for the surface - boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'} - Boundary condition that defines the behavior for particles hitting the - surface. - coefficients : dict - Dictionary of surface coefficients - id : int - Unique identifier for the surface - name : str - Name of the surface - type : str - Type of the surface - - """ - - _type = 'quadric' - _coeff_keys = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k') - - def __init__(self, a=0., b=0., c=0., d=0., e=0., f=0., g=0., h=0., j=0., - k=0., boundary_type='transmission', name='', surface_id=None): - super().__init__(surface_id, boundary_type, name=name) - self.a = a - self.b = b - self.c = c - self.d = d - self.e = e - self.f = f - self.g = g - self.h = h - self.j = j - self.k = k - - @property - def a(self): - return self.coefficients['a'] - - @property - def b(self): - return self.coefficients['b'] - - @property - def c(self): - return self.coefficients['c'] - - @property - def d(self): - return self.coefficients['d'] - - @property - def e(self): - return self.coefficients['e'] - - @property - def f(self): - return self.coefficients['f'] - - @property - def g(self): - return self.coefficients['g'] - - @property - def h(self): - return self.coefficients['h'] - - @property - def j(self): - return self.coefficients['j'] - - @property - def k(self): - return self.coefficients['k'] - - @a.setter - def a(self, a): - check_type('a coefficient', a, Real) - self._coefficients['a'] = a - - @b.setter - def b(self, b): - check_type('b coefficient', b, Real) - self._coefficients['b'] = b - - @c.setter - def c(self, c): - check_type('c coefficient', c, Real) - self._coefficients['c'] = c - - @d.setter - def d(self, d): - check_type('d coefficient', d, Real) - self._coefficients['d'] = d - - @e.setter - def e(self, e): - check_type('e coefficient', e, Real) - self._coefficients['e'] = e - - @f.setter - def f(self, f): - check_type('f coefficient', f, Real) - self._coefficients['f'] = f - - @g.setter - def g(self, g): - check_type('g coefficient', g, Real) - self._coefficients['g'] = g - - @h.setter - def h(self, h): - check_type('h coefficient', h, Real) - self._coefficients['h'] = h - - @j.setter - def j(self, j): - check_type('j coefficient', j, Real) - self._coefficients['j'] = j - - @k.setter - def k(self, k): - check_type('k coefficient', k, Real) - self._coefficients['k'] = k - - def evaluate(self, point): - """Evaluate the surface equation at a given point. - - Parameters - ---------- - point : 3-tuple of float - The Cartesian coordinates, :math:`(x',y',z')`, at which the surface - equation should be evaluated. - - Returns - ------- - float - :math:`Ax'^2 + By'^2 + Cz'^2 + Dx'y' + Ey'z' + Fx'z' + Gx' + Hy' + - Jz' + K = 0` - - """ - x, y, z = point - return x*(self.a*x + self.d*y + self.g) + \ - y*(self.b*y + self.e*z + self.h) + \ - z*(self.c*z + self.f*x + self.j) + self.k - - def translate(self, vector): - """Translate surface in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which surface should be translated - - Returns - ------- - openmc.Quadric - Translated surface - - """ - vx, vy, vz = vector - a, b, c, d, e, f, g, h, j, k = (getattr(self, key) for key in - self._coeff_keys) - k = (k + vx*vx + vy*vy + vz*vz + d*vx*vy + e*vy*vz + f*vx*vz - - g*vx - h*vy - j*vz) - g = g - 2*a*vx - d*vy - f*vz - h = h - 2*b*vy - d*vx - e*vz - j = j - 2*c*vz - e*vy - f*vx - return type(self)(a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h, j=j, k=k) - - -class Halfspace(Region): - """A positive or negative half-space region. - - A half-space is either of the two parts into which a two-dimension surface - divides the three-dimensional Euclidean space. If the equation of the - surface is :math:`f(x,y,z) = 0`, the region for which :math:`f(x,y,z) < 0` - is referred to as the negative half-space and the region for which - :math:`f(x,y,z) > 0` is referred to as the positive half-space. - - Instances of Halfspace are generally not instantiated directly. Rather, they - can be created from an existing Surface through the __neg__ and __pos__ - operators, as the following example demonstrates: - - >>> sphere = openmc.Sphere(surface_id=1, r=10.0) - >>> inside_sphere = -sphere - >>> outside_sphere = +sphere - >>> type(inside_sphere) - - - Parameters - ---------- - surface : openmc.Surface - Surface which divides Euclidean space. - side : {'+', '-'} - Indicates whether the positive or negative half-space is used. - - Attributes - ---------- - surface : openmc.Surface - Surface which divides Euclidean space. - side : {'+', '-'} - Indicates whether the positive or negative half-space is used. - bounding_box : tuple of numpy.ndarray - Lower-left and upper-right coordinates of an axis-aligned bounding box - - """ - - def __init__(self, surface, side): - self.surface = surface - self.side = side - - def __and__(self, other): - if isinstance(other, Intersection): - return Intersection([self] + other[:]) - else: - return Intersection((self, other)) - - def __or__(self, other): - if isinstance(other, Union): - return Union([self] + other[:]) - else: - return Union((self, other)) - - def __invert__(self): - return -self.surface if self.side == '+' else +self.surface - - def __contains__(self, point): - """Check whether a point is contained in the half-space. - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates, :math:`(x',y',z')`, of the point - - Returns - ------- - bool - Whether the point is in the half-space - - """ - - val = self.surface.evaluate(point) - return val >= 0. if self.side == '+' else val < 0. - - @property - def surface(self): - return self._surface - - @surface.setter - def surface(self, surface): - check_type('surface', surface, Surface) - self._surface = surface - - @property - def side(self): - return self._side - - @side.setter - def side(self, side): - check_value('side', side, ('+', '-')) - self._side = side - - @property - def bounding_box(self): - return self.surface.bounding_box(self.side) - - def __str__(self): - return '-' + str(self.surface.id) if self.side == '-' \ - else str(self.surface.id) - - def get_surfaces(self, surfaces=None): - """ - Returns the surface that this is a halfspace of. - - Parameters - ---------- - surfaces: collections.OrderedDict, optional - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - Returns - ------- - surfaces: collections.OrderedDict - Dictionary mapping surface IDs to :class:`openmc.Surface` instances - - """ - if surfaces is None: - surfaces = OrderedDict() - - surfaces[self.surface.id] = self.surface - return surfaces - - def clone(self, memo=None): - """Create a copy of this halfspace, with a cloned surface with a - unique ID. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Halfspace - The clone of this halfspace - - """ - - if memo is None: - memo = dict - - clone = deepcopy(self) - clone.surface = self.surface.clone(memo) - return clone - - def translate(self, vector, memo=None): - """Translate half-space in given direction - - Parameters - ---------- - vector : iterable of float - Direction in which region should be translated - memo : dict or None - Dictionary used for memoization - - Returns - ------- - openmc.Halfspace - Translated half-space - - """ - if memo is None: - memo = {} - - # If translated surface not in memo, add it - key = (self.surface, tuple(vector)) - if key not in memo: - memo[key] = self.surface.translate(vector) - - # Return translated surface - return type(self)(memo[key], self.side) diff --git a/openmc/tallies.py b/openmc/tallies.py deleted file mode 100644 index 18c359c46..000000000 --- a/openmc/tallies.py +++ /dev/null @@ -1,3204 +0,0 @@ -from collections.abc import Iterable, MutableSequence -import copy -import re -from functools import partial, reduce -from itertools import product -from numbers import Integral, Real -import operator -from pathlib import Path -import warnings -from xml.etree import ElementTree as ET - -import numpy as np -import pandas as pd -import scipy.sparse as sps -import h5py - -import openmc -import openmc.checkvalue as cv -from openmc._xml import clean_indentation -from .mixin import IDManagerMixin - - -# The tally arithmetic product types. The tensor product performs the full -# cross product of the data in two tallies with respect to a specified axis -# (filters, nuclides, or scores). The entrywise product performs the arithmetic -# operation entrywise across the entries in two tallies with respect to a -# specified axis. -_PRODUCT_TYPES = ['tensor', 'entrywise'] - -# The following indicate acceptable types when setting Tally.scores, -# Tally.nuclides, and Tally.filters -_SCORE_CLASSES = (str, openmc.CrossScore, openmc.AggregateScore) -_NUCLIDE_CLASSES = (str, openmc.CrossNuclide, openmc.AggregateNuclide) -_FILTER_CLASSES = (openmc.Filter, openmc.CrossFilter, openmc.AggregateFilter) - -# Valid types of estimators -ESTIMATOR_TYPES = ['tracklength', 'collision', 'analog'] - - -class Tally(IDManagerMixin): - """A tally defined by a set of scores that are accumulated for a list of - nuclides given a set of filters. - - Parameters - ---------- - tally_id : int, optional - Unique identifier for the tally. If none is specified, an identifier - will automatically be assigned - name : str, optional - Name of the tally. If not specified, the name is the empty string. - - Attributes - ---------- - id : int - Unique identifier for the tally - name : str - Name of the tally - filters : list of openmc.Filter - List of specified filters for the tally - nuclides : list of openmc.Nuclide - List of nuclides to score results for - scores : list of str - List of defined scores, e.g. 'flux', 'fission', etc. - estimator : {'analog', 'tracklength', 'collision'} - Type of estimator for the tally - triggers : list of openmc.Trigger - List of tally triggers - num_scores : int - Total number of scores - num_filter_bins : int - Total number of filter bins accounting for all filters - num_bins : int - Total number of bins for the tally - shape : 3-tuple of int - The shape of the tally data array ordered as the number of filter bins, - nuclide bins and score bins - filter_strides : list of int - Stride in memory for each filter - num_realizations : int - Total number of realizations - with_summary : bool - Whether or not a Summary has been linked - sum : numpy.ndarray - An array containing the sum of each independent realization for each bin - sum_sq : numpy.ndarray - An array containing the sum of each independent realization squared for - each bin - mean : numpy.ndarray - An array containing the sample mean for each bin - std_dev : numpy.ndarray - An array containing the sample standard deviation for each bin - derived : bool - Whether or not the tally is derived from one or more other tallies - sparse : bool - Whether or not the tally uses SciPy's LIL sparse matrix format for - compressed data storage - derivative : openmc.TallyDerivative - A material perturbation derivative to apply to all scores in the tally. - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, tally_id=None, name=''): - # Initialize Tally class attributes - self.id = tally_id - self.name = name - self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters') - self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides') - self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores') - self._estimator = None - self._triggers = cv.CheckedList(openmc.Trigger, 'tally triggers') - self._derivative = None - - self._num_realizations = 0 - self._with_summary = False - - self._sum = None - self._sum_sq = None - self._mean = None - self._std_dev = None - self._with_batch_statistics = False - self._derived = False - self._sparse = False - - self._sp_filename = None - self._results_read = False - - def __repr__(self): - string = 'Tally\n' - string += '{: <16}=\t{}\n'.format('\tID', self.id) - string += '{: <16}=\t{}\n'.format('\tName', self.name) - - if self.derivative is not None: - string += '{: <16}=\t{}\n'.format('\tDerivative ID', - str(self.derivative.id)) - - filters = ', '.join(type(f).__name__ for f in self.filters) - string += '{: <16}=\t{}\n'.format('\tFilters', filters) - - string += '{: <16}=\t'.format('\tNuclides') - - for nuclide in self.nuclides: - string += str(nuclide) + ' ' - - string += '\n' - - string += '{: <16}=\t{}\n'.format('\tScores', self.scores) - string += '{: <16}=\t{}\n'.format('\tEstimator', self.estimator) - - return string - - @property - def name(self): - return self._name - - @property - def filters(self): - return self._filters - - @property - def nuclides(self): - return self._nuclides - - @property - def num_nuclides(self): - return len(self._nuclides) - - @property - def scores(self): - return self._scores - - @property - def num_scores(self): - return len(self._scores) - - @property - def num_filters(self): - return len(self.filters) - - @property - def num_filter_bins(self): - return reduce(operator.mul, (f.num_bins for f in self.filters), 1) - - @property - def num_bins(self): - return self.num_filter_bins * self.num_nuclides * self.num_scores - - @property - def shape(self): - return (self.num_filter_bins, self.num_nuclides, self.num_scores) - - @property - def estimator(self): - return self._estimator - - @property - def triggers(self): - return self._triggers - - @property - def num_realizations(self): - return self._num_realizations - - @property - def with_summary(self): - return self._with_summary - - @property - def sum(self): - if not self._sp_filename or self.derived: - return None - - if not self._results_read: - # Open the HDF5 statepoint file - f = h5py.File(self._sp_filename, 'r') - - # Extract Tally data from the file - data = f['tallies/tally {0}/results'.format(self.id)] - sum = data[:, :, 0] - sum_sq = data[:, :, 1] - - # Reshape the results arrays - sum = np.reshape(sum, self.shape) - sum_sq = np.reshape(sum_sq, self.shape) - - # Set the data for this Tally - self._sum = sum - self._sum_sq = sum_sq - - # Convert NumPy arrays to SciPy sparse LIL matrices - if self.sparse: - self._sum = sps.lil_matrix(self._sum.flatten(), - self._sum.shape) - self._sum_sq = sps.lil_matrix(self._sum_sq.flatten(), - self._sum_sq.shape) - - # Indicate that Tally results have been read - self._results_read = True - - # Close the HDF5 statepoint file - f.close() - - if self.sparse: - return np.reshape(self._sum.toarray(), self.shape) - else: - return self._sum - - @property - def sum_sq(self): - if not self._sp_filename or self.derived: - return None - - if not self._results_read: - # Force reading of sum and sum_sq - self.sum - - if self.sparse: - return np.reshape(self._sum_sq.toarray(), self.shape) - else: - return self._sum_sq - - @property - def mean(self): - if self._mean is None: - if not self._sp_filename: - return None - - self._mean = self.sum / self.num_realizations - - # Convert NumPy array to SciPy sparse LIL matrix - if self.sparse: - self._mean = sps.lil_matrix(self._mean.flatten(), - self._mean.shape) - - if self.sparse: - return np.reshape(self._mean.toarray(), self.shape) - else: - return self._mean - - @property - def std_dev(self): - if self._std_dev is None: - if not self._sp_filename: - return None - - n = self.num_realizations - nonzero = np.abs(self.mean) > 0 - self._std_dev = np.zeros_like(self.mean) - self._std_dev[nonzero] = np.sqrt((self.sum_sq[nonzero]/n - - self.mean[nonzero]**2)/(n - 1)) - - # Convert NumPy array to SciPy sparse LIL matrix - if self.sparse: - self._std_dev = sps.lil_matrix(self._std_dev.flatten(), - self._std_dev.shape) - - self.with_batch_statistics = True - - if self.sparse: - return np.reshape(self._std_dev.toarray(), self.shape) - else: - return self._std_dev - - @property - def with_batch_statistics(self): - return self._with_batch_statistics - - @property - def derived(self): - return self._derived - - @property - def derivative(self): - return self._derivative - - @property - def sparse(self): - return self._sparse - - @estimator.setter - def estimator(self, estimator): - cv.check_value('estimator', estimator, ESTIMATOR_TYPES) - self._estimator = estimator - - @triggers.setter - def triggers(self, triggers): - cv.check_type('tally triggers', triggers, MutableSequence) - self._triggers = cv.CheckedList(openmc.Trigger, 'tally triggers', - triggers) - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('tally name', name, str) - self._name = name - else: - self._name = '' - - @derivative.setter - def derivative(self, deriv): - if deriv is not None: - cv.check_type('tally derivative', deriv, openmc.TallyDerivative) - self._derivative = deriv - - @filters.setter - def filters(self, filters): - cv.check_type('tally filters', filters, MutableSequence) - - # If the filter is already in the Tally, raise an error - for i, f in enumerate(filters[:-1]): - if f in filters[i+1:]: - msg = 'Unable to add a duplicate filter "{0}" to Tally ID="{1}" ' \ - 'since duplicate filters are not supported in the OpenMC ' \ - 'Python API'.format(f, self.id) - raise ValueError(msg) - - self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters', filters) - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_type('tally nuclides', nuclides, MutableSequence) - - # If the nuclide is already in the Tally, raise an error - for i, nuclide in enumerate(nuclides[:-1]): - if nuclide in nuclides[i+1:]: - msg = 'Unable to add a duplicate nuclide "{0}" to Tally ID="{1}" ' \ - 'since duplicate nuclides are not supported in the OpenMC ' \ - 'Python API'.format(nuclide, self.id) - raise ValueError(msg) - - self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides', - nuclides) - - @scores.setter - def scores(self, scores): - cv.check_type('tally scores', scores, MutableSequence) - - for i, score in enumerate(scores): - # If the score is already in the Tally, raise an error - if score in scores[i+1:]: - msg = 'Unable to add a duplicate score "{0}" to Tally ID="{1}" ' \ - 'since duplicate scores are not supported in the OpenMC ' \ - 'Python API'.format(score, self.id) - raise ValueError(msg) - - # If score is a string, strip whitespace - if isinstance(score, str): - # Check to see if scores are deprecated before storing - for deprecated in ['scatter-', 'nu-scatter-', 'scatter-p', - 'nu-scatter-p', 'scatter-y', 'nu-scatter-y', - 'flux-y', 'total-y']: - if score.strip().startswith(deprecated): - msg = score.strip() + ' is no longer supported.' - raise ValueError(msg) - scores[i] = score.strip() - - self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) - - @num_realizations.setter - def num_realizations(self, num_realizations): - cv.check_type('number of realizations', num_realizations, Integral) - cv.check_greater_than('number of realizations', num_realizations, 0, True) - self._num_realizations = num_realizations - - @with_summary.setter - def with_summary(self, with_summary): - cv.check_type('with_summary', with_summary, bool) - self._with_summary = with_summary - - @with_batch_statistics.setter - def with_batch_statistics(self, with_batch_statistics): - cv.check_type('with_batch_statistics', with_batch_statistics, bool) - self._with_batch_statistics = with_batch_statistics - - @sum.setter - def sum(self, sum): - cv.check_type('sum', sum, Iterable) - self._sum = sum - - @sum_sq.setter - def sum_sq(self, sum_sq): - cv.check_type('sum_sq', sum_sq, Iterable) - self._sum_sq = sum_sq - - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within the Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - - # Convert NumPy arrays to SciPy sparse LIL matrices - if sparse and not self.sparse: - if self._sum is not None: - self._sum = sps.lil_matrix(self._sum.flatten(), self._sum.shape) - if self._sum_sq is not None: - self._sum_sq = sps.lil_matrix(self._sum_sq.flatten(), - self._sum_sq.shape) - if self._mean is not None: - self._mean = sps.lil_matrix(self._mean.flatten(), - self._mean.shape) - if self._std_dev is not None: - self._std_dev = sps.lil_matrix(self._std_dev.flatten(), - self._std_dev.shape) - - self._sparse = True - - # Convert SciPy sparse LIL matrices to NumPy arrays - elif not sparse and self.sparse: - if self._sum is not None: - self._sum = np.reshape(self._sum.toarray(), self.shape) - if self._sum_sq is not None: - self._sum_sq = np.reshape(self._sum_sq.toarray(), self.shape) - if self._mean is not None: - self._mean = np.reshape(self._mean.toarray(), self.shape) - if self._std_dev is not None: - self._std_dev = np.reshape(self._std_dev.toarray(), self.shape) - self._sparse = False - - def remove_score(self, score): - """Remove a score from the tally - - Parameters - ---------- - score : str - Score to remove - - """ - - if score not in self.scores: - msg = 'Unable to remove score "{0}" from Tally ID="{1}" since ' \ - 'the Tally does not contain this score'.format(score, self.id) - ValueError(msg) - - self._scores.remove(score) - - def remove_filter(self, old_filter): - """Remove a filter from the tally - - Parameters - ---------- - old_filter : openmc.Filter - Filter to remove - - """ - - if old_filter not in self.filters: - msg = 'Unable to remove filter "{0}" from Tally ID="{1}" since the ' \ - 'Tally does not contain this filter'.format(old_filter, self.id) - ValueError(msg) - - self._filters.remove(old_filter) - - def remove_nuclide(self, nuclide): - """Remove a nuclide from the tally - - Parameters - ---------- - nuclide : openmc.Nuclide - Nuclide to remove - - """ - - if nuclide not in self.nuclides: - msg = 'Unable to remove nuclide "{0}" from Tally ID="{1}" since the ' \ - 'Tally does not contain this nuclide'.format(nuclide, self.id) - ValueError(msg) - - self._nuclides.remove(nuclide) - - def _can_merge_filters(self, other): - """Determine if another tally's filters can be merged with this one's - - The types of filters between the two tallies must match identically. - The bins in all of the filters must match identically, or be mergeable - in only one filter. This is a helper method for the can_merge(...) - and merge(...) methods. - - Parameters - ---------- - other : openmc.Tally - Tally to check for mergeable filters - - """ - - # Two tallies must have the same number of filters - if len(self.filters) != len(other.filters): - return False - - # Return False if only one tally has a delayed group filter - tally1_dg = self.contains_filter(openmc.DelayedGroupFilter) - tally2_dg = other.contains_filter(openmc.DelayedGroupFilter) - if sum([tally1_dg, tally2_dg]) == 1: - return False - - # Look to see if all filters are the same, or one or more can be merged - for filter1 in self.filters: - merge_filters = False - mergeable_filter = False - - for filter2 in other.filters: - - # If filters match, they are mergeable - if filter1 == filter2: - mergeable_filter = True - break - - # If filters are first mergeable filters encountered - elif filter1.can_merge(filter2) and not merge_filters: - merge_filters = True - mergeable_filter = True - break - - # If filters are the second mergeable filters encountered - elif filter1.can_merge(filter2) and merge_filters: - return False - - # If no mergeable filter was found, the tallies are not mergeable - if not mergeable_filter: - return False - - # Tally filters are mergeable if all conditional checks passed - return True - - def _can_merge_nuclides(self, other): - """Determine if another tally's nuclides can be merged with this one's - - The nuclides between the two tallies must be mutually exclusive or - identically matching. This is a helper method for the can_merge(...) - and merge(...) methods. - - Parameters - ---------- - other : openmc.Tally - Tally to check for mergeable nuclides - - """ - - no_nuclides_match = True - all_nuclides_match = True - - # Search for each of this tally's nuclides in the other tally - for nuclide in self.nuclides: - if nuclide not in other.nuclides: - all_nuclides_match = False - else: - no_nuclides_match = False - - # Search for each of the other tally's nuclides in this tally - for nuclide in other.nuclides: - if nuclide not in self.nuclides: - all_nuclides_match = False - else: - no_nuclides_match = False - - # Either all nuclides should match, or none should - return no_nuclides_match or all_nuclides_match - - def _can_merge_scores(self, other): - """Determine if another tally's scores can be merged with this one's - - The scores between the two tallies must be mutually exclusive or - identically matching. This is a helper method for the can_merge(...) - and merge(...) methods. - - Parameters - ---------- - other : openmc.Tally - Tally to check for mergeable scores - - """ - - no_scores_match = True - all_scores_match = True - - # Search for each of this tally's scores in the other tally - for score in self.scores: - if score in other.scores: - no_scores_match = False - - # Search for each of the other tally's scores in this tally - for score in other.scores: - if score not in self.scores: - all_scores_match = False - else: - no_scores_match = False - - if score == 'current' and score not in self.scores: - return False - - # Nuclides cannot be specified on 'flux' scores - if 'flux' in self.scores or 'flux' in other.scores: - if self.nuclides != other.nuclides: - return False - - # Either all scores should match, or none should - return no_scores_match or all_scores_match - - def can_merge(self, other): - """Determine if another tally can be merged with this one - - If results have been loaded from a statepoint, then tallies are only - mergeable along one and only one of filter bins, nuclides or scores. - - Parameters - ---------- - other : openmc.Tally - Tally to check for merging - - """ - - if not isinstance(other, Tally): - return False - - # Must have same estimator - if self.estimator != other.estimator: - return False - - equal_filters = sorted(self.filters) == sorted(other.filters) - equal_nuclides = sorted(self.nuclides) == sorted(other.nuclides) - equal_scores = sorted(self.scores) == sorted(other.scores) - equality = [equal_filters, equal_nuclides, equal_scores] - - # If all filters, nuclides and scores match then tallies are mergeable - if equal_filters and equal_nuclides and equal_scores: - return True - - # Variables to indicate matching filter bins, nuclides and scores - merge_filters = self._can_merge_filters(other) - merge_nuclides = self._can_merge_nuclides(other) - merge_scores = self._can_merge_scores(other) - mergeability = [merge_filters, merge_nuclides, merge_scores] - - if not all(mergeability): - return False - - # If the tally results have been read from the statepoint, we can only - # at least two of filters, nuclides and scores must match - elif self._results_read and sum(equality) < 2: - return False - else: - return True - - def merge(self, other): - """Merge another tally with this one - - If results have been loaded from a statepoint, then tallies are only - mergeable along one and only one of filter bins, nuclides or scores. - - Parameters - ---------- - other : openmc.Tally - Tally to merge with this one - - Returns - ------- - merged_tally : openmc.Tally - Merged tallies - - """ - - if not self.can_merge(other): - msg = 'Unable to merge tally ID="{0}" with ' \ - '"{1}"'.format(other.id, self.id) - raise ValueError(msg) - - # Create deep copy of tally to return as merged tally - merged_tally = copy.deepcopy(self) - - # Differentiate Tally with a new auto-generated Tally ID - merged_tally.id = None - - # Create deep copy of other tally to use for array concatenation - other_copy = copy.deepcopy(other) - - # Identify if filters, nuclides and scores are mergeable and/or equal - merge_filters = self._can_merge_filters(other) - merge_nuclides = self._can_merge_nuclides(other) - merge_scores = self._can_merge_scores(other) - equal_filters = sorted(self.filters) == sorted(other.filters) - equal_nuclides = sorted(self.nuclides) == sorted(other.nuclides) - equal_scores = sorted(self.scores) == sorted(other.scores) - - # If two tallies can be merged along a filter's bins - if merge_filters and not equal_filters: - - # Search for mergeable filters - for i, filter1 in enumerate(self.filters): - for filter2 in other.filters: - if filter1 != filter2 and filter1.can_merge(filter2): - other_copy._swap_filters(other_copy.filters[i], filter2) - merged_tally.filters[i] = filter1.merge(filter2) - join_right = filter1 < filter2 - merge_axis = i - break - - # If two tallies can be merged along nuclide bins - if merge_nuclides and not equal_nuclides: - merge_axis = self.num_filters - join_right = True - - # Add unique nuclides from other tally to merged tally - for nuclide in other.nuclides: - if nuclide not in merged_tally.nuclides: - merged_tally.nuclides.append(nuclide) - - # If two tallies can be merged along score bins - if merge_scores and not equal_scores: - merge_axis = self.num_filters + 1 - join_right = True - - # Add unique scores from other tally to merged tally - for score in other.scores: - if score not in merged_tally.scores: - merged_tally.scores.append(score) - - # Add triggers from other tally to merged tally - for trigger in other.triggers: - merged_tally.triggers.append(trigger) - - # If results have not been read, then return tally for input generation - if self._results_read is None: - return merged_tally - # Otherwise, this is a derived tally which needs merged results arrays - else: - self._derived = True - - # Concatenate sum arrays if present in both tallies - if self.sum is not None and other_copy.sum is not None: - self_sum = self.get_reshaped_data(value='sum') - other_sum = other_copy.get_reshaped_data(value='sum') - - if join_right: - merged_sum = np.concatenate((self_sum, other_sum), - axis=merge_axis) - else: - merged_sum = np.concatenate((other_sum, self_sum), - axis=merge_axis) - - merged_tally._sum = np.reshape(merged_sum, merged_tally.shape) - - # Concatenate sum_sq arrays if present in both tallies - if self.sum_sq is not None and other.sum_sq is not None: - self_sum_sq = self.get_reshaped_data(value='sum_sq') - other_sum_sq = other_copy.get_reshaped_data(value='sum_sq') - - if join_right: - merged_sum_sq = np.concatenate((self_sum_sq, other_sum_sq), - axis=merge_axis) - else: - merged_sum_sq = np.concatenate((other_sum_sq, self_sum_sq), - axis=merge_axis) - - merged_tally._sum_sq = np.reshape(merged_sum_sq, merged_tally.shape) - - # Concatenate mean arrays if present in both tallies - if self.mean is not None and other.mean is not None: - self_mean = self.get_reshaped_data(value='mean') - other_mean = other_copy.get_reshaped_data(value='mean') - - if join_right: - merged_mean = np.concatenate((self_mean, other_mean), - axis=merge_axis) - else: - merged_mean = np.concatenate((other_mean, self_mean), - axis=merge_axis) - - merged_tally._mean = np.reshape(merged_mean, merged_tally.shape) - - # Concatenate std. dev. arrays if present in both tallies - if self.std_dev is not None and other.std_dev is not None: - self_std_dev = self.get_reshaped_data(value='std_dev') - other_std_dev = other_copy.get_reshaped_data(value='std_dev') - - if join_right: - merged_std_dev = np.concatenate((self_std_dev, other_std_dev), - axis=merge_axis) - else: - merged_std_dev = np.concatenate((other_std_dev, self_std_dev), - axis=merge_axis) - - merged_tally._std_dev = np.reshape(merged_std_dev, merged_tally.shape) - - # Sparsify merged tally if both tallies are sparse - merged_tally.sparse = self.sparse and other.sparse - - return merged_tally - - def to_xml_element(self): - """Return XML representation of the tally - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing tally data - - """ - - element = ET.Element("tally") - - # Tally ID - element.set("id", str(self.id)) - - # Optional Tally name - if self.name != '': - element.set("name", self.name) - - # Optional Tally filters - if len(self.filters) > 0: - subelement = ET.SubElement(element, "filters") - subelement.text = ' '.join(str(f.id) for f in self.filters) - - # Optional Nuclides - if self.nuclides: - subelement = ET.SubElement(element, "nuclides") - subelement.text = ' '.join(str(n) for n in self.nuclides) - - # Scores - if len(self.scores) == 0: - msg = 'Unable to get XML for Tally ID="{0}" since it does not ' \ - 'contain any scores'.format(self.id) - raise ValueError(msg) - - else: - scores = '' - for score in self.scores: - scores += '{0} '.format(score) - - subelement = ET.SubElement(element, "scores") - subelement.text = scores.rstrip(' ') - - # Tally estimator type - if self.estimator is not None: - subelement = ET.SubElement(element, "estimator") - subelement.text = self.estimator - - # Optional Triggers - for trigger in self.triggers: - trigger.get_trigger_xml(element) - - # Optional derivatives - if self.derivative is not None: - subelement = ET.SubElement(element, "derivative") - subelement.text = str(self.derivative.id) - - return element - - def contains_filter(self, filter_type): - """Looks for a filter in the tally that matches a specified type - - Parameters - ---------- - filter_type : openmc.FilterMeta - Type of the filter, e.g. MeshFilter - - Returns - ------- - filter_found : bool - True if the tally contains a filter of the requested type; - otherwise false - - """ - - filter_found = False - - # Look through all of this Tally's Filters for the type requested - for test_filter in self.filters: - if type(test_filter) is filter_type: - filter_found = True - break - - return filter_found - - def find_filter(self, filter_type): - """Return a filter in the tally that matches a specified type - - Parameters - ---------- - filter_type : openmc.FilterMeta - Type of the filter, e.g. MeshFilter - - Returns - ------- - filter_found : openmc.Filter - Filter from this tally with matching type, or None if no matching - Filter is found - - Raises - ------ - ValueError - If no matching Filter is found - - """ - - filter_found = None - - # Look through all of this Tally's Filters for the type requested - for test_filter in self.filters: - if type(test_filter) is filter_type: - filter_found = test_filter - break - - # Also check to see if the desired filter is wrapped up in an - # aggregate - elif isinstance(test_filter, openmc.AggregateFilter): - if isinstance(test_filter.aggregate_filter, filter_type): - filter_found = test_filter - break - - # If we did not find the Filter, throw an Exception - if filter_found is None: - msg = 'Unable to find filter type "{0}" in ' \ - 'Tally ID="{1}"'.format(filter_type, self.id) - raise ValueError(msg) - - return filter_found - - def get_nuclide_index(self, nuclide): - """Returns the index in the Tally's results array for a Nuclide bin - - Parameters - ---------- - nuclide : str - The name of the Nuclide (e.g., 'H1', 'U238') - - Returns - ------- - nuclide_index : int - The index in the Tally data array for this nuclide. - - Raises - ------ - KeyError - When the argument passed to the 'nuclide' parameter cannot be found - in the Tally. - - """ - - nuclide_index = -1 - - # Look for the user-requested nuclide in all of the Tally's Nuclides - for i, test_nuclide in enumerate(self.nuclides): - - # If the Summary was linked, then values are Nuclide objects - if isinstance(test_nuclide, openmc.Nuclide): - if test_nuclide.name == nuclide: - nuclide_index = i - break - - # If the Summary has not been linked, then values are ZAIDs - else: - if test_nuclide == nuclide: - nuclide_index = i - break - - if nuclide_index == -1: - msg = 'Unable to get the nuclide index for Tally since "{0}" ' \ - 'is not one of the nuclides'.format(nuclide) - raise KeyError(msg) - else: - return nuclide_index - - def get_score_index(self, score): - """Returns the index in the Tally's results array for a score bin - - Parameters - ---------- - score : str - The score string (e.g., 'absorption', 'nu-fission') - - Returns - ------- - score_index : int - The index in the Tally data array for this score. - - Raises - ------ - ValueError - When the argument passed to the 'score' parameter cannot be found in - the Tally. - - """ - - try: - score_index = self.scores.index(score) - - except ValueError: - msg = 'Unable to get the score index for Tally since "{0}" ' \ - 'is not one of the scores'.format(score) - raise ValueError(msg) - - return score_index - - def get_filter_indices(self, filters=[], filter_bins=[]): - """Get indices into the filter axis of this tally's data arrays. - - This is a helper method for the Tally.get_values(...) method to - extract tally data. This method returns the indices into the filter - axis of the tally's data array (axis=0) for particular combinations - of filters and their corresponding bins. - - Parameters - ---------- - filters : Iterable of openmc.FilterMeta - An iterable of filter types - (e.g., [MeshFilter, EnergyFilter]; default is []) - filter_bins : Iterable of tuple - A list of tuples of filter bins corresponding to the filter_types - parameter (e.g., [(1,), ((0., 0.625e-6),)]; default is []). Each - tuple contains bins for the corresponding filter type in the filters - parameter. Each bin is an integer ID for Material-, Surface-, - Cell-, Cellborn-, and Universe- Filters. Each bin is an integer - for the cell instance ID for DistribcellFilters. Each bin is a - 2-tuple of floats for Energy- and Energyout- Filters corresponding - to the energy boundaries of the bin of interest. The bin is an - (x,y,z) 3-tuple for MeshFilters corresponding to the mesh cell - of interest. The order of the bins in the list must correspond to - the filter_types parameter. - - Returns - ------- - numpy.ndarray - A NumPy array of the filter indices - - """ - - cv.check_type('filters', filters, Iterable, openmc.FilterMeta) - cv.check_type('filter_bins', filter_bins, Iterable, tuple) - - # Determine the score indices from any of the requested scores - if filters: - # Initialize empty list of indices for each bin in each Filter - filter_indices = [] - - # Loop over all of the Tally's Filters - for i, self_filter in enumerate(self.filters): - # If a user-requested Filter, get the user-requested bins - for j, test_filter in enumerate(filters): - if type(self_filter) is test_filter: - bins = filter_bins[j] - break - else: - # If not a user-requested Filter, get all bins - if isinstance(self_filter, openmc.DistribcellFilter): - # Create list of cell instance IDs for distribcell Filters - bins = list(range(self_filter.num_bins)) - - elif isinstance(self_filter, openmc.EnergyFunctionFilter): - # EnergyFunctionFilters don't have bins so just add a None - bins = [None] - - else: - # Create list of IDs for bins for all other filter types - bins = self_filter.bins - - # Add indices for each bin in this Filter to the list - indices = np.array([self_filter.get_bin_index(b) for b in bins]) - filter_indices.append(indices) - - # Account for stride in each of the previous filters - for indices in filter_indices[:i]: - indices *= self_filter.num_bins - - # Apply outer product sum between all filter bin indices - filter_indices = list(map(sum, product(*filter_indices))) - - # If user did not specify any specific Filters, use them all - else: - filter_indices = np.arange(self.num_filter_bins) - - return filter_indices - - def get_nuclide_indices(self, nuclides): - """Get indices into the nuclide axis of this tally's data arrays. - - This is a helper method for the Tally.get_values(...) method to - extract tally data. This method returns the indices into the nuclide - axis of the tally's data array (axis=1) for one or more nuclides. - - Parameters - ---------- - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - - Returns - ------- - numpy.ndarray - A NumPy array of the nuclide indices - - """ - - cv.check_iterable_type('nuclides', nuclides, str) - - # Determine the score indices from any of the requested scores - if nuclides: - nuclide_indices = np.zeros(len(nuclides), dtype=int) - for i, nuclide in enumerate(nuclides): - nuclide_indices[i] = self.get_nuclide_index(nuclide) - - # If user did not specify any specific Nuclides, use them all - else: - nuclide_indices = np.arange(self.num_nuclides) - - return nuclide_indices - - def get_score_indices(self, scores): - """Get indices into the score axis of this tally's data arrays. - - This is a helper method for the Tally.get_values(...) method to - extract tally data. This method returns the indices into the score - axis of the tally's data array (axis=2) for one or more scores. - - Parameters - ---------- - scores : list of str - A list of one or more score strings - (e.g., ['absorption', 'nu-fission']; default is []) - - Returns - ------- - numpy.ndarray - A NumPy array of the score indices - - """ - - for score in scores: - if not isinstance(score, (str, openmc.CrossScore)): - msg = 'Unable to get score indices for score "{0}" in Tally ' \ - 'ID="{1}" since it is not a string or CrossScore'\ - .format(score, self.id) - raise ValueError(msg) - - # Determine the score indices from any of the requested scores - if scores: - score_indices = np.zeros(len(scores), dtype=int) - for i, score in enumerate(scores): - score_indices[i] = self.get_score_index(score) - - # If user did not specify any specific scores, use them all - else: - score_indices = np.arange(self.num_scores) - - return score_indices - - def get_values(self, scores=[], filters=[], filter_bins=[], - nuclides=[], value='mean'): - """Returns one or more tallied values given a list of scores, filters, - filter bins and nuclides. - - This method constructs a 3D NumPy array for the requested Tally data - indexed by filter bin, nuclide bin, and score index. The method will - order the data in the array as specified in the parameter lists. - - Parameters - ---------- - scores : list of str - A list of one or more score strings - (e.g., ['absorption', 'nu-fission']; default is []) - filters : Iterable of openmc.FilterMeta - An iterable of filter types - (e.g., [MeshFilter, EnergyFilter]; default is []) - filter_bins : list of Iterables - A list of tuples of filter bins corresponding to the filter_types - parameter (e.g., [(1,), ((0., 0.625e-6),)]; default is []). Each - tuple contains bins for the corresponding filter type in the filters - parameter. Each bins is the integer ID for 'material', 'surface', - 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer - for the cell instance ID for 'distribcell' Filters. Each bin is a - 2-tuple of floats for 'energy' and 'energyout' filters corresponding - to the energy boundaries of the bin of interest. The bin is an - (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell - of interest. The order of the bins in the list must correspond to - the filter_types parameter. - nuclides : list of str - A list of nuclide name strings - (e.g., ['U235', 'U238']; default is []) - value : str - A string for the type of value to return - 'mean' (default), - 'std_dev', 'rel_err', 'sum', or 'sum_sq' are accepted - - Returns - ------- - float or numpy.ndarray - A scalar or NumPy array of the Tally data indexed in the order - each filter, nuclide and score is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data, - or the input parameters do not correspond to the Tally's attributes, - e.g., if the score(s) do not match those in the Tally. - - """ - - # Ensure that the tally has data - if (value == 'mean' and self.mean is None) or \ - (value == 'std_dev' and self.std_dev is None) or \ - (value == 'rel_err' and self.mean is None) or \ - (value == 'sum' and self.sum is None) or \ - (value == 'sum_sq' and self.sum_sq is None): - msg = 'The Tally ID="{0}" has no data to return'.format(self.id) - raise ValueError(msg) - - # Get filter, nuclide and score indices - filter_indices = self.get_filter_indices(filters, filter_bins) - nuclide_indices = self.get_nuclide_indices(nuclides) - score_indices = self.get_score_indices(scores) - - # Construct outer product of all three index types with each other - indices = np.ix_(filter_indices, nuclide_indices, score_indices) - - # Return the desired result from Tally - if value == 'mean': - data = self.mean[indices] - elif value == 'std_dev': - data = self.std_dev[indices] - elif value == 'rel_err': - data = self.std_dev[indices] / self.mean[indices] - elif value == 'sum': - data = self.sum[indices] - elif value == 'sum_sq': - data = self.sum_sq[indices] - else: - msg = 'Unable to return results from Tally ID="{0}" since the ' \ - 'the requested value "{1}" is not \'mean\', \'std_dev\', ' \ - '\'rel_err\', \'sum\', or \'sum_sq\''.format(self.id, value) - raise LookupError(msg) - - return data - - def get_pandas_dataframe(self, filters=True, nuclides=True, scores=True, - derivative=True, paths=True, float_format='{:.2e}'): - """Build a Pandas DataFrame for the Tally data. - - This method constructs a Pandas DataFrame object for the Tally data - with columns annotated by filter, nuclide and score bin information. - - This capability has been tested for Pandas >=0.13.1. However, it is - recommended to use v0.16 or newer versions of Pandas since this method - uses the Multi-index Pandas feature. - - Parameters - ---------- - filters : bool - Include columns with filter bin information (default is True). - nuclides : bool - Include columns with nuclide bin information (default is True). - scores : bool - Include columns with score bin information (default is True). - derivative : bool - Include columns with differential tally info (default is True). - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into a - Multi-index column with a geometric "path" to each distribcell - instance. - float_format : str - All floats in the DataFrame will be formatted using the given - format string before printing. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with each column annotated by filter, nuclide and - score bin information (if these parameters are True), and the mean - and standard deviation of the Tally's data. - - Raises - ------ - KeyError - When this method is called before the Tally is populated with data - - """ - - # Ensure that the tally has data - if self.mean is None or self.std_dev is None: - msg = 'The Tally ID="{0}" has no data to return'.format(self.id) - raise KeyError(msg) - - # Initialize a pandas dataframe for the tally data - df = pd.DataFrame() - - # Find the total length of the tally data array - data_size = self.mean.size - - # Build DataFrame columns for filters if user requested them - if filters: - # Append each Filter's DataFrame to the overall DataFrame - for f, stride in zip(self.filters, self.filter_strides): - filter_df = f.get_pandas_dataframe( - data_size, stride, paths=paths) - df = pd.concat([df, filter_df], axis=1) - - # Include DataFrame column for nuclides if user requested it - if nuclides: - nuclides = [] - column_name = 'nuclide' - - for nuclide in self.nuclides: - if isinstance(nuclide, openmc.Nuclide): - nuclides.append(nuclide.name) - elif isinstance(nuclide, openmc.AggregateNuclide): - nuclides.append(nuclide.name) - column_name = '{0}(nuclide)'.format(nuclide.aggregate_op) - else: - nuclides.append(nuclide) - - # Tile the nuclide bins into a DataFrame column - nuclides = np.repeat(nuclides, len(self.scores)) - tile_factor = data_size / len(nuclides) - df[column_name] = np.tile(nuclides, int(tile_factor)) - - # Include column for scores if user requested it - if scores: - scores = [] - column_name = 'score' - - for score in self.scores: - if isinstance(score, (str, openmc.CrossScore)): - scores.append(str(score)) - elif isinstance(score, openmc.AggregateScore): - scores.append(score.name) - column_name = '{0}(score)'.format(score.aggregate_op) - - tile_factor = data_size / len(self.scores) - df[column_name] = np.tile(scores, int(tile_factor)) - - # Include columns for derivatives if user requested it - if derivative and (self.derivative is not None): - df['d_variable'] = self.derivative.variable - if self.derivative.material is not None: - df['d_material'] = self.derivative.material - if self.derivative.nuclide is not None: - df['d_nuclide'] = self.derivative.nuclide - - # Append columns with mean, std. dev. for each tally bin - df['mean'] = self.mean.ravel() - df['std. dev.'] = self.std_dev.ravel() - - df = df.dropna(axis=1) - - # Expand the columns into Pandas MultiIndices for readability - if pd.__version__ >= '0.16': - columns = copy.deepcopy(df.columns.values) - - # Convert all elements in columns list to tuples - for i, column in enumerate(columns): - if not isinstance(column, tuple): - columns[i] = (column,) - - # Make each tuple the same length - max_len_column = len(max(columns, key=len)) - for i, column in enumerate(columns): - delta_len = max_len_column - len(column) - if delta_len > 0: - new_column = list(column) - new_column.extend(['']*delta_len) - columns[i] = tuple(new_column) - - # Create and set a MultiIndex for the DataFrame's columns, but only - # if any column actually is multi-level (e.g., a mesh filter) - if any(len(c) > 1 for c in columns): - df.columns = pd.MultiIndex.from_tuples(columns) - - # Modify the df.to_string method so that it prints formatted strings. - # Credit to http://stackoverflow.com/users/3657742/chrisb for this trick - df.to_string = partial(df.to_string, float_format=float_format.format) - - return df - - def get_reshaped_data(self, value='mean'): - """Returns an array of tally data with one dimension per filter. - - The tally data in OpenMC is stored as a 3D array with the dimensions - corresponding to filters, nuclides and scores. As a result, tally data - can be opaque for a user to directly index (i.e., without use of - :meth:`openmc.Tally.get_values`) since one must know how to properly use - the number of bins and strides for each filter to index into the first - (filter) dimension. - - This builds and returns a reshaped version of the tally data array with - unique dimensions corresponding to each tally filter. For example, - suppose this tally has arrays of data with shape (8,5,5) corresponding - to two filters (2 and 4 bins, respectively), five nuclides and five - scores. This method will return a version of the data array with the - with a new shape of (2,4,5,5) such that the first two dimensions - correspond directly to the two filters with two and four bins. - - Parameters - ---------- - value : str - A string for the type of value to return - 'mean' (default), - 'std_dev', 'rel_err', 'sum', or 'sum_sq' are accepted - - Returns - ------- - numpy.ndarray - The tally data array indexed by filters, nuclides and scores. - - """ - - # Get the 3D array of data in filters, nuclides and scores - data = self.get_values(value=value) - - # Build a new array shape with one dimension per filter - new_shape = tuple(f.num_bins for f in self.filters) - new_shape += (self.num_nuclides, self.num_scores) - - # Reshape the data with one dimension for each filter - data = np.reshape(data, new_shape) - return data - - def hybrid_product(self, other, binary_op, filter_product=None, - nuclide_product=None, score_product=None): - """Combines filters, scores and nuclides with another tally. - - This is a helper method for the tally arithmetic operator overloaded - methods. It is called a "hybrid product" because it performs a - combination of tensor (or Kronecker) and entrywise (or Hadamard) - products. The filters from both tallies are combined using an entrywise - (or Hadamard) product on matching filters. By default, if all nuclides - are identical in the two tallies, the entrywise product is performed - across nuclides; else the tensor product is performed. By default, if - all scores are identical in the two tallies, the entrywise product is - performed across scores; else the tensor product is performed. Users - can also call the method explicitly and specify the desired product. - - Parameters - ---------- - other : openmc.Tally - The tally on the right hand side of the hybrid product - binary_op : {'+', '-', '*', '/', '^'} - The binary operation in the hybrid product - filter_product : {'tensor', 'entrywise' or None} - The type of product (tensor or entrywise) to be performed between - filter data. The default is the entrywise product. Currently only - the entrywise product is supported since a tally cannot contain - two of the same filter. - nuclide_product : {'tensor', 'entrywise' or None} - The type of product (tensor or entrywise) to be performed between - nuclide data. The default is the entrywise product if all nuclides - between the two tallies are the same; otherwise the default is - the tensor product. - score_product : {'tensor', 'entrywise' or None} - The type of product (tensor or entrywise) to be performed between - score data. The default is the entrywise product if all scores - between the two tallies are the same; otherwise the default is - the tensor product. - - Returns - ------- - openmc.Tally - A new Tally that is the hybrid product with this one. - - Raises - ------ - ValueError - When this method is called before the other tally is populated - with data. - - """ - - # Set default value for filter product if it was not set - if filter_product is None: - filter_product = 'entrywise' - elif filter_product == 'tensor': - msg = 'Unable to perform Tally arithmetic with a tensor product' \ - 'for the filter data as this is not currently supported.' - raise ValueError(msg) - - # Set default value for nuclide product if it was not set - if nuclide_product is None: - if self.nuclides == other.nuclides: - nuclide_product = 'entrywise' - else: - nuclide_product = 'tensor' - - # Set default value for score product if it was not set - if score_product is None: - if self.scores == other.scores: - score_product = 'entrywise' - else: - score_product = 'tensor' - - # Check product types - cv.check_value('filter product', filter_product, _PRODUCT_TYPES) - cv.check_value('nuclide product', nuclide_product, _PRODUCT_TYPES) - cv.check_value('score product', score_product, _PRODUCT_TYPES) - - # Check that results have been read - if not other.derived and other.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(other.id) - raise ValueError(msg) - - new_tally = Tally() - new_tally._derived = True - new_tally.with_batch_statistics = True - new_tally._num_realizations = self.num_realizations - new_tally._estimator = self.estimator - new_tally._with_summary = self.with_summary - new_tally._sp_filename = self._sp_filename - - # Construct a combined derived name from the two tally operands - if self.name != '' and other.name != '': - new_name = '({0} {1} {2})'.format(self.name, binary_op, other.name) - new_tally.name = new_name - - # Query the mean and std dev so the tally data is read in from file - # if it has not already been read in. - self.mean, self.std_dev, other.mean, other.std_dev - - # Create copies of self and other tallies to rearrange for tally - # arithmetic - self_copy = copy.deepcopy(self) - other_copy = copy.deepcopy(other) - - self_copy.sparse = False - other_copy.sparse = False - - # Align the tally data based on desired hybrid product - data = self_copy._align_tally_data(other_copy, filter_product, - nuclide_product, score_product) - - # Perform tally arithmetic operation - if binary_op == '+': - new_tally._mean = data['self']['mean'] + data['other']['mean'] - new_tally._std_dev = np.sqrt(data['self']['std. dev.']**2 + - data['other']['std. dev.']**2) - elif binary_op == '-': - new_tally._mean = data['self']['mean'] - data['other']['mean'] - new_tally._std_dev = np.sqrt(data['self']['std. dev.']**2 + - data['other']['std. dev.']**2) - elif binary_op == '*': - with np.errstate(divide='ignore', invalid='ignore'): - self_rel_err = data['self']['std. dev.'] / data['self']['mean'] - other_rel_err = data['other']['std. dev.'] / data['other']['mean'] - new_tally._mean = data['self']['mean'] * data['other']['mean'] - new_tally._std_dev = np.abs(new_tally.mean) * \ - np.sqrt(self_rel_err**2 + other_rel_err**2) - elif binary_op == '/': - with np.errstate(divide='ignore', invalid='ignore'): - self_rel_err = data['self']['std. dev.'] / data['self']['mean'] - other_rel_err = data['other']['std. dev.'] / data['other']['mean'] - new_tally._mean = data['self']['mean'] / data['other']['mean'] - new_tally._std_dev = np.abs(new_tally.mean) * \ - np.sqrt(self_rel_err**2 + other_rel_err**2) - elif binary_op == '^': - with np.errstate(divide='ignore', invalid='ignore'): - mean_ratio = data['other']['mean'] / data['self']['mean'] - first_term = mean_ratio * data['self']['std. dev.'] - second_term = \ - np.log(data['self']['mean']) * data['other']['std. dev.'] - new_tally._mean = data['self']['mean'] ** data['other']['mean'] - new_tally._std_dev = np.abs(new_tally.mean) * \ - np.sqrt(first_term**2 + second_term**2) - - # Convert any infs and nans to zero - new_tally._mean[np.isinf(new_tally._mean)] = 0 - new_tally._mean = np.nan_to_num(new_tally._mean) - new_tally._std_dev[np.isinf(new_tally._std_dev)] = 0 - new_tally._std_dev = np.nan_to_num(new_tally._std_dev) - - # Set tally attributes - if self_copy.estimator == other_copy.estimator: - new_tally.estimator = self_copy.estimator - if self_copy.with_summary and other_copy.with_summary: - new_tally.with_summary = self_copy.with_summary - if self_copy.num_realizations == other_copy.num_realizations: - new_tally.num_realizations = self_copy.num_realizations - - # Add filters to the new tally - if filter_product == 'entrywise': - for self_filter in self_copy.filters: - new_tally.filters.append(self_filter) - else: - all_filters = [self_copy.filters, other_copy.filters] - for self_filter, other_filter in product(*all_filters): - new_filter = openmc.CrossFilter(self_filter, other_filter, - binary_op) - new_tally.filters.append(new_filter) - - # Add nuclides to the new tally - if nuclide_product == 'entrywise': - for self_nuclide in self_copy.nuclides: - new_tally.nuclides.append(self_nuclide) - else: - all_nuclides = [self_copy.nuclides, other_copy.nuclides] - for self_nuclide, other_nuclide in product(*all_nuclides): - new_nuclide = openmc.CrossNuclide(self_nuclide, other_nuclide, - binary_op) - new_tally.nuclides.append(new_nuclide) - - # Define helper function that handles score units appropriately - # depending on the binary operator - def cross_score(score1, score2, binary_op): - if binary_op == '+' or binary_op == '-': - if score1 == score2: - return score1 - else: - return openmc.CrossScore(score1, score2, binary_op) - else: - return openmc.CrossScore(score1, score2, binary_op) - - # Add scores to the new tally - if score_product == 'entrywise': - for self_score in self_copy.scores: - new_score = cross_score(self_score, self_score, binary_op) - new_tally.scores.append(new_score) - else: - all_scores = [self_copy.scores, other_copy.scores] - for self_score, other_score in product(*all_scores): - new_score = cross_score(self_score, other_score, binary_op) - new_tally.scores.append(new_score) - - return new_tally - - @property - def filter_strides(self): - all_strides = [] - stride = self.num_nuclides * self.num_scores - for self_filter in reversed(self.filters): - all_strides.append(stride) - stride *= self_filter.num_bins - return all_strides[::-1] - - def _align_tally_data(self, other, filter_product, nuclide_product, - score_product): - """Aligns data from two tallies for tally arithmetic. - - This is a helper method to construct a dict of dicts of the "aligned" - data arrays from each tally for tally arithmetic. The method analyzes - the filters, scores and nuclides in both tallies and determines how to - appropriately align the data for vectorized arithmetic. For example, - if the two tallies have different filters, this method will use NumPy - 'tile' and 'repeat' operations to the new data arrays such that all - possible combinations of the data in each tally's bins will be made - when the arithmetic operation is applied to the arrays. - - Parameters - ---------- - other : openmc.Tally - The tally to outer product with this tally - filter_product : {'entrywise'} - The type of product to be performed between filter data. Currently, - only the entrywise product is supported for the filter product. - nuclide_product : {'tensor', 'entrywise'} - The type of product (tensor or entrywise) to be performed between - nuclide data. - score_product : {'tensor', 'entrywise'} - The type of product (tensor or entrywise) to be performed between - score data. - - Returns - ------- - dict - A dictionary of dictionaries to "aligned" 'mean' and 'std. dev' - NumPy arrays for each tally's data. - - """ - - # Get the set of filters that each tally is missing - other_missing_filters = set(self.filters) - set(other.filters) - self_missing_filters = set(other.filters) - set(self.filters) - - # Add filters present in self but not in other to other - for other_filter in other_missing_filters: - filter_copy = copy.deepcopy(other_filter) - other._mean = np.repeat(other.mean, filter_copy.num_bins, axis=0) - other._std_dev = np.repeat(other.std_dev, filter_copy.num_bins, axis=0) - other.filters.append(filter_copy) - - # Add filters present in other but not in self to self - for self_filter in self_missing_filters: - filter_copy = copy.deepcopy(self_filter) - self._mean = np.repeat(self.mean, filter_copy.num_bins, axis=0) - self._std_dev = np.repeat(self.std_dev, filter_copy.num_bins, axis=0) - self.filters.append(filter_copy) - - # Align other filters with self filters - for i, self_filter in enumerate(self.filters): - other_index = other.filters.index(self_filter) - - # If necessary, swap other filter - if other_index != i: - other._swap_filters(self_filter, other.filters[i]) - - # Repeat and tile the data by nuclide in preparation for performing - # the tensor product across nuclides. - if nuclide_product == 'tensor': - self._mean = np.repeat(self.mean, other.num_nuclides, axis=1) - self._std_dev = np.repeat(self.std_dev, other.num_nuclides, axis=1) - other._mean = np.tile(other.mean, (1, self.num_nuclides, 1)) - other._std_dev = np.tile(other.std_dev, (1, self.num_nuclides, 1)) - - # Add nuclides to each tally such that each tally contains the complete - # set of nuclides necessary to perform an entrywise product. New - # nuclides added to a tally will have all their scores set to zero. - else: - - # Get the set of nuclides that each tally is missing - other_missing_nuclides = set(self.nuclides) - set(other.nuclides) - self_missing_nuclides = set(other.nuclides) - set(self.nuclides) - - # Add nuclides present in self but not in other to other - for nuclide in other_missing_nuclides: - other._mean = np.insert(other.mean, other.num_nuclides, 0, axis=1) - other._std_dev = np.insert(other.std_dev, other.num_nuclides, 0, - axis=1) - other.nuclides.append(nuclide) - - # Add nuclides present in other but not in self to self - for nuclide in self_missing_nuclides: - self._mean = np.insert(self.mean, self.num_nuclides, 0, axis=1) - self._std_dev = np.insert(self.std_dev, self.num_nuclides, 0, - axis=1) - self.nuclides.append(nuclide) - - # Align other nuclides with self nuclides - for i, nuclide in enumerate(self.nuclides): - other_index = other.get_nuclide_index(nuclide) - - # If necessary, swap other nuclide - if other_index != i: - other._swap_nuclides(nuclide, other.nuclides[i]) - - # Repeat and tile the data by score in preparation for performing - # the tensor product across scores. - if score_product == 'tensor': - self._mean = np.repeat(self.mean, other.num_scores, axis=2) - self._std_dev = np.repeat(self.std_dev, other.num_scores, axis=2) - other._mean = np.tile(other.mean, (1, 1, self.num_scores)) - other._std_dev = np.tile(other.std_dev, (1, 1, self.num_scores)) - - # Add scores to each tally such that each tally contains the complete set - # of scores necessary to perform an entrywise product. New scores added - # to a tally will be set to zero. - else: - - # Get the set of scores that each tally is missing - other_missing_scores = set(self.scores) - set(other.scores) - self_missing_scores = set(other.scores) - set(self.scores) - - # Add scores present in self but not in other to other - for score in other_missing_scores: - other._mean = np.insert(other.mean, other.num_scores, 0, axis=2) - other._std_dev = np.insert(other.std_dev, other.num_scores, 0, axis=2) - other.scores.append(score) - - # Add scores present in other but not in self to self - for score in self_missing_scores: - self._mean = np.insert(self.mean, self.num_scores, 0, axis=2) - self._std_dev = np.insert(self.std_dev, self.num_scores, 0, axis=2) - self.scores.append(score) - - # Align other scores with self scores - for i, score in enumerate(self.scores): - other_index = other.scores.index(score) - - # If necessary, swap other score - if other_index != i: - other._swap_scores(score, other.scores[i]) - - data = {} - data['self'] = {} - data['other'] = {} - data['self']['mean'] = self.mean - data['other']['mean'] = other.mean - data['self']['std. dev.'] = self.std_dev - data['other']['std. dev.'] = other.std_dev - return data - - def _swap_filters(self, filter1, filter2): - """Reverse the ordering of two filters in this tally - - This is a helper method for tally arithmetic which helps align the data - in two tallies with shared filters. This method reverses the order of - the two filters in place. - - Parameters - ---------- - filter1 : Filter - The filter to swap with filter2 - filter2 : Filter - The filter to swap with filter1 - - Raises - ------ - ValueError - If this is a derived tally or this method is called before the tally - is populated with data. - - """ - - cv.check_type('filter1', filter1, _FILTER_CLASSES) - cv.check_type('filter2', filter2, _FILTER_CLASSES) - - # Check that the filters exist in the tally and are not the same - if filter1 == filter2: - return - elif filter1 not in self.filters: - msg = 'Unable to swap "{0}" filter1 in Tally ID="{1}" since it ' \ - 'does not contain such a filter'.format(filter1.type, self.id) - raise ValueError(msg) - elif filter2 not in self.filters: - msg = 'Unable to swap "{0}" filter2 in Tally ID="{1}" since it ' \ - 'does not contain such a filter'.format(filter2.type, self.id) - raise ValueError(msg) - - # Construct lists of tuples for the bins in each of the two filters - filters = [type(filter1), type(filter2)] - if isinstance(filter1, openmc.DistribcellFilter): - filter1_bins = [b for b in range(filter1.num_bins)] - elif isinstance(filter1, openmc.EnergyFunctionFilter): - filter1_bins = [None] - else: - filter1_bins = filter1.bins - - if isinstance(filter2, openmc.DistribcellFilter): - filter2_bins = [b for b in range(filter2.num_bins)] - elif isinstance(filter2, openmc.EnergyFunctionFilter): - filter2_bins = [None] - else: - filter2_bins = filter2.bins - - # Create variables to store views of data in the misaligned structure - mean = {} - std_dev = {} - - # Store the data from the misaligned structure - for i, (bin1, bin2) in enumerate(product(filter1_bins, filter2_bins)): - filter_bins = [(bin1,), (bin2,)] - - if self.mean is not None: - mean[i] = self.get_values( - filters=filters, filter_bins=filter_bins, value='mean') - - if self.std_dev is not None: - std_dev[i] = self.get_values( - filters=filters, filter_bins=filter_bins, value='std_dev') - - # Swap the filters in the copied version of this Tally - filter1_index = self.filters.index(filter1) - filter2_index = self.filters.index(filter2) - self.filters[filter1_index] = filter2 - self.filters[filter2_index] = filter1 - - # Realign the data - for i, (bin1, bin2) in enumerate(product(filter1_bins, filter2_bins)): - filter_bins = [(bin1,), (bin2,)] - indices = self.get_filter_indices(filters, filter_bins) - - if self.mean is not None: - self.mean[indices, :, :] = mean[i] - - if self.std_dev is not None: - self.std_dev[indices, :, :] = std_dev[i] - - def _swap_nuclides(self, nuclide1, nuclide2): - """Reverse the ordering of two nuclides in this tally - - This is a helper method for tally arithmetic which helps align the data - in two tallies with shared nuclides. This method reverses the order of - the two nuclides in place. - - Parameters - ---------- - nuclide1 : Nuclide - The nuclide to swap with nuclide2 - - nuclide2 : Nuclide - The nuclide to swap with nuclide1 - - Raises - ------ - ValueError - If this is a derived tally or this method is called before the tally - is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - cv.check_type('nuclide1', nuclide1, _NUCLIDE_CLASSES) - cv.check_type('nuclide2', nuclide2, _NUCLIDE_CLASSES) - - # Check that the nuclides exist in the tally and are not the same - if nuclide1 == nuclide2: - msg = 'Unable to swap a nuclide with itself' - raise ValueError(msg) - elif nuclide1 not in self.nuclides: - msg = 'Unable to swap nuclide1 "{0}" in Tally ID="{1}" since it ' \ - 'does not contain such a nuclide'\ - .format(nuclide1.name, self.id) - raise ValueError(msg) - elif nuclide2 not in self.nuclides: - msg = 'Unable to swap "{0}" nuclide2 in Tally ID="{1}" since it ' \ - 'does not contain such a nuclide'\ - .format(nuclide2.name, self.id) - raise ValueError(msg) - - # Swap the nuclides in the Tally - nuclide1_index = self.get_nuclide_index(nuclide1) - nuclide2_index = self.get_nuclide_index(nuclide2) - self.nuclides[nuclide1_index] = nuclide2 - self.nuclides[nuclide2_index] = nuclide1 - - # Adjust the mean data array to relect the new nuclide order - if self.mean is not None: - nuclide1_mean = self.mean[:, nuclide1_index, :].copy() - nuclide2_mean = self.mean[:, nuclide2_index, :].copy() - self.mean[:, nuclide2_index, :] = nuclide1_mean - self.mean[:, nuclide1_index, :] = nuclide2_mean - - # Adjust the std_dev data array to relect the new nuclide order - if self.std_dev is not None: - nuclide1_std_dev = self.std_dev[:, nuclide1_index, :].copy() - nuclide2_std_dev = self.std_dev[:, nuclide2_index, :].copy() - self.std_dev[:, nuclide2_index, :] = nuclide1_std_dev - self.std_dev[:, nuclide1_index, :] = nuclide2_std_dev - - def _swap_scores(self, score1, score2): - """Reverse the ordering of two scores in this tally - - This is a helper method for tally arithmetic which helps align the data - in two tallies with shared scores. This method reverses the order - of the two scores in place. - - Parameters - ---------- - score1 : str or CrossScore - The score to swap with score2 - - score2 : str or CrossScore - The score to swap with score1 - - Raises - ------ - ValueError - If this is a derived tally or this method is called before the tally - is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - # Check that the scores are valid - if not isinstance(score1, (str, openmc.CrossScore)): - msg = 'Unable to swap score1 "{0}" in Tally ID="{1}" since it is ' \ - 'not a string or CrossScore'.format(score1, self.id) - raise ValueError(msg) - elif not isinstance(score2, (str, openmc.CrossScore)): - msg = 'Unable to swap score2 "{0}" in Tally ID="{1}" since it is ' \ - 'not a string or CrossScore'.format(score2, self.id) - raise ValueError(msg) - - # Check that the scores exist in the tally and are not the same - if score1 == score2: - msg = 'Unable to swap a score with itself' - raise ValueError(msg) - elif score1 not in self.scores: - msg = 'Unable to swap score1 "{0}" in Tally ID="{1}" since it ' \ - 'does not contain such a score'.format(score1, self.id) - raise ValueError(msg) - elif score2 not in self.scores: - msg = 'Unable to swap score2 "{0}" in Tally ID="{1}" since it ' \ - 'does not contain such a score'.format(score2, self.id) - raise ValueError(msg) - - # Swap the scores in the Tally - score1_index = self.get_score_index(score1) - score2_index = self.get_score_index(score2) - self.scores[score1_index] = score2 - self.scores[score2_index] = score1 - - # Adjust the mean data array to relect the new nuclide order - if self.mean is not None: - score1_mean = self.mean[:, :, score1_index].copy() - score2_mean = self.mean[:, :, score2_index].copy() - self.mean[:, :, score2_index] = score1_mean - self.mean[:, :, score1_index] = score2_mean - - # Adjust the std_dev data array to relect the new nuclide order - if self.std_dev is not None: - score1_std_dev = self.std_dev[:, :, score1_index].copy() - score2_std_dev = self.std_dev[:, :, score2_index].copy() - self.std_dev[:, :, score2_index] = score1_std_dev - self.std_dev[:, :, score1_index] = score2_std_dev - - def __add__(self, other): - """Adds this tally to another tally or scalar value. - - This method builds a new tally with data that is the sum of this - tally's data and that from the other tally or scalar value. If the - filters, scores and nuclides in the two tallies are not the same, then - they are combined in all possible ways in the new derived tally. - - Uncertainty propagation is used to compute the standard deviation - for the new tally's data. It is important to note that this makes - the assumption that the tally data is independently distributed. - In most use cases, this is *not* true and may lead to under-prediction - of the uncertainty. The uncertainty propagation model is from the - following source: - - https://en.wikipedia.org/wiki/Propagation_of_uncertainty - - Parameters - ---------- - other : openmc.Tally or float - The tally or scalar value to add to this tally - - Returns - ------- - openmc.Tally - A new derived tally which is the sum of this tally and the other - tally or scalar value in the addition. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - if isinstance(other, Tally): - new_tally = self.hybrid_product(other, binary_op='+') - - # If both tally operands were sparse, sparsify the new tally - if self.sparse and other.sparse: - new_tally.sparse = True - - elif isinstance(other, Real): - new_tally = Tally(name='derived') - new_tally._derived = True - new_tally.with_batch_statistics = True - new_tally.name = self.name - new_tally._mean = self.mean + other - new_tally._std_dev = self.std_dev - new_tally.estimator = self.estimator - new_tally.with_summary = self.with_summary - new_tally.num_realizations = self.num_realizations - - new_tally.filters = copy.deepcopy(self.filters) - new_tally.nuclides = copy.deepcopy(self.nuclides) - new_tally.scores = copy.deepcopy(self.scores) - - # If this tally operand is sparse, sparsify the new tally - new_tally.sparse = self.sparse - - else: - msg = 'Unable to add "{0}" to Tally ID="{1}"'.format(other, self.id) - raise ValueError(msg) - - return new_tally - - def __sub__(self, other): - """Subtracts another tally or scalar value from this tally. - - This method builds a new tally with data that is the difference of - this tally's data and that from the other tally or scalar value. If the - filters, scores and nuclides in the two tallies are not the same, then - they are combined in all possible ways in the new derived tally. - - Uncertainty propagation is used to compute the standard deviation - for the new tally's data. It is important to note that this makes - the assumption that the tally data is independently distributed. - In most use cases, this is *not* true and may lead to under-prediction - of the uncertainty. The uncertainty propagation model is from the - following source: - - https://en.wikipedia.org/wiki/Propagation_of_uncertainty - - Parameters - ---------- - other : openmc.Tally or float - The tally or scalar value to subtract from this tally - - Returns - ------- - openmc.Tally - A new derived tally which is the difference of this tally and the - other tally or scalar value in the subtraction. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - if isinstance(other, Tally): - new_tally = self.hybrid_product(other, binary_op='-') - - # If both tally operands were sparse, sparsify the new tally - if self.sparse and other.sparse: - new_tally.sparse = True - - elif isinstance(other, Real): - new_tally = Tally(name='derived') - new_tally._derived = True - new_tally.name = self.name - new_tally._mean = self.mean - other - new_tally._std_dev = self.std_dev - new_tally.estimator = self.estimator - new_tally.with_summary = self.with_summary - new_tally.num_realizations = self.num_realizations - - new_tally.filters = copy.deepcopy(self.filters) - new_tally.nuclides = copy.deepcopy(self.nuclides) - new_tally.scores = copy.deepcopy(self.scores) - - # If this tally operand is sparse, sparsify the new tally - new_tally.sparse = self.sparse - - else: - msg = 'Unable to subtract "{0}" from Tally ' \ - 'ID="{1}"'.format(other, self.id) - raise ValueError(msg) - - return new_tally - - def __mul__(self, other): - """Multiplies this tally with another tally or scalar value. - - This method builds a new tally with data that is the product of - this tally's data and that from the other tally or scalar value. If the - filters, scores and nuclides in the two tallies are not the same, then - they are combined in all possible ways in the new derived tally. - - Uncertainty propagation is used to compute the standard deviation - for the new tally's data. It is important to note that this makes - the assumption that the tally data is independently distributed. - In most use cases, this is *not* true and may lead to under-prediction - of the uncertainty. The uncertainty propagation model is from the - following source: - - https://en.wikipedia.org/wiki/Propagation_of_uncertainty - - Parameters - ---------- - other : openmc.Tally or float - The tally or scalar value to multiply with this tally - - Returns - ------- - openmc.Tally - A new derived tally which is the product of this tally and the - other tally or scalar value in the multiplication. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - if isinstance(other, Tally): - new_tally = self.hybrid_product(other, binary_op='*') - - # If original tally operands were sparse, sparsify the new tally - if self.sparse and other.sparse: - new_tally.sparse = True - - elif isinstance(other, Real): - new_tally = Tally(name='derived') - new_tally._derived = True - new_tally.name = self.name - new_tally._mean = self.mean * other - new_tally._std_dev = self.std_dev * np.abs(other) - new_tally.estimator = self.estimator - new_tally.with_summary = self.with_summary - new_tally.num_realizations = self.num_realizations - - new_tally.filters = copy.deepcopy(self.filters) - new_tally.nuclides = copy.deepcopy(self.nuclides) - new_tally.scores = copy.deepcopy(self.scores) - - # If this tally operand is sparse, sparsify the new tally - new_tally.sparse = self.sparse - - else: - msg = 'Unable to multiply Tally ID="{0}" ' \ - 'by "{1}"'.format(self.id, other) - raise ValueError(msg) - - return new_tally - - def __truediv__(self, other): - """Divides this tally by another tally or scalar value. - - This method builds a new tally with data that is the dividend of - this tally's data and that from the other tally or scalar value. If the - filters, scores and nuclides in the two tallies are not the same, then - they are combined in all possible ways in the new derived tally. - - Uncertainty propagation is used to compute the standard deviation - for the new tally's data. It is important to note that this makes - the assumption that the tally data is independently distributed. - In most use cases, this is *not* true and may lead to under-prediction - of the uncertainty. The uncertainty propagation model is from the - following source: - - https://en.wikipedia.org/wiki/Propagation_of_uncertainty - - Parameters - ---------- - other : openmc.Tally or float - The tally or scalar value to divide this tally by - - Returns - ------- - openmc.Tally - A new derived tally which is the dividend of this tally and the - other tally or scalar value in the division. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - if isinstance(other, Tally): - new_tally = self.hybrid_product(other, binary_op='/') - - # If original tally operands were sparse, sparsify the new tally - if self.sparse and other.sparse: - new_tally.sparse = True - - elif isinstance(other, Real): - new_tally = Tally(name='derived') - new_tally._derived = True - new_tally.name = self.name - new_tally._mean = self.mean / other - new_tally._std_dev = self.std_dev * np.abs(1. / other) - new_tally.estimator = self.estimator - new_tally.with_summary = self.with_summary - new_tally.num_realizations = self.num_realizations - - new_tally.filters = copy.deepcopy(self.filters) - new_tally.nuclides = copy.deepcopy(self.nuclides) - new_tally.scores = copy.deepcopy(self.scores) - - # If this tally operand is sparse, sparsify the new tally - new_tally.sparse = self.sparse - - else: - msg = 'Unable to divide Tally ID="{0}" ' \ - 'by "{1}"'.format(self.id, other) - raise ValueError(msg) - - return new_tally - - def __div__(self, other): - return self.__truediv__(other) - - def __pow__(self, power): - """Raises this tally to another tally or scalar value power. - - This method builds a new tally with data that is the power of - this tally's data to that from the other tally or scalar value. If the - filters, scores and nuclides in the two tallies are not the same, then - they are combined in all possible ways in the new derived tally. - - Uncertainty propagation is used to compute the standard deviation - for the new tally's data. It is important to note that this makes - the assumption that the tally data is independently distributed. - In most use cases, this is *not* true and may lead to under-prediction - of the uncertainty. The uncertainty propagation model is from the - following source: - - https://en.wikipedia.org/wiki/Propagation_of_uncertainty - - Parameters - ---------- - power : openmc.Tally or float - The tally or scalar value exponent - - Returns - ------- - openmc.Tally - A new derived tally which is this tally raised to the power of the - other tally or scalar value in the exponentiation. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Check that results have been read - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - if isinstance(power, Tally): - new_tally = self.hybrid_product(power, binary_op='^') - - # If original tally operand was sparse, sparsify the new tally - if self.sparse: - new_tally.sparse = True - - elif isinstance(power, Real): - new_tally = Tally(name='derived') - new_tally._derived = True - new_tally.name = self.name - new_tally._mean = self._mean ** power - self_rel_err = self.std_dev / self.mean - new_tally._std_dev = np.abs(new_tally._mean * power * self_rel_err) - new_tally.estimator = self.estimator - new_tally.with_summary = self.with_summary - new_tally.num_realizations = self.num_realizations - - new_tally.filters = copy.deepcopy(self.filters) - new_tally.nuclides = copy.deepcopy(self.nuclides) - new_tally.scores = copy.deepcopy(self.scores) - - # If original tally was sparse, sparsify the exponentiated tally - new_tally.sparse = self.sparse - - else: - msg = 'Unable to raise Tally ID="{0}" to ' \ - 'power "{1}"'.format(self.id, power) - raise ValueError(msg) - - return new_tally - - def __radd__(self, other): - """Right addition with a scalar value. - - This reverses the operands and calls the __add__ method. - - Parameters - ---------- - other : float - The scalar value to add to this tally - - Returns - ------- - openmc.Tally - A new derived tally of this tally added with the scalar value. - - """ - - return self + other - - def __rsub__(self, other): - """Right subtraction from a scalar value. - - This reverses the operands and calls the __sub__ method. - - Parameters - ---------- - other : float - The scalar value to subtract this tally from - - Returns - ------- - openmc.Tally - A new derived tally of this tally subtracted from the scalar value. - - """ - - return -1. * self + other - - def __rmul__(self, other): - """Right multiplication with a scalar value. - - This reverses the operands and calls the __mul__ method. - - Parameters - ---------- - other : float - The scalar value to multiply with this tally - - Returns - ------- - openmc.Tally - A new derived tally of this tally multiplied by the scalar value. - - """ - - return self * other - - def __rdiv__(self, other): - """Right division with a scalar value. - - This reverses the operands and calls the __div__ method. - - Parameters - ---------- - other : float - The scalar value to divide by this tally - - Returns - ------- - openmc.Tally - A new derived tally of the scalar value divided by this tally. - - """ - - return other * self**-1 - - def __abs__(self): - """The absolute value of this tally. - - Returns - ------- - openmc.Tally - A new derived tally which is the absolute value of this tally. - - """ - - new_tally = copy.deepcopy(self) - new_tally._mean = np.abs(new_tally.mean) - return new_tally - - def __neg__(self): - """The negated value of this tally. - - Returns - ------- - openmc.Tally - A new derived tally which is the negated value of this tally. - - """ - - new_tally = self * -1 - return new_tally - - def get_slice(self, scores=[], filters=[], filter_bins=[], nuclides=[], - squeeze=False): - """Build a sliced tally for the specified filters, scores and nuclides. - - This method constructs a new tally to encapsulate a subset of the data - represented by this tally. The subset of data to include in the tally - slice is determined by the scores, filters and nuclides specified in - the input parameters. - - Parameters - ---------- - scores : list of str - A list of one or more score strings (e.g., ['absorption', - 'nu-fission'] - filters : Iterable of openmc.FilterMeta - An iterable of filter types (e.g., [MeshFilter, EnergyFilter]) - filter_bins : list of Iterables - A list of iterables of filter bins corresponding to the specified - filter types (e.g., [(1,), ((0., 0.625e-6),)]). Each iterable - contains bins to slice for the corresponding filter type in the - filters parameter. Each bin is the integer ID for 'material', - 'surface', 'cell', 'cellborn', and 'universe' Filters. Each bin is - an integer for the cell instance ID for 'distribcell' Filters. Each - bin is a 2-tuple of floats for 'energy' and 'energyout' filters - corresponding to the energy boundaries of the bin of interest. The - bin is an (x,y,z) 3-tuple for 'mesh' filters corresponding to the - mesh cell of interest. The order of the bins in the list must - correspond to the `filters` argument. - nuclides : list of str - A list of nuclide name strings (e.g., ['U235', 'U238']) - squeeze : bool - Whether to remove filters with only a single bin in the sliced tally - - Returns - ------- - openmc.Tally - A new tally which encapsulates the subset of data requested in the - order each filter, nuclide and score is listed in the parameters. - - Raises - ------ - ValueError - When this method is called before the Tally is populated with data. - - """ - - # Ensure that the tally has data - if not self.derived and self.sum is None: - msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \ - 'since it does not contain any results.'.format(self.id) - raise ValueError(msg) - - # Create deep copy of tally to return as sliced tally - new_tally = copy.deepcopy(self) - new_tally._derived = True - - # Differentiate Tally with a new auto-generated Tally ID - new_tally.id = None - - new_tally.sparse = False - - if not self.derived and self.sum is not None: - new_sum = self.get_values(scores, filters, filter_bins, - nuclides, 'sum') - new_tally.sum = new_sum - if not self.derived and self.sum_sq is not None: - new_sum_sq = self.get_values(scores, filters, filter_bins, - nuclides, 'sum_sq') - new_tally.sum_sq = new_sum_sq - if self.mean is not None: - new_mean = self.get_values(scores, filters, filter_bins, - nuclides, 'mean') - new_tally._mean = new_mean - if self.std_dev is not None: - new_std_dev = self.get_values(scores, filters, filter_bins, - nuclides, 'std_dev') - new_tally._std_dev = new_std_dev - - # SCORES - if scores: - score_indices = [] - - # Determine the score indices from any of the requested scores - for score in self.scores: - if score not in scores: - score_index = self.get_score_index(score) - score_indices.append(score_index) - - # Loop over indices in reverse to remove excluded scores - for score_index in reversed(score_indices): - new_tally.remove_score(self.scores[score_index]) - - # NUCLIDES - if nuclides: - nuclide_indices = [] - - # Determine the nuclide indices from any of the requested nuclides - for nuclide in self.nuclides: - if nuclide.name not in nuclides: - nuclide_index = self.get_nuclide_index(nuclide.name) - nuclide_indices.append(nuclide_index) - - # Loop over indices in reverse to remove excluded Nuclides - for nuclide_index in reversed(nuclide_indices): - new_tally.remove_nuclide(self.nuclides[nuclide_index]) - - # FILTERS - if filters: - - # Determine the filter indices from any of the requested filters - for i, filter_type in enumerate(filters): - f = new_tally.find_filter(filter_type) - - # Remove filters with only a single bin if requested - if squeeze: - if len(filter_bins[i]) == 1: - new_tally.filters.remove(f) - continue - else: - raise RuntimeError('Cannot remove sliced filter with ' - 'more than one bin.') - - # Remove and/or reorder filter bins to user specifications - bin_indices = [f.get_bin_index(b) - for b in filter_bins[i]] - bin_indices = np.unique(bin_indices) - - # Set bins for sliced filter - new_filter = copy.copy(f) - new_filter.bins = [f.bins[i] for i in bin_indices] - - # Set number of bins manually for mesh/distribcell filters - if filter_type is openmc.DistribcellFilter: - new_filter._num_bins = f._num_bins - - # Replace existing filter with new one - for j, test_filter in enumerate(new_tally.filters): - if isinstance(test_filter, filter_type): - new_tally.filters[j] = new_filter - - # If original tally was sparse, sparsify the sliced tally - new_tally.sparse = self.sparse - return new_tally - - def summation(self, scores=[], filter_type=None, - filter_bins=[], nuclides=[], remove_filter=False): - """Vectorized sum of tally data across scores, filter bins and/or - nuclides using tally aggregation. - - This method constructs a new tally to encapsulate the sum of the data - represented by the summation of the data in this tally. The tally data - sum is determined by the scores, filter bins and nuclides specified - in the input parameters. - - Parameters - ---------- - scores : list of str - A list of one or more score strings to sum across - (e.g., ['absorption', 'nu-fission']; default is []) - filter_type : openmc.FilterMeta - Type of the filter, e.g. MeshFilter - filter_bins : Iterable of int or tuple - A list of the filter bins corresponding to the filter_type parameter - Each bin in the list is the integer ID for 'material', 'surface', - 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer - for the cell instance ID for 'distribcell' Filters. Each bin is a - 2-tuple of floats for 'energy' and 'energyout' filters corresponding - to the energy boundaries of the bin of interest. Each bin is an - (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of - interest. - nuclides : list of str - A list of nuclide name strings to sum across - (e.g., ['U235', 'U238']; default is []) - remove_filter : bool - If a filter is being summed over, this bool indicates whether to - remove that filter in the returned tally. Default is False. - - Returns - ------- - openmc.Tally - A new tally which encapsulates the sum of data requested. - """ - - # Create new derived Tally for summation - tally_sum = Tally() - tally_sum._derived = True - tally_sum._estimator = self.estimator - tally_sum._num_realizations = self.num_realizations - tally_sum._with_batch_statistics = self.with_batch_statistics - tally_sum._with_summary = self.with_summary - tally_sum._sp_filename = self._sp_filename - tally_sum._results_read = self._results_read - - # Get tally data arrays reshaped with one dimension per filter - mean = self.get_reshaped_data(value='mean') - std_dev = self.get_reshaped_data(value='std_dev') - - # Sum across any filter bins specified by the user - if isinstance(filter_type, openmc.FilterMeta): - find_filter = self.find_filter(filter_type) - - # If user did not specify filter bins, sum across all bins - if len(filter_bins) == 0: - bin_indices = np.arange(find_filter.num_bins) - - if isinstance(find_filter, openmc.DistribcellFilter): - filter_bins = np.arange(find_filter.num_bins) - elif isinstance(find_filter, openmc.EnergyFunctionFilter): - filter_bins = [None] - else: - filter_bins = find_filter.bins - - # Only sum across bins specified by the user - else: - bin_indices = \ - [find_filter.get_bin_index(bin) for bin in filter_bins] - - # Sum across the bins in the user-specified filter - for i, self_filter in enumerate(self.filters): - if type(self_filter) == filter_type: - shape = mean.shape - mean = np.take(mean, indices=bin_indices, axis=i) - std_dev = np.take(std_dev, indices=bin_indices, axis=i) - - # NumPy take introduces a new dimension in output array - # for some special cases that must be removed - if len(mean.shape) > len(shape): - mean = np.squeeze(mean, axis=i) - std_dev = np.squeeze(std_dev, axis=i) - - mean = np.sum(mean, axis=i, keepdims=True) - std_dev = np.sum(std_dev**2, axis=i, keepdims=True) - std_dev = np.sqrt(std_dev) - - # Add AggregateFilter to the tally sum - if not remove_filter: - filter_sum = openmc.AggregateFilter(self_filter, - [tuple(filter_bins)], 'sum') - tally_sum.filters.append(filter_sum) - - # Add a copy of each filter not summed across to the tally sum - else: - tally_sum.filters.append(copy.deepcopy(self_filter)) - - # Add a copy of this tally's filters to the tally sum - else: - tally_sum._filters = copy.deepcopy(self.filters) - - # Sum across any nuclides specified by the user - if len(nuclides) != 0: - nuclide_bins = [self.get_nuclide_index(nuclide) for nuclide in nuclides] - axis_index = self.num_filters - mean = np.take(mean, indices=nuclide_bins, axis=axis_index) - std_dev = np.take(std_dev, indices=nuclide_bins, axis=axis_index) - mean = np.sum(mean, axis=axis_index, keepdims=True) - std_dev = np.sum(std_dev**2, axis=axis_index, keepdims=True) - std_dev = np.sqrt(std_dev) - - # Add AggregateNuclide to the tally sum - nuclide_sum = openmc.AggregateNuclide(nuclides, 'sum') - tally_sum.nuclides.append(nuclide_sum) - - # Add a copy of this tally's nuclides to the tally sum - else: - tally_sum._nuclides = copy.deepcopy(self.nuclides) - - # Sum across any scores specified by the user - if len(scores) != 0: - score_bins = [self.get_score_index(score) for score in scores] - axis_index = self.num_filters + 1 - mean = np.take(mean, indices=score_bins, axis=axis_index) - std_dev = np.take(std_dev, indices=score_bins, axis=axis_index) - mean = np.sum(mean, axis=axis_index, keepdims=True) - std_dev = np.sum(std_dev**2, axis=axis_index, keepdims=True) - std_dev = np.sqrt(std_dev) - - # Add AggregateScore to the tally sum - score_sum = openmc.AggregateScore(scores, 'sum') - tally_sum.scores.append(score_sum) - - # Add a copy of this tally's scores to the tally sum - else: - tally_sum._scores = copy.deepcopy(self.scores) - - # Reshape condensed data arrays with one dimension for all filters - mean = np.reshape(mean, tally_sum.shape) - std_dev = np.reshape(std_dev, tally_sum.shape) - - # Assign tally sum's data with the new arrays - tally_sum._mean = mean - tally_sum._std_dev = std_dev - - # If original tally was sparse, sparsify the tally summation - tally_sum.sparse = self.sparse - return tally_sum - - def average(self, scores=[], filter_type=None, - filter_bins=[], nuclides=[], remove_filter=False): - """Vectorized average of tally data across scores, filter bins and/or - nuclides using tally aggregation. - - This method constructs a new tally to encapsulate the average of the - data represented by the average of the data in this tally. The tally - data average is determined by the scores, filter bins and nuclides - specified in the input parameters. - - Parameters - ---------- - scores : list of str - A list of one or more score strings to average across - (e.g., ['absorption', 'nu-fission']; default is []) - filter_type : openmc.FilterMeta - Type of the filter, e.g. MeshFilter - filter_bins : Iterable of int or tuple - A list of the filter bins corresponding to the filter_type parameter - Each bin in the list is the integer ID for 'material', 'surface', - 'cell', 'cellborn', and 'universe' Filters. Each bin is an integer - for the cell instance ID for 'distribcell' Filters. Each bin is a - 2-tuple of floats for 'energy' and 'energyout' filters corresponding - to the energy boundaries of the bin of interest. Each bin is an - (x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of - interest. - nuclides : list of str - A list of nuclide name strings to average across - (e.g., ['U235', 'U238']; default is []) - remove_filter : bool - If a filter is being averaged over, this bool indicates whether to - remove that filter in the returned tally. Default is False. - - Returns - ------- - openmc.Tally - A new tally which encapsulates the average of data requested. - """ - - # Create new derived Tally for average - tally_avg = Tally() - tally_avg._derived = True - tally_avg._estimator = self.estimator - tally_avg._num_realizations = self.num_realizations - tally_avg._with_batch_statistics = self.with_batch_statistics - tally_avg._with_summary = self.with_summary - tally_avg._sp_filename = self._sp_filename - tally_avg._results_read = self._results_read - - # Get tally data arrays reshaped with one dimension per filter - mean = self.get_reshaped_data(value='mean') - std_dev = self.get_reshaped_data(value='std_dev') - - # Average across any filter bins specified by the user - if isinstance(filter_type, openmc.FilterMeta): - find_filter = self.find_filter(filter_type) - - # If user did not specify filter bins, average across all bins - if len(filter_bins) == 0: - bin_indices = np.arange(find_filter.num_bins) - - if isinstance(find_filter, openmc.DistribcellFilter): - filter_bins = np.arange(find_filter.num_bins) - elif isinstance(find_filter, openmc.EnergyFunctionFilter): - filter_bins = [None] - else: - filter_bins = find_filter.bins - - # Only average across bins specified by the user - else: - bin_indices = \ - [find_filter.get_bin_index(bin) for bin in filter_bins] - - # Average across the bins in the user-specified filter - for i, self_filter in enumerate(self.filters): - if isinstance(self_filter, filter_type): - shape = mean.shape - mean = np.take(mean, indices=bin_indices, axis=i) - std_dev = np.take(std_dev, indices=bin_indices, axis=i) - - # NumPy take introduces a new dimension in output array - # for some special cases that must be removed - if len(mean.shape) > len(shape): - mean = np.squeeze(mean, axis=i) - std_dev = np.squeeze(std_dev, axis=i) - - mean = np.nanmean(mean, axis=i, keepdims=True) - std_dev = np.nanmean(std_dev**2, axis=i, keepdims=True) - std_dev /= len(bin_indices) - std_dev = np.sqrt(std_dev) - - # Add AggregateFilter to the tally avg - if not remove_filter: - filter_sum = openmc.AggregateFilter(self_filter, - [tuple(filter_bins)], 'avg') - tally_avg.filters.append(filter_sum) - - # Add a copy of each filter not averaged across to the tally avg - else: - tally_avg.filters.append(copy.deepcopy(self_filter)) - - # Add a copy of this tally's filters to the tally avg - else: - tally_avg._filters = copy.deepcopy(self.filters) - - # Sum across any nuclides specified by the user - if len(nuclides) != 0: - nuclide_bins = [self.get_nuclide_index(nuclide) for nuclide in nuclides] - axis_index = self.num_filters - mean = np.take(mean, indices=nuclide_bins, axis=axis_index) - std_dev = np.take(std_dev, indices=nuclide_bins, axis=axis_index) - mean = np.nanmean(mean, axis=axis_index, keepdims=True) - std_dev = np.nanmean(std_dev**2, axis=axis_index, keepdims=True) - std_dev /= len(nuclide_bins) - std_dev = np.sqrt(std_dev) - - # Add AggregateNuclide to the tally avg - nuclide_avg = openmc.AggregateNuclide(nuclides, 'avg') - tally_avg.nuclides.append(nuclide_avg) - - # Add a copy of this tally's nuclides to the tally avg - else: - tally_avg._nuclides = copy.deepcopy(self.nuclides) - - # Sum across any scores specified by the user - if len(scores) != 0: - score_bins = [self.get_score_index(score) for score in scores] - axis_index = self.num_filters + 1 - mean = np.take(mean, indices=score_bins, axis=axis_index) - std_dev = np.take(std_dev, indices=score_bins, axis=axis_index) - mean = np.nanmean(mean, axis=axis_index, keepdims=True) - std_dev = np.nanmean(std_dev**2, axis=axis_index, keepdims=True) - std_dev /= len(score_bins) - std_dev = np.sqrt(std_dev) - - # Add AggregateScore to the tally avg - score_sum = openmc.AggregateScore(scores, 'avg') - tally_avg.scores.append(score_sum) - - # Add a copy of this tally's scores to the tally avg - else: - tally_avg._scores = copy.deepcopy(self.scores) - - # Reshape condensed data arrays with one dimension for all filters - mean = np.reshape(mean, tally_avg.shape) - std_dev = np.reshape(std_dev, tally_avg.shape) - - # Assign tally avg's data with the new arrays - tally_avg._mean = mean - tally_avg._std_dev = std_dev - - # If original tally was sparse, sparsify the tally average - tally_avg.sparse = self.sparse - return tally_avg - - def diagonalize_filter(self, new_filter, filter_position=-1): - """Diagonalize the tally data array along a new axis of filter bins. - - This is a helper method for the tally arithmetic methods. This method - adds the new filter to a derived tally constructed copied from this one. - The data in the derived tally arrays is "diagonalized" along the bins in - the new filter. This functionality is used by the openmc.mgxs module; to - transport-correct scattering matrices by subtracting a 'scatter-P1' - reaction rate tally with an energy filter from a 'scatter' reaction - rate tally with both energy and energyout filters. - - Parameters - ---------- - new_filter : Filter - The filter along which to diagonalize the data in the new - filter_position : int - Where to place the new filter in the Tally.filters list. Defaults - to last position. - - Returns - ------- - openmc.Tally - A new derived Tally with data diagaonalized along the new filter. - - """ - - cv.check_type('new_filter', new_filter, _FILTER_CLASSES) - cv.check_type('filter_position', filter_position, Integral) - - if new_filter in self.filters: - msg = 'Unable to diagonalize Tally ID="{0}" which already ' \ - 'contains a "{1}" filter'.format(self.id, type(new_filter)) - raise ValueError(msg) - - # Add the new filter to a copy of this Tally - new_tally = copy.deepcopy(self) - new_tally.filters.insert(filter_position, new_filter) - - # Determine "base" indices along the new "diagonal", and the factor - # by which the "base" indices should be repeated to account for all - # other filter bins in the diagonalized tally - indices = np.arange(0, new_filter.num_bins**2, new_filter.num_bins+1) - diag_factor = self.num_filter_bins // new_filter.num_bins - diag_indices = np.zeros(self.num_filter_bins, dtype=int) - - # Determine the filter indices along the new "diagonal" - for i in range(diag_factor): - start = i * new_filter.num_bins - end = (i+1) * new_filter.num_bins - diag_indices[start:end] = indices + (i * new_filter.num_bins**2) - - # Inject this Tally's data along the diagonal of the diagonalized Tally - if not self.derived and self.sum is not None: - new_tally._sum = np.zeros(new_tally.shape, dtype=np.float64) - new_tally._sum[diag_indices, :, :] = self.sum - if not self.derived and self.sum_sq is not None: - new_tally._sum_sq = np.zeros(new_tally.shape, dtype=np.float64) - new_tally._sum_sq[diag_indices, :, :] = self.sum_sq - if self.mean is not None: - new_tally._mean = np.zeros(new_tally.shape, dtype=np.float64) - new_tally._mean[diag_indices, :, :] = self.mean - if self.std_dev is not None: - new_tally._std_dev = np.zeros(new_tally.shape, dtype=np.float64) - new_tally._std_dev[diag_indices, :, :] = self.std_dev - - # If original tally was sparse, sparsify the diagonalized tally - new_tally.sparse = self.sparse - return new_tally - - -class Tallies(cv.CheckedList): - """Collection of Tallies used for an OpenMC simulation. - - This class corresponds directly to the tallies.xml input file. It can be - thought of as a normal Python list where each member is a :class:`Tally`. It - behaves like a list as the following example demonstrates: - - >>> t1 = openmc.Tally() - >>> t2 = openmc.Tally() - >>> t3 = openmc.Tally() - >>> tallies = openmc.Tallies([t1]) - >>> tallies.append(t2) - >>> tallies += [t3] - - Parameters - ---------- - tallies : Iterable of openmc.Tally - Tallies to add to the collection - - """ - - def __init__(self, tallies=None): - super().__init__(Tally, 'tallies collection') - if tallies is not None: - self += tallies - - def append(self, tally, merge=False): - """Append tally to collection - - Parameters - ---------- - tally : openmc.Tally - Tally to append - merge : bool - Indicate whether the tally should be merged with an existing tally, - if possible. Defaults to False. - - """ - if not isinstance(tally, Tally): - msg = 'Unable to add a non-Tally "{0}" to the ' \ - 'Tallies instance'.format(tally) - raise TypeError(msg) - - if merge: - merged = False - - # Look for a tally to merge with this one - for i, tally2 in enumerate(self): - - # If a mergeable tally is found - if tally2.can_merge(tally): - # Replace tally2 with the merged tally - merged_tally = tally2.merge(tally) - self[i] = merged_tally - merged = True - break - - # If no mergeable tally was found, simply add this tally - if not merged: - super().append(tally) - - else: - super().append(tally) - - def insert(self, index, item): - """Insert tally before index - - Parameters - ---------- - index : int - Index in list - item : openmc.Tally - Tally to insert - - """ - super().insert(index, item) - - def merge_tallies(self): - """Merge any mergeable tallies together. Note that n-way merges are - possible. - - """ - - for i, tally1 in enumerate(self): - for j, tally2 in enumerate(self): - # Do not merge the same tally with itself - if i == j: - continue - - # If the two tallies are mergeable - if tally1.can_merge(tally2): - # Replace tally 1 with the merged tally - merged_tally = tally1.merge(tally2) - self[i] = merged_tally - - # Remove tally 2 since it is no longer needed - self.pop(j) - - # Continue iterating from the first loop - break - - def _create_tally_subelements(self, root_element): - for tally in self: - root_element.append(tally.to_xml_element()) - - def _create_mesh_subelements(self, root_element): - already_written = set() - for tally in self: - for f in tally.filters: - if isinstance(f, openmc.MeshFilter): - if f.mesh.id not in already_written: - if len(f.mesh.name) > 0: - root_element.append(ET.Comment(f.mesh.name)) - - root_element.append(f.mesh.to_xml_element()) - already_written.add(f.mesh.id) - - def _create_filter_subelements(self, root_element): - already_written = dict() - for tally in self: - for f in tally.filters: - if f not in already_written: - root_element.append(f.to_xml_element()) - already_written[f] = f.id - elif f.id != already_written[f]: - # Set the IDs of identical filters with different - # user-defined IDs to the same value - f.id = already_written[f] - - def _create_derivative_subelements(self, root_element): - # Get a list of all derivatives referenced in a tally. - derivs = [] - for tally in self: - deriv = tally.derivative - if deriv is not None and deriv not in derivs: - derivs.append(deriv) - - # Add the derivatives to the XML tree. - for d in derivs: - root_element.append(d.to_xml_element()) - - def export_to_xml(self, path='tallies.xml'): - """Create a tallies.xml file that can be used for a simulation. - - Parameters - ---------- - path : str - Path to file to write. Defaults to 'tallies.xml'. - - """ - - root_element = ET.Element("tallies") - self._create_mesh_subelements(root_element) - self._create_filter_subelements(root_element) - self._create_tally_subelements(root_element) - self._create_derivative_subelements(root_element) - - # Clean the indentation in the file to be user-readable - clean_indentation(root_element) - - # Check if path is a directory - p = Path(path) - if p.is_dir(): - p /= 'tallies.xml' - - # Write the XML Tree to the tallies.xml file - tree = ET.ElementTree(root_element) - tree.write(str(p), xml_declaration=True, encoding='utf-8') diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py deleted file mode 100644 index 9be748b2c..000000000 --- a/openmc/tally_derivative.py +++ /dev/null @@ -1,113 +0,0 @@ -import sys -from numbers import Integral -from xml.etree import ElementTree as ET - -import openmc.checkvalue as cv -from openmc.mixin import EqualityMixin, IDManagerMixin - - -class TallyDerivative(EqualityMixin, IDManagerMixin): - """A material perturbation derivative to apply to a tally. - - Parameters - ---------- - derivative_id : int, optional - Unique identifier for the tally derivative. If none is specified, an - identifier will automatically be assigned - variable : str, optional - Accepted values are 'density', 'nuclide_density', and 'temperature' - material : int, optional - The perturbed material ID - nuclide : str, optional - The perturbed nuclide. Only needed for 'nuclide_density' derivatives. - Ex: 'Xe135' - - Attributes - ---------- - id : int - Unique identifier for the tally derivative - variable : str - Accepted values are 'density', 'nuclide_density', and 'temperature' - material : int - The perturubed material ID - nuclide : str - The perturbed nuclide. Only needed for 'nuclide_density' derivatives. - Ex: 'Xe135' - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, derivative_id=None, variable=None, material=None, - nuclide=None): - # Initialize Tally class attributes - self.id = derivative_id - self.variable = variable - self.material = material - self.nuclide = nuclide - - def __repr__(self): - string = 'Tally Derivative\n' - string += '{: <16}=\t{}\n'.format('\tID', self.id) - string += '{: <16}=\t{}\n'.format('\tVariable', self.variable) - - if self.variable == 'density': - string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) - elif self.variable == 'nuclide_density': - string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) - string += '{: <16}=\t{}\n'.format('\tNuclide', self.nuclide) - elif self.variable == 'temperature': - string += '{: <16}=\t{}\n'.format('\tMaterial', self.material) - - return string - - @property - def variable(self): - return self._variable - - @property - def material(self): - return self._material - - @property - def nuclide(self): - return self._nuclide - - @variable.setter - def variable(self, var): - if var is not None: - cv.check_type('derivative variable', var, str) - cv.check_value('derivative variable', var, - ('density', 'nuclide_density', 'temperature')) - self._variable = var - - @material.setter - def material(self, mat): - if mat is not None: - cv.check_type('derivative material', mat, Integral) - self._material = mat - - @nuclide.setter - def nuclide(self, nuc): - if nuc is not None: - cv.check_type('derivative nuclide', nuc, str) - self._nuclide = nuc - - def to_xml_element(self): - """Return XML representation of the tally derivative - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing derivative data - - """ - - element = ET.Element("derivative") - element.set("id", str(self.id)) - element.set("variable", self.variable) - element.set("material", str(self.material)) - if self.variable == 'nuclide_density': - element.set("nuclide", self.nuclide) - return element diff --git a/openmc/trigger.py b/openmc/trigger.py deleted file mode 100644 index 98557aab5..000000000 --- a/openmc/trigger.py +++ /dev/null @@ -1,98 +0,0 @@ -from numbers import Real -from xml.etree import ElementTree as ET -import sys -import warnings -from collections.abc import Iterable - -import openmc.checkvalue as cv - - -class Trigger(object): - """A criterion for when to finish a simulation based on tally uncertainties. - - Parameters - ---------- - trigger_type : {'variance', 'std_dev', 'rel_err'} - Determine whether to trigger on the variance, standard deviation, or - relative error of scores. - threshold : float - The threshold for the trigger type. - - Attributes - ---------- - trigger_type : {'variance', 'std_dev', 'rel_err'} - Determine whether to trigger on the variance, standard deviation, or - relative error of scores. - threshold : float - The threshold for the trigger type. - scores : list of str - Scores which should be checked against the trigger - - """ - - def __init__(self, trigger_type, threshold): - self.trigger_type = trigger_type - self.threshold = threshold - self._scores = [] - - def __eq__(self, other): - return str(self) == str(other) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - string = 'Trigger\n' - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type) - string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold) - string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores) - return string - - @property - def trigger_type(self): - return self._trigger_type - - @property - def threshold(self): - return self._threshold - - @property - def scores(self): - return self._scores - - @trigger_type.setter - def trigger_type(self, trigger_type): - cv.check_value('tally trigger type', trigger_type, - ['variance', 'std_dev', 'rel_err']) - self._trigger_type = trigger_type - - @threshold.setter - def threshold(self, threshold): - cv.check_type('tally trigger threshold', threshold, Real) - self._threshold = threshold - - @scores.setter - def scores(self, scores): - cv.check_type('trigger scores', scores, Iterable, str) - - # Set scores making sure not to have duplicates - self._scores = [] - for score in scores: - if score not in self._scores: - self._scores.append(score) - - def get_trigger_xml(self, element): - """Return XML representation of the trigger - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing trigger data - - """ - - subelement = ET.SubElement(element, "trigger") - subelement.set("type", self._trigger_type) - subelement.set("threshold", str(self._threshold)) - if len(self._scores) != 0: - subelement.set("scores", ' '.join(map(str, self._scores))) diff --git a/openmc/universe.py b/openmc/universe.py deleted file mode 100644 index ee038ebef..000000000 --- a/openmc/universe.py +++ /dev/null @@ -1,571 +0,0 @@ -from collections import OrderedDict -from collections.abc import Iterable -from copy import copy, deepcopy -from numbers import Integral, Real -import random -import sys - -import numpy as np - -import openmc -import openmc.checkvalue as cv -from openmc.plots import _SVG_COLORS -from openmc.mixin import IDManagerMixin - - -class Universe(IDManagerMixin): - """A collection of cells that can be repeated. - - Parameters - ---------- - universe_id : int, optional - Unique identifier of the universe. If not specified, an identifier will - automatically be assigned - name : str, optional - Name of the universe. If not specified, the name is the empty string. - cells : Iterable of openmc.Cell, optional - Cells to add to the universe. By default no cells are added. - - Attributes - ---------- - id : int - Unique identifier of the universe - name : str - Name of the universe - cells : collections.OrderedDict - Dictionary whose keys are cell IDs and values are :class:`Cell` - instances - volume : float - Volume of the universe in cm^3. This can either be set manually or - calculated in a stochastic volume calculation and added via the - :meth:`Universe.add_volume_information` method. - bounding_box : 2-tuple of numpy.array - Lower-left and upper-right coordinates of an axis-aligned bounding box - of the universe. - - """ - - next_id = 1 - used_ids = set() - - def __init__(self, universe_id=None, name='', cells=None): - # Initialize Cell class attributes - self.id = universe_id - self.name = name - self._volume = None - self._atoms = {} - - # Keys - Cell IDs - # Values - Cells - self._cells = OrderedDict() - - if cells is not None: - self.add_cells(cells) - - def __repr__(self): - string = 'Universe\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tCells', '=\t', - list(self._cells.keys())) - return string - - @property - def name(self): - return self._name - - @property - def cells(self): - return self._cells - - @property - def volume(self): - return self._volume - - @property - def bounding_box(self): - regions = [c.region for c in self.cells.values() - if c.region is not None] - if regions: - return openmc.Union(regions).bounding_box - else: - # Infinite bounding box - return openmc.Intersection([]).bounding_box - - @name.setter - def name(self, name): - if name is not None: - cv.check_type('universe name', name, str) - self._name = name - else: - self._name = '' - - @volume.setter - def volume(self, volume): - if volume is not None: - cv.check_type('universe volume', volume, Real) - self._volume = volume - - @classmethod - def from_hdf5(cls, group, cells): - """Create universe from HDF5 group - - Parameters - ---------- - group : h5py.Group - Group in HDF5 file - cells : dict - Dictionary mapping cell IDs to instances of :class:`openmc.Cell`. - - Returns - ------- - openmc.Universe - Universe instance - - """ - universe_id = int(group.name.split('/')[-1].lstrip('universe ')) - cell_ids = group['cells'][()] - - # Create this Universe - universe = cls(universe_id) - - # Add each Cell to the Universe - for cell_id in cell_ids: - universe.add_cell(cells[cell_id]) - - return universe - - def add_volume_information(self, volume_calc): - """Add volume information to a universe. - - Parameters - ---------- - volume_calc : openmc.VolumeCalculation - Results from a stochastic volume calculation - - """ - if volume_calc.domain_type == 'universe': - if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id].n - self._atoms = volume_calc.atoms[self.id] - else: - raise ValueError('No volume information found for this universe.') - else: - raise ValueError('No volume information found for this universe.') - - def find(self, point): - """Find cells/universes/lattices which contain a given point - - Parameters - ---------- - point : 3-tuple of float - Cartesian coordinates of the point - - Returns - ------- - list - Sequence of universes, cells, and lattices which are traversed to - find the given point - - """ - p = np.asarray(point) - for cell in self._cells.values(): - if p in cell: - if cell.fill_type in ('material', 'distribmat', 'void'): - return [self, cell] - elif cell.fill_type == 'universe': - if cell.translation is not None: - p -= cell.translation - if cell.rotation is not None: - p[:] = cell.rotation_matrix.dot(p) - return [self, cell] + cell.fill.find(p) - else: - return [self, cell] + cell.fill.find(p) - return [] - - def plot(self, origin=(0., 0., 0.), width=(1., 1.), pixels=(200, 200), - basis='xy', color_by='cell', colors=None, seed=None, - **kwargs): - """Display a slice plot of the universe. - - To display or save the plot, call :func:`matplotlib.pyplot.show` or - :func:`matplotlib.pyplot.savefig`. In a Jupyter notebook, enabling the - matplotlib inline backend will show the plot inline. - - Parameters - ---------- - origin : Iterable of float - Coordinates at the origin of the plot - width : Iterable of float - Width of the plot in each basis direction - pixels : Iterable of int - Number of pixels to use in each basis direction - basis : {'xy', 'xz', 'yz'} - The basis directions for the plot - color_by : {'cell', 'material'} - Indicate whether the plot should be colored by cell or by material - colors : dict - Assigns colors to specific materials or cells. Keys are instances of - :class:`Cell` or :class:`Material` and values are RGB 3-tuples, RGBA - 4-tuples, or strings indicating SVG color names. Red, green, blue, - and alpha should all be floats in the range [0.0, 1.0], for example: - - .. code-block:: python - - # Make water blue - water = openmc.Cell(fill=h2o) - universe.plot(..., colors={water: (0., 0., 1.)) - - seed : hashable object or None - Hashable object which is used to seed the random number generator - used to select colors. If None, the generator is seeded from the - current time. - **kwargs - All keyword arguments are passed to - :func:`matplotlib.pyplot.imshow`. - - Returns - ------- - matplotlib.image.AxesImage - Resulting image - - """ - import matplotlib.pyplot as plt - - # Seed the random number generator - if seed is not None: - random.seed(seed) - - if colors is None: - # Create default dictionary if none supplied - colors = {} - else: - # Convert to RGBA if necessary - colors = copy(colors) - for obj, color in colors.items(): - if isinstance(color, str): - if color.lower() not in _SVG_COLORS: - raise ValueError("'{}' is not a valid color." - .format(color)) - colors[obj] = [x/255 for x in - _SVG_COLORS[color.lower()]] + [1.0] - elif len(color) == 3: - colors[obj] = list(color) + [1.0] - - if basis == 'xy': - x_min = origin[0] - 0.5*width[0] - x_max = origin[0] + 0.5*width[0] - y_min = origin[1] - 0.5*width[1] - y_max = origin[1] + 0.5*width[1] - elif basis == 'yz': - # The x-axis will correspond to physical y and the y-axis will - # correspond to physical z - x_min = origin[1] - 0.5*width[0] - x_max = origin[1] + 0.5*width[0] - y_min = origin[2] - 0.5*width[1] - y_max = origin[2] + 0.5*width[1] - elif basis == 'xz': - # The y-axis will correspond to physical z - x_min = origin[0] - 0.5*width[0] - x_max = origin[0] + 0.5*width[0] - y_min = origin[2] - 0.5*width[1] - y_max = origin[2] + 0.5*width[1] - - # Determine locations to determine cells at - x_coords = np.linspace(x_min, x_max, pixels[0], endpoint=False) + \ - 0.5*(x_max - x_min)/pixels[0] - y_coords = np.linspace(y_max, y_min, pixels[1], endpoint=False) - \ - 0.5*(y_max - y_min)/pixels[1] - - # Initialize output image in RGBA format. Flip the pixels from - # traditional (x, y) to (y, x) used in graphics. - img = np.zeros((pixels[1], pixels[0], 4)) - for i, x in enumerate(x_coords): - for j, y in enumerate(y_coords): - if basis == 'xy': - path = self.find((x, y, origin[2])) - elif basis == 'yz': - path = self.find((origin[0], x, y)) - elif basis == 'xz': - path = self.find((x, origin[1], y)) - - if len(path) > 0: - try: - if color_by == 'cell': - obj = path[-1] - elif color_by == 'material': - if path[-1].fill_type == 'material': - obj = path[-1].fill - else: - continue - except AttributeError: - continue - if obj not in colors: - colors[obj] = (random.random(), random.random(), - random.random(), 1.0) - img[j, i, :] = colors[obj] - - # Display image - return plt.imshow(img, extent=(x_min, x_max, y_min, y_max), - interpolation='nearest', **kwargs) - - def add_cell(self, cell): - """Add a cell to the universe. - - Parameters - ---------- - cell : openmc.Cell - Cell to add - - """ - - if not isinstance(cell, openmc.Cell): - msg = 'Unable to add a Cell to Universe ID="{0}" since "{1}" is not ' \ - 'a Cell'.format(self._id, cell) - raise TypeError(msg) - - cell_id = cell.id - - if cell_id not in self._cells: - self._cells[cell_id] = cell - - def add_cells(self, cells): - """Add multiple cells to the universe. - - Parameters - ---------- - cells : Iterable of openmc.Cell - Cells to add - - """ - - if not isinstance(cells, Iterable): - msg = 'Unable to add Cells to Universe ID="{0}" since "{1}" is not ' \ - 'iterable'.format(self._id, cells) - raise TypeError(msg) - - for cell in cells: - self.add_cell(cell) - - def remove_cell(self, cell): - """Remove a cell from the universe. - - Parameters - ---------- - cell : openmc.Cell - Cell to remove - - """ - - if not isinstance(cell, openmc.Cell): - msg = 'Unable to remove a Cell from Universe ID="{0}" since "{1}" is ' \ - 'not a Cell'.format(self._id, cell) - raise TypeError(msg) - - # If the Cell is in the Universe's list of Cells, delete it - if cell.id in self._cells: - del self._cells[cell.id] - - def clear_cells(self): - """Remove all cells from the universe.""" - - self._cells.clear() - - def get_nuclides(self): - """Returns all nuclides in the universe - - Returns - ------- - nuclides : list of str - List of nuclide names - - """ - - nuclides = [] - - # Append all Nuclides in each Cell in the Universe to the dictionary - for cell in self.cells.values(): - for nuclide in cell.get_nuclides(): - if nuclide not in nuclides: - nuclides.append(nuclide) - - return nuclides - - def get_nuclide_densities(self): - """Return all nuclides contained in the universe - - Returns - ------- - nuclides : collections.OrderedDict - Dictionary whose keys are nuclide names and values are 2-tuples of - (nuclide, density) - - """ - nuclides = OrderedDict() - - if self._atoms is not None: - volume = self.volume - for name, atoms in self._atoms.items(): - nuclide = openmc.Nuclide(name) - density = 1.0e-24 * atoms.n/volume # density in atoms/b-cm - nuclides[name] = (nuclide, density) - else: - raise RuntimeError( - 'Volume information is needed to calculate microscopic cross ' - 'sections for universe {}. This can be done by running a ' - 'stochastic volume calculation via the ' - 'openmc.VolumeCalculation object'.format(self.id)) - - return nuclides - - def get_all_cells(self): - """Return all cells that are contained within the universe - - Returns - ------- - cells : collections.OrderedDict - Dictionary whose keys are cell IDs and values are :class:`Cell` - instances - - """ - - cells = OrderedDict() - - # Add this Universe's cells to the dictionary - cells.update(self._cells) - - # Append all Cells in each Cell in the Universe to the dictionary - for cell in self._cells.values(): - cells.update(cell.get_all_cells()) - - return cells - - def get_all_materials(self): - """Return all materials that are contained within the universe - - Returns - ------- - materials : collections.OrderedDict - Dictionary whose keys are material IDs and values are - :class:`Material` instances - - """ - - materials = OrderedDict() - - # Append all Cells in each Cell in the Universe to the dictionary - cells = self.get_all_cells() - for cell in cells.values(): - materials.update(cell.get_all_materials()) - - return materials - - def get_all_universes(self): - """Return all universes that are contained within this one. - - Returns - ------- - universes : collections.OrderedDict - Dictionary whose keys are universe IDs and values are - :class:`Universe` instances - - """ - # Append all Universes within each Cell to the dictionary - universes = OrderedDict() - for cell in self.get_all_cells().values(): - universes.update(cell.get_all_universes()) - - return universes - - def clone(self, memo=None): - """Create a copy of this universe with a new unique ID, and clones - all cells within this universe. - - Parameters - ---------- - memo : dict or None - A nested dictionary of previously cloned objects. This parameter - is used internally and should not be specified by the user. - - Returns - ------- - clone : openmc.Universe - The clone of this universe - - """ - - if memo is None: - memo = {} - - # If no nemoize'd clone exists, instantiate one - if self not in memo: - clone = deepcopy(self) - clone.id = None - - # Clone all cells for the universe clone - clone._cells = OrderedDict() - for cell in self._cells.values(): - clone.add_cell(cell.clone(memo)) - - # Memoize the clone - memo[self] = clone - - return memo[self] - - def create_xml_subelement(self, xml_element): - # Iterate over all Cells - for cell_id, cell in self._cells.items(): - path = "./cell[@id='{}']".format(cell_id) - - # If the cell was not already written, write it - if xml_element.find(path) is None: - # Create XML subelement for this Cell - cell_element = cell.create_xml_subelement(xml_element) - - # Append the Universe ID to the subelement and add to Element - cell_element.set("universe", str(self._id)) - xml_element.append(cell_element) - - def _determine_paths(self, path='', instances_only=False): - """Count the number of instances for each cell in the universe, and - record the count in the :attr:`Cell.num_instances` properties.""" - - univ_path = path + 'u{}'.format(self.id) - - for cell in self.cells.values(): - cell_path = '{}->c{}'.format(univ_path, cell.id) - fill = cell._fill - fill_type = cell.fill_type - - # If universe-filled, recursively count cells in filling universe - if fill_type == 'universe': - fill._determine_paths(cell_path + '->', instances_only) - - # If lattice-filled, recursively call for all universes in lattice - elif fill_type == 'lattice': - latt = fill - - # Count instances in each universe in the lattice - for index in latt._natural_indices: - latt_path = '{}->l{}({})->'.format( - cell_path, latt.id, ",".join(str(x) for x in index)) - univ = latt.get_universe(index) - univ._determine_paths(latt_path, instances_only) - - else: - if fill_type == 'material': - mat = fill - elif fill_type == 'distribmat': - mat = fill[cell._num_instances] - else: - mat = None - - if mat is not None: - mat._num_instances += 1 - if not instances_only: - mat._paths.append('{}->m{}'.format(cell_path, mat.id)) - - # Append current path - cell._num_instances += 1 - if not instances_only: - cell._paths.append(cell_path) diff --git a/openmc/volume.py b/openmc/volume.py deleted file mode 100644 index 91ff829cb..000000000 --- a/openmc/volume.py +++ /dev/null @@ -1,280 +0,0 @@ -from collections import OrderedDict -from collections.abc import Iterable, Mapping -from numbers import Real, Integral -from xml.etree import ElementTree as ET -import warnings - -import numpy as np -import pandas as pd -import h5py -from uncertainties import ufloat - -import openmc -import openmc.checkvalue as cv - -_VERSION_VOLUME = 1 - - -class VolumeCalculation(object): - """Stochastic volume calculation specifications and results. - - Parameters - ---------- - domains : Iterable of openmc.Cell, openmc.Material, or openmc.Universe - Domains to find volumes of - samples : int - Number of samples used to generate volume estimates - lower_left : Iterable of float - Lower-left coordinates of bounding box used to sample points. If this - argument is not supplied, an attempt is made to automatically determine - a bounding box. - upper_right : Iterable of float - Upper-right coordinates of bounding box used to sample points. If this - argument is not supplied, an attempt is made to automatically determine - a bounding box. - - Attributes - ---------- - ids : Iterable of int - IDs of domains to find volumes of - domain_type : {'cell', 'material', 'universe'} - Type of each domain - samples : int - Number of samples used to generate volume estimates - lower_left : Iterable of float - Lower-left coordinates of bounding box used to sample points - upper_right : Iterable of float - Upper-right coordinates of bounding box used to sample points - atoms : dict - Dictionary mapping unique IDs of domains to a mapping of nuclides to - total number of atoms for each nuclide present in the domain. For - example, {10: {'U235': 1.0e22, 'U238': 5.0e22, ...}}. - atoms_dataframe : pandas.DataFrame - DataFrame showing the estimated number of atoms for each nuclide present - in each domain specified. - volumes : dict - Dictionary mapping unique IDs of domains to estimated volumes in cm^3. - - """ - def __init__(self, domains, samples, lower_left=None, - upper_right=None): - self._atoms = {} - self._volumes = {} - - cv.check_type('domains', domains, Iterable, - (openmc.Cell, openmc.Material, openmc.Universe)) - if isinstance(domains[0], openmc.Cell): - self._domain_type = 'cell' - elif isinstance(domains[0], openmc.Material): - self._domain_type = 'material' - elif isinstance(domains[0], openmc.Universe): - self._domain_type = 'universe' - self.ids = [d.id for d in domains] - - self.samples = samples - - if lower_left is not None: - if upper_right is None: - raise ValueError('Both lower-left and upper-right coordinates ' - 'should be specified') - - # For cell domains, try to compute bounding box and make sure - # user-specified one is valid - if self.domain_type == 'cell': - for c in domains: - ll, ur = c.bounding_box - if np.any(np.isinf(ll)) or np.any(np.isinf(ur)): - continue - if (np.any(np.asarray(lower_left) > ll) or - np.any(np.asarray(upper_right) < ur)): - warnings.warn( - "Specified bounding box is smaller than computed " - "bounding box for cell {}. Volume calculation may " - "be incorrect!".format(c.id)) - - self.lower_left = lower_left - self.upper_right = upper_right - else: - if self.domain_type == 'cell': - ll, ur = openmc.Union(c.region for c in domains).bounding_box - if np.any(np.isinf(ll)) or np.any(np.isinf(ur)): - raise ValueError('Could not automatically determine bounding ' - 'box for stochastic volume calculation.') - else: - self.lower_left = ll - self.upper_right = ur - else: - raise ValueError('Could not automatically determine bounding box ' - 'for stochastic volume calculation.') - - @property - def ids(self): - return self._ids - - @property - def samples(self): - return self._samples - - @property - def lower_left(self): - return self._lower_left - - @property - def upper_right(self): - return self._upper_right - - @property - def domain_type(self): - return self._domain_type - - @property - def atoms(self): - return self._atoms - - @property - def volumes(self): - return self._volumes - - @property - def atoms_dataframe(self): - items = [] - columns = [self.domain_type.capitalize(), 'Nuclide', 'Atoms'] - for uid, atoms_dict in self.atoms.items(): - for name, atoms in atoms_dict.items(): - items.append((uid, name, atoms)) - - return pd.DataFrame.from_records(items, columns=columns) - - @ids.setter - def ids(self, ids): - cv.check_type('domain IDs', ids, Iterable, Real) - self._ids = ids - - @samples.setter - def samples(self, samples): - cv.check_type('number of samples', samples, Integral) - cv.check_greater_than('number of samples', samples, 0) - self._samples = samples - - @lower_left.setter - def lower_left(self, lower_left): - name = 'lower-left bounding box coordinates', - cv.check_type(name, lower_left, Iterable, Real) - cv.check_length(name, lower_left, 3) - self._lower_left = lower_left - - @upper_right.setter - def upper_right(self, upper_right): - name = 'upper-right bounding box coordinates' - cv.check_type(name, upper_right, Iterable, Real) - cv.check_length(name, upper_right, 3) - self._upper_right = upper_right - - @volumes.setter - def volumes(self, volumes): - cv.check_type('volumes', volumes, Mapping) - self._volumes = volumes - - @atoms.setter - def atoms(self, atoms): - cv.check_type('atoms', atoms, Mapping) - self._atoms = atoms - - @classmethod - def from_hdf5(cls, filename): - """Load stochastic volume calculation results from HDF5 file. - - Parameters - ---------- - filename : str - Path to volume.h5 file - - Returns - ------- - openmc.VolumeCalculation - Results of the stochastic volume calculation - - """ - with h5py.File(filename, 'r') as f: - cv.check_filetype_version(f, "volume", _VERSION_VOLUME) - - domain_type = f.attrs['domain_type'].decode() - samples = f.attrs['samples'] - lower_left = f.attrs['lower_left'] - upper_right = f.attrs['upper_right'] - - volumes = {} - atoms = {} - ids = [] - for obj_name in f: - if obj_name.startswith('domain_'): - domain_id = int(obj_name[7:]) - ids.append(domain_id) - group = f[obj_name] - volume = ufloat(*group['volume'][()]) - volumes[domain_id] = volume - nucnames = group['nuclides'][()] - atoms_ = group['atoms'][()] - atom_dict = OrderedDict() - for name_i, atoms_i in zip(nucnames, atoms_): - atom_dict[name_i.decode()] = ufloat(*atoms_i) - atoms[domain_id] = atom_dict - - # Instantiate some throw-away domains that are used by the constructor - # to assign IDs - with warnings.catch_warnings(): - warnings.simplefilter('ignore', openmc.IDWarning) - if domain_type == 'cell': - domains = [openmc.Cell(uid) for uid in ids] - elif domain_type == 'material': - domains = [openmc.Material(uid) for uid in ids] - elif domain_type == 'universe': - domains = [openmc.Universe(uid) for uid in ids] - - # Instantiate the class and assign results - vol = cls(domains, samples, lower_left, upper_right) - vol.volumes = volumes - vol.atoms = atoms - return vol - - def load_results(self, filename): - """Load stochastic volume calculation results from an HDF5 file. - - Parameters - ---------- - filename : str - Path to volume.h5 file - - """ - results = type(self).from_hdf5(filename) - - # Make sure properties match - assert self.ids == results.ids - assert np.all(self.lower_left == results.lower_left) - assert np.all(self.upper_right == results.upper_right) - - # Copy results - self.volumes = results.volumes - self.atoms = results.atoms - - def to_xml_element(self): - """Return XML representation of the volume calculation - - Returns - ------- - element : xml.etree.ElementTree.Element - XML element containing volume calculation data - - """ - element = ET.Element("volume_calc") - dt_elem = ET.SubElement(element, "domain_type") - dt_elem.text = self.domain_type - id_elem = ET.SubElement(element, "domain_ids") - id_elem.text = ' '.join(str(uid) for uid in self.ids) - samples_elem = ET.SubElement(element, "samples") - samples_elem.text = str(self.samples) - ll_elem = ET.SubElement(element, "lower_left") - ll_elem.text = ' '.join(str(x) for x in self.lower_left) - ur_elem = ET.SubElement(element, "upper_right") - ur_elem.text = ' '.join(str(x) for x in self.upper_right) - return element diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index d5970617a..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel", "numpy", "cython"] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index cdd367ea9..000000000 --- a/pytest.ini +++ /dev/null @@ -1,5 +0,0 @@ -[pytest] -python_files = test*.py -python_classes = NoThanks -filterwarnings = ignore::UserWarning -addopts = -rs diff --git a/schemas.xml b/schemas.xml deleted file mode 100644 index 3e586ec6a..000000000 --- a/schemas.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scripts/casl_chain.py b/scripts/casl_chain.py deleted file mode 100755 index 94fc9dd96..000000000 --- a/scripts/casl_chain.py +++ /dev/null @@ -1,280 +0,0 @@ -# This dictionary contains the 255-nuclides, simplified burnup chain used in -# CASL-ORIGEN, which can be found in Appendix A of Kang Seog Kim, "Specification -# for the VERA Depletion Benchmark Suite", CASL-U-2015-1014-000, Rev. 0, -# ORNL/TM-2016/53, 2016. -# -# Note 32 of the 255 nuclides appeare twice as they are both activation -# nuclides (category 1) and fission product nuclides (category 3). - -# Te129 has been added due to it's link to I129 production. - -CASL_CHAIN = { - # Nuclide: (Stable, CAT, IFPY, Special yield treatment) - # Stable: True if nuclide has no decay reactions - # CAT: Category of nuclides - # 1-Activation nuclides - # 2-Heavy metal nuclides - # 3-Fission product nuclides - # IFPY: Indicator of fission product yield - # 0-Non FPY - # 1-Direct FPY (-1 indicates (stable+metastable) direct FPY) - # 2-Cumulative FPY - # 3-Special treatment with weight fractions - # Special yield: (nuclide_i/weight_i/IFPY_i) - 'B10': (True, 1, 0, None), - 'B11': (True, 1, 0, None), - 'O16': (True, 1, 0, None), - 'Ag107': (True, 1, 0, None), - 'Ag109': (True, 1, 0, None), # redundant as FP - 'Ag110': (False, 1, 0, None), # redundant as FP - 'Cd110': (True, 1, 0, None), # redundant as FP - 'Cd111': (True, 1, 0, None), # redundant as FP - 'Cd112': (True, 1, 0, None), - 'Cd113': (True, 1, 0, None), # redundant as FP - 'Cd114': (True, 1, 0, None), - 'Cd115': (False, 1, 0, None), - 'In113': (True, 1, 0, None), - 'In115': (True, 1, 0, None), # redundant as FP - 'Sm152': (True, 1, 0, None), # redundant as FP - 'Sm153': (False, 1, 0, None), # redundant as FP - 'Eu151': (True, 1, 0, None), # redundant as FP - 'Eu152': (False, 1, 0, None), - 'Eu152_m1': (False, 1, 0, None), - 'Eu153': (True, 1, 0, None), # redundant as FP - 'Eu154': (False, 1, 0, None), # redundant as FP - 'Eu155': (False, 1, 0, None), # redundant as FP - 'Eu156': (False, 1, 0, None), # redundant as FP - 'Eu157': (False, 1, 0, None), # redundant as FP - 'Gd152': (True, 1, 0, None), - 'Gd154': (True, 1, 0, None), # redundant as FP - 'Gd155': (True, 1, 0, None), # redundant as FP - 'Gd156': (True, 1, 0, None), # redundant as FP - 'Gd157': (True, 1, 0, None), # redundant as FP - 'Gd158': (True, 1, 0, None), # redundant as FP - 'Gd159': (False, 1, 0, None), # redundant as FP - 'Gd160': (True, 1, 0, None), # redundant as FP - 'Gd161': (False, 1, 0, None), # redundant as FP - 'Tb159': (True, 1, 0, None), # redundant as FP - 'Tb160': (False, 1, 0, None), # redundant as FP - 'Tb161': (False, 1, 0, None), # redundant as FP - 'Dy160': (True, 1, 0, None), # redundant as FP - 'Dy161': (True, 1, 0, None), # redundant as FP - 'Dy162': (True, 1, 0, None), # redundant as FP - 'Dy163': (True, 1, 0, None), # redundant as FP - 'Dy164': (True, 1, 0, None), # redundant as FP - 'Dy165': (False, 1, 0, None), # redundant as FP - 'Ho165': (True, 1, 0, None), # redundant as FP - 'Er162': (True, 1, 0, None), - 'Er164': (True, 1, 0, None), - 'Er166': (True, 1, 0, None), - 'Er167': (True, 1, 0, None), - 'Er168': (True, 1, 0, None), - 'Er169': (False, 1, 0, None), - 'Er170': (True, 1, 0, None), - 'Er171': (False, 1, 0, None), - 'Tm169': (True, 1, 0, None), - 'Tm170': (False, 1, 0, None), - 'Tm171': (False, 1, 0, None), - 'Hf174': (True, 1, 0, None), - 'Hf176': (True, 1, 0, None), - 'Hf177': (True, 1, 0, None), - 'Hf178': (True, 1, 0, None), - 'Hf179': (True, 1, 0, None), - 'Hf180': (True, 1, 0, None), - 'Hf181': (False, 1, 0, None), - 'Ta181': (True, 1, 0, None), - 'Ta182': (False, 1, 0, None), - 'Th230': (False, 2, 0, None), - 'Th231': (False, 2, 0, None), - 'Th232': (False, 2, 0, None), - 'Th233': (False, 2, 0, None), - 'Th234': (False, 2, 0, None), - 'Pa231': (False, 2, 0, None), - 'Pa232': (False, 2, 0, None), - 'Pa233': (False, 2, 0, None), - 'Pa234': (False, 2, 0, None), - 'U232': (False, 2, 0, None), - 'U233': (False, 2, 0, None), - 'U234': (False, 2, 0, None), - 'U235': (False, 2, 0, None), - 'U236': (False, 2, 0, None), - 'U237': (False, 2, 0, None), - 'U238': (False, 2, 0, None), - 'U239': (False, 2, 0, None), - 'Np236': (False, 2, 0, None), - 'Np237': (False, 2, 0, None), - 'Np238': (False, 2, 0, None), - 'Np239': (False, 2, 0, None), - 'Np240': (False, 2, 0, None), - 'Np240_m1': (False, 2, 0, None), - 'Pu236': (False, 2, 0, None), - 'Pu237': (False, 2, 0, None), - 'Pu238': (False, 2, 0, None), - 'Pu239': (False, 2, 0, None), - 'Pu240': (False, 2, 0, None), - 'Pu241': (False, 2, 0, None), - 'Pu242': (False, 2, 0, None), - 'Pu243': (False, 2, 0, None), - 'Am241': (False, 2, 0, None), - 'Am242': (False, 2, 0, None), - 'Am242_m1': (False, 2, 0, None), - 'Am243': (False, 2, 0, None), - 'Am244': (False, 2, 0, None), - 'Am244_m1': (False, 2, 0, None), - 'Cm242': (False, 2, 0, None), - 'Cm243': (False, 2, 0, None), - 'Cm244': (False, 2, 0, None), - 'Cm245': (False, 2, 0, None), - 'Cm246': (False, 2, 0, None), - 'Br81': (True, 3, 2, None), - 'Br82': (False, 3, 2, None), - 'Kr82': (True, 3, 3, [('Br82_m1', 0.024, 1), ('Kr82', 1.000, 1)]), - 'Kr83': (True, 3, 2, None), - 'Kr84': (True, 3, 2, None), - 'Kr85': (False, 3, 2, None), - 'Kr86': (True, 3, 2, None), - 'Sr89': (False, 3, 2, None), - 'Sr90': (False, 3, 2, None), - 'Y89': (True, 3, 1, None), - 'Y90': (False, 3, 1, None), - 'Y91': (False, 3, 2, None), - 'Zr91': (True, 3, 1, None), - 'Zr93': (False, 3, 2, None), - 'Zr95': (False, 3, 2, None), - 'Zr96': (True, 3, 2, None), - 'Nb95': (False, 3, 3, [('Nb95',1.000, 1), ('Nb95_m1', 0.944, 1)]), - 'Mo95': (True, 3, 3, [('Nb95_m1',0.056, 1), ('Mo95', 1.000, 1)]), - 'Mo96': (True, 3, 3, [('Nb96',1.000, 1), ('Mo96', 1.000, 1)]), - 'Mo97': (True, 3, 2, None), - 'Mo98': (True, 3, 2, None), - 'Mo99': (False, 3, 2, None), - 'Mo100': (True, 3, 2, None), - 'Tc99': (False, 3, 1, None), - 'Tc99_m1': (False, 3, 1, None), - 'Tc100': (False, 3, 1, None), - 'Ru100': (True, 3, 1, None), - 'Ru101': (True, 3, 2, None), - 'Ru102': (True, 3, 2, None), - 'Ru103': (False, 3, 2, None), - 'Ru104': (True, 3, 2, None), - 'Ru105': (False, 3, 2, None), - 'Ru106': (False, 3, 2, None), - 'Rh102': (False, 3, 1, None), - 'Rh102_m1': (False, 3, 1, None), - 'Rh103': (True, 3, 1, None), - 'Rh103_m1': (False, 3, 1, None), - 'Rh104': (False, 3, 1, None), - 'Rh105': (False, 3, 1, None), - 'Rh105_m1': (False, 3, 1, None), - 'Rh106': (False, 3, 1, None), - 'Rh106_m1': (False, 3, 1, None), - 'Pd104': (True, 3, 1, None), - 'Pd105': (True, 3, 1, None), - 'Pd106': (True, 3, 1, None), - 'Pd107': (False, 3, 2, None), - 'Pd108': (True, 3, 2, None), - 'Pd109': (False, 3, 2, None), - 'Ag109': (True, 3, 1, None), - 'Ag109_m1': (False, 3, 1, None), - 'Ag110': (False, 3, 2, None), - 'Ag110_m1': (False, 3, 2, None), - 'Ag111': (False, 3, 2, None), - 'Cd110': (True, 3, 1, None), - 'Cd111': (True, 3, 3, [('Ag110', -1.000, 2), ('Cd110', 1.000, 2), ('Cd111', 1.000, 1)]), - 'Cd113': (True, 3, 2, None), - 'In115': (True, 3, 2, None), - 'Sb121': (True, 3, 2, None), - 'Sb123': (False, 3, 2, None), - 'Sb125': (False, 3, 2, None), - 'Sb127': (False, 3, 2, None), - 'Te127': (False, 3, -1, None), - 'Te127_m1': (False, 3, -1, None), - 'Te129': (False, 3, 1, None), - 'Te129_m1': (False, 3, 2, None), - 'Te132': (False, 3, 2, None), - 'I127': (True, 3, 1, None), - 'I128': (False, 3, 3, [('I128', 0.931, 2)]), - 'I129': (False, 3, 3, [('I129', 1.000, 2), ('I129', -1.000, 2)]), - 'I130': (False, 3, 2, None), - 'I131': (False, 3, 2, None), - 'I132': (False, 3, 1, None), - 'I135': (False, 3, 2, None), - 'Xe128': (True, 3, 1, None), - 'Xe130': (True, 3, 1, None), - 'Xe131': (True, 3, 1, None), - 'Xe132': (True, 3, 1, None), - 'Xe133': (False, 3, 2, None), - 'Xe134': (True, 3, 2, None), - 'Xe135': (False, 3, 1, None), - 'Xe135_m1': (False, 3, 1, None), - 'Xe136': (True, 3, 2, None), - 'Xe137': (False, 3, 2, None), - 'Cs133': (True, 3, 1, None), - 'Cs134': (False, 3, 1, None), - 'Cs135': (False, 3, 1, None), - 'Cs136': (False, 3, 1, None), - 'Cs137': (False, 3, 1, None), - 'Ba134': (True, 3, 1, None), - 'Ba137': (True, 3, 1, None), - 'Ba140': (False, 3, 2, None), - 'La139': (True, 3, 2, None), - 'La140': (False, 3, 1, None), - 'Ce140': (True, 3, 1, None), - 'Ce141': (False, 3, 2, None), - 'Ce142': (True, 3, 2, None), - 'Ce143': (False, 3, 2, None), - 'Ce144': (False, 3, 2, None), - 'Pr141': (True, 3, 1, None), - 'Pr142': (False, 3, 1, None), - 'Pr143': (False, 3, 1, None), - 'Pr144': (False, 3, 1, None), - 'Nd142': (True, 3, 1, None), - 'Nd143': (True, 3, 1, None), - 'Nd144': (False, 3, 1, None), - 'Nd145': (True, 3, 2, None), - 'Nd146': (True, 3, 2, None), - 'Nd147': (False, 3, 2, None), - 'Nd148': (True, 3, 2, None), - 'Nd149': (False, 3, 2, None), - 'Nd150': (True, 3, 2, None), - 'Nd151': (False, 3, 2, None), - 'Pm147': (False, 3, 1, None), - 'Pm148': (False, 3, -1, None), - 'Pm148_m1': (False, 3, -1, None), - 'Pm149': (False, 3, 1, None), - 'Pm150': (False, 3, 1, None), - 'Pm151': (False, 3, 1, None), - 'Sm147': (False, 3, 1, None), - 'Sm148': (False, 3, 1, None), - 'Sm149': (False, 3, 1, None), - 'Sm150': (True, 3, 1, None), - 'Sm151': (False, 3, 1, None), - 'Sm152': (True, 3, 2, None), - 'Sm153': (False, 3, 2, None), - 'Sm154': (True, 3, 2, None), - 'Sm155': (False, 3, 2, None), - 'Eu151': (True, 3, 1, None), - 'Eu153': (True, 3, 1, None), - 'Eu154': (False, 3, 1, None), - 'Eu155': (False, 3, 1, None), - 'Eu156': (False, 3, 2, None), - 'Eu157': (False, 3, 2, None), - 'Gd154': (True, 3, 1, None), - 'Gd155': (True, 3, 1, None), - 'Gd156': (True, 3, 1, None), - 'Gd157': (True, 3, 1, None), - 'Gd158': (True, 3, 2, None), - 'Gd159': (False, 3, 2, None), - 'Gd160': (True, 3, 2, None), - 'Gd161': (False, 3, 2, None), - 'Tb159': (True, 3, 1, None), - 'Tb160': (False, 3, 1, None), - 'Tb161': (False, 3, 1, None), - 'Dy160': (True, 3, 1, None), - 'Dy161': (True, 3, 1, None), - 'Dy162': (True, 3, 2, None), - 'Dy163': (True, 3, 2, None), - 'Dy164': (True, 3, 2, None), - 'Dy165': (False, 3, 2, None), - 'Ho165': (True, 3, 3, [('Dy165_m1', 0.022, 2), ('Ho165', 1.000, 1)]) -} diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 deleted file mode 100755 index 1933a6e4a..000000000 --- a/scripts/openmc-ace-to-hdf5 +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import xml.etree.ElementTree as ET -import warnings - -import openmc.data - -description = """ -This script can be used to create HDF5 nuclear data libraries used by -OpenMC. There are four different ways you can specify ACE libraries that are to -be converted: - -1. List each ACE library as a positional argument. This is very useful in - conjunction with the usual shell utilities (ls, find, etc.). -2. Use the --xml option to specify a pre-v0.9 cross_sections.xml file. -3. Use the --xsdir option to specify a MCNP xsdir file. -4. Use the --xsdata option to specify a Serpent xsdata file. - -The script does not use any extra information from cross_sections.xml/ xsdir/ -xsdata files to determine whether the nuclide is metastable. Instead, the ---metastable argument can be used to specify whether the ZAID naming convention -follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the MCNP data -convention (essentially the same as NNDC, except that the first metastable state -of Am242 is 95242 and the ground state is 95642). - -""" - -class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, - argparse.RawDescriptionHelpFormatter): - pass - -parser = argparse.ArgumentParser( - description=description, - formatter_class=CustomFormatter -) -parser.add_argument('libraries', nargs='*', - help='ACE libraries to convert to HDF5') -parser.add_argument('-d', '--destination', default='.', - help='Directory to create new library in') -parser.add_argument('-m', '--metastable', choices=['mcnp', 'nndc'], - default='nndc', - help='How to interpret ZAIDs for metastable nuclides') -parser.add_argument('--xml', help='Old-style cross_sections.xml that ' - 'lists ACE libraries') -parser.add_argument('--xsdir', help='MCNP xsdir file that lists ' - 'ACE libraries') -parser.add_argument('--xsdata', help='Serpent xsdata file that lists ' - 'ACE libraries') -parser.add_argument('--libver', choices=['earliest', 'latest'], - default='earliest', help="Output HDF5 versioning. Use " - "'earliest' for backwards compatibility or 'latest' for " - "performance") -args = parser.parse_args() - -if not os.path.isdir(args.destination): - os.mkdir(args.destination) - -# If the --xml argument was given, get the list of ACE libraries directory from -# elements within the specified cross_sections.xml file -ace_libraries = [] -if args.xml is not None: - tree = ET.parse(args.xml) - root = tree.getroot() - if root.find('directory') is not None: - directory = root.find('directory').text - else: - directory = os.path.dirname(args.xml) - - for ace_table in root.findall('ace_table'): - path = os.path.join(directory, ace_table.attrib['path']) - if path not in ace_libraries: - ace_libraries.append(path) - -elif args.xsdir is not None: - # Find 'directory' section - lines = open(args.xsdir, 'r').readlines() - for index, line in enumerate(lines): - if line.strip().lower() == 'directory': - break - else: - raise IOError("Could not find 'directory' section in MCNP xsdir file") - - # Handle continuation lines indicated by '+' at end of line - lines = lines[index + 1:] - continue_lines = [i for i, line in enumerate(lines) - if line.strip().endswith('+')] - for i in reversed(continue_lines): - lines[i] += lines[i].strip()[:-1] + lines.pop(i + 1) - - # Create list of ACE libraries - for line in lines: - words = line.split() - if len(words) < 3: - continue - - path = os.path.join(os.path.dirname(args.xsdir), words[2]) - if path not in ace_libraries: - ace_libraries.append(path) - -elif args.xsdata is not None: - with open(args.xsdata, 'r') as xsdata: - for line in xsdata: - words = line.split() - if len(words) >= 9: - path = os.path.join(os.path.dirname(args.xsdata), words[8]) - if path not in ace_libraries: - ace_libraries.append(path) - -else: - ace_libraries = args.libraries - -nuclides = {} -library = openmc.data.DataLibrary() - -for filename in ace_libraries: - # Check that ACE library exists - if not os.path.exists(filename): - warnings.warn("ACE library '{}' does not exist.".format(filename)) - continue - - lib = openmc.data.ace.Library(filename) - for table in lib.tables: - name, xs = table.name.split('.') - if xs.endswith('c'): - # Continuous-energy neutron data - if name not in nuclides: - try: - neutron = openmc.data.IncidentNeutron.from_ace( - table, args.metastable) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) - continue - - print('Converting {} (ACE) to {} (HDF5)'.format(table.name, - neutron.name)) - - # Determine filename - outfile = os.path.join(args.destination, - neutron.name.replace('.', '_') + '.h5') - neutron.export_to_hdf5(outfile, 'w', libver=args.libver) - - # Register with library - library.register_file(outfile) - - # Add nuclide to list - nuclides[name] = outfile - else: - # Then we only need to append the data - try: - neutron = \ - openmc.data.IncidentNeutron.from_hdf5(nuclides[name]) - print('Converting {} (ACE) to {} (HDF5)' - .format(table.name, neutron.name)) - neutron.add_temperature_from_ace(table, args.metastable) - neutron.export_to_hdf5(nuclides[name] + '_1', 'w', - libver=args.libver) - os.rename(nuclides[name] + '_1', nuclides[name]) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) - continue - - elif xs.endswith('t'): - # Adjust name to be the new thermal scattering name - name = openmc.data.get_thermal_name(name) - # Thermal scattering data - if name not in nuclides: - try: - thermal = openmc.data.ThermalScattering.from_ace(table) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) - continue - print('Converting {} (ACE) to {} (HDF5)'.format(table.name, - thermal.name)) - - # Determine filename - outfile = os.path.join(args.destination, - thermal.name.replace('.', '_') + '.h5') - thermal.export_to_hdf5(outfile, 'w', libver=args.libver) - - # Register with library - library.register_file(outfile) - - # Add data to list - nuclides[name] = outfile - - else: - # Then we only need to append the data - try: - thermal = openmc.data.ThermalScattering.from_hdf5( - nuclides[name]) - print('Converting {} (ACE) to {} (HDF5)' - .format(table.name,thermal.name)) - thermal.add_temperature_from_ace(table) - thermal.export_to_hdf5(nuclides[name] + '_1', 'w', - libver=args.libver) - os.rename(nuclides[name] + '_1', nuclides[name]) - except Exception as e: - print('Failed to convert {}: {}'.format(table.name, e)) - continue - -# Write cross_sections.xml -libpath = os.path.join(args.destination, 'cross_sections.xml') -library.export_to_xml(libpath) diff --git a/scripts/openmc-get-photon-data b/scripts/openmc-get-photon-data deleted file mode 100755 index 39e44b177..000000000 --- a/scripts/openmc-get-photon-data +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -""" -Download ENDF/B-VII.1 ENDF data from NNDC for photo-atomic and atomic -relaxation data and convert it to an HDF5 library for use with OpenMC. -This data is used for photon transport in OpenMC. -""" - -import os -import sys -import shutil -import zipfile -import argparse -from io import BytesIO -from urllib.request import urlopen - -import openmc.data - - -class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, - argparse.RawDescriptionHelpFormatter): - pass - -parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=CustomFormatter -) -parser.add_argument('-c', '--cross-sections', - help='cross_sections.xml file to append libraries to') -args = parser.parse_args() - -base_url = 'http://www.nndc.bnl.gov/endf/b7.1/zips/' -files = ['ENDF-B-VII.1-photoat.zip', 'ENDF-B-VII.1-atomic_relax.zip'] -block_size = 16384 - -# ============================================================================== -# DOWNLOAD FILES FROM NNDC SITE - -if not os.path.exists('photon_hdf5'): - os.mkdir('photon_hdf5') - -for f in files: - # Establish connection to URL - url = base_url + f - req = urlopen(url) - - # Get file size from header - file_size = req.length - downloaded = 0 - - # Check if file already downloaded - if os.path.exists(f): - if os.path.getsize(f) == file_size: - print('Skipping ' + f) - continue - else: - overwrite = input('Overwrite {}? ([y]/n) '.format(f)) - if overwrite.lower().startswith('n'): - continue - - # Copy file to disk - print('Downloading {}... '.format(f), end='') - with open(f, 'wb') as fh: - while True: - chunk = req.read(block_size) - if not chunk: break - fh.write(chunk) - downloaded += len(chunk) - status = '{0:10} [{1:3.2f}%]'.format( - downloaded, downloaded * 100. / file_size) - print(status + chr(8)*len(status), end='') - print('') - -# ============================================================================== -# EXTRACT FILES - -for f in files: - print('Extracting {0}...'.format(f)) - zipfile.ZipFile(f).extractall() - -# ============================================================================== -# GENERATE HDF5 DATA LIBRARY - -# If previous cross_sections.xml was specified, load it in -if args.cross_sections is not None: - lib_path = args.cross_sections - library = openmc.data.DataLibrary.from_xml(lib_path) -else: - lib_path = os.path.join('photon_hdf5', 'cross_sections.xml') - library = openmc.data.DataLibrary() - -for z in range(1, 101): - element = openmc.data.ATOMIC_SYMBOL[z] - print('Generating HDF5 file for Z={} ({})...'.format(z, element)) - - # Generate instance of IncidentPhoton - photo_file = os.path.join('photoat', 'photoat-{:03}_{}_000.endf'.format(z, element)) - atom_file = os.path.join('atomic_relax', 'atom-{:03}_{}_000.endf'.format(z, element)) - f = openmc.data.IncidentPhoton.from_endf(photo_file, atom_file) - - # Write HDF5 file and register it - hdf5_file = os.path.join('photon_hdf5', element + '.h5') - f.export_to_hdf5(hdf5_file, 'w') - library.register_file(hdf5_file) - -library.export_to_xml(lib_path) diff --git a/scripts/openmc-make-compton b/scripts/openmc-make-compton deleted file mode 100755 index c4bd5b06b..000000000 --- a/scripts/openmc-make-compton +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -import tarfile -from urllib.request import urlopen - -import numpy as np -import h5py - - -base_url = 'http://geant4.cern.ch/support/source/' -filename = 'G4EMLOW.6.48.tar.gz' -block_size = 16384 - -# ============================================================================== -# DOWNLOAD FILES FROM GEANT4 SITE - -# Establish connection to URL -req = urlopen(base_url + filename) - -# Get file size from header -file_size = req.length -downloaded = 0 - -# Check if file already downloaded -download = True -if os.path.exists(filename): - if os.path.getsize(filename) == file_size: - print('Already downloaded ' + filename) - download = False - else: - overwrite = input('Overwrite {}? ([y]/n) '.format(filename)) - if overwrite.lower().startswith('n'): - download = False - -if download: - # Copy file to disk - print('Downloading {}... '.format(filename), end='') - with open(filename, 'wb') as fh: - while True: - chunk = req.read(block_size) - if not chunk: break - fh.write(chunk) - downloaded += len(chunk) - status = '{0:10} [{1:3.2f}%]'.format( - downloaded, downloaded * 100. / file_size) - print(status + chr(8)*len(status), end='') - print('') - -# ============================================================================== -# EXTRACT FILES FROM TGZ - -if not os.path.isdir('G4EMLOW6.48'): - with tarfile.open(filename, 'r') as tgz: - print('Extracting {0}...'.format(filename)) - tgz.extractall() - -# ============================================================================== -# GENERATE COMPTON PROFILE HDF5 FILE - -print('Generating compton_profiles.h5...') - -shell_file = os.path.join('G4EMLOW6.48', 'doppler', 'shell-doppler.dat') - -with open(shell_file, 'r') as shell: - with h5py.File('compton_profiles.h5', 'w') as f: - # Read/write electron momentum values - pz = np.loadtxt(os.path.join('G4EMLOW6.48', 'doppler', 'p-biggs.dat')) - f.create_dataset('pz', data=pz) - - for Z in range(1, 101): - # Create group for this element - group = f.create_group('{:03}'.format(Z)) - - # Read data into one long array - path = os.path.join('G4EMLOW6.48', 'doppler', 'profile-{}.dat'.format(Z)) - J = np.fromstring(open(path, 'r').read(), sep=' ') - - # Determine number of electron shells and reshape - n_shells = J.size // 31 - J.shape = (n_shells, 31) - - # Write Compton profile for this Z - group.create_dataset('J', data=J) - - # Determine binding energies and number of electrons for each shell - num_electrons = [] - binding_energy = [] - while True: - words = shell.readline().split() - if words[0] == '-1': - break - num_electrons.append(float(words[0])) - binding_energy.append(float(words[1])) - - # Write binding energies and number of electrons - group.create_dataset('num_electrons', data=num_electrons) - group.create_dataset('binding_energy', data=binding_energy) diff --git a/scripts/openmc-make-depletion-chain b/scripts/openmc-make-depletion-chain deleted file mode 100755 index 51092a722..000000000 --- a/scripts/openmc-make-depletion-chain +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 - -import os -from pathlib import Path -from zipfile import ZipFile - -from openmc._utils import download -import openmc.deplete - - -URLS = [ - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-neutrons.zip', - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-decay.zip', - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-nfy.zip' -] - -def main(): - endf_dir = os.environ.get("OPENMC_ENDF_DATA") - if endf_dir is not None: - endf_dir = Path(endf_dir) - elif all(os.path.isdir(lib) for lib in ("neutrons", "decay", "nfy")): - endf_dir = Path(".") - else: - for url in URLS: - basename = download(url) - with ZipFile(basename, 'r') as zf: - print('Extracting {}...'.format(basename)) - zf.extractall() - endf_dir = Path(".") - - decay_files = tuple((endf_dir / "decay").glob("*endf")) - neutron_files = tuple((endf_dir / "neutrons").glob("*endf")) - nfy_files = tuple((endf_dir / "nfy").glob("*endf")) - - # check files exist - for flist, ftype in [(decay_files, "decay"), (neutron_files, "neutron"), - (nfy_files, "neutron fission product yield")]: - if not flist: - raise IOError("No {} endf files found in {}".format(ftype, endf_dir)) - - chain = openmc.deplete.Chain.from_endf(decay_files, nfy_files, neutron_files) - chain.export_to_xml('chain_endfb71.xml') - - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-make-depletion-chain-casl b/scripts/openmc-make-depletion-chain-casl deleted file mode 100755 index 7fdeed072..000000000 --- a/scripts/openmc-make-depletion-chain-casl +++ /dev/null @@ -1,240 +0,0 @@ -#!/usr/bin/env python3 - -import glob -import os -from zipfile import ZipFile -from collections import OrderedDict, defaultdict -from io import StringIO -from itertools import chain - -try: - import lxml.etree as ET - _have_lxml = True -except ImportError: - import xml.etree.ElementTree as ET - _have_lxml = False - -import openmc.data -import openmc.deplete -from openmc._xml import clean_indentation -from openmc.deplete.chain import _REACTIONS -from openmc.deplete.nuclide import Nuclide, DecayTuple, ReactionTuple -from openmc._utils import download - -from casl_chain import CASL_CHAIN - -URLS = [ - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-neutrons.zip', - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-decay.zip', - 'http://www.nndc.bnl.gov/endf/b7.1/zips/ENDF-B-VII.1-nfy.zip' -] - -def main(): - if os.path.isdir('./decay') and os.path.isdir('./nfy') and os.path.isdir('./neutrons'): - endf_dir = '.' - elif 'OPENMC_ENDF_DATA' in os.environ: - endf_dir = os.environ['OPENMC_ENDF_DATA'] - else: - for url in URLS: - basename = download(url) - with ZipFile(basename, 'r') as zf: - print('Extracting {}...'.format(basename)) - zf.extractall() - endf_dir = '.' - - decay_files = glob.glob(os.path.join(endf_dir, 'decay', '*.endf')) - fpy_files = glob.glob(os.path.join(endf_dir, 'nfy', '*.endf')) - neutron_files = glob.glob(os.path.join(endf_dir, 'neutrons', '*.endf')) - - # Create a Chain - chain = openmc.deplete.Chain() - - print('Reading ENDF nuclear data from "{}"...'.format(os.path.abspath(endf_dir))) - - # 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 - if name in CASL_CHAIN: - 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) - name = data.nuclide['name'] - if name in CASL_CHAIN: - decay_data[name] = data - - for name in CASL_CHAIN: - if name not in decay_data: - print('WARNING: {} has no decay data!'.format(name)) - - print('Processing fission product yield sub-library files...') - fpy_data = {} - for f in fpy_files: - data = openmc.data.FissionProductYields(f) - name = data.nuclide['name'] - if name in CASL_CHAIN: - fpy_data[name] = data - - print('Creating depletion_chain...') - missing_daughter = [] - missing_rx_product = [] - missing_fpy = [] - - 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 CASL_CHAIN[parent][0] and \ - 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)) - continue - - # 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)) - daughter = 'Nothing' - - # 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_yd, table_yc in zip(nuclide.yield_energies, fpy.independent, fpy.cumulative): - yields = defaultdict(float) - for product in table_yd: - if product in decay_data: - # identifier - ifpy = CASL_CHAIN[product][2] - # 1 for independent - if ifpy == 1: - if product not in table_yd: - print('No independent fission yields found for {} in {}'.format(product, parent)) - else: - yields[product] += table_yd[product].nominal_value - # 2 for cumulative - elif ifpy == 2: - if product not in table_yc: - print('No cumulative fission yields found for {} in {}'.format(product, parent)) - else: - yields[product] += table_yc[product].nominal_value - # -1 for stable + unstable - elif ifpy == -1: - if product not in table_yd: - print('No independent fission yields found for {} in {}'.format(product, parent)) - else: - yields[product] += table_yc[product].nominal_value - product_meta = '{}_m1'.format(product) - if product_meta in table_yd: - yields[product] += table_yc[product_meta].nominal_value - # 3 for special treatment with weight fractions - elif ifpy == 3: - for tuple_i in CASL_CHAIN[product][3]: - name_i, weight_i, ifpy_i = tuple_i - if name_i not in table_yd: - print('No fission yields found for {} in {}'.format(name_i, parent)) - else: - if ifpy_i == 1: - yields[product] += weight_i * table_yd[name_i].nominal_value - elif ifpy_i == 2: - yields[product] += weight_i * table_yc[name_i].nominal_value - - 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('') - - chain.export_to_xml('chain_casl.xml') - - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-make-stopping-powers b/scripts/openmc-make-stopping-powers deleted file mode 100755 index 76ac6686c..000000000 --- a/scripts/openmc-make-stopping-powers +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python - -from urllib.parse import urlencode -from urllib.request import urlopen -from lxml import html - -import numpy as np -import h5py -from openmc.data import ATOMIC_SYMBOL - - -base_url = 'https://physics.nist.gov/cgi-bin/Star/e_table-t.pl' -energies = np.logspace(-3, 3, 200) -data = {'matno': '', 'Energies': '\n'.join(str(x) for x in energies)} -columns = {1: 's_collision', 2: 's_radiative'} - -# ============================================================================== -# SCRAPE DATA FROM ESTAR SITE AND GENERATE STOPPING POWER HDF5 FILE - -print('Generating stopping_powers.h5...') - -with h5py.File('stopping_powers.h5', 'w') as f: - - # Write energies - f.create_dataset('energy', data=energies) - - for Z in range(1, 99): - print('Processing {} data...'.format(ATOMIC_SYMBOL[Z])) - - # Update form-encoded data to send in POST request for this element - data['matno'] = '{:03}'.format(Z) - payload = urlencode(data).encode("utf-8") - - # Retrieve data from ESTAR site - r = urlopen(url=base_url, data=payload).read() - - # Remove text and reformat data - r = html.fromstring(r).xpath('//pre//text()') - values = np.fromstring(' '.join(r[12:-5]), sep=' ').reshape((-1, 5)).T - - # Create group for this element - group = f.create_group('{:03}'.format(Z)) - - # Write the mean excitation energy - attributes = np.fromstring(r[3], sep=' ') - group.attrs['I'] = attributes[2] - - # Write collision and radiative stopping powers - for i in columns: - group.create_dataset(columns[i], data=values[i]) diff --git a/scripts/openmc-make-test-data b/scripts/openmc-make-test-data deleted file mode 100755 index a37a78fa9..000000000 --- a/scripts/openmc-make-test-data +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python3 - -""" -Download ENDF/B-VII.1 ENDF and ACE files from NNDC and WMP files from GitHub and -generate a full HDF5 library with incident neutron, incident photon, thermal -scattering data, and windowed multipole data. This data is used for OpenMC's -regression test suite. -""" - -import glob -import os -from pathlib import Path -import tarfile -import tempfile -from urllib.parse import urljoin -import zipfile - -import openmc.data -from openmc._utils import download - -base_ace = 'http://www.nndc.bnl.gov/endf/b7.1/aceFiles/' -base_endf = 'http://www.nndc.bnl.gov/endf/b7.1/zips/' -base_wmp = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/' -files = [ - (base_ace, 'ENDF-B-VII.1-neutron-293.6K.tar.gz', '9729a17eb62b75f285d8a7628ace1449'), - (base_ace, 'ENDF-B-VII.1-tsl.tar.gz', 'e17d827c92940a30f22f096d910ea186'), - (base_endf, 'ENDF-B-VII.1-neutrons.zip', 'e5d7f441fc4c92893322c24d1725e29c'), - (base_endf, 'ENDF-B-VII.1-photoat.zip', '5192f94e61f0b385cf536f448ffab4a4'), - (base_endf, 'ENDF-B-VII.1-atomic_relax.zip', 'fddb6035e7f2b6931e51a58fc754bd10'), - (base_wmp, 'WMP_Library_v1.1.tar.gz', '8523895928dd6ba63fba803e3a45d4f3') -] - - -def fix_zaid(table, old, new): - filename = os.path.join('tsl', table) - with open(filename, 'r') as fh: - text = fh.read() - text = text.replace(old, new, 1) - with open(filename, 'w') as fh: - fh.write(text) - -pwd = Path.cwd() -output_dir = pwd / 'nndc_hdf5' -os.makedirs('nndc_hdf5/photon', exist_ok=True) - -with tempfile.TemporaryDirectory() as tmpdir: - # Temporarily change dir - os.chdir(tmpdir) - - # ========================================================================= - # Download files from NNDC server - for base, fname, checksum in files: - download(urljoin(base, fname), checksum) - - # ========================================================================= - # EXTRACT FILES FROM TGZ - - for _, f, _ in files: - print('Extracting {}...'.format(f)) - path = Path(f) - if path.suffix == '.gz': - with tarfile.open(f, 'r') as tgz: - if 'tsl' in f: - tgz.extractall(path='tsl') - else: - tgz.extractall() - elif path.suffix == '.zip': - zipfile.ZipFile(f).extractall() - - # ========================================================================= - # FIX ZAID ASSIGNMENTS FOR VARIOUS S(A,B) TABLES - - print('Fixing ZAIDs for S(a,b) tables') - fix_zaid('bebeo.acer', '8016', ' 0') - fix_zaid('obeo.acer', '4009', ' 0') - - library = openmc.data.DataLibrary() - - # ========================================================================= - # INCIDENT NEUTRON DATA - - neutron_files = sorted(glob.glob('ENDF-B-VII.1-neutron-293.6K/*.ace')) - for f in neutron_files: - print('Converting {}...'.format(os.path.basename(f))) - data = openmc.data.IncidentNeutron.from_ace(f) - - # Check for fission energy release data - endf_filename = 'neutrons/n-{:03}_{}_{:03}{}.endf'.format( - data.atomic_number, - data.atomic_symbol, - data.mass_number, - 'm{}'.format(data.metastable) if data.metastable else '' - ) - ev = openmc.data.endf.Evaluation(endf_filename) - if (1, 458) in ev.section: - endf_data = openmc.data.IncidentNeutron.from_endf(ev) - data.fission_energy = endf_data.fission_energy - - # Add 0K elastic scattering data for select nuclides - if data.name in ('U235', 'U238', 'Pu239'): - data.add_elastic_0K_from_endf(endf_filename) - - # Determine filename - outfile = output_dir / (data.name + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - - # Register with library - library.register_file(outfile) - - # ========================================================================= - # THERMAL SCATTERING DATA - - thermal_files = sorted(glob.glob('tsl/*.acer')) - for f in thermal_files: - print('Converting {}...'.format(os.path.basename(f))) - data = openmc.data.ThermalScattering.from_ace(f) - - # Determine filename - outfile = output_dir / (data.name + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - - # Register with library - library.register_file(outfile) - - # ========================================================================= - # INCIDENT PHOTON DATA - - for z in range(1, 101): - element = openmc.data.ATOMIC_SYMBOL[z] - print('Generating HDF5 file for Z={} ({})...'.format(z, element)) - - # Generate instance of IncidentPhoton - photo_file = Path('photoat') / 'photoat-{:03}_{}_000.endf'.format(z, element) - atom_file = Path('atomic_relax') / 'atom-{:03}_{}_000.endf'.format(z, element) - data = openmc.data.IncidentPhoton.from_endf(photo_file, atom_file) - - # Write HDF5 file and register it - outfile = output_dir / 'photon' / (element + '.h5') - data.export_to_hdf5(outfile, 'w', 'earliest') - library.register_file(outfile) - - # ========================================================================= - # WINDOWED MULTIPOLE DATA - - # Move data into output directory - os.rename('WMP_Library', str(output_dir / 'wmp')) - - # Add multipole data to library - for f in sorted(glob.glob('{}/wmp/*.h5'.format(output_dir))): - print('Registering WMP file {}...'.format(f)) - library.register_file(f) - - library.export_to_xml(output_dir / 'cross_sections.xml') - - # ========================================================================= - # CREATE TARBALL AND MOVE BACK - - print('Creating compressed archive...') - test_tar = pwd / 'nndc_hdf5_test.tar.xz' - with tarfile.open(str(test_tar), 'w:xz') as txz: - txz.add('nndc_hdf5') - - # Change back to original directory - os.chdir(str(pwd)) diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally deleted file mode 100755 index 183fe35c5..000000000 --- a/scripts/openmc-plot-mesh-tally +++ /dev/null @@ -1,325 +0,0 @@ -#!/usr/bin/env python3 - -"""Python script to plot tally data generated by OpenMC.""" - -import os -import sys -import argparse -import tkinter as tk -import tkinter.filedialog as filedialog -import tkinter.font as font -import tkinter.messagebox as messagebox -import tkinter.ttk as ttk - -import matplotlib -matplotlib.use("TkAgg") -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk -from matplotlib.figure import Figure -import matplotlib.pyplot as plt -import numpy as np - -from openmc import StatePoint, MeshFilter - - -class MeshPlotter(tk.Frame): - def __init__(self, parent, filename): - tk.Frame.__init__(self, parent) - - self.labels = {'Cell': 'Cell:', 'Cellborn': 'Cell born:', - 'Surface': 'Surface:', 'Material': 'Material:', - 'Universe': 'Universe:', 'Energy': 'Energy in:', - 'Energyout': 'Energy out:'} - - self.filterBoxes = {} - - # Read data from source or leakage fraction file - self.get_file_data(filename) - - # Set up top-level window - top = self.winfo_toplevel() - top.title('Mesh Tally Plotter: ' + filename) - top.rowconfigure(0, weight=1) - top.columnconfigure(0, weight=1) - self.grid(sticky=tk.W+tk.N) - - # Create widgets and draw to screen - self.create_widgets() - self.update() - - def create_widgets(self): - figureFrame = tk.Frame(self) - figureFrame.grid(row=0, column=0) - - # Create the Figure and Canvas - self.dpi = 100 - self.fig = Figure((5.0, 5.0), dpi=self.dpi) - self.canvas = FigureCanvasTkAgg(self.fig, master=figureFrame) - self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) - - # Create the navigation toolbar, tied to the canvas - self.mpl_toolbar = NavigationToolbar2Tk(self.canvas, figureFrame) - self.mpl_toolbar.update() - self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) - - # Create frame for comboboxes - self.selectFrame = tk.Frame(self) - self.selectFrame.grid(row=1, column=0, sticky=tk.W+tk.E) - - # Tally selection - labelTally = tk.Label(self.selectFrame, text='Tally:') - labelTally.grid(row=0, column=0, sticky=tk.W) - self.tallyBox = ttk.Combobox(self.selectFrame, state='readonly') - self.tallyBox['values'] = [self.datafile.tallies[i].id - for i in self.meshTallies] - self.tallyBox.current(0) - self.tallyBox.grid(row=0, column=1, sticky=tk.W+tk.E) - self.tallyBox.bind('<>', self.update) - - # Planar basis selection - labelBasis = tk.Label(self.selectFrame, text='Basis:') - labelBasis.grid(row=1, column=0, sticky=tk.W) - self.basisBox = ttk.Combobox(self.selectFrame, state='readonly') - self.basisBox['values'] = ('xy', 'yz', 'xz') - self.basisBox.current(0) - self.basisBox.grid(row=1, column=1, sticky=tk.W+tk.E) - self.basisBox.bind('<>', self.update) - - # Axial level - labelAxial = tk.Label(self.selectFrame, text='Axial level:') - labelAxial.grid(row=2, column=0, sticky=tk.W) - self.axialBox = ttk.Combobox(self.selectFrame, state='readonly') - self.axialBox.grid(row=2, column=1, sticky=tk.W+tk.E) - self.axialBox.bind('<>', self.redraw) - - # Option for mean/uncertainty - labelMean = tk.Label(self.selectFrame, text='Mean/Uncertainty:') - labelMean.grid(row=3, column=0, sticky=tk.W) - self.meanBox = ttk.Combobox(self.selectFrame, state='readonly') - self.meanBox['values'] = ('Mean', 'Absolute uncertainty', - 'Relative uncertainty') - self.meanBox.current(0) - self.meanBox.grid(row=3, column=1, sticky=tk.W+tk.E) - self.meanBox.bind('<>', self.update) - - # Scores - labelScore = tk.Label(self.selectFrame, text='Score:') - labelScore.grid(row=4, column=0, sticky=tk.W) - self.scoreBox = ttk.Combobox(self.selectFrame, state='readonly') - self.scoreBox.grid(row=4, column=1, sticky=tk.W+tk.E) - self.scoreBox.bind('<>', self.redraw) - - # Filter label - boldfont = font.Font(weight='bold') - labelFilters = tk.Label(self.selectFrame, text='Filters:', - font=boldfont) - labelFilters.grid(row=5, column=0, sticky=tk.W) - - def update(self, event=None): - if not event: - widget = None - else: - widget = event.widget - - tally_id = self.meshTallies[self.tallyBox.current()] - selectedTally = self.datafile.tallies[tally_id] - - # Get mesh for selected tally - self.mesh = selectedTally.find_filter(MeshFilter).mesh - - # Get mesh dimensions - if len(self.mesh.dimension) == 2: - self.nx, self.ny = self.mesh.dimension - self.nz = 1 - else: - self.nx, self.ny, self.nz = self.mesh.dimension - - # Repopulate comboboxes baesd on current basis selection - text = self.basisBox.get() - if text == 'xy': - self.axialBox['values'] = [str(i+1) for i in range(self.nz)] - elif text == 'yz': - self.axialBox['values'] = [str(i+1) for i in range(self.nx)] - else: - self.axialBox['values'] = [str(i+1) for i in range(self.ny)] - self.axialBox.current(0) - - # If update() was called by a change in the basis combobox, we don't - # need to repopulate the filters - if widget == self.basisBox: - self.redraw() - return - - # Update scores - self.scoreBox['values'] = selectedTally.scores - self.scoreBox.current(0) - - # Remove any filter labels/comboboxes that exist - for row in range(6, self.selectFrame.grid_size()[1]): - for w in self.selectFrame.grid_slaves(row=row): - w.grid_forget() - w.destroy() - - # create a label/combobox for each filter in selected tally - count = 0 - for f in selectedTally.filters: - filterType = f.short_name - if filterType == 'Mesh': - continue - count += 1 - - # Create label and combobox for this filter - label = tk.Label(self.selectFrame, text=self.labels[filterType]) - label.grid(row=count+6, column=0, sticky=tk.W) - combobox = ttk.Combobox(self.selectFrame, state='readonly') - self.filterBoxes[filterType] = combobox - - # Set combobox items - if filterType in ['Energy', 'Energyout']: - combobox['values'] = ['{0} to {1}'.format(*f.bins[i:i+2]) - for i in range(len(f.bins) - 1)] - else: - combobox['values'] = [str(i) for i in f.bins] - - combobox.current(0) - combobox.grid(row=count+6, column=1, sticky=tk.W+tk.E) - combobox.bind('<>', self.redraw) - - # If There are no filters, leave a 'None available' message - if count == 0: - count += 1 - label = tk.Label(self.selectFrame, text="None Available") - label.grid(row=count+6, column=0, sticky=tk.W) - - self.redraw() - - def redraw(self, event=None): - basis = self.basisBox.current() + 1 - axial_level = self.axialBox.current() + 1 - mbvalue = self.meanBox.get() - - # Get selected tally - tally_id = self.meshTallies[self.tallyBox.current()] - selectedTally = self.datafile.tallies[tally_id] - - # Create spec_list - spec_list = [] - for f in selectedTally.filters: - if f.short_name == 'Mesh': - mesh_filter = f - continue - elif f.short_name in ['Energy', 'Energyout']: - index = self.filterBoxes[f.short_name].current() - ebin = (f.bins[index], f.bins[index + 1]) - spec_list.append((type(f), (ebin,))) - else: - index = self.filterBoxes[f.short_name].current() - spec_list.append((type(f), (index,))) - - dims = (self.nx, self.ny, self.nz) - - text = self.basisBox.get() - if text == 'xy': - h_ind = 0 - v_ind = 1 - elif text == 'yz': - h_ind = 1 - v_ind = 2 - else: - h_ind = 0 - v_ind = 2 - - axial_ind = 3 - (h_ind + v_ind) - dims = (dims[h_ind], dims[v_ind]) - - mesh_dim = len(self.mesh.dimension) - if mesh_dim == 3: - mesh_indices = [0,0,0] - else: - mesh_indices = [0,0] - - matrix = np.zeros(dims) - for i in range(dims[0]): - for j in range(dims[1]): - if mesh_dim == 3: - mesh_indices[h_ind] = i + 1 - mesh_indices[v_ind] = j + 1 - mesh_indices[axial_ind] = axial_level - else: - mesh_indices[0] = i + 1 - mesh_indices[1] = j + 1 - filters, filter_bins = zip(*spec_list + [ - (type(mesh_filter), (tuple(mesh_indices),))]) - mean = selectedTally.get_values( - [self.scoreBox.get()], filters, filter_bins) - stdev = selectedTally.get_values( - [self.scoreBox.get()], filters, filter_bins, - value='std_dev') - if mbvalue == 'Mean': - matrix[i, j] = mean - elif mbvalue == 'Absolute uncertainty': - matrix[i, j] = stdev - else: - if mean > 0.: - matrix[i, j] = stdev/mean - else: - matrix[i, j] = 0. - - # Clear the figure - self.fig.clear() - - # Make figure, set up color bar - self.axes = self.fig.add_subplot(111) - cax = self.axes.imshow(matrix.transpose(), vmin=0.0, vmax=matrix.max(), - interpolation='none', origin='lower') - self.fig.colorbar(cax) - - self.axes.set_xticks([]) - self.axes.set_yticks([]) - self.axes.set_aspect('equal') - - # Draw canvas - self.canvas.draw() - - def get_file_data(self, filename): - # Create StatePoint object and read in data - self.datafile = StatePoint(filename) - - # Find which tallies are mesh tallies - self.meshTallies = [] - for itally, tally in self.datafile.tallies.items(): - if any([isinstance(f, MeshFilter) for f in tally.filters]): - self.meshTallies.append(itally) - - if not self.meshTallies: - messagebox.showerror("Invalid StatePoint File", - "File does not contain mesh tallies!") - sys.exit(1) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('statepoint', nargs='?', help='Statepoint file') - args = parser.parse_args() - - # Hide root window - root = tk.Tk() - root.withdraw() - - # If no filename given as command-line argument, open file dialog - if args.statepoint is None: - filename = filedialog.askopenfilename(title='Select statepoint file', - initialdir='.') - else: - filename = args.statepoint - - if filename: - # Check to make sure file exists - if not os.path.isfile(filename): - messagebox.showerror("File not found", - "Could not find regular file: " + filename) - sys.exit(1) - - app = MeshPlotter(root, filename) - root.deiconify() - root.mainloop() diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk deleted file mode 100755 index fa154a2a7..000000000 --- a/scripts/openmc-track-to-vtk +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python3 - -"""Convert HDF5 particle track to VTK poly data. - -""" - -import os -import argparse -import struct - -import h5py -import vtk - - -def _parse_args(): - # Create argument parser. - parser = argparse.ArgumentParser( - description='Convert particle track file to a .pvtp file.') - parser.add_argument('input', metavar='IN', type=str, nargs='+', - help='Input particle track data filename(s).') - parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out', - help='Output VTK poly data filename.') - - # Parse and return commandline arguments. - return parser.parse_args() - - -def main(): - # Parse commandline arguments. - args = _parse_args() - - # Make sure that the output filename ends with '.pvtp'. - if not args.out: - args.out = 'tracks.pvtp' - elif not args.out.endswith('.pvtp'): - args.out += '.pvtp' - - # Initialize data arrays and offset. - points = vtk.vtkPoints() - cells = vtk.vtkCellArray() - point_offset = 0 - for fname in args.input: - # Write coordinate values to points array. - track = h5py.File(fname) - n_particles = track.attrs['n_particles'] - n_coords = track.attrs['n_coords'] - coords = [] - for i in range(n_particles): - coords.append(track['coordinates_' + str(i + 1)].value) - for j in range(n_coords[i]): - points.InsertNextPoint(coords[i][j,:]) - - for i in range(n_particles): - # Create VTK line and assign points to line. - line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(n_coords[i]) - for j in range(n_coords[i]): - line.GetPointIds().SetId(j, point_offset + j) - - # Add line to cell array - cells.InsertNextCell(line) - point_offset += n_coords[i] - - data = vtk.vtkPolyData() - data.SetPoints(points) - data.SetLines(cells) - - writer = vtk.vtkXMLPPolyDataWriter() - if vtk.vtkVersion.GetVTKMajorVersion() > 5: - writer.SetInputData(data) - else: - writer.SetInput(data) - writer.SetFileName(args.out) - writer.Write() - - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-update-inputs b/scripts/openmc-update-inputs deleted file mode 100755 index 0d25b5b97..000000000 --- a/scripts/openmc-update-inputs +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/env python3 -"""Update OpenMC's input XML files to the latest format. - -""" - -import argparse -from difflib import get_close_matches -from itertools import chain -from random import randint -from shutil import move -import xml.etree.ElementTree as ET - -import openmc.data - - -description = "Update OpenMC's input XML files to the latest format." -epilog = """\ -If any of the given files do not match the most up-to-date formatting, then they -will be automatically rewritten. The old out-of-date files will not be deleted; -they will be moved to a new file with '.original' appended to their name. - -Formatting changes that will be made: - -geometry.xml: Lattices containing 'outside' attributes/tags will be replaced - with lattices containing 'outer' attributes, and the appropriate - cells/universes will be added. Any 'surfaces' attributes/elements on a cell - will be renamed 'region'. - -materials.xml: Nuclide names will be changed from ACE aliases (e.g., Am-242m) to - HDF5/GND names (e.g., Am242_m1). Thermal scattering table names will be - changed from ACE aliases (e.g., HH2O) to HDF5/GND names (e.g., c_H_in_H2O). - -""" - - -def parse_args(): - """Read the input files from the commandline.""" - # Create argument parser. - parser = argparse.ArgumentParser( - description=description, - epilog=epilog, - formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('input', metavar='IN', type=str, nargs='+', - help='Input XML file(s).') - - # Parse and return commandline arguments. - return parser.parse_args() - - -def get_universe_ids(geometry_root): - """Return a set of universe id numbers.""" - root = geometry_root - out = set() - - # Get the ids of universes defined by cells. - for cell in root.iter('cell'): - # Get universe attributes/elements - if 'universe' in cell.attrib: - uid = cell.attrib['universe'] - out.add(int(uid)) - elif cell.find('universe') is not None: - elem = cell.find('universe') - uid = elem.text - out.add(int(uid)) - else: - # Default to universe 0 - out.add(0) - - # Get the ids of universes defined by lattices. - for lat in root.iter('lattice'): - # Get id attributes. - if 'id' in lat.attrib: - uid = lat.attrib['id'] - out.add(int(uid)) - - # Get id elements. - elif lat.find('id') is not None: - elem = lat.find('id') - uid = elem.text - out.add(int(uid)) - - return out - - -def get_cell_ids(geometry_root): - """Return a set of cell id numbers.""" - root = geometry_root - out = set() - - # Get the ids of universes defined by cells. - for cell in root.iter('cell'): - # Get id attributes. - if 'id' in cell.attrib: - cid = cell.attrib['id'] - out.add(int(cid)) - - # Get id elements. - elif cell.find('id') is not None: - elem = cell.find('id') - cid = elem.text - out.add(int(cid)) - - return out - - -def find_new_id(current_ids, preferred=None): - """Return a new id that is not already present in current_ids.""" - distance_from_preferred = 21 - max_random_attempts = 10000 - - # First, try to find an id near the preferred number. - if preferred is not None: - assert isinstance(preferred, int) - for i in range(1, distance_from_preferred): - if (preferred - i not in current_ids) and (preferred - i > 0): - return preferred - i - if (preferred + i not in current_ids) and (preferred + i > 0): - return preferred + i - - # If that was unsuccessful, attempt to randomly guess a new id number. - for i in range(max_random_attempts): - num = randint(1, 2147483647) - if num not in current_inds: - return num - - # Raise an error if an id was not found. - raise RuntimeError('Could not find a unique id number for a new universe.') - - -def get_lat_id(lattice_element): - """Return the id integer of the lattice_element.""" - assert isinstance(lattice_element, ET.Element) - if 'id' in lattice_element.attrib: - return int(lattice_element.attrib['id'].strip()) - elif any([child.tag == 'id' for child in lattice_element]): - elem = lattice_element.find('id') - return int(elem.text.strip()) - else: - raise RuntimeError('Could not find the id for a lattice.') - - -def pop_lat_outside(lattice_element): - """Return lattice's outside material and remove from attributes/elements.""" - assert isinstance(lattice_element, ET.Element) - - # Check attributes. - if 'outside' in lattice_element.attrib: - material = lattice_element.attrib['outside'].strip() - del lattice_element.attrib['outside'] - - # Check subelements. - elif any([child.tag == 'outside' for child in lattice_element]): - elem = lattice_element.find('outside') - material = elem.text.strip() - lattice_element.remove(elem) - - # No 'outside' specified. This means the outside is a void. - else: - material = 'void' - - return material - - -def update_geometry(geometry_root): - """Update the given XML geometry tree. Return True if changes were made.""" - root = geometry_root - was_updated = False - - # Get a set of already-used universe and cell ids. - uids = get_universe_ids(root) - cids = get_cell_ids(root) - taken_ids = uids.union(cids) - - # Replace 'outside' with 'outer' in lattices. - for lat in chain(root.iter('lattice'), root.iter('hex_lattice')): - # Get the lattice's id. - lat_id = get_lat_id(lat) - - # Ignore lattices that have 'outer' specified. - if any([child.tag == 'outer' for child in lat]): continue - if 'outer' in lat.attrib: continue - - # Pop the 'outside' material. - material = pop_lat_outside(lat) - - # Get an id number for a new outer universe. Ideally, the id should - # be close to the lattice's id. - new_uid = find_new_id(taken_ids, preferred=lat_id) - assert new_uid not in taken_ids - - # Add the new universe filled with the old 'outside' material to the - # geometry. - new_cell = ET.Element('cell') - new_cell.attrib['id'] = str(new_uid) - new_cell.attrib['universe'] = str(new_uid) - new_cell.attrib['material'] = material - root.append(new_cell) - taken_ids.add(new_uid) - - # Add the new universe to the lattice's 'outer' attribute. - lat.attrib['outer'] = str(new_uid) - - was_updated = True - - # Remove 'type' from lattice definitions. - for lat in root.iter('lattice'): - elem = lat.find('type') - if elem is not None: - lat.remove(elem) - was_updated = True - if 'type' in lat.attrib: - del lat.attrib['type'] - was_updated = True - - # Change 'width' to 'pitch' in lattice definitions. - for lat in root.iter('lattice'): - elem = lat.find('width') - if elem is not None: - elem.tag = 'pitch' - was_updated = True - if 'width' in lat.attrib: - lat.attrib['pitch'] = lat.attrib['width'] - del lat.attrib['width'] - was_updated = True - - # Change 'surfaces' to 'region' in cell definitions - for cell in root.iter('cell'): - elem = cell.find('surfaces') - if elem is not None: - elem.tag = 'region' - was_updated = True - if 'surfaces' in cell.attrib: - cell.attrib['region'] = cell.attrib['surfaces'] - del cell.attrib['surfaces'] - was_updated = True - - return was_updated - -def update_materials(root): - """Update the given XML materials tree. Return True if changes were made.""" - was_updated = False - - for material in root.findall('material'): - for nuclide in material.findall('nuclide'): - if 'name' in nuclide.attrib: - nucname = nuclide.attrib['name'] - nucname = nucname.replace('-', '') - # If a nuclide name is in the ZAID notation (e.g., a number), - # convert it to the proper nuclide name. - if nucname.strip().isnumeric(): - nucname = openmc.data.ace.get_metadata(int(nucname))[0] - nucname = nucname.replace('Nat', '0') - if nucname.endswith('m'): - nucname = nucname[:-1] + '_m1' - nuclide.set('name', nucname) - was_updated = True - - elif nuclide.find('name') is not None: - name_elem = nuclide.find('name') - nucname = name_elem.text - nucname = nucname.replace('-', '') - nucname = nucname.replace('Nat', '0') - if nucname.endswith('m'): - nucname = nucname[:-1] + '_m1' - name_elem.text = nucname - was_updated = True - - for sab in material.findall('sab'): - if 'name' in sab.attrib: - sabname = sab.attrib['name'] - sab.set('name', openmc.data.get_thermal_name(sabname)) - was_updated = True - - elif sab.find('name') is not None: - name_elem = sab.find('name') - sabname = name_elem.text - name_elem.text = openmc.data.get_thermal_name(sabname) - was_updated = True - - return was_updated - - -if __name__ == '__main__': - args = parse_args() - for fname in args.input: - # Parse the XML data. - tree = ET.parse(fname) - root = tree.getroot() - was_updated = False - - if root.tag == 'geometry': - was_updated = update_geometry(root) - elif root.tag == 'materials': - was_updated = update_materials(root) - - if was_updated: - # Move the original geometry file to preserve it. - move(fname, fname + '.original') - - # Write a new geometry file. - tree.write(fname) diff --git a/scripts/openmc-update-mgxs b/scripts/openmc-update-mgxs deleted file mode 100755 index 8559affb9..000000000 --- a/scripts/openmc-update-mgxs +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env python3 -"""Update OpenMC's deprecated multi-group cross section XML files to the latest -HDF5-based format. - -""" - -import os -import warnings -import xml.etree.ElementTree as ET - -import argparse -import numpy as np - -import openmc.mgxs_library - -description = """\ -Update OpenMC's deprecated multi-group cross section XML files to the latest -HDF5-based format.""" - - -def parse_args(): - """Read the input files from the commandline.""" - # Create argument parser - parser = argparse.ArgumentParser(description=description, - formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-i', '--input', type=argparse.FileType('r'), - help='input XML file') - parser.add_argument('-o', '--output', nargs='?', default='', - help='output file, in HDF5 format') - args = vars(parser.parse_args()) - - if args['output'] == '': - filename = args['input'].name - extension = os.path.splitext(filename) - if extension == '.xml': - filename = filename[:filename.rfind('.')] + '.h5' - args['output'] = filename - - # Parse and return commandline arguments. - return args - - -def get_data(element, entry): - value = element.find(entry) - if value is not None: - value = value.text.strip() - else: - if entry in element.attrib: - value = element.attrib[entry].strip() - else: - value = None - - return value - - -if __name__ == '__main__': - args = parse_args() - - # Parse the XML data. - tree = ET.parse(args['input']) - root = tree.getroot() - - # Get old metadata - temp = tree.find('group_structure').text.strip() - temp = np.array(temp.split()) - group_structure = temp.astype(np.float) - # Convert from MeV to eV - group_structure *= 1.e6 - energy_groups = openmc.mgxs.EnergyGroups(group_structure) - temp = tree.find('inverse-velocity') - if temp is not None: - temp = temp.text.strip() - temp = np.array(temp.split()) - inverse_velocity = temp.astype(np.float) - else: - inverse_velocity = None - - xsd = [] - names = [] - - # Now move on to the cross section data itself - for xsdata_elem in root.iter('xsdata'): - name = get_data(xsdata_elem, 'name') - - temperature = get_data(xsdata_elem, 'kT') - if temperature is not None: - temperature = \ - float(temperature) / openmc.data.K_BOLTZMANN * 1.E6 - else: - temperature = 294. - temperatures = [temperature] - - awr = get_data(xsdata_elem, 'awr') - if awr is not None: - awr = float(awr) - - representation = get_data(xsdata_elem, 'representation') - if representation is None: - representation = 'isotropic' - if representation == 'angle': - n_azi = int(get_data(xsdata_elem, 'num_azimuthal')) - n_pol = int(get_data(xsdata_elem, 'num_polar')) - - scatter_format = get_data(xsdata_elem, 'scatt_type') - if scatter_format is None: - scatter_format = 'legendre' - - order = int(get_data(xsdata_elem, 'order')) - - tab_leg = get_data(xsdata_elem, 'tabular_legendre') - if tab_leg is not None: - warnings.Warning('The tabular_legendre option has moved to the ' - 'settings.xml file and must be added manually') - - # Either add the data to a previously existing xsdata (if it is - # for the same 'name' but a different temperature), or create a - # new one. - try: - # It is in our list, so store that entry - i = names.index(name) - except ValueError: - # It is not in our list, so add it - i = -1 - xsd.append(openmc.XSdata(name, energy_groups, - temperatures=temperatures, - representation=representation)) - if awr is not None: - xsd[-1].atomic_weight_ratio = awr - if representation == 'angle': - xsd[-1].num_azimuthal = n_azi - xsd[-1].num_polar = n_pol - xsd[-1].scatter_format = scatter_format - xsd[-1].order = order - names.append(name) - - if scatter_format == 'legendre': - order_dim = order + 1 - else: - order_dim = order - - if i != -1: - xsd[i].add_temperature(temperature) - - temp = get_data(xsdata_elem, 'total') - if temp is not None: - temp = np.array(temp.split(), dtype=float) - total = temp.astype(np.float) - total.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_total(total, temperature) - - if inverse_velocity is not None: - xsd[i].set_inverse_velocity(inverse_velocity, temperature) - - temp = get_data(xsdata_elem, 'absorption') - temp = np.array(temp.split()) - absorption = temp.astype(np.float) - absorption.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_absorption(absorption, temperature) - - temp = get_data(xsdata_elem, 'scatter') - temp = np.array(temp.split()) - scatter = temp.astype(np.float) - # This is now a flattened-array of something that started with a - # shape of [Order][G][G']; we need to unflatten and then switch the - # ordering - in_shape = (order_dim, energy_groups.num_groups, - energy_groups.num_groups) - if representation == 'angle': - in_shape = (n_pol, n_azi) + in_shape - scatter.shape = in_shape - scatter = np.swapaxes(scatter, 2, 3) - scatter = np.swapaxes(scatter, 3, 4) - else: - scatter.shape = in_shape - scatter = np.swapaxes(scatter, 0, 1) - scatter = np.swapaxes(scatter, 1, 2) - - xsd[i].set_scatter_matrix(scatter, temperature) - - temp = get_data(xsdata_elem, 'multiplicity') - if temp is not None: - temp = np.array(temp.split()) - multiplicity = temp.astype(np.float) - multiplicity.shape = xsd[i].xs_shapes["[G][G']"] - xsd[i].set_multiplicity_matrix(multiplicity, temperature) - - temp = get_data(xsdata_elem, 'fission') - if temp is not None: - temp = np.array(temp.split()) - fission = temp.astype(np.float) - fission.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_fission(fission, temperature) - - temp = get_data(xsdata_elem, 'kappa_fission') - if temp is not None: - temp = np.array(temp.split()) - kappa_fission = temp.astype(np.float) - kappa_fission.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_kappa_fission(kappa_fission, temperature) - - temp = get_data(xsdata_elem, 'chi') - if temp is not None: - temp = np.array(temp.split()) - chi = temp.astype(np.float) - chi.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_chi(chi, temperature) - else: - chi = None - - temp = get_data(xsdata_elem, 'nu_fission') - if temp is not None: - temp = np.array(temp.split()) - nu_fission = temp.astype(np.float) - if chi is not None: - nu_fission.shape = xsd[i].xs_shapes['[G]'] - else: - nu_fission.shape = xsd[i].xs_shapes["[G][G']"] - xsd[i].set_nu_fission(nu_fission, temperature) - - # Build library as we go, but first we have enough to initialize it - lib = openmc.MGXSLibrary(energy_groups) - - lib.add_xsdatas(xsd) - - lib.export_to_hdf5(args['output']) diff --git a/scripts/openmc-validate-xml b/scripts/openmc-validate-xml deleted file mode 100755 index f36ba2b5d..000000000 --- a/scripts/openmc-validate-xml +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import glob -import lxml.etree as etree -from subprocess import call -from optparse import OptionParser - -# Command line parsing -parser = OptionParser() -parser.add_option('-r', '--relaxng-path', dest='relaxng', - help="Path to RelaxNG files.") -parser.add_option('-i', '--input-path', dest='inputs', default=os.getcwd(), - help="Path to OpenMC input files." ) -(options, args) = parser.parse_args() - -# Colored output -if sys.stdout.isatty(): - OK = '\033[92m' - FAIL = '\033[91m' - NOT_FOUND = '\033[93m' - ENDC = '\033[0m' - BOLD = '\033[1m' -else: - OK = '' - FAIL = '' - ENDC = '' - BOLD = '' - NOT_FOUND = '' - -# Get absolute paths -if options.relaxng is not None: - relaxng_path = os.path.abspath(options.relaxng) -if options.inputs is not None: - inputs_path = os.path.abspath(options.inputs) - -# Search for relaxng path if not set -if options.relaxng is None: - xml_validate_path = os.path.abspath(os.path.dirname(sys.argv[0])) - if "bin" in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "share", "relaxng") - elif os.path.join("src", "utils") in xml_validate_path: - relaxng_path = os.path.join(xml_validate_path, "..", "relaxng") - else: - raise Exception("Set RelaxNG path with -r command line option.") -if not os.path.exists(relaxng_path): - raise Exception("RelaxNG path: {0} does not exist, set with -r " - "command line option.".format(relaxng_path)) - -# Make sure there are .rng files in RelaxNG path -rng_files = glob.glob(os.path.join(relaxng_path, "*.rng")) -if len(rng_files) == 0: - raise Exception("No .rng files found in RelaxNG " - "path: {0}.".format(relaxng_path)) - -# Get list of xml input files -xml_files = glob.glob(os.path.join(inputs_path, "*.xml")) -if len(xml_files) == 0: - raise Exception("No .xml files found at input path: {0}" - ".".format(inputs_path)) - -# Begin loop around input files -for xml_file in xml_files: - - text = "Validating {0}".format(os.path.basename(xml_file)) - print(text + '.'*(30 - len(text)), end="") - - # Validate the XML file - try: - xml_tree = etree.parse(xml_file) - except etree.XMLSyntaxError as e: - print(BOLD + FAIL + '[XML ERROR]' + ENDC) - print(" {0}".format(e)) - continue - - # Get xml_filename prefix - xml_prefix = os.path.basename(xml_file) - xml_prefix = xml_prefix.split(".")[0] - - # Search for rng file - rng_file = os.path.join(relaxng_path, xml_prefix + ".rng") - if rng_file in rng_files: - - # read in RelaxNG - relaxng_doc = etree.parse(rng_file) - relaxng = etree.RelaxNG(relaxng_doc) - - # validate xml file again RelaxNG - try: - relaxng.assertValid(xml_tree) - print(BOLD + OK + '[VALID]' + ENDC) - except (etree.DocumentInvalid, TypeError) as e: - print(BOLD + FAIL + '[NOT VALID]' + ENDC) - print(" {0}".format(e)) - - # RNG file does not exist - else: - print(BOLD + NOT_FOUND + '[NO RELAXNG FOUND]' + ENDC) diff --git a/scripts/openmc-voxel-to-vtk b/scripts/openmc-voxel-to-vtk deleted file mode 100755 index c7f5ffa1a..000000000 --- a/scripts/openmc-voxel-to-vtk +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 - -import struct -import sys -from argparse import ArgumentParser - -import numpy as np -import h5py -import vtk - -_min_version = (2,0) - - -def main(): - # Process command line arguments - parser = ArgumentParser() - parser.add_argument('voxel_file', help='Path to voxel file') - parser.add_argument('-o', '--output', action='store', - default='plot', help='Path to output VTK file.') - args = parser.parse_args() - - # Read data from voxel file - fh = h5py.File(args.voxel_file, 'r') - - # check version - version = tuple(fh.attrs['version']) - if version < _min_version: - old_version = ".".join(map(str,version)) - min_version = ".".join(map(str,_min_version)) - err_msg = "This voxel file's version is {}. This script " \ - "only supports voxel files with version {} or " \ - "higher. Please generate a new voxel file using " \ - "a newer version of OpenMC.".format(old_version, min_version) - raise ValueError(err_msg) - - dimension = fh.attrs['num_voxels'] - width = fh.attrs['voxel_width'] - lower_left = fh.attrs['lower_left'] - - nx, ny, nz = dimension - upper_right = lower_left + width*dimension - - grid = vtk.vtkImageData() - grid.SetDimensions(nx+1, ny+1, nz+1) - grid.SetOrigin(*lower_left) - grid.SetSpacing(*width) - - # transpose data from OpenMC ordering (zyx) to VTK ordering (xyz) - # and flatten to 1-D array - print("Reading and translating data...") - h5data = fh['data'][...] - - data = vtk.vtkIntArray() - data.SetName("id") - # set the array using the h5data array - data.SetArray(h5data, h5data.size, True) - # add data to image grid - grid.GetCellData().AddArray(data) - - writer = vtk.vtkXMLImageDataWriter() - if vtk.vtkVersion.GetVTKMajorVersion() > 5: - writer.SetInputData(grid) - else: - writer.SetInput(grid) - if not args.output.endswith(".vti"): - args.output += ".vti" - writer.SetFileName(args.output) - print("Writing VTK file {}...".format(args.output)) - writer.Write() - -if __name__ == '__main__': - main() diff --git a/setup.py b/setup.py deleted file mode 100755 index aff7834d7..000000000 --- a/setup.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python - -import glob -import sys -import numpy as np - -from setuptools import setup, find_packages -try: - from Cython.Build import cythonize - have_cython = True -except ImportError: - have_cython = False - - -# Determine shared library suffix -if sys.platform == 'darwin': - suffix = 'dylib' -else: - suffix = 'so' - -# Get version information from __init__.py. This is ugly, but more reliable than -# using an import. -with open('openmc/__init__.py', 'r') as f: - version = f.readlines()[-1].split()[-1].strip("'") - -kwargs = { - 'name': 'openmc', - 'version': version, - 'packages': find_packages(exclude=['tests*']), - 'scripts': glob.glob('scripts/openmc-*'), - - # Data files and librarries - 'package_data': { - 'openmc.lib': ['libopenmc.{}'.format(suffix)], - 'openmc.data': ['mass16.txt', 'BREMX.DAT', '*.h5'] - }, - - # Metadata - 'author': 'The OpenMC Development Team', - 'author_email': 'openmc-dev@googlegroups.com', - 'description': 'OpenMC', - 'url': 'https://openmc.org', - 'download_url': 'https://github.com/openmc-dev/openmc/releases', - 'project_urls': { - 'Issue Tracker': 'https://github.com/openmc-dev/openmc/issues', - 'Documentation': 'https://openmc.readthedocs.io', - 'Source Code': 'https://github.com/openmc-dev/openmc', - }, - 'classifiers': [ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Topic :: Scientific/Engineering' - 'Programming Language :: C++', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - ], - - # Dependencies - 'python_requires': '>=3.4', - 'install_requires': [ - 'numpy>=1.9', 'h5py', 'scipy', 'ipython', 'matplotlib', - 'pandas', 'lxml', 'uncertainties' - ], - 'extras_require': { - 'test': ['pytest', 'pytest-cov'], - 'vtk': ['vtk'], - }, -} - -# If Cython is present, add resonance reconstruction and fast float_endf -if have_cython: - kwargs.update({ - 'ext_modules': cythonize('openmc/data/*.pyx'), - 'include_dirs': [np.get_include()] - }) - -setup(**kwargs) diff --git a/src/bank.cpp b/src/bank.cpp deleted file mode 100644 index 172ecf84f..000000000 --- a/src/bank.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "openmc/bank.h" - -#include "openmc/capi.h" -#include "openmc/error.h" - -#include - -// Explicit template instantiation definition -template class std::vector; - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -std::vector source_bank; -std::vector fission_bank; -std::vector secondary_bank; -#ifdef _OPENMP -std::vector master_fission_bank; -#endif - -} // namespace simulation - -//============================================================================== -// Non-member functions -//============================================================================== - -void free_memory_bank() -{ - simulation::source_bank.clear(); - #pragma omp parallel - { - simulation::fission_bank.clear(); - } -#ifdef _OPENMP - simulation::master_fission_bank.clear(); -#endif -} - -//============================================================================== -// C API -//============================================================================== - -extern "C" int openmc_source_bank(void** ptr, int64_t* n) -{ - if (simulation::source_bank.size() == 0) { - set_errmsg("Source bank has not been allocated."); - return OPENMC_E_ALLOCATE; - } else { - *ptr = simulation::source_bank.data(); - *n = simulation::source_bank.size(); - return 0; - } -} - -extern "C" int openmc_fission_bank(void** ptr, int64_t* n) -{ - if (simulation::fission_bank.size() == 0) { - set_errmsg("Fission bank has not been allocated."); - return OPENMC_E_ALLOCATE; - } else { - *ptr = simulation::fission_bank.data(); - *n = simulation::fission_bank.size(); - return 0; - } -} - -} // namespace openmc diff --git a/src/bremsstrahlung.cpp b/src/bremsstrahlung.cpp deleted file mode 100644 index e6b76d19d..000000000 --- a/src/bremsstrahlung.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "openmc/bremsstrahlung.h" - -#include "openmc/constants.h" -#include "openmc/material.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/settings.h" - -#include "xtensor/xmath.hpp" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -xt::xtensor ttb_e_grid; -xt::xtensor ttb_k_grid; -std::vector ttb; - -} // namespace data - -//============================================================================== -// Non-member functions -//============================================================================== - -void thick_target_bremsstrahlung(Particle& p, double* E_lost) -{ - if (p.material_ == MATERIAL_VOID) return; - - int photon = static_cast(Particle::Type::photon); - if (p.E_ < settings::energy_cutoff[photon]) return; - - // Get bremsstrahlung data for this material and particle type - BremsstrahlungData* mat; - if (p.type_ == Particle::Type::positron) { - mat = &model::materials[p.material_]->ttb_->positron; - } else { - mat = &model::materials[p.material_]->ttb_->electron; - } - - double e = std::log(p.E_); - auto n_e = data::ttb_e_grid.size(); - - // Find the lower bounding index of the incident electron energy - size_t j = lower_bound_index(data::ttb_e_grid.cbegin(), - data::ttb_e_grid.cend(), e); - if (j == n_e - 1) --j; - - // Get the interpolation bounds - double e_l = data::ttb_e_grid(j); - double e_r = data::ttb_e_grid(j+1); - double y_l = mat->yield(j); - double y_r = mat->yield(j+1); - - // Calculate the interpolation weight w_j+1 of the bremsstrahlung energy PDF - // interpolated in log energy, which can be interpreted as the probability - // of index j+1 - double f = (e - e_l)/(e_r - e_l); - - // Get the photon number yield for the given energy using linear - // interpolation on a log-log scale - double y = std::exp(y_l + (y_r - y_l)*f); - - // Sample number of secondary bremsstrahlung photons - int n = y + prn(); - - *E_lost = 0.0; - if (n == 0) return; - - // Sample index of the tabulated PDF in the energy grid, j or j+1 - double c_max; - int i_e; - if (prn() <= f || j == 0) { - i_e = j + 1; - - // Interpolate the maximum value of the CDF at the incoming particle - // energy on a log-log scale - double p_l = mat->pdf(i_e, i_e - 1); - double p_r = mat->pdf(i_e, i_e); - double c_l = mat->cdf(i_e, i_e - 1); - double a = std::log(p_r/p_l)/(e_r - e_l) + 1.0; - c_max = c_l + std::exp(e_l)*p_l/a*(std::exp(a*(e - e_l)) - 1.0); - } else { - i_e = j; - - // Maximum value of the CDF - c_max = mat->cdf(i_e, i_e); - } - - // Sample the energies of the emitted photons - for (int i = 0; i < n; ++i) { - // Generate a random number r and determine the index i for which - // cdf(i) <= r*cdf,max <= cdf(i+1) - double c = prn()*c_max; - int i_w = lower_bound_index(&mat->cdf(i_e, 0), &mat->cdf(i_e, 0) + i_e, c); - - // Sample the photon energy - double w_l = data::ttb_e_grid(i_w); - double w_r = data::ttb_e_grid(i_w + 1); - double p_l = mat->pdf(i_e, i_w); - double p_r = mat->pdf(i_e, i_w + 1); - double c_l = mat->cdf(i_e, i_w); - double a = std::log(p_r/p_l)/(w_r - w_l) + 1.0; - double w = std::exp(w_l)*std::pow(a*(c - c_l)/(std::exp(w_l)*p_l) + 1.0, 1.0/a); - - if (w > settings::energy_cutoff[photon]) { - // Create secondary photon - p.create_secondary(p.u(), w, Particle::Type::photon); - *E_lost += w; - } - } -} - -} // namespace openmc diff --git a/src/cell.cpp b/src/cell.cpp deleted file mode 100644 index 3a7a2598f..000000000 --- a/src/cell.cpp +++ /dev/null @@ -1,1234 +0,0 @@ - -#include "openmc/cell.h" - -#include -#include -#include -#include -#include -#include - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/dagmc.h" -#include "openmc/error.h" -#include "openmc/geometry.h" -#include "openmc/hdf5_interface.h" -#include "openmc/lattice.h" -#include "openmc/material.h" -#include "openmc/nuclide.h" -#include "openmc/settings.h" -#include "openmc/surface.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - std::vector> cells; - std::unordered_map cell_map; - - std::vector> universes; - std::unordered_map universe_map; -} // namespace model - -//============================================================================== -//! Convert region specification string to integer tokens. -//! -//! The characters (, ), |, and ~ count as separate tokens since they represent -//! operators. -//============================================================================== - -std::vector -tokenize(const std::string region_spec) { - // Check for an empty region_spec first. - std::vector tokens; - if (region_spec.empty()) { - return tokens; - } - - // Parse all halfspaces and operators except for intersection (whitespace). - for (int i = 0; i < region_spec.size(); ) { - if (region_spec[i] == '(') { - tokens.push_back(OP_LEFT_PAREN); - i++; - - } else if (region_spec[i] == ')') { - tokens.push_back(OP_RIGHT_PAREN); - i++; - - } else if (region_spec[i] == '|') { - tokens.push_back(OP_UNION); - i++; - - } else if (region_spec[i] == '~') { - tokens.push_back(OP_COMPLEMENT); - i++; - - } else if (region_spec[i] == '-' || region_spec[i] == '+' - || std::isdigit(region_spec[i])) { - // This is the start of a halfspace specification. Iterate j until we - // find the end, then push-back everything between i and j. - int j = i + 1; - while (j < region_spec.size() && std::isdigit(region_spec[j])) {j++;} - tokens.push_back(std::stoi(region_spec.substr(i, j-i))); - i = j; - - } else if (std::isspace(region_spec[i])) { - i++; - - } else { - std::stringstream err_msg; - err_msg << "Region specification contains invalid character, \"" - << region_spec[i] << "\""; - fatal_error(err_msg); - } - } - - // Add in intersection operators where a missing operator is needed. - int i = 0; - while (i < tokens.size()-1) { - bool left_compat {(tokens[i] < OP_UNION) || (tokens[i] == OP_RIGHT_PAREN)}; - bool right_compat {(tokens[i+1] < OP_UNION) - || (tokens[i+1] == OP_LEFT_PAREN) - || (tokens[i+1] == OP_COMPLEMENT)}; - if (left_compat && right_compat) { - tokens.insert(tokens.begin()+i+1, OP_INTERSECTION); - } - i++; - } - - return tokens; -} - -//============================================================================== -//! Convert infix region specification to Reverse Polish Notation (RPN) -//! -//! This function uses the shunting-yard algorithm. -//============================================================================== - -std::vector -generate_rpn(int32_t cell_id, std::vector infix) -{ - std::vector rpn; - std::vector stack; - - for (int32_t token : infix) { - if (token < OP_UNION) { - // If token is not an operator, add it to output - rpn.push_back(token); - } else if (token < OP_RIGHT_PAREN) { - // Regular operators union, intersection, complement - while (stack.size() > 0) { - int32_t op = stack.back(); - - if (op < OP_RIGHT_PAREN && - ((token == OP_COMPLEMENT && token < op) || - (token != OP_COMPLEMENT && token <= op))) { - // While there is an operator, op, on top of the stack, if the token - // is left-associative and its precedence is less than or equal to - // that of op or if the token is right-associative and its precedence - // is less than that of op, move op to the output queue and push the - // token on to the stack. Note that only complement is - // right-associative. - rpn.push_back(op); - stack.pop_back(); - } else { - break; - } - } - - stack.push_back(token); - - } else if (token == OP_LEFT_PAREN) { - // If the token is a left parenthesis, push it onto the stack - stack.push_back(token); - - } else { - // If the token is a right parenthesis, move operators from the stack to - // the output queue until reaching the left parenthesis. - for (auto it = stack.rbegin(); *it != OP_LEFT_PAREN; it++) { - // If we run out of operators without finding a left parenthesis, it - // means there are mismatched parentheses. - if (it == stack.rend()) { - std::stringstream err_msg; - err_msg << "Mismatched parentheses in region specification for cell " - << cell_id; - fatal_error(err_msg); - } - rpn.push_back(stack.back()); - stack.pop_back(); - } - - // Pop the left parenthesis. - stack.pop_back(); - } - } - - while (stack.size() > 0) { - int32_t op = stack.back(); - - // If the operator is a parenthesis it is mismatched. - if (op >= OP_RIGHT_PAREN) { - std::stringstream err_msg; - err_msg << "Mismatched parentheses in region specification for cell " - << cell_id; - fatal_error(err_msg); - } - - rpn.push_back(stack.back()); - stack.pop_back(); - } - - return rpn; -} - -//============================================================================== -// Universe implementation -//============================================================================== - -void -Universe::to_hdf5(hid_t universes_group) const -{ - // Create a group for this universe. - std::stringstream group_name; - group_name << "universe " << id_; - auto group = create_group(universes_group, group_name); - - // Write the contained cells. - if (cells_.size() > 0) { - std::vector cell_ids; - for (auto i_cell : cells_) cell_ids.push_back(model::cells[i_cell]->id_); - write_dataset(group, "cells", cell_ids); - } - - close_group(group); -} - -BoundingBox Universe::bounding_box() const { - BoundingBox bbox = {INFTY, -INFTY, INFTY, -INFTY, INFTY, -INFTY}; - if (cells_.size() == 0) { - return {}; - } else { - for (const auto& cell : cells_) { - auto& c = model::cells[cell]; - bbox |= c->bounding_box(); - } - } - return bbox; -} - -//============================================================================== -// Cell implementation -//============================================================================== - -double -Cell::temperature(int32_t instance) const -{ - if (sqrtkT_.size() < 1) { - throw std::runtime_error{"Cell temperature has not yet been set."}; - } - - if (instance >= 0) { - double sqrtkT = sqrtkT_.size() == 1 ? - sqrtkT_.at(0) : - sqrtkT_.at(instance); - return sqrtkT * sqrtkT / K_BOLTZMANN; - } else { - return sqrtkT_[0] * sqrtkT_[0] / K_BOLTZMANN; - } -} - -void -Cell::set_temperature(double T, int32_t instance) -{ - if (settings::temperature_method == TEMPERATURE_INTERPOLATION) { - if (T < data::temperature_min) { - throw std::runtime_error{"Temperature is below minimum temperature at " - "which data is available."}; - } else if (T > data::temperature_max) { - throw std::runtime_error{"Temperature is above maximum temperature at " - "which data is available."}; - } - } - - if (instance >= 0) { - sqrtkT_.at(instance) = std::sqrt(K_BOLTZMANN * T); - } else { - for (auto& T_ : sqrtkT_) { - T_ = std::sqrt(K_BOLTZMANN * T); - } - } -} - -//============================================================================== -// CSGCell implementation -//============================================================================== - -CSGCell::CSGCell() {} // empty constructor - -CSGCell::CSGCell(pugi::xml_node cell_node) -{ - if (check_for_node(cell_node, "id")) { - id_ = std::stoi(get_node_value(cell_node, "id")); - } else { - fatal_error("Must specify id of cell in geometry XML file."); - } - - if (check_for_node(cell_node, "name")) { - name_ = get_node_value(cell_node, "name"); - } - - if (check_for_node(cell_node, "universe")) { - universe_ = std::stoi(get_node_value(cell_node, "universe")); - } else { - universe_ = 0; - } - - // Make sure that either material or fill was specified, but not both. - bool fill_present = check_for_node(cell_node, "fill"); - bool material_present = check_for_node(cell_node, "material"); - if (!(fill_present || material_present)) { - std::stringstream err_msg; - err_msg << "Neither material nor fill was specified for cell " << id_; - fatal_error(err_msg); - } - if (fill_present && material_present) { - std::stringstream err_msg; - err_msg << "Cell " << id_ << " has both a material and a fill specified; " - << "only one can be specified per cell"; - fatal_error(err_msg); - } - - if (fill_present) { - fill_ = std::stoi(get_node_value(cell_node, "fill")); - } else { - fill_ = C_NONE; - } - - // Read the material element. There can be zero materials (filled with a - // universe), more than one material (distribmats), and some materials may - // be "void". - if (material_present) { - std::vector mats - {get_node_array(cell_node, "material", true)}; - if (mats.size() > 0) { - material_.reserve(mats.size()); - for (std::string mat : mats) { - if (mat.compare("void") == 0) { - material_.push_back(MATERIAL_VOID); - } else { - material_.push_back(std::stoi(mat)); - } - } - } else { - std::stringstream err_msg; - err_msg << "An empty material element was specified for cell " << id_; - fatal_error(err_msg); - } - } - - // Read the temperature element which may be distributed like materials. - if (check_for_node(cell_node, "temperature")) { - sqrtkT_ = get_node_array(cell_node, "temperature"); - sqrtkT_.shrink_to_fit(); - - // Make sure this is a material-filled cell. - if (material_.size() == 0) { - std::stringstream err_msg; - err_msg << "Cell " << id_ << " was specified with a temperature but " - "no material. Temperature specification is only valid for cells " - "filled with a material."; - fatal_error(err_msg); - } - - // Make sure all temperatures are non-negative. - for (auto T : sqrtkT_) { - if (T < 0) { - std::stringstream err_msg; - err_msg << "Cell " << id_ - << " was specified with a negative temperature"; - fatal_error(err_msg); - } - } - - // Convert to sqrt(k*T). - for (auto& T : sqrtkT_) { - T = std::sqrt(K_BOLTZMANN * T); - } - } - - // Read the region specification. - std::string region_spec; - if (check_for_node(cell_node, "region")) { - region_spec = get_node_value(cell_node, "region"); - } - - // Get a tokenized representation of the region specification. - region_ = tokenize(region_spec); - region_.shrink_to_fit(); - - // Convert user IDs to surface indices. - for (auto& r : region_) { - if (r < OP_UNION) { - const auto& it {model::surface_map.find(abs(r))}; - if (it == model::surface_map.end()) { - throw std::runtime_error{"Invalid surface ID " + std::to_string(abs(r)) - + " specified in region for cell " + std::to_string(id_) + "."}; - } - r = copysign(it->second + 1, r); - } - } - - // Convert the infix region spec to RPN. - rpn_ = generate_rpn(id_, region_); - - // Check if this is a simple cell. - simple_ = true; - for (int32_t token : rpn_) { - if ((token == OP_COMPLEMENT) || (token == OP_UNION)) { - simple_ = false; - break; - } - } - - // If this cell is simple, remove all the superfluous operator tokens. - if (simple_) { - size_t i0 = 0; - size_t i1 = 0; - while (i1 < rpn_.size()) { - if (rpn_[i1] < OP_UNION) { - rpn_[i0] = rpn_[i1]; - ++i0; - } - ++i1; - } - rpn_.resize(i0); - } - rpn_.shrink_to_fit(); - - // Read the translation vector. - if (check_for_node(cell_node, "translation")) { - if (fill_ == C_NONE) { - std::stringstream err_msg; - err_msg << "Cannot apply a translation to cell " << id_ - << " because it is not filled with another universe"; - fatal_error(err_msg); - } - - auto xyz {get_node_array(cell_node, "translation")}; - if (xyz.size() != 3) { - std::stringstream err_msg; - err_msg << "Non-3D translation vector applied to cell " << id_; - fatal_error(err_msg); - } - translation_ = xyz; - } - - // Read the rotation transform. - if (check_for_node(cell_node, "rotation")) { - if (fill_ == C_NONE) { - std::stringstream err_msg; - err_msg << "Cannot apply a rotation to cell " << id_ - << " because it is not filled with another universe"; - fatal_error(err_msg); - } - - auto rot {get_node_array(cell_node, "rotation")}; - if (rot.size() != 3) { - std::stringstream err_msg; - err_msg << "Non-3D rotation vector applied to cell " << id_; - fatal_error(err_msg); - } - - // Store the rotation angles. - rotation_.reserve(12); - rotation_.push_back(rot[0]); - rotation_.push_back(rot[1]); - rotation_.push_back(rot[2]); - - // Compute and store the rotation matrix. - auto phi = -rot[0] * PI / 180.0; - auto theta = -rot[1] * PI / 180.0; - auto psi = -rot[2] * PI / 180.0; - rotation_.push_back(std::cos(theta) * std::cos(psi)); - rotation_.push_back(-std::cos(phi) * std::sin(psi) - + std::sin(phi) * std::sin(theta) * std::cos(psi)); - rotation_.push_back(std::sin(phi) * std::sin(psi) - + std::cos(phi) * std::sin(theta) * std::cos(psi)); - rotation_.push_back(std::cos(theta) * std::sin(psi)); - rotation_.push_back(std::cos(phi) * std::cos(psi) - + std::sin(phi) * std::sin(theta) * std::sin(psi)); - rotation_.push_back(-std::sin(phi) * std::cos(psi) - + std::cos(phi) * std::sin(theta) * std::sin(psi)); - rotation_.push_back(-std::sin(theta)); - rotation_.push_back(std::sin(phi) * std::cos(theta)); - rotation_.push_back(std::cos(phi) * std::cos(theta)); - } -} - -//============================================================================== - -bool -CSGCell::contains(Position r, Direction u, int32_t on_surface) const -{ - if (simple_) { - return contains_simple(r, u, on_surface); - } else { - return contains_complex(r, u, on_surface); - } -} - -//============================================================================== - -std::pair -CSGCell::distance(Position r, Direction u, int32_t on_surface) const -{ - double min_dist {INFTY}; - int32_t i_surf {std::numeric_limits::max()}; - - for (int32_t token : rpn_) { - // Ignore this token if it corresponds to an operator rather than a region. - if (token >= OP_UNION) continue; - - // Calculate the distance to this surface. - // Note the off-by-one indexing - bool coincident {std::abs(token) == std::abs(on_surface)}; - double d {model::surfaces[abs(token)-1]->distance(r, u, coincident)}; - - // Check if this distance is the new minimum. - if (d < min_dist) { - if (std::abs(d - min_dist) / min_dist >= FP_PRECISION) { - min_dist = d; - i_surf = -token; - } - } - } - - return {min_dist, i_surf}; -} - -//============================================================================== - -void -CSGCell::to_hdf5(hid_t cell_group) const -{ - // Create a group for this cell. - std::stringstream group_name; - group_name << "cell " << id_; - auto group = create_group(cell_group, group_name); - - if (!name_.empty()) { - write_string(group, "name", name_, false); - } - - write_dataset(group, "universe", model::universes[universe_]->id_); - - // Write the region specification. - if (!region_.empty()) { - std::stringstream region_spec {}; - for (int32_t token : region_) { - if (token == OP_LEFT_PAREN) { - region_spec << " ("; - } else if (token == OP_RIGHT_PAREN) { - region_spec << " )"; - } else if (token == OP_COMPLEMENT) { - region_spec << " ~"; - } else if (token == OP_INTERSECTION) { - } else if (token == OP_UNION) { - region_spec << " |"; - } else { - // Note the off-by-one indexing - region_spec << " " - << copysign(model::surfaces[abs(token)-1]->id_, token); - } - } - write_string(group, "region", region_spec.str(), false); - } - - // Write fill information. - if (type_ == FILL_MATERIAL) { - write_dataset(group, "fill_type", "material"); - std::vector mat_ids; - for (auto i_mat : material_) { - if (i_mat != MATERIAL_VOID) { - mat_ids.push_back(model::materials[i_mat]->id_); - } else { - mat_ids.push_back(MATERIAL_VOID); - } - } - if (mat_ids.size() == 1) { - write_dataset(group, "material", mat_ids[0]); - } else { - write_dataset(group, "material", mat_ids); - } - - std::vector temps; - for (auto sqrtkT_val : sqrtkT_) - temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN); - write_dataset(group, "temperature", temps); - - } else if (type_ == FILL_UNIVERSE) { - write_dataset(group, "fill_type", "universe"); - write_dataset(group, "fill", model::universes[fill_]->id_); - if (translation_ != Position(0, 0, 0)) { - write_dataset(group, "translation", translation_); - } - if (!rotation_.empty()) { - std::array rot {rotation_[0], rotation_[1], rotation_[2]}; - write_dataset(group, "rotation", rot); - } - - } else if (type_ == FILL_LATTICE) { - write_dataset(group, "fill_type", "lattice"); - write_dataset(group, "lattice", model::lattices[fill_]->id_); - } - - close_group(group); -} - -BoundingBox CSGCell::bounding_box_simple() const { - BoundingBox bbox; - for (int32_t token : rpn_) { - bbox &= model::surfaces[abs(token)-1]->bounding_box(token > 0); - } - return bbox; -} - -void CSGCell::apply_demorgan(std::vector::iterator start, - std::vector::iterator stop) -{ - while (start < stop) { - if (*start < OP_UNION) { *start *= -1; } - else if (*start == OP_UNION) { *start = OP_INTERSECTION; } - else if (*start == OP_INTERSECTION) { *start = OP_UNION; } - start++; - } -} - -std::vector::iterator -CSGCell::find_left_parenthesis(std::vector::iterator start, - const std::vector& rpn) { - // start search at zero - int parenthesis_level = 0; - auto it = start; - while (it != rpn.begin()) { - // look at two tokens at a time - int32_t one = *it; - int32_t two = *(it - 1); - - // decrement parenthesis level if there are two adjacent surfaces - if (one < OP_UNION && two < OP_UNION) { - parenthesis_level--; - // increment if there are two adjacent operators - } else if (one >= OP_UNION && two >= OP_UNION) { - parenthesis_level++; - } - - // if the level gets to zero, return the position - if (parenthesis_level == 0) { - // move the iterator back one before leaving the loop - // so that all tokens in the parenthesis block are included - it--; - break; - } - - // continue loop, one token at a time - it--; - } - return it; -} - -void CSGCell::remove_complement_ops(std::vector& rpn) { - auto it = std::find(rpn.begin(), rpn.end(), OP_COMPLEMENT); - while (it != rpn.end()) { - // find the opening parenthesis (if any) - auto left = find_left_parenthesis(it, rpn); - std::vector tmp(left, it+1); - - // apply DeMorgan's law to any surfaces/operators between these - // positions in the RPN - apply_demorgan(left, it); - // remove complement operator - rpn.erase(it); - // update iterator position - it = std::find(rpn.begin(), rpn.end(), OP_COMPLEMENT); - } -} - -BoundingBox CSGCell::bounding_box_complex(std::vector rpn) { - // remove complements by adjusting surface signs and operators - remove_complement_ops(rpn); - - std::vector stack(rpn.size()); - int i_stack = -1; - - for (auto& token : rpn) { - if (token == OP_UNION) { - stack[i_stack - 1] = stack[i_stack - 1] | stack[i_stack]; - i_stack--; - } else if (token == OP_INTERSECTION) { - stack[i_stack - 1] = stack[i_stack - 1] & stack[i_stack]; - i_stack--; - } else { - i_stack++; - stack[i_stack] = model::surfaces[abs(token) - 1]->bounding_box(token > 0); - } - } - - Ensures(i_stack == 0); - return stack.front(); -} - -BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(rpn_); -} - -//============================================================================== - -bool -CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const -{ - for (int32_t token : rpn_) { - // Assume that no tokens are operators. Evaluate the sense of particle with - // respect to the surface and see if the token matches the sense. If the - // particle's surface attribute is set and matches the token, that - // overrides the determination based on sense(). - if (token == on_surface) { - } else if (-token == on_surface) { - return false; - } else { - // Note the off-by-one indexing - bool sense = model::surfaces[abs(token)-1]->sense(r, u); - if (sense != (token > 0)) {return false;} - } - } - return true; -} - -//============================================================================== - -bool -CSGCell::contains_complex(Position r, Direction u, int32_t on_surface) const -{ - // Make a stack of booleans. We don't know how big it needs to be, but we do - // know that rpn.size() is an upper-bound. - std::vector stack(rpn_.size()); - int i_stack = -1; - - for (int32_t token : rpn_) { - // If the token is a binary operator (intersection/union), apply it to - // the last two items on the stack. If the token is a unary operator - // (complement), apply it to the last item on the stack. - if (token == OP_UNION) { - stack[i_stack-1] = stack[i_stack-1] || stack[i_stack]; - i_stack --; - } else if (token == OP_INTERSECTION) { - stack[i_stack-1] = stack[i_stack-1] && stack[i_stack]; - i_stack --; - } else if (token == OP_COMPLEMENT) { - stack[i_stack] = !stack[i_stack]; - } else { - // If the token is not an operator, evaluate the sense of particle with - // respect to the surface and see if the token matches the sense. If the - // particle's surface attribute is set and matches the token, that - // overrides the determination based on sense(). - i_stack ++; - if (token == on_surface) { - stack[i_stack] = true; - } else if (-token == on_surface) { - stack[i_stack] = false; - } else { - // Note the off-by-one indexing - bool sense = model::surfaces[abs(token)-1]->sense(r, u); - stack[i_stack] = (sense == (token > 0)); - } - } - } - - if (i_stack == 0) { - // The one remaining bool on the stack indicates whether the particle is - // in the cell. - return stack[i_stack]; - } else { - // This case occurs if there is no region specification since i_stack will - // still be -1. - return true; - } -} - -//============================================================================== -// DAGMC Cell implementation -//============================================================================== -#ifdef DAGMC -DAGCell::DAGCell() : Cell{} {}; - -std::pair -DAGCell::distance(Position r, Direction u, int32_t on_surface) const -{ - // if we've changed direction or we're not on a surface, - // reset the history and update last direction - if (u != simulation::last_dir || on_surface == 0) { - simulation::history.reset(); - simulation::last_dir = u; - } - - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - moab::EntityHandle hit_surf; - double dist; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &simulation::history); - MB_CHK_ERR_CONT(rval); - int surf_idx; - if (hit_surf != 0) { - surf_idx = dagmc_ptr_->index_by_handle(hit_surf); - } else { - // indicate that particle is lost - surf_idx = -1; - dist = INFINITY; - } - - return {dist, surf_idx}; -} - -bool DAGCell::contains(Position r, Direction u, int32_t on_surface) const -{ - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - - int result = 0; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->point_in_volume(vol, pnt, result, dir); - MB_CHK_ERR_CONT(rval); - return result; -} - -void DAGCell::to_hdf5(hid_t group_id) const { return; } - -BoundingBox DAGCell::bounding_box() const -{ - moab::ErrorCode rval; - moab::EntityHandle vol = dagmc_ptr_->entity_by_index(3, dag_index_); - double min[3], max[3]; - rval = dagmc_ptr_->getobb(vol, min, max); - MB_CHK_ERR_CONT(rval); - return {min[0], max[0], min[1], max[1], min[2], max[2]}; -} - -#endif - -//============================================================================== -// UniversePartitioner implementation -//============================================================================== - -UniversePartitioner::UniversePartitioner(const Universe& univ) -{ - // Define an ordered set of surface indices that point to z-planes. Use a - // functor to to order the set by the z0_ values of the corresponding planes. - struct compare_surfs { - bool operator()(const int32_t& i_surf, const int32_t& j_surf) const - { - const auto* surf = model::surfaces[i_surf].get(); - const auto* zplane = dynamic_cast(surf); - double zi = zplane->z0_; - surf = model::surfaces[j_surf].get(); - zplane = dynamic_cast(surf); - double zj = zplane->z0_; - return zi < zj; - } - }; - std::set surf_set; - - // Find all of the z-planes in this universe. A set is used here for the - // O(log(n)) insertions that will ensure entries are not repeated. - for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->rpn_) { - if (token < OP_UNION) { - auto i_surf = std::abs(token) - 1; - const auto* surf = model::surfaces[i_surf].get(); - if (const auto* zplane = dynamic_cast(surf)) - surf_set.insert(i_surf); - } - } - } - - // Populate the surfs_ vector from the ordered set. - surfs_.insert(surfs_.begin(), surf_set.begin(), surf_set.end()); - - // Populate the partition lists. - partitions_.resize(surfs_.size() + 1); - for (auto i_cell : univ.cells_) { - // It is difficult to determine the bounds of a complex cell, so add complex - // cells to all partitions. - if (!model::cells[i_cell]->simple_) { - for (auto& p : partitions_) p.push_back(i_cell); - continue; - } - - // Find the tokens for bounding z-planes. - int32_t lower_token = 0, upper_token = 0; - double min_z, max_z; - for (auto token : model::cells[i_cell]->rpn_) { - if (token < OP_UNION) { - const auto* surf = model::surfaces[std::abs(token) - 1].get(); - if (const auto* zplane = dynamic_cast(surf)) { - if (lower_token == 0 || zplane->z0_ < min_z) { - lower_token = token; - min_z = zplane->z0_; - } - if (upper_token == 0 || zplane->z0_ > max_z) { - upper_token = token; - max_z = zplane->z0_; - } - } - } - } - - // If there are no bounding z-planes, add this cell to all partitions. - if (lower_token == 0) { - for (auto& p : partitions_) p.push_back(i_cell); - continue; - } - - // Find the first partition this cell lies in. If the lower_token indicates - // a negative halfspace, then the cell is unbounded in the lower direction - // and it lies in the first partition onward. Otherwise, it is bounded by - // the positive halfspace given by the lower_token. - int first_partition = 0; - if (lower_token > 0) { - for (int i = 0; i < surfs_.size(); ++i) { - if (lower_token == surfs_[i] + 1) { - first_partition = i + 1; - break; - } - } - } - - // Find the last partition this cell lies in. The logic is analogous to the - // logic for first_partition. - int last_partition = surfs_.size(); - if (upper_token < 0) { - for (int i = first_partition; i < surfs_.size(); ++i) { - if (upper_token == -(surfs_[i] + 1)) { - last_partition = i; - break; - } - } - } - - // Add the cell to all relevant partitions. - for (int i = first_partition; i <= last_partition; ++i) { - partitions_[i].push_back(i_cell); - } - } -} - -const std::vector& -UniversePartitioner::get_cells(Position r, Direction u) const -{ - // Perform a binary search for the partition containing the given coordinates. - int left = 0; - int middle = (surfs_.size() - 1) / 2; - int right = surfs_.size() - 1; - while (true) { - // Check the sense of the coordinates for the current surface. - const auto& surf = *model::surfaces[surfs_[middle]]; - if (surf.sense(r, u)) { - // The coordinates lie in the positive halfspace. Recurse if there are - // more surfaces to check. Otherwise, return the cells on the positive - // side of this surface. - int right_leaf = right - (right - middle) / 2; - if (right_leaf != middle) { - left = middle + 1; - middle = right_leaf; - } else { - return partitions_[middle+1]; - } - - } else { - // The coordinates lie in the negative halfspace. Recurse if there are - // more surfaces to check. Otherwise, return the cells on the negative - // side of this surface. - int left_leaf = left + (middle - left) / 2; - if (left_leaf != middle) { - right = middle-1; - middle = left_leaf; - } else { - return partitions_[middle]; - } - } - } -} - -//============================================================================== -// Non-method functions -//============================================================================== - -void read_cells(pugi::xml_node node) -{ - // Count the number of cells. - int n_cells = 0; - for (pugi::xml_node cell_node: node.children("cell")) {n_cells++;} - if (n_cells == 0) { - fatal_error("No cells found in geometry.xml!"); - } - - // Loop over XML cell elements and populate the array. - model::cells.reserve(n_cells); - for (pugi::xml_node cell_node : node.children("cell")) { - model::cells.push_back(std::make_unique(cell_node)); - } - - // Fill the cell map. - for (int i = 0; i < model::cells.size(); i++) { - int32_t id = model::cells[i]->id_; - auto search = model::cell_map.find(id); - if (search == model::cell_map.end()) { - model::cell_map[id] = i; - } else { - std::stringstream err_msg; - err_msg << "Two or more cells use the same unique ID: " << id; - fatal_error(err_msg); - } - } - - // Populate the Universe vector and map. - for (int i = 0; i < model::cells.size(); i++) { - int32_t uid = model::cells[i]->universe_; - auto it = model::universe_map.find(uid); - if (it == model::universe_map.end()) { - model::universes.push_back(std::make_unique()); - model::universes.back()->id_ = uid; - model::universes.back()->cells_.push_back(i); - model::universe_map[uid] = model::universes.size() - 1; - } else { - model::universes[it->second]->cells_.push_back(i); - } - } - model::universes.shrink_to_fit(); - - // Allocate the cell overlap count if necessary. - if (settings::check_overlaps) { - model::overlap_check_count.resize(model::cells.size(), 0); - } -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n) -{ - if (index >= 0 && index < model::cells.size()) { - Cell& c {*model::cells[index]}; - *type = c.type_; - if (c.type_ == FILL_MATERIAL) { - *indices = c.material_.data(); - *n = c.material_.size(); - } else { - *indices = &c.fill_; - *n = 1; - } - } else { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_cell_set_fill(int32_t index, int type, int32_t n, - const int32_t* indices) -{ - if (index >= 0 && index < model::cells.size()) { - Cell& c {*model::cells[index]}; - if (type == FILL_MATERIAL) { - c.type_ = FILL_MATERIAL; - c.material_.clear(); - for (int i = 0; i < n; i++) { - int i_mat = indices[i]; - if (i_mat == MATERIAL_VOID) { - c.material_.push_back(MATERIAL_VOID); - } else if (i_mat >= 0 && i_mat < model::materials.size()) { - c.material_.push_back(i_mat); - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - } - c.material_.shrink_to_fit(); - } else if (type == FILL_UNIVERSE) { - c.type_ = FILL_UNIVERSE; - } else { - c.type_ = FILL_LATTICE; - } - } else { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_cell_set_temperature(int32_t index, double T, const int32_t* instance) -{ - if (index < 0 || index >= model::cells.size()) { - strcpy(openmc_err_msg, "Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - int32_t instance_index = instance ? *instance : -1; - try { - model::cells[index]->set_temperature(T, instance_index); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - return 0; -} - -extern "C" int -openmc_cell_get_temperature(int32_t index, const int32_t* instance, double* T) -{ - if (index < 0 || index >= model::cells.size()) { - strcpy(openmc_err_msg, "Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - int32_t instance_index = instance ? *instance : -1; - try { - *T = model::cells[index]->temperature(instance_index); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - return 0; -} - -//! Get the bounding box of a cell -extern "C" int -openmc_cell_bounding_box(const int32_t index, double* llc, double* urc) { - - BoundingBox bbox; - - const auto& c = model::cells[index]; - bbox = c->bounding_box(); - - // set lower left corner values - llc[0] = bbox.xmin; - llc[1] = bbox.ymin; - llc[2] = bbox.zmin; - - // set upper right corner values - urc[0] = bbox.xmax; - urc[1] = bbox.ymax; - urc[2] = bbox.zmax; - - return 0; -} - -//! Get the name of a cell -extern "C" int -openmc_cell_get_name(int32_t index, const char** name) { - if (index < 0 || index >= model::cells.size()) { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *name = model::cells[index]->name().data(); - - return 0; -} - -//! Set the name of a cell -extern "C" int -openmc_cell_set_name(int32_t index, const char* name) { - if (index < 0 || index >= model::cells.size()) { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - model::cells[index]->set_name(name); - - return 0; -} - - -//! Return the index in the cells array of a cell with a given ID -extern "C" int -openmc_get_cell_index(int32_t id, int32_t* index) -{ - auto it = model::cell_map.find(id); - if (it != model::cell_map.end()) { - *index = it->second; - return 0; - } else { - set_errmsg("No cell exists with ID=" + std::to_string(id) + "."); - return OPENMC_E_INVALID_ID; - } -} - -//! Return the ID of a cell -extern "C" int -openmc_cell_get_id(int32_t index, int32_t* id) -{ - if (index >= 0 && index < model::cells.size()) { - *id = model::cells[index]->id_; - return 0; - } else { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -//! Set the ID of a cell -extern "C" int -openmc_cell_set_id(int32_t index, int32_t id) -{ - if (index >= 0 && index < model::cells.size()) { - model::cells[index]->id_ = id; - model::cell_map[id] = index; - return 0; - } else { - set_errmsg("Index in cells array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -//! Extend the cells array by n elements -extern "C" int -openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end) -{ - if (index_start) *index_start = model::cells.size(); - if (index_end) *index_end = model::cells.size() + n - 1; - for (int32_t i = 0; i < n; i++) { - model::cells.push_back(std::make_unique()); - } - return 0; -} - -#ifdef DAGMC -int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed) -{ - moab::EntityHandle surf = - surf_xed->dagmc_ptr_->entity_by_index(2, surf_xed->dag_index_); - moab::EntityHandle vol = - cur_cell->dagmc_ptr_->entity_by_index(3, cur_cell->dag_index_); - - moab::EntityHandle new_vol; - cur_cell->dagmc_ptr_->next_vol(surf, vol, new_vol); - - return cur_cell->dagmc_ptr_->index_by_handle(new_vol); -} -#endif - -extern "C" int cells_size() { return model::cells.size(); } - -} // namespace openmc diff --git a/src/cmfd_solver.cpp b/src/cmfd_solver.cpp deleted file mode 100644 index f7ef57546..000000000 --- a/src/cmfd_solver.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include "openmc/cmfd_solver.h" - -#include -#include - -#include "xtensor/xtensor.hpp" - -#include "openmc/error.h" -#include "openmc/constants.h" -#include "openmc/capi.h" - -namespace openmc { - -namespace cmfd { - -//============================================================================== -// Global variables -//============================================================================== - -std::vector indptr; - -std::vector indices; - -int dim; - -double spectral; - -int nx, ny, nz, ng; - -xt::xtensor indexmap; - -} // namespace cmfd - -//============================================================================== -// MATRIX_TO_INDICES converts a matrix index to spatial and group -// indices -//============================================================================== - -void matrix_to_indices(int irow, int& g, int& i, int& j, int& k) -{ - g = irow % cmfd::ng; - i = cmfd::indexmap(irow/cmfd::ng, 0); - j = cmfd::indexmap(irow/cmfd::ng, 1); - k = cmfd::indexmap(irow/cmfd::ng, 2); -} - -//============================================================================== -// GET_DIAGONAL_INDEX returns the index in CSR index array corresponding to -// the diagonal element of a specified row -//============================================================================== - -int get_diagonal_index(int row) -{ - for (int j = cmfd::indptr[row]; j < cmfd::indptr[row+1]; j++) { - if (cmfd::indices[j] == row) - return j; - } - - // Return -1 if not found - return -1; -} - -//============================================================================== -// SET_INDEXMAP sets the elements of indexmap based on input coremap -//============================================================================== - -void set_indexmap(const int* coremap) -{ - for (int z = 0; z < cmfd::nz; z++) { - for (int y = 0; y < cmfd::ny; y++) { - for (int x = 0; x < cmfd::nx; x++) { - if (coremap[(z*cmfd::ny*cmfd::nx) + (y*cmfd::nx) + x] != CMFD_NOACCEL) { - int counter = coremap[(z*cmfd::ny*cmfd::nx) + (y*cmfd::nx) + x]; - cmfd::indexmap(counter, 0) = x; - cmfd::indexmap(counter, 1) = y; - cmfd::indexmap(counter, 2) = z; - } - } - } - } -} - -//============================================================================== -// CMFD_LINSOLVER_1G solves a one group CMFD linear system -//============================================================================== - -int cmfd_linsolver_1g(const double* A_data, const double* b, double* x, - double tol) -{ - // Set overrelaxation parameter - double w = 1.0; - - // Perform Gauss-Seidel iterations - for (int igs = 1; igs <= 10000; igs++) { - double err = 0.0; - - // Copy over x vector - std::vector tmpx {x, x+cmfd::dim}; - - // Perform red/black Gauss-Seidel iterations - for (int irb = 0; irb < 2; irb++) { - - // Loop around matrix rows - for (int irow = 0; irow < cmfd::dim; irow++) { - int g, i, j, k; - matrix_to_indices(irow, g, i, j, k); - - // Filter out black cells - if ((i+j+k) % 2 != irb) continue; - - // Get index of diagonal for current row - int didx = get_diagonal_index(irow); - - // Perform temporary sums, first do left of diag, then right of diag - double tmp1 = 0.0; - for (int icol = cmfd::indptr[irow]; icol < didx; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - for (int icol = didx + 1; icol < cmfd::indptr[irow + 1]; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - - // Solve for new x - double x1 = (b[irow] - tmp1) / A_data[didx]; - - // Perform overrelaxation - x[irow] = (1.0 - w) * x[irow] + w * x1; - - // Compute residual and update error - double res = (tmpx[irow] - x[irow]) / tmpx[irow]; - err += res * res; - } - } - - // Check convergence - err = std::sqrt(err / cmfd::dim); - if (err < tol) - return igs; - - // Calculate new overrelaxation parameter - w = 1.0/(1.0 - 0.25 * cmfd::spectral * w); - } - - // Throw error, as max iterations met - fatal_error("Maximum Gauss-Seidel iterations encountered."); - - // Return -1 by default, although error thrown before reaching this point - return -1; -} - -//============================================================================== -// CMFD_LINSOLVER_2G solves a two group CMFD linear system -//============================================================================== - -int cmfd_linsolver_2g(const double* A_data, const double* b, double* x, - double tol) -{ - // Set overrelaxation parameter - double w = 1.0; - - // Perform Gauss-Seidel iterations - for (int igs = 1; igs <= 10000; igs++) { - double err = 0.0; - - // Copy over x vector - std::vector tmpx {x, x+cmfd::dim}; - - // Perform red/black Gauss-Seidel iterations - for (int irb = 0; irb < 2; irb++) { - - // Loop around matrix rows - for (int irow = 0; irow < cmfd::dim; irow+=2) { - int g, i, j, k; - matrix_to_indices(irow, g, i, j, k); - - // Filter out black cells - if ((i+j+k) % 2 != irb) continue; - - // Get index of diagonals for current row and next row - int d1idx = get_diagonal_index(irow); - int d2idx = get_diagonal_index(irow+1); - - // Get block diagonal - double m11 = A_data[d1idx]; // group 1 diagonal - double m12 = A_data[d1idx + 1]; // group 1 right of diagonal (sorted by col) - double m21 = A_data[d2idx - 1]; // group 2 left of diagonal (sorted by col) - double m22 = A_data[d2idx]; // group 2 diagonal - - // Analytically invert the diagonal - double dm = m11*m22 - m12*m21; - double d11 = m22/dm; - double d12 = -m12/dm; - double d21 = -m21/dm; - double d22 = m11/dm; - - // Perform temporary sums, first do left of diag, then right of diag - double tmp1 = 0.0; - double tmp2 = 0.0; - for (int icol = cmfd::indptr[irow]; icol < d1idx; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - for (int icol = cmfd::indptr[irow+1]; icol < d2idx-1; icol++) - tmp2 += A_data[icol] * x[cmfd::indices[icol]]; - for (int icol = d1idx + 2; icol < cmfd::indptr[irow + 1]; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - for (int icol = d2idx + 1; icol < cmfd::indptr[irow + 2]; icol++) - tmp2 += A_data[icol] * x[cmfd::indices[icol]]; - - // Adjust with RHS vector - tmp1 = b[irow] - tmp1; - tmp2 = b[irow + 1] - tmp2; - - // Solve for new x - double x1 = d11*tmp1 + d12*tmp2; - double x2 = d21*tmp1 + d22*tmp2; - - // Perform overrelaxation - x[irow] = (1.0 - w) * x[irow] + w * x1; - x[irow + 1] = (1.0 - w) * x[irow + 1] + w * x2; - - // Compute residual and update error - double res = (tmpx[irow] - x[irow]) / tmpx[irow]; - err += res * res; - } - } - - // Check convergence - err = std::sqrt(err / cmfd::dim); - if (err < tol) - return igs; - - // Calculate new overrelaxation parameter - w = 1.0/(1.0 - 0.25 * cmfd::spectral * w); - } - - // Throw error, as max iterations met - fatal_error("Maximum Gauss-Seidel iterations encountered."); - - // Return -1 by default, although error thrown before reaching this point - return -1; -} - -//============================================================================== -// CMFD_LINSOLVER_NG solves a general CMFD linear system -//============================================================================== - -int cmfd_linsolver_ng(const double* A_data, const double* b, double* x, - double tol) -{ - // Set overrelaxation parameter - double w = 1.0; - - // Perform Gauss-Seidel iterations - for (int igs = 1; igs <= 10000; igs++) { - double err = 0.0; - - // Copy over x vector - std::vector tmpx {x, x+cmfd::dim}; - - // Loop around matrix rows - for (int irow = 0; irow < cmfd::dim; irow++) { - // Get index of diagonal for current row - int didx = get_diagonal_index(irow); - - // Perform temporary sums, first do left of diag, then right of diag - double tmp1 = 0.0; - for (int icol = cmfd::indptr[irow]; icol < didx; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - for (int icol = didx + 1; icol < cmfd::indptr[irow + 1]; icol++) - tmp1 += A_data[icol] * x[cmfd::indices[icol]]; - - // Solve for new x - double x1 = (b[irow] - tmp1) / A_data[didx]; - - // Perform overrelaxation - x[irow] = (1.0 - w) * x[irow] + w * x1; - - // Compute residual and update error - double res = (tmpx[irow] - x[irow]) / tmpx[irow]; - err += res * res; - } - - // Check convergence - err = std::sqrt(err / cmfd::dim); - if (err < tol) - return igs; - - // Calculate new overrelaxation parameter - w = 1.0/(1.0 - 0.25 * cmfd::spectral * w); - } - - // Throw error, as max iterations met - fatal_error("Maximum Gauss-Seidel iterations encountered."); - - // Return -1 by default, although error thrown before reaching this point - return -1; -} - -//============================================================================== -// OPENMC_INITIALIZE_LINSOLVER sets the fixed variables that are used for the -// linear solver -//============================================================================== - -extern "C" -void openmc_initialize_linsolver(const int* indptr, int len_indptr, - const int* indices, int n_elements, int dim, - double spectral, const int* cmfd_indices, - const int* map) -{ - // Store elements of indptr - for (int i = 0; i < len_indptr; i++) - cmfd::indptr.push_back(indptr[i]); - - // Store elements of indices - for (int i = 0; i < n_elements; i++) - cmfd::indices.push_back(indices[i]); - - // Set dimenion of CMFD problem and specral radius - cmfd::dim = dim; - cmfd::spectral = spectral; - - // Set number of groups - cmfd::ng = cmfd_indices[3]; - - // Set problem dimensions and indexmap if 1 or 2 group problem - if (cmfd::ng == 1 || cmfd::ng == 2) { - cmfd::nx = cmfd_indices[0]; - cmfd::ny = cmfd_indices[1]; - cmfd::nz = cmfd_indices[2]; - - // Resize indexmap and set its elements - cmfd::indexmap.resize({static_cast(dim), 3}); - set_indexmap(map); - } -} - -//============================================================================== -// OPENMC_RUN_LINSOLVER runs a Gauss Seidel linear solver to solve CMFD matrix -// equations -//============================================================================== - -extern "C" -int openmc_run_linsolver(const double* A_data, const double* b, double* x, - double tol) -{ - switch (cmfd::ng) { - case 1: - return cmfd_linsolver_1g(A_data, b, x, tol); - case 2: - return cmfd_linsolver_2g(A_data, b, x, tol); - default: - return cmfd_linsolver_ng(A_data, b, x, tol); - } -} - -void free_memory_cmfd() -{ - cmfd::indptr.clear(); - cmfd::indices.clear(); - // Resize indexmap to be an empty array - cmfd::indexmap.resize({0}); -} - -} // namespace openmc diff --git a/src/cross_sections.cpp b/src/cross_sections.cpp deleted file mode 100644 index 3c29dd8e6..000000000 --- a/src/cross_sections.cpp +++ /dev/null @@ -1,433 +0,0 @@ -#include "openmc/cross_sections.h" - -#include "openmc/constants.h" -#include "openmc/container_util.h" -#ifdef DAGMC -#include "openmc/dagmc.h" -#endif -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/thermal.h" -#include "openmc/xml_interface.h" -#include "openmc/wmp.h" - -#include "pugixml.hpp" - -#include // for getenv -#include - -namespace openmc { - -//============================================================================== -// Global variable declarations -//============================================================================== - -namespace data { - -std::vector libraries; -std::map library_map; - -} - -//============================================================================== -// Library methods -//============================================================================== - -Library::Library(pugi::xml_node node, const std::string& directory) -{ - // Get type of library - if (check_for_node(node, "type")) { - auto type = get_node_value(node, "type"); - if (type == "neutron") { - type_ = Type::neutron; - } else if (type == "thermal") { - type_ = Type::thermal; - } else if (type == "photon") { - type_ = Type::photon; - } else if (type == "wmp") { - type_ = Type::wmp; - } else { - fatal_error("Unrecognized library type: " + type); - } - } else { - fatal_error("Missing library type"); - } - - // Get list of materials - if (check_for_node(node, "materials")) { - materials_ = get_node_array(node, "materials"); - } - - // determine path of cross section table - if (!check_for_node(node, "path")) { - fatal_error("Missing library path"); - } - std::string path = get_node_value(node, "path"); - - if (starts_with(path, "/")) { - path_ = path; - } else if (ends_with(directory, "/")) { - path_ = directory + path; - } else { - path_ = directory + "/" + path; - } - - if (!file_exists(path_)) { - warning("Cross section library " + path_ + " does not exist."); - } -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_cross_sections_xml() -{ - pugi::xml_document doc; - std::string filename = settings::path_input + "materials.xml"; -#ifdef DAGMC - std::string s; - bool found_uwuw_mats = false; - if (settings::dagmc) { - found_uwuw_mats = get_uwuw_materials_xml(s); - } - - if (found_uwuw_mats) { - // if we found uwuw materials, load those - doc.load_file(s.c_str()); - } else { -#endif - // Check if materials.xml exists - if (!file_exists(filename)) { - fatal_error("Material XML file '" + filename + "' does not exist."); - } - // Parse materials.xml file - doc.load_file(filename.c_str()); -#ifdef DAGMC - } -#endif - - auto root = doc.document_element(); - - // Find cross_sections.xml file -- the first place to look is the - // materials.xml file. If no file is found there, then we check the - // OPENMC_CROSS_SECTIONS environment variable - if (!check_for_node(root, "cross_sections")) { - // No cross_sections.xml file specified in settings.xml, check - // environment variable - if (settings::run_CE) { - char* envvar = std::getenv("OPENMC_CROSS_SECTIONS"); - if (!envvar) { - fatal_error("No cross_sections.xml file was specified in " - "materials.xml or in the OPENMC_CROSS_SECTIONS" - " environment variable. OpenMC needs such a file to identify " - "where to find data libraries. Please consult the" - " user's guide at https://openmc.readthedocs.io for " - "information on how to set up data libraries."); - } - settings::path_cross_sections = envvar; - } else { - char* envvar = std::getenv("OPENMC_MG_CROSS_SECTIONS"); - if (!envvar) { - fatal_error("No mgxs.h5 file was specified in " - "materials.xml or in the OPENMC_MG_CROSS_SECTIONS environment " - "variable. OpenMC needs such a file to identify where to " - "find MG cross section libraries. Please consult the user's " - "guide at http://openmc.readthedocs.io for information on " - "how to set up MG cross section libraries."); - } - settings::path_cross_sections = envvar; - } - } else { - settings::path_cross_sections = get_node_value(root, "cross_sections"); - } - - // Now that the cross_sections.xml or mgxs.h5 has been located, read it in - if (settings::run_CE) { - read_ce_cross_sections_xml(); - } else { - read_mg_cross_sections_header(); - } - - // Establish mapping between (type, material) and index in libraries - int i = 0; - for (const auto& lib : data::libraries) { - for (const auto& name : lib.materials_) { - LibraryKey key {lib.type_, name}; - data::library_map.insert({key, i}); - } - ++i; - } - - // Check that 0K nuclides are listed in the cross_sections.xml file - for (const auto& name : settings::res_scat_nuclides) { - LibraryKey key {Library::Type::neutron, name}; - if (data::library_map.find(key) == data::library_map.end()) { - fatal_error("Could not find resonant scatterer " + - name + " in cross_sections.xml file!"); - } - } -} - -void -read_ce_cross_sections(const std::vector>& nuc_temps, - const std::vector>& thermal_temps) -{ - std::unordered_set already_read; - - // Construct a vector of nuclide names because we haven't loaded nuclide data - // yet, but we need to know the name of the i-th nuclide - std::vector nuclide_names(data::nuclide_map.size()); - std::vector thermal_names(data::thermal_scatt_map.size()); - for (const auto& kv : data::nuclide_map) { - nuclide_names[kv.second] = kv.first; - } - for (const auto& kv : data::thermal_scatt_map) { - thermal_names[kv.second] = kv.first; - } - - // Read cross sections - for (const auto& mat : model::materials) { - for (int i_nuc : mat->nuclide_) { - // Find name of corresponding nuclide. Because we haven't actually loaded - // data, we don't have the name available, so instead we search through - // all key/value pairs in nuclide_map - std::string& name = nuclide_names[i_nuc]; - - // If we've already read this nuclide, skip it - if (already_read.find(name) != already_read.end()) continue; - - LibraryKey key {Library::Type::neutron, name}; - int idx = data::library_map[key]; - std::string& filename = data::libraries[idx].path_; - - write_message("Reading " + name + " from " + filename, 6); - - // Open file and make sure version is sufficient - hid_t file_id = file_open(filename, 'r'); - check_data_version(file_id); - - // Read nuclide data from HDF5 - hid_t group = open_group(file_id, name.c_str()); - int i_nuclide = data::nuclides.size(); - data::nuclides.push_back(std::make_unique( - group, nuc_temps[i_nuc], i_nuclide)); - - close_group(group); - file_close(file_id); - - // Determine if minimum/maximum energy for this nuclide is greater/less - // than the previous - if (data::nuclides[i_nuclide]->grid_.size() >= 1) { - int neutron = static_cast(Particle::Type::neutron); - data::energy_min[neutron] = std::max(data::energy_min[neutron], - data::nuclides[i_nuclide]->grid_[0].energy.front()); - data::energy_max[neutron] = std::min(data::energy_max[neutron], - data::nuclides[i_nuclide]->grid_[0].energy.back()); - } - - // Add name and alias to dictionary - already_read.insert(name); - - // Check if elemental data has been read, if needed - std::string element = to_element(name); - if (settings::photon_transport) { - if (already_read.find(element) == already_read.end()) { - // Read photon interaction data from HDF5 photon library - LibraryKey key {Library::Type::photon, element}; - int idx = data::library_map[key]; - std::string& filename = data::libraries[idx].path_; - write_message("Reading " + element + " from " + filename, 6); - - // Open file and make sure version is sufficient - hid_t file_id = file_open(filename, 'r'); - check_data_version(file_id); - - // Read element data from HDF5 - hid_t group = open_group(file_id, element.c_str()); - data::elements.emplace_back(group, data::elements.size()); - - // Determine if minimum/maximum energy for this element is greater/less than - // the previous - const auto& elem {data::elements.back()}; - if (elem.energy_.size() >= 1) { - int photon = static_cast(Particle::Type::photon); - int n = elem.energy_.size(); - data::energy_min[photon] = std::max(data::energy_min[photon], - std::exp(elem.energy_(1))); - data::energy_max[photon] = std::min(data::energy_max[photon], - std::exp(elem.energy_(n - 1))); - } - - close_group(group); - file_close(file_id); - - // Add element to set - already_read.insert(element); - } - } - - // Read multipole file into the appropriate entry on the nuclides array - if (settings::temperature_multipole) read_multipole_data(i_nuclide); - } - } - - for (auto& mat : model::materials) { - for (const auto& table : mat->thermal_tables_) { - // Get name of S(a,b) table - int i_table = table.index_table; - std::string& name = thermal_names[i_table]; - - if (already_read.find(name) == already_read.end()) { - LibraryKey key {Library::Type::thermal, name}; - int idx = data::library_map[key]; - std::string& filename = data::libraries[idx].path_; - - write_message("Reading " + name + " from " + filename, 6); - - // Open file and make sure version matches - hid_t file_id = file_open(filename, 'r'); - check_data_version(file_id); - - // Read thermal scattering data from HDF5 - hid_t group = open_group(file_id, name.c_str()); - data::thermal_scatt.push_back(std::make_unique( - group, thermal_temps[i_table])); - close_group(group); - file_close(file_id); - - // Add name to dictionary - already_read.insert(name); - } - } // thermal_tables_ - - // Finish setting up materials (normalizing densities, etc.) - mat->finalize(); - } // materials - - - // Set up logarithmic grid for nuclides - for (auto& nuc : data::nuclides) { - nuc->init_grid(); - } - int neutron = static_cast(Particle::Type::neutron); - simulation::log_spacing = std::log(data::energy_max[neutron] / - data::energy_min[neutron]) / settings::n_log_bins; - - if (settings::photon_transport && settings::electron_treatment == ELECTRON_TTB) { - // Determine if minimum/maximum energy for bremsstrahlung is greater/less - // than the current minimum/maximum - if (data::ttb_e_grid.size() >= 1) { - int photon = static_cast(Particle::Type::photon); - int n_e = data::ttb_e_grid.size(); - data::energy_min[photon] = std::max(data::energy_min[photon], data::ttb_e_grid(1)); - data::energy_max[photon] = std::min(data::energy_max[photon], data::ttb_e_grid(n_e - 1)); - } - - // Take logarithm of energies since they are log-log interpolated - data::ttb_e_grid = xt::log(data::ttb_e_grid); - } - - // Show which nuclide results in lowest energy for neutron transport - for (const auto& nuc : data::nuclides) { - // If a nuclide is present in a material that's not used in the model, its - // grid has not been allocated - if (nuc->grid_.size() > 0) { - double max_E = nuc->grid_[0].energy.back(); - int neutron = static_cast(Particle::Type::neutron); - if (max_E == data::energy_max[neutron]) { - write_message("Maximum neutron transport energy: " + - std::to_string(data::energy_max[neutron]) + " eV for " + - nuc->name_, 7); - if (mpi::master && data::energy_max[neutron] < 20.0e6) { - warning("Maximum neutron energy is below 20 MeV. This may bias " - " the results."); - } - break; - } - } - } - - // Show minimum/maximum temperature - write_message("Minimum neutron data temperature: " + - std::to_string(data::temperature_min) + " K", 4); - write_message("Maximum neutron data temperature: " + - std::to_string(data::temperature_max) + " K", 4); - - // If the user wants multipole, make sure we found a multipole library. - if (settings::temperature_multipole) { - bool mp_found = false; - for (const auto& nuc : data::nuclides) { - if (nuc->multipole_) { - mp_found = true; - break; - } - } - if (mpi::master && !mp_found) { - warning("Windowed multipole functionality is turned on, but no multipole " - "libraries were found. Make sure that windowed multipole data is " - "present in your cross_sections.xml file."); - } - } -} - -void read_ce_cross_sections_xml() -{ - // Check if cross_sections.xml exists - const auto& filename = settings::path_cross_sections; - if (!file_exists(filename)) { - // Could not find cross_sections.xml file - fatal_error("Cross sections XML file '" + filename + - "' does not exist."); - } - - write_message("Reading cross sections XML file...", 5); - - // Parse cross_sections.xml file - pugi::xml_document doc; - auto result = doc.load_file(filename.c_str()); - if (!result) { - fatal_error("Error processing cross_sections.xml file."); - } - auto root = doc.document_element(); - - std::string directory; - if (check_for_node(root, "directory")) { - // Copy directory information if present - directory = get_node_value(root, "directory"); - } else { - // If no directory is listed in cross_sections.xml, by default select the - // directory in which the cross_sections.xml file resides - auto pos = filename.rfind("/"); - if (pos == std::string::npos) { - // no '/' found, probably a Windows directory - pos = filename.rfind("\\"); - } - directory = filename.substr(0, pos); - } - - for (const auto& node_library : root.children("library")) { - data::libraries.emplace_back(node_library, directory); - } - - // Make sure file was not empty - if (data::libraries.empty()) { - fatal_error("No cross section libraries present in cross_sections.xml file."); - } -} - -void library_clear() { - data::libraries.clear(); - data::library_map.clear(); -} - -} // namespace openmc diff --git a/src/dagmc.cpp b/src/dagmc.cpp deleted file mode 100644 index 04d4f08c1..000000000 --- a/src/dagmc.cpp +++ /dev/null @@ -1,406 +0,0 @@ -#include "openmc/dagmc.h" - -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/geometry.h" -#include "openmc/geometry_aux.h" -#include "openmc/material.h" -#include "openmc/string_utils.h" -#include "openmc/settings.h" -#include "openmc/surface.h" - -#ifdef DAGMC - -#include "uwuw.hpp" -#include "dagmcmetadata.hpp" - -#endif - -#include -#include -#include -#include - -namespace openmc { - -#ifdef DAGMC -const bool dagmc_enabled = true; -#else -const bool dagmc_enabled = false; -#endif - -} - -#ifdef DAGMC - -namespace openmc { - -const std::string DAGMC_FILENAME = "dagmc.h5m"; - -namespace simulation { - -moab::DagMC::RayHistory history; -Direction last_dir; - -} - -namespace model { - -moab::DagMC* DAG; - -} // namespace model - - -void check_dagmc_file() { - std::string filename = settings::path_input + DAGMC_FILENAME; - if (!file_exists(filename)) { - fatal_error("Geometry DAGMC file '" + filename + "' does not exist!"); - } -} - -bool get_uwuw_materials_xml(std::string& s) { - check_dagmc_file(); - UWUW uwuw((settings::path_input + DAGMC_FILENAME).c_str()); - - std::stringstream ss; - bool uwuw_mats_present = false; - if (uwuw.material_library.size() != 0) { - uwuw_mats_present = true; - // write header - ss << "\n"; - ss << "\n"; - const auto& mat_lib = uwuw.material_library; - // write materials - for (auto mat : mat_lib) { ss << mat.second.openmc("atom"); } - // write footer - ss << ""; - s = ss.str(); - } - - return uwuw_mats_present; -} - -bool read_uwuw_materials(pugi::xml_document& doc) { - std::string s; - bool found_uwuw_mats = get_uwuw_materials_xml(s); - if (found_uwuw_mats) { - pugi::xml_parse_result result = doc.load_string(s.c_str()); - } - return found_uwuw_mats; -} - -bool write_uwuw_materials_xml() { - std::string s; - bool found_uwuw_mats = get_uwuw_materials_xml(s); - // if there is a material library in the file - if (found_uwuw_mats) { - // write a material.xml file - std::ofstream mats_xml("materials.xml"); - mats_xml << s; - mats_xml.close(); - } - - return found_uwuw_mats; -} - -void legacy_assign_material(const std::string& mat_string, DAGCell* c) -{ - bool mat_found_by_name = false; - // attempt to find a material with a matching name - for (const auto& m : model::materials) { - if (mat_string == m->name_) { - // assign the material with that name - if (!mat_found_by_name) { - mat_found_by_name = true; - c->material_.push_back(m->id_); - // report error if more than one material is found - } else { - std::stringstream err_msg; - err_msg << "More than one material found with name " << mat_string - << ". Please ensure materials have unique names if using this" - << " property to assign materials."; - fatal_error(err_msg); - } - } - } - - // if no material was set using a name, assign by id - if (!mat_found_by_name) { - try { - auto id = std::stoi(mat_string); - c->material_.emplace_back(id); - } catch (const std::invalid_argument&) { - std::stringstream err_msg; - err_msg << "No material " << mat_string - << " found for volume (cell) " << c->id_; - fatal_error(err_msg); - } - } - - if (settings::verbosity >= 10) { - const auto& m = model::materials[model::material_map.at(c->material_[0])]; - std::stringstream msg; - msg << "DAGMC material " << mat_string << " was assigned"; - if (mat_found_by_name) { - msg << " using material name: " << m->name_; - } else { - msg << " using material id: " << m->id_; - } - write_message(msg.str(), 10); - } -} - -void load_dagmc_geometry() -{ - check_dagmc_file(); - - if (!model::DAG) { - model::DAG = new moab::DagMC(); - } - - - std::string filename = settings::path_input + DAGMC_FILENAME; - // --- Materials --- - - // create uwuw instance - UWUW uwuw(filename.c_str()); - - // check for uwuw material definitions - bool using_uwuw = !uwuw.material_library.empty(); - - // notify user if UWUW materials are going to be used - if (using_uwuw) { - write_message("Found UWUW Materials in the DAGMC geometry file.", 6); - } - - int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs - - // load the DAGMC geometry - moab::ErrorCode rval = model::DAG->load_file(filename.c_str()); - MB_CHK_ERR_CONT(rval); - - // initialize acceleration data structures - rval = model::DAG->init_OBBTree(); - MB_CHK_ERR_CONT(rval); - - // parse model metadata - dagmcMetaData DMD(model::DAG); - if (using_uwuw) { - DMD.load_property_data(); - } - std::vector keywords {"temp", "mat", "density", "boundary"}; - std::map dum; - std::string delimiters = ":/"; - rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str()); - MB_CHK_ERR_CONT(rval); - - // --- Cells (Volumes) --- - - // initialize cell objects - int n_cells = model::DAG->num_entities(3); - moab::EntityHandle graveyard = 0; - for (int i = 0; i < n_cells; i++) { - moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1); - - // set cell ids using global IDs - DAGCell* c = new DAGCell(); - c->dag_index_ = i+1; - c->id_ = model::DAG->id_by_index(3, c->dag_index_); - c->dagmc_ptr_ = model::DAG; - c->universe_ = dagmc_univ_id; // set to zero for now - c->fill_ = C_NONE; // no fill, single universe - - model::cells.emplace_back(c); - model::cell_map[c->id_] = i; - - // Populate the Universe vector and dict - auto it = model::universe_map.find(dagmc_univ_id); - if (it == model::universe_map.end()) { - model::universes.push_back(std::make_unique()); - model::universes.back()->id_ = dagmc_univ_id; - model::universes.back()->cells_.push_back(i); - model::universe_map[dagmc_univ_id] = model::universes.size() - 1; - } else { - model::universes[it->second]->cells_.push_back(i); - } - - // MATERIALS - - if (model::DAG->is_implicit_complement(vol_handle)) { - if (model::DAG->has_prop(vol_handle, "mat")) { - // if the implicit complement has been assigned a material, use it - if (using_uwuw) { - std::string comp_mat = DMD.volume_material_property_data_eh[vol_handle]; - // Note: material numbers are set by UWUW - int mat_number = uwuw.material_library[comp_mat].metadata["mat_number"].asInt(); - c->material_.push_back(mat_number); - } else { - std::string mat_value; - rval= model::DAG->prop_value(vol_handle, "mat", mat_value); - MB_CHK_ERR_CONT(rval); - // remove _comp - std::string _comp = "_comp"; - size_t _comp_pos = mat_value.find(_comp); - if (_comp_pos != std::string::npos) { mat_value.erase(_comp_pos, _comp.length()); } - // assign IC material by id - legacy_assign_material(mat_value, c); - } - } else { - // if no material is found, the implicit complement is void - c->material_.push_back(MATERIAL_VOID); - } - continue; - } - - // determine volume material assignment - std::string mat_value; - if (model::DAG->has_prop(vol_handle, "mat")) { - rval = model::DAG->prop_value(vol_handle, "mat", mat_value); - MB_CHK_ERR_CONT(rval); - } else { - std::stringstream err_msg; - err_msg << "Volume " << c->id_ << " has no material assignment."; - fatal_error(err_msg.str()); - } - - std::string cmp_str = mat_value; - to_lower(cmp_str); - - if (cmp_str.find("graveyard") != std::string::npos) { - graveyard = vol_handle; - } - - // material void checks - if (cmp_str.find("void") != std::string::npos || - cmp_str.find("vacuum") != std::string::npos || - cmp_str.find("graveyard") != std::string::npos) { - c->material_.push_back(MATERIAL_VOID); - } else { - if (using_uwuw) { - // lookup material in uwuw if the were present - std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle]; - if (uwuw.material_library.count(uwuw_mat) != 0) { - // Note: material numbers are set by UWUW - int mat_number = uwuw.material_library[uwuw_mat].metadata["mat_number"].asInt(); - c->material_.push_back(mat_number); - } else { - std::stringstream err_msg; - err_msg << "Material with value " << mat_value << " not found "; - err_msg << "in the UWUW material library"; - fatal_error(err_msg); - } - } else { - legacy_assign_material(mat_value, c); - } - } - - // check for temperature assignment - std::string temp_value; - - // no temperature if void - if (c->material_[0] == MATERIAL_VOID) continue; - - // assign cell temperature - const auto& mat = model::materials[model::material_map.at(c->material_[0])]; - if (model::DAG->has_prop(vol_handle, "temp")) { - rval = model::DAG->prop_value(vol_handle, "temp", temp_value); - MB_CHK_ERR_CONT(rval); - double temp = std::stod(temp_value); - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp)); - } else if (mat->temperature_ > 0.0) { - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature_)); - } else { - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default)); - } - - } - - // allocate the cell overlap count if necessary - if (settings::check_overlaps) { - model::overlap_check_count.resize(model::cells.size(), 0); - } - - if (!graveyard) { - warning("No graveyard volume found in the DagMC model." - "This may result in lost particles and rapid simulation failure."); - } - - // --- Surfaces --- - - // initialize surface objects - int n_surfaces = model::DAG->num_entities(2); - - for (int i = 0; i < n_surfaces; i++) { - moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1); - - // set cell ids using global IDs - DAGSurface* s = new DAGSurface(); - s->dag_index_ = i+1; - s->id_ = model::DAG->id_by_index(2, s->dag_index_); - s->dagmc_ptr_ = model::DAG; - - // set BCs - std::string bc_value; - if (model::DAG->has_prop(surf_handle, "boundary")) { - rval = model::DAG->prop_value(surf_handle, "boundary", bc_value); - MB_CHK_ERR_CONT(rval); - to_lower(bc_value); - - if (bc_value == "transmit" || bc_value == "transmission") { - s->bc_ = BC_TRANSMIT; - } else if (bc_value == "vacuum") { - s->bc_ = BC_VACUUM; - } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") { - s->bc_ = BC_REFLECT; - } else if (bc_value == "periodic") { - fatal_error("Periodic boundary condition not supported in DAGMC."); - } else { - std::stringstream err_msg; - err_msg << "Unknown boundary condition \"" << s->bc_ - << "\" specified on surface " << s->id_; - fatal_error(err_msg); - } - } else { - // if no condition is found, set to transmit - s->bc_ = BC_TRANSMIT; - } - - // graveyard check - moab::Range parent_vols; - rval = model::DAG->moab_instance()->get_parent_meshsets(surf_handle, parent_vols); - MB_CHK_ERR_CONT(rval); - - // if this surface belongs to the graveyard - if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) { - // set BC to vacuum - s->bc_ = BC_VACUUM; - } - - // add to global array and map - model::surfaces.emplace_back(s); - model::surface_map[s->id_] = i; - } - - return; -} - -void read_geometry_dagmc() -{ - // Check if dagmc.h5m exists - check_dagmc_file(); - write_message("Reading DAGMC geometry...", 5); - load_dagmc_geometry(); - - model::root_universe = find_root_universe(); -} - -void free_memory_dagmc() -{ - delete model::DAG; -} - - -} -#endif diff --git a/src/distribution.cpp b/src/distribution.cpp deleted file mode 100644 index 8b77d86b8..000000000 --- a/src/distribution.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "openmc/distribution.h" - -#include // for copy -#include // for sqrt, floor, max -#include // for back_inserter -#include // for accumulate -#include // for runtime_error -#include // for string, stod - -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/random_lcg.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Discrete implementation -//============================================================================== - -Discrete::Discrete(pugi::xml_node node) -{ - auto params = get_node_array(node, "parameters"); - - std::size_t n = params.size(); - std::copy(params.begin(), params.begin() + n/2, std::back_inserter(x_)); - std::copy(params.begin() + n/2, params.end(), std::back_inserter(p_)); - - normalize(); -} - -Discrete::Discrete(const double* x, const double* p, int n) - : x_{x, x+n}, p_{p, p+n} -{ - normalize(); -} - -double Discrete::sample() const -{ - int n = x_.size(); - if (n > 1) { - double xi = prn(); - double c = 0.0; - for (int i = 0; i < n; ++i) { - c += p_[i]; - if (xi < c) return x_[i]; - } - throw std::runtime_error{"Error when sampling probability mass function."}; - } else { - return x_[0]; - } -} - -void Discrete::normalize() -{ - // Renormalize density function so that it sums to unity - double norm = std::accumulate(p_.begin(), p_.end(), 0.0); - for (auto& p_i : p_) - p_i /= norm; -} - -//============================================================================== -// Uniform implementation -//============================================================================== - -Uniform::Uniform(pugi::xml_node node) -{ - auto params = get_node_array(node, "parameters"); - if (params.size() != 2) - openmc::fatal_error("Uniform distribution must have two " - "parameters specified."); - - a_ = params.at(0); - b_ = params.at(1); -} - -double Uniform::sample() const -{ - return a_ + prn()*(b_ - a_); -} - -//============================================================================== -// Maxwell implementation -//============================================================================== - -Maxwell::Maxwell(pugi::xml_node node) -{ - theta_ = std::stod(get_node_value(node, "parameters")); -} - -double Maxwell::sample() const -{ - return maxwell_spectrum(theta_); -} - -//============================================================================== -// Watt implementation -//============================================================================== - -Watt::Watt(pugi::xml_node node) -{ - auto params = get_node_array(node, "parameters"); - if (params.size() != 2) - openmc::fatal_error("Watt energy distribution must have two " - "parameters specified."); - - a_ = params.at(0); - b_ = params.at(1); -} - -double Watt::sample() const -{ - return watt_spectrum(a_, b_); -} - -//============================================================================== -// Normal implementation -//============================================================================== -Normal::Normal(pugi::xml_node node) -{ - auto params = get_node_array(node,"parameters"); - if (params.size() != 2) - openmc::fatal_error("Normal energy distribution must have two " - "parameters specified."); - - mean_value_ = params.at(0); - std_dev_ = params.at(1); -} - -double Normal::sample() const -{ - return normal_variate(mean_value_, std_dev_); -} - -//============================================================================== -// Muir implementation -//============================================================================== -Muir::Muir(pugi::xml_node node) -{ - auto params = get_node_array(node,"parameters"); - if (params.size() != 3) - openmc::fatal_error("Muir energy distribution must have three " - "parameters specified."); - - e0_ = params.at(0); - m_rat_ = params.at(1); - kt_ = params.at(2); -} - -double Muir::sample() const -{ - return muir_spectrum(e0_, m_rat_, kt_); -} - -//============================================================================== -// Tabular implementation -//============================================================================== - -Tabular::Tabular(pugi::xml_node node) -{ - if (check_for_node(node, "interpolation")) { - std::string temp = get_node_value(node, "interpolation"); - if (temp == "histogram") { - interp_ = Interpolation::histogram; - } else if (temp == "linear-linear") { - interp_ = Interpolation::lin_lin; - } else { - openmc::fatal_error("Unknown interpolation type for distribution: " + temp); - } - } else { - interp_ = Interpolation::histogram; - } - - // Read and initialize tabular distribution - auto params = get_node_array(node, "parameters"); - std::size_t n = params.size() / 2; - const double* x = params.data(); - const double* p = x + n; - init(x, p, n); -} - -Tabular::Tabular(const double* x, const double* p, int n, Interpolation interp, const double* c) - : interp_{interp} -{ - init(x, p, n, c); -} - -void Tabular::init(const double* x, const double* p, std::size_t n, const double* c) -{ - // Copy x/p arrays into vectors - std::copy(x, x + n, std::back_inserter(x_)); - std::copy(p, p + n, std::back_inserter(p_)); - - // Check interpolation parameter - if (interp_ != Interpolation::histogram && - interp_ != Interpolation::lin_lin) { - openmc::fatal_error("Only histogram and linear-linear interpolation " - "for tabular distribution is supported."); - } - - // Calculate cumulative distribution function - if (c) { - std::copy(c, c + n, std::back_inserter(c_)); - } else { - c_.resize(n); - c_[0] = 0.0; - for (int i = 1; i < n; ++i) { - if (interp_ == Interpolation::histogram) { - c_[i] = c_[i-1] + p_[i-1]*(x_[i] - x_[i-1]); - } else if (interp_ == Interpolation::lin_lin) { - c_[i] = c_[i-1] + 0.5*(p_[i-1] + p_[i]) * (x_[i] - x_[i-1]); - } - } - } - - // Normalize density and distribution functions - for (int i = 0; i < n; ++i) { - p_[i] = p_[i]/c_[n-1]; - c_[i] = c_[i]/c_[n-1]; - } -} - -double Tabular::sample() const -{ - // Sample value of CDF - double c = prn(); - - // Find first CDF bin which is above the sampled value - double c_i = c_[0]; - int i; - std::size_t n = c_.size(); - for (i = 0; i < n - 1; ++i) { - if (c <= c_[i+1]) break; - c_i = c_[i+1]; - } - - // Determine bounding PDF values - double x_i = x_[i]; - double p_i = p_[i]; - - if (interp_ == Interpolation::histogram) { - // Histogram interpolation - if (p_i > 0.0) { - return x_i + (c - c_i)/p_i; - } else { - return x_i; - } - } else { - // Linear-linear interpolation - double x_i1 = x_[i + 1]; - double p_i1 = p_[i + 1]; - - double m = (p_i1 - p_i)/(x_i1 - x_i); - if (m == 0.0) { - return x_i + (c - c_i)/p_i; - } else { - return x_i + (std::sqrt(std::max(0.0, p_i*p_i + 2*m*(c - c_i))) - p_i)/m; - } - } -} - -//============================================================================== -// Equiprobable implementation -//============================================================================== - -double Equiprobable::sample() const -{ - std::size_t n = x_.size(); - - double r = prn(); - int i = std::floor((n - 1)*r); - - double xl = x_[i]; - double xr = x_[i+i]; - return xl + ((n - 1)*r - i) * (xr - xl); -} - -//============================================================================== -// Helper function -//============================================================================== - -UPtrDist distribution_from_xml(pugi::xml_node node) -{ - if (!check_for_node(node, "type")) - openmc::fatal_error("Distribution type must be specified."); - - // Determine type of distribution - std::string type = get_node_value(node, "type", true, true); - - // Allocate extension of Distribution - UPtrDist dist; - if (type == "uniform") { - dist = UPtrDist{new Uniform(node)}; - } else if (type == "maxwell") { - dist = UPtrDist{new Maxwell(node)}; - } else if (type == "watt") { - dist = UPtrDist{new Watt(node)}; - } else if (type == "normal") { - dist = UPtrDist{new Normal(node)}; - } else if (type == "muir") { - dist = UPtrDist{new Muir(node)}; - } else if (type == "discrete") { - dist = UPtrDist{new Discrete(node)}; - } else if (type == "tabular") { - dist = UPtrDist{new Tabular(node)}; - } else { - openmc::fatal_error("Invalid distribution type: " + type); - } - return dist; -} - -} // namespace openmc diff --git a/src/distribution_angle.cpp b/src/distribution_angle.cpp deleted file mode 100644 index 615f84f68..000000000 --- a/src/distribution_angle.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "openmc/distribution_angle.h" - -#include // for abs, copysign -#include // for vector - -#include "xtensor/xarray.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/endf.h" -#include "openmc/hdf5_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" - -namespace openmc { - -//============================================================================== -// AngleDistribution implementation -//============================================================================== - -AngleDistribution::AngleDistribution(hid_t group) -{ - // Get incoming energies - read_dataset(group, "energy", energy_); - int n_energy = energy_.size(); - - // Get outgoing energy distribution data - std::vector offsets; - std::vector interp; - hid_t dset = open_dataset(group, "mu"); - read_attribute(dset, "offsets", offsets); - read_attribute(dset, "interpolation", interp); - xt::xarray temp; - read_dataset(dset, temp); - close_dataset(dset); - - for (int i = 0; i < n_energy; ++i) { - // Determine number of outgoing energies - int j = offsets[i]; - int n; - if (i < n_energy - 1) { - n = offsets[i+1] - j; - } else { - n = temp.shape()[1] - j; - } - - // Create and initialize tabular distribution - auto xs = xt::view(temp, 0, xt::range(j, j+n)); - auto ps = xt::view(temp, 1, xt::range(j, j+n)); - auto cs = xt::view(temp, 2, xt::range(j, j+n)); - std::vector x {xs.begin(), xs.end()}; - std::vector p {ps.begin(), ps.end()}; - std::vector c {cs.begin(), cs.end()}; - - // To get answers that match ACE data, for now we still use the tabulated - // CDF values that were passed through to the HDF5 library. At a later - // time, we can remove the CDF values from the HDF5 library and - // reconstruct them using the PDF - Tabular* mudist = new Tabular{x.data(), p.data(), n, int2interp(interp[i]), - c.data()}; - - distribution_.emplace_back(mudist); - } -} - -double AngleDistribution::sample(double E) const -{ - // Determine number of incoming energies - auto n = energy_.size(); - - // Find energy bin and calculate interpolation factor -- if the energy is - // outside the range of the tabulated energies, choose the first or last bins - int i; - double r; - if (E < energy_[0]) { - i = 0; - r = 0.0; - } else if (E > energy_[n - 1]) { - i = n - 2; - r = 1.0; - } else { - i = lower_bound_index(energy_.begin(), energy_.end(), E); - r = (E - energy_[i])/(energy_[i+1] - energy_[i]); - } - - // Sample between the ith and (i+1)th bin - if (r > prn()) ++i; - - // Sample i-th distribution - double mu = distribution_[i]->sample(); - - // Make sure mu is in range [-1,1] and return - if (std::abs(mu) > 1.0) mu = std::copysign(1.0, mu); - return mu; -} - -} // namespace openmc diff --git a/src/distribution_energy.cpp b/src/distribution_energy.cpp deleted file mode 100644 index 1b9be7346..000000000 --- a/src/distribution_energy.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "openmc/distribution_energy.h" - -#include // for max, min, copy, move -#include // for size_t -#include // for back_inserter - -#include "xtensor/xview.hpp" - -#include "openmc/endf.h" -#include "openmc/hdf5_interface.h" -#include "openmc/math_functions.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" - -namespace openmc { - -//============================================================================== -// DiscretePhoton implementation -//============================================================================== - -DiscretePhoton::DiscretePhoton(hid_t group) -{ - read_attribute(group, "primary_flag", primary_flag_); - read_attribute(group, "energy", energy_); - read_attribute(group, "atomic_weight_ratio", A_); -} - -double DiscretePhoton::sample(double E) const -{ - if (primary_flag_ == 2) { - return energy_ + A_/(A_+ 1)*E; - } else { - return energy_; - } -} - -//============================================================================== -// LevelInelastic implementation -//============================================================================== - -LevelInelastic::LevelInelastic(hid_t group) -{ - read_attribute(group, "threshold", threshold_); - read_attribute(group, "mass_ratio", mass_ratio_); -} - -double LevelInelastic::sample(double E) const -{ - return mass_ratio_*(E - threshold_); -} - -//============================================================================== -// ContinuousTabular implementation -//============================================================================== - -ContinuousTabular::ContinuousTabular(hid_t group) -{ - // Open incoming energy dataset - hid_t dset = open_dataset(group, "energy"); - - // Get interpolation parameters - xt::xarray temp; - read_attribute(dset, "interpolation", temp); - - auto temp_b = xt::view(temp, 0); // view of breakpoints - auto temp_i = xt::view(temp, 1); // view of interpolation parameters - - std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_)); - for (const auto i : temp_i) - interpolation_.push_back(int2interp(i)); - n_region_ = breakpoints_.size(); - - // Get incoming energies - read_dataset(dset, energy_); - std::size_t n_energy = energy_.size(); - close_dataset(dset); - - // Get outgoing energy distribution data - dset = open_dataset(group, "distribution"); - std::vector offsets; - std::vector interp; - std::vector n_discrete; - read_attribute(dset, "offsets", offsets); - read_attribute(dset, "interpolation", interp); - read_attribute(dset, "n_discrete_lines", n_discrete); - - xt::xarray eout; - read_dataset(dset, eout); - close_dataset(dset); - - for (int i = 0; i < n_energy; ++i) { - // Determine number of outgoing energies - int j = offsets[i]; - int n; - if (i < n_energy - 1) { - n = offsets[i+1] - j; - } else { - n = eout.shape()[1] - j; - } - - // Assign interpolation scheme and number of discrete lines - CTTable d; - d.interpolation = int2interp(interp[i]); - d.n_discrete = n_discrete[i]; - - // Copy data - d.e_out = xt::view(eout, 0, xt::range(j, j+n)); - d.p = xt::view(eout, 1, xt::range(j, j+n)); - - // To get answers that match ACE data, for now we still use the tabulated - // CDF values that were passed through to the HDF5 library. At a later - // time, we can remove the CDF values from the HDF5 library and - // reconstruct them using the PDF - if (true) { - d.c = xt::view(eout, 2, xt::range(j, j+n)); - } else { - // Calculate cumulative distribution function -- discrete portion - for (int k = 0; k < d.n_discrete; ++k) { - if (k == 0) { - d.c[k] = d.p[k]; - } else { - d.c[k] = d.c[k-1] + d.p[k]; - } - } - - // Continuous portion - for (int k = d.n_discrete; k < n; ++k) { - if (k == d.n_discrete) { - d.c[k] = d.c[k-1] + d.p[k]; - } else { - if (d.interpolation == Interpolation::histogram) { - d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]); - } else if (d.interpolation == Interpolation::lin_lin) { - d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) * - (d.e_out[k] - d.e_out[k-1]); - } - } - } - - // Normalize density and distribution functions - d.p /= d.c[n - 1]; - d.c /= d.c[n - 1]; - } - - distribution_.push_back(std::move(d)); - } // incoming energies -} - -double ContinuousTabular::sample(double E) const -{ - // Read number of interpolation regions and incoming energies - bool histogram_interp; - if (n_region_ == 1) { - histogram_interp = (interpolation_[0] == Interpolation::histogram); - } else { - histogram_interp = false; - } - - // Find energy bin and calculate interpolation factor -- if the energy is - // outside the range of the tabulated energies, choose the first or last bins - auto n_energy_in = energy_.size(); - int i; - double r; - if (E < energy_[0]) { - i = 0; - r = 0.0; - } else if (E > energy_[n_energy_in - 1]) { - i = n_energy_in - 2; - r = 1.0; - } else { - i = lower_bound_index(energy_.begin(), energy_.end(), E); - r = (E - energy_[i]) / (energy_[i+1] - energy_[i]); - } - - // Sample between the ith and [i+1]th bin - int l; - if (histogram_interp) { - l = i; - } else { - l = r > prn() ? i + 1 : i; - } - - // Interpolation for energy E1 and EK - int n_energy_out = distribution_[i].e_out.size(); - int n_discrete = distribution_[i].n_discrete; - double E_i_1 = distribution_[i].e_out[n_discrete]; - double E_i_K = distribution_[i].e_out[n_energy_out - 1]; - - n_energy_out = distribution_[i+1].e_out.size(); - n_discrete = distribution_[i+1].n_discrete; - double E_i1_1 = distribution_[i+1].e_out[n_discrete]; - double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1]; - - double E_1 = E_i_1 + r*(E_i1_1 - E_i_1); - double E_K = E_i_K + r*(E_i1_K - E_i_K); - - // Determine outgoing energy bin - n_energy_out = distribution_[l].e_out.size(); - n_discrete = distribution_[l].n_discrete; - double r1 = prn(); - double c_k = distribution_[l].c[0]; - int k = 0; - int end = n_energy_out - 2; - - // Discrete portion - for (int j = 0; j < n_discrete; ++j) { - k = j; - c_k = distribution_[l].c[k]; - if (r1 < c_k) { - end = j; - break; - } - } - - // Continuous portion - double c_k1; - for (int j = n_discrete; j < end; ++j) { - k = j; - c_k1 = distribution_[l].c[k+1]; - if (r1 < c_k1) break; - k = j + 1; - c_k = c_k1; - } - - double E_l_k = distribution_[l].e_out[k]; - double p_l_k = distribution_[l].p[k]; - double E_out; - if (distribution_[l].interpolation == Interpolation::histogram) { - // Histogram interpolation - if (p_l_k > 0.0 && k >= n_discrete) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k; - } - - } else if (distribution_[l].interpolation == Interpolation::lin_lin) { - // Linear-linear interpolation - double E_l_k1 = distribution_[l].e_out[k+1]; - double p_l_k1 = distribution_[l].p[k+1]; - - double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k); - if (frac == 0.0) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k + - 2.0*frac*(r1 - c_k))) - p_l_k)/frac; - } - } else { - throw std::runtime_error{"Unexpected interpolation for continuous energy " - "distribution."}; - } - - // Now interpolate between incident energy bins i and i + 1 - if (!histogram_interp && n_energy_out > 1 && k >= n_discrete) { - if (l == i) { - return E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1); - } else { - return E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1); - } - } else { - return E_out; - } - -} - -//============================================================================== -// MaxwellEnergy implementation -//============================================================================== - -MaxwellEnergy::MaxwellEnergy(hid_t group) -{ - read_attribute(group, "u", u_); - hid_t dset = open_dataset(group, "theta"); - theta_ = Tabulated1D{dset}; - close_dataset(dset); -} - -double MaxwellEnergy::sample(double E) const -{ - // Get temperature corresponding to incoming energy - double theta = theta_(E); - - while (true) { - // Sample maxwell fission spectrum - double E_out = maxwell_spectrum(theta); - - // Accept energy based on restriction energy - if (E_out <= E - u_) return E_out; - } -} - -//============================================================================== -// Evaporation implementation -//============================================================================== - -Evaporation::Evaporation(hid_t group) -{ - read_attribute(group, "u", u_); - hid_t dset = open_dataset(group, "theta"); - theta_ = Tabulated1D{dset}; - close_dataset(dset); -} - -double Evaporation::sample(double E) const -{ - // Get temperature corresponding to incoming energy - double theta = theta_(E); - - double y = (E - u_)/theta; - double v = 1.0 - std::exp(-y); - - // Sample outgoing energy based on evaporation spectrum probability - // density function - double x; - while (true) { - x = -std::log((1.0 - v*prn())*(1.0 - v*prn())); - if (x <= y) break; - } - - return x*theta; -} - -//============================================================================== -// WattEnergy implementation -//============================================================================== - -WattEnergy::WattEnergy(hid_t group) -{ - // Read restriction energy - read_attribute(group, "u", u_); - - // Read tabulated functions - hid_t dset = open_dataset(group, "a"); - a_ = Tabulated1D{dset}; - close_dataset(dset); - dset = open_dataset(group, "b"); - b_ = Tabulated1D{dset}; - close_dataset(dset); -} - -double WattEnergy::sample(double E) const -{ - // Determine Watt parameters at incident energy - double a = a_(E); - double b = b_(E); - - while (true) { - // Sample energy-dependent Watt fission spectrum - double E_out = watt_spectrum(a, b); - - // Accept energy based on restriction energy - if (E_out <= E - u_) return E_out; - } -} - -} diff --git a/src/distribution_multi.cpp b/src/distribution_multi.cpp deleted file mode 100644 index c388254b6..000000000 --- a/src/distribution_multi.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "openmc/distribution_multi.h" - -#include // for move -#include // for sqrt, sin, cos, max - -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/random_lcg.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// UnitSphereDistribution implementation -//============================================================================== - -UnitSphereDistribution::UnitSphereDistribution(pugi::xml_node node) -{ - // Read reference directional unit vector - if (check_for_node(node, "reference_uvw")) { - auto u_ref = get_node_array(node, "reference_uvw"); - if (u_ref.size() != 3) - fatal_error("Angular distribution reference direction must have " - "three parameters specified."); - u_ref_ = Direction(u_ref.data()); - } -} - - -//============================================================================== -// PolarAzimuthal implementation -//============================================================================== - -PolarAzimuthal::PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi) : - UnitSphereDistribution{u}, mu_{std::move(mu)}, phi_{std::move(phi)} { } - -PolarAzimuthal::PolarAzimuthal(pugi::xml_node node) - : UnitSphereDistribution{node} -{ - if (check_for_node(node, "mu")) { - pugi::xml_node node_dist = node.child("mu"); - mu_ = distribution_from_xml(node_dist); - } else { - mu_ = UPtrDist{new Uniform(-1., 1.)}; - } - - if (check_for_node(node, "phi")) { - pugi::xml_node node_dist = node.child("phi"); - phi_ = distribution_from_xml(node_dist); - } else { - phi_ = UPtrDist{new Uniform(0.0, 2.0*PI)}; - } -} - -Direction PolarAzimuthal::sample() const -{ - // Sample cosine of polar angle - double mu = mu_->sample(); - if (mu == 1.0) return u_ref_; - - // Sample azimuthal angle - double phi = phi_->sample(); - - // If the reference direction is along the z-axis, rotate the aziumthal angle - // to match spherical coordinate conventions. - // TODO: apply this change directly to rotate_angle - if (u_ref_.x == 0 && u_ref_.y == 0) phi += 0.5*PI; - - return rotate_angle(u_ref_, mu, &phi); -} - -//============================================================================== -// Isotropic implementation -//============================================================================== - -Direction Isotropic::sample() const -{ - double phi = 2.0*PI*prn(); - double mu = 2.0*prn() - 1.0; - return {mu, std::sqrt(1.0 - mu*mu) * std::cos(phi), - std::sqrt(1.0 - mu*mu) * std::sin(phi)}; -} - -//============================================================================== -// Monodirectional implementation -//============================================================================== - -Direction Monodirectional::sample() const -{ - return u_ref_; -} - -} // namespace openmc diff --git a/src/distribution_spatial.cpp b/src/distribution_spatial.cpp deleted file mode 100644 index 15098407b..000000000 --- a/src/distribution_spatial.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "openmc/distribution_spatial.h" - -#include "openmc/error.h" -#include "openmc/random_lcg.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// CartesianIndependent implementation -//============================================================================== - -CartesianIndependent::CartesianIndependent(pugi::xml_node node) -{ - // Read distribution for x coordinate - if (check_for_node(node, "x")) { - pugi::xml_node node_dist = node.child("x"); - x_ = distribution_from_xml(node_dist); - } else { - // If no distribution was specified, default to a single point at x=0 - double x[] {0.0}; - double p[] {1.0}; - x_ = UPtrDist{new Discrete{x, p, 1}}; - } - - // Read distribution for y coordinate - if (check_for_node(node, "y")) { - pugi::xml_node node_dist = node.child("y"); - y_ = distribution_from_xml(node_dist); - } else { - // If no distribution was specified, default to a single point at y=0 - double x[] {0.0}; - double p[] {1.0}; - y_ = UPtrDist{new Discrete{x, p, 1}}; - } - - // Read distribution for z coordinate - if (check_for_node(node, "z")) { - pugi::xml_node node_dist = node.child("z"); - z_ = distribution_from_xml(node_dist); - } else { - // If no distribution was specified, default to a single point at z=0 - double x[] {0.0}; - double p[] {1.0}; - z_ = UPtrDist{new Discrete{x, p, 1}}; - } -} - -Position CartesianIndependent::sample() const -{ - return {x_->sample(), y_->sample(), z_->sample()}; -} - -//============================================================================== -// SpatialBox implementation -//============================================================================== - -SpatialBox::SpatialBox(pugi::xml_node node, bool fission) - : only_fissionable_{fission} -{ - // Read lower-right/upper-left coordinates - auto params = get_node_array(node, "parameters"); - if (params.size() != 6) - openmc::fatal_error("Box/fission spatial source must have six " - "parameters specified."); - - lower_left_ = Position{params[0], params[1], params[2]}; - upper_right_ = Position{params[3], params[4], params[5]}; -} - -Position SpatialBox::sample() const -{ - Position xi {prn(), prn(), prn()}; - return lower_left_ + xi*(upper_right_ - lower_left_); -} - -//============================================================================== -// SpatialPoint implementation -//============================================================================== - -SpatialPoint::SpatialPoint(pugi::xml_node node) -{ - // Read location of point source - auto params = get_node_array(node, "parameters"); - if (params.size() != 3) - openmc::fatal_error("Point spatial source must have three " - "parameters specified."); - - // Set position - r_ = Position{params.data()}; -} - -Position SpatialPoint::sample() const -{ - return r_; -} - -} // namespace openmc diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp deleted file mode 100644 index a0b7f82c5..000000000 --- a/src/eigenvalue.cpp +++ /dev/null @@ -1,654 +0,0 @@ -#include "openmc/eigenvalue.h" - -#include "xtensor/xbuilder.hpp" -#include "xtensor/xmath.hpp" -#include "xtensor/xtensor.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/math_functions.h" -#include "openmc/mesh.h" -#include "openmc/message_passing.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/timer.h" -#include "openmc/tallies/tally.h" - -#ifdef _OPENMP -#include -#endif - -#include // for min -#include -#include // for sqrt, abs, pow -#include // for back_inserter -#include -#include //for infinity - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -double keff_generation; -std::array k_sum; -std::vector entropy; -xt::xtensor source_frac; - -} // namespace simulation - -//============================================================================== -// Non-member functions -//============================================================================== - -void calculate_generation_keff() -{ - const auto& gt = simulation::global_tallies; - - // Get keff for this generation by subtracting off the starting value - simulation::keff_generation = gt(K_TRACKLENGTH, RESULT_VALUE) - simulation::keff_generation; - - double keff_reduced; -#ifdef OPENMC_MPI - // Combine values across all processors - MPI_Allreduce(&simulation::keff_generation, &keff_reduced, 1, MPI_DOUBLE, - MPI_SUM, mpi::intracomm); -#else - keff_reduced = simulation::keff_generation; -#endif - - // Normalize single batch estimate of k - // TODO: This should be normalized by total_weight, not by n_particles - keff_reduced /= settings::n_particles; - simulation::k_generation.push_back(keff_reduced); -} - -void synchronize_bank() -{ - simulation::time_bank.start(); - - // In order to properly understand the fission bank algorithm, you need to - // think of the fission and source bank as being one global array divided - // over multiple processors. At the start, each processor has a random amount - // of fission bank sites -- each processor needs to know the total number of - // sites in order to figure out the probability for selecting - // sites. Furthermore, each proc also needs to know where in the 'global' - // fission bank its own sites starts in order to ensure reproducibility by - // skipping ahead to the proper seed. - -#ifdef OPENMC_MPI - int64_t start = 0; - int64_t n_bank = simulation::fission_bank.size(); - MPI_Exscan(&n_bank, &start, 1, MPI_INT64_T, MPI_SUM, mpi::intracomm); - - // While we would expect the value of start on rank 0 to be 0, the MPI - // standard says that the receive buffer on rank 0 is undefined and not - // significant - if (mpi::rank == 0) start = 0; - - int64_t finish = start + simulation::fission_bank.size(); - int64_t total = finish; - MPI_Bcast(&total, 1, MPI_INT64_T, mpi::n_procs - 1, mpi::intracomm); - -#else - int64_t start = 0; - int64_t finish = simulation::fission_bank.size(); - int64_t total = simulation::fission_bank.size(); -#endif - - // If there are not that many particles per generation, it's possible that no - // fission sites were created at all on a single processor. Rather than add - // extra logic to treat this circumstance, we really want to ensure the user - // runs enough particles to avoid this in the first place. - - if (simulation::fission_bank.empty()) { - fatal_error("No fission sites banked on MPI rank " + std::to_string(mpi::rank)); - } - - // Make sure all processors start at the same point for random sampling. Then - // skip ahead in the sequence using the starting index in the 'global' - // fission bank for each processor. - - set_particle_seed(simulation::total_gen + overall_generation()); - advance_prn_seed(start); - - // Determine how many fission sites we need to sample from the source bank - // and the probability for selecting a site. - - int64_t sites_needed; - if (total < settings::n_particles) { - sites_needed = settings::n_particles % total; - } else { - sites_needed = settings::n_particles; - } - double p_sample = static_cast(sites_needed) / total; - - simulation::time_bank_sample.start(); - - // ========================================================================== - // SAMPLE N_PARTICLES FROM FISSION BANK AND PLACE IN TEMP_SITES - - // Allocate temporary source bank - int64_t index_temp = 0; - std::vector temp_sites(3*simulation::work_per_rank); - - for (const auto& site : simulation::fission_bank) { - // If there are less than n_particles particles banked, automatically add - // int(n_particles/total) sites to temp_sites. For example, if you need - // 1000 and 300 were banked, this would add 3 source sites per banked site - // and the remaining 100 would be randomly sampled. - if (total < settings::n_particles) { - for (int64_t j = 1; j <= settings::n_particles / total; ++j) { - temp_sites[index_temp] = site; - ++index_temp; - } - } - - // Randomly sample sites needed - if (prn() < p_sample) { - temp_sites[index_temp] = site; - ++index_temp; - } - } - - // At this point, the sampling of source sites is done and now we need to - // figure out where to send source sites. Since it is possible that one - // processor's share of the source bank spans more than just the immediate - // neighboring processors, we have to perform an ALLGATHER to determine the - // indices for all processors - -#ifdef OPENMC_MPI - // First do an exclusive scan to get the starting indices for - start = 0; - MPI_Exscan(&index_temp, &start, 1, MPI_INT64_T, MPI_SUM, mpi::intracomm); - finish = start + index_temp; - - // Allocate space for bank_position if this hasn't been done yet - int64_t bank_position[mpi::n_procs]; - MPI_Allgather(&start, 1, MPI_INT64_T, bank_position, 1, - MPI_INT64_T, mpi::intracomm); -#else - start = 0; - finish = index_temp; -#endif - - // Now that the sampling is complete, we need to ensure that we have exactly - // n_particles source sites. The way this is done in a reproducible manner is - // to adjust only the source sites on the last processor. - - if (mpi::rank == mpi::n_procs - 1) { - if (finish > settings::n_particles) { - // If we have extra sites sampled, we will simply discard the extra - // ones on the last processor - index_temp = settings::n_particles - start; - - } else if (finish < settings::n_particles) { - // If we have too few sites, repeat sites from the very end of the - // fission bank - sites_needed = settings::n_particles - finish; - for (int i = 0; i < sites_needed; ++i) { - int i_bank = simulation::fission_bank.size() - sites_needed + i; - temp_sites[index_temp] = simulation::fission_bank[i_bank]; - ++index_temp; - } - } - - // the last processor should not be sending sites to right - finish = simulation::work_index[mpi::rank + 1]; - } - - simulation::time_bank_sample.stop(); - simulation::time_bank_sendrecv.start(); - -#ifdef OPENMC_MPI - // ========================================================================== - // SEND BANK SITES TO NEIGHBORS - - int64_t index_local = 0; - std::vector requests; - - if (start < settings::n_particles) { - // Determine the index of the processor which has the first part of the - // source_bank for the local processor - int neighbor = upper_bound_index(simulation::work_index.begin(), - simulation::work_index.end(), start); - - while (start < finish) { - // Determine the number of sites to send - int64_t n = std::min(simulation::work_index[neighbor + 1], finish) - start; - - // Initiate an asynchronous send of source sites to the neighboring - // process - if (neighbor != mpi::rank) { - requests.emplace_back(); - MPI_Isend(&temp_sites[index_local], static_cast(n), mpi::bank, - neighbor, mpi::rank, mpi::intracomm, &requests.back()); - } - - // Increment all indices - start += n; - index_local += n; - ++neighbor; - - // Check for sites out of bounds -- this only happens in the rare - // circumstance that a processor close to the end has so many sites that - // it would exceed the bank on the last processor - if (neighbor > mpi::n_procs - 1) break; - } - } - - // ========================================================================== - // RECEIVE BANK SITES FROM NEIGHBORS OR TEMPORARY BANK - - start = simulation::work_index[mpi::rank]; - index_local = 0; - - // Determine what process has the source sites that will need to be stored at - // the beginning of this processor's source bank. - - int neighbor; - if (start >= bank_position[mpi::n_procs - 1]) { - neighbor = mpi::n_procs - 1; - } else { - neighbor = upper_bound_index(bank_position, bank_position + mpi::n_procs, start); - } - - while (start < simulation::work_index[mpi::rank + 1]) { - // Determine how many sites need to be received - int64_t n; - if (neighbor == mpi::n_procs - 1) { - n = simulation::work_index[mpi::rank + 1] - start; - } else { - n = std::min(bank_position[neighbor + 1], simulation::work_index[mpi::rank + 1]) - start; - } - - if (neighbor != mpi::rank) { - // If the source sites are not on this processor, initiate an - // asynchronous receive for the source sites - - requests.emplace_back(); - MPI_Irecv(&simulation::source_bank[index_local], static_cast(n), mpi::bank, - neighbor, neighbor, mpi::intracomm, &requests.back()); - - } else { - // If the source sites are on this procesor, we can simply copy them - // from the temp_sites bank - - index_temp = start - bank_position[mpi::rank]; - std::copy(&temp_sites[index_temp], &temp_sites[index_temp + n], - &simulation::source_bank[index_local]); - } - - // Increment all indices - start += n; - index_local += n; - ++neighbor; - } - - // Since we initiated a series of asynchronous ISENDs and IRECVs, now we have - // to ensure that the data has actually been communicated before moving on to - // the next generation - - int n_request = requests.size(); - MPI_Waitall(n_request, requests.data(), MPI_STATUSES_IGNORE); - -#else - std::copy(temp_sites.data(), temp_sites.data() + settings::n_particles, - simulation::source_bank.begin()); -#endif - - simulation::time_bank_sendrecv.stop(); - simulation::time_bank.stop(); -} - -void calculate_average_keff() -{ - // Determine overall generation and number of active generations - int i = overall_generation() - 1; - int n; - if (simulation::current_batch > settings::n_inactive) { - n = settings::gen_per_batch*simulation::n_realizations + simulation::current_gen; - } else { - n = 0; - } - - if (n <= 0) { - // For inactive generations, use current generation k as estimate for next - // generation - simulation::keff = simulation::k_generation[i]; - } else { - // Sample mean of keff - simulation::k_sum[0] += simulation::k_generation[i]; - simulation::k_sum[1] += std::pow(simulation::k_generation[i], 2); - - // Determine mean - simulation::keff = simulation::k_sum[0] / n; - - if (n > 1) { - double t_value; - if (settings::confidence_intervals) { - // Calculate t-value for confidence intervals - double alpha = 1.0 - CONFIDENCE_LEVEL; - t_value = t_percentile(1.0 - alpha/2.0, n - 1); - } else { - t_value = 1.0; - } - - // Standard deviation of the sample mean of k - simulation::keff_std = t_value * std::sqrt((simulation::k_sum[1]/n - - std::pow(simulation::keff, 2)) / (n - 1)); - } - } -} - -#ifdef _OPENMP -void join_bank_from_threads() -{ - int n_threads = omp_get_max_threads(); - - #pragma omp parallel - { - // Copy thread fission bank sites to one shared copy - #pragma omp for ordered schedule(static) - for (int i = 0; i < n_threads; ++i) { - #pragma omp ordered - { - std::copy( - simulation::fission_bank.cbegin(), - simulation::fission_bank.cend(), - std::back_inserter(simulation::master_fission_bank) - ); - } - } - - // Make sure all threads have made it to this point - #pragma omp barrier - - // Now copy the shared fission bank sites back to the master thread's copy. - if (omp_get_thread_num() == 0) { - simulation::fission_bank = simulation::master_fission_bank; - simulation::master_fission_bank.clear(); - } else { - simulation::fission_bank.clear(); - } - } -} -#endif - -int openmc_get_keff(double* k_combined) -{ - k_combined[0] = 0.0; - k_combined[1] = 0.0; - - // Special case for n <=3. Notice that at the end, - // there is a N-3 term in a denominator. - if (simulation::n_realizations <= 3) { - k_combined[0] = simulation::keff; - k_combined[1] = simulation::keff_std; - if (simulation::n_realizations <=1) { - k_combined[1] = std::numeric_limits::infinity(); - } - return 0; - } - - // Initialize variables - int64_t n = simulation::n_realizations; - - // Copy estimates of k-effective and its variance (not variance of the mean) - const auto& gt = simulation::global_tallies; - - std::array kv {}; - xt::xtensor cov = xt::zeros({3, 3}); - kv[0] = gt(K_COLLISION, RESULT_SUM) / n; - kv[1] = gt(K_ABSORPTION, RESULT_SUM) / n; - kv[2] = gt(K_TRACKLENGTH, RESULT_SUM) / n; - cov(0, 0) = (gt(K_COLLISION, RESULT_SUM_SQ) - n*kv[0]*kv[0]) / (n - 1); - cov(1, 1) = (gt(K_ABSORPTION, RESULT_SUM_SQ) - n*kv[1]*kv[1]) / (n - 1); - cov(2, 2) = (gt(K_TRACKLENGTH, RESULT_SUM_SQ) - n*kv[2]*kv[2]) / (n - 1); - - // Calculate covariances based on sums with Bessel's correction - cov(0, 1) = (simulation::k_col_abs - n * kv[0] * kv[1]) / (n - 1); - cov(0, 2) = (simulation::k_col_tra - n * kv[0] * kv[2]) / (n - 1); - cov(1, 2) = (simulation::k_abs_tra - n * kv[1] * kv[2]) / (n - 1); - cov(1, 0) = cov(0, 1); - cov(2, 0) = cov(0, 2); - cov(2, 1) = cov(1, 2); - - // Check to see if two estimators are the same; this is guaranteed to happen - // in MG-mode with survival biasing when the collision and absorption - // estimators are the same, but can theoretically happen at anytime. - // If it does, the standard estimators will produce floating-point - // exceptions and an expression specifically derived for the combination of - // two estimators (vice three) should be used instead. - - // First we will identify if there are any matching estimators - int i, j, k; - if ((std::abs(kv[0] - kv[1]) / kv[0] < FP_REL_PRECISION) && - (std::abs(cov(0, 0) - cov(1, 1)) / cov(0, 0) < FP_REL_PRECISION)) { - // 0 and 1 match, so only use 0 and 2 in our comparisons - i = 0; - j = 2; - - } else if ((std::abs(kv[0] - kv[2]) / kv[0] < FP_REL_PRECISION) && - (std::abs(cov(0, 0) - cov(2, 2)) / cov(0, 0) < FP_REL_PRECISION)) { - // 0 and 2 match, so only use 0 and 1 in our comparisons - i = 0; - j = 1; - - } else if ((std::abs(kv[1] - kv[2]) / kv[1] < FP_REL_PRECISION) && - (std::abs(cov(1, 1) - cov(2, 2)) / cov(1, 1) < FP_REL_PRECISION)) { - // 1 and 2 match, so only use 0 and 1 in our comparisons - i = 0; - j = 1; - - } else { - // No two estimators match, so set i to -1 and this will be the indicator - // to use all three estimators. - i = -1; - } - - if (i == -1) { - // Use three estimators as derived in the paper by Urbatsch - - // Initialize variables - double g = 0.0; - std::array S {}; - - for (int l = 0; l < 3; ++l) { - // Permutations of estimates - switch (l) { - case 0: - // i = collision, j = absorption, k = tracklength - i = 0; - j = 1; - k = 2; - break; - case 1: - // i = absortion, j = tracklength, k = collision - i = 1; - j = 2; - k = 0; - break; - case 2: - // i = tracklength, j = collision, k = absorption - i = 2; - j = 0; - k = 1; - break; - } - - // Calculate weighting - double f = cov(j, j) * (cov(k, k) - cov(i, k)) - cov(k, k) * cov(i, j) + - cov(j, k) * (cov(i, j) + cov(i, k) - cov(j, k)); - - // Add to S sums for variance of combined estimate - S[0] += f * cov(0, l); - S[1] += (cov(j, j) + cov(k, k) - 2.0 * cov(j, k)) * kv[l] * kv[l]; - S[2] += (cov(k, k) + cov(i, j) - cov(j, k) - cov(i, k)) * kv[l] * kv[j]; - - // Add to sum for combined k-effective - k_combined[0] += f * kv[l]; - g += f; - } - - // Complete calculations of S sums - for (auto& S_i : S) { - S_i *= (n - 1); - } - S[0] *= (n - 1)*(n - 1); - - // Calculate combined estimate of k-effective - k_combined[0] /= g; - - // Calculate standard deviation of combined estimate - g *= (n - 1)*(n - 1); - k_combined[1] = std::sqrt(S[0] / (g*n*(n - 3)) * - (1 + n*((S[1] - 2*S[2]) / g))); - - } else { - // Use only two estimators - // These equations are derived analogously to that done in the paper by - // Urbatsch, but are simpler than for the three estimators case since the - // block matrices of the three estimator equations reduces to scalars here - - // Store the commonly used term - double f = kv[i] - kv[j]; - double g = cov(i, i) + cov(j, j) - 2.0*cov(i, j); - - // Calculate combined estimate of k-effective - k_combined[0] = kv[i] - (cov(i, i) - cov(i, j)) / g * f; - - // Calculate standard deviation of combined estimate - k_combined[1] = (cov(i, i)*cov(j, j) - cov(i, j)*cov(i, j)) * - (g + n*f*f) / (n*(n - 2)*g*g); - k_combined[1] = std::sqrt(k_combined[1]); - - } - return 0; -} - -void shannon_entropy() -{ - // Get source weight in each mesh bin - bool sites_outside; - xt::xtensor p = simulation::entropy_mesh->count_sites( - simulation::fission_bank, &sites_outside); - - // display warning message if there were sites outside entropy box - if (sites_outside) { - if (mpi::master) warning("Fission source site(s) outside of entropy box."); - } - - // sum values to obtain shannon entropy - if (mpi::master) { - // Normalize to total weight of bank sites - p /= xt::sum(p); - - double H = 0.0; - for (auto p_i : p) { - if (p_i > 0.0) { - H -= p_i * std::log(p_i)/std::log(2.0); - } - } - - // Add value to vector - simulation::entropy.push_back(H); - } -} - -void ufs_count_sites() -{ - if (simulation::current_batch == 1 && simulation::current_gen == 1) { - // On the first generation, just assume that the source is already evenly - // distributed so that effectively the production of fission sites is not - // biased - - auto s = xt::view(simulation::source_frac, xt::all()); - s = simulation::ufs_mesh->volume_frac_; - - } else { - // count number of source sites in each ufs mesh cell - bool sites_outside; - simulation::source_frac = simulation::ufs_mesh->count_sites( - simulation::source_bank, &sites_outside); - - // Check for sites outside of the mesh - if (mpi::master && sites_outside) { - fatal_error("Source sites outside of the UFS mesh!"); - } - -#ifdef OPENMC_MPI - // Send source fraction to all processors - int n_bins = xt::prod(simulation::ufs_mesh->shape_)(); - MPI_Bcast(simulation::source_frac.data(), n_bins, MPI_DOUBLE, 0, mpi::intracomm); -#endif - - // Normalize to total weight to get fraction of source in each cell - double total = xt::sum(simulation::source_frac)(); - simulation::source_frac /= total; - - // Since the total starting weight is not equal to n_particles, we need to - // renormalize the weight of the source sites - for (int i = 0; i < simulation::work_per_rank; ++i) { - simulation::source_bank[i].wgt *= settings::n_particles / total; - } - } -} - -double ufs_get_weight(const Particle* p) -{ - // Determine indices on ufs mesh for current location - int mesh_bin = simulation::ufs_mesh->get_bin(p->r()); - if (mesh_bin < 0) { - p->write_restart(); - fatal_error("Source site outside UFS mesh!"); - } - - if (simulation::source_frac(mesh_bin) != 0.0) { - return simulation::ufs_mesh->volume_frac_ - / simulation::source_frac(mesh_bin); - } else { - return 1.0; - } -} - -void write_eigenvalue_hdf5(hid_t group) -{ - write_dataset(group, "n_inactive", settings::n_inactive); - write_dataset(group, "generations_per_batch", settings::gen_per_batch); - write_dataset(group, "k_generation", simulation::k_generation); - if (settings::entropy_on) { - write_dataset(group, "entropy", simulation::entropy); - } - write_dataset(group, "k_col_abs", simulation::k_col_abs); - write_dataset(group, "k_col_tra", simulation::k_col_tra); - write_dataset(group, "k_abs_tra", simulation::k_abs_tra); - std::array k_combined; - openmc_get_keff(k_combined.data()); - write_dataset(group, "k_combined", k_combined); -} - -void read_eigenvalue_hdf5(hid_t group) -{ - read_dataset(group, "generations_per_batch", settings::gen_per_batch); - int n = simulation::restart_batch*settings::gen_per_batch; - simulation::k_generation.resize(n); - read_dataset(group, "k_generation", simulation::k_generation); - if (settings::entropy_on) { - read_dataset(group, "entropy", simulation::entropy); - } - read_dataset(group, "k_col_abs", simulation::k_col_abs); - read_dataset(group, "k_col_tra", simulation::k_col_tra); - read_dataset(group, "k_abs_tra", simulation::k_abs_tra); -} - -} // namespace openmc diff --git a/src/endf.cpp b/src/endf.cpp deleted file mode 100644 index f01a64311..000000000 --- a/src/endf.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include "openmc/endf.h" - -#include // for copy -#include -#include // for log, exp -#include // for back_inserter -#include // for runtime_error - -#include "xtensor/xarray.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/search.h" - -namespace openmc { - -//============================================================================== -// Functions -//============================================================================== - -Interpolation int2interp(int i) -{ - // TODO: We are ignoring specification of two-dimensional interpolation - // schemes (method of corresponding points and unit base interpolation). Those - // should be accounted for in the distribution classes somehow. - - switch (i) { - case 1: case 11: case 21: - return Interpolation::histogram; - case 2: case 12: case 22: - return Interpolation::lin_lin; - case 3: case 13: case 23: - return Interpolation::lin_log; - case 4: case 14: case 24: - return Interpolation::log_lin; - case 5: case 15: case 25: - return Interpolation::log_log; - default: - throw std::runtime_error{"Invalid interpolation code."}; - } -} - -bool is_fission(int mt) -{ - return mt == 18 || mt == 19 || mt == 20 || mt == 21 || mt == 38; -} - -bool is_disappearance(int mt) -{ - if (mt >= N_DISAPPEAR && mt <= N_DA) { - return true; - } else if (mt >= N_P0 && mt <= N_AC) { - return true; - } else if (mt == N_TA || mt == N_DT || mt == N_P3HE || mt == N_D3HE - || mt == N_3HEA || mt == N_3P) { - return true; - } else { - return false; - } -} - -bool is_inelastic_scatter(int mt) -{ - if (mt < 100) { - if (is_fission(mt)) { - return false; - } else { - return mt >= MISC && mt != 27; - } - } else if (mt <= 200) { - return !is_disappearance(mt); - } else if (mt >= N_2N0 && mt <= N_2NC) { - return true; - } else { - return false; - } -} - -std::unique_ptr -read_function(hid_t group, const char* name) -{ - hid_t dset = open_dataset(group, name); - std::string func_type; - read_attribute(dset, "type", func_type); - std::unique_ptr func; - if (func_type == "Tabulated1D") { - func = std::make_unique(dset); - } else if (func_type == "Polynomial") { - func = std::make_unique(dset); - } else if (func_type == "CoherentElastic") { - func = std::make_unique(dset); - } else if (func_type == "IncoherentElastic") { - func = std::make_unique(dset); - } else { - throw std::runtime_error{"Unknown function type " + func_type + - " for dataset " + object_name(dset)}; - } - close_dataset(dset); - return func; -} - -//============================================================================== -// Polynomial implementation -//============================================================================== - -Polynomial::Polynomial(hid_t dset) -{ - // Read coefficients into a vector - read_dataset(dset, coef_); -} - -double Polynomial::operator()(double x) const -{ - // Use Horner's rule to evaluate polynomial. Note that coefficients are - // ordered in increasing powers of x. - double y = 0.0; - for (auto c = coef_.crbegin(); c != coef_.crend(); ++c) { - y = y*x + *c; - } - return y; -} - -//============================================================================== -// Tabulated1D implementation -//============================================================================== - -Tabulated1D::Tabulated1D(hid_t dset) -{ - read_attribute(dset, "breakpoints", nbt_); - n_regions_ = nbt_.size(); - - // Change 1-indexing to 0-indexing - for (auto& b : nbt_) --b; - - std::vector int_temp; - read_attribute(dset, "interpolation", int_temp); - - // Convert vector of ints into Interpolation - for (const auto i : int_temp) - int_.push_back(int2interp(i)); - - xt::xarray arr; - read_dataset(dset, arr); - - auto xs = xt::view(arr, 0); - auto ys = xt::view(arr, 1); - - std::copy(xs.begin(), xs.end(), std::back_inserter(x_)); - std::copy(ys.begin(), ys.end(), std::back_inserter(y_)); - n_pairs_ = x_.size(); -} - -double Tabulated1D::operator()(double x) const -{ - // find which bin the abscissa is in -- if the abscissa is outside the - // tabulated range, the first or last point is chosen, i.e. no interpolation - // is done outside the energy range - int i; - if (x < x_[0]) { - return y_[0]; - } else if (x > x_[n_pairs_ - 1]) { - return y_[n_pairs_ - 1]; - } else { - i = lower_bound_index(x_.begin(), x_.end(), x); - } - - // determine interpolation scheme - Interpolation interp; - if (n_regions_ == 0) { - interp = Interpolation::lin_lin; - } else { - interp = int_[0]; - for (int j = 0; j < n_regions_; ++j) { - if (i < nbt_[j]) { - interp = int_[j]; - break; - } - } - } - - // handle special case of histogram interpolation - if (interp == Interpolation::histogram) return y_[i]; - - // determine bounding values - double x0 = x_[i]; - double x1 = x_[i + 1]; - double y0 = y_[i]; - double y1 = y_[i + 1]; - - // determine interpolation factor and interpolated value - double r; - switch (interp) { - case Interpolation::lin_lin: - r = (x - x0)/(x1 - x0); - return y0 + r*(y1 - y0); - case Interpolation::lin_log: - r = log(x/x0)/log(x1/x0); - return y0 + r*(y1 - y0); - case Interpolation::log_lin: - r = (x - x0)/(x1 - x0); - return y0*exp(r*log(y1/y0)); - case Interpolation::log_log: - r = log(x/x0)/log(x1/x0); - return y0*exp(r*log(y1/y0)); - default: - throw std::runtime_error{"Invalid interpolation scheme."}; - } -} - -//============================================================================== -// CoherentElasticXS implementation -//============================================================================== - -CoherentElasticXS::CoherentElasticXS(hid_t dset) -{ - // Read 2D array from dataset - xt::xarray arr; - read_dataset(dset, arr); - - // Get views for Bragg edges and structure factors - auto E = xt::view(arr, 0); - auto s = xt::view(arr, 1); - - // Copy Bragg edges and partial sums of structure factors - std::copy(E.begin(), E.end(), std::back_inserter(bragg_edges_)); - std::copy(s.begin(), s.end(), std::back_inserter(factors_)); -} - -double CoherentElasticXS::operator()(double E) const -{ - if (E < bragg_edges_[0]) { - // If energy is below that of the lowest Bragg peak, the elastic cross - // section will be zero - return 0.0; - } else { - auto i_grid = lower_bound_index(bragg_edges_.begin(), bragg_edges_.end(), E); - return factors_[i_grid] / E; - } -} - -//============================================================================== -// IncoherentElasticXS implementation -//============================================================================== - -IncoherentElasticXS::IncoherentElasticXS(hid_t dset) -{ - std::array tmp; - read_dataset(dset, nullptr, tmp); - bound_xs_ = tmp[0]; - debye_waller_ = tmp[1]; -} - -double IncoherentElasticXS::operator()(double E) const -{ - // Determine cross section using ENDF-102, Eq. (7.5) - double W = debye_waller_; - return bound_xs_ / 2.0 * ((1 - std::exp(-4.0*E*W))/(2.0*E*W)); -} - -} // namespace openmc diff --git a/src/error.cpp b/src/error.cpp deleted file mode 100644 index 83e7e8781..000000000 --- a/src/error.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "openmc/error.h" - -#include "openmc/message_passing.h" -#include "openmc/settings.h" - -#if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) -#include // for isatty -#endif - -#include // for exit -#include // for setw -#include - -//============================================================================== -// Global variables / constants -//============================================================================== - -// Error codes -int OPENMC_E_UNASSIGNED {-1}; -int OPENMC_E_ALLOCATE {-2}; -int OPENMC_E_OUT_OF_BOUNDS {-3}; -int OPENMC_E_INVALID_SIZE {-4}; -int OPENMC_E_INVALID_ARGUMENT {-5}; -int OPENMC_E_INVALID_TYPE {-6}; -int OPENMC_E_INVALID_ID {-7}; -int OPENMC_E_GEOMETRY {-8}; -int OPENMC_E_DATA {-9}; -int OPENMC_E_PHYSICS {-10}; -int OPENMC_E_WARNING {1}; - -// Error message -char openmc_err_msg[256]; - -//============================================================================== -// Functions -//============================================================================== - -namespace openmc { - -#ifdef OPENMC_MPI -void abort_mpi(int code) -{ - MPI_Abort(mpi::intracomm, code); -} -#endif - -void output(const std::string& message, std::ostream& out, int indent) -{ - // Set line wrapping and indentation - int line_wrap = 80; - - // Determine length of message - int length = message.size(); - - int i_start = 0; - int line_len = line_wrap - indent + 1; - while (i_start < length) { - if (length - i_start < line_len) { - // Remainder of message will fit on line - out << message.substr(i_start) << '\n'; - break; - - } else { - // Determine last space in current line - std::string s = message.substr(i_start, line_len); - auto pos = s.find_last_of(' '); - - // Write up to last space, or whole line if no space is present - out << s.substr(0, pos) << '\n' << std::setw(indent) << " "; - - // Advance starting position - i_start += (pos == std::string::npos) ? line_len : pos + 1; - } - } -} - -void warning(const std::string& message) -{ -#ifdef _POSIX_VERSION - // Make output yellow if user is in a terminal - if (isatty(STDERR_FILENO)) { - std::cerr << "\033[0;33m"; - } -#endif - - // Write warning - std::cerr << " WARNING: "; - output(message, std::cerr, 10); - -#ifdef _POSIX_VERSION - // Reset color for terminal - if (isatty(STDERR_FILENO)) { - std::cerr << "\033[0m"; - } -#endif -} - -void write_message(const std::string& message, int level) -{ - // Only allow master to print to screen - if (!mpi::master) return; - - if (level <= settings::verbosity) { - std::cout << " "; - output(message, std::cout, 1); - } -} - -void fatal_error(const std::string& message, int err) -{ -#ifdef _POSIX_VERSION - // Make output red if user is in a terminal - if (isatty(STDERR_FILENO)) { - std::cerr << "\033[0;31m"; - } -#endif - - // Write error message - std::cerr << " ERROR: "; - output(message, std::cerr, 8); - -#ifdef _POSIX_VERSION - // Reset color for terminal - if (isatty(STDERR_FILENO)) { - std::cerr << "\033[0m"; - } -#endif - -#ifdef OPENMC_MPI - MPI_Abort(mpi::intracomm, err); -#endif - - // Abort the program - std::exit(err); -} - -} // namespace openmc diff --git a/src/finalize.cpp b/src/finalize.cpp deleted file mode 100644 index 3de20d6d0..000000000 --- a/src/finalize.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "openmc/finalize.h" - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/cmfd_solver.h" -#include "openmc/constants.h" -#include "openmc/cross_sections.h" -#include "openmc/dagmc.h" -#include "openmc/eigenvalue.h" -#include "openmc/geometry.h" -#include "openmc/geometry_aux.h" -#include "openmc/material.h" -#include "openmc/mesh.h" -#include "openmc/message_passing.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/source.h" -#include "openmc/surface.h" -#include "openmc/thermal.h" -#include "openmc/timer.h" -#include "openmc/tallies/tally.h" -#include "openmc/volume_calc.h" - -#include "xtensor/xview.hpp" - -namespace openmc { - -void free_memory() -{ - free_memory_geometry(); - free_memory_surfaces(); - free_memory_material(); - free_memory_volume(); - free_memory_simulation(); - free_memory_photon(); - free_memory_settings(); - free_memory_thermal(); - library_clear(); - nuclides_clear(); - free_memory_source(); - free_memory_mesh(); - free_memory_tally(); - free_memory_bank(); - free_memory_cmfd(); -#ifdef DAGMC - free_memory_dagmc(); -#endif -} - -} - -using namespace openmc; - -int openmc_finalize() -{ - // Clear results - openmc_reset(); - - // Reset timers - reset_timers(); - - // Reset global variables - settings::assume_separate = false; - settings::check_overlaps = false; - settings::confidence_intervals = false; - settings::create_fission_neutrons = true; - settings::electron_treatment = ELECTRON_LED; - settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0}; - settings::entropy_on = false; - settings::gen_per_batch = 1; - settings::legendre_to_tabular = true; - settings::legendre_to_tabular_points = -1; - settings::n_particles = -1; - settings::output_summary = true; - settings::output_tallies = true; - settings::particle_restart_run = false; - settings::photon_transport = false; - settings::reduce_tallies = true; - settings::res_scat_on = false; - settings::res_scat_method = ResScatMethod::rvs; - settings::res_scat_energy_min = 0.01; - settings::res_scat_energy_max = 1000.0; - settings::restart_run = false; - settings::run_CE = true; - settings::run_mode = -1; - settings::dagmc = false; - settings::source_latest = false; - settings::source_separate = false; - settings::source_write = true; - settings::survival_biasing = false; - settings::temperature_default = 293.6; - settings::temperature_method = TEMPERATURE_NEAREST; - settings::temperature_multipole = false; - settings::temperature_range = {0.0, 0.0}; - settings::temperature_tolerance = 10.0; - settings::trigger_on = false; - settings::trigger_predict = false; - settings::trigger_batch_interval = 1; - settings::ufs_on = false; - settings::urr_ptables_on = true; - settings::verbosity = 7; - settings::weight_cutoff = 0.25; - settings::weight_survive = 1.0; - settings::write_all_tracks = false; - settings::write_initial_source = false; - - simulation::keff = 1.0; - simulation::n_lost_particles = 0; - simulation::satisfy_triggers = false; - simulation::total_gen = 0; - - simulation::entropy_mesh = nullptr; - simulation::ufs_mesh = nullptr; - - data::energy_max = {INFTY, INFTY}; - data::energy_min = {0.0, 0.0}; - data::temperature_min = 0.0; - data::temperature_max = INFTY; - model::root_universe = -1; - openmc::openmc_set_seed(DEFAULT_SEED); - - // Deallocate arrays - free_memory(); - - // Free all MPI types -#ifdef OPENMC_MPI - if (mpi::bank != MPI_DATATYPE_NULL) MPI_Type_free(&mpi::bank); -#endif - - return 0; -} - -int openmc_reset() -{ - for (auto& t : model::tallies) { - t->reset(); - } - - // Reset global tallies - simulation::n_realizations = 0; - xt::view(simulation::global_tallies, xt::all()) = 0.0; - - simulation::k_col_abs = 0.0; - simulation::k_col_tra = 0.0; - simulation::k_abs_tra = 0.0; - simulation::k_sum = {0.0, 0.0}; - - return 0; -} - -int openmc_hard_reset() -{ - // Reset all tallies and timers - openmc_reset(); - reset_timers(); - - // Reset total generations and keff guess - simulation::keff = 1.0; - simulation::total_gen = 0; - - // Reset the random number generator state - openmc::openmc_set_seed(DEFAULT_SEED); - return 0; -} diff --git a/src/geometry.cpp b/src/geometry.cpp deleted file mode 100644 index 556d10650..000000000 --- a/src/geometry.cpp +++ /dev/null @@ -1,496 +0,0 @@ -#include "openmc/geometry.h" - -#include -#include - -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/lattice.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/surface.h" - - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - - -namespace model { - -int root_universe {-1}; -int n_coord_levels; - -std::vector overlap_check_count; - -} // namespace model - -//============================================================================== -// Non-member functions -//============================================================================== - -bool check_cell_overlap(Particle* p, bool error) -{ - int n_coord = p->n_coord_; - - // Loop through each coordinate level - for (int j = 0; j < n_coord; j++) { - Universe& univ = *model::universes[p->coord_[j].universe]; - - // Loop through each cell on this level - for (auto index_cell : univ.cells_) { - Cell& c = *model::cells[index_cell]; - if (c.contains(p->coord_[j].r, p->coord_[j].u, p->surface_)) { - if (index_cell != p->coord_[j].cell) { - if (error) { - std::stringstream err_msg; - err_msg << "Overlapping cells detected: " << c.id_ << ", " - << model::cells[p->coord_[j].cell]->id_ << " on universe " - << univ.id_; - fatal_error(err_msg); - } - return true; - } - ++model::overlap_check_count[index_cell]; - } - } - } - - return false; -} - -//============================================================================== - -bool -find_cell_inner(Particle* p, const NeighborList* neighbor_list) -{ - // Find which cell of this universe the particle is in. Use the neighbor list - // to shorten the search if one was provided. - bool found = false; - int32_t i_cell; - if (neighbor_list) { - for (auto it = neighbor_list->cbegin(); it != neighbor_list->cend(); ++it) { - i_cell = *it; - - // Make sure the search cell is in the same universe. - int i_universe = p->coord_[p->n_coord_-1].universe; - if (model::cells[i_cell]->universe_ != i_universe) continue; - - // Check if this cell contains the particle. - Position r {p->r_local()}; - Direction u {p->u_local()}; - auto surf = p->surface_; - if (model::cells[i_cell]->contains(r, u, surf)) { - p->coord_[p->n_coord_-1].cell = i_cell; - found = true; - break; - } - } - - } else { - int i_universe = p->coord_[p->n_coord_-1].universe; - const auto& univ {*model::universes[i_universe]}; - const auto& cells { - !univ.partitioner_ - ? model::universes[i_universe]->cells_ - : univ.partitioner_->get_cells(p->r_local(), p->u_local()) - }; - for (auto it = cells.cbegin(); it != cells.cend(); it++) { - i_cell = *it; - - // Make sure the search cell is in the same universe. - int i_universe = p->coord_[p->n_coord_-1].universe; - if (model::cells[i_cell]->universe_ != i_universe) continue; - - // Check if this cell contains the particle. - Position r {p->r_local()}; - Direction u {p->u_local()}; - auto surf = p->surface_; - if (model::cells[i_cell]->contains(r, u, surf)) { - p->coord_[p->n_coord_-1].cell = i_cell; - found = true; - break; - } - } - } - - // Announce the cell that the particle is entering. - if (found && (settings::verbosity >= 10 || simulation::trace)) { - std::stringstream msg; - msg << " Entering cell " << model::cells[i_cell]->id_; - write_message(msg, 1); - } - - if (found) { - Cell& c {*model::cells[i_cell]}; - if (c.type_ == FILL_MATERIAL) { - //======================================================================= - //! Found a material cell which means this is the lowest coord level. - - // Find the distribcell instance number. - if (c.material_.size() > 1 || c.sqrtkT_.size() > 1) { - int offset = 0; - for (int i = 0; i < p->n_coord_; i++) { - const auto& c_i {*model::cells[p->coord_[i].cell]}; - if (c_i.type_ == FILL_UNIVERSE) { - offset += c_i.offset_[c.distribcell_index_]; - } else if (c_i.type_ == FILL_LATTICE) { - auto& lat {*model::lattices[p->coord_[i+1].lattice]}; - int i_xyz[3] {p->coord_[i+1].lattice_x, - p->coord_[i+1].lattice_y, - p->coord_[i+1].lattice_z}; - if (lat.are_valid_indices(i_xyz)) { - offset += lat.offset(c.distribcell_index_, i_xyz); - } - } - } - p->cell_instance_ = offset; - } else { - p->cell_instance_ = 0; - } - - // Set the material and temperature. - p->material_last_ = p->material_; - if (c.material_.size() > 1) { - p->material_ = c.material_[p->cell_instance_]; - } else { - p->material_ = c.material_[0]; - } - p->sqrtkT_last_ = p->sqrtkT_; - if (c.sqrtkT_.size() > 1) { - p->sqrtkT_ = c.sqrtkT_[p->cell_instance_]; - } else { - p->sqrtkT_ = c.sqrtkT_[0]; - } - - return true; - - } else if (c.type_ == FILL_UNIVERSE) { - //======================================================================== - //! Found a lower universe, update this coord level then search the next. - - // Set the lower coordinate level universe. - auto& coord {p->coord_[p->n_coord_]}; - coord.universe = c.fill_; - - // Set the position and direction. - coord.r = p->r_local(); - coord.u = p->u_local(); - - // Apply translation. - coord.r -= c.translation_; - - // Apply rotation. - if (!c.rotation_.empty()) { - coord.rotate(c.rotation_); - } - - // Update the coordinate level and recurse. - ++p->n_coord_; - return find_cell_inner(p, nullptr); - - } else if (c.type_ == FILL_LATTICE) { - //======================================================================== - //! Found a lower lattice, update this coord level then search the next. - - Lattice& lat {*model::lattices[c.fill_]}; - - // Set the position and direction. - auto& coord {p->coord_[p->n_coord_]}; - coord.r = p->r_local(); - coord.u = p->u_local(); - - // Apply translation. - coord.r -= c.translation_; - - // Apply rotation. - if (!c.rotation_.empty()) { - coord.rotate(c.rotation_); - } - - // Determine lattice indices. - auto i_xyz = lat.get_indices(coord.r, coord.u); - - // Get local position in appropriate lattice cell - coord.r = lat.get_local_position(coord.r, i_xyz); - - // Set lattice indices. - coord.lattice = c.fill_; - coord.lattice_x = i_xyz[0]; - coord.lattice_y = i_xyz[1]; - coord.lattice_z = i_xyz[2]; - - // Set the lower coordinate level universe. - if (lat.are_valid_indices(i_xyz)) { - coord.universe = lat[i_xyz]; - } else { - if (lat.outer_ != NO_OUTER_UNIVERSE) { - coord.universe = lat.outer_; - } else { - std::stringstream err_msg; - err_msg << "Particle " << p->id_ << " is outside lattice " - << lat.id_ << " but the lattice has no defined outer " - "universe."; - warning(err_msg); - return false; - } - } - - // Update the coordinate level and recurse. - ++p->n_coord_; - return find_cell_inner(p, nullptr); - } - } - - return found; -} - -//============================================================================== - -bool -find_cell(Particle* p, bool use_neighbor_lists) -{ - // Determine universe (if not yet set, use root universe). - int i_universe = p->coord_[p->n_coord_-1].universe; - if (i_universe == C_NONE) { - p->coord_[0].universe = model::root_universe; - p->n_coord_ = 1; - i_universe = model::root_universe; - } - - // Reset all the deeper coordinate levels. - for (int i = p->n_coord_; i < p->coord_.size(); i++) { - p->coord_[i].reset(); - } - - if (use_neighbor_lists) { - // Get the cell this particle was in previously. - auto coord_lvl = p->n_coord_ - 1; - auto i_cell = p->coord_[coord_lvl].cell; - Cell& c {*model::cells[i_cell]}; - - // Search for the particle in that cell's neighbor list. Return if we - // found the particle. - bool found = find_cell_inner(p, &c.neighbors_); - if (found) return found; - - // The particle could not be found in the neighbor list. Try searching all - // cells in this universe, and update the neighbor list if we find a new - // neighboring cell. - found = find_cell_inner(p, nullptr); - if (found) c.neighbors_.push_back(p->coord_[coord_lvl].cell); - return found; - - } else { - // Search all cells in this universe for the particle. - return find_cell_inner(p, nullptr); - } -} - -//============================================================================== - -void -cross_lattice(Particle* p, const BoundaryInfo& boundary) -{ - auto& coord {p->coord_[p->n_coord_ - 1]}; - auto& lat {*model::lattices[coord.lattice]}; - - if (settings::verbosity >= 10 || simulation::trace) { - std::stringstream msg; - msg << " Crossing lattice " << lat.id_ << ". Current position (" - << coord.lattice_x << "," << coord.lattice_y << "," - << coord.lattice_z << "). r=" << p->r(); - write_message(msg, 1); - } - - // Set the lattice indices. - coord.lattice_x += boundary.lattice_translation[0]; - coord.lattice_y += boundary.lattice_translation[1]; - coord.lattice_z += boundary.lattice_translation[2]; - std::array i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z}; - - // Set the new coordinate position. - const auto& upper_coord {p->coord_[p->n_coord_ - 2]}; - const auto& cell {model::cells[upper_coord.cell]}; - Position r = upper_coord.r; - r -= cell->translation_; - if (!cell->rotation_.empty()) { - r = r.rotate(cell->rotation_); - } - p->r_local() = lat.get_local_position(r, i_xyz); - - if (!lat.are_valid_indices(i_xyz)) { - // The particle is outside the lattice. Search for it from the base coords. - p->n_coord_ = 1; - bool found = find_cell(p, 0); - if (!found && p->alive_) { - std::stringstream err_msg; - err_msg << "Could not locate particle " << p->id_ - << " after crossing a lattice boundary"; - p->mark_as_lost(err_msg); - } - - } else { - // Find cell in next lattice element. - p->coord_[p->n_coord_-1].universe = lat[i_xyz]; - bool found = find_cell(p, 0); - - if (!found) { - // A particle crossing the corner of a lattice tile may not be found. In - // this case, search for it from the base coords. - p->n_coord_ = 1; - bool found = find_cell(p, 0); - if (!found && p->alive_) { - std::stringstream err_msg; - err_msg << "Could not locate particle " << p->id_ - << " after crossing a lattice boundary"; - p->mark_as_lost(err_msg); - } - } - } -} - -//============================================================================== - -BoundaryInfo distance_to_boundary(Particle* p) -{ - BoundaryInfo info; - double d_lat = INFINITY; - double d_surf = INFINITY; - int32_t level_surf_cross; - std::array level_lat_trans {}; - - // Loop over each coordinate level. - for (int i = 0; i < p->n_coord_; i++) { - const auto& coord {p->coord_[i]}; - Position r {coord.r}; - Direction u {coord.u}; - Cell& c {*model::cells[coord.cell]}; - - // Find the oncoming surface in this cell and the distance to it. - auto surface_distance = c.distance(r, u, p->surface_); - d_surf = surface_distance.first; - level_surf_cross = surface_distance.second; - - // Find the distance to the next lattice tile crossing. - if (coord.lattice != C_NONE) { - auto& lat {*model::lattices[coord.lattice]}; - std::array i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z}; - //TODO: refactor so both lattice use the same position argument (which - //also means the lat.type attribute can be removed) - std::pair> lattice_distance; - switch (lat.type_) { - case LatticeType::rect: - lattice_distance = lat.distance(r, u, i_xyz); - break; - case LatticeType::hex: - auto& cell_above {model::cells[p->coord_[i-1].cell]}; - Position r_hex {p->coord_[i-1].r}; - r_hex -= cell_above->translation_; - if (coord.rotated) { - r_hex = r_hex.rotate(cell_above->rotation_); - } - r_hex.z = coord.r.z; - lattice_distance = lat.distance(r_hex, u, i_xyz); - break; - } - d_lat = lattice_distance.first; - level_lat_trans = lattice_distance.second; - - if (d_lat < 0) { - std::stringstream err_msg; - err_msg << "Particle " << p->id_ - << " had a negative distance to a lattice boundary"; - p->mark_as_lost(err_msg); - } - } - - // If the boundary on this coordinate level is coincident with a boundary on - // a higher level then we need to make sure that the higher level boundary - // is selected. This logic must consider floating point precision. - double& d = info.distance; - if (d_surf < d_lat - FP_COINCIDENT) { - if (d == INFINITY || (d - d_surf)/d >= FP_REL_PRECISION) { - d = d_surf; - - // If the cell is not simple, it is possible that both the negative and - // positive half-space were given in the region specification. Thus, we - // have to explicitly check which half-space the particle would be - // traveling into if the surface is crossed - if (c.simple_) { - info.surface_index = level_surf_cross; - } else { - Position r_hit = r + d_surf * u; - Surface& surf {*model::surfaces[std::abs(level_surf_cross)-1]}; - Direction norm = surf.normal(r_hit); - if (u.dot(norm) > 0) { - info.surface_index = std::abs(level_surf_cross); - } else { - info.surface_index = -std::abs(level_surf_cross); - } - } - - info.lattice_translation[0] = 0; - info.lattice_translation[1] = 0; - info.lattice_translation[2] = 0; - info.coord_level = i + 1; - } - } else { - if (d == INFINITY || (d - d_lat)/d >= FP_REL_PRECISION) { - d = d_lat; - info.surface_index = 0; - info.lattice_translation = level_lat_trans; - info.coord_level = i + 1; - } - } - } - return info; -} - -//============================================================================== -// C API -//============================================================================== - -extern "C" int -openmc_find_cell(const double* xyz, int32_t* index, int32_t* instance) -{ - Particle p; - - p.r() = Position{xyz}; - p.u() = {0.0, 0.0, 1.0}; - - if (!find_cell(&p, false)) { - std::stringstream msg; - msg << "Could not find cell at position (" << p.r().x << ", " << p.r().y - << ", " << p.r().z << ")."; - set_errmsg(msg); - return OPENMC_E_GEOMETRY; - } - - *index = p.coord_[p.n_coord_-1].cell; - *instance = p.cell_instance_; - return 0; -} - -extern "C" int openmc_global_bounding_box(double* llc, double* urc) { - auto bbox = model::universes.at(model::root_universe)->bounding_box(); - - // set lower left corner values - llc[0] = bbox.xmin; - llc[1] = bbox.ymin; - llc[2] = bbox.zmin; - - // set upper right corner values - urc[0] = bbox.xmax; - urc[1] = bbox.ymax; - urc[2] = bbox.zmax; - - return 0; -} - - -} // namespace openmc diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp deleted file mode 100644 index d195a9de3..000000000 --- a/src/geometry_aux.cpp +++ /dev/null @@ -1,569 +0,0 @@ -#include "openmc/geometry_aux.h" - -#include // for std::max -#include -#include - -#include "pugixml.hpp" - -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/container_util.h" -#include "openmc/dagmc.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/geometry.h" -#include "openmc/lattice.h" -#include "openmc/material.h" -#include "openmc/settings.h" -#include "openmc/surface.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/filter_distribcell.h" - - -namespace openmc { - -void read_geometry_xml() -{ -#ifdef DAGMC - if (settings::dagmc) { - read_geometry_dagmc(); - return; - } -#endif - - // Display output message - write_message("Reading geometry XML file...", 5); - - // Check if geometry.xml exists - std::string filename = settings::path_input + "geometry.xml"; - if (!file_exists(filename)) { - fatal_error("Geometry XML file '" + filename + "' does not exist!"); - } - - // Parse settings.xml file - pugi::xml_document doc; - auto result = doc.load_file(filename.c_str()); - if (!result) { - fatal_error("Error processing geometry.xml file."); - } - - // Get root element - pugi::xml_node root = doc.document_element(); - - // Read surfaces, cells, lattice - read_surfaces(root); - read_cells(root); - read_lattices(root); - - // Allocate universes, universe cell arrays, and assign base universe - model::root_universe = find_root_universe(); -} - -//============================================================================== - -void -adjust_indices() -{ - // Adjust material/fill idices. - for (auto& c : model::cells) { - if (c->fill_ != C_NONE) { - int32_t id = c->fill_; - auto search_univ = model::universe_map.find(id); - auto search_lat = model::lattice_map.find(id); - if (search_univ != model::universe_map.end()) { - c->type_ = FILL_UNIVERSE; - c->fill_ = search_univ->second; - } else if (search_lat != model::lattice_map.end()) { - c->type_ = FILL_LATTICE; - c->fill_ = search_lat->second; - } else { - std::stringstream err_msg; - err_msg << "Specified fill " << id << " on cell " << c->id_ - << " is neither a universe nor a lattice."; - fatal_error(err_msg); - } - } else { - c->type_ = FILL_MATERIAL; - for (auto& mat_id : c->material_) { - if (mat_id != MATERIAL_VOID) { - auto search = model::material_map.find(mat_id); - if (search == model::material_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find material " << mat_id - << " specified on cell " << c->id_; - fatal_error(err_msg); - } - // Change from ID to index - mat_id = search->second; - } - } - } - } - - // Change cell.universe values from IDs to indices. - for (auto& c : model::cells) { - auto search = model::universe_map.find(c->universe_); - if (search != model::universe_map.end()) { - c->universe_ = search->second; - } else { - std::stringstream err_msg; - err_msg << "Could not find universe " << c->universe_ - << " specified on cell " << c->id_; - fatal_error(err_msg); - } - } - - // Change all lattice universe values from IDs to indices. - for (auto& l : model::lattices) { - l->adjust_indices(); - } -} - -//============================================================================== -//! Partition some universes with many z-planes for faster find_cell searches. - -void -partition_universes() -{ - // Iterate over universes with more than 10 cells. (Fewer than 10 is likely - // not worth partitioning.) - for (const auto& univ : model::universes) { - if (univ->cells_.size() > 10) { - // Collect the set of surfaces in this universe. - std::unordered_set surf_inds; - for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->rpn_) { - if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); - } - } - - // Partition the universe if there are more than 5 z-planes. (Fewer than - // 5 is likely not worth it.) - int n_zplanes = 0; - for (auto i_surf : surf_inds) { - if (dynamic_cast(model::surfaces[i_surf].get())) { - ++n_zplanes; - if (n_zplanes > 5) { - univ->partitioner_ = std::make_unique(*univ); - break; - } - } - } - } - } -} - -//============================================================================== - -void -assign_temperatures() -{ - for (auto& c : model::cells) { - // Ignore non-material cells and cells with defined temperature. - if (c->material_.size() == 0) continue; - if (c->sqrtkT_.size() > 0) continue; - - c->sqrtkT_.reserve(c->material_.size()); - for (auto i_mat : c->material_) { - if (i_mat == MATERIAL_VOID) { - // Set void region to 0K. - c->sqrtkT_.push_back(0); - - } else { - if (model::materials[i_mat]->temperature_ >= 0) { - // This material has a default temperature; use that value. - auto T = model::materials[i_mat]->temperature_; - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * T)); - } else { - // Use the global default temperature. - c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * - settings::temperature_default)); - } - } - } - } -} - -//============================================================================== - -void -get_temperatures(std::vector>& nuc_temps, - std::vector>& thermal_temps) -{ - for (const auto& cell : model::cells) { - // Skip non-material cells. - if (cell->fill_ != C_NONE) continue; - - for (int j = 0; j < cell->material_.size(); ++j) { - // Skip void materials - int i_material = cell->material_[j]; - if (i_material == MATERIAL_VOID) continue; - - // Get temperature(s) of cell (rounding to nearest integer) - std::vector cell_temps; - if (cell->sqrtkT_.size() == 1) { - double sqrtkT = cell->sqrtkT_[0]; - cell_temps.push_back(sqrtkT*sqrtkT / K_BOLTZMANN); - } else if (cell->sqrtkT_.size() == cell->material_.size()) { - double sqrtkT = cell->sqrtkT_[j]; - cell_temps.push_back(sqrtkT*sqrtkT / K_BOLTZMANN); - } else { - for (double sqrtkT : cell->sqrtkT_) - cell_temps.push_back(sqrtkT*sqrtkT / K_BOLTZMANN); - } - - const auto& mat {model::materials[i_material]}; - for (const auto& i_nuc : mat->nuclide_) { - for (double temperature : cell_temps) { - // Add temperature if it hasn't already been added - if (!contains(nuc_temps[i_nuc], temperature)) - nuc_temps[i_nuc].push_back(temperature); - } - } - - for (const auto& table : mat->thermal_tables_) { - // Get index in data::thermal_scatt array - int i_sab = table.index_table; - - for (double temperature : cell_temps) { - // Add temperature if it hasn't already been added - if (!contains(thermal_temps[i_sab], temperature)) - thermal_temps[i_sab].push_back(temperature); - } - } - } - } -} - -//============================================================================== - -void finalize_geometry(std::vector>& nuc_temps, - std::vector>& thermal_temps) -{ - // Perform some final operations to set up the geometry - adjust_indices(); - count_cell_instances(model::root_universe); - partition_universes(); - - // Assign temperatures to cells that don't have temperatures already assigned - assign_temperatures(); - - // Determine desired temperatures for each nuclide and S(a,b) table - get_temperatures(nuc_temps, thermal_temps); - - // Determine number of nested coordinate levels in the geometry - model::n_coord_levels = maximum_levels(model::root_universe); -} - -//============================================================================== - -int32_t -find_root_universe() -{ - // Find all the universes listed as a cell fill. - std::unordered_set fill_univ_ids; - for (const auto& c : model::cells) { - fill_univ_ids.insert(c->fill_); - } - - // Find all the universes contained in a lattice. - for (const auto& lat : model::lattices) { - for (auto it = lat->begin(); it != lat->end(); ++it) { - fill_univ_ids.insert(*it); - } - if (lat->outer_ != NO_OUTER_UNIVERSE) { - fill_univ_ids.insert(lat->outer_); - } - } - - // Figure out which universe is not in the set. This is the root universe. - bool root_found {false}; - int32_t root_univ; - for (int32_t i = 0; i < model::universes.size(); i++) { - auto search = fill_univ_ids.find(model::universes[i]->id_); - if (search == fill_univ_ids.end()) { - if (root_found) { - fatal_error("Two or more universes are not used as fill universes, so " - "it is not possible to distinguish which one is the root " - "universe."); - } else { - root_found = true; - root_univ = i; - } - } - } - if (!root_found) fatal_error("Could not find a root universe. Make sure " - "there are no circular dependencies in the geometry."); - - return root_univ; -} - -//============================================================================== - -void -prepare_distribcell() -{ - // Find all cells listed in a DistribcellFilter. - std::unordered_set distribcells; - for (auto& filt : model::tally_filters) { - auto* distrib_filt = dynamic_cast(filt.get()); - if (distrib_filt) { - distribcells.insert(distrib_filt->cell()); - } - } - - // Find all cells with distributed materials or temperatures. Make sure that - // the number of materials/temperatures matches the number of cell instances. - for (int i = 0; i < model::cells.size(); i++) { - Cell& c {*model::cells[i]}; - - if (c.material_.size() > 1) { - if (c.material_.size() != c.n_instances_) { - std::stringstream err_msg; - err_msg << "Cell " << c.id_ << " was specified with " - << c.material_.size() << " materials but has " << c.n_instances_ - << " distributed instances. The number of materials must equal " - "one or the number of instances."; - fatal_error(err_msg); - } - distribcells.insert(i); - } - - if (c.sqrtkT_.size() > 1) { - if (c.sqrtkT_.size() != c.n_instances_) { - std::stringstream err_msg; - err_msg << "Cell " << c.id_ << " was specified with " - << c.sqrtkT_.size() << " temperatures but has " << c.n_instances_ - << " distributed instances. The number of temperatures must equal " - "one or the number of instances."; - fatal_error(err_msg); - } - distribcells.insert(i); - } - } - - // Search through universes for distributed cells and assign each one a - // unique distribcell array index. - int distribcell_index = 0; - std::vector target_univ_ids; - for (const auto& u : model::universes) { - for (auto cell_indx : u->cells_) { - if (distribcells.find(cell_indx) != distribcells.end()) { - model::cells[cell_indx]->distribcell_index_ = distribcell_index; - target_univ_ids.push_back(u->id_); - ++distribcell_index; - } - } - } - - // Allocate the cell and lattice offset tables. - int n_maps = target_univ_ids.size(); - for (auto& c : model::cells) { - if (c->type_ != FILL_MATERIAL) { - c->offset_.resize(n_maps, C_NONE); - } - } - for (auto& lat : model::lattices) { - lat->allocate_offset_table(n_maps); - } - - // Fill the cell and lattice offset tables. - for (int map = 0; map < target_univ_ids.size(); map++) { - auto target_univ_id = target_univ_ids[map]; - for (const auto& univ : model::universes) { - int32_t offset {0}; // TODO: is this a bug? It matches F90 implementation. - for (int32_t cell_indx : univ->cells_) { - Cell& c = *model::cells[cell_indx]; - - if (c.type_ == FILL_UNIVERSE) { - c.offset_[map] = offset; - int32_t search_univ = c.fill_; - offset += count_universe_instances(search_univ, target_univ_id); - - } else if (c.type_ == FILL_LATTICE) { - Lattice& lat = *model::lattices[c.fill_]; - offset = lat.fill_offset_table(offset, target_univ_id, map); - } - } - } - } -} - -//============================================================================== - -void -count_cell_instances(int32_t univ_indx) -{ - for (int32_t cell_indx : model::universes[univ_indx]->cells_) { - Cell& c = *model::cells[cell_indx]; - ++c.n_instances_; - - if (c.type_ == FILL_UNIVERSE) { - // This cell contains another universe. Recurse into that universe. - count_cell_instances(c.fill_); - - } else if (c.type_ == FILL_LATTICE) { - // This cell contains a lattice. Recurse into the lattice universes. - Lattice& lat = *model::lattices[c.fill_]; - for (auto it = lat.begin(); it != lat.end(); ++it) { - count_cell_instances(*it); - } - } - } -} - -//============================================================================== - -int -count_universe_instances(int32_t search_univ, int32_t target_univ_id) -{ - // If this is the target, it can't contain itself. - if (model::universes[search_univ]->id_ == target_univ_id) { - return 1; - } - - int count {0}; - for (int32_t cell_indx : model::universes[search_univ]->cells_) { - Cell& c = *model::cells[cell_indx]; - - if (c.type_ == FILL_UNIVERSE) { - int32_t next_univ = c.fill_; - count += count_universe_instances(next_univ, target_univ_id); - - } else if (c.type_ == FILL_LATTICE) { - Lattice& lat = *model::lattices[c.fill_]; - for (auto it = lat.begin(); it != lat.end(); ++it) { - int32_t next_univ = *it; - count += count_universe_instances(next_univ, target_univ_id); - } - } - } - - return count; -} - -//============================================================================== - -std::string -distribcell_path_inner(int32_t target_cell, int32_t map, int32_t target_offset, - const Universe& search_univ, int32_t offset) -{ - std::stringstream path; - - path << "u" << search_univ.id_ << "->"; - - // Check to see if this universe directly contains the target cell. If so, - // write to the path and return. - for (int32_t cell_indx : search_univ.cells_) { - if ((cell_indx == target_cell) && (offset == target_offset)) { - Cell& c = *model::cells[cell_indx]; - path << "c" << c.id_; - return path.str(); - } - } - - // The target must be further down the geometry tree and contained in a fill - // cell or lattice cell in this universe. Find which cell contains the - // target. - std::vector::const_reverse_iterator cell_it - {search_univ.cells_.crbegin()}; - for (; cell_it != search_univ.cells_.crend(); ++cell_it) { - Cell& c = *model::cells[*cell_it]; - - // Material cells don't contain other cells so ignore them. - if (c.type_ != FILL_MATERIAL) { - int32_t temp_offset; - if (c.type_ == FILL_UNIVERSE) { - temp_offset = offset + c.offset_[map]; - } else { - Lattice& lat = *model::lattices[c.fill_]; - int32_t indx = lat.universes_.size()*map + lat.begin().indx_; - temp_offset = offset + lat.offsets_[indx]; - } - - // The desired cell is the first cell that gives an offset smaller or - // equal to the target offset. - if (temp_offset <= target_offset) break; - } - } - - // Add the cell to the path string. - Cell& c = *model::cells[*cell_it]; - path << "c" << c.id_ << "->"; - - if (c.type_ == FILL_UNIVERSE) { - // Recurse into the fill cell. - offset += c.offset_[map]; - path << distribcell_path_inner(target_cell, map, target_offset, - *model::universes[c.fill_], offset); - return path.str(); - } else { - // Recurse into the lattice cell. - Lattice& lat = *model::lattices[c.fill_]; - path << "l" << lat.id_; - for (ReverseLatticeIter it = lat.rbegin(); it != lat.rend(); ++it) { - int32_t indx = lat.universes_.size()*map + it.indx_; - int32_t temp_offset = offset + lat.offsets_[indx]; - if (temp_offset <= target_offset) { - offset = temp_offset; - path << "(" << lat.index_to_string(it.indx_) << ")->"; - path << distribcell_path_inner(target_cell, map, target_offset, - *model::universes[*it], offset); - return path.str(); - } - } - throw std::runtime_error{"Error determining distribcell path."}; - } -} - -std::string -distribcell_path(int32_t target_cell, int32_t map, int32_t target_offset) -{ - auto& root_univ = *model::universes[model::root_universe]; - return distribcell_path_inner(target_cell, map, target_offset, root_univ, 0); -} - -//============================================================================== - -int -maximum_levels(int32_t univ) -{ - int levels_below {0}; - - for (int32_t cell_indx : model::universes[univ]->cells_) { - Cell& c = *model::cells[cell_indx]; - if (c.type_ == FILL_UNIVERSE) { - int32_t next_univ = c.fill_; - levels_below = std::max(levels_below, maximum_levels(next_univ)); - } else if (c.type_ == FILL_LATTICE) { - Lattice& lat = *model::lattices[c.fill_]; - for (auto it = lat.begin(); it != lat.end(); ++it) { - int32_t next_univ = *it; - levels_below = std::max(levels_below, maximum_levels(next_univ)); - } - } - } - - ++levels_below; - return levels_below; -} - -//============================================================================== - -void -free_memory_geometry() -{ - model::cells.clear(); - model::cell_map.clear(); - - model::universes.clear(); - model::universe_map.clear(); - - model::lattices.clear(); - model::lattice_map.clear(); - - model::overlap_check_count.clear(); -} - -} // namespace openmc diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp deleted file mode 100644 index b1a90cb8f..000000000 --- a/src/hdf5_interface.cpp +++ /dev/null @@ -1,805 +0,0 @@ -#include "openmc/hdf5_interface.h" - -#include -#include -#include -#include -#include - -#include "xtensor/xtensor.hpp" -#include "xtensor/xarray.hpp" - -#include "hdf5.h" -#include "hdf5_hl.h" -#ifdef OPENMC_MPI -#include "mpi.h" -#include "openmc/message_passing.h" -#endif - - -namespace openmc { - -bool -attribute_exists(hid_t obj_id, const char* name) -{ - htri_t out = H5Aexists_by_name(obj_id, ".", name, H5P_DEFAULT); - return out > 0; -} - - -size_t -attribute_typesize(hid_t obj_id, const char* name) -{ - hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); - hid_t filetype = H5Aget_type(attr); - size_t n = H5Tget_size(filetype); - H5Tclose(filetype); - H5Aclose(attr); - return n; -} - - -void -get_shape(hid_t obj_id, hsize_t* dims) -{ - auto type = H5Iget_type(obj_id); - hid_t dspace; - if (type == H5I_DATASET) { - dspace = H5Dget_space(obj_id); - } else if (type == H5I_ATTR) { - dspace = H5Aget_space(obj_id); - } else { - throw std::runtime_error{"Expected dataset or attribute in call to get_shape."}; - } - H5Sget_simple_extent_dims(dspace, dims, nullptr); - H5Sclose(dspace); -} - - -std::vector attribute_shape(hid_t obj_id, const char* name) -{ - hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); - std::vector shape = object_shape(attr); - H5Aclose(attr); - return shape; -} - -std::vector object_shape(hid_t obj_id) -{ - // Get number of dimensions - auto type = H5Iget_type(obj_id); - hid_t dspace; - if (type == H5I_DATASET) { - dspace = H5Dget_space(obj_id); - } else if (type == H5I_ATTR) { - dspace = H5Aget_space(obj_id); - } else { - throw std::runtime_error{"Expected dataset or attribute in call to object_shape."}; - } - int n = H5Sget_simple_extent_ndims(dspace); - - // Get shape of array - std::vector shape(n); - H5Sget_simple_extent_dims(dspace, shape.data(), nullptr); - - // Free resources and return - H5Sclose(dspace); - return shape; -} - -void -get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims) -{ - hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); - hid_t dspace = H5Aget_space(attr); - H5Sget_simple_extent_dims(dspace, dims, nullptr); - H5Sclose(dspace); - H5Aclose(attr); -} - - -hid_t -create_group(hid_t parent_id, char const *name) -{ - hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - if (out < 0) { - std::stringstream err_msg; - err_msg << "Failed to create HDF5 group \"" << name << "\""; - fatal_error(err_msg); - } - return out; -} - - -hid_t -create_group(hid_t parent_id, const std::string &name) -{ - return create_group(parent_id, name.c_str()); -} - - -void -close_dataset(hid_t dataset_id) -{ - if (H5Dclose(dataset_id) < 0) fatal_error("Failed to close dataset"); -} - - -void -close_group(hid_t group_id) -{ - if (H5Gclose(group_id) < 0) fatal_error("Failed to close group"); -} - - -int -dataset_ndims(hid_t dset) -{ - hid_t dspace = H5Dget_space(dset); - int ndims = H5Sget_simple_extent_ndims(dspace); - H5Sclose(dspace); - return ndims; -} - - -size_t -dataset_typesize(hid_t obj_id, const char* name) -{ - hid_t dset = open_dataset(obj_id, name); - hid_t filetype = H5Dget_type(dset); - size_t n = H5Tget_size(filetype); - H5Tclose(filetype); - close_dataset(dset); - return n; -} - - -void -ensure_exists(hid_t obj_id, const char* name, bool attribute) -{ - if (attribute) { - if (!attribute_exists(obj_id, name)) { - std::stringstream err_msg; - err_msg << "Attribute \"" << name << "\" does not exist in object " - << object_name(obj_id); - fatal_error(err_msg); - } - } else { - if (!object_exists(obj_id, name)) { - std::stringstream err_msg; - err_msg << "Object \"" << name << "\" does not exist in object " - << object_name(obj_id); - fatal_error(err_msg); - } - } -} - - -hid_t -file_open(const char* filename, char mode, bool parallel) -{ - bool create; - unsigned int flags; - switch (mode) { - case 'r': - case 'a': - create = false; - flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); - break; - case 'w': - case 'x': - create = true; - flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); - break; - default: - std::stringstream err_msg; - err_msg << "Invalid file mode: " << mode; - fatal_error(err_msg); - } - - hid_t plist = H5P_DEFAULT; -#ifdef PHDF5 - if (parallel) { - // Setup file access property list with parallel I/O access - plist = H5Pcreate(H5P_FILE_ACCESS); - H5Pset_fapl_mpio(plist, openmc::mpi::intracomm, MPI_INFO_NULL); - } -#endif - - // Open the file collectively - hid_t file_id; - if (create) { - file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist); - } else { - file_id = H5Fopen(filename, flags, plist); - } - if (file_id < 0) { - std::stringstream msg; - msg << "Failed to open HDF5 file with mode '" << mode << "': " << filename; - fatal_error(msg); - } - -#ifdef PHDF5 - // Close the property list - if (parallel) H5Pclose(plist); -#endif - - return file_id; -} - -hid_t -file_open(const std::string& filename, char mode, bool parallel) -{ - return file_open(filename.c_str(), mode, parallel); -} - -void file_close(hid_t file_id) -{ - H5Fclose(file_id); -} - - -void -get_name(hid_t obj_id, char* name) -{ - size_t size = 1 + H5Iget_name(obj_id, nullptr, 0); - H5Iget_name(obj_id, name, size); -} - - -int get_num_datasets(hid_t group_id) -{ - // Determine number of links in the group - H5G_info_t info; - H5Gget_info(group_id, &info); - - // Iterate over links to get number of groups - H5O_info_t oinfo; - int ndatasets = 0; - for (hsize_t i = 0; i < info.nlinks; ++i) { - // Determine type of object (and skip non-group) - H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, - H5P_DEFAULT); - if (oinfo.type == H5O_TYPE_DATASET) ndatasets += 1; - } - - return ndatasets; -} - - -int get_num_groups(hid_t group_id) -{ - // Determine number of links in the group - H5G_info_t info; - H5Gget_info(group_id, &info); - - // Iterate over links to get number of groups - H5O_info_t oinfo; - int ngroups = 0; - for (hsize_t i = 0; i < info.nlinks; ++i) { - // Determine type of object (and skip non-group) - H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, - H5P_DEFAULT); - if (oinfo.type == H5O_TYPE_GROUP) ngroups += 1; - } - - return ngroups; -} - - -void -get_datasets(hid_t group_id, char* name[]) -{ - // Determine number of links in the group - H5G_info_t info; - H5Gget_info(group_id, &info); - - // Iterate over links to get names - H5O_info_t oinfo; - hsize_t count = 0; - size_t size; - for (hsize_t i = 0; i < info.nlinks; ++i) { - // Determine type of object (and skip non-group) - H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, - H5P_DEFAULT); - if (oinfo.type != H5O_TYPE_DATASET) continue; - - // Get size of name - size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, - i, nullptr, 0, H5P_DEFAULT); - - // Read name - H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, - name[count], size, H5P_DEFAULT); - count += 1; - } -} - - -void -get_groups(hid_t group_id, char* name[]) -{ - // Determine number of links in the group - H5G_info_t info; - H5Gget_info(group_id, &info); - - // Iterate over links to get names - H5O_info_t oinfo; - hsize_t count = 0; - size_t size; - for (hsize_t i = 0; i < info.nlinks; ++i) { - // Determine type of object (and skip non-group) - H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, - H5P_DEFAULT); - if (oinfo.type != H5O_TYPE_GROUP) continue; - - // Get size of name - size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, - i, nullptr, 0, H5P_DEFAULT); - - // Read name - H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, - name[count], size, H5P_DEFAULT); - count += 1; - } -} - -std::vector -member_names(hid_t group_id, H5O_type_t type) -{ - // Determine number of links in the group - H5G_info_t info; - H5Gget_info(group_id, &info); - - // Iterate over links to get names - H5O_info_t oinfo; - size_t size; - std::vector names; - for (hsize_t i = 0; i < info.nlinks; ++i) { - // Determine type of object (and skip non-group) - H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, - H5P_DEFAULT); - if (oinfo.type != type) continue; - - // Get size of name - size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, - i, nullptr, 0, H5P_DEFAULT); - - // Read name - char* buffer = new char[size]; - H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, - buffer, size, H5P_DEFAULT); - names.emplace_back(&buffer[0]); - delete[] buffer; - } - return names; -} - -std::vector -group_names(hid_t group_id) -{ - return member_names(group_id, H5O_TYPE_GROUP); -} - -std::vector -dataset_names(hid_t group_id) -{ - return member_names(group_id, H5O_TYPE_DATASET); -} - -bool -object_exists(hid_t object_id, const char* name) -{ - htri_t out = H5LTpath_valid(object_id, name, true); - if (out < 0) { - std::stringstream err_msg; - err_msg << "Failed to check if object \"" << name << "\" exists."; - fatal_error(err_msg); - } - return (out > 0); -} - - -std::string -object_name(hid_t obj_id) -{ - // Determine size and create buffer - size_t size = 1 + H5Iget_name(obj_id, nullptr, 0); - char* buffer = new char[size]; - - // Read and return name - H5Iget_name(obj_id, buffer, size); - std::string str = buffer; - delete[] buffer; - return str; -} - - -hid_t -open_dataset(hid_t group_id, const char* name) -{ - ensure_exists(group_id, name); - return H5Dopen(group_id, name, H5P_DEFAULT); -} - - -hid_t -open_group(hid_t group_id, const char* name) -{ - ensure_exists(group_id, name); - return H5Gopen(group_id, name, H5P_DEFAULT); -} - -void -read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer) -{ - hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); - H5Aread(attr, mem_type_id, buffer); - H5Aclose(attr); -} - - -void -read_attr_double(hid_t obj_id, const char* name, double* buffer) -{ - read_attr(obj_id, name, H5T_NATIVE_DOUBLE, buffer); -} - - -void -read_attr_int(hid_t obj_id, const char* name, int* buffer) -{ - read_attr(obj_id, name, H5T_NATIVE_INT, buffer); -} - - -void -read_attr_string(hid_t obj_id, const char* name, size_t slen, char* buffer) -{ - // Create datatype for a string - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, slen); - // numpy uses null-padding when writing fixed-length strings - H5Tset_strpad(datatype, H5T_STR_NULLPAD); - - // Read data into buffer - read_attr(obj_id, name, datatype, buffer); - - // Free resources - H5Tclose(datatype); -} - - -void -read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, - void* buffer, bool indep) -{ - hid_t dset = obj_id; - if (name) dset = open_dataset(obj_id, name); - - if (using_mpio_device(dset)) { -#ifdef PHDF5 - // Set up collective vs independent I/O - auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE; - - // Create dataset transfer property list - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, data_xfer_mode); - - // Read data - H5Dread(dset, mem_type_id, H5S_ALL, H5S_ALL, plist, buffer); - H5Pclose(plist); -#endif - } else { - H5Dread(dset, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - } - - if (name) H5Dclose(dset); -} - -template<> -void read_dataset(hid_t dset, xt::xarray>& arr, bool indep) -{ - // Get shape of dataset - std::vector shape = object_shape(dset); - - // Allocate new array to read data into - std::size_t size = 1; - for (const auto x : shape) - size *= x; - std::vector> buffer(size); - - // Read data from attribute - read_complex(dset, nullptr, buffer.data(), indep); - - // Adapt into xarray - arr = xt::adapt(buffer, shape); -} - - -void -read_double(hid_t obj_id, const char* name, double* buffer, bool indep) -{ - read_dataset(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); -} - - -void -read_int(hid_t obj_id, const char* name, int* buffer, bool indep) -{ - read_dataset(obj_id, name, H5T_NATIVE_INT, buffer, indep); -} - - -void -read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) -{ - read_dataset(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); -} - - -void -read_string(hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep) -{ - // Create datatype for a string - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, slen); - // numpy uses null-padding when writing fixed-length strings - H5Tset_strpad(datatype, H5T_STR_NULLPAD); - - // Read data into buffer - read_dataset(obj_id, name, datatype, buffer, indep); - - // Free resources - H5Tclose(datatype); -} - - -void -read_complex(hid_t obj_id, const char* name, std::complex* buffer, bool indep) -{ - // Create compound datatype for complex numbers - struct complex_t { - double re; - double im; - }; - complex_t tmp; - hid_t complex_id = H5Tcreate(H5T_COMPOUND, sizeof tmp); - H5Tinsert(complex_id, "r", HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE); - H5Tinsert(complex_id, "i", HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE); - - // Read data - read_dataset(obj_id, name, complex_id, buffer, indep); - - // Free resources - H5Tclose(complex_id); -} - - -void -read_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, double* results) -{ - // Create dataspace for hyperslab in memory - hsize_t dims[] {n_filter, n_score, 3}; - hsize_t start[] {0, 0, 1}; - hsize_t count[] {n_filter, n_score, 2}; - hid_t memspace = H5Screate_simple(3, dims, nullptr); - H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Create and write dataset - hid_t dset = H5Dopen(group_id, "results", H5P_DEFAULT); - H5Dread(dset, H5T_NATIVE_DOUBLE, memspace, H5S_ALL, H5P_DEFAULT, results); - - // Free resources - H5Dclose(dset); - H5Sclose(memspace); -} - - -void -write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer) -{ - // If array is given, create a simple dataspace. Otherwise, create a scalar - // datascape. - hid_t dspace; - if (ndim > 0) { - dspace = H5Screate_simple(ndim, dims, nullptr); - } else { - dspace = H5Screate(H5S_SCALAR); - } - - // Create attribute and Write data - hid_t attr = H5Acreate(obj_id, name, mem_type_id, dspace, - H5P_DEFAULT, H5P_DEFAULT); - H5Awrite(attr, mem_type_id, buffer); - - // Free resources - H5Aclose(attr); - H5Sclose(dspace); -} - - -void -write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, - const double* buffer) -{ - write_attr(obj_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer); -} - - -void -write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, - const int* buffer) -{ - write_attr(obj_id, ndim, dims, name, H5T_NATIVE_INT, buffer); -} - - -void -write_attr_string(hid_t obj_id, const char* name, const char* buffer) -{ - size_t n = strlen(buffer); - if (n > 0) { - // Set up appropriate datatype for a fixed-length string - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, n); - - write_attr(obj_id, 0, nullptr, name, datatype, buffer); - - // Free resources - H5Tclose(datatype); - } -} - - -void -write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer, bool indep) -{ - // If array is given, create a simple dataspace. Otherwise, create a scalar - // datascape. - hid_t dspace; - if (ndim > 0) { - dspace = H5Screate_simple(ndim, dims, nullptr); - } else { - dspace = H5Screate(H5S_SCALAR); - } - - hid_t dset = H5Dcreate(group_id, name, mem_type_id, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - if (using_mpio_device(group_id)) { -#ifdef PHDF5 - // Set up collective vs independent I/O - auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE; - - // Create dataset transfer property list - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, data_xfer_mode); - - // Write data - H5Dwrite(dset, mem_type_id, H5S_ALL, H5S_ALL, plist, buffer); - H5Pclose(plist); -#endif - } else { - H5Dwrite(dset, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - } - - // Free resources - H5Dclose(dset); - H5Sclose(dspace); -} - - -void -write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const double* buffer, bool indep) -{ - write_dataset(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); -} - - -void -write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const int* buffer, bool indep) -{ - write_dataset(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); -} - - -void -write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const long long* buffer, bool indep) -{ - write_dataset(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); -} - - -void -write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, - const char* name, const char* buffer, bool indep) -{ - if (slen > 0) { - // Set up appropriate datatype for a fixed-length string - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, slen); - - write_dataset(group_id, ndim, dims, name, datatype, buffer, indep); - - // Free resources - H5Tclose(datatype); - } -} - - -void -write_string(hid_t group_id, const char* name, const std::string& buffer, bool indep) -{ - write_string(group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep); -} - - -void -write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results) -{ - // Set dimensions of sum/sum_sq hyperslab to store - hsize_t count[] {n_filter, n_score, 2}; - hid_t dspace = H5Screate_simple(3, count, nullptr); - - // Set dimensions of results array - hsize_t dims[] {n_filter, n_score, 3}; - hsize_t start[] {0, 0, 1}; - hid_t memspace = H5Screate_simple(3, dims, nullptr); - H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Create and write dataset - hid_t dset = H5Dcreate(group_id, "results", H5T_NATIVE_DOUBLE, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dset, H5T_NATIVE_DOUBLE, memspace, H5S_ALL, H5P_DEFAULT, results); - - // Free resources - H5Dclose(dset); - H5Sclose(memspace); - H5Sclose(dspace); -} - - -bool -using_mpio_device(hid_t obj_id) -{ - // Determine file that this object is part of - hid_t file_id = H5Iget_file_id(obj_id); - - // Get file access property list - hid_t fapl_id = H5Fget_access_plist(file_id); - - // Get low-level driver identifier - hid_t driver = H5Pget_driver(fapl_id); - - // Free resources - H5Pclose(fapl_id); - H5Fclose(file_id); - - return driver == H5FD_MPIO; -} - -// Specializations of the H5TypeMap template struct -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_INT8; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_INT; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_ULONG; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_ULLONG; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_UINT; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_INT64; -template<> -const hid_t H5TypeMap::type_id = H5T_NATIVE_DOUBLE; -template <> -const hid_t H5TypeMap::type_id = H5T_NATIVE_CHAR; - -} // namespace openmc diff --git a/src/initialize.cpp b/src/initialize.cpp deleted file mode 100644 index fd524a2de..000000000 --- a/src/initialize.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include "openmc/initialize.h" - -#include -#include // for getenv -#include -#include -#include -#include - -#ifdef _OPENMP -#include -#endif - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/cross_sections.h" -#include "openmc/error.h" -#include "openmc/geometry_aux.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/plot.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/summary.h" -#include "openmc/tallies/tally.h" -#include "openmc/thermal.h" -#include "openmc/timer.h" - - -int openmc_init(int argc, char* argv[], const void* intracomm) -{ - using namespace openmc; - -#ifdef OPENMC_MPI - // Check if intracomm was passed - MPI_Comm comm; - if (intracomm) { - comm = *static_cast(intracomm); - } else { - comm = MPI_COMM_WORLD; - } - - // Initialize MPI for C++ - initialize_mpi(comm); -#endif - - // Parse command-line arguments - int err = parse_command_line(argc, argv); - if (err) return err; - - // Start total and initialization timer - simulation::time_total.start(); - simulation::time_initialize.start(); - -#ifdef _OPENMP - // If OMP_SCHEDULE is not set, default to a static schedule - char* envvar = std::getenv("OMP_SCHEDULE"); - if (!envvar) { - omp_set_schedule(omp_sched_static, 0); - } -#endif - - // Initialize random number generator -- if the user specifies a seed, it - // will be re-initialized later - openmc::openmc_set_seed(DEFAULT_SEED); - - // Read XML input files - read_input_xml(); - - // Check for particle restart run - if (settings::particle_restart_run) settings::run_mode = RUN_MODE_PARTICLE; - - // Stop initialization timer - simulation::time_initialize.stop(); - - return 0; -} - -namespace openmc { - -#ifdef OPENMC_MPI -void initialize_mpi(MPI_Comm intracomm) -{ - mpi::intracomm = intracomm; - - // Initialize MPI - int flag; - MPI_Initialized(&flag); - if (!flag) MPI_Init(nullptr, nullptr); - - // Determine number of processes and rank for each - MPI_Comm_size(intracomm, &mpi::n_procs); - MPI_Comm_rank(intracomm, &mpi::rank); - mpi::master = (mpi::rank == 0); - - // Create bank datatype - Particle::Bank b; - MPI_Aint disp[6]; - MPI_Get_address(&b.r, &disp[0]); - MPI_Get_address(&b.u, &disp[1]); - MPI_Get_address(&b.E, &disp[2]); - MPI_Get_address(&b.wgt, &disp[3]); - MPI_Get_address(&b.delayed_group, &disp[4]); - MPI_Get_address(&b.particle, &disp[5]); - for (int i = 5; i >= 0; --i) disp[i] -= disp[0]; - - int blocks[] {3, 3, 1, 1, 1, 1}; - MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT}; - MPI_Type_create_struct(6, blocks, disp, types, &mpi::bank); - MPI_Type_commit(&mpi::bank); -} -#endif // OPENMC_MPI - - -int -parse_command_line(int argc, char* argv[]) -{ - int last_flag = 0; - for (int i=1; i < argc; ++i) { - std::string arg {argv[i]}; - if (arg[0] == '-') { - if (arg == "-p" || arg == "--plot") { - settings::run_mode = RUN_MODE_PLOTTING; - settings::check_overlaps = true; - - } else if (arg == "-n" || arg == "--particles") { - i += 1; - settings::n_particles = std::stoll(argv[i]); - - } else if (arg == "-r" || arg == "--restart") { - i += 1; - - // Check what type of file this is - hid_t file_id = file_open(argv[i], 'r', true); - std::string filetype; - read_attribute(file_id, "filetype", filetype); - file_close(file_id); - - // Set path and flag for type of run - if (filetype == "statepoint") { - settings::path_statepoint = argv[i]; - settings::restart_run = true; - } else if (filetype == "particle restart") { - settings::path_particle_restart = argv[i]; - settings::particle_restart_run = true; - } else { - std::stringstream msg; - msg << "Unrecognized file after restart flag: " << filetype << "."; - strcpy(openmc_err_msg, msg.str().c_str()); - return OPENMC_E_INVALID_ARGUMENT; - } - - // If its a restart run check for additional source file - if (settings::restart_run && i + 1 < argc) { - // Check if it has extension we can read - if (ends_with(argv[i+1], ".h5")) { - - // Check file type is a source file - file_id = file_open(argv[i+1], 'r', true); - read_attribute(file_id, "filetype", filetype); - file_close(file_id); - if (filetype != "source") { - std::string msg {"Second file after restart flag must be a source file"}; - strcpy(openmc_err_msg, msg.c_str()); - return OPENMC_E_INVALID_ARGUMENT; - } - - // It is a source file - settings::path_sourcepoint = argv[i+1]; - i += 1; - - } else { - // Source is in statepoint file - settings::path_sourcepoint = settings::path_statepoint; - } - - } else { - // Source is assumed to be in statepoint file - settings::path_sourcepoint = settings::path_statepoint; - } - - } else if (arg == "-g" || arg == "--geometry-debug") { - settings::check_overlaps = true; - } else if (arg == "-c" || arg == "--volume") { - settings::run_mode = RUN_MODE_VOLUME; - } else if (arg == "-s" || arg == "--threads") { - // Read number of threads - i += 1; - -#ifdef _OPENMP - // Read and set number of OpenMP threads - int n_threads = std::stoi(argv[i]); - if (n_threads < 1) { - std::string msg {"Number of threads must be positive."}; - strcpy(openmc_err_msg, msg.c_str()); - return OPENMC_E_INVALID_ARGUMENT; - } - omp_set_num_threads(n_threads); -#else - if (mpi::master) - warning("Ignoring number of threads specified on command line."); -#endif - - } else if (arg == "-?" || arg == "-h" || arg == "--help") { - print_usage(); - return OPENMC_E_UNASSIGNED; - - } else if (arg == "-v" || arg == "--version") { - print_version(); - return OPENMC_E_UNASSIGNED; - - } else if (arg == "-t" || arg == "--track") { - settings::write_all_tracks = true; - - } else { - std::cerr << "Unknown option: " << argv[i] << '\n'; - print_usage(); - return OPENMC_E_UNASSIGNED; - } - - last_flag = i; - } - } - - // Determine directory where XML input files are - if (argc > 1 && last_flag < argc - 1) { - settings::path_input = std::string(argv[last_flag + 1]); - - // Add slash at end of directory if it isn't there - if (!ends_with(settings::path_input, "/")) { - settings::path_input += "/"; - } - } - - return 0; -} - -void read_input_xml() -{ - read_settings_xml(); - read_cross_sections_xml(); - read_materials_xml(); - read_geometry_xml(); - - // Convert user IDs -> indices, assign temperatures - double_2dvec nuc_temps(data::nuclide_map.size()); - double_2dvec thermal_temps(data::thermal_scatt_map.size()); - finalize_geometry(nuc_temps, thermal_temps); - - if (settings::run_mode != RUN_MODE_PLOTTING) { - simulation::time_read_xs.start(); - if (settings::run_CE) { - // Read continuous-energy cross sections - read_ce_cross_sections(nuc_temps, thermal_temps); - } else { - // Create material macroscopic data for MGXS - read_mgxs(); - create_macro_xs(); - } - simulation::time_read_xs.stop(); - } - - read_tallies_xml(); - - // Initialize distribcell_filters - prepare_distribcell(); - - if (settings::run_mode == RUN_MODE_PLOTTING) { - // Read plots.xml if it exists - read_plots_xml(); - if (mpi::master && settings::verbosity >= 5) print_plot(); - - } else { - // Write summary information - if (mpi::master && settings::output_summary) write_summary(); - - // Warn if overlap checking is on - if (mpi::master && settings::check_overlaps) { - warning("Cell overlap checking is ON."); - } - } - -} - -} // namespace openmc diff --git a/src/lattice.cpp b/src/lattice.cpp deleted file mode 100644 index 6f10ed358..000000000 --- a/src/lattice.cpp +++ /dev/null @@ -1,1075 +0,0 @@ -#include "openmc/lattice.h" - -#include -#include -#include - -#include "openmc/cell.h" -#include "openmc/error.h" -#include "openmc/geometry.h" -#include "openmc/geometry_aux.h" -#include "openmc/hdf5_interface.h" -#include "openmc/string_utils.h" -#include "openmc/xml_interface.h" - - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - std::vector> lattices; - std::unordered_map lattice_map; -} - -//============================================================================== -// Lattice implementation -//============================================================================== - -Lattice::Lattice(pugi::xml_node lat_node) -{ - if (check_for_node(lat_node, "id")) { - id_ = std::stoi(get_node_value(lat_node, "id")); - } else { - fatal_error("Must specify id of lattice in geometry XML file."); - } - - if (check_for_node(lat_node, "name")) { - name_ = get_node_value(lat_node, "name"); - } - - if (check_for_node(lat_node, "outer")) { - outer_ = std::stoi(get_node_value(lat_node, "outer")); - } -} - -//============================================================================== - -LatticeIter Lattice::begin() -{return LatticeIter(*this, 0);} - -LatticeIter Lattice::end() -{return LatticeIter(*this, universes_.size());} - -ReverseLatticeIter Lattice::rbegin() -{return ReverseLatticeIter(*this, universes_.size()-1);} - -ReverseLatticeIter Lattice::rend() -{return ReverseLatticeIter(*this, -1);} - -//============================================================================== - -void -Lattice::adjust_indices() -{ - // Adjust the indices for the universes array. - for (LatticeIter it = begin(); it != end(); ++it) { - int uid = *it; - auto search = model::universe_map.find(uid); - if (search != model::universe_map.end()) { - *it = search->second; - } else { - std::stringstream err_msg; - err_msg << "Invalid universe number " << uid << " specified on " - "lattice " << id_; - fatal_error(err_msg); - } - } - - // Adjust the index for the outer universe. - if (outer_ != NO_OUTER_UNIVERSE) { - auto search = model::universe_map.find(outer_); - if (search != model::universe_map.end()) { - outer_ = search->second; - } else { - std::stringstream err_msg; - err_msg << "Invalid universe number " << outer_ << " specified on " - "lattice " << id_; - fatal_error(err_msg); - } - } -} - -//============================================================================== - -int32_t -Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id, int map) -{ - for (LatticeIter it = begin(); it != end(); ++it) { - offsets_[map * universes_.size() + it.indx_] = offset; - offset += count_universe_instances(*it, target_univ_id); - } - return offset; -} - -//============================================================================== - -void -Lattice::to_hdf5(hid_t lattices_group) const -{ - // Make a group for the lattice. - std::string group_name {"lattice "}; - group_name += std::to_string(id_); - hid_t lat_group = create_group(lattices_group, group_name); - - // Write the name and outer universe. - if (!name_.empty()) { - write_string(lat_group, "name", name_, false); - } - - if (outer_ != NO_OUTER_UNIVERSE) { - int32_t outer_id = model::universes[outer_]->id_; - write_dataset(lat_group, "outer", outer_id); - } else { - write_dataset(lat_group, "outer", outer_); - } - - // Call subclass-overriden function to fill in other details. - to_hdf5_inner(lat_group); - - close_group(lat_group); -} - -//============================================================================== -// RectLattice implementation -//============================================================================== - -RectLattice::RectLattice(pugi::xml_node lat_node) - : Lattice {lat_node} -{ - type_ = LatticeType::rect; - - // Read the number of lattice cells in each dimension. - std::string dimension_str {get_node_value(lat_node, "dimension")}; - std::vector dimension_words {split(dimension_str)}; - if (dimension_words.size() == 2) { - n_cells_[0] = std::stoi(dimension_words[0]); - n_cells_[1] = std::stoi(dimension_words[1]); - n_cells_[2] = 1; - is_3d_ = false; - } else if (dimension_words.size() == 3) { - n_cells_[0] = std::stoi(dimension_words[0]); - n_cells_[1] = std::stoi(dimension_words[1]); - n_cells_[2] = std::stoi(dimension_words[2]); - is_3d_ = true; - } else { - fatal_error("Rectangular lattice must be two or three dimensions."); - } - - // Read the lattice lower-left location. - std::string ll_str {get_node_value(lat_node, "lower_left")}; - std::vector ll_words {split(ll_str)}; - if (ll_words.size() != dimension_words.size()) { - fatal_error("Number of entries on must be the same as the " - "number of entries on ."); - } - lower_left_[0] = stod(ll_words[0]); - lower_left_[1] = stod(ll_words[1]); - if (is_3d_) {lower_left_[2] = stod(ll_words[2]);} - - // Read the lattice pitches. - std::string pitch_str {get_node_value(lat_node, "pitch")}; - std::vector pitch_words {split(pitch_str)}; - if (pitch_words.size() != dimension_words.size()) { - fatal_error("Number of entries on must be the same as the " - "number of entries on ."); - } - pitch_[0] = stod(pitch_words[0]); - pitch_[1] = stod(pitch_words[1]); - if (is_3d_) {pitch_[2] = stod(pitch_words[2]);} - - // Read the universes and make sure the correct number was specified. - std::string univ_str {get_node_value(lat_node, "universes")}; - std::vector univ_words {split(univ_str)}; - if (univ_words.size() != nx*ny*nz) { - std::stringstream err_msg; - err_msg << "Expected " << nx*ny*nz - << " universes for a rectangular lattice of size " - << nx << "x" << ny << "x" << nz << " but " << univ_words.size() - << " were specified."; - fatal_error(err_msg); - } - - // Parse the universes. - universes_.resize(nx*ny*nz, C_NONE); - for (int iz = 0; iz < nz; iz++) { - for (int iy = ny-1; iy > -1; iy--) { - for (int ix = 0; ix < nx; ix++) { - int indx1 = nx*ny*iz + nx*(ny-iy-1) + ix; - int indx2 = nx*ny*iz + nx*iy + ix; - universes_[indx1] = std::stoi(univ_words[indx2]); - } - } - } -} - -//============================================================================== - -int32_t& -RectLattice::operator[](std::array i_xyz) -{ - int indx = nx*ny*i_xyz[2] + nx*i_xyz[1] + i_xyz[0]; - return universes_[indx]; -} - -//============================================================================== - -bool -RectLattice::are_valid_indices(const int i_xyz[3]) const -{ - return ( (i_xyz[0] >= 0) && (i_xyz[0] < n_cells_[0]) - && (i_xyz[1] >= 0) && (i_xyz[1] < n_cells_[1]) - && (i_xyz[2] >= 0) && (i_xyz[2] < n_cells_[2])); -} - -//============================================================================== - -std::pair> -RectLattice::distance(Position r, Direction u, const std::array& i_xyz) -const -{ - // Get short aliases to the coordinates. - double x = r.x; - double y = r.y; - double z = r.z; - - // Determine the oncoming edge. - double x0 {copysign(0.5 * pitch_[0], u.x)}; - double y0 {copysign(0.5 * pitch_[1], u.y)}; - - // Left and right sides - double d {INFTY}; - std::array lattice_trans; - if ((std::abs(x - x0) > FP_PRECISION) && u.x != 0) { - d = (x0 - x) / u.x; - if (u.x > 0) { - lattice_trans = {1, 0, 0}; - } else { - lattice_trans = {-1, 0, 0}; - } - } - - // Front and back sides - if ((std::abs(y - y0) > FP_PRECISION) && u.y != 0) { - double this_d = (y0 - y) / u.y; - if (this_d < d) { - d = this_d; - if (u.y > 0) { - lattice_trans = {0, 1, 0}; - } else { - lattice_trans = {0, -1, 0}; - } - } - } - - // Top and bottom sides - if (is_3d_) { - double z0 {copysign(0.5 * pitch_[2], u.z)}; - if ((std::abs(z - z0) > FP_PRECISION) && u.z != 0) { - double this_d = (z0 - z) / u.z; - if (this_d < d) { - d = this_d; - if (u.z > 0) { - lattice_trans = {0, 0, 1}; - } else { - lattice_trans = {0, 0, -1}; - } - } - } - } - - return {d, lattice_trans}; -} - -//============================================================================== - -std::array -RectLattice::get_indices(Position r, Direction u) const -{ - // Determine x index, accounting for coincidence - double ix_ {(r.x - lower_left_.x) / pitch_.x}; - long ix_close {std::lround(ix_)}; - int ix; - if (coincident(ix_, ix_close)) { - ix = (u.x > 0) ? ix_close : ix_close - 1; - } else { - ix = std::floor(ix_); - } - - // Determine y index, accounting for coincidence - double iy_ {(r.y - lower_left_.y) / pitch_.y}; - long iy_close {std::lround(iy_)}; - int iy; - if (coincident(iy_, iy_close)) { - iy = (u.y > 0) ? iy_close : iy_close - 1; - } else { - iy = std::floor(iy_); - } - - // Determine z index, accounting for coincidence - int iz = 0; - if (is_3d_) { - double iz_ {(r.z - lower_left_.z) / pitch_.z}; - long iz_close {std::lround(iz_)}; - if (coincident(iz_, iz_close)) { - iz = (u.z > 0) ? iz_close : iz_close - 1; - } else { - iz = std::floor(iz_); - } - } - return {ix, iy, iz}; -} - -//============================================================================== - -Position -RectLattice::get_local_position(Position r, const std::array i_xyz) -const -{ - r.x -= (lower_left_.x + (i_xyz[0] + 0.5)*pitch_.x); - r.y -= (lower_left_.y + (i_xyz[1] + 0.5)*pitch_.y); - if (is_3d_) { - r.z -= (lower_left_.z + (i_xyz[2] + 0.5)*pitch_.z); - } - return r; -} - -//============================================================================== - -int32_t& -RectLattice::offset(int map, const int i_xyz[3]) -{ - return offsets_[nx*ny*nz*map + nx*ny*i_xyz[2] + nx*i_xyz[1] + i_xyz[0]]; -} - -//============================================================================== - -std::string -RectLattice::index_to_string(int indx) const -{ - int iz {indx / (nx * ny)}; - int iy {(indx - nx * ny * iz) / nx}; - int ix {indx - nx * ny * iz - nx * iy}; - std::string out {std::to_string(ix)}; - out += ','; - out += std::to_string(iy); - if (is_3d_) { - out += ','; - out += std::to_string(iz); - } - return out; -} - -//============================================================================== - -void -RectLattice::to_hdf5_inner(hid_t lat_group) const -{ - // Write basic lattice information. - write_string(lat_group, "type", "rectangular", false); - if (is_3d_) { - write_dataset(lat_group, "pitch", pitch_); - write_dataset(lat_group, "lower_left", lower_left_); - write_dataset(lat_group, "dimension", n_cells_); - } else { - std::array pitch_short {{pitch_[0], pitch_[1]}}; - write_dataset(lat_group, "pitch", pitch_short); - std::array ll_short {{lower_left_[0], lower_left_[1]}}; - write_dataset(lat_group, "lower_left", ll_short); - std::array nc_short {{n_cells_[0], n_cells_[1]}}; - write_dataset(lat_group, "dimension", nc_short); - } - - // Write the universe ids. The convention here is to switch the ordering on - // the y-axis to match the way universes are input in a text file. - if (is_3d_) { - hsize_t nx {static_cast(n_cells_[0])}; - hsize_t ny {static_cast(n_cells_[1])}; - hsize_t nz {static_cast(n_cells_[2])}; - std::vector out(nx*ny*nz); - - for (int m = 0; m < nz; m++) { - for (int k = 0; k < ny; k++) { - for (int j = 0; j < nx; j++) { - int indx1 = nx*ny*m + nx*k + j; - int indx2 = nx*ny*m + nx*(ny-k-1) + j; - out[indx2] = model::universes[universes_[indx1]]->id_; - } - } - } - - hsize_t dims[3] {nz, ny, nx}; - write_int(lat_group, 3, dims, "universes", out.data(), false); - - } else { - hsize_t nx {static_cast(n_cells_[0])}; - hsize_t ny {static_cast(n_cells_[1])}; - std::vector out(nx*ny); - - for (int k = 0; k < ny; k++) { - for (int j = 0; j < nx; j++) { - int indx1 = nx*k + j; - int indx2 = nx*(ny-k-1) + j; - out[indx2] = model::universes[universes_[indx1]]->id_; - } - } - - hsize_t dims[3] {1, ny, nx}; - write_int(lat_group, 3, dims, "universes", out.data(), false); - } -} - -//============================================================================== -// HexLattice implementation -//============================================================================== - -HexLattice::HexLattice(pugi::xml_node lat_node) - : Lattice {lat_node} -{ - type_ = LatticeType::hex; - - // Read the number of lattice cells in each dimension. - n_rings_ = std::stoi(get_node_value(lat_node, "n_rings")); - if (check_for_node(lat_node, "n_axial")) { - n_axial_ = std::stoi(get_node_value(lat_node, "n_axial")); - is_3d_ = true; - } else { - n_axial_ = 1; - is_3d_ = false; - } - - // Read the lattice orientation. Default to 'y'. - if (check_for_node(lat_node, "orientation")) { - std::string orientation = get_node_value(lat_node, "orientation"); - if (orientation == "y") { - orientation_ = Orientation::y; - } else if (orientation == "x") { - orientation_ = Orientation::x; - } else { - fatal_error("Unrecognized orientation '" + orientation - + "' for lattice " + std::to_string(id_)); - } - } else { - orientation_ = Orientation::y; - } - - // Read the lattice center. - std::string center_str {get_node_value(lat_node, "center")}; - std::vector center_words {split(center_str)}; - if (is_3d_ && (center_words.size() != 3)) { - fatal_error("A hexagonal lattice with must have
" - "specified by 3 numbers."); - } else if (!is_3d_ && center_words.size() != 2) { - fatal_error("A hexagonal lattice without must have
" - "specified by 2 numbers."); - } - center_[0] = stod(center_words[0]); - center_[1] = stod(center_words[1]); - if (is_3d_) {center_[2] = stod(center_words[2]);} - - // Read the lattice pitches. - std::string pitch_str {get_node_value(lat_node, "pitch")}; - std::vector pitch_words {split(pitch_str)}; - if (is_3d_ && (pitch_words.size() != 2)) { - fatal_error("A hexagonal lattice with must have " - "specified by 2 numbers."); - } else if (!is_3d_ && (pitch_words.size() != 1)) { - fatal_error("A hexagonal lattice without must have " - "specified by 1 number."); - } - pitch_[0] = stod(pitch_words[0]); - if (is_3d_) {pitch_[1] = stod(pitch_words[1]);} - - // Read the universes and make sure the correct number was specified. - int n_univ = (3*n_rings_*n_rings_ - 3*n_rings_ + 1) * n_axial_; - std::string univ_str {get_node_value(lat_node, "universes")}; - std::vector univ_words {split(univ_str)}; - if (univ_words.size() != n_univ) { - std::stringstream err_msg; - err_msg << "Expected " << n_univ - << " universes for a hexagonal lattice with " << n_rings_ - << " rings and " << n_axial_ << " axial levels" << " but " - << univ_words.size() << " were specified."; - fatal_error(err_msg); - } - - // Parse the universes. - // Universes in hexagonal lattices are stored in a manner that represents - // a skewed coordinate system: (x, alpha) in case of 'y' orientation - // and (alpha,y) in 'x' one rather than (x, y). There is - // no obvious, direct relationship between the order of universes in the - // input and the order that they will be stored in the skewed array so - // the following code walks a set of index values across the skewed array - // in a manner that matches the input order. Note that i_x = 0, i_a = 0 - // or i_a = 0, i_y = 0 corresponds to the center of the hexagonal lattice. - universes_.resize((2*n_rings_-1) * (2*n_rings_-1) * n_axial_, C_NONE); - if (orientation_ == Orientation::y) { - fill_lattice_y(univ_words); - } else { - fill_lattice_x(univ_words); - } -} - -//============================================================================== - -void -HexLattice::fill_lattice_x(const std::vector& univ_words) -{ - int input_index = 0; - for (int m = 0; m < n_axial_; m++) { - // Initialize lattice indecies. - int i_a = -(n_rings_ - 1); - int i_y = n_rings_ - 1; - - // Map upper region of hexagonal lattice which is found in the - // first n_rings-1 rows of the input. - for (int k = 0; k < n_rings_-1; k++) { - - // Iterate over the input columns. - for (int j = 0; j < k+n_rings_; j++) { - int indx = (2*n_rings_-1)*(2*n_rings_-1) * m - + (2*n_rings_-1) * (i_y+n_rings_-1) - + (i_a+n_rings_-1); - universes_[indx] = std::stoi(univ_words[input_index]); - input_index++; - // Move to the next right neighbour cell - i_a += 1; - } - - // Return the lattice index to the start of the current row. - i_a = -(n_rings_ - 1); - i_y -= 1; - } - - // Map the lower region from the centerline of cart to down side - for (int k = 0; k < n_rings_; k++) { - // Walk the index to the lower-right neighbor of the last row start. - i_a = -(n_rings_ - 1) + k; - - // Iterate over the input columns. - for (int j = 0; j < 2*n_rings_-k-1; j++) { - int indx = (2*n_rings_-1)*(2*n_rings_-1) * m - + (2*n_rings_-1) * (i_y+n_rings_-1) - + (i_a+n_rings_-1); - universes_[indx] = std::stoi(univ_words[input_index]); - input_index++; - // Move to the next right neighbour cell - i_a += 1; - } - - // Return lattice index to start of current row. - i_y -= 1; - } - } -} - -//============================================================================== - -void -HexLattice::fill_lattice_y(const std::vector& univ_words) -{ - int input_index = 0; - for (int m = 0; m < n_axial_; m++) { - // Initialize lattice indecies. - int i_x = 1; - int i_a = n_rings_ - 1; - - // Map upper triangular region of hexagonal lattice which is found in the - // first n_rings-1 rows of the input. - for (int k = 0; k < n_rings_-1; k++) { - // Walk the index to lower-left neighbor of last row start. - i_x -= 1; - - // Iterate over the input columns. - for (int j = 0; j < k+1; j++) { - int indx = (2*n_rings_-1)*(2*n_rings_-1) * m - + (2*n_rings_-1) * (i_a+n_rings_-1) - + (i_x+n_rings_-1); - universes_[indx] = std::stoi(univ_words[input_index]); - input_index++; - // Walk the index to the right neighbor (which is not adjacent). - i_x += 2; - i_a -= 1; - } - - // Return the lattice index to the start of the current row. - i_x -= 2 * (k+1); - i_a += (k+1); - } - - // Map the middle square region of the hexagonal lattice which is found in - // the next 2*n_rings-1 rows of the input. - for (int k = 0; k < 2*n_rings_-1; k++) { - if ((k % 2) == 0) { - // Walk the index to the lower-left neighbor of the last row start. - i_x -= 1; - } else { - // Walk the index to the lower-right neighbor of the last row start. - i_x += 1; - i_a -= 1; - } - - // Iterate over the input columns. - for (int j = 0; j < n_rings_ - (k % 2); j++) { - int indx = (2*n_rings_-1)*(2*n_rings_-1) * m - + (2*n_rings_-1) * (i_a+n_rings_-1) - + (i_x+n_rings_-1); - universes_[indx] = std::stoi(univ_words[input_index]); - input_index++; - // Walk the index to the right neighbor (which is not adjacent). - i_x += 2; - i_a -= 1; - } - - // Return the lattice index to the start of the current row. - i_x -= 2*(n_rings_ - (k % 2)); - i_a += n_rings_ - (k % 2); - } - - // Map the lower triangular region of the hexagonal lattice. - for (int k = 0; k < n_rings_-1; k++) { - // Walk the index to the lower-right neighbor of the last row start. - i_x += 1; - i_a -= 1; - - // Iterate over the input columns. - for (int j = 0; j < n_rings_-k-1; j++) { - int indx = (2*n_rings_-1)*(2*n_rings_-1) * m - + (2*n_rings_-1) * (i_a+n_rings_-1) - + (i_x+n_rings_-1); - universes_[indx] = std::stoi(univ_words[input_index]); - input_index++; - // Walk the index to the right neighbor (which is not adjacent). - i_x += 2; - i_a -= 1; - } - - // Return lattice index to start of current row. - i_x -= 2*(n_rings_ - k - 1); - i_a += n_rings_ - k - 1; - } - } -} - -//============================================================================== - -int32_t& -HexLattice::operator[](std::array i_xyz) -{ - int indx = (2*n_rings_-1)*(2*n_rings_-1) * i_xyz[2] - + (2*n_rings_-1) * i_xyz[1] - + i_xyz[0]; - return universes_[indx]; -} - -//============================================================================== - -LatticeIter HexLattice::begin() -{return LatticeIter(*this, n_rings_-1);} - -ReverseLatticeIter HexLattice::rbegin() -{return ReverseLatticeIter(*this, universes_.size()-n_rings_);} - -//============================================================================== - -bool -HexLattice::are_valid_indices(const int i_xyz[3]) const -{ - return ((i_xyz[0] >= 0) && (i_xyz[1] >= 0) && (i_xyz[2] >= 0) - && (i_xyz[0] < 2*n_rings_-1) && (i_xyz[1] < 2*n_rings_-1) - && (i_xyz[0] + i_xyz[1] > n_rings_-2) - && (i_xyz[0] + i_xyz[1] < 3*n_rings_-2) - && (i_xyz[2] < n_axial_)); -} - -//============================================================================== - -std::pair> -HexLattice::distance(Position r, Direction u, const std::array& i_xyz) -const -{ - // Short description of the direction vectors used here. The beta, gamma, and - // delta vectors point towards the flat sides of each hexagonal tile. - // Y - orientation: - // basis0 = (1, 0) - // basis1 = (-1/sqrt(3), 1) = +120 degrees from basis0 - // beta = (sqrt(3)/2, 1/2) = +30 degrees from basis0 - // gamma = (sqrt(3)/2, -1/2) = -60 degrees from beta - // delta = (0, 1) = +60 degrees from beta - // X - orientation: - // basis0 = (1/sqrt(3), -1) - // basis1 = (0, 1) = +120 degrees from basis0 - // beta = (1, 0) = +30 degrees from basis0 - // gamma = (1/2, -sqrt(3)/2) = -60 degrees from beta - // delta = (1/2, sqrt(3)/2) = +60 degrees from beta - // The z-axis is considered separately. - double beta_dir; - double gamma_dir; - double delta_dir; - if (orientation_ == Orientation::y) { - beta_dir = u.x * std::sqrt(3.0) / 2.0 + u.y / 2.0; - gamma_dir = u.x * std::sqrt(3.0) / 2.0 - u.y / 2.0; - delta_dir = u.y; - } else { - beta_dir = u.x; - gamma_dir = u.x / 2.0 - u.y * std::sqrt(3.0) / 2.0; - delta_dir = u.x / 2.0 + u.y * std::sqrt(3.0) / 2.0; - } - - // Note that hexagonal lattice distance calculations are performed - // using the particle's coordinates relative to the neighbor lattice - // cells, not relative to the particle's current cell. This is done - // because there is significant disagreement between neighboring cells - // on where the lattice boundary is due to finite precision issues. - - // beta direction - double d {INFTY}; - std::array lattice_trans; - double edge = -copysign(0.5*pitch_[0], beta_dir); // Oncoming edge - Position r_t; - if (beta_dir > 0) { - const std::array i_xyz_t {i_xyz[0]+1, i_xyz[1], i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } else { - const std::array i_xyz_t {i_xyz[0]-1, i_xyz[1], i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } - double beta; - if (orientation_ == Orientation::y) { - beta = r_t.x * std::sqrt(3.0) / 2.0 + r_t.y / 2.0; - } else { - beta = r_t.x; - } - if ((std::abs(beta - edge) > FP_PRECISION) && beta_dir != 0) { - d = (edge - beta) / beta_dir; - if (beta_dir > 0) { - lattice_trans = {1, 0, 0}; - } else { - lattice_trans = {-1, 0, 0}; - } - } - - // gamma direction - edge = -copysign(0.5*pitch_[0], gamma_dir); - if (gamma_dir > 0) { - const std::array i_xyz_t {i_xyz[0]+1, i_xyz[1]-1, i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } else { - const std::array i_xyz_t {i_xyz[0]-1, i_xyz[1]+1, i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } - double gamma; - if (orientation_ == Orientation::y) { - gamma = r_t.x * std::sqrt(3.0) / 2.0 - r_t.y / 2.0; - } else { - gamma = r_t.x / 2.0 - r_t.y * std::sqrt(3.0) / 2.0; - } - if ((std::abs(gamma - edge) > FP_PRECISION) && gamma_dir != 0) { - double this_d = (edge - gamma) / gamma_dir; - if (this_d < d) { - if (gamma_dir > 0) { - lattice_trans = {1, -1, 0}; - } else { - lattice_trans = {-1, 1, 0}; - } - d = this_d; - } - } - - // delta direction - edge = -copysign(0.5*pitch_[0], delta_dir); - if (delta_dir > 0) { - const std::array i_xyz_t {i_xyz[0], i_xyz[1]+1, i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } else { - const std::array i_xyz_t {i_xyz[0], i_xyz[1]-1, i_xyz[2]}; - r_t = get_local_position(r, i_xyz_t); - } - double delta; - if (orientation_ == Orientation::y) { - delta = r_t.y; - } else { - delta = r_t.x / 2.0 + r_t.y * std::sqrt(3.0) / 2.0; - } - if ((std::abs(delta - edge) > FP_PRECISION) && delta_dir != 0) { - double this_d = (edge - delta) / delta_dir; - if (this_d < d) { - if (delta_dir > 0) { - lattice_trans = {0, 1, 0}; - } else { - lattice_trans = {0, -1, 0}; - } - d = this_d; - } - } - - // Top and bottom sides - if (is_3d_) { - double z = r.z; - double z0 {copysign(0.5 * pitch_[1], u.z)}; - if ((std::abs(z - z0) > FP_PRECISION) && u.z != 0) { - double this_d = (z0 - z) / u.z; - if (this_d < d) { - d = this_d; - if (u.z > 0) { - lattice_trans = {0, 0, 1}; - } else { - lattice_trans = {0, 0, -1}; - } - d = this_d; - } - } - } - - return {d, lattice_trans}; -} - -//============================================================================== - -std::array -HexLattice::get_indices(Position r, Direction u) const -{ - // Offset the xyz by the lattice center. - Position r_o {r.x - center_.x, r.y - center_.y, r.z}; - if (is_3d_) {r_o.z -= center_.z;} - - // Index the z direction, accounting for coincidence - int iz = 0; - if (is_3d_) { - double iz_ {r_o.z / pitch_[1] + 0.5 * n_axial_}; - long iz_close {std::lround(iz_)}; - if (coincident(iz_, iz_close)) { - iz = (u.z > 0) ? iz_close : iz_close - 1; - } else { - iz = std::floor(iz_); - } - } - - int i1, i2; - if (orientation_ == Orientation::y) { - // Convert coordinates into skewed bases. The (x, alpha) basis is used to - // find the index of the global coordinates to within 4 cells. - double alpha = r_o.y - r_o.x / std::sqrt(3.0); - i1 = std::floor(r_o.x / (0.5*std::sqrt(3.0) * pitch_[0])); - i2 = std::floor(alpha / pitch_[0]); - } else { - // Convert coordinates into skewed bases. The (alpha, y) basis is used to - // find the index of the global coordinates to within 4 cells. - double alpha = r_o.y - r_o.x * std::sqrt(3.0); - i1 = std::floor(-alpha / (std::sqrt(3.0) * pitch_[0])); - i2 = std::floor(r_o.y / (0.5*std::sqrt(3.0) * pitch_[0])); - } - - // Add offset to indices (the center cell is (i1, i2) = (0, 0) but - // the array is offset so that the indices never go below 0). - i1 += n_rings_-1; - i2 += n_rings_-1; - - // Calculate the (squared) distance between the particle and the centers of - // the four possible cells. Regular hexagonal tiles form a Voronoi - // tessellation so the xyz should be in the hexagonal cell that it is closest - // to the center of. This method is used over a method that uses the - // remainders of the floor divisions above because it provides better finite - // precision performance. Squared distances are used because they are more - // computationally efficient than normal distances. - - // COINCIDENCE CHECK - // if a distance to center, d, is within the coincidence tolerance of the - // current minimum distance, d_min, the particle is on an edge or vertex. - // In this case, the dot product of the position vector and direction vector - // for the current indices, dp, and the dot product for the currently selected - // indices, dp_min, are compared. The cell which the particle is moving into - // is kept (i.e. the cell with the lowest dot product as the vectors will be - // completely opposed if the particle is moving directly toward the center of - // the cell). - int i1_chg {}; - int i2_chg {}; - double d_min {INFTY}; - double dp_min {INFTY}; - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - // get local coordinates - const std::array i_xyz {i1 + j, i2 + i, 0}; - Position r_t = get_local_position(r, i_xyz); - // calculate distance - double d = r_t.x*r_t.x + r_t.y*r_t.y; - // check for coincidence - bool on_boundary = coincident(d, d_min); - if (d < d_min || on_boundary) { - // normalize r_t and find dot product - r_t /= std::sqrt(d); - double dp = u.x * r_t.x + u.y * r_t.y; - // do not update values if particle is on a - // boundary and not moving into this cell - if (on_boundary && dp > dp_min) continue; - // update values - d_min = d; - i1_chg = j; - i2_chg = i; - dp_min = dp; - } - } - } - - // update outgoing indices - i1 += i1_chg; - i2 += i2_chg; - - return {i1, i2, iz}; -} - -//============================================================================== - -Position -HexLattice::get_local_position(Position r, const std::array i_xyz) -const -{ - if (orientation_ == Orientation::y) { - // x_l = x_g - (center + pitch_x*cos(30)*index_x) - r.x -= center_.x - + std::sqrt(3.0)/2.0 * (i_xyz[0] - n_rings_ + 1) * pitch_[0]; - // y_l = y_g - (center + pitch_x*index_x + pitch_y*sin(30)*index_y) - r.y -= (center_.y + (i_xyz[1] - n_rings_ + 1) * pitch_[0] - + (i_xyz[0] - n_rings_ + 1) * pitch_[0] / 2.0); - } else { - // x_l = x_g - (center + pitch_x*index_a + pitch_y*sin(30)*index_y) - r.x -= (center_.x + (i_xyz[0] - n_rings_ + 1) * pitch_[0] - + (i_xyz[1] - n_rings_ + 1) * pitch_[0] / 2.0); - // y_l = y_g - (center + pitch_y*cos(30)*index_y) - r.y -= center_.y - + std::sqrt(3.0)/2.0 * (i_xyz[1] - n_rings_ + 1) * pitch_[0]; - } - - if (is_3d_) { - r.z -= center_.z - (0.5 * n_axial_ - i_xyz[2] - 0.5) * pitch_[1]; - } - - return r; -} - -//============================================================================== - -bool -HexLattice::is_valid_index(int indx) const -{ - int nx {2*n_rings_ - 1}; - int ny {2*n_rings_ - 1}; - int iz = indx / (nx * ny); - int iy = (indx - nx*ny*iz) / nx; - int ix = indx - nx*ny*iz - nx*iy; - int i_xyz[3] {ix, iy, iz}; - return are_valid_indices(i_xyz); -} - -//============================================================================== - -int32_t& -HexLattice::offset(int map, const int i_xyz[3]) -{ - int nx {2*n_rings_ - 1}; - int ny {2*n_rings_ - 1}; - int nz {n_axial_}; - return offsets_[nx*ny*nz*map + nx*ny*i_xyz[2] + nx*i_xyz[1] + i_xyz[0]]; -} - -//============================================================================== - -std::string -HexLattice::index_to_string(int indx) const -{ - int nx {2*n_rings_ - 1}; - int ny {2*n_rings_ - 1}; - int iz {indx / (nx * ny)}; - int iy {(indx - nx * ny * iz) / nx}; - int ix {indx - nx * ny * iz - nx * iy}; - std::string out {std::to_string(ix - n_rings_ + 1)}; - out += ','; - out += std::to_string(iy - n_rings_ + 1); - if (is_3d_) { - out += ','; - out += std::to_string(iz); - } - return out; -} - -//============================================================================== - -void -HexLattice::to_hdf5_inner(hid_t lat_group) const -{ - // Write basic lattice information. - write_string(lat_group, "type", "hexagonal", false); - write_dataset(lat_group, "n_rings", n_rings_); - write_dataset(lat_group, "n_axial", n_axial_); - if (orientation_ == Orientation::y) { - write_string(lat_group, "orientation", "y", false); - } else { - write_string(lat_group, "orientation", "x", false); - } - if (is_3d_) { - write_dataset(lat_group, "pitch", pitch_); - write_dataset(lat_group, "center", center_); - } else { - std::array pitch_short {{pitch_[0]}}; - write_dataset(lat_group, "pitch", pitch_short); - std::array center_short {{center_[0], center_[1]}}; - write_dataset(lat_group, "center", center_short); - } - - // Write the universe ids. - hsize_t nx {static_cast(2*n_rings_ - 1)}; - hsize_t ny {static_cast(2*n_rings_ - 1)}; - hsize_t nz {static_cast(n_axial_)}; - std::vector out(nx*ny*nz); - - for (int m = 0; m < nz; m++) { - for (int k = 0; k < ny; k++) { - for (int j = 0; j < nx; j++) { - int indx = nx*ny*m + nx*k + j; - if (j + k < n_rings_ - 1) { - // This array position is never used; put a -1 to indicate this. - out[indx] = -1; - } else if (j + k > 3*n_rings_ - 3) { - // This array position is never used; put a -1 to indicate this. - out[indx] = -1; - } else { - out[indx] = model::universes[universes_[indx]]->id_; - } - } - } - } - - hsize_t dims[3] {nz, ny, nx}; - write_int(lat_group, 3, dims, "universes", out.data(), false); -} - -//============================================================================== -// Non-method functions -//============================================================================== - -void read_lattices(pugi::xml_node node) -{ - for (pugi::xml_node lat_node : node.children("lattice")) { - model::lattices.push_back(std::make_unique(lat_node)); - } - for (pugi::xml_node lat_node : node.children("hex_lattice")) { - model::lattices.push_back(std::make_unique(lat_node)); - } - - // Fill the lattice map. - for (int i_lat = 0; i_lat < model::lattices.size(); i_lat++) { - int id = model::lattices[i_lat]->id_; - auto in_map = model::lattice_map.find(id); - if (in_map == model::lattice_map.end()) { - model::lattice_map[id] = i_lat; - } else { - std::stringstream err_msg; - err_msg << "Two or more lattices use the same unique ID: " << id; - fatal_error(err_msg); - } - } -} - -} // namespace openmc diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 936c89b78..000000000 --- a/src/main.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifdef OPENMC_MPI -#include -#endif -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/message_passing.h" -#include "openmc/particle_restart.h" -#include "openmc/settings.h" - - -int main(int argc, char* argv[]) { - using namespace openmc; - int err; - - // Initialize run -- when run with MPI, pass communicator -#ifdef OPENMC_MPI - MPI_Comm world {MPI_COMM_WORLD}; - err = openmc_init(argc, argv, &world); -#else - err = openmc_init(argc, argv, nullptr); -#endif - if (err == -1) { - // This happens for the -h and -v flags - return 0; - } else if (err) { - fatal_error(openmc_err_msg); - } - - // start problem based on mode - switch (settings::run_mode) { - case RUN_MODE_FIXEDSOURCE: - case RUN_MODE_EIGENVALUE: - err = openmc_run(); - break; - case RUN_MODE_PLOTTING: - err = openmc_plot_geometry(); - break; - case RUN_MODE_PARTICLE: - if (mpi::master) run_particle_restart(); - err = 0; - break; - case RUN_MODE_VOLUME: - err = openmc_calculate_volumes(); - break; - } - if (err) fatal_error(openmc_err_msg); - - // Finalize and free up memory - err = openmc_finalize(); - if (err) fatal_error(openmc_err_msg); - - // If MPI is in use and enabled, terminate it -#ifdef OPENMC_MPI - MPI_Finalize(); -#endif -} diff --git a/src/material.cpp b/src/material.cpp deleted file mode 100644 index 9a1e206ac..000000000 --- a/src/material.cpp +++ /dev/null @@ -1,1439 +0,0 @@ -#include "openmc/material.h" - -#include // for min, max, sort, fill -#include -#include -#include -#include - -#include "xtensor/xbuilder.hpp" -#include "xtensor/xoperation.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/capi.h" -#include "openmc/cross_sections.h" -#include "openmc/container_util.h" -#include "openmc/dagmc.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/hdf5_interface.h" -#include "openmc/math_functions.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/thermal.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - -std::vector> materials; -std::unordered_map material_map; - -} // namespace model - -//============================================================================== -// Material implementation -//============================================================================== - -Material::Material(pugi::xml_node node) - : index_{model::materials.size()} -{ - if (check_for_node(node, "id")) { - this->set_id(std::stoi(get_node_value(node, "id"))); - } else { - fatal_error("Must specify id of material in materials XML file."); - } - - if (check_for_node(node, "name")) { - name_ = get_node_value(node, "name"); - } - - if (check_for_node(node, "depletable")) { - depletable_ = get_node_value_bool(node, "depletable"); - } - - bool sum_density {false}; - pugi::xml_node density_node = node.child("density"); - std::string units; - if (density_node) { - units = get_node_value(density_node, "units"); - if (units == "sum") { - sum_density = true; - } else if (units == "macro") { - if (check_for_node(density_node, "value")) { - density_ = std::stod(get_node_value(density_node, "value")); - } else { - density_ = 1.0; - } - } else { - double val = std::stod(get_node_value(density_node, "value")); - if (val <= 0.0) { - fatal_error("Need to specify a positive density on material " - + std::to_string(id_) + "."); - } - - if (units == "g/cc" || units == "g/cm3") { - density_ = -val; - } else if (units == "kg/m3") { - density_ = -1.0e-3 * val; - } else if (units == "atom/b-cm") { - density_ = val; - } else if (units == "atom/cc" || units == "atom/cm3") { - density_ = 1.0e-24 * val; - } else { - fatal_error("Unknown units '" + units + "' specified on material " - + std::to_string(id_) + "."); - } - } - } else { - fatal_error("Must specify element in material " - + std::to_string(id_) + "."); - } - - if (node.child("element")) { - fatal_error("Unable to add an element to material " + std::to_string(id_) + - " since the element option has been removed from the xml input. " - "Elements can only be added via the Python API, which will expand " - "elements into their natural nuclides."); - } - - // ======================================================================= - // READ AND PARSE TAGS - - // Check to ensure material has at least one nuclide - if (!check_for_node(node, "nuclide") && !check_for_node(node, "macroscopic")) { - fatal_error("No macroscopic data or nuclides specified on material " - + std::to_string(id_)); - } - - // Create list of macroscopic x/s based on those specified, just treat - // them as nuclides. This is all really a facade so the user thinks they - // are entering in macroscopic data but the code treats them the same - // as nuclides internally. - // Get pointer list of XML - auto node_macros = node.children("macroscopic"); - int num_macros = std::distance(node_macros.begin(), node_macros.end()); - - std::vector names; - std::vector densities; - if (settings::run_CE && num_macros > 0) { - fatal_error("Macroscopic can not be used in continuous-energy mode."); - } else if (num_macros > 1) { - fatal_error("Only one macroscopic object permitted per material, " - + std::to_string(id_)); - } else if (num_macros == 1) { - pugi::xml_node node_nuc = *node_macros.begin(); - - // Check for empty name on nuclide - if (!check_for_node(node_nuc, "name")) { - fatal_error("No name specified on macroscopic data in material " - + std::to_string(id_)); - } - - // store nuclide name - std::string name = get_node_value(node_nuc, "name", false, true); - names.push_back(name); - - // Set density for macroscopic data - if (units == "macro") { - densities.push_back(1.0); - } else { - fatal_error("Units can only be macro for macroscopic data " + name); - } - } else { - // Create list of nuclides based on those specified - for (auto node_nuc : node.children("nuclide")) { - // Check for empty name on nuclide - if (!check_for_node(node_nuc, "name")) { - fatal_error("No name specified on nuclide in material " - + std::to_string(id_)); - } - - // store nuclide name - std::string name = get_node_value(node_nuc, "name", false, true); - names.push_back(name); - - // Check if no atom/weight percents were specified or if both atom and - // weight percents were specified - if (units == "macro") { - densities.push_back(1.0); - } else { - bool has_ao = check_for_node(node_nuc, "ao"); - bool has_wo = check_for_node(node_nuc, "wo"); - - if (!has_ao && !has_wo) { - fatal_error("No atom or weight percent specified for nuclide: " + name); - } else if (has_ao && has_wo) { - fatal_error("Cannot specify both atom and weight percents for a " - "nuclide: " + name); - } - - // Copy atom/weight percents - if (has_ao) { - densities.push_back(std::stod(get_node_value(node_nuc, "ao"))); - } else { - densities.push_back(-std::stod(get_node_value(node_nuc, "wo"))); - } - } - } - } - - // ======================================================================= - // READ AND PARSE element - - std::vector iso_lab; - if (check_for_node(node, "isotropic")) { - iso_lab = get_node_array(node, "isotropic"); - } - - // ======================================================================== - // COPY NUCLIDES TO ARRAYS IN MATERIAL - - // allocate arrays in Material object - auto n = names.size(); - nuclide_.reserve(n); - atom_density_ = xt::empty({n}); - if (settings::photon_transport) element_.reserve(n); - - for (int i = 0; i < n; ++i) { - const auto& name {names[i]}; - - // Check that this nuclide is listed in the cross_sections.xml file - LibraryKey key {Library::Type::neutron, name}; - if (data::library_map.find(key) == data::library_map.end()) { - fatal_error("Could not find nuclide " + name + " in cross_sections.xml."); - } - - // If this nuclide hasn't been encountered yet, we need to add its name - // and alias to the nuclide_dict - if (data::nuclide_map.find(name) == data::nuclide_map.end()) { - int index = data::nuclide_map.size(); - data::nuclide_map[name] = index; - nuclide_.push_back(index); - } else { - nuclide_.push_back(data::nuclide_map[name]); - } - - // If the corresponding element hasn't been encountered yet and photon - // transport will be used, we need to add its symbol to the element_dict - if (settings::photon_transport) { - std::string element = to_element(name); - - // Make sure photon cross section data is available - LibraryKey key {Library::Type::photon, element}; - if (data::library_map.find(key) == data::library_map.end()) { - fatal_error("Could not find element " + element - + " in cross_sections.xml."); - } - - if (data::element_map.find(element) == data::element_map.end()) { - int index = data::element_map.size(); - data::element_map[element] = index; - element_.push_back(index); - } else { - element_.push_back(data::element_map[element]); - } - } - - // Copy atom/weight percent - atom_density_(i) = densities[i]; - } - - if (settings::run_CE) { - // By default, isotropic-in-lab is not used - if (iso_lab.size() > 0) { - p0_.resize(n); - - // Apply isotropic-in-lab treatment to specified nuclides - for (int j = 0; j < n; ++j) { - for (const auto& nuc : iso_lab) { - if (names[j] == nuc) { - p0_[j] = true; - break; - } - } - } - } - } - - // Check to make sure either all atom percents or all weight percents are - // given - if (!(xt::all(atom_density_ >= 0.0) || xt::all(atom_density_ <= 0.0))) { - fatal_error("Cannot mix atom and weight percents in material " - + std::to_string(id_)); - } - - // Determine density if it is a sum value - if (sum_density) density_ = xt::sum(atom_density_)(); - - - if (check_for_node(node, "temperature")) { - temperature_ = std::stod(get_node_value(node, "temperature")); - } - - if (check_for_node(node, "volume")) { - volume_ = std::stod(get_node_value(node, "volume")); - } - - // ======================================================================= - // READ AND PARSE TAG FOR THERMAL SCATTERING DATA - if (settings::run_CE) { - // Loop over elements - - std::vector sab_names; - for (auto node_sab : node.children("sab")) { - // Determine name of thermal scattering table - if (!check_for_node(node_sab, "name")) { - fatal_error("Need to specify for thermal scattering table."); - } - std::string name = get_node_value(node_sab, "name"); - sab_names.push_back(name); - - // Read the fraction of nuclei affected by this thermal scattering table - double fraction = 1.0; - if (check_for_node(node_sab, "fraction")) { - fraction = std::stod(get_node_value(node_sab, "fraction")); - } - - // Check that the thermal scattering table is listed in the - // cross_sections.xml file - LibraryKey key {Library::Type::thermal, name}; - if (data::library_map.find(key) == data::library_map.end()) { - fatal_error("Could not find thermal scattering data " + name + - " in cross_sections.xml file."); - } - - // Determine index of thermal scattering data in global - // data::thermal_scatt array - int index_table; - if (data::thermal_scatt_map.find(name) == data::thermal_scatt_map.end()) { - index_table = data::thermal_scatt_map.size(); - data::thermal_scatt_map[name] = index_table; - } else { - index_table = data::thermal_scatt_map[name]; - } - - // Add entry to thermal tables vector. For now, we put the nuclide index - // as zero since we don't know which nuclides the table is being applied - // to yet (this is assigned in init_thermal) - thermal_tables_.push_back({index_table, 0, fraction}); - } - } -} - -Material::~Material() -{ - model::material_map.erase(id_); -} - -void Material::finalize() -{ - // Set fissionable if any nuclide is fissionable - for (const auto& i_nuc : nuclide_) { - if (data::nuclides[i_nuc]->fissionable_) { - fissionable_ = true; - break; - } - } - - // Generate material bremsstrahlung data for electrons and positrons - if (settings::photon_transport && settings::electron_treatment == ELECTRON_TTB) { - this->init_bremsstrahlung(); - } - - // Assign thermal scattering tables - this->init_thermal(); - - // Normalize density - this->normalize_density(); -} - -void Material::normalize_density() -{ - bool percent_in_atom = (atom_density_(0) >= 0.0); - bool density_in_atom = (density_ >= 0.0); - - for (int i = 0; i < nuclide_.size(); ++i) { - // determine atomic weight ratio - int i_nuc = nuclide_[i]; - double awr = settings::run_CE ? - data::nuclides[i_nuc]->awr_ : data::nuclides_MG[i_nuc].awr; - - // if given weight percent, convert all values so that they are divided - // by awr. thus, when a sum is done over the values, it's actually - // sum(w/awr) - if (!percent_in_atom) atom_density_(i) = -atom_density_(i) / awr; - } - - // determine normalized atom percents. if given atom percents, this is - // straightforward. if given weight percents, the value is w/awr and is - // divided by sum(w/awr) - atom_density_ /= xt::sum(atom_density_)(); - - // Change density in g/cm^3 to atom/b-cm. Since all values are now in - // atom percent, the sum needs to be re-evaluated as 1/sum(x*awr) - if (!density_in_atom) { - double sum_percent = 0.0; - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - double awr = settings::run_CE ? - data::nuclides[i_nuc]->awr_ : data::nuclides_MG[i_nuc].awr; - sum_percent += atom_density_(i)*awr; - } - sum_percent = 1.0 / sum_percent; - density_ = -density_ * N_AVOGADRO / MASS_NEUTRON * sum_percent; - } - - // Calculate nuclide atom densities - atom_density_ *= density_; - - // Calculate density in g/cm^3. - density_gpcc_ = 0.0; - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - double awr = settings::run_CE ? data::nuclides[i_nuc]->awr_ : 1.0; - density_gpcc_ += atom_density_(i) * awr * MASS_NEUTRON / N_AVOGADRO; - } -} - -void Material::init_thermal() -{ - std::vector tables; - - for (const auto& table : thermal_tables_) { - // In order to know which nuclide the S(a,b) table applies to, we need - // to search through the list of nuclides for one which has a matching - // name - bool found = false; - for (int j = 0; j < nuclide_.size(); ++j) { - const auto& name {data::nuclides[nuclide_[j]]->name_}; - if (contains(data::thermal_scatt[table.index_table]->nuclides_, name)) { - tables.push_back({table.index_table, j, table.fraction}); - found = true; - } - } - - // Check to make sure thermal scattering table matched a nuclide - if (!found) { - fatal_error("Thermal scattering table " + data::thermal_scatt[ - table.index_table]->name_ + " did not match any nuclide on material " - + std::to_string(id_)); - } - } - - // Make sure each nuclide only appears in one table. - for (int j = 0; j < tables.size(); ++j) { - for (int k = j+1; k < tables.size(); ++k) { - if (tables[j].index_nuclide == tables[k].index_nuclide) { - int index = nuclide_[tables[j].index_nuclide]; - auto name = data::nuclides[index]->name_; - fatal_error(name + " in material " + std::to_string(id_) + " was found " - "in multiple thermal scattering tables. Each nuclide can appear in " - "only one table per material."); - } - } - } - - // If there are multiple S(a,b) tables, we need to make sure that the - // entries in i_sab_nuclides are sorted or else they won't be applied - // correctly in the cross_section module. - std::sort(tables.begin(), tables.end(), [](ThermalTable a, ThermalTable b) { - return a.index_nuclide < b.index_nuclide; - }); - - // Update the list of thermal tables - thermal_tables_ = tables; -} - -void Material::collision_stopping_power(double* s_col, bool positron) -{ - // Average electron number and average atomic weight - double electron_density = 0.0; - double mass_density = 0.0; - - // Log of the mean excitation energy of the material - double log_I = 0.0; - - // Effective number of conduction electrons in the material - double n_conduction = 0.0; - - // Oscillator strength and square of the binding energy for each oscillator - // in material - std::vector f; - std::vector e_b_sq; - - for (int i = 0; i < element_.size(); ++i) { - const auto& elm = data::elements[element_[i]]; - double awr = data::nuclides[nuclide_[i]]->awr_; - - // Get atomic density of nuclide given atom/weight percent - double atom_density = (atom_density_[0] > 0.0) ? - atom_density_[i] : -atom_density_[i] / awr; - - electron_density += atom_density * elm.Z_; - mass_density += atom_density * awr * MASS_NEUTRON; - log_I += atom_density * elm.Z_ * std::log(elm.I_); - - for (int j = 0; j < elm.n_electrons_.size(); ++j) { - if (elm.n_electrons_[j] < 0) { - n_conduction -= elm.n_electrons_[j] * atom_density; - continue; - } - e_b_sq.push_back(elm.ionization_energy_[j] * elm.ionization_energy_[j]); - f.push_back(elm.n_electrons_[j] * atom_density); - } - } - log_I /= electron_density; - n_conduction /= electron_density; - for (auto& f_i : f) f_i /= electron_density; - - // Get density in g/cm^3 if it is given in atom/b-cm - double density = (density_ < 0.0) ? -density_ : mass_density / N_AVOGADRO; - - // Calculate the square of the plasma energy - double e_p_sq = PLANCK_C * PLANCK_C * PLANCK_C * N_AVOGADRO * - electron_density * density / (2.0 * PI * PI * FINE_STRUCTURE * - MASS_ELECTRON_EV * mass_density); - - // Get the Sternheimer adjustment factor - double rho = sternheimer_adjustment(f, e_b_sq, e_p_sq, n_conduction, log_I, - 1.0e-6, 100); - - // Classical electron radius in cm - constexpr double CM_PER_ANGSTROM {1.0e-8}; - constexpr double r_e = CM_PER_ANGSTROM * PLANCK_C / (2.0 * PI * - FINE_STRUCTURE * MASS_ELECTRON_EV); - - // Constant in expression for collision stopping power - constexpr double BARN_PER_CM_SQ {1.0e24}; - double c = BARN_PER_CM_SQ * 2.0 * PI * r_e * r_e * MASS_ELECTRON_EV * - electron_density; - - // Loop over incident charged particle energies - for (int i = 0; i < data::ttb_e_grid.size(); ++i) { - double E = data::ttb_e_grid(i); - - // Get the density effect correction - double delta = density_effect(f, e_b_sq, e_p_sq, n_conduction, rho, E, - 1.0e-6, 100); - - // Square of the ratio of the speed of light to the velocity of the charged - // particle - double beta_sq = E * (E + 2.0 * MASS_ELECTRON_EV) / ((E + MASS_ELECTRON_EV) - * (E + MASS_ELECTRON_EV)); - - double tau = E / MASS_ELECTRON_EV; - - double F; - if (positron) { - double t = tau + 2.0; - F = std::log(4.0) - (beta_sq / 12.0) * (23.0 + 14.0 / t + 10.0 / (t * t) - + 4.0 / (t * t * t)); - } else { - F = (1.0 - beta_sq) * (1.0 + tau * tau / 8.0 - (2.0 * tau + 1.0) * - std::log(2.0)); - } - - // Calculate the collision stopping power for this energy - s_col[i] = c / beta_sq * (2.0 * (std::log(E) - log_I) + std::log(1.0 + tau - / 2.0) + F - delta); - } -} - -void Material::init_bremsstrahlung() -{ - // Create new object - ttb_ = std::make_unique(); - - // Get the size of the energy grids - auto n_k = data::ttb_k_grid.size(); - auto n_e = data::ttb_e_grid.size(); - - // Determine number of elements - int n = element_.size(); - - for (int particle = 0; particle < 2; ++particle) { - // Loop over logic twice, once for electron, once for positron - BremsstrahlungData* ttb = (particle == 0) ? &ttb_->electron : &ttb_->positron; - bool positron = (particle == 1); - - // Allocate arrays for TTB data - ttb->pdf = xt::zeros({n_e, n_e}); - ttb->cdf = xt::zeros({n_e, n_e}); - ttb->yield = xt::empty({n_e}); - - // Allocate temporary arrays - xt::xtensor stopping_power_collision({n_e}, 0.0); - xt::xtensor stopping_power_radiative({n_e}, 0.0); - xt::xtensor dcs({n_e, n_k}, 0.0); - - double Z_eq_sq = 0.0; - double sum_density = 0.0; - - // Get the collision stopping power of the material - this->collision_stopping_power(stopping_power_collision.data(), positron); - - // Calculate the molecular DCS and the molecular radiative stopping power using - // Bragg's additivity rule. - for (int i = 0; i < n; ++i) { - // Get pointer to current element - const auto& elm = data::elements[element_[i]]; - double awr = data::nuclides[nuclide_[i]]->awr_; - - // Get atomic density and mass density of nuclide given atom/weight percent - double atom_density = (atom_density_[0] > 0.0) ? - atom_density_[i] : -atom_density_[i] / awr; - - // Calculate the "equivalent" atomic number Zeq of the material - Z_eq_sq += atom_density * elm.Z_ * elm.Z_; - sum_density += atom_density; - - // Accumulate material DCS - dcs += (atom_density * elm.Z_ * elm.Z_) * elm.dcs_; - - // Accumulate material radiative stopping power - stopping_power_radiative += atom_density * elm.stopping_power_radiative_; - } - Z_eq_sq /= sum_density; - - // Calculate the positron DCS and radiative stopping power. These are - // obtained by multiplying the electron DCS and radiative stopping powers by - // a factor r, which is a numerical approximation of the ratio of the - // radiative stopping powers for positrons and electrons. Source: F. Salvat, - // J. M. Fernández-Varea, and J. Sempau, "PENELOPE-2011: A Code System for - // Monte Carlo Simulation of Electron and Photon Transport," OECD-NEA, - // Issy-les-Moulineaux, France (2011). - if (positron) { - for (int i = 0; i < n_e; ++i) { - double t = std::log(1.0 + 1.0e6*data::ttb_e_grid(i)/(Z_eq_sq*MASS_ELECTRON_EV)); - double r = 1.0 - std::exp(-1.2359e-1*t + 6.1274e-2*std::pow(t, 2) - - 3.1516e-2*std::pow(t, 3) + 7.7446e-3*std::pow(t, 4) - - 1.0595e-3*std::pow(t, 5) + 7.0568e-5*std::pow(t, 6) - - 1.808e-6*std::pow(t, 7)); - stopping_power_radiative(i) *= r; - auto dcs_i = xt::view(dcs, i, xt::all()); - dcs_i *= r; - } - } - - // Total material stopping power - xt::xtensor stopping_power = stopping_power_collision + - stopping_power_radiative; - - // Loop over photon energies - xt::xtensor f({n_e}, 0.0); - xt::xtensor z({n_e}, 0.0); - for (int i = 0; i < n_e - 1; ++i) { - double w = data::ttb_e_grid(i); - - // Loop over incident particle energies - for (int j = i; j < n_e; ++j) { - double e = data::ttb_e_grid(j); - - // Reduced photon energy - double k = w / e; - - // Find the lower bounding index of the reduced photon energy - int i_k = lower_bound_index(data::ttb_k_grid.cbegin(), - data::ttb_k_grid.cend(), k); - - // Get the interpolation bounds - double k_l = data::ttb_k_grid(i_k); - double k_r = data::ttb_k_grid(i_k + 1); - double x_l = dcs(j, i_k); - double x_r = dcs(j, i_k + 1); - - // Find the value of the DCS using linear interpolation in reduced - // photon energy k - double x = x_l + (k - k_l)*(x_r - x_l)/(k_r - k_l); - - // Square of the ratio of the speed of light to the velocity of the - // charged particle - double beta_sq = e * (e + 2.0 * MASS_ELECTRON_EV) / ((e + - MASS_ELECTRON_EV) * (e + MASS_ELECTRON_EV)); - - // Compute the integrand of the PDF - f(j) = x / (beta_sq * stopping_power(j) * w); - } - - // Number of points to integrate - int n = n_e - i; - - // Integrate the PDF using cubic spline integration over the incident - // particle energy - if (n > 2) { - spline(n, &data::ttb_e_grid(i), &f(i), &z(i)); - - double c = 0.0; - for (int j = i; j < n_e - 1; ++j) { - c += spline_integrate(n, &data::ttb_e_grid(i), &f(i), &z(i), - data::ttb_e_grid(j), data::ttb_e_grid(j+1)); - - ttb->pdf(j+1,i) = c; - } - - // Integrate the last two points using trapezoidal rule in log-log space - } else { - double e_l = std::log(data::ttb_e_grid(i)); - double e_r = std::log(data::ttb_e_grid(i+1)); - double x_l = std::log(f(i)); - double x_r = std::log(f(i+1)); - - ttb->pdf(i+1,i) = 0.5*(e_r - e_l)*(std::exp(e_l + x_l) + std::exp(e_r + x_r)); - } - } - - // Loop over incident particle energies - for (int j = 1; j < n_e; ++j) { - // Set last element of PDF to small non-zero value to enable log-log - // interpolation - ttb->pdf(j,j) = std::exp(-500.0); - - // Loop over photon energies - double c = 0.0; - for (int i = 0; i < j; ++i) { - // Integrate the CDF from the PDF using the trapezoidal rule in log-log - // space - double w_l = std::log(data::ttb_e_grid(i)); - double w_r = std::log(data::ttb_e_grid(i+1)); - double x_l = std::log(ttb->pdf(j,i)); - double x_r = std::log(ttb->pdf(j,i+1)); - - c += 0.5*(w_r - w_l)*(std::exp(w_l + x_l) + std::exp(w_r + x_r)); - ttb->cdf(j,i+1) = c; - } - - // Set photon number yield - ttb->yield(j) = c; - } - - // Use logarithm of number yield since it is log-log interpolated - ttb->yield = xt::where(ttb->yield > 0.0, xt::log(ttb->yield), -500.0); - } -} - -void Material::init_nuclide_index() -{ - int n = settings::run_CE ? - data::nuclides.size() : data::nuclides_MG.size(); - mat_nuclide_index_.resize(n); - std::fill(mat_nuclide_index_.begin(), mat_nuclide_index_.end(), C_NONE); - for (int i = 0; i < nuclide_.size(); ++i) { - mat_nuclide_index_[nuclide_[i]] = i; - } -} - -void Material::calculate_xs(Particle& p) const -{ - // Set all material macroscopic cross sections to zero - p.macro_xs_.total = 0.0; - p.macro_xs_.absorption = 0.0; - p.macro_xs_.fission = 0.0; - p.macro_xs_.nu_fission = 0.0; - - if (p.type_ == Particle::Type::neutron) { - this->calculate_neutron_xs(p); - } else if (p.type_ == Particle::Type::photon) { - this->calculate_photon_xs(p); - } -} - -void Material::calculate_neutron_xs(Particle& p) const -{ - // Find energy index on energy grid - int neutron = static_cast(Particle::Type::neutron); - int i_grid = std::log(p.E_/data::energy_min[neutron])/simulation::log_spacing; - - // Determine if this material has S(a,b) tables - bool check_sab = (thermal_tables_.size() > 0); - - // Initialize position in i_sab_nuclides - int j = 0; - - // Add contribution from each nuclide in material - for (int i = 0; i < nuclide_.size(); ++i) { - // ====================================================================== - // CHECK FOR S(A,B) TABLE - - int i_sab = C_NONE; - double sab_frac = 0.0; - - // Check if this nuclide matches one of the S(a,b) tables specified. - // This relies on thermal_tables_ being sorted by .index_nuclide - if (check_sab) { - const auto& sab {thermal_tables_[j]}; - if (i == sab.index_nuclide) { - // Get index in sab_tables - i_sab = sab.index_table; - sab_frac = sab.fraction; - - // If particle energy is greater than the highest energy for the - // S(a,b) table, then don't use the S(a,b) table - if (p.E_ > data::thermal_scatt[i_sab]->energy_max_) i_sab = C_NONE; - - // Increment position in thermal_tables_ - ++j; - - // Don't check for S(a,b) tables if there are no more left - if (j == thermal_tables_.size()) check_sab = false; - } - } - - // ====================================================================== - // CALCULATE MICROSCOPIC CROSS SECTION - - // Determine microscopic cross sections for this nuclide - int i_nuclide = nuclide_[i]; - - // Calculate microscopic cross section for this nuclide - const auto& micro {p.neutron_xs_[i_nuclide]}; - if (p.E_ != micro.last_E - || p.sqrtkT_ != micro.last_sqrtkT - || i_sab != micro.index_sab - || sab_frac != micro.sab_frac) { - data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p); - } - - // ====================================================================== - // ADD TO MACROSCOPIC CROSS SECTION - - // Copy atom density of nuclide in material - double atom_density = atom_density_(i); - - // Add contributions to cross sections - p.macro_xs_.total += atom_density * micro.total; - p.macro_xs_.absorption += atom_density * micro.absorption; - p.macro_xs_.fission += atom_density * micro.fission; - p.macro_xs_.nu_fission += atom_density * micro.nu_fission; - } -} - -void Material::calculate_photon_xs(Particle& p) const -{ - p.macro_xs_.coherent = 0.0; - p.macro_xs_.incoherent = 0.0; - p.macro_xs_.photoelectric = 0.0; - p.macro_xs_.pair_production = 0.0; - - // Add contribution from each nuclide in material - for (int i = 0; i < nuclide_.size(); ++i) { - // ======================================================================== - // CALCULATE MICROSCOPIC CROSS SECTION - - // Determine microscopic cross sections for this nuclide - int i_element = element_[i]; - - // Calculate microscopic cross section for this nuclide - const auto& micro {p.photon_xs_[i_element]}; - if (p.E_ != micro.last_E) { - data::elements[i_element].calculate_xs(p); - } - - // ======================================================================== - // ADD TO MACROSCOPIC CROSS SECTION - - // Copy atom density of nuclide in material - double atom_density = atom_density_(i); - - // Add contributions to material macroscopic cross sections - p.macro_xs_.total += atom_density * micro.total; - p.macro_xs_.coherent += atom_density * micro.coherent; - p.macro_xs_.incoherent += atom_density * micro.incoherent; - p.macro_xs_.photoelectric += atom_density * micro.photoelectric; - p.macro_xs_.pair_production += atom_density * micro.pair_production; - } -} - -void Material::set_id(int32_t id) -{ - Expects(id >= -1); - - // Clear entry in material map if an ID was already assigned before - if (id_ != -1) { - model::material_map.erase(id_); - id_ = -1; - } - - // Make sure no other material has same ID - if (model::material_map.find(id) != model::material_map.end()) { - throw std::runtime_error{"Two materials have the same ID: " + std::to_string(id)}; - } - - // If no ID specified, auto-assign next ID in sequence - if (id == -1) { - id = 0; - for (const auto& m : model::materials) { - id = std::max(id, m->id_); - } - ++id; - } - - // Update ID and entry in material map - id_ = id; - model::material_map[id] = index_; -} - -void Material::set_density(double density, gsl::cstring_span units) -{ - Expects(density >= 0.0); - - if (nuclide_.empty()) { - throw std::runtime_error{"No nuclides exist in material yet."}; - } - - if (units == "atom/b-cm") { - // Set total density based on value provided - density_ = density; - - // Determine normalized atom percents - double sum_percent = xt::sum(atom_density_)(); - atom_density_ /= sum_percent; - - // Recalculate nuclide atom densities based on given density - atom_density_ *= density; - - // Calculate density in g/cm^3. - density_gpcc_ = 0.0; - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - double awr = data::nuclides[i_nuc]->awr_; - density_gpcc_ += atom_density_(i) * awr * MASS_NEUTRON / N_AVOGADRO; - } - } else if (units == "g/cm3" || units == "g/cc") { - // Determine factor by which to change densities - double previous_density_gpcc = density_gpcc_; - double f = density / previous_density_gpcc; - - // Update densities - density_gpcc_ = density; - density_ *= f; - atom_density_ *= f; - } else { - throw std::invalid_argument{"Invalid units '" + std::string(units.data()) - + "' specified."}; - } -} - -void Material::set_densities(const std::vector& name, - const std::vector& density) -{ - auto n = name.size(); - Expects(n > 0); - Expects(n == density.size()); - - if (n != nuclide_.size()) { - nuclide_.resize(n); - atom_density_ = xt::zeros({n}); - } - - double sum_density = 0.0; - for (gsl::index i = 0; i < n; ++i) { - const auto& nuc {name[i]}; - if (data::nuclide_map.find(nuc) == data::nuclide_map.end()) { - int err = openmc_load_nuclide(nuc.c_str()); - if (err < 0) throw std::runtime_error{openmc_err_msg}; - } - - nuclide_[i] = data::nuclide_map.at(nuc); - Expects(density[i] > 0.0); - atom_density_(i) = density[i]; - sum_density += density[i]; - } - - // Set total density to the sum of the vector - this->set_density(sum_density, "atom/b-cm"); - - // Assign S(a,b) tables - this->init_thermal(); -} - -double Material::volume() const -{ - if (volume_ < 0.0) { - throw std::runtime_error{"Volume for material with ID=" - + std::to_string(id_) + " not set."}; - } - return volume_; -} - -void Material::to_hdf5(hid_t group) const -{ - hid_t material_group = create_group(group, "material " + std::to_string(id_)); - - write_attribute(material_group, "depletable", static_cast(depletable_)); - if (volume_ > 0.0) { - write_attribute(material_group, "volume", volume_); - } - if (temperature_ > 0.0) { - write_attribute(material_group, "temperature", temperature_); - } - write_dataset(material_group, "name", name_); - write_dataset(material_group, "atom_density", density_); - - // Copy nuclide/macro name for each nuclide to vector - std::vector nuc_names; - std::vector macro_names; - std::vector nuc_densities; - if (settings::run_CE) { - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - nuc_names.push_back(data::nuclides[i_nuc]->name_); - nuc_densities.push_back(atom_density_(i)); - } - } else { - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - if (data::nuclides_MG[i_nuc].awr != MACROSCOPIC_AWR) { - nuc_names.push_back(data::nuclides_MG[i_nuc].name); - nuc_densities.push_back(atom_density_(i)); - } else { - macro_names.push_back(data::nuclides_MG[i_nuc].name); - } - } - } - - // Write vector to 'nuclides' - if (!nuc_names.empty()) { - write_dataset(material_group, "nuclides", nuc_names); - write_dataset(material_group, "nuclide_densities", nuc_densities); - } - - // Write vector to 'macroscopics' - if (!macro_names.empty()) { - write_dataset(material_group, "macroscopics", macro_names); - } - - if (!thermal_tables_.empty()) { - std::vector sab_names; - for (const auto& table : thermal_tables_) { - sab_names.push_back(data::thermal_scatt[table.index_table]->name_); - } - write_dataset(material_group, "sab_names", sab_names); - } - - close_group(material_group); -} - -void Material::add_nuclide(const std::string& name, double density) -{ - // Check if nuclide is already in material - for (int i = 0; i < nuclide_.size(); ++i) { - int i_nuc = nuclide_[i]; - if (data::nuclides[i_nuc]->name_ == name) { - double awr = data::nuclides[i_nuc]->awr_; - density_ += density - atom_density_(i); - density_gpcc_ += (density - atom_density_(i)) - * awr * MASS_NEUTRON / N_AVOGADRO; - atom_density_(i) = density; - return; - } - } - - // If nuclide wasn't found, extend nuclide/density arrays - int err = openmc_load_nuclide(name.c_str()); - if (err < 0) throw std::runtime_error{openmc_err_msg}; - - // Append new nuclide/density - int i_nuc = data::nuclide_map[name]; - nuclide_.push_back(i_nuc); - - auto n = nuclide_.size(); - - // Create copy of atom_density_ array with one extra entry - xt::xtensor atom_density = xt::zeros({n}); - xt::view(atom_density, xt::range(0, n-1)) = atom_density_; - atom_density(n-1) = density; - atom_density_ = atom_density; - - density_ += density; - density_gpcc_ += density * data::nuclides[i_nuc]->awr_ - * MASS_NEUTRON / N_AVOGADRO; -} - -//============================================================================== -// Non-method functions -//============================================================================== - -double sternheimer_adjustment(const std::vector& f, const - std::vector& e_b_sq, double e_p_sq, double n_conduction, double - log_I, double tol, int max_iter) -{ - // Get the total number of oscillators - int n = f.size(); - - // Calculate the Sternheimer adjustment factor using Newton's method - double rho = 2.0; - int iter; - for (iter = 0; iter < max_iter; ++iter) { - double rho_0 = rho; - - // Function to find the root of and its derivative - double g = 0.0; - double gp = 0.0; - - for (int i = 0; i < n; ++i) { - // Square of resonance energy of a bound-shell oscillator - double e_r_sq = e_b_sq[i] * rho * rho + 2.0 / 3.0 * f[i] * e_p_sq; - g += f[i] * std::log(e_r_sq); - gp += e_b_sq[i] * f[i] * rho / e_r_sq; - } - // Include conduction electrons - if (n_conduction > 0.0) { - g += n_conduction * std::log(n_conduction * e_p_sq); - } - - // Set the next guess: rho_n+1 = rho_n - g(rho_n)/g'(rho_n) - rho -= (g - 2.0 * log_I) / (2.0 * gp); - - // If the initial guess is too large, rho can be negative - if (rho < 0.0) rho = rho_0 / 2.0; - - // Check for convergence - if (std::abs(rho - rho_0) / rho_0 < tol) break; - } - // Did not converge - if (iter >= max_iter) { - warning("Maximum Newton-Raphson iterations exceeded."); - rho = 1.0e-6; - } - return rho; -} - -double density_effect(const std::vector& f, const std::vector& - e_b_sq, double e_p_sq, double n_conduction, double rho, double E, double tol, - int max_iter) -{ - // Get the total number of oscillators - int n = f.size(); - - // Square of the ratio of the speed of light to the velocity of the charged - // particle - double beta_sq = E * (E + 2.0 * MASS_ELECTRON_EV) / ((E + MASS_ELECTRON_EV) * - (E + MASS_ELECTRON_EV)); - - // For nonmetals, delta = 0 for beta < beta_0, where beta_0 is obtained by - // setting the frequency w = 0. - double beta_0_sq = 0.0; - if (n_conduction == 0.0) { - for (int i = 0; i < n; ++i) { - beta_0_sq += f[i] * e_p_sq / (e_b_sq[i] * rho * rho); - } - beta_0_sq = 1.0 / (1.0 + beta_0_sq); - } - double delta = 0.0; - if (beta_sq < beta_0_sq) return delta; - - // Compute the square of the frequency w^2 using Newton's method, with the - // initial guess of w^2 equal to beta^2 * gamma^2 - double w_sq = E / MASS_ELECTRON_EV * (E / MASS_ELECTRON_EV + 2); - int iter; - for (iter = 0; iter < max_iter; ++iter) { - double w_sq_0 = w_sq; - - // Function to find the root of and its derivative - double g = 0.0; - double gp = 0.0; - - for (int i = 0; i < n; ++i) { - double c = e_b_sq[i] * rho * rho / e_p_sq + w_sq; - g += f[i] / c; - gp -= f[i] / (c * c); - } - // Include conduction electrons - g += n_conduction / w_sq; - gp -= n_conduction / (w_sq * w_sq); - - // Set the next guess: w_n+1 = w_n - g(w_n)/g'(w_n) - w_sq -= (g + 1.0 - 1.0 / beta_sq) / gp; - - // If the initial guess is too large, w can be negative - if (w_sq < 0.0) w_sq = w_sq_0 / 2.0; - - // Check for convergence - if (std::abs(w_sq - w_sq_0) / w_sq_0 < tol) break; - } - // Did not converge - if (iter >= max_iter) { - warning("Maximum Newton-Raphson iterations exceeded: setting density " - "effect correction to zero."); - return delta; - } - - // Solve for the density effect correction - for (int i = 0; i < n; ++i) { - double l_sq = e_b_sq[i] * rho * rho / e_p_sq + 2.0 / 3.0 * f[i]; - delta += f[i] * std::log((l_sq + w_sq)/l_sq); - } - // Include conduction electrons - if (n_conduction > 0.0) { - delta += n_conduction * std::log((n_conduction + w_sq) / n_conduction); - } - - return delta - w_sq * (1.0 - beta_sq); -} - -void read_materials_xml() -{ - write_message("Reading materials XML file...", 5); - - pugi::xml_document doc; - - bool using_dagmc_mats = false; -#ifdef DAGMC - if (settings::dagmc) { - using_dagmc_mats = read_uwuw_materials(doc); - } -#endif - - - if (!using_dagmc_mats) { - // Check if materials.xml exists - std::string filename = settings::path_input + "materials.xml"; - if (!file_exists(filename)) { - fatal_error("Material XML file '" + filename + "' does not exist!"); - } - - // Parse materials.xml file and get root element - doc.load_file(filename.c_str()); - } - - // Loop over XML material elements and populate the array. - pugi::xml_node root = doc.document_element(); - for (pugi::xml_node material_node : root.children("material")) { - model::materials.push_back(std::make_unique(material_node)); - } - model::materials.shrink_to_fit(); -} - -void free_memory_material() -{ - model::materials.clear(); - model::material_map.clear(); -} - -//============================================================================== -// C API -//============================================================================== - -extern "C" int -openmc_get_material_index(int32_t id, int32_t* index) -{ - auto it = model::material_map.find(id); - if (it == model::material_map.end()) { - set_errmsg("No material exists with ID=" + std::to_string(id) + "."); - return OPENMC_E_INVALID_ID; - } else { - *index = it->second; - return 0; - } -} - -extern "C" int -openmc_material_add_nuclide(int32_t index, const char* name, double density) -{ - int err = 0; - if (index >= 0 && index < model::materials.size()) { - try { - model::materials[index]->add_nuclide(name, density); - } catch (const std::runtime_error& e) { - return OPENMC_E_DATA; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return err; -} - -extern "C" int -openmc_material_get_densities(int32_t index, const int** nuclides, const double** densities, int* n) -{ - if (index >= 0 && index < model::materials.size()) { - auto& mat = model::materials[index]; - if (!mat->nuclides().empty()) { - *nuclides = mat->nuclides().data(); - *densities = mat->densities().data(); - *n = mat->nuclides().size(); - return 0; - } else { - set_errmsg("Material atom density array has not been allocated."); - return OPENMC_E_ALLOCATE; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_material_get_density(int32_t index, double* density) -{ - if (index >= 0 && index < model::materials.size()) { - auto& mat = model::materials[index]; - *density = mat->density_gpcc(); - return 0; - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_material_get_fissionable(int32_t index, bool* fissionable) -{ - if (index >= 0 && index < model::materials.size()) { - *fissionable = model::materials[index]->fissionable(); - return 0; - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_material_get_id(int32_t index, int32_t* id) -{ - if (index >= 0 && index < model::materials.size()) { - *id = model::materials[index]->id(); - return 0; - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_material_get_volume(int32_t index, double* volume) -{ - if (index >= 0 && index < model::materials.size()) { - try { - *volume = model::materials[index]->volume(); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - return 0; - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_material_set_density(int32_t index, double density, const char* units) -{ - if (index >= 0 && index < model::materials.size()) { - try { - model::materials[index]->set_density(density, units); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_material_set_densities(int32_t index, int n, const char** name, const double* density) -{ - if (index >= 0 && index < model::materials.size()) { - try { - model::materials[index]->set_densities({name, name + n}, {density, density + n}); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_material_set_id(int32_t index, int32_t id) -{ - if (index >= 0 && index < model::materials.size()) { - try { - model::materials.at(index)->set_id(id); - } catch (const std::exception& e) { - set_errmsg(e.what()); - return OPENMC_E_UNASSIGNED; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_material_get_name(int32_t index, const char** name) { - if (index < 0 || index >= model::materials.size()) { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *name = model::materials[index]->name().data(); - - return 0; -} - -extern "C" int -openmc_material_set_name(int32_t index, const char* name) { - if (index < 0 || index >= model::materials.size()) { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - model::materials[index]->set_name(name); - - return 0; -} - -extern "C" int -openmc_material_set_volume(int32_t index, double volume) -{ - if (index >= 0 && index < model::materials.size()) { - auto& m {model::materials[index]}; - if (volume >= 0.0) { - m->volume_ = volume; - return 0; - } else { - set_errmsg("Volume must be non-negative"); - return OPENMC_E_INVALID_ARGUMENT; - } - } else { - set_errmsg("Index in materials array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -extern "C" int -openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end) -{ - if (index_start) *index_start = model::materials.size(); - if (index_end) *index_end = model::materials.size() + n - 1; - for (int32_t i = 0; i < n; i++) { - model::materials.push_back(std::make_unique()); - } - return 0; -} - -extern "C" size_t n_materials() { return model::materials.size(); } - -} // namespace openmc diff --git a/src/math_functions.cpp b/src/math_functions.cpp deleted file mode 100644 index 7525a7ddd..000000000 --- a/src/math_functions.cpp +++ /dev/null @@ -1,896 +0,0 @@ -#include "openmc/math_functions.h" - -#include "Faddeeva.hh" - -namespace openmc { - -//============================================================================== -// Mathematical methods -//============================================================================== - -double normal_percentile(double p) -{ - constexpr double p_low = 0.02425; - constexpr double a[6] = {-3.969683028665376e1, 2.209460984245205e2, - -2.759285104469687e2, 1.383577518672690e2, - -3.066479806614716e1, 2.506628277459239e0}; - constexpr double b[5] = {-5.447609879822406e1, 1.615858368580409e2, - -1.556989798598866e2, 6.680131188771972e1, - -1.328068155288572e1}; - constexpr double c[6] = {-7.784894002430293e-3, -3.223964580411365e-1, - -2.400758277161838, -2.549732539343734, - 4.374664141464968, 2.938163982698783}; - constexpr double d[4] = {7.784695709041462e-3, 3.224671290700398e-1, - 2.445134137142996, 3.754408661907416}; - - // The rational approximation used here is from an unpublished work at - // http://home.online.no/~pjacklam/notes/invnorm/ - - double z; - double q; - - if (p < p_low) { - // Rational approximation for lower region. - - q = std::sqrt(-2.0 * std::log(p)); - z = (((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]) / - ((((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0); - - } else if (p <= 1.0 - p_low) { - // Rational approximation for central region - q = p - 0.5; - double r = q * q; - z = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q / - (((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0); - - } else { - // Rational approximation for upper region - - q = std::sqrt(-2.0*std::log(1.0 - p)); - z = -(((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]) / - ((((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0); - } - - // Refinement based on Newton's method - - z = z - (0.5 * std::erfc(-z / std::sqrt(2.0)) - p) * std::sqrt(2.0 * PI) * - std::exp(0.5 * z * z); - - return z; - -} - - -double t_percentile(double p, int df) -{ - double t; - - if (df == 1) { - // For one degree of freedom, the t-distribution becomes a Cauchy - // distribution whose cdf we can invert directly - - t = std::tan(PI*(p - 0.5)); - } else if (df == 2) { - // For two degrees of freedom, the cdf is given by 1/2 + x/(2*sqrt(x^2 + - // 2)). This can be directly inverted to yield the solution below - - t = 2.0 * std::sqrt(2.0)*(p - 0.5) / - std::sqrt(1. - 4. * std::pow(p - 0.5, 2.)); - } else { - // This approximation is from E. Olusegun George and Meenakshi Sivaram, "A - // modification of the Fisher-Cornish approximation for the student t - // percentiles," Communication in Statistics - Simulation and Computation, - // 16 (4), pp. 1123-1132 (1987). - double n = df; - double k = 1. / (n - 2.); - double z = normal_percentile(p); - double z2 = z * z; - t = std::sqrt(n * k) * (z + (z2 - 3.) * z * k / 4. + ((5. * z2 - 56.) * z2 + - 75.) * z * k * k / 96. + (((z2 - 27.) * 3. * z2 + 417.) * z2 - 315.) * - z * k * k * k / 384.); - } - - return t; -} - - -void calc_pn_c(int n, double x, double pnx[]) -{ - pnx[0] = 1.; - if (n >= 1) { - pnx[1] = x; - } - - // Use recursion relation to build the higher orders - for (int l = 1; l < n; l++) { - pnx[l + 1] = ((2 * l + 1) * x * pnx[l] - l * pnx[l - 1]) / (l + 1); - } -} - - -double evaluate_legendre(int n, const double data[], double x) -{ - double* pnx = new double[n + 1]; - double val = 0.0; - calc_pn_c(n, x, pnx); - for (int l = 0; l <= n; l++) { - val += (l + 0.5) * data[l] * pnx[l]; - } - delete[] pnx; - return val; -} - - -void calc_rn_c(int n, const double uvw[3], double rn[]) -{ - Direction u {uvw}; - calc_rn(n, u, rn); -} - - -void calc_rn(int n, Direction u, double rn[]) -{ - // rn[] is assumed to have already been allocated to the correct size - - // Store the cosine of the polar angle and the azimuthal angle - double w = u.z; - double phi; - if (u.x == 0.) { - phi = 0.; - } else { - phi = std::atan2(u.y, u.x); - } - - // Store the shorthand of 1-w * w - double w2m1 = 1. - w * w; - - // Now evaluate the spherical harmonics function - rn[0] = 1.; - int i = 0; - for (int l = 1; l <= n; l++) { - // Set the index to the start of this order - i += 2 * (l - 1) + 1; - - // Now evaluate each - switch (l) { - case 1: - // l = 1, m = -1 - rn[i] = -(std::sqrt(w2m1) * std::sin(phi)); - // l = 1, m = 0 - rn[i + 1] = w; - // l = 1, m = 1 - rn[i + 2] = -(std::sqrt(w2m1) * std::cos(phi)); - break; - case 2: - // l = 2, m = -2 - rn[i] = 0.288675134594813 * (-3. * w * w + 3.) * std::sin(2. * phi); - // l = 2, m = -1 - rn[i + 1] = -(1.73205080756888 * w*std::sqrt(w2m1) * std::sin(phi)); - // l = 2, m = 0 - rn[i + 2] = 1.5 * w * w - 0.5; - // l = 2, m = 1 - rn[i + 3] = -(1.73205080756888 * w*std::sqrt(w2m1) * std::cos(phi)); - // l = 2, m = 2 - rn[i + 4] = 0.288675134594813 * (-3. * w * w + 3.) * std::cos(2. * phi); - break; - case 3: - // l = 3, m = -3 - rn[i] = -(0.790569415042095 * std::pow(w2m1, 1.5) * std::sin(3. * phi)); - // l = 3, m = -2 - rn[i + 1] = 1.93649167310371 * w*(w2m1) * std::sin(2.*phi); - // l = 3, m = -1 - rn[i + 2] = -(0.408248290463863*std::sqrt(w2m1)*((7.5)*w * w - 3./2.) * - std::sin(phi)); - // l = 3, m = 0 - rn[i + 3] = 2.5 * std::pow(w, 3) - 1.5 * w; - // l = 3, m = 1 - rn[i + 4] = -(0.408248290463863*std::sqrt(w2m1)*((7.5)*w * w - 3./2.) * - std::cos(phi)); - // l = 3, m = 2 - rn[i + 5] = 1.93649167310371 * w*(w2m1) * std::cos(2.*phi); - // l = 3, m = 3 - rn[i + 6] = -(0.790569415042095 * std::pow(w2m1, 1.5) * std::cos(3.* phi)); - break; - case 4: - // l = 4, m = -4 - rn[i] = 0.739509972887452 * (w2m1 * w2m1) * std::sin(4.0*phi); - // l = 4, m = -3 - rn[i + 1] = -(2.09165006633519 * w * std::pow(w2m1, 1.5) * std::sin(3.* phi)); - // l = 4, m = -2 - rn[i + 2] = 0.074535599249993 * (w2m1)*(52.5 * w * w - 7.5) * std::sin(2. *phi); - // l = 4, m = -1 - rn[i + 3] = -(0.316227766016838*std::sqrt(w2m1)*(17.5 * std::pow(w, 3) - 7.5 * w) * - std::sin(phi)); - // l = 4, m = 0 - rn[i + 4] = 4.375 * std::pow(w, 4) - 3.75 * w * w + 0.375; - // l = 4, m = 1 - rn[i + 5] = -(0.316227766016838*std::sqrt(w2m1)*(17.5 * std::pow(w, 3) - 7.5*w) * - std::cos(phi)); - // l = 4, m = 2 - rn[i + 6] = 0.074535599249993 * (w2m1)*(52.5*w * w - 7.5) * std::cos(2.*phi); - // l = 4, m = 3 - rn[i + 7] = -(2.09165006633519 * w * std::pow(w2m1, 1.5) * std::cos(3.* phi)); - // l = 4, m = 4 - rn[i + 8] = 0.739509972887452 * w2m1 * w2m1 * std::cos(4.0*phi); - break; - case 5: - // l = 5, m = -5 - rn[i] = -(0.701560760020114 * std::pow(w2m1, 2.5) * std::sin(5.0 * phi)); - // l = 5, m = -4 - rn[i + 1] = 2.21852991866236 * w * w2m1 * w2m1 * std::sin(4.0 * phi); - // l = 5, m = -3 - rn[i + 2] = -(0.00996023841111995 * std::pow(w2m1, 1.5) * - ((945.0 /2.)* w * w - 52.5) * std::sin(3.*phi)); - // l = 5, m = -2 - rn[i + 3] = 0.0487950036474267 * (w2m1) - * ((315.0/2.)* std::pow(w, 3) - 52.5 * w) * std::sin(2.*phi); - // l = 5, m = -1 - rn[i + 4] = -(0.258198889747161*std::sqrt(w2m1) * - (39.375 * std::pow(w, 4) - 105.0/4.0 * w * w + 15.0/8.0) * std::sin(phi)); - // l = 5, m = 0 - rn[i + 5] = 7.875 * std::pow(w, 5) - 8.75 * std::pow(w, 3) + 1.875 * w; - // l = 5, m = 1 - rn[i + 6] = -(0.258198889747161 * std::sqrt(w2m1)* - (39.375 * std::pow(w, 4) - 105.0/4.0 * w * w + 15.0/8.0) * std::cos(phi)); - // l = 5, m = 2 - rn[i + 7] = 0.0487950036474267 * (w2m1) * - ((315.0 / 2.) * std::pow(w, 3) - 52.5*w) * std::cos(2.*phi); - // l = 5, m = 3 - rn[i + 8] = -(0.00996023841111995 * std::pow(w2m1, 1.5) * - ((945.0 / 2.) * w * w - 52.5) * std::cos(3.*phi)); - // l = 5, m = 4 - rn[i + 9] = 2.21852991866236 * w * w2m1 * w2m1 * std::cos(4.0*phi); - // l = 5, m = 5 - rn[i + 10] = -(0.701560760020114 * std::pow(w2m1, 2.5) * std::cos(5.0* phi)); - break; - case 6: - // l = 6, m = -6 - rn[i] = 0.671693289381396 * std::pow(w2m1, 3) * std::sin(6.0*phi); - // l = 6, m = -5 - rn[i + 1] = -(2.32681380862329 * w*std::pow(w2m1, 2.5) * std::sin(5.0*phi)); - // l = 6, m = -4 - rn[i + 2] = 0.00104990131391452 * w2m1 * w2m1 * - ((10395.0/2.) * w * w - 945.0/2.) * std::sin(4.0 * phi); - // l = 6, m = -3 - rn[i + 3] = -(0.00575054632785295 * std::pow(w2m1, 1.5) * - ((3465.0/2.) * std::pow(w, 3) - 945.0/2.*w) * std::sin(3.*phi)); - // l = 6, m = -2 - rn[i + 4] = 0.0345032779671177 * (w2m1) * - ((3465.0/8.0)* std::pow(w, 4) - 945.0/4.0 * w * w + 105.0/8.0) * - std::sin(2. * phi); - // l = 6, m = -1 - rn[i + 5] = -(0.218217890235992*std::sqrt(w2m1) * - ((693.0/8.0)* std::pow(w, 5)- 315.0/4.0 * std::pow(w, 3) + (105.0/8.0)*w) * - std::sin(phi)); - // l = 6, m = 0 - rn[i + 6] = 14.4375 * std::pow(w, 6) - 19.6875 * std::pow(w, 4) + 6.5625 * w * w - - 0.3125; - // l = 6, m = 1 - rn[i + 7] = -(0.218217890235992*std::sqrt(w2m1) * - ((693.0/8.0)* std::pow(w, 5)- 315.0/4.0 * std::pow(w, 3) + (105.0/8.0)*w) * - std::cos(phi)); - // l = 6, m = 2 - rn[i + 8] = 0.0345032779671177 * w2m1 * - ((3465.0/8.0)* std::pow(w, 4) -945.0/4.0 * w * w + 105.0/8.0) * - std::cos(2.*phi); - // l = 6, m = 3 - rn[i + 9] = -(0.00575054632785295 * std::pow(w2m1, 1.5) * - ((3465.0/2.) * std::pow(w, 3) - 945.0/2.*w) * std::cos(3.*phi)); - // l = 6, m = 4 - rn[i + 10] = 0.00104990131391452 * w2m1 * w2m1 * - ((10395.0/2.)*w * w - 945.0/2.) * std::cos(4.0*phi); - // l = 6, m = 5 - rn[i + 11] = -(2.32681380862329 * w * std::pow(w2m1, 2.5) * std::cos(5.0*phi)); - // l = 6, m = 6 - rn[i + 12] = 0.671693289381396 * std::pow(w2m1, 3) * std::cos(6.0*phi); - break; - case 7: - // l = 7, m = -7 - rn[i] = -(0.647259849287749 * std::pow(w2m1, 3.5) * std::sin(7.0*phi)); - // l = 7, m = -6 - rn[i + 1] = 2.42182459624969 * w*std::pow(w2m1, 3) * std::sin(6.0*phi); - // l = 7, m = -5 - rn[i + 2] = -(9.13821798555235e-5*std::pow(w2m1, 2.5) * - ((135135.0/2.)*w * w - 10395.0/2.) * std::sin(5.0*phi)); - // l = 7, m = -4 - rn[i + 3] = 0.000548293079133141 * w2m1 * w2m1 * - ((45045.0/2.)*std::pow(w, 3) - 10395.0/2.*w) * std::sin(4.0*phi); - // l = 7, m = -3 - rn[i + 4] = -(0.00363696483726654 * std::pow(w2m1, 1.5) * - ((45045.0/8.0)* std::pow(w, 4) - 10395.0/4.0 * w * w + 945.0/8.0) * - std::sin(3.*phi)); - // l = 7, m = -2 - rn[i + 5] = 0.025717224993682 * (w2m1) * - ((9009.0/8.0)* std::pow(w, 5) -3465.0/4.0 * std::pow(w, 3) + (945.0/8.0)*w) * - std::sin(2.*phi); - // l = 7, m = -1 - rn[i + 6] = -(0.188982236504614*std::sqrt(w2m1) * - ((3003.0/16.0)* std::pow(w, 6) - 3465.0/16.0 * std::pow(w, 4) + - (945.0/16.0)*w * w - 35.0/16.0) * std::sin(phi)); - // l = 7, m = 0 - rn[i + 7] = 26.8125 * std::pow(w, 7) - 43.3125 * std::pow(w, 5) + 19.6875 * std::pow(w, 3) - - 2.1875 * w; - // l = 7, m = 1 - rn[i + 8] = -(0.188982236504614*std::sqrt(w2m1) * ((3003.0/16.0) * std::pow(w, 6) - - 3465.0/16.0 * std::pow(w, 4) + (945.0/16.0)*w * w - 35.0/16.0) * std::cos(phi)); - // l = 7, m = 2 - rn[i + 9] = 0.025717224993682 * (w2m1) * ((9009.0/8.0)* std::pow(w, 5) - - 3465.0/4.0 * std::pow(w, 3) + (945.0/8.0)*w) * std::cos(2.*phi); - // l = 7, m = 3 - rn[i + 10] = -(0.00363696483726654 * std::pow(w2m1, 1.5) * - ((45045.0/8.0)* std::pow(w, 4) - 10395.0/4.0 * w * w + 945.0/8.0) * - std::cos(3.*phi)); - // l = 7, m = 4 - rn[i + 11] = 0.000548293079133141 * w2m1 * w2m1 * - ((45045.0/2.)*std::pow(w, 3) - 10395.0/2.*w) * std::cos(4.0*phi); - // l = 7, m = 5 - rn[i + 12] = -(9.13821798555235e-5*std::pow(w2m1, 2.5) * - ((135135.0/2.)*w * w - 10395.0/2.) * std::cos(5.0*phi)); - // l = 7, m = 6 - rn[i + 13] = 2.42182459624969 * w*std::pow(w2m1, 3) * std::cos(6.0*phi); - // l = 7, m = 7 - rn[i + 14] = -(0.647259849287749 * std::pow(w2m1, 3.5) * std::cos(7.0*phi)); - break; - case 8: - // l = 8, m = -8 - rn[i] = 0.626706654240044 * std::pow(w2m1, 4) * std::sin(8.0*phi); - // l = 8, m = -7 - rn[i + 1] = -(2.50682661696018 * w*std::pow(w2m1, 3.5) * std::sin(7.0*phi)); - // l = 8, m = -6 - rn[i + 2] = 6.77369783729086e-6*std::pow(w2m1, 3)* - ((2027025.0/2.)*w * w - 135135.0/2.) * std::sin(6.0*phi); - // l = 8, m = -5 - rn[i + 3] = -(4.38985792528482e-5*std::pow(w2m1, 2.5) * - ((675675.0/2.)*std::pow(w, 3) - 135135.0/2.*w) * std::sin(5.0*phi)); - // l = 8, m = -4 - rn[i + 4] = 0.000316557156832328 * w2m1 * w2m1 * - ((675675.0/8.0)* std::pow(w, 4) - 135135.0/4.0 * w * w + 10395.0/8.0) * - std::sin(4.0*phi); - // l = 8, m = -3 - rn[i + 5] = -(0.00245204119306875 * std::pow(w2m1, 1.5) * ((135135.0/8.0) * - std::pow(w, 5) - 45045.0/4.0 * std::pow(w, 3) + (10395.0/8.0)*w) * std::sin(3.*phi)); - // l = 8, m = -2 - rn[i + 6] = 0.0199204768222399 * (w2m1) * - ((45045.0/16.0)* std::pow(w, 6)- 45045.0/16.0 * std::pow(w, 4) + - (10395.0/16.0)*w * w - 315.0/16.0) * std::sin(2.*phi); - // l = 8, m = -1 - rn[i + 7] = -(0.166666666666667*std::sqrt(w2m1) * - ((6435.0/16.0)* std::pow(w, 7) - 9009.0/16.0 * std::pow(w, 5) + - (3465.0/16.0)*std::pow(w, 3) - 315.0/16.0 * w) * std::sin(phi)); - // l = 8, m = 0 - rn[i + 8] = 50.2734375 * std::pow(w, 8) - 93.84375 * std::pow(w, 6) + 54.140625 * - std::pow(w, 4) - 9.84375 * w * w + 0.2734375; - // l = 8, m = 1 - rn[i + 9] = -(0.166666666666667*std::sqrt(w2m1) * - ((6435.0/16.0)* std::pow(w, 7) - 9009.0/16.0 * std::pow(w, 5) + - (3465.0/16.0)*std::pow(w, 3) - 315.0/16.0 * w) * std::cos(phi)); - // l = 8, m = 2 - rn[i + 10] = 0.0199204768222399 * (w2m1)*((45045.0/16.0)* std::pow(w, 6)- - 45045.0/16.0 * std::pow(w, 4) + (10395.0/16.0)*w * w - - 315.0/16.0) * std::cos(2.*phi); - // l = 8, m = 3 - rn[i + 11] = -(0.00245204119306875 * std::pow(w2m1, 1.5)* - ((135135.0/8.0) * std::pow(w, 5) - 45045.0/4.0 * std::pow(w, 3) + - (10395.0/8.0)*w) * std::cos(3.*phi)); - // l = 8, m = 4 - rn[i + 12] = 0.000316557156832328 * w2m1 * w2m1*((675675.0/8.0)* std::pow(w, 4) - - 135135.0/4.0 * w * w + 10395.0/8.0) * std::cos(4.0*phi); - // l = 8, m = 5 - rn[i + 13] = -(4.38985792528482e-5*std::pow(w2m1, 2.5)*((675675.0/2.)*std::pow(w, 3) - - 135135.0/2.*w) * std::cos(5.0*phi)); - // l = 8, m = 6 - rn[i + 14] = 6.77369783729086e-6*std::pow(w2m1, 3)*((2027025.0/2.)*w * w - - 135135.0/2.) * std::cos(6.0*phi); - // l = 8, m = 7 - rn[i + 15] = -(2.50682661696018 * w*std::pow(w2m1, 3.5) * std::cos(7.0*phi)); - // l = 8, m = 8 - rn[i + 16] = 0.626706654240044 * std::pow(w2m1, 4) * std::cos(8.0*phi); - break; - case 9: - // l = 9, m = -9 - rn[i] = -(0.609049392175524 * std::pow(w2m1, 4.5) * std::sin(9.0 * phi)); - // l = 9, m = -8 - rn[i + 1] = 2.58397773170915 * w*std::pow(w2m1, 4) * std::sin(8.0 * phi); - // l = 9, m = -7 - rn[i + 2] = -(4.37240315267812e-7*std::pow(w2m1, 3.5) * - ((34459425.0/2.)*w * w - 2027025.0/2.) * std::sin(7.0 * phi)); - // l = 9, m = -6 - rn[i + 3] = 3.02928976464514e-6*std::pow(w2m1, 3)* - ((11486475.0/2.)*std::pow(w, 3) - 2027025.0/2.*w) * std::sin(6.0 * phi); - // l = 9, m = -5 - rn[i + 4] = -(2.34647776186144e-5*std::pow(w2m1, 2.5) * - ((11486475.0/8.0)* std::pow(w, 4) - 2027025.0 / 4.0 * w * w + - 135135.0/8.0) * std::sin(5.0 * phi)); - // l = 9, m = -4 - rn[i + 5] = 0.000196320414650061 * w2m1 * w2m1*((2297295.0/8.0)* std::pow(w, 5) - - 675675.0/4.0 * std::pow(w, 3) + (135135.0/8.0)*w) * std::sin(4.0*phi); - // l = 9, m = -3 - rn[i + 6] = -(0.00173385495536766 * std::pow(w2m1, 1.5) * - ((765765.0/16.0)* std::pow(w, 6) - 675675.0/16.0 * std::pow(w, 4) + - (135135.0/16.0)*w * w - 3465.0/16.0) * std::sin(3. * phi)); - // l = 9, m = -2 - rn[i + 7] = 0.0158910431540932 * (w2m1)*((109395.0/16.0)* std::pow(w, 7)- - 135135.0/16.0 * std::pow(w, 5) + (45045.0/16.0)*std::pow(w, 3) - - 3465.0/16.0 * w) * std::sin(2. * phi); - // l = 9, m = -1 - rn[i + 8] = -(0.149071198499986*std::sqrt(w2m1)*((109395.0/128.0)* std::pow(w, 8) - - 45045.0/32.0 * std::pow(w, 6) + (45045.0/64.0)* std::pow(w, 4) - - 3465.0/32.0 * w * w + 315.0/128.0) * std::sin(phi)); - // l = 9, m = 0 - rn[i + 9] = 94.9609375 * std::pow(w, 9) - 201.09375 * std::pow(w, 7) + - 140.765625 * std::pow(w, 5)- 36.09375 * std::pow(w, 3) + 2.4609375 * w; - // l = 9, m = 1 - rn[i + 10] = -(0.149071198499986*std::sqrt(w2m1)*((109395.0/128.0)* std::pow(w, 8) - - 45045.0/32.0 * std::pow(w, 6) + (45045.0/64.0)* std::pow(w, 4) - - 3465.0/32.0 * w * w + 315.0/128.0) * std::cos(phi)); - // l = 9, m = 2 - rn[i + 11] = 0.0158910431540932 * (w2m1)*((109395.0/16.0)* std::pow(w, 7) - - 135135.0/16.0 * std::pow(w, 5) + (45045.0/16.0)*std::pow(w, 3) - - 3465.0/ 16.0 * w) * std::cos(2. * phi); - // l = 9, m = 3 - rn[i + 12] = -(0.00173385495536766 * std::pow(w2m1, 1.5)*((765765.0/16.0) * - std::pow(w, 6) - 675675.0/16.0 * std::pow(w, 4) + - (135135.0/16.0)* w * w - 3465.0/16.0)* std::cos(3. * phi)); - // l = 9, m = 4 - rn[i + 13] = 0.000196320414650061 * w2m1 * w2m1*((2297295.0/8.0) * std::pow(w, 5) - - 675675.0/4.0 * std::pow(w, 3) + (135135.0/8.0)*w) * std::cos(4.0 * phi); - // l = 9, m = 5 - rn[i + 14] = -(2.34647776186144e-5*std::pow(w2m1, 2.5)*((11486475.0/8.0) * - std::pow(w, 4) - 2027025.0/4.0 * w * w + 135135.0/8.0) * - std::cos(5.0 * phi)); - // l = 9, m = 6 - rn[i + 15] = 3.02928976464514e-6*std::pow(w2m1, 3)*((11486475.0/2.)*std::pow(w, 3) - - 2027025.0/2. * w) * std::cos(6.0 * phi); - // l = 9, m = 7 - rn[i + 16] = -(4.37240315267812e-7*std::pow(w2m1, 3.5)* - ((34459425.0/2.) * w * w - 2027025.0/2.) * std::cos(7.0 * phi)); - // l = 9, m = 8 - rn[i + 17] = 2.58397773170915 * w*std::pow(w2m1, 4) * std::cos(8.0 * phi); - // l = 9, m = 9 - rn[i + 18] = -(0.609049392175524 * std::pow(w2m1, 4.5) * std::cos(9.0 * phi)); - break; - case 10: - // l = 10, m = -10 - rn[i] = 0.593627917136573 * std::pow(w2m1, 5) * std::sin(10.0 * phi); - // l = 10, m = -9 - rn[i + 1] = -(2.65478475211798 * w * std::pow(w2m1, 4.5) * std::sin(9.0 * phi)); - // l = 10, m = -8 - rn[i + 2] = 2.49953651452314e-8 * std::pow(w2m1, 4) * - ((654729075.0/2.) * w * w - 34459425.0/2.) * std::sin(8.0 * phi); - // l = 10, m = -7 - rn[i + 3] = -(1.83677671621093e-7*std::pow(w2m1, 3.5)* - ((218243025.0/2.)*std::pow(w, 3) - 34459425.0/2.*w) * - std::sin(7.0 * phi)); - // l = 10, m = -6 - rn[i + 4] = 1.51464488232257e-6*std::pow(w2m1, 3)*((218243025.0/8.0)* std::pow(w, 4) - - 34459425.0/4.0 * w * w + 2027025.0/8.0) * std::sin(6.0 * phi); - // l = 10, m = -5 - rn[i + 5] = -(1.35473956745817e-5*std::pow(w2m1, 2.5)* - ((43648605.0/8.0)* std::pow(w, 5) - 11486475.0/4.0 * std::pow(w, 3) + - (2027025.0/8.0)*w) * std::sin(5.0 * phi)); - // l = 10, m = -4 - rn[i + 6] = 0.000128521880085575 * w2m1 * w2m1*((14549535.0/16.0)* std::pow(w, 6) - - 11486475.0/16.0 * std::pow(w, 4) + (2027025.0/16.0)*w * w - - 45045.0/16.0) * std::sin(4.0 * phi); - // l = 10, m = -3 - rn[i + 7] = -(0.00127230170115096 * std::pow(w2m1, 1.5)* - ((2078505.0/16.0)* std::pow(w, 7) - 2297295.0/16.0 * std::pow(w, 5) + - (675675.0/16.0)*std::pow(w, 3) - 45045.0/16.0 * w) * std::sin(3. * phi)); - // l = 10, m = -2 - rn[i + 8] = 0.012974982402692 * (w2m1)*((2078505.0/128.0)* std::pow(w, 8) - - 765765.0/32.0 * std::pow(w, 6) + (675675.0/64.0)* std::pow(w, 4) - - 45045.0/32.0 * w * w + 3465.0/128.0) * std::sin(2. * phi); - // l = 10, m = -1 - rn[i + 9] = -(0.134839972492648*std::sqrt(w2m1)*((230945.0/128.0)* std::pow(w, 9) - - 109395.0/32.0 * std::pow(w, 7) + (135135.0/64.0)* std::pow(w, 5) - - 15015.0/32.0 * std::pow(w, 3) + (3465.0/128.0)*w) * std::sin(phi)); - // l = 10, m = 0 - rn[i + 10] = 180.42578125 * std::pow(w, 10) - 427.32421875 * std::pow(w, 8) +351.9140625 - * std::pow(w, 6) - 117.3046875 * std::pow(w, 4) + 13.53515625 * w * w -0.24609375; - // l = 10, m = 1 - rn[i + 11] = -(0.134839972492648*std::sqrt(w2m1)*((230945.0/128.0)* std::pow(w, 9) - - 109395.0/32.0 * std::pow(w, 7) + (135135.0/64.0)* std::pow(w, 5) -15015.0/ - 32.0 * std::pow(w, 3) + (3465.0/128.0)*w) * std::cos(phi)); - // l = 10, m = 2 - rn[i + 12] = 0.012974982402692 * (w2m1)*((2078505.0/128.0)* std::pow(w, 8) - - 765765.0/32.0 * std::pow(w, 6) + (675675.0/64.0)* std::pow(w, 4) - - 45045.0/32.0 * w * w + 3465.0/128.0) * std::cos(2. * phi); - // l = 10, m = 3 - rn[i + 13] = -(0.00127230170115096 * std::pow(w2m1, 1.5)* - ((2078505.0/16.0)* std::pow(w, 7) - 2297295.0/16.0 * std::pow(w, 5) + - (675675.0/16.0)*std::pow(w, 3) - 45045.0/16.0 * w) * std::cos(3. * phi)); - // l = 10, m = 4 - rn[i + 14] = 0.000128521880085575 * w2m1 * w2m1*((14549535.0/16.0)* std::pow(w, 6) - - 11486475.0/16.0 * std::pow(w, 4) + (2027025.0/16.0) * w * w - - 45045.0/16.0) * std::cos(4.0 * phi); - // l = 10, m = 5 - rn[i + 15] = -(1.35473956745817e-5*std::pow(w2m1, 2.5)* - ((43648605.0/8.0)* std::pow(w, 5) - 11486475.0/4.0 * std::pow(w, 3) + - (2027025.0/8.0)*w) * std::cos(5.0 * phi)); - // l = 10, m = 6 - rn[i + 16] = 1.51464488232257e-6*std::pow(w2m1, 3)*((218243025.0/8.0)* std::pow(w, 4) - - 34459425.0/4.0 * w * w + 2027025.0/8.0) * std::cos(6.0 * phi); - // l = 10, m = 7 - rn[i + 17] = -(1.83677671621093e-7*std::pow(w2m1, 3.5) * - ((218243025.0/2.)*std::pow(w, 3) - 34459425.0/2.*w) * std::cos(7.0 * phi)); - // l = 10, m = 8 - rn[i + 18] = 2.49953651452314e-8*std::pow(w2m1, 4)* - ((654729075.0/2.)*w * w - 34459425.0/2.) * std::cos(8.0 * phi); - // l = 10, m = 9 - rn[i + 19] = -(2.65478475211798 * w*std::pow(w2m1, 4.5) * std::cos(9.0 * phi)); - // l = 10, m = 10 - rn[i + 20] = 0.593627917136573 * std::pow(w2m1, 5) * std::cos(10.0 * phi); - } - } -} - - -void calc_zn(int n, double rho, double phi, double zn[]) { - // =========================================================================== - // Determine vector of sin(n*phi) and cos(n*phi). This takes advantage of the - // following recurrence relations so that only a single sin/cos have to be - // evaluated (http://mathworld.wolfram.com/Multiple-AngleFormulas.html) - // - // sin(nx) = 2 cos(x) sin((n-1)x) - sin((n-2)x) - // cos(nx) = 2 cos(x) cos((n-1)x) - cos((n-2)x) - - double sin_phi = std::sin(phi); - double cos_phi = std::cos(phi); - - std::vector sin_phi_vec(n + 1); // Sin[n * phi] - std::vector cos_phi_vec(n + 1); // Cos[n * phi] - sin_phi_vec[0] = 1.0; - cos_phi_vec[0] = 1.0; - sin_phi_vec[1] = 2.0 * cos_phi; - cos_phi_vec[1] = cos_phi; - - for (int i = 2; i <= n; i++) { - sin_phi_vec[i] = 2. * cos_phi * sin_phi_vec[i - 1] - sin_phi_vec[i - 2]; - cos_phi_vec[i] = 2. * cos_phi * cos_phi_vec[i - 1] - cos_phi_vec[i - 2]; - } - - for (int i = 0; i <= n; i++) { - sin_phi_vec[i] *= sin_phi; - } - - // =========================================================================== - // Calculate R_pq(rho) - // Matrix forms of the coefficients which are easier to work with - std::vector> zn_mat(n + 1, std::vector(n + 1)); - - // Fill the main diagonal first (Eq 3.9 in Chong) - for (int p = 0; p <= n; p++) { - zn_mat[p][p] = std::pow(rho, p); - } - - // Fill the 2nd diagonal (Eq 3.10 in Chong) - for (int q = 0; q <= n - 2; q++) { - zn_mat[q][q+2] = (q + 2) * zn_mat[q+2][q+2] - (q + 1) * zn_mat[q][q]; - } - - // Fill in the rest of the values using the original results (Eq. 3.8 in Chong) - for (int p = 4; p <= n; p++) { - double k2 = 2 * p * (p - 1) * (p - 2); - for (int q = p - 4; q >= 0; q -= 2) { - double k1 = ((p + q) * (p - q) * (p - 2)) / 2.; - double k3 = -q * q * (p - 1) - p * (p - 1) * (p - 2); - double k4 = (-p * (p + q - 2) * (p - q - 2)) / 2.; - zn_mat[q][p] = - ((k2 * rho * rho + k3) * zn_mat[q][p-2] + k4 * zn_mat[q][p-4]) / k1; - } - } - - // Roll into a single vector for easier computation later - // The vector is ordered (0,0), (1,-1), (1,1), (2,-2), (2,0), - // (2, 2), .... in (n,m) indices - // Note that the cos and sin vectors are offset by one - // sin_phi_vec = [sin(x), sin(2x), sin(3x) ...] - // cos_phi_vec = [1.0, cos(x), cos(2x)... ] - int i = 0; - for (int p = 0; p <= n; p++) { - for (int q = -p; q <= p; q += 2) { - if (q < 0) { - zn[i] = zn_mat[std::abs(q)][p] * sin_phi_vec[std::abs(q) - 1]; - } else if (q == 0) { - zn[i] = zn_mat[q][p]; - } else { - zn[i] = zn_mat[q][p] * cos_phi_vec[q]; - } - i++; - } - } - -} - -void calc_zn_rad(int n, double rho, double zn_rad[]) { - // Calculate R_p0(rho) as Zn_p0(rho) - // Set up the array of the coefficients - - double q = 0; - - // R_00 is always 1 - zn_rad[0] = 1; - - // Fill in the rest of the array (Eq 3.8 and Eq 3.10 in Chong) - for (int p = 2; p <= n; p += 2) { - int index = int(p/2); - if (p == 2) { - // Setting up R_22 to calculate R_20 (Eq 3.10 in Chong) - double R_22 = rho * rho; - zn_rad[index] = 2 * R_22 - zn_rad[0]; - } else { - double k1 = ((p + q) * (p - q) * (p - 2)) / 2.; - double k2 = 2 * p * (p - 1) * (p - 2); - double k3 = -q * q * (p - 1) - p * (p - 1) * (p - 2); - double k4 = (-p * (p + q - 2) * (p - q - 2)) / 2.; - zn_rad[index] = - ((k2 * rho * rho + k3) * zn_rad[index-1] + k4 * zn_rad[index-2]) / k1; - } - } -} - - -void rotate_angle_c(double uvw[3], double mu, const double* phi) { - Direction u = rotate_angle({uvw}, mu, phi); - uvw[0] = u.x; - uvw[1] = u.y; - uvw[2] = u.z; -} - - -Direction rotate_angle(Direction u, double mu, const double* phi) -{ - // Sample azimuthal angle in [0,2pi) if none provided - double phi_; - if (phi != nullptr) { - phi_ = (*phi); - } else { - phi_ = 2.0*PI*prn(); - } - - // Precompute factors to save flops - double sinphi = std::sin(phi_); - double cosphi = std::cos(phi_); - double a = std::sqrt(std::fmax(0., 1. - mu*mu)); - double b = std::sqrt(std::fmax(0., 1. - u.z*u.z)); - - // Need to treat special case where sqrt(1 - w**2) is close to zero by - // expanding about the v component rather than the w component - if (b > 1e-10) { - return {mu*u.x + a*(u.x*u.z*cosphi - u.y*sinphi) / b, - mu*u.y + a*(u.y*u.z*cosphi + u.x*sinphi) / b, - mu*u.z - a*b*cosphi}; - } else { - b = std::sqrt(1. - u.y*u.y); - return {mu*u.x + a*(u.x*u.y*cosphi + u.z*sinphi) / b, - mu*u.y - a*b*cosphi, - mu*u.z + a*(u.y*u.z*cosphi - u.x*sinphi) / b}; - // TODO: use the following code to make PolarAzimuthal distributions match - // spherical coordinate conventions. Remove the related fixup code in - // PolarAzimuthal::sample. - //return {mu*u.x + a*(-u.x*u.y*sinphi + u.z*cosphi) / b, - // mu*u.y + a*b*sinphi, - // mu*u.z - a*(u.y*u.z*sinphi + u.x*cosphi) / b}; - } -} - - -double maxwell_spectrum(double T) { - // Set the random numbers - double r1 = prn(); - double r2 = prn(); - double r3 = prn(); - - // determine cosine of pi/2*r - double c = std::cos(PI / 2. * r3); - - // Determine outgoing energy - double E_out = -T * (std::log(r1) + std::log(r2) * c * c); - - return E_out; -} - - -double normal_variate(double mean, double standard_deviation) { - // perhaps there should be a limit to the number of resamples - while ( true ) { - double v1 = 2 * prn() - 1.; - double v2 = 2 * prn() - 1.; - - double r = std::pow(v1, 2) + std::pow(v2, 2); - double r2 = std::pow(r, 2); - if (r2 < 1) { - double z = std::sqrt(-2.0 * std::log(r2)/r2); - z *= (prn() <= 0.5) ? v1 : v2; - return mean + standard_deviation*z; - } - } -} - -double muir_spectrum(double e0, double m_rat, double kt) { - // note sigma here is a factor of 2 shy of equation - // 8 in https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS - double sigma = std::sqrt(2.*e0*kt/m_rat); - return normal_variate(e0, sigma); -} - - -double watt_spectrum(double a, double b) { - double w = maxwell_spectrum(a); - double E_out = w + 0.25 * a * a * b + (2. * prn() - 1.) * std::sqrt(a * a * b * w); - - return E_out; -} - - -void broaden_wmp_polynomials(double E, double dopp, int n, double factors[]) -{ - // Factors is already pre-allocated - double sqrtE = std::sqrt(E); - double beta = sqrtE * dopp; - double half_inv_dopp2 = 0.5 / (dopp * dopp); - double quarter_inv_dopp4 = half_inv_dopp2 * half_inv_dopp2; - - double erf_beta; // error function of beta - double exp_m_beta2; // exp(-beta**2) - if (beta > 6.0) { - // Save time, ERF(6) is 1 to machine precision. - // beta/sqrtpi*exp(-beta**2) is also approximately 1 machine epsilon. - erf_beta = 1.; - exp_m_beta2 = 0.; - } else { - erf_beta = std::erf(beta); - exp_m_beta2 = std::exp(-beta * beta); - } - - // Assume that, for sure, we'll use a second order (1/E, 1/V, const) - // fit, and no less. - - factors[0] = erf_beta / E; - factors[1] = 1. / sqrtE; - factors[2] = factors[0] * (half_inv_dopp2 + E) + exp_m_beta2 / - (beta * SQRT_PI); - - // Perform recursive broadening of high order components - for (int i = 0; i < n - 3; i++) { - double ip1_dbl = i + 1; - if (i != 0) { - factors[i + 3] = -factors[i - 1] * (ip1_dbl - 1.) * ip1_dbl * - quarter_inv_dopp4 + factors[i + 1] * - (E + (1. + 2. * ip1_dbl) * half_inv_dopp2); - } else { - // Although it's mathematically identical, factors[0] will contain - // nothing, and we don't want to have to worry about memory. - factors[i + 3] = factors[i + 1] * - (E + (1. + 2. * ip1_dbl) * half_inv_dopp2); - } - } -} - - -void spline(int n, const double x[], const double y[], double z[]) -{ - std::vector c_new(n-1); - - // Set natural boundary conditions - c_new[0] = 0.0; - z[0] = 0.0; - z[n-1] = 0.0; - - // Solve using tridiagonal matrix algorithm; first do forward sweep - for (int i = 1; i < n - 1; i++) { - double a = x[i] - x[i-1]; - double c = x[i+1] - x[i]; - double b = 2.0*(a + c); - double d = 6.0*((y[i+1] - y[i])/c - (y[i] - y[i-1])/a); - - c_new[i] = c/(b - a*c_new[i-1]); - z[i] = (d - a*z[i-1])/(b - a*c_new[i-1]); - } - - // Back substitution - for (int i = n - 2; i >= 0; i--) { - z[i] = z[i] - c_new[i]*z[i+1]; - } -} - - -double spline_interpolate(int n, const double x[], const double y[], - const double z[], double xint) -{ - // Find the lower bounding index in x of xint - int i = n - 1; - while (--i) { - if (xint >= x[i]) break; - } - - double h = x[i+1] - x[i]; - double r = xint - x[i]; - - // Compute the coefficients - double b = (y[i+1] - y[i])/h - (h/6.0)*(z[i+1] + 2.0*z[i]); - double c = z[i]/2.0; - double d = (z[i+1] - z[i])/(h*6.0); - - return y[i] + b*r + c*r*r + d*r*r*r; -} - - -double spline_integrate(int n, const double x[], const double y[], - const double z[], double xa, double xb) -{ - // Find the lower bounding index in x of the lower limit of integration. - int ia = n - 1; - while (--ia) { - if (xa >= x[ia]) break; - } - - // Find the lower bounding index in x of the upper limit of integration. - int ib = n - 1; - while (--ib) { - if (xb >= x[ib]) break; - } - - // Evaluate the integral - double s = 0.0; - for (int i = ia; i <= ib; i++) { - double h = x[i+1] - x[i]; - - // Compute the coefficients - double b = (y[i+1] - y[i])/h - (h/6.0)*(z[i+1] + 2.0*z[i]); - double c = z[i]/2.0; - double d = (z[i+1] - z[i])/(h*6.0); - - // Subtract the integral from x[ia] to xa - if (i == ia) { - double r = xa - x[ia]; - s = s - (y[i]*r + b/2.0*r*r + c/3.0*r*r*r + d/4.0*r*r*r*r); - } - - // Integrate from x[ib] to xb in final interval - if (i == ib) { - h = xb - x[ib]; - } - - // Accumulate the integral - s = s + y[i]*h + b/2.0*h*h + c/3.0*h*h*h + d/4.0*h*h*h*h; - } - - return s; -} - -std::complex faddeeva(std::complex z) -{ - // Technically, the value we want is given by the equation: - // w(z) = I/pi * Integrate[Exp[-t^2]/(z-t), {t, -Infinity, Infinity}] - // as shown in Equation 63 from Hwang, R. N. "A rigorous pole - // representation of multilevel cross sections and its practical - // applications." Nucl. Sci. Eng. 96.3 (1987): 192-209. - // - // The MIT Faddeeva function evaluates w(z) = exp(-z^2)erfc(-iz). These - // two forms of the Faddeeva function are related by a transformation. - // - // If we call the integral form w_int, and the function form w_fun: - // For imag(z) > 0, w_int(z) = w_fun(z) - // For imag(z) < 0, w_int(z) = -conjg(w_fun(conjg(z))) - - // Note that Faddeeva::w will interpret zero as machine epsilon - return z.imag() > 0.0 ? Faddeeva::w(z) : - -std::conj(Faddeeva::w(std::conj(z))); -} - -std::complex w_derivative(std::complex z, int order) -{ - using namespace std::complex_literals; - switch (order) { - case 0: - return faddeeva(z); - case 1: - return -2.0*z*faddeeva(z) + 2.0i / SQRT_PI; - default: - return -2.0*z*w_derivative(z, order-1) - - 2.0*(order-1)*w_derivative(z, order-2); - } -} - -} // namespace openmc diff --git a/src/mesh.cpp b/src/mesh.cpp deleted file mode 100644 index acd80c7ba..000000000 --- a/src/mesh.cpp +++ /dev/null @@ -1,1534 +0,0 @@ -#include "openmc/mesh.h" - -#include // for copy, equal, min, min_element -#include // for size_t -#include // for ceil -#include - -#ifdef OPENMC_MPI -#include "mpi.h" -#endif -#include "xtensor/xbuilder.hpp" -#include "xtensor/xeval.hpp" -#include "xtensor/xmath.hpp" -#include "xtensor/xsort.hpp" -#include "xtensor/xtensor.hpp" - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/message_passing.h" -#include "openmc/search.h" -#include "openmc/tallies/filter.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - -std::vector> meshes; -std::unordered_map mesh_map; - -} // namespace model - -//============================================================================== -// Helper functions -//============================================================================== - -//! Update an intersection point if the given candidate is closer. -// -//! The first 6 arguments are coordinates for the starting point of a particle -//! and its intersection with a mesh surface. If the distance between these -//! two points is shorter than the given `min_distance`, then the `r` argument -//! will be updated to match the intersection point, and `min_distance` will -//! also be updated. - -inline bool check_intersection_point(double x1, double x0, double y1, - double y0, double z1, double z0, Position& r, double& min_distance) -{ - double dist = std::pow(x1-x0, 2) + std::pow(y1-y0, 2) + std::pow(z1-z0, 2); - if (dist < min_distance) { - r.x = x1; - r.y = y1; - r.z = z1; - min_distance = dist; - return true; - } - return false; -} - -//============================================================================== -// Mesh implementation -//============================================================================== - -Mesh::Mesh(pugi::xml_node node) -{ - // Copy mesh id - if (check_for_node(node, "id")) { - id_ = std::stoi(get_node_value(node, "id")); - - // Check to make sure 'id' hasn't been used - if (model::mesh_map.find(id_) != model::mesh_map.end()) { - fatal_error("Two or more meshes use the same unique ID: " + - std::to_string(id_)); - } - } -} - -//============================================================================== -// RegularMesh implementation -//============================================================================== - -RegularMesh::RegularMesh(pugi::xml_node node) - : Mesh {node} -{ - // Determine number of dimensions for mesh - if (check_for_node(node, "dimension")) { - shape_ = get_node_xarray(node, "dimension"); - int n = n_dimension_ = shape_.size(); - if (n != 1 && n != 2 && n != 3) { - fatal_error("Mesh must be one, two, or three dimensions."); - } - - // Check that dimensions are all greater than zero - if (xt::any(shape_ <= 0)) { - fatal_error("All entries on the element for a tally " - "mesh must be positive."); - } - } - - // Check for lower-left coordinates - if (check_for_node(node, "lower_left")) { - // Read mesh lower-left corner location - lower_left_ = get_node_xarray(node, "lower_left"); - } else { - fatal_error("Must specify on a mesh."); - } - - if (check_for_node(node, "width")) { - // Make sure both upper-right or width were specified - if (check_for_node(node, "upper_right")) { - fatal_error("Cannot specify both and on a mesh."); - } - - width_ = get_node_xarray(node, "width"); - - // Check to ensure width has same dimensions - auto n = width_.size(); - if (n != lower_left_.size()) { - fatal_error("Number of entries on must be the same as " - "the number of entries on ."); - } - - // Check for negative widths - if (xt::any(width_ < 0.0)) { - fatal_error("Cannot have a negative on a tally mesh."); - } - - // Set width and upper right coordinate - upper_right_ = xt::eval(lower_left_ + shape_ * width_); - - } else if (check_for_node(node, "upper_right")) { - upper_right_ = get_node_xarray(node, "upper_right"); - - // Check to ensure width has same dimensions - auto n = upper_right_.size(); - if (n != lower_left_.size()) { - fatal_error("Number of entries on must be the " - "same as the number of entries on ."); - } - - // Check that upper-right is above lower-left - if (xt::any(upper_right_ < lower_left_)) { - fatal_error("The coordinates must be greater than " - "the coordinates on a tally mesh."); - } - - // Set width and upper right coordinate - width_ = xt::eval((upper_right_ - lower_left_) / shape_); - } else { - fatal_error("Must specify either and on a mesh."); - } - - // TODO: Change to zero when xtensor is updated - if (shape_.size() > 1) { - if (shape_.size() != lower_left_.size()) { - fatal_error("Number of entries on must be the same " - "as the number of entries on ."); - } - - // Set volume fraction - volume_frac_ = 1.0/xt::prod(shape_)(); - } -} - -int RegularMesh::get_bin(Position r) const -{ - // Loop over the dimensions of the mesh - for (int i = 0; i < n_dimension_; ++i) { - // Check for cases where particle is outside of mesh - if (r[i] < lower_left_[i]) { - return -1; - } else if (r[i] > upper_right_[i]) { - return -1; - } - } - - // Determine indices - std::vector ijk(n_dimension_); - bool in_mesh; - get_indices(r, ijk.data(), &in_mesh); - if (!in_mesh) return -1; - - // Convert indices to bin - return get_bin_from_indices(ijk.data()); -} - -int RegularMesh::get_bin_from_indices(const int* ijk) const -{ - switch (n_dimension_) { - case 1: - return ijk[0] - 1; - case 2: - return (ijk[1] - 1)*shape_[0] + ijk[0] - 1; - case 3: - return ((ijk[2] - 1)*shape_[1] + (ijk[1] - 1))*shape_[0] + ijk[0] - 1; - default: - throw std::runtime_error{"Invalid number of mesh dimensions"}; - } -} - -void RegularMesh::get_indices(Position r, int* ijk, bool* in_mesh) const -{ - // Find particle in mesh - *in_mesh = true; - for (int i = 0; i < n_dimension_; ++i) { - ijk[i] = std::ceil((r[i] - lower_left_[i]) / width_[i]); - - // Check if indices are within bounds - if (ijk[i] < 1 || ijk[i] > shape_[i]) *in_mesh = false; - } -} - -void RegularMesh::get_indices_from_bin(int bin, int* ijk) const -{ - if (n_dimension_ == 1) { - ijk[0] = bin + 1; - } else if (n_dimension_ == 2) { - ijk[0] = bin % shape_[0] + 1; - ijk[1] = bin / shape_[0] + 1; - } else if (n_dimension_ == 3) { - ijk[0] = bin % shape_[0] + 1; - ijk[1] = (bin % (shape_[0] * shape_[1])) / shape_[0] + 1; - ijk[2] = bin / (shape_[0] * shape_[1]) + 1; - } -} - -int RegularMesh::n_bins() const -{ - int n_bins = 1; - for (auto dim : shape_) n_bins *= dim; - return n_bins; -} - -int RegularMesh::n_surface_bins() const -{ - return 4 * n_dimension_ * n_bins(); -} - -bool RegularMesh::intersects(Position& r0, Position r1, int* ijk) const -{ - switch(n_dimension_) { - case 1: - return intersects_1d(r0, r1, ijk); - case 2: - return intersects_2d(r0, r1, ijk); - case 3: - return intersects_3d(r0, r1, ijk); - default: - throw std::runtime_error{"Invalid number of mesh dimensions."}; - } -} - -bool RegularMesh::intersects_1d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left and upper_right - double xm0 = lower_left_[0]; - double xm1 = upper_right_[0]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (check_intersection_point(xm0, x0, yi, yi, zi, zi, r0, min_dist)) { - ijk[0] = 1; - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (check_intersection_point(xm1, x0, yi, yi, zi, zi, r0, min_dist)) { - ijk[0] = shape_[0]; - } - } - - return min_dist < INFTY; -} - -bool RegularMesh::intersects_2d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = lower_left_[0]; - double ym0 = lower_left_[1]; - - // Copy coordinates of mesh upper_right - double xm1 = upper_right_[0]; - double ym1 = upper_right_[1]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, zi, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, zi, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, zi, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, zi, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = shape_[1]; - } - } - } - - return min_dist < INFTY; -} - -bool RegularMesh::intersects_3d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = lower_left_[0]; - double ym0 = lower_left_[1]; - double zm0 = lower_left_[2]; - - // Copy coordinates of mesh upper_right - double xm1 = upper_right_[0]; - double ym1 = upper_right_[1]; - double zm1 = upper_right_[2]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = 1; - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects bottom surface -- calculate the intersection - // point (x,y) - if ((z0 < zm0 && z1 > zm0) || (z0 > zm0 && z1 < zm0)) { - double xi = x0 + (zm0 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm0 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm0, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = shape_[1]; - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects top surface -- calculate the intersection point - // (x,y) - if ((z0 < zm1 && z1 > zm1) || (z0 > zm1 && z1 < zm1)) { - double xi = x0 + (zm1 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm1 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm1, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = shape_[2]; - } - } - } - - return min_dist < INFTY; -} - -void RegularMesh::bins_crossed(const Particle* p, std::vector& bins, - std::vector& lengths) const -{ - // ======================================================================== - // Determine where the track intersects the mesh and if it intersects at all. - - // Copy the starting and ending coordinates of the particle. - Position last_r {p->r_last_}; - Position r {p->r()}; - Direction u {p->u()}; - - // Compute the length of the entire track. - double total_distance = (r - last_r).norm(); - - // While determining if this track intersects the mesh, offset the starting - // and ending coords by a bit. This avoid finite-precision errors that can - // occur when the mesh surfaces coincide with lattice or geometric surfaces. - Position r0 = last_r + TINY_BIT*u; - Position r1 = r - TINY_BIT*u; - - // Determine the mesh indices for the starting and ending coords. - int n = n_dimension_; - std::vector ijk0(n), ijk1(n); - bool start_in_mesh; - get_indices(r0, ijk0.data(), &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1.data(), &end_in_mesh); - - // Reset coordinates and check for a mesh intersection if necessary. - if (start_in_mesh) { - // The initial coords lie in the mesh, use those coords for tallying. - r0 = last_r; - } else { - // The initial coords do not lie in the mesh. Check to see if the particle - // eventually intersects the mesh and compute the relevant coords and - // indices. - if (!intersects(r0, r1, ijk0.data())) return; - } - r1 = r; - - // ======================================================================== - // Find which mesh cells are traversed and the length of each traversal. - - while (true) { - if (ijk0 == ijk1) { - // The track ends in this cell. Use the particle end location rather - // than the mesh surface and stop iterating. - double distance = (r1 - r0).norm(); - bins.push_back(get_bin_from_indices(ijk0.data())); - lengths.push_back(distance / total_distance); - break; - } - - // The track exits this cell. Determine the distance to each mesh surface. - std::vector d(n); - for (int k = 0; k < n; ++k) { - if (std::fabs(u[k]) < FP_PRECISION) { - d[k] = INFTY; - } else if (u[k] > 0) { - double xyz_cross = lower_left_[k] + ijk0[k] * width_[k]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } else { - double xyz_cross = lower_left_[k] + (ijk0[k] - 1) * width_[k]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } - } - - // Pick the closest mesh surface and append this traversal to the output. - auto j = std::min_element(d.begin(), d.end()) - d.begin(); - double distance = d[j]; - bins.push_back(get_bin_from_indices(ijk0.data())); - lengths.push_back(distance / total_distance); - - // Translate to the oncoming mesh surface. - r0 += distance * u; - - // Increment the indices into the next mesh cell. - if (u[j] > 0.0) { - ++ijk0[j]; - } else { - --ijk0[j]; - } - - // If the next indices are invalid, then the track has left the mesh and - // we are done. - bool in_mesh = true; - for (int i = 0; i < n; ++i) { - if (ijk0[i] < 1 || ijk0[i] > shape_[i]) { - in_mesh = false; - break; - } - } - if (!in_mesh) break; - } -} - -void RegularMesh::surface_bins_crossed(const Particle* p, - std::vector& bins) const -{ - // ======================================================================== - // Determine if the track intersects the tally mesh. - - // Copy the starting and ending coordinates of the particle. - Position r0 {p->r_last_current_}; - Position r1 {p->r()}; - Direction u {p->u()}; - - // Determine indices for starting and ending location. - int n = n_dimension_; - std::vector ijk0(n), ijk1(n); - bool start_in_mesh; - get_indices(r0, ijk0.data(), &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1.data(), &end_in_mesh); - - // Check if the track intersects any part of the mesh. - if (!start_in_mesh) { - Position r0_copy = r0; - std::vector ijk0_copy(ijk0); - if (!intersects(r0_copy, r1, ijk0_copy.data())) return; - } - - // ======================================================================== - // Find which mesh surfaces are crossed. - - // Calculate number of surface crossings - int n_cross = 0; - for (int i = 0; i < n; ++i) n_cross += std::abs(ijk1[i] - ijk0[i]); - if (n_cross == 0) return; - - // Bounding coordinates - Position xyz_cross; - for (int i = 0; i < n; ++i) { - if (u[i] > 0.0) { - xyz_cross[i] = lower_left_[i] + ijk0[i] * width_[i]; - } else { - xyz_cross[i] = lower_left_[i] + (ijk0[i] - 1) * width_[i]; - } - } - - for (int j = 0; j < n_cross; ++j) { - // Set the distances to infinity - Position d {INFTY, INFTY, INFTY}; - - // Determine closest bounding surface. We need to treat - // special case where the cosine of the angle is zero since this would - // result in a divide-by-zero. - double distance = INFTY; - for (int i = 0; i < n; ++i) { - if (u[i] == 0) { - d[i] = INFTY; - } else { - d[i] = (xyz_cross[i] - r0[i])/u[i]; - } - distance = std::min(distance, d[i]); - } - - // Loop over the dimensions - for (int i = 0; i < n; ++i) { - // Check whether distance is the shortest distance - if (distance == d[i]) { - - // Check whether the current indices are within the mesh bounds - bool in_mesh = true; - for (int j = 0; j < n; ++j) { - if (ijk0[j] < 1 || ijk0[j] > shape_[j]) { - in_mesh = false; - break; - } - } - - // Check whether particle is moving in positive i direction - if (u[i] > 0) { - - // Outward current on i max surface - if (in_mesh) { - int i_surf = 4*i + 3; - int i_mesh = get_bin_from_indices(ijk0.data()); - int i_bin = 4*n*i_mesh + i_surf - 1; - - bins.push_back(i_bin); - } - - // Advance position - ++ijk0[i]; - xyz_cross[i] += width_[i]; - in_mesh = true; - for (int j = 0; j < n; ++j) { - if (ijk0[j] < 1 || ijk0[j] > shape_[j]) { - in_mesh = false; - break; - } - } - - // If the particle crossed the surface, tally the inward current on - // i min surface - if (in_mesh) { - int i_surf = 4*i + 2; - int i_mesh = get_bin_from_indices(ijk0.data()); - int i_bin = 4*n*i_mesh + i_surf - 1; - - bins.push_back(i_bin); - } - - } else { - // The particle is moving in the negative i direction - - // Outward current on i min surface - if (in_mesh) { - int i_surf = 4*i + 1; - int i_mesh = get_bin_from_indices(ijk0.data()); - int i_bin = 4*n*i_mesh + i_surf - 1; - - bins.push_back(i_bin); - } - - // Advance position - --ijk0[i]; - xyz_cross[i] -= width_[i]; - in_mesh = true; - for (int j = 0; j < n; ++j) { - if (ijk0[j] < 1 || ijk0[j] > shape_[j]) { - in_mesh = false; - break; - } - } - - // If the particle crossed the surface, tally the inward current on - // i max surface - if (in_mesh) { - int i_surf = 4*i + 4; - int i_mesh = get_bin_from_indices(ijk0.data()); - int i_bin = 4*n*i_mesh + i_surf - 1; - - bins.push_back(i_bin); - } - } - } - } - - // Calculate new coordinates - r0 += distance * u; - } -} - -std::pair, std::vector> -RegularMesh::plot(Position plot_ll, Position plot_ur) const -{ - // Figure out which axes lie in the plane of the plot. - std::array axes {-1, -1}; - if (plot_ur.z == plot_ll.z) { - axes[0] = 0; - if (n_dimension_ > 1) axes[1] = 1; - } else if (plot_ur.y == plot_ll.y) { - axes[0] = 0; - if (n_dimension_ > 2) axes[1] = 2; - } else if (plot_ur.x == plot_ll.x) { - if (n_dimension_ > 1) axes[0] = 1; - if (n_dimension_ > 2) axes[1] = 2; - } else { - fatal_error("Can only plot mesh lines on an axis-aligned plot"); - } - - // Get the coordinates of the mesh lines along both of the axes. - std::array, 2> axis_lines; - for (int i_ax = 0; i_ax < 2; ++i_ax) { - int axis = axes[i_ax]; - if (axis == -1) continue; - auto& lines {axis_lines[i_ax]}; - - double coord = lower_left_[axis]; - for (int i = 0; i < shape_[axis] + 1; ++i) { - if (coord >= plot_ll[axis] && coord <= plot_ur[axis]) - lines.push_back(coord); - coord += width_[axis]; - } - } - - return {axis_lines[0], axis_lines[1]}; -} - -void RegularMesh::to_hdf5(hid_t group) const -{ - hid_t mesh_group = create_group(group, "mesh " + std::to_string(id_)); - - write_dataset(mesh_group, "type", "regular"); - write_dataset(mesh_group, "dimension", shape_); - write_dataset(mesh_group, "lower_left", lower_left_); - write_dataset(mesh_group, "upper_right", upper_right_); - write_dataset(mesh_group, "width", width_); - - close_group(mesh_group); -} - -xt::xtensor -RegularMesh::count_sites(const std::vector& bank, - bool* outside) const -{ - // Determine shape of array for counts - std::size_t m = xt::prod(shape_)(); - std::vector shape = {m}; - - // Create array of zeros - xt::xarray cnt {shape, 0.0}; - bool outside_ = false; - - for (const auto& site : bank) { - // determine scoring bin for entropy mesh - int mesh_bin = get_bin(site.r); - - // if outside mesh, skip particle - if (mesh_bin < 0) { - outside_ = true; - continue; - } - - // Add to appropriate bin - cnt(mesh_bin) += site.wgt; - } - - // Create copy of count data - int total = cnt.size(); - double* cnt_reduced = new double[total]; - -#ifdef OPENMC_MPI - // collect values from all processors - MPI_Reduce(cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0, - mpi::intracomm); - - // Check if there were sites outside the mesh for any processor - if (outside) { - MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm); - } -#else - std::copy(cnt.data(), cnt.data() + total, cnt_reduced); - if (outside) *outside = outside_; -#endif - - // Adapt reduced values in array back into an xarray - auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), shape); - xt::xarray counts = arr; - - return counts; -} - -//============================================================================== -// RectilinearMesh implementation -//============================================================================== - -RectilinearMesh::RectilinearMesh(pugi::xml_node node) - : Mesh {node} -{ - n_dimension_ = 3; - - grid_.resize(3); - grid_[0] = get_node_array(node, "x_grid"); - grid_[1] = get_node_array(node, "y_grid"); - grid_[2] = get_node_array(node, "z_grid"); - - shape_ = {static_cast(grid_[0].size()) - 1, - static_cast(grid_[1].size()) - 1, - static_cast(grid_[2].size()) - 1}; - - for (const auto& g : grid_) { - if (g.size() < 2) fatal_error("x-, y-, and z- grids for rectilinear meshes " - "must each have at least 2 points"); - for (int i = 1; i < g.size(); ++i) { - if (g[i] <= g[i-1]) fatal_error("Values in for x-, y-, and z- grids for " - "rectilinear meshes must be sorted and unique."); - } - } - - lower_left_ = {grid_[0].front(), grid_[1].front(), grid_[2].front()}; - upper_right_ = {grid_[0].back(), grid_[1].back(), grid_[2].back()}; -} - -void RectilinearMesh::bins_crossed(const Particle* p, std::vector& bins, - std::vector& lengths) const -{ - // ======================================================================== - // Determine where the track intersects the mesh and if it intersects at all. - - // Copy the starting and ending coordinates of the particle. - Position last_r {p->r_last_}; - Position r {p->r()}; - Direction u {p->u()}; - - // Compute the length of the entire track. - double total_distance = (r - last_r).norm(); - - // While determining if this track intersects the mesh, offset the starting - // and ending coords by a bit. This avoid finite-precision errors that can - // occur when the mesh surfaces coincide with lattice or geometric surfaces. - Position r0 = last_r + TINY_BIT*u; - Position r1 = r - TINY_BIT*u; - - // Determine the mesh indices for the starting and ending coords. - int ijk0[3], ijk1[3]; - bool start_in_mesh; - get_indices(r0, ijk0, &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1, &end_in_mesh); - - // Reset coordinates and check for a mesh intersection if necessary. - if (start_in_mesh) { - // The initial coords lie in the mesh, use those coords for tallying. - r0 = last_r; - } else { - // The initial coords do not lie in the mesh. Check to see if the particle - // eventually intersects the mesh and compute the relevant coords and - // indices. - if (!intersects(r0, r1, ijk0)) return; - } - r1 = r; - - // ======================================================================== - // Find which mesh cells are traversed and the length of each traversal. - - while (true) { - if (std::equal(ijk0, ijk0+3, ijk1)) { - // The track ends in this cell. Use the particle end location rather - // than the mesh surface and stop iterating. - double distance = (r1 - r0).norm(); - bins.push_back(get_bin_from_indices(ijk0)); - lengths.push_back(distance / total_distance); - break; - } - - // The track exits this cell. Determine the distance to each mesh surface. - double d[3]; - for (int k = 0; k < 3; ++k) { - if (std::fabs(u[k]) < FP_PRECISION) { - d[k] = INFTY; - } else if (u[k] > 0) { - double xyz_cross = grid_[k][ijk0[k]]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } else { - double xyz_cross = grid_[k][ijk0[k] - 1]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } - } - - // Pick the closest mesh surface and append this traversal to the output. - auto j = std::min_element(d, d+3) - d; - double distance = d[j]; - bins.push_back(get_bin_from_indices(ijk0)); - lengths.push_back(distance / total_distance); - - // Translate to the oncoming mesh surface. - r0 += distance * u; - - // Increment the indices into the next mesh cell. - if (u[j] > 0.0) { - ++ijk0[j]; - } else { - --ijk0[j]; - } - - // If the next indices are invalid, then the track has left the mesh and - // we are done. - bool in_mesh = true; - for (int i = 0; i < 3; ++i) { - if (ijk0[i] < 1 || ijk0[i] > shape_[i]) { - in_mesh = false; - break; - } - } - if (!in_mesh) break; - } -} - -void RectilinearMesh::surface_bins_crossed(const Particle* p, - std::vector& bins) const -{ - // ======================================================================== - // Determine if the track intersects the tally mesh. - - // Copy the starting and ending coordinates of the particle. - Position r0 {p->r_last_current_}; - Position r1 {p->r()}; - Direction u {p->u()}; - - // Determine indices for starting and ending location. - int ijk0[3], ijk1[3]; - bool start_in_mesh; - get_indices(r0, ijk0, &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1, &end_in_mesh); - - // If the starting coordinates do not lie in the mesh, compute the coords and - // mesh indices of the first intersection, and add the bin for this first - // intersection. Return if the particle does not intersect the mesh at all. - if (!start_in_mesh) { - // Compute the incoming intersection coordinates and indices. - if (!intersects(r0, r1, ijk0)) return; - - // Determine which surface the particle entered. - double min_dist = INFTY; - int i_surf; - for (int i = 0; i < 3; ++i) { - if (u[i] > 0.0 && ijk0[i] == 1) { - double d = std::abs(r0[i] - grid_[i][0]); - if (d < min_dist) { - min_dist = d; - i_surf = 4*i + 2; - } - } else if (u[i] < 0.0 && ijk0[i] == shape_[i]) { - double d = std::abs(r0[i] - grid_[i][shape_[i]]); - if (d < min_dist) { - min_dist = d; - i_surf = 4*i + 4; - } - } // u[i] == 0 intentionally skipped - } - - // Add the incoming current bin. - int i_mesh = get_bin_from_indices(ijk0); - int i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - } - - // If the ending coordinates do not lie in the mesh, compute the coords and - // mesh indices of the last intersection, and add the bin for this last - // intersection. - if (!end_in_mesh) { - // Compute the outgoing intersection coordinates and indices. - intersects(r1, r0, ijk1); - - // Determine which surface the particle exited. - double min_dist = INFTY; - int i_surf; - for (int i = 0; i < 3; ++i) { - if (u[i] > 0.0 && ijk1[i] == shape_[i]) { - double d = std::abs(r1[i] - grid_[i][shape_[i]]); - if (d < min_dist) { - min_dist = d; - i_surf = 4*i + 3; - } - } else if (u[i] < 0.0 && ijk1[i] == 1) { - double d = std::abs(r1[i] - grid_[i][0]); - if (d < min_dist) { - min_dist = d; - i_surf = 4*i + 1; - } - } // u[i] == 0 intentionally skipped - } - - // Add the outgoing current bin. - int i_mesh = get_bin_from_indices(ijk1); - int i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - } - - // ======================================================================== - // Find which mesh surfaces are crossed. - - // Calculate number of surface crossings - int n_cross = 0; - for (int i = 0; i < 3; ++i) n_cross += std::abs(ijk1[i] - ijk0[i]); - if (n_cross == 0) return; - - // Bounding coordinates - Position xyz_cross; - for (int i = 0; i < 3; ++i) { - if (u[i] > 0.0) { - xyz_cross[i] = grid_[i][ijk0[i]]; - } else { - xyz_cross[i] = grid_[i][ijk0[i] - 1]; - } - } - - for (int j = 0; j < n_cross; ++j) { - // Set the distances to infinity - Position d {INFTY, INFTY, INFTY}; - - // Determine closest bounding surface. We need to treat - // special case where the cosine of the angle is zero since this would - // result in a divide-by-zero. - double distance = INFTY; - for (int i = 0; i < 3; ++i) { - if (u[i] == 0) { - d[i] = INFTY; - } else { - d[i] = (xyz_cross[i] - r0[i])/u[i]; - } - distance = std::min(distance, d[i]); - } - - // Loop over the dimensions - for (int i = 0; i < 3; ++i) { - // Check whether distance is the shortest distance - if (distance == d[i]) { - - // Check whether particle is moving in positive i direction - if (u[i] > 0) { - - // Outward current on i max surface - int i_surf = 4*i + 3; - int i_mesh = get_bin_from_indices(ijk0); - int i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - - // Advance position - ++ijk0[i]; - xyz_cross[i] = grid_[i][ijk0[i]]; - - // Inward current on i min surface - i_surf = 4*i + 2; - i_mesh = get_bin_from_indices(ijk0); - i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - - } else { - // The particle is moving in the negative i direction - - // Outward current on i min surface - int i_surf = 4*i + 1; - int i_mesh = get_bin_from_indices(ijk0); - int i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - - // Advance position - --ijk0[i]; - xyz_cross[i] = grid_[i][ijk0[i] - 1]; - - // Inward current on i min surface - i_surf = 4*i + 4; - i_mesh = get_bin_from_indices(ijk0); - i_bin = 4*3*i_mesh + i_surf - 1; - bins.push_back(i_bin); - } - } - } - - // Calculate new coordinates - r0 += distance * u; - } -} - -int RectilinearMesh::get_bin(Position r) const -{ - // Determine indices - int ijk[3]; - bool in_mesh; - get_indices(r, ijk, &in_mesh); - if (!in_mesh) return -1; - - // Convert indices to bin - return get_bin_from_indices(ijk); -} - -int RectilinearMesh::get_bin_from_indices(const int* ijk) const -{ - return ((ijk[2] - 1)*shape_[1] + (ijk[1] - 1))*shape_[0] + ijk[0] - 1; -} - -void RectilinearMesh::get_indices(Position r, int* ijk, bool* in_mesh) const -{ - *in_mesh = true; - - for (int i = 0; i < 3; ++i) { - if (r[i] < grid_[i].front() || r[i] > grid_[i].back()) { - ijk[i] = -1; - *in_mesh = false; - } else { - ijk[i] = lower_bound_index(grid_[i].begin(), grid_[i].end(), r[i]) + 1; - } - } -} - -void RectilinearMesh::get_indices_from_bin(int bin, int* ijk) const -{ - ijk[0] = bin % shape_[0] + 1; - ijk[1] = (bin % (shape_[0] * shape_[1])) / shape_[0] + 1; - ijk[2] = bin / (shape_[0] * shape_[1]) + 1; -} - -int RectilinearMesh::n_bins() const -{ - int n_bins = 1; - for (auto dim : shape_) n_bins *= dim; - return n_bins; -} - -int RectilinearMesh::n_surface_bins() const -{ - return 4 * n_dimension_ * n_bins(); -} - -std::pair, std::vector> -RectilinearMesh::plot(Position plot_ll, Position plot_ur) const -{ - // Figure out which axes lie in the plane of the plot. - std::array axes {-1, -1}; - if (plot_ur.z == plot_ll.z) { - axes = {0, 1}; - } else if (plot_ur.y == plot_ll.y) { - axes = {0, 2}; - } else if (plot_ur.x == plot_ll.x) { - axes = {1, 2}; - } else { - fatal_error("Can only plot mesh lines on an axis-aligned plot"); - } - - // Get the coordinates of the mesh lines along both of the axes. - std::array, 2> axis_lines; - for (int i_ax = 0; i_ax < 2; ++i_ax) { - int axis = axes[i_ax]; - std::vector& lines {axis_lines[i_ax]}; - - for (auto coord : grid_[axis]) { - if (coord >= plot_ll[axis] && coord <= plot_ur[axis]) - lines.push_back(coord); - } - } - - return {axis_lines[0], axis_lines[1]}; -} - -void RectilinearMesh::to_hdf5(hid_t group) const -{ - hid_t mesh_group = create_group(group, "mesh " + std::to_string(id_)); - - write_dataset(mesh_group, "type", "rectilinear"); - write_dataset(mesh_group, "x_grid", grid_[0]); - write_dataset(mesh_group, "y_grid", grid_[1]); - write_dataset(mesh_group, "z_grid", grid_[2]); - - close_group(mesh_group); -} - -bool RectilinearMesh::intersects(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = grid_[0].front(); - double ym0 = grid_[1].front(); - double zm0 = grid_[2].front(); - - // Copy coordinates of mesh upper_right - double xm1 = grid_[0].back(); - double ym1 = grid_[1].back(); - double zm1 = grid_[2].back(); - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects bottom surface -- calculate the intersection - // point (x,y) - if ((z0 < zm0 && z1 > zm0) || (z0 > zm0 && z1 < zm0)) { - double xi = x0 + (zm0 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm0 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm0, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = shape_[1]; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects top surface -- calculate the intersection point - // (x,y) - if ((z0 < zm1 && z1 > zm1) || (z0 > zm1 && z1 < zm1)) { - double xi = x0 + (zm1 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm1 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm1, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = shape_[2]; - } - } - } - - return min_dist < INFTY; -} - -//============================================================================== -// Helper functions for the C API -//============================================================================== - -int -check_mesh(int32_t index) -{ - if (index < 0 || index >= model::meshes.size()) { - set_errmsg("Index in meshes array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -int -check_regular_mesh(int32_t index, RegularMesh** mesh) -{ - if (int err = check_mesh(index)) return err; - *mesh = dynamic_cast(model::meshes[index].get()); - if (!*mesh) { - set_errmsg("This function is only valid for regular meshes."); - return OPENMC_E_INVALID_TYPE; - } - return 0; -} - -//============================================================================== -// C API functions -//============================================================================== - -//! Extend the meshes array by n elements -extern "C" int -openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end) -{ - if (index_start) *index_start = model::meshes.size(); - for (int i = 0; i < n; ++i) { - model::meshes.push_back(std::make_unique()); - } - if (index_end) *index_end = model::meshes.size() - 1; - - return 0; -} - -//! Return the index in the meshes array of a mesh with a given ID -extern "C" int -openmc_get_mesh_index(int32_t id, int32_t* index) -{ - auto pair = model::mesh_map.find(id); - if (pair == model::mesh_map.end()) { - set_errmsg("No mesh exists with ID=" + std::to_string(id) + "."); - return OPENMC_E_INVALID_ID; - } - *index = pair->second; - return 0; -} - -// Return the ID of a mesh -extern "C" int -openmc_mesh_get_id(int32_t index, int32_t* id) -{ - if (int err = check_mesh(index)) return err; - *id = model::meshes[index]->id_; - return 0; -} - -//! Set the ID of a mesh -extern "C" int -openmc_mesh_set_id(int32_t index, int32_t id) -{ - if (int err = check_mesh(index)) return err; - model::meshes[index]->id_ = id; - model::mesh_map[id] = index; - return 0; -} - -//! Get the dimension of a mesh -extern "C" int -openmc_mesh_get_dimension(int32_t index, int** dims, int* n) -{ - RegularMesh* mesh; - if (int err = check_regular_mesh(index, &mesh)) return err; - *dims = mesh->shape_.data(); - *n = mesh->n_dimension_; - return 0; -} - -//! Set the dimension of a mesh -extern "C" int -openmc_mesh_set_dimension(int32_t index, int n, const int* dims) -{ - RegularMesh* mesh; - if (int err = check_regular_mesh(index, &mesh)) return err; - - // Copy dimension - std::vector shape = {static_cast(n)}; - mesh->shape_ = xt::adapt(dims, n, xt::no_ownership(), shape); - mesh->n_dimension_ = mesh->shape_.size(); - - return 0; -} - -//! Get the mesh parameters -extern "C" int -openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n) -{ - RegularMesh* m; - if (int err = check_regular_mesh(index, &m)) return err; - - if (m->lower_left_.dimension() == 0) { - set_errmsg("Mesh parameters have not been set."); - return OPENMC_E_ALLOCATE; - } - - *ll = m->lower_left_.data(); - *ur = m->upper_right_.data(); - *width = m->width_.data(); - *n = m->n_dimension_; - return 0; -} - -//! Set the mesh parameters -extern "C" int -openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, - const double* width) -{ - RegularMesh* m; - if (int err = check_regular_mesh(index, &m)) return err; - - std::vector shape = {static_cast(n)}; - if (ll && ur) { - m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape); - m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape); - m->width_ = (m->upper_right_ - m->lower_left_) / m->shape_; - } else if (ll && width) { - m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape); - m->width_ = xt::adapt(width, n, xt::no_ownership(), shape); - m->upper_right_ = m->lower_left_ + m->shape_ * m->width_; - } else if (ur && width) { - m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape); - m->width_ = xt::adapt(width, n, xt::no_ownership(), shape); - m->lower_left_ = m->upper_right_ - m->shape_ * m->width_; - } else { - set_errmsg("At least two parameters must be specified."); - return OPENMC_E_INVALID_ARGUMENT; - } - - return 0; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_meshes(pugi::xml_node root) -{ - for (auto node : root.children("mesh")) { - std::string mesh_type; - if (check_for_node(node, "type")) { - mesh_type = get_node_value(node, "type", true, true); - } else { - mesh_type = "regular"; - } - - // Read mesh and add to vector - if (mesh_type == "regular") { - model::meshes.push_back(std::make_unique(node)); - } else if (mesh_type == "rectilinear") { - model::meshes.push_back(std::make_unique(node)); - } else { - fatal_error("Invalid mesh type: " + mesh_type); - } - - // Map ID to position in vector - model::mesh_map[model::meshes.back()->id_] = model::meshes.size() - 1; - } -} - -void meshes_to_hdf5(hid_t group) -{ - // Write number of meshes - hid_t meshes_group = create_group(group, "meshes"); - int32_t n_meshes = model::meshes.size(); - write_attribute(meshes_group, "n_meshes", n_meshes); - - if (n_meshes > 0) { - // Write IDs of meshes - std::vector ids; - for (const auto& m : model::meshes) { - m->to_hdf5(meshes_group); - ids.push_back(m->id_); - } - write_attribute(meshes_group, "ids", ids); - } - - close_group(meshes_group); -} - -void free_memory_mesh() -{ - model::meshes.clear(); - model::mesh_map.clear(); -} - -extern "C" int n_meshes() { return model::meshes.size(); } - -} // namespace openmc diff --git a/src/message_passing.cpp b/src/message_passing.cpp deleted file mode 100644 index aea17f9f4..000000000 --- a/src/message_passing.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "openmc/message_passing.h" - -namespace openmc { -namespace mpi { - -int rank {0}; -int n_procs {1}; -bool master {true}; - -#ifdef OPENMC_MPI -MPI_Comm intracomm {MPI_COMM_NULL}; -MPI_Datatype bank {MPI_DATATYPE_NULL}; -#endif - -extern "C" bool openmc_master() { return mpi::master; } - -} // namespace mpi - -} // namespace openmc diff --git a/src/mgxs.cpp b/src/mgxs.cpp deleted file mode 100644 index 1fca66308..000000000 --- a/src/mgxs.cpp +++ /dev/null @@ -1,700 +0,0 @@ -#include "openmc/mgxs.h" - -#include -#include -#include -#include - -#ifdef _OPENMP -#include -#endif - -#include "xtensor/xmath.hpp" -#include "xtensor/xsort.hpp" -#include "xtensor/xadapt.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/mgxs_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/string_utils.h" - - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -// Storage for the MGXS data -std::vector nuclides_MG; -std::vector macro_xs; - -} // namespace data - -//============================================================================== -// Mgxs base-class methods -//============================================================================== - -void -Mgxs::init(const std::string& in_name, double in_awr, - const std::vector& in_kTs, bool in_fissionable, int in_scatter_format, - bool in_is_isotropic, - const std::vector& in_polar, const std::vector& in_azimuthal) -{ - // Set the metadata - name = in_name; - awr = in_awr; - //TODO: Remove adapt when in_KTs is an xtensor - kTs = xt::adapt(in_kTs); - fissionable = in_fissionable; - scatter_format = in_scatter_format; - num_groups = data::num_energy_groups; - num_delayed_groups = data::num_delayed_groups; - xs.resize(in_kTs.size()); - is_isotropic = in_is_isotropic; - n_pol = in_polar.size(); - n_azi = in_azimuthal.size(); - polar = in_polar; - azimuthal = in_azimuthal; - - // Set the cross section index cache -#ifdef _OPENMP - int n_threads = omp_get_max_threads(); -#else - int n_threads = 1; -#endif - cache.resize(n_threads); - // std::vector.resize() will value-initialize the members of cache[:] -} - -//============================================================================== - -void -Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector& temperature, - std::vector& temps_to_read, int& order_dim) -{ - // get name - char char_name[MAX_WORD_LEN]; - get_name(xs_id, char_name); - std::string in_name {char_name}; - // remove the leading '/' - in_name = in_name.substr(1); - - // Get the AWR - double in_awr; - if (attribute_exists(xs_id, "atomic_weight_ratio")) { - read_attr_double(xs_id, "atomic_weight_ratio", &in_awr); - } else { - in_awr = MACROSCOPIC_AWR; - } - - // Determine the available temperatures - hid_t kT_group = open_group(xs_id, "kTs"); - int num_temps = get_num_datasets(kT_group); - char** dset_names = new char*[num_temps]; - for (int i = 0; i < num_temps; i++) { - dset_names[i] = new char[151]; - } - get_datasets(kT_group, dset_names); - xt::xarray available_temps(num_temps); - for (int i = 0; i < num_temps; i++) { - read_double(kT_group, dset_names[i], &available_temps[i], true); - - // convert eV to Kelvin - available_temps[i] /= K_BOLTZMANN; - - // Done with dset_names, so delete it - delete[] dset_names[i]; - } - delete[] dset_names; - std::sort(available_temps.begin(), available_temps.end()); - - // If only one temperature is available, lets just use nearest temperature - // interpolation - if ((num_temps == 1) && (settings::temperature_method == TEMPERATURE_INTERPOLATION)) { - warning("Cross sections for " + strtrim(name) + " are only available " + - "at one temperature. Reverting to the nearest temperature " + - "method."); - settings::temperature_method = TEMPERATURE_NEAREST; - } - - switch(settings::temperature_method) { - case TEMPERATURE_NEAREST: - // Determine actual temperatures to read - for (const auto& T : temperature) { - auto i_closest = xt::argmin(xt::abs(available_temps - T))[0]; - double temp_actual = available_temps[i_closest]; - if (std::fabs(temp_actual - T) < settings::temperature_tolerance) { - if (std::find(temps_to_read.begin(), temps_to_read.end(), std::round(temp_actual)) - == temps_to_read.end()) { - temps_to_read.push_back(std::round(temp_actual)); - } - } else { - std::stringstream msg; - msg << "MGXS library does not contain cross sections for " - << in_name << " at or near " << std::round(T) << " K."; - fatal_error(msg); - } - } - break; - - case TEMPERATURE_INTERPOLATION: - for (int i = 0; i < temperature.size(); i++) { - for (int j = 0; j < num_temps - 1; j++) { - if ((available_temps[j] <= temperature[i]) && - (temperature[i] < available_temps[j + 1])) { - if (std::find(temps_to_read.begin(), - temps_to_read.end(), - std::round(available_temps[j])) == temps_to_read.end()) { - temps_to_read.push_back(std::round((int)available_temps[j])); - } - - if (std::find(temps_to_read.begin(), temps_to_read.end(), - std::round(available_temps[j + 1])) == temps_to_read.end()) { - temps_to_read.push_back(std::round((int) available_temps[j + 1])); - } - continue; - } - } - - fatal_error("MGXS Library does not contain cross sections for " + - in_name + " at temperatures that bound " + - std::to_string(std::round(temperature[i]))); - } - } - std::sort(temps_to_read.begin(), temps_to_read.end()); - - // Get the library's temperatures - int n_temperature = temps_to_read.size(); - std::vector in_kTs(n_temperature); - for (int i = 0; i < n_temperature; i++) { - std::string temp_str(std::to_string(temps_to_read[i]) + "K"); - - //read exact temperature value - read_double(kT_group, temp_str.c_str(), &in_kTs[i], true); - } - close_group(kT_group); - - // Load the remaining metadata - int in_scatter_format; - if (attribute_exists(xs_id, "scatter_format")) { - std::string temp_str(MAX_WORD_LEN, ' '); - read_attr_string(xs_id, "scatter_format", MAX_WORD_LEN, &temp_str[0]); - to_lower(strtrim(temp_str)); - if (temp_str.compare(0, 8, "legendre") == 0) { - in_scatter_format = ANGLE_LEGENDRE; - } else if (temp_str.compare(0, 9, "histogram") == 0) { - in_scatter_format = ANGLE_HISTOGRAM; - } else if (temp_str.compare(0, 7, "tabular") == 0) { - in_scatter_format = ANGLE_TABULAR; - } else { - fatal_error("Invalid scatter_format option!"); - } - } else { - in_scatter_format = ANGLE_LEGENDRE; - } - - if (attribute_exists(xs_id, "scatter_shape")) { - std::string temp_str(MAX_WORD_LEN, ' '); - read_attr_string(xs_id, "scatter_shape", MAX_WORD_LEN, &temp_str[0]); - to_lower(strtrim(temp_str)); - if (temp_str.compare(0, 14, "[g][g\'][order]") != 0) { - fatal_error("Invalid scatter_shape option!"); - } - } - - bool in_fissionable = false; - if (attribute_exists(xs_id, "fissionable")) { - int int_fiss; - read_attr_int(xs_id, "fissionable", &int_fiss); - in_fissionable = int_fiss; - } else { - fatal_error("Fissionable element must be set!"); - } - - // Get the library's value for the order - if (attribute_exists(xs_id, "order")) { - read_attr_int(xs_id, "order", &order_dim); - } else { - fatal_error("Order must be provided!"); - } - - // Store the dimensionality of the data in order_dim. - // For Legendre data, we usually refer to it as Pn where n is the order. - // However Pn has n+1 sets of points (since you need to count the P0 - // moment). Adjust for that. Histogram and Tabular formats dont need this - // adjustment. - if (in_scatter_format == ANGLE_LEGENDRE) { - ++order_dim; - } - - // Get the angular information - int in_n_pol; - int in_n_azi; - bool in_is_isotropic = true; - if (attribute_exists(xs_id, "representation")) { - std::string temp_str(MAX_WORD_LEN, ' '); - read_attr_string(xs_id, "representation", MAX_WORD_LEN, &temp_str[0]); - to_lower(strtrim(temp_str)); - if (temp_str.compare(0, 5, "angle") == 0) { - in_is_isotropic = false; - } else if (temp_str.compare(0, 9, "isotropic") != 0) { - fatal_error("Invalid Data Representation!"); - } - } - - if (!in_is_isotropic) { - if (attribute_exists(xs_id, "num_polar")) { - read_attr_int(xs_id, "num_polar", &in_n_pol); - } else { - fatal_error("num_polar must be provided!"); - } - if (attribute_exists(xs_id, "num_azimuthal")) { - read_attr_int(xs_id, "num_azimuthal", &in_n_azi); - } else { - fatal_error("num_azimuthal must be provided!"); - } - } else { - in_n_pol = 1; - in_n_azi = 1; - } - - // Set the angular bins to use equally-spaced bins - std::vector in_polar(in_n_pol); - double dangle = PI / in_n_pol; - for (int p = 0; p < in_n_pol; p++) { - in_polar[p] = (p + 0.5) * dangle; - } - std::vector in_azimuthal(in_n_azi); - dangle = 2. * PI / in_n_azi; - for (int a = 0; a < in_n_azi; a++) { - in_azimuthal[a] = (a + 0.5) * dangle - PI; - } - - // Finally use this data to initialize the MGXS Object - init(in_name, in_awr, in_kTs, in_fissionable, in_scatter_format, - in_is_isotropic, in_polar, - in_azimuthal); -} - -//============================================================================== - -Mgxs::Mgxs(hid_t xs_id, const std::vector& temperature) -{ - // Call generic data gathering routine (will populate the metadata) - int order_data; - std::vector temps_to_read; - metadata_from_hdf5(xs_id, temperature, temps_to_read, order_data); - - // Set number of energy and delayed groups - int final_scatter_format = scatter_format; - if (settings::legendre_to_tabular) { - if (scatter_format == ANGLE_LEGENDRE) final_scatter_format = ANGLE_TABULAR; - } - - // Load the more specific XsData information - for (int t = 0; t < temps_to_read.size(); t++) { - xs[t] = XsData(fissionable, final_scatter_format, n_pol, n_azi); - // Get the temperature as a string and then open the HDF5 group - std::string temp_str = std::to_string(temps_to_read[t]) + "K"; - hid_t xsdata_grp = open_group(xs_id, temp_str.c_str()); - - xs[t].from_hdf5(xsdata_grp, fissionable, scatter_format, - final_scatter_format, order_data, is_isotropic, n_pol, n_azi); - close_group(xsdata_grp); - - } // end temperature loop - - // Make sure the scattering format is updated to the final case - scatter_format = final_scatter_format; -} - -//============================================================================== - -Mgxs::Mgxs(const std::string& in_name, const std::vector& mat_kTs, - const std::vector& micros, const std::vector& atom_densities) -{ - // Get the minimum data needed to initialize: - // Dont need awr, but lets just initialize it anyways - double in_awr = -1.; - // start with the assumption it is not fissionable - bool in_fissionable = false; - for (int m = 0; m < micros.size(); m++) { - if (micros[m]->fissionable) in_fissionable = true; - } - // Force all of the following data to be the same; these will be verified - // to be true later - int in_scatter_format = micros[0]->scatter_format; - bool in_is_isotropic = micros[0]->is_isotropic; - std::vector in_polar = micros[0]->polar; - std::vector in_azimuthal = micros[0]->azimuthal; - - init(in_name, in_awr, mat_kTs, in_fissionable, in_scatter_format, - in_is_isotropic, in_polar, in_azimuthal); - - // Create the xs data for each temperature - for (int t = 0; t < mat_kTs.size(); t++) { - xs[t] = XsData(in_fissionable, in_scatter_format, in_polar.size(), - in_azimuthal.size()); - - // Find the right temperature index to use - double temp_desired = mat_kTs[t]; - - // Create the list of temperature indices and interpolation factors for - // each microscopic data at the material temperature - std::vector micro_t(micros.size(), 0); - std::vector micro_t_interp(micros.size(), 0.); - for (int m = 0; m < micros.size(); m++) { - switch(settings::temperature_method) { - case TEMPERATURE_NEAREST: - { - micro_t[m] = xt::argmin(xt::abs(micros[m]->kTs - temp_desired))[0]; - auto temp_actual = micros[m]->kTs[micro_t[m]]; - - if (std::abs(temp_actual - temp_desired) >= K_BOLTZMANN * settings::temperature_tolerance) { - std::stringstream msg; - msg << "MGXS Library does not contain cross section for " << name - << " at or near " << std::round(temp_desired / K_BOLTZMANN) << "K."; - fatal_error(msg); - } - } - break; - case TEMPERATURE_INTERPOLATION: - // Get a list of bounding temperatures for each actual temperature - // present in the model - for (int k = 0; k < micros[m]->kTs.shape()[0] - 1; k++) { - if ((micros[m]->kTs[k] <= temp_desired) && - (temp_desired < micros[m]->kTs[k + 1])) { - micro_t[m] = k; - if (k == 0) { - micro_t_interp[m] = (temp_desired - micros[m]->kTs[k]) / - (micros[m]->kTs[k + 1] - micros[m]->kTs[k]); - } else { - micro_t_interp[m] = 1.; - } - } - } - } // end switch - } // end microscopic temperature loop - - // We are about to loop through each of the microscopic objects - // and incorporate the contribution of each microscopic data at - // one of the two temperature interpolants to this macroscopic quantity. - // If we are doing nearest temperature interpolation, then we don't need - // to do the 2nd temperature - int num_interp_points = 2; - if (settings::temperature_method == TEMPERATURE_NEAREST) num_interp_points = 1; - for (int interp_point = 0; interp_point < num_interp_points; interp_point++) { - std::vector interp(micros.size()); - std::vector temp_indices(micros.size()); - for (int m = 0; m < micros.size(); m++) { - interp[m] = (1. - micro_t_interp[m]) * atom_densities[m]; - temp_indices[m] = micro_t[m] + interp_point; - } - - combine(micros, interp, micro_t, t); - } // end loop to sum all micros across the temperatures - } // end temperature (t) loop -} - -//============================================================================== - -void -Mgxs::combine(const std::vector& micros, const std::vector& scalars, - const std::vector& micro_ts, int this_t) -{ - // Build the vector of pointers to the xs objects within micros - std::vector those_xs(micros.size()); - for (int i = 0; i < micros.size(); i++) { - if (!xs[this_t].equiv(micros[i]->xs[micro_ts[i]])) { - fatal_error("Cannot combine the Mgxs objects!"); - } - those_xs[i] = &(micros[i]->xs[micro_ts[i]]); - } - - xs[this_t].combine(those_xs, scalars); -} - -//============================================================================== - -double -Mgxs::get_xs(int xstype, int gin, const int* gout, const double* mu, - const int* dg) -{ - // This method assumes that the temperature and angle indices are set -#ifdef _OPENMP - int tid = omp_get_thread_num(); - XsData* xs_t = &xs[cache[tid].t]; - int a = cache[tid].a; -#else - XsData* xs_t = &xs[cache[0].t]; - int a = cache[0].a; -#endif - double val; - switch(xstype) { - case MG_GET_XS_TOTAL: - val = xs_t->total(a, gin); - break; - case MG_GET_XS_NU_FISSION: - val = fissionable ? xs_t->nu_fission(a, gin) : 0.; - break; - case MG_GET_XS_ABSORPTION: - val = xs_t->absorption(a, gin);; - break; - case MG_GET_XS_FISSION: - val = fissionable ? xs_t->fission(a, gin) : 0.; - break; - case MG_GET_XS_KAPPA_FISSION: - val = fissionable ? xs_t->kappa_fission(a, gin) : 0.; - break; - case MG_GET_XS_SCATTER: - case MG_GET_XS_SCATTER_MULT: - case MG_GET_XS_SCATTER_FMU_MULT: - case MG_GET_XS_SCATTER_FMU: - val = xs_t->scatter[a]->get_xs(xstype, gin, gout, mu); - break; - case MG_GET_XS_PROMPT_NU_FISSION: - val = fissionable ? xs_t->prompt_nu_fission(a, gin) : 0.; - break; - case MG_GET_XS_DELAYED_NU_FISSION: - if (fissionable) { - if (dg != nullptr) { - val = xs_t->delayed_nu_fission(a, *dg, gin); - } else { - val = 0.; - for (int d = 0; d < xs_t->delayed_nu_fission.shape()[1]; d++) { - val += xs_t->delayed_nu_fission(a, d, gin); - } - } - } else { - val = 0.; - } - break; - case MG_GET_XS_CHI_PROMPT: - if (fissionable) { - if (gout != nullptr) { - val = xs_t->chi_prompt(a, gin, *gout); - } else { - // provide an outgoing group-wise sum - val = 0.; - for (int g = 0; g < xs_t->chi_prompt.shape()[2]; g++) { - val += xs_t->chi_prompt(a, gin, g); - } - } - } else { - val = 0.; - } - break; - case MG_GET_XS_CHI_DELAYED: - if (fissionable) { - if (gout != nullptr) { - if (dg != nullptr) { - val = xs_t->chi_delayed(a, *dg, gin, *gout); - } else { - val = xs_t->chi_delayed(a, 0, gin, *gout); - } - } else { - if (dg != nullptr) { - val = 0.; - for (int g = 0; g < xs_t->delayed_nu_fission.shape()[2]; g++) { - val += xs_t->delayed_nu_fission(a, *dg, gin, g); - } - } else { - val = 0.; - for (int g = 0; g < xs_t->delayed_nu_fission.shape()[2]; g++) { - for (int d = 0; d < xs_t->delayed_nu_fission.shape()[3]; d++) { - val += xs_t->delayed_nu_fission(a, d, gin, g); - } - } - } - } - } else { - val = 0.; - } - break; - case MG_GET_XS_INVERSE_VELOCITY: - val = xs_t->inverse_velocity(a, gin); - break; - case MG_GET_XS_DECAY_RATE: - if (dg != nullptr) { - val = xs_t->decay_rate(a, *dg); - } else { - val = xs_t->decay_rate(a, 0); - } - break; - default: - val = 0.; - } - return val; -} - -//============================================================================== - -void -Mgxs::sample_fission_energy(int gin, int& dg, int& gout) -{ - // This method assumes that the temperature and angle indices are set -#ifdef _OPENMP - int tid = omp_get_thread_num(); -#else - int tid = 0; -#endif - XsData* xs_t = &xs[cache[tid].t]; - double nu_fission = xs_t->nu_fission(cache[tid].a, gin); - - // Find the probability of having a prompt neutron - double prob_prompt = - xs_t->prompt_nu_fission(cache[tid].a, gin); - - // sample random numbers - double xi_pd = prn() * nu_fission; - double xi_gout = prn(); - - // Select whether the neutron is prompt or delayed - if (xi_pd <= prob_prompt) { - // the neutron is prompt - - // set the delayed group for the particle to be -1, indicating prompt - dg = -1; - - // sample the outgoing energy group - gout = 0; - double prob_gout = - xs_t->chi_prompt(cache[tid].a, gin, gout); - while (prob_gout < xi_gout) { - gout++; - prob_gout += xs_t->chi_prompt(cache[tid].a, gin, gout); - } - - } else { - // the neutron is delayed - - // get the delayed group - dg = 0; - while (xi_pd >= prob_prompt) { - dg++; - prob_prompt += - xs_t->delayed_nu_fission(cache[tid].a, dg, gin); - } - - // adjust dg in case of round-off error - dg = std::min(dg, num_delayed_groups - 1); - - // sample the outgoing energy group - gout = 0; - double prob_gout = - xs_t->chi_delayed(cache[tid].a, dg, gin, gout); - while (prob_gout < xi_gout) { - gout++; - prob_gout += - xs_t->chi_delayed(cache[tid].a, dg, gin, gout); - } - } -} - -//============================================================================== - -void -Mgxs::sample_scatter(int gin, int& gout, double& mu, double& wgt) -{ - // This method assumes that the temperature and angle indices are set - // Sample the data -#ifdef _OPENMP - int tid = omp_get_thread_num(); -#else - int tid = 0; -#endif - xs[cache[tid].t].scatter[cache[tid].a]->sample(gin, gout, mu, wgt); -} - -//============================================================================== - -void -Mgxs::calculate_xs(int gin, double sqrtkT, Direction u, - double& total_xs, double& abs_xs, double& nu_fiss_xs) -{ - // Set our indices -#ifdef _OPENMP - int tid = omp_get_thread_num(); -#else - int tid = 0; -#endif - set_temperature_index(sqrtkT); - set_angle_index(u); - XsData* xs_t = &xs[cache[tid].t]; - total_xs = xs_t->total(cache[tid].a, gin); - abs_xs = xs_t->absorption(cache[tid].a, gin); - - nu_fiss_xs = fissionable ? xs_t->nu_fission(cache[tid].a, gin) : 0.; -} - -//============================================================================== - -bool -Mgxs::equiv(const Mgxs& that) -{ - return ((num_delayed_groups == that.num_delayed_groups) && - (num_groups == that.num_groups) && - (n_pol == that.n_pol) && - (n_azi == that.n_azi) && - (std::equal(polar.begin(), polar.end(), that.polar.begin())) && - (std::equal(azimuthal.begin(), azimuthal.end(), that.azimuthal.begin())) && - (scatter_format == that.scatter_format)); -} - -//============================================================================== - -void -Mgxs::set_temperature_index(double sqrtkT) -{ - // See if we need to find the new index -#ifdef _OPENMP - int tid = omp_get_thread_num(); -#else - int tid = 0; -#endif - if (sqrtkT != cache[tid].sqrtkT) { - cache[tid].t = xt::argmin(xt::abs(kTs - sqrtkT * sqrtkT))[0]; - cache[tid].sqrtkT = sqrtkT; - } -} - -//============================================================================== - -void -Mgxs::set_angle_index(Direction u) -{ - // See if we need to find the new index -#ifdef _OPENMP - int tid = omp_get_thread_num(); -#else - int tid = 0; -#endif - if (!is_isotropic && - ((u.x != cache[tid].u) || (u.y != cache[tid].v) || - (u.z != cache[tid].w))) { - // convert direction to polar and azimuthal angles - double my_pol = std::acos(u.z); - double my_azi = std::atan2(u.y, u.x); - - // Find the location, assuming equal-bin angles - double delta_angle = PI / n_pol; - int p = std::floor(my_pol / delta_angle); - delta_angle = 2. * PI / n_azi; - int a = std::floor((my_azi + PI) / delta_angle); - - cache[tid].a = n_azi * p + a; - - // store this direction as the last one used - cache[tid].u = u.x; - cache[tid].v = u.y; - cache[tid].w = u.z; - } -} - -} // namespace openmc diff --git a/src/mgxs_interface.cpp b/src/mgxs_interface.cpp deleted file mode 100644 index 29e5e8b36..000000000 --- a/src/mgxs_interface.cpp +++ /dev/null @@ -1,319 +0,0 @@ -#include "openmc/mgxs_interface.h" - -#include -#include - -#include "openmc/cell.h" -#include "openmc/cross_sections.h" -#include "openmc/container_util.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/geometry_aux.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/math_functions.h" -#include "openmc/nuclide.h" -#include "openmc/settings.h" - - -namespace openmc { - -//============================================================================== -// Global variable definitions -//============================================================================== - -namespace data { - -int num_energy_groups; -int num_delayed_groups; -std::vector energy_bins; -std::vector energy_bin_avg; -std::vector rev_energy_bins; - -} // namesapce data - -//============================================================================== -// Mgxs data loading interface methods -//============================================================================== - -void read_mgxs() -{ - // Check if MGXS Library exists - if (!file_exists(settings::path_cross_sections)) { - // Could not find MGXS Library file - fatal_error("Cross sections HDF5 file '" + settings::path_cross_sections + - "' does not exist."); - } - - write_message("Loading cross section data...", 5); - - // Get temperatures - std::vector> nuc_temps(data::nuclide_map.size()); - std::vector> dummy; - get_temperatures(nuc_temps, dummy); - - // Open file for reading - hid_t file_id = file_open(settings::path_cross_sections, 'r'); - - // Read filetype - std::string type; - read_attribute(file_id, "filetype", type); - if (type != "mgxs") { - fatal_error("Provided MGXS Library is not a MGXS Library file."); - } - - // Read revision number for the MGXS Library file and make sure it matches - // with the current version - std::array array; - read_attribute(file_id, "version", array); - if (array != VERSION_MGXS_LIBRARY) { - fatal_error("MGXS Library file version does not match current version " - "supported by OpenMC."); - } - - // ========================================================================== - // READ ALL MGXS CROSS SECTION TABLES - - std::unordered_set already_read; - - // Build vector of nuclide names - std::vector nuclide_names(data::nuclide_map.size()); - for (const auto& kv : data::nuclide_map) { - nuclide_names[kv.second] = kv.first; - } - - // Loop over all files - for (const auto& mat : model::materials) { - for (int i_nuc : mat->nuclide_) { - std::string& name = nuclide_names[i_nuc]; - - if (already_read.find(name) == already_read.end()) { - add_mgxs(file_id, name, nuc_temps[i_nuc]); - already_read.insert(name); - } - - if (data::nuclides_MG[i_nuc].fissionable) { - mat->fissionable_ = true; - } - } - } - - file_close(file_id); -} - -//============================================================================== - -void -add_mgxs(hid_t file_id, const std::string& name, - const std::vector& temperature) -{ - write_message("Loading " + std::string(name) + " data...", 6); - - // Check to make sure cross section set exists in the library - hid_t xs_grp; - if (object_exists(file_id, name.c_str())) { - xs_grp = open_group(file_id, name.c_str()); - } else { - fatal_error("Data for " + std::string(name) + " does not exist in " - + "provided MGXS Library"); - } - - data::nuclides_MG.emplace_back(xs_grp, temperature); - close_group(xs_grp); -} - -//============================================================================== - -void create_macro_xs() -{ - // Get temperatures to read for each material - auto kTs = get_mat_kTs(); - - // Force all nuclides in a material to be the same representation. - // Therefore type(nuclides[mat->nuclide_[0]]) dictates type(macroxs). - // At the same time, we will find the scattering type, as that will dictate - // how we allocate the scatter object within macroxs. - for (int i = 0; i < model::materials.size(); ++i) { - if (kTs[i].size() > 0) { - // Convert atom_densities to a vector - auto& mat {model::materials[i]}; - std::vector atom_densities(mat->atom_density_.begin(), - mat->atom_density_.end()); - - // Build array of pointers to nuclides_MG's Mgxs objects needed for this - // material - std::vector mgxs_ptr; - for (int i_nuclide : mat->nuclide_) { - mgxs_ptr.push_back(&data::nuclides_MG[i_nuclide]); - } - - data::macro_xs.emplace_back(mat->name_, kTs[i], mgxs_ptr, atom_densities); - } else { - // Preserve the ordering of materials by including a blank entry - data::macro_xs.emplace_back(); - } - } -} - -//============================================================================== - -std::vector> get_mat_kTs() -{ - std::vector> kTs(model::materials.size()); - - for (const auto& cell : model::cells) { - // Skip non-material cells - if (cell->fill_ != C_NONE) continue; - - for (int j = 0; j < cell->material_.size(); ++j) { - // Skip void materials - int i_material = cell->material_[j]; - if (i_material == MATERIAL_VOID) continue; - - // Get temperature of cell (rounding to nearest integer) - double sqrtkT = cell->sqrtkT_.size() == 1 ? - cell->sqrtkT_[j] : cell->sqrtkT_[0]; - double kT = sqrtkT * sqrtkT; - - // Add temperature if it hasn't already been added - if (!contains(kTs[i_material], kT)) { - kTs[i_material].push_back(kT); - } - } - } - return kTs; -} - -//============================================================================== - -void read_mg_cross_sections_header() -{ - // Check if MGXS Library exists - if (!file_exists(settings::path_cross_sections)) { - // Could not find MGXS Library file - fatal_error("Cross sections HDF5 file '" + settings::path_cross_sections + - "' does not exist."); - } - write_message("Reading cross sections HDF5 file...", 5); - - // Open file for reading - hid_t file_id = file_open(settings::path_cross_sections, 'r', true); - - ensure_exists(file_id, "energy_groups", true); - read_attribute(file_id, "energy_groups", data::num_energy_groups); - - if (attribute_exists(file_id, "delayed_groups")) { - read_attribute(file_id, "delayed_groups", data::num_delayed_groups); - } else { - data::num_delayed_groups = 0; - } - - ensure_exists(file_id, "group structure", true); - read_attribute(file_id, "group structure", data::rev_energy_bins); - - // Reverse energy bins - std::copy(data::rev_energy_bins.crbegin(), data::rev_energy_bins.crend(), - std::back_inserter(data::energy_bins)); - - // Create average energies - for (int i = 0; i < data::energy_bins.size() - 1; ++i) { - data::energy_bin_avg.push_back(0.5*(data::energy_bins[i] + data::energy_bins[i+1])); - } - - // Add entries into libraries for MG data - auto names = group_names(file_id); - if (names.empty()) { - fatal_error("At least one MGXS data set must be present in mgxs " - "library file!"); - } - - for (auto& name : names) { - Library lib {}; - lib.type_ = Library::Type::neutron; - lib.materials_.push_back(name); - data::libraries.push_back(lib); - } - - // Get the minimum and maximum energies - int neutron = static_cast(Particle::Type::neutron); - data::energy_min[neutron] = data::energy_bins.back(); - data::energy_max[neutron] = data::energy_bins.front(); - - // Close MGXS HDF5 file - file_close(file_id); -} - -//============================================================================== -// Mgxs tracking/transport/tallying interface methods -//============================================================================== - -void -calculate_xs_c(int i_mat, int gin, double sqrtkT, Direction u, - double& total_xs, double& abs_xs, double& nu_fiss_xs) -{ - data::macro_xs[i_mat].calculate_xs(gin - 1, sqrtkT, u, total_xs, abs_xs, - nu_fiss_xs); -} - -//============================================================================== - -double -get_nuclide_xs(int index, int xstype, int gin, const int* gout, - const double* mu, const int* dg) -{ - int gout_c; - const int* gout_c_p; - if (gout != nullptr) { - gout_c = *gout - 1; - gout_c_p = &gout_c; - } else { - gout_c_p = gout; - } - return data::nuclides_MG[index].get_xs(xstype, gin - 1, gout_c_p, mu, dg); -} - -//============================================================================== - -double -get_macro_xs(int index, int xstype, int gin, const int* gout, - const double* mu, const int* dg) -{ - int gout_c; - const int* gout_c_p; - if (gout != nullptr) { - gout_c = *gout - 1; - gout_c_p = &gout_c; - } else { - gout_c_p = gout; - } - return data::macro_xs[index].get_xs(xstype, gin - 1, gout_c_p, mu, dg); -} - -//============================================================================== -// General Mgxs methods -//============================================================================== - -void -get_name_c(int index, int name_len, char* name) -{ - // First blank out our input string - std::string str(name_len - 1, ' '); - std::strcpy(name, str.c_str()); - - // Now get the data and copy to the C-string - str = data::nuclides_MG[index - 1].name; - std::strcpy(name, str.c_str()); - - // Finally, remove the null terminator - name[std::strlen(name)] = ' '; -} - -//============================================================================== - -double -get_awr_c(int index) -{ - return data::nuclides_MG[index - 1].awr; -} - -} // namespace openmc diff --git a/src/nuclide.cpp b/src/nuclide.cpp deleted file mode 100644 index 3b092ddf4..000000000 --- a/src/nuclide.cpp +++ /dev/null @@ -1,977 +0,0 @@ -#include "openmc/nuclide.h" - -#include "openmc/capi.h" -#include "openmc/container_util.h" -#include "openmc/cross_sections.h" -#include "openmc/endf.h" -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/message_passing.h" -#include "openmc/photon.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/thermal.h" - -#include "xtensor/xbuilder.hpp" -#include "xtensor/xview.hpp" - -#include // for sort, min_element -#include // for to_string, stoi - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { -std::array energy_min {0.0, 0.0}; -std::array energy_max {INFTY, INFTY}; -double temperature_min {0.0}; -double temperature_max {INFTY}; -std::vector> nuclides; -std::unordered_map nuclide_map; -} // namespace data - -//============================================================================== -// Nuclide implementation -//============================================================================== - -int Nuclide::XS_TOTAL {0}; -int Nuclide::XS_ABSORPTION {1}; -int Nuclide::XS_FISSION {2}; -int Nuclide::XS_NU_FISSION {3}; -int Nuclide::XS_PHOTON_PROD {4}; - -Nuclide::Nuclide(hid_t group, const std::vector& temperature, int i_nuclide) - : i_nuclide_{i_nuclide} -{ - // Get name of nuclide from group, removing leading '/' - name_ = object_name(group).substr(1); - - read_attribute(group, "Z", Z_); - read_attribute(group, "A", A_); - read_attribute(group, "metastable", metastable_); - read_attribute(group, "atomic_weight_ratio", awr_); - - // Determine temperatures available - hid_t kT_group = open_group(group, "kTs"); - auto dset_names = dataset_names(kT_group); - std::vector temps_available; - for (const auto& name : dset_names) { - double T; - read_dataset(kT_group, name.c_str(), T); - temps_available.push_back(T / K_BOLTZMANN); - } - std::sort(temps_available.begin(), temps_available.end()); - - // If only one temperature is available, revert to nearest temperature - if (temps_available.size() == 1 && settings::temperature_method == TEMPERATURE_INTERPOLATION) { - if (mpi::master) { - warning("Cross sections for " + name_ + " are only available at one " - "temperature. Reverting to nearest temperature method."); - } - settings::temperature_method = TEMPERATURE_NEAREST; - } - - // Determine actual temperatures to read -- start by checking whether a - // temperature range was given, in which case all temperatures in the range - // are loaded irrespective of what temperatures actually appear in the model - std::vector temps_to_read; - int n = temperature.size(); - double T_min = n > 0 ? settings::temperature_range[0] : 0.0; - double T_max = n > 0 ? settings::temperature_range[1] : INFTY; - if (T_max > 0.0) { - for (auto T : temps_available) { - if (T_min <= T && T <= T_max) { - temps_to_read.push_back(std::round(T)); - } - } - } - - switch (settings::temperature_method) { - case TEMPERATURE_NEAREST: - // Find nearest temperatures - for (double T_desired : temperature) { - - // Determine closest temperature - double min_delta_T = INFTY; - double T_actual = 0.0; - for (auto T : temps_available) { - double delta_T = std::abs(T - T_desired); - if (delta_T < min_delta_T) { - T_actual = T; - min_delta_T = delta_T; - } - } - - if (std::abs(T_actual - T_desired) < settings::temperature_tolerance) { - if (!contains(temps_to_read, std::round(T_actual))) { - temps_to_read.push_back(std::round(T_actual)); - - // Write warning for resonance scattering data if 0K is not available - if (std::abs(T_actual - T_desired) > 0 && T_desired == 0 && mpi::master) { - warning(name_ + " does not contain 0K data needed for resonance " - "scattering options selected. Using data at " + std::to_string(T_actual) - + " K instead."); - } - } - } else { - fatal_error("Nuclear data library does not contain cross sections for " + - name_ + " at or near " + std::to_string(T_desired) + " K."); - } - } - break; - - case TEMPERATURE_INTERPOLATION: - // If temperature interpolation or multipole is selected, get a list of - // bounding temperatures for each actual temperature present in the model - for (double T_desired : temperature) { - bool found_pair = false; - for (int j = 0; j < temps_available.size() - 1; ++j) { - if (temps_available[j] <= T_desired && T_desired < temps_available[j + 1]) { - int T_j = std::round(temps_available[j]); - int T_j1 = std::round(temps_available[j+1]); - if (!contains(temps_to_read, T_j)) { - temps_to_read.push_back(T_j); - } - if (!contains(temps_to_read, T_j1)) { - temps_to_read.push_back(T_j1); - } - found_pair = true; - } - } - - if (!found_pair) { - fatal_error("Nuclear data library does not contain cross sections for " + - name_ +" at temperatures that bound " + std::to_string(T_desired) + " K."); - } - } - break; - } - - // Sort temperatures to read - std::sort(temps_to_read.begin(), temps_to_read.end()); - - double T_min_read = *std::min_element(temps_to_read.cbegin(), temps_to_read.cend()); - double T_max_read = *std::max_element(temps_to_read.cbegin(), temps_to_read.cend()); - - data::temperature_min = std::max(data::temperature_min, T_min_read); - data::temperature_max = std::min(data::temperature_max, T_max_read); - - hid_t energy_group = open_group(group, "energy"); - for (const auto& T : temps_to_read) { - std::string dset {std::to_string(T) + "K"}; - - // Determine exact kT values - double kT; - read_dataset(kT_group, dset.c_str(), kT); - kTs_.push_back(kT); - - // Read energy grid - grid_.emplace_back(); - read_dataset(energy_group, dset.c_str(), grid_.back().energy); - } - close_group(kT_group); - - // Check for 0K energy grid - if (object_exists(energy_group, "0K")) { - read_dataset(energy_group, "0K", energy_0K_); - } - close_group(energy_group); - - // Read reactions - hid_t rxs_group = open_group(group, "reactions"); - for (auto name : group_names(rxs_group)) { - if (starts_with(name, "reaction_")) { - hid_t rx_group = open_group(rxs_group, name.c_str()); - reactions_.push_back(std::make_unique(rx_group, temps_to_read)); - - // Check for 0K elastic scattering - const auto& rx = reactions_.back(); - if (rx->mt_ == ELASTIC) { - if (object_exists(rx_group, "0K")) { - hid_t temp_group = open_group(rx_group, "0K"); - read_dataset(temp_group, "xs", elastic_0K_); - close_group(temp_group); - } - } - close_group(rx_group); - - // Determine reaction indices for inelastic scattering reactions - if (is_inelastic_scatter(rx->mt_) && !rx->redundant_) { - index_inelastic_scatter_.push_back(reactions_.size() - 1); - } - } - } - close_group(rxs_group); - - // Read unresolved resonance probability tables if present - if (object_exists(group, "urr")) { - urr_present_ = true; - urr_data_.reserve(temps_to_read.size()); - - for (int i = 0; i < temps_to_read.size(); i++) { - // Get temperature as a string - std::string temp_str {std::to_string(temps_to_read[i]) + "K"}; - - // Read probability tables for i-th temperature - hid_t urr_group = open_group(group, ("urr/" + temp_str).c_str()); - urr_data_.emplace_back(urr_group); - close_group(urr_group); - - // Check for negative values - if (xt::any(urr_data_[i].prob_ < 0.) && mpi::master) { - warning("Negative value(s) found on probability table for nuclide " + - name_ + " at " + temp_str); - } - } - - // If the inelastic competition flag indicates that the inelastic cross - // section should be determined from a normal reaction cross section, we - // need to get the index of the reaction. - if (temps_to_read.size() > 0) { - if (urr_data_[0].inelastic_flag_ > 0) { - for (int i = 0; i < reactions_.size(); i++) { - if (reactions_[i]->mt_ == urr_data_[0].inelastic_flag_) { - urr_inelastic_ = i; - } - } - - // Abort if no corresponding inelastic reaction was found - if (urr_inelastic_ == C_NONE) { - fatal_error("Could no find inelastic reaction specified on " - "unresolved resonance probability table."); - } - } - } - } - - // Check for total nu data - if (object_exists(group, "total_nu")) { - // Read total nu data - hid_t nu_group = open_group(group, "total_nu"); - total_nu_ = read_function(nu_group, "yield"); - close_group(nu_group); - } - - // Read fission energy release data if present - if (object_exists(group, "fission_energy_release")) { - hid_t fer_group = open_group(group, "fission_energy_release"); - fission_q_prompt_ = read_function(fer_group, "q_prompt"); - fission_q_recov_ = read_function(fer_group, "q_recoverable"); - close_group(fer_group); - } - - this->create_derived(); -} - -void Nuclide::create_derived() -{ - for (const auto& grid : grid_) { - // Allocate and initialize cross section - std::array shape {grid.energy.size(), 5}; - xs_.emplace_back(shape, 0.0); - } - - reaction_index_.fill(C_NONE); - for (int i = 0; i < reactions_.size(); ++i) { - const auto& rx {reactions_[i]}; - - // Set entry in direct address table for reaction - reaction_index_[rx->mt_] = i; - - for (int t = 0; t < kTs_.size(); ++t) { - int j = rx->xs_[t].threshold; - int n = rx->xs_[t].value.size(); - auto xs = xt::adapt(rx->xs_[t].value); - - for (const auto& p : rx->products_) { - if (p.particle_ == Particle::Type::photon) { - auto pprod = xt::view(xs_[t], xt::range(j, j+n), XS_PHOTON_PROD); - for (int k = 0; k < n; ++k) { - double E = grid_[t].energy[k+j]; - pprod[k] += xs[k] * (*p.yield_)(E); - } - } - } - - // Skip redundant reactions - if (rx->redundant_) continue; - - // Add contribution to total cross section - auto total = xt::view(xs_[t], xt::range(j,j+n), XS_TOTAL); - total += xs; - - // Add contribution to absorption cross section - auto absorption = xt::view(xs_[t], xt::range(j,j+n), XS_ABSORPTION); - if (is_disappearance(rx->mt_)) { - absorption += xs; - } - - if (is_fission(rx->mt_)) { - fissionable_ = true; - auto fission = xt::view(xs_[t], xt::range(j,j+n), XS_FISSION); - fission += xs; - absorption += xs; - - // Keep track of fission reactions - if (t == 0) { - fission_rx_.push_back(rx.get()); - if (rx->mt_ == N_F) has_partial_fission_ = true; - } - } - } - } - - // Determine number of delayed neutron precursors - if (fissionable_) { - for (const auto& product : fission_rx_[0]->products_) { - if (product.emission_mode_ == EmissionMode::delayed) { - ++n_precursor_; - } - } - } - - // Calculate nu-fission cross section - for (int t = 0; t < kTs_.size(); ++t) { - if (fissionable_) { - int n = grid_[t].energy.size(); - for (int i = 0; i < n; ++i) { - double E = grid_[t].energy[i]; - xs_[t](i, XS_NU_FISSION) = nu(E, EmissionMode::total) - * xs_[t](i, XS_FISSION); - } - } - } - - if (settings::res_scat_on) { - // Determine if this nuclide should be treated as a resonant scatterer - if (!settings::res_scat_nuclides.empty()) { - // If resonant nuclides were specified, check the list explicitly - for (const auto& name : settings::res_scat_nuclides) { - if (name_ == name) { - resonant_ = true; - - // Make sure nuclide has 0K data - if (energy_0K_.empty()) { - fatal_error("Cannot treat " + name_ + " as a resonant scatterer " - "because 0 K elastic scattering data is not present."); - } - break; - } - } - } else { - // Otherwise, assume that any that have 0 K elastic scattering data are - // resonant - resonant_ = !energy_0K_.empty(); - } - - if (resonant_) { - // Build CDF for 0K elastic scattering - double xs_cdf_sum = 0.0; - xs_cdf_.resize(energy_0K_.size()); - xs_cdf_[0] = 0.0; - - const auto& E = energy_0K_; - auto& xs = elastic_0K_; - for (int i = 0; i < E.size() - 1; ++i) { - // Negative cross sections result in a CDF that is not monotonically - // increasing. Set all negative xs values to zero. - if (xs[i] < 0.0) xs[i] = 0.0; - - // build xs cdf - xs_cdf_sum += (std::sqrt(E[i])*xs[i] + std::sqrt(E[i+1])*xs[i+1]) - / 2.0 * (E[i+1] - E[i]); - xs_cdf_[i] = xs_cdf_sum; - } - } - } -} - -void Nuclide::init_grid() -{ - int neutron = static_cast(Particle::Type::neutron); - double E_min = data::energy_min[neutron]; - double E_max = data::energy_max[neutron]; - int M = settings::n_log_bins; - - // Determine equal-logarithmic energy spacing - double spacing = std::log(E_max/E_min)/M; - - // Create equally log-spaced energy grid - auto umesh = xt::linspace(0.0, M*spacing, M+1); - - for (auto& grid : grid_) { - // Resize array for storing grid indices - grid.grid_index.resize(M + 1); - - // Determine corresponding indices in nuclide grid to energies on - // equal-logarithmic grid - int j = 0; - for (int k = 0; k <= M; ++k) { - while (std::log(grid.energy[j + 1]/E_min) <= umesh(k)) { - // Ensure that for isotopes where maxval(grid.energy) << E_max that - // there are no out-of-bounds issues. - if (j + 2 == grid.energy.size()) break; - ++j; - } - grid.grid_index[k] = j; - } - } -} - -double Nuclide::nu(double E, EmissionMode mode, int group) const -{ - if (!fissionable_) return 0.0; - - switch (mode) { - case EmissionMode::prompt: - return (*fission_rx_[0]->products_[0].yield_)(E); - case EmissionMode::delayed: - if (n_precursor_ > 0) { - auto rx = fission_rx_[0]; - if (group >= 1 && group < rx->products_.size()) { - // If delayed group specified, determine yield immediately - return (*rx->products_[group].yield_)(E); - } else { - double nu {0.0}; - - for (int i = 1; i < rx->products_.size(); ++i) { - // Skip any non-neutron products - const auto& product = rx->products_[i]; - if (product.particle_ != Particle::Type::neutron) continue; - - // Evaluate yield - if (product.emission_mode_ == EmissionMode::delayed) { - nu += (*product.yield_)(E); - } - } - return nu; - } - } else { - return 0.0; - } - case EmissionMode::total: - if (total_nu_) { - return (*total_nu_)(E); - } else { - return (*fission_rx_[0]->products_[0].yield_)(E); - } - } - UNREACHABLE(); -} - -void Nuclide::calculate_elastic_xs(Particle& p) const -{ - // Get temperature index, grid index, and interpolation factor - auto& micro {p.neutron_xs_[i_nuclide_]}; - int i_temp = micro.index_temp; - int i_grid = micro.index_grid; - double f = micro.interp_factor; - - if (i_temp >= 0) { - const auto& xs = reactions_[0]->xs_[i_temp].value; - micro.elastic = (1.0 - f)*xs[i_grid] + f*xs[i_grid + 1]; - } -} - -double Nuclide::elastic_xs_0K(double E) const -{ - // Determine index on nuclide energy grid - int i_grid; - if (E < energy_0K_.front()) { - i_grid = 0; - } else if (E > energy_0K_.back()) { - i_grid = energy_0K_.size() - 2; - } else { - i_grid = lower_bound_index(energy_0K_.begin(), energy_0K_.end(), E); - } - - // check for rare case where two energy points are the same - if (energy_0K_[i_grid] == energy_0K_[i_grid+1]) ++i_grid; - - // calculate interpolation factor - double f = (E - energy_0K_[i_grid]) / - (energy_0K_[i_grid + 1] - energy_0K_[i_grid]); - - // Calculate microscopic nuclide elastic cross section - return (1.0 - f)*elastic_0K_[i_grid] + f*elastic_0K_[i_grid + 1]; -} - -void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle& p) -{ - auto& micro {p.neutron_xs_[i_nuclide_]}; - - // Initialize cached cross sections to zero - micro.elastic = CACHE_INVALID; - micro.thermal = 0.0; - micro.thermal_elastic = 0.0; - - // Check to see if there is multipole data present at this energy - bool use_mp = false; - if (multipole_) { - use_mp = (p.E_ >= multipole_->E_min_ && p.E_ <= multipole_->E_max_); - } - - // Evaluate multipole or interpolate - if (use_mp) { - // Call multipole kernel - double sig_s, sig_a, sig_f; - std::tie(sig_s, sig_a, sig_f) = multipole_->evaluate(p.E_, p.sqrtkT_); - - micro.total = sig_s + sig_a; - micro.elastic = sig_s; - micro.absorption = sig_a; - micro.fission = sig_f; - micro.nu_fission = fissionable_ ? - sig_f * this->nu(p.E_, EmissionMode::total) : 0.0; - - if (simulation::need_depletion_rx) { - // Only non-zero reaction is (n,gamma) - micro.reaction[0] = sig_a - sig_f; - - // Set all other reaction cross sections to zero - for (int i = 1; i < DEPLETION_RX.size(); ++i) { - micro.reaction[i] = 0.0; - } - } - - // Ensure these values are set - // Note, the only time either is used is in one of 4 places: - // 1. physics.cpp - scatter - For inelastic scatter. - // 2. physics.cpp - sample_fission - For partial fissions. - // 3. tally.F90 - score_general - For tallying on MTxxx reactions. - // 4. nuclide.cpp - calculate_urr_xs - For unresolved purposes. - // It is worth noting that none of these occur in the resolved - // resonance range, so the value here does not matter. index_temp is - // set to -1 to force a segfault in case a developer messes up and tries - // to use it with multipole. - micro.index_temp = -1; - micro.index_grid = -1; - micro.interp_factor = 0.0; - - } else { - // Find the appropriate temperature index. - double kT = p.sqrtkT_*p.sqrtkT_; - double f; - int i_temp = -1; - switch (settings::temperature_method) { - case TEMPERATURE_NEAREST: - { - double max_diff = INFTY; - for (int t = 0; t < kTs_.size(); ++t) { - double diff = std::abs(kTs_[t] - kT); - if (diff < max_diff) { - i_temp = t; - max_diff = diff; - } - } - } - break; - - case TEMPERATURE_INTERPOLATION: - // Find temperatures that bound the actual temperature - for (i_temp = 0; i_temp < kTs_.size() - 1; ++i_temp) { - if (kTs_[i_temp] <= kT && kT < kTs_[i_temp + 1]) break; - } - - // Randomly sample between temperature i and i+1 - f = (kT - kTs_[i_temp]) / (kTs_[i_temp + 1] - kTs_[i_temp]); - if (f > prn()) ++i_temp; - break; - } - - // Determine the energy grid index using a logarithmic mapping to - // reduce the energy range over which a binary search needs to be - // performed - - const auto& grid {grid_[i_temp]}; - const auto& xs {xs_[i_temp]}; - - int i_grid; - if (p.E_ < grid.energy.front()) { - i_grid = 0; - } else if (p.E_ > grid.energy.back()) { - i_grid = grid.energy.size() - 2; - } else { - // Determine bounding indices based on which equal log-spaced - // interval the energy is in - int i_low = grid.grid_index[i_log_union]; - int i_high = grid.grid_index[i_log_union + 1] + 1; - - // Perform binary search over reduced range - i_grid = i_low + lower_bound_index(&grid.energy[i_low], &grid.energy[i_high], p.E_); - } - - // check for rare case where two energy points are the same - if (grid.energy[i_grid] == grid.energy[i_grid + 1]) ++i_grid; - - // calculate interpolation factor - f = (p.E_ - grid.energy[i_grid]) / - (grid.energy[i_grid + 1]- grid.energy[i_grid]); - - micro.index_temp = i_temp; - micro.index_grid = i_grid; - micro.interp_factor = f; - - // Calculate microscopic nuclide total cross section - micro.total = (1.0 - f)*xs(i_grid, XS_TOTAL) - + f*xs(i_grid + 1, XS_TOTAL); - - // Calculate microscopic nuclide absorption cross section - micro.absorption = (1.0 - f)*xs(i_grid, XS_ABSORPTION) - + f*xs(i_grid + 1, XS_ABSORPTION); - - if (fissionable_) { - // Calculate microscopic nuclide total cross section - micro.fission = (1.0 - f)*xs(i_grid, XS_FISSION) - + f*xs(i_grid + 1, XS_FISSION); - - // Calculate microscopic nuclide nu-fission cross section - micro.nu_fission = (1.0 - f)*xs(i_grid, XS_NU_FISSION) - + f*xs(i_grid + 1, XS_NU_FISSION); - } else { - micro.fission = 0.0; - micro.nu_fission = 0.0; - } - - // Calculate microscopic nuclide photon production cross section - micro.photon_prod = (1.0 - f)*xs(i_grid, XS_PHOTON_PROD) - + f*xs(i_grid + 1, XS_PHOTON_PROD); - - // Depletion-related reactions - if (simulation::need_depletion_rx) { - // Initialize all reaction cross sections to zero - for (double& xs_i : micro.reaction) { - xs_i = 0.0; - } - - for (int j = 0; j < DEPLETION_RX.size(); ++j) { - // If reaction is present and energy is greater than threshold, set the - // reaction xs appropriately - int i_rx = reaction_index_[DEPLETION_RX[j]]; - if (i_rx >= 0) { - const auto& rx = reactions_[i_rx]; - const auto& rx_xs = rx->xs_[i_temp].value; - - // Physics says that (n,gamma) is not a threshold reaction, so we don't - // need to specifically check its threshold index - if (j == 0) { - micro.reaction[0] = (1.0 - f)*rx_xs[i_grid] - + f*rx_xs[i_grid + 1]; - continue; - } - - int threshold = rx->xs_[i_temp].threshold; - if (i_grid >= threshold) { - micro.reaction[j] = (1.0 - f)*rx_xs[i_grid - threshold] + - f*rx_xs[i_grid - threshold + 1]; - } else if (j >= 3) { - // One can show that the the threshold for (n,(x+1)n) is always - // higher than the threshold for (n,xn). Thus, if we are below - // the threshold for, e.g., (n,2n), there is no reason to check - // the threshold for (n,3n) and (n,4n). - break; - } - } - } - } - } - - // Initialize sab treatment to false - micro.index_sab = C_NONE; - micro.sab_frac = 0.0; - - // Initialize URR probability table treatment to false - micro.use_ptable = false; - - // If there is S(a,b) data for this nuclide, we need to set the sab_scatter - // and sab_elastic cross sections and correct the total and elastic cross - // sections. - - if (i_sab >= 0) this->calculate_sab_xs(i_sab, sab_frac, p); - - // If the particle is in the unresolved resonance range and there are - // probability tables, we need to determine cross sections from the table - if (settings::urr_ptables_on && urr_present_ && !use_mp) { - int n = urr_data_[micro.index_temp].n_energy_; - if ((p.E_ > urr_data_[micro.index_temp].energy_(0)) && - (p.E_ < urr_data_[micro.index_temp].energy_(n-1))) { - this->calculate_urr_xs(micro.index_temp, p); - } - } - - micro.last_E = p.E_; - micro.last_sqrtkT = p.sqrtkT_; -} - -void Nuclide::calculate_sab_xs(int i_sab, double sab_frac, Particle& p) -{ - auto& micro {p.neutron_xs_[i_nuclide_]}; - - // Set flag that S(a,b) treatment should be used for scattering - micro.index_sab = i_sab; - - // Calculate the S(a,b) cross section - int i_temp; - double elastic; - double inelastic; - data::thermal_scatt[i_sab]->calculate_xs(p.E_, p.sqrtkT_, &i_temp, &elastic, &inelastic); - - // Store the S(a,b) cross sections. - micro.thermal = sab_frac * (elastic + inelastic); - micro.thermal_elastic = sab_frac * elastic; - - // Calculate free atom elastic cross section - this->calculate_elastic_xs(p); - - // Correct total and elastic cross sections - micro.total = micro.total + micro.thermal - sab_frac*micro.elastic; - micro.elastic = micro.thermal + (1.0 - sab_frac)*micro.elastic; - - // Save temperature index and thermal fraction - micro.index_temp_sab = i_temp; - micro.sab_frac = sab_frac; -} - -void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const -{ - auto& micro = p.neutron_xs_[i_nuclide_]; - micro.use_ptable = true; - - // Create a shorthand for the URR data - const auto& urr = urr_data_[i_temp]; - - // Determine the energy table - int i_energy = 0; - while (p.E_ >= urr.energy_(i_energy + 1)) {++i_energy;}; - - // Sample the probability table using the cumulative distribution - - // Random nmbers for the xs calculation are sampled from a separate stream. - // This guarantees the randomness and, at the same time, makes sure we - // reuse random numbers for the same nuclide at different temperatures, - // therefore preserving correlation of temperature in probability tables. - prn_set_stream(STREAM_URR_PTABLE); - //TODO: to maintain the same random number stream as the Fortran code this - //replaces, the seed is set with i_nuclide_ + 1 instead of i_nuclide_ - double r = future_prn(static_cast(i_nuclide_ + 1)); - prn_set_stream(STREAM_TRACKING); - - int i_low = 0; - while (urr.prob_(i_energy, URR_CUM_PROB, i_low) <= r) {++i_low;}; - - int i_up = 0; - while (urr.prob_(i_energy + 1, URR_CUM_PROB, i_up) <= r) {++i_up;}; - - // Determine elastic, fission, and capture cross sections from the - // probability table - double elastic = 0.; - double fission = 0.; - double capture = 0.; - double f; - if (urr.interp_ == Interpolation::lin_lin) { - // Determine the interpolation factor on the table - f = (p.E_ - urr.energy_(i_energy)) / - (urr.energy_(i_energy + 1) - urr.energy_(i_energy)); - - elastic = (1. - f) * urr.prob_(i_energy, URR_ELASTIC, i_low) + - f * urr.prob_(i_energy + 1, URR_ELASTIC, i_up); - fission = (1. - f) * urr.prob_(i_energy, URR_FISSION, i_low) + - f * urr.prob_(i_energy + 1, URR_FISSION, i_up); - capture = (1. - f) * urr.prob_(i_energy, URR_N_GAMMA, i_low) + - f * urr.prob_(i_energy + 1, URR_N_GAMMA, i_up); - } else if (urr.interp_ == Interpolation::log_log) { - // Determine interpolation factor on the table - f = std::log(p.E_ / urr.energy_(i_energy)) / - std::log(urr.energy_(i_energy + 1) / urr.energy_(i_energy)); - - // Calculate the elastic cross section/factor - if ((urr.prob_(i_energy, URR_ELASTIC, i_low) > 0.) && - (urr.prob_(i_energy + 1, URR_ELASTIC, i_up) > 0.)) { - elastic = - std::exp((1. - f) * - std::log(urr.prob_(i_energy, URR_ELASTIC, i_low)) + - f * std::log(urr.prob_(i_energy + 1, URR_ELASTIC, i_up))); - } else { - elastic = 0.; - } - - // Calculate the fission cross section/factor - if ((urr.prob_(i_energy, URR_FISSION, i_low) > 0.) && - (urr.prob_(i_energy + 1, URR_FISSION, i_up) > 0.)) { - fission = - std::exp((1. - f) * - std::log(urr.prob_(i_energy, URR_FISSION, i_low)) + - f * std::log(urr.prob_(i_energy + 1, URR_FISSION, i_up))); - } else { - fission = 0.; - } - - // Calculate the capture cross section/factor - if ((urr.prob_(i_energy, URR_N_GAMMA, i_low) > 0.) && - (urr.prob_(i_energy + 1, URR_N_GAMMA, i_up) > 0.)) { - capture = - std::exp((1. - f) * - std::log(urr.prob_(i_energy, URR_N_GAMMA, i_low)) + - f * std::log(urr.prob_(i_energy + 1, URR_N_GAMMA, i_up))); - } else { - capture = 0.; - } - } - - // Determine the treatment of inelastic scattering - double inelastic = 0.; - if (urr.inelastic_flag_ != C_NONE) { - // get interpolation factor - f = micro.interp_factor; - - // Determine inelastic scattering cross section - Reaction* rx = reactions_[urr_inelastic_].get(); - int xs_index = micro.index_grid - rx->xs_[i_temp].threshold; - if (xs_index >= 0) { - inelastic = (1. - f) * rx->xs_[i_temp].value[xs_index] + - f * rx->xs_[i_temp].value[xs_index + 1]; - } - } - - // Multiply by smooth cross-section if needed - if (urr.multiply_smooth_) { - calculate_elastic_xs(p); - elastic *= micro.elastic; - capture *= (micro.absorption - micro.fission); - fission *= micro.fission; - } - - // Check for negative values - if (elastic < 0.) {elastic = 0.;} - if (fission < 0.) {fission = 0.;} - if (capture < 0.) {capture = 0.;} - - // Set elastic, absorption, fission, and total x/s. Note that the total x/s - // is calculated as a sum of partials instead of the table-provided value - micro.elastic = elastic; - micro.absorption = capture + fission; - micro.fission = fission; - micro.total = elastic + inelastic + capture + fission; - - // Determine nu-fission cross-section - if (fissionable_) { - micro.nu_fission = nu(p.E_, EmissionMode::total) * micro.fission; - } - -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void check_data_version(hid_t file_id) -{ - if (attribute_exists(file_id, "version")) { - std::vector version; - read_attribute(file_id, "version", version); - if (version[0] != HDF5_VERSION[0]) { - fatal_error("HDF5 data format uses version " + std::to_string(version[0]) - + "." + std::to_string(version[1]) + " whereas your installation of " - "OpenMC expects version " + std::to_string(HDF5_VERSION[0]) - + ".x data."); - } - } else { - fatal_error("HDF5 data does not indicate a version. Your installation of " - "OpenMC expects version " + std::to_string(HDF5_VERSION[0]) + - ".x data."); - } -} - -extern "C" size_t -nuclides_size() -{ - return data::nuclides.size(); -} - -//============================================================================== -// C API -//============================================================================== - -extern "C" int openmc_load_nuclide(const char* name) -{ - if (data::nuclide_map.find(name) == data::nuclide_map.end()) { - const auto& it = data::library_map.find({Library::Type::neutron, name}); - if (it != data::library_map.end()) { - // Get filename for library containing nuclide - int idx = it->second; - std::string& filename = data::libraries[idx].path_; - write_message("Reading " + std::string{name} + " from " + filename, 6); - - // Open file and make sure version is sufficient - hid_t file_id = file_open(filename, 'r'); - check_data_version(file_id); - - // Read nuclide data from HDF5 - hid_t group = open_group(file_id, name); - std::vector temperature; - int i_nuclide = data::nuclides.size(); - data::nuclides.push_back(std::make_unique( - group, temperature, i_nuclide)); - - close_group(group); - file_close(file_id); - - // Add entry to nuclide dictionary - data::nuclide_map[name] = i_nuclide; - - // Initialize nuclide grid - data::nuclides.back()->init_grid(); - - // Read multipole file into the appropriate entry on the nuclides array - if (settings::temperature_multipole) read_multipole_data(i_nuclide); - } else { - set_errmsg("Nuclide '" + std::string{name} + "' is not present in library."); - return OPENMC_E_DATA; - } - } - return 0; -} - -extern "C" int -openmc_get_nuclide_index(const char* name, int* index) -{ - auto it = data::nuclide_map.find(name); - if (it == data::nuclide_map.end()) { - set_errmsg("No nuclide named '" + std::string{name} + "' has been loaded."); - return OPENMC_E_DATA; - } - *index = it->second; - return 0; -} - -extern "C" int -openmc_nuclide_name(int index, const char** name) -{ - if (index >= 0 && index < data::nuclides.size()) { - *name = data::nuclides[index]->name_.data(); - return 0; - } else { - set_errmsg("Index in nuclides vector is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } -} - -void nuclides_clear() -{ - data::nuclides.clear(); - data::nuclide_map.clear(); -} - -bool multipole_in_range(const Nuclide* nuc, double E) -{ - return nuc->multipole_ && E >= nuc->multipole_->E_min_&& - E <= nuc->multipole_->E_max_; -} - -} // namespace openmc diff --git a/src/output.cpp b/src/output.cpp deleted file mode 100644 index d3262cc4d..000000000 --- a/src/output.cpp +++ /dev/null @@ -1,736 +0,0 @@ -#include "openmc/output.h" - -#include // for std::transform -#include // for strlen -#include // for time, localtime -#include // for setw, setprecision, put_time -#include // for fixed, scientific, left -#include -#include -#include -#include -#include // for pair - -#ifdef _OPENMP -#include -#endif -#include "xtensor/xview.hpp" - -#include "openmc/capi.h" -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/geometry.h" -#include "openmc/lattice.h" -#include "openmc/math_functions.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/plot.h" -#include "openmc/reaction.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/surface.h" -#include "openmc/tallies/derivative.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/tally.h" -#include "openmc/tallies/tally_scoring.h" -#include "openmc/timer.h" - -namespace openmc { - -//============================================================================== - -void title() -{ - std::cout << - " %%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%%%%%%%%%%%%%%\n" << - " ############### %%%%%%%%%%%%%%%%%%%%%%%%\n" << - " ################## %%%%%%%%%%%%%%%%%%%%%%%\n" << - " ################### %%%%%%%%%%%%%%%%%%%%%%%\n" << - " #################### %%%%%%%%%%%%%%%%%%%%%%\n" << - " ##################### %%%%%%%%%%%%%%%%%%%%%\n" << - " ###################### %%%%%%%%%%%%%%%%%%%%\n" << - " ####################### %%%%%%%%%%%%%%%%%%\n" << - " ####################### %%%%%%%%%%%%%%%%%\n" << - " ###################### %%%%%%%%%%%%%%%%%\n" << - " #################### %%%%%%%%%%%%%%%%%\n" << - " ################# %%%%%%%%%%%%%%%%%\n" << - " ############### %%%%%%%%%%%%%%%%\n" << - " ############ %%%%%%%%%%%%%%%\n" << - " ######## %%%%%%%%%%%%%%\n" << - " %%%%%%%%%%%\n\n"; - - // Write version information - std::cout << - " | The OpenMC Monte Carlo Code\n" << - " Copyright | 2011-2019 MIT and OpenMC contributors\n" << - " License | http://openmc.readthedocs.io/en/latest/license.html\n" << - " Version | " << VERSION_MAJOR << '.' << VERSION_MINOR << '.' - << VERSION_RELEASE << (VERSION_DEV ? "-dev" : "") << '\n'; -#ifdef GIT_SHA1 - std::cout << " Git SHA1 | " << GIT_SHA1 << '\n'; -#endif - - // Write the date and time - std::cout << " Date/Time | " << time_stamp() << '\n'; - -#ifdef OPENMC_MPI - // Write number of processors - std::cout << " MPI Processes | " << mpi::n_procs << '\n'; -#endif - -#ifdef _OPENMP - // Write number of OpenMP threads - std::cout << " OpenMP Threads | " << omp_get_max_threads() << '\n'; -#endif - std::cout << '\n'; -} - -//============================================================================== - -std::string -header(const char* msg) { - // Determine how many times to repeat the '=' character. - int n_prefix = (63 - strlen(msg)) / 2; - int n_suffix = n_prefix; - if ((strlen(msg) % 2) == 0) ++n_suffix; - - // Convert to uppercase. - std::string upper(msg); - std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper); - - // Add ===> <=== markers. - std::stringstream out; - out << ' '; - for (int i = 0; i < n_prefix; i++) out << '='; - out << "> " << upper << " <"; - for (int i = 0; i < n_suffix; i++) out << '='; - - return out.str(); -} - -std::string header(const std::string& msg) {return header(msg.c_str());} - -void -header(const char* msg, int level) { - auto out = header(msg); - - // Print header based on verbosity level. - if (settings::verbosity >= level) - std::cout << '\n' << out << "\n\n"; -} - -//============================================================================== - -std::string time_stamp() -{ - std::stringstream ts; - std::time_t t = std::time(nullptr); // get time now - ts << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S"); - return ts.str(); -} - -//============================================================================== - -extern "C" void print_particle(Particle* p) -{ - // Display particle type and ID. - switch (p->type_) { - case Particle::Type::neutron: - std::cout << "Neutron "; - break; - case Particle::Type::photon: - std::cout << "Photon "; - break; - case Particle::Type::electron: - std::cout << "Electron "; - break; - case Particle::Type::positron: - std::cout << "Positron "; - break; - default: - std::cout << "Unknown Particle "; - } - std::cout << p->id_ << "\n"; - - // Display particle geometry hierarchy. - for (auto i = 0; i < p->n_coord_; i++) { - std::cout << " Level " << i << "\n"; - - if (p->coord_[i].cell != C_NONE) { - const Cell& c {*model::cells[p->coord_[i].cell]}; - std::cout << " Cell = " << c.id_ << "\n"; - } - - if (p->coord_[i].universe != C_NONE) { - const Universe& u {*model::universes[p->coord_[i].universe]}; - std::cout << " Universe = " << u.id_ << "\n"; - } - - if (p->coord_[i].lattice != C_NONE) { - const Lattice& lat {*model::lattices[p->coord_[i].lattice]}; - std::cout << " Lattice = " << lat.id_ << "\n"; - std::cout << " Lattice position = (" << p->coord_[i].lattice_x - << "," << p->coord_[i].lattice_y << "," - << p->coord_[i].lattice_z << ")\n"; - } - - std::cout << " r = (" << p->coord_[i].r.x << ", " - << p->coord_[i].r.y << ", " << p->coord_[i].r.z << ")\n"; - std::cout << " u = (" << p->coord_[i].u.x << ", " - << p->coord_[i].u.y << ", " << p->coord_[i].u.z << ")\n"; - } - - // Display miscellaneous info. - if (p->surface_ != 0) { - const Surface& surf {*model::surfaces[std::abs(p->surface_)-1]}; - std::cout << " Surface = " << std::copysign(surf.id_, p->surface_) << "\n"; - } - std::cout << " Weight = " << p->wgt_ << "\n"; - if (settings::run_CE) { - std::cout << " Energy = " << p->E_ << "\n"; - } else { - std::cout << " Energy Group = " << p->g_ << "\n"; - } - std::cout << " Delayed Group = " << p->delayed_group_ << "\n"; - - std::cout << "\n"; -} - -//============================================================================== - -void print_plot() -{ - header("PLOTTING SUMMARY", 5); - if (settings::verbosity < 5) return; - - for (auto pl : model::plots) { - // Plot id - std::cout << "Plot ID: " << pl.id_ << "\n"; - // Plot filename - std::cout << "Plot file: " << pl.path_plot_ << "\n"; - // Plot level - std::cout << "Universe depth: " << pl.level_ << "\n"; - - // Plot type - if (PlotType::slice == pl.type_) { - std::cout << "Plot Type: Slice" << "\n"; - } else if (PlotType::voxel == pl.type_) { - std::cout << "Plot Type: Voxel" << "\n"; - } - - // Plot parameters - std::cout << "Origin: " << pl.origin_[0] << " " - << pl.origin_[1] << " " - << pl.origin_[2] << "\n"; - - if (PlotType::slice == pl.type_) { - std::cout << std::setprecision(4) - << "Width: " - << pl.width_[0] << " " - << pl.width_[1] << "\n"; - } else if (PlotType::voxel == pl.type_) { - std::cout << std::setprecision(4) - << "Width: " - << pl.width_[0] << " " - << pl.width_[1] << " " - << pl.width_[2] << "\n"; - } - - if (PlotColorBy::cells == pl.color_by_) { - std::cout << "Coloring: Cells" << "\n"; - } else if (PlotColorBy::mats == pl.color_by_) { - std::cout << "Coloring: Materials" << "\n"; - } - - if (PlotType::slice == pl.type_) { - switch(pl.basis_) { - case PlotBasis::xy: - std::cout << "Basis: XY" << "\n"; - break; - case PlotBasis::xz: - std::cout << "Basis: XZ" << "\n"; - break; - case PlotBasis::yz: - std::cout << "Basis: YZ" << "\n"; - break; - } - std::cout << "Pixels: " << pl.pixels_[0] << " " - << pl.pixels_[1] << " " << "\n"; - } else if (PlotType::voxel == pl.type_) { - std::cout << "Voxels: " << pl.pixels_[0] << " " - << pl.pixels_[1] << " " - << pl.pixels_[2] << "\n"; - } - - std::cout << "\n"; - - } -} - -//============================================================================== - -void -print_overlap_check() -{ - #ifdef OPENMC_MPI - std::vector temp(model::overlap_check_count); - MPI_Reduce(temp.data(), model::overlap_check_count.data(), - model::overlap_check_count.size(), MPI_INT64_T, - MPI_SUM, 0, mpi::intracomm); - #endif - - if (mpi::master) { - header("cell overlap check summary", 1); - std::cout << " Cell ID No. Overlap Checks\n"; - - std::vector sparse_cell_ids; - for (int i = 0; i < model::cells.size(); i++) { - std::cout << " " << std::setw(8) << model::cells[i]->id_ << std::setw(17) - << model::overlap_check_count[i] << "\n"; - if (model::overlap_check_count[i] < 10) { - sparse_cell_ids.push_back(model::cells[i]->id_); - } - } - - std::cout << "\n There were " << sparse_cell_ids.size() - << " cells with less than 10 overlap checks\n"; - for (auto id : sparse_cell_ids) { - std::cout << " " << id; - } - std::cout << "\n"; - } -} - -//============================================================================== - -void print_usage() -{ - if (mpi::master) { - std::cout << - "Usage: openmc [options] [directory]\n\n" - "Options:\n" - " -c, --volume Run in stochastic volume calculation mode\n" - " -g, --geometry-debug Run with geometry debugging on\n" - " -n, --particles Number of particles per generation\n" - " -p, --plot Run in plotting mode\n" - " -r, --restart Restart a previous run from a state point\n" - " or a particle restart file\n" - " -s, --threads Number of OpenMP threads\n" - " -t, --track Write tracks for all particles\n" - " -v, --version Show version information\n" - " -h, --help Show this message\n"; - } -} - -//============================================================================== - -void print_version() -{ - if (mpi::master) { - std::cout << "OpenMC version " << VERSION_MAJOR << '.' << VERSION_MINOR - << '.' << VERSION_RELEASE << '\n'; -#ifdef GIT_SHA1 - std::cout << "Git SHA1: " << GIT_SHA1 << '\n'; -#endif - std::cout << "Copyright (c) 2011-2019 Massachusetts Institute of " - "Technology and OpenMC contributors\nMIT/X license at " - "\n"; - } -} - -//============================================================================== - -void print_columns() -{ - if (settings::entropy_on) { - std::cout << - " Bat./Gen. k Entropy Average k \n" - " ========= ======== ======== ====================\n"; - } else { - std::cout << - " Bat./Gen. k Average k\n" - " ========= ======== ====================\n"; - } -} - -//============================================================================== - -void print_generation() -{ - // Save state of cout - auto f {std::cout.flags()}; - - // Determine overall generation and number of active generations - int i = overall_generation() - 1; - int n = simulation::current_batch > settings::n_inactive ? - settings::gen_per_batch*simulation::n_realizations + simulation::current_gen : 0; - - // Set format for values - std::cout << std::fixed << std::setprecision(5); - - // write out information batch and option independent output - std::cout << " " << std::setw(9) << std::to_string(simulation::current_batch) - + "/" + std::to_string(simulation::current_gen) << " " << std::setw(8) - << simulation::k_generation[i]; - - // write out entropy info - if (settings::entropy_on) { - std::cout << " " << std::setw(8) << simulation::entropy[i]; - } - - if (n > 1) { - std::cout << " " << std::setw(8) << simulation::keff << " +/-" - << std::setw(8) << simulation::keff_std; - } - std::cout << '\n'; - - // Restore state of cout - std::cout.flags(f); -} - -//============================================================================== - -void print_batch_keff() -{ - // Save state of cout - auto f {std::cout.flags()}; - - // Determine overall generation and number of active generations - int i = simulation::current_batch*settings::gen_per_batch - 1; - int n = simulation::n_realizations*settings::gen_per_batch; - - // Set format for values - std::cout << std::fixed << std::setprecision(5); - - // write out information batch and option independent output - std::cout << " " << std::setw(9) << std::to_string(simulation::current_batch) - + "/" + std::to_string(settings::gen_per_batch) << " " << std::setw(8) - << simulation::k_generation[i]; - - // write out entropy info - if (settings::entropy_on) { - std::cout << " " << std::setw(8) << simulation::entropy[i]; - } - - if (n > 1) { - std::cout << " " << std::setw(8) << simulation::keff << " +/-" - << std::setw(8) << simulation::keff_std; - } - std::cout << std::endl; - - // Restore state of cout - std::cout.flags(f); -} - -//============================================================================== - -void show_time(const char* label, double secs, int indent_level=0) -{ - std::cout << std::string(2*indent_level, ' '); - int width = 33 - indent_level*2; - std::cout << " " << std::setw(width) << std::left << label << " = " - << std::setw(10) << std::right << secs << " seconds\n"; -} - -void show_rate(const char* label, double particles_per_sec) -{ - std::cout << " " << std::setw(33) << std::left << label << " = " << - particles_per_sec << " particles/second\n"; -} - -void print_runtime() -{ - using namespace simulation; - - // display header block - header("Timing Statistics", 6); - if (settings::verbosity < 6) return; - - // Save state of cout - auto f {std::cout.flags()}; - - // display time elapsed for various sections - std::cout << std::scientific << std::setprecision(4); - show_time("Total time for initialization", time_initialize.elapsed()); - show_time("Reading cross sections", time_read_xs.elapsed(), 1); - show_time("Total time in simulation", time_inactive.elapsed() + - time_active.elapsed()); - show_time("Time in transport only", time_transport.elapsed(), 1); - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - show_time("Time in inactive batches", time_inactive.elapsed(), 1); - } - show_time("Time in active batches", time_active.elapsed(), 1); - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - show_time("Time synchronizing fission bank", time_bank.elapsed(), 1); - show_time("Sampling source sites", time_bank_sample.elapsed(), 2); - show_time("SEND/RECV source sites", time_bank_sendrecv.elapsed(), 2); - } - show_time("Time accumulating tallies", time_tallies.elapsed(), 1); - show_time("Total time for finalization", time_finalize.elapsed()); - show_time("Total time elapsed", time_total.elapsed()); - - // Restore state of cout - std::cout.flags(f); - - // Calculate particle rate in active/inactive batches - int n_active = simulation::current_batch - settings::n_inactive; - double speed_inactive = 0.0; - double speed_active; - if (settings::restart_run) { - if (simulation::restart_batch < settings::n_inactive) { - speed_inactive = (settings::n_particles * (settings::n_inactive - - simulation::restart_batch) * settings::gen_per_batch) - / time_inactive.elapsed(); - speed_active = (settings::n_particles * n_active - * settings::gen_per_batch) / time_active.elapsed(); - } else { - speed_active = (settings::n_particles * (settings::n_batches - - simulation::restart_batch) * settings::gen_per_batch) - / time_active.elapsed(); - } - } else { - if (settings::n_inactive > 0) { - speed_inactive = (settings::n_particles * settings::n_inactive - * settings::gen_per_batch) / time_inactive.elapsed(); - } - speed_active = (settings::n_particles * n_active * settings::gen_per_batch) - / time_active.elapsed(); - } - - // display calculation rate - std::cout << std::setprecision(6) << std::showpoint; - if (!(settings::restart_run && (simulation::restart_batch >= settings::n_inactive)) - && settings::n_inactive > 0) { - show_rate("Calculation Rate (inactive)", speed_inactive); - } - show_rate("Calculation Rate (active)", speed_active); - - // Restore state of cout - std::cout.flags(f); -} - -//============================================================================== - -std::pair -mean_stdev(const double* x, int n) -{ - double mean = x[RESULT_SUM] / n; - double stdev = n > 1 ? std::sqrt((x[RESULT_SUM_SQ]/n - - mean*mean)/(n - 1)) : 0.0; - return {mean, stdev}; -} - -//============================================================================== - -void print_results() -{ - // Save state of cout - auto f {std::cout.flags()}; - - // display header block for results - header("Results", 4); - if (settings::verbosity < 4) return; - - // Calculate t-value for confidence intervals - int n = simulation::n_realizations; - double alpha, t_n1, t_n3; - if (settings::confidence_intervals) { - alpha = 1.0 - CONFIDENCE_LEVEL; - t_n1 = t_percentile(1.0 - alpha/2.0, n - 1); - t_n3 = t_percentile(1.0 - alpha/2.0, n - 3); - } else { - t_n1 = 1.0; - t_n3 = 1.0; - } - - // Set formatting for floats - std::cout << std::fixed << std::setprecision(5); - - // write global tallies - const auto& gt = simulation::global_tallies; - double mean, stdev; - if (n > 1) { - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - std::tie(mean, stdev) = mean_stdev(>(K_COLLISION, 0), n); - std::cout << " k-effective (Collision) = " - << mean << " +/- " << t_n1 * stdev << '\n'; - std::tie(mean, stdev) = mean_stdev(>(K_TRACKLENGTH, 0), n); - std::cout << " k-effective (Track-length) = " - << mean << " +/- " << t_n1 * stdev << '\n'; - std::tie(mean, stdev) = mean_stdev(>(K_ABSORPTION, 0), n); - std::cout << " k-effective (Absorption) = " - << mean << " +/- " << t_n1 * stdev << '\n'; - if (n > 3) { - double k_combined[2]; - openmc_get_keff(k_combined); - std::cout << " Combined k-effective = " - << k_combined[0] << " +/- " << t_n3 * k_combined[1] << '\n'; - } - } - std::tie(mean, stdev) = mean_stdev(>(LEAKAGE, 0), n); - std::cout << " Leakage Fraction = " - << mean << " +/- " << t_n1 * stdev << '\n'; - } else { - if (mpi::master) warning("Could not compute uncertainties -- only one " - "active batch simulated!"); - - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - std::cout << " k-effective (Collision) = " - << gt(K_COLLISION, RESULT_SUM) / n << '\n'; - std::cout << " k-effective (Track-length) = " - << gt(K_TRACKLENGTH, RESULT_SUM) / n << '\n'; - std::cout << " k-effective (Absorption) = " - << gt(K_ABSORPTION, RESULT_SUM) / n << '\n'; - } - std::cout << " Leakage Fraction = " - << gt(LEAKAGE, RESULT_SUM) / n << '\n'; - } - std::cout << '\n'; - - // Restore state of cout - std::cout.flags(f); -} - -//============================================================================== - -const std::unordered_map score_names = { - {SCORE_FLUX, "Flux"}, - {SCORE_TOTAL, "Total Reaction Rate"}, - {SCORE_SCATTER, "Scattering Rate"}, - {SCORE_NU_SCATTER, "Scattering Production Rate"}, - {SCORE_ABSORPTION, "Absorption Rate"}, - {SCORE_FISSION, "Fission Rate"}, - {SCORE_NU_FISSION, "Nu-Fission Rate"}, - {SCORE_KAPPA_FISSION, "Kappa-Fission Rate"}, - {SCORE_EVENTS, "Events"}, - {SCORE_DECAY_RATE, "Decay Rate"}, - {SCORE_DELAYED_NU_FISSION, "Delayed-Nu-Fission Rate"}, - {SCORE_PROMPT_NU_FISSION, "Prompt-Nu-Fission Rate"}, - {SCORE_INVERSE_VELOCITY, "Flux-Weighted Inverse Velocity"}, - {SCORE_FISS_Q_PROMPT, "Prompt fission power"}, - {SCORE_FISS_Q_RECOV, "Recoverable fission power"}, - {SCORE_CURRENT, "Current"}, -}; - -//! Create an ASCII output file showing all tally results. - -void -write_tallies() -{ - if (model::tallies.empty()) return; - - // Open the tallies.out file. - std::ofstream tallies_out; - tallies_out.open("tallies.out", std::ios::out | std::ios::trunc); - tallies_out << std::setprecision(6); - - // Loop over each tally. - for (auto i_tally = 0; i_tally < model::tallies.size(); ++i_tally) { - const auto& tally {*model::tallies[i_tally]}; - - // Write header block. - std::string tally_header("TALLY " + std::to_string(tally.id_)); - if (!tally.name_.empty()) tally_header += ": " + tally.name_; - tallies_out << header(tally_header) << "\n\n"; - - if (!tally.writable_) { - tallies_out << " Internal\n\n"; - continue; - } - - // Calculate t-value for confidence intervals - double t_value = 1; - if (settings::confidence_intervals) { - auto alpha = 1 - CONFIDENCE_LEVEL; - t_value = t_percentile(1 - alpha*0.5, tally.n_realizations_ - 1); - } - - // Write derivative information. - if (tally.deriv_ != C_NONE) { - const auto& deriv {model::tally_derivs[tally.deriv_]}; - switch (deriv.variable) { - case DIFF_DENSITY: - tallies_out << " Density derivative Material " - << std::to_string(deriv.diff_material) << "\n"; - break; - case DIFF_NUCLIDE_DENSITY: - tallies_out << " Nuclide density derivative Material " - << std::to_string(deriv.diff_material) << " Nuclide " - << data::nuclides[deriv.diff_nuclide]->name_ << "\n"; - break; - case DIFF_TEMPERATURE: - tallies_out << " Temperature derivative Material " - << std::to_string(deriv.diff_material) << "\n"; - break; - default: - fatal_error("Differential tally dependent variable for tally " - + std::to_string(tally.id_) + " not defined in output.cpp"); - } - } - - // Loop over all filter bin combinations. - auto filter_iter = FilterBinIter(tally, false); - auto end = FilterBinIter(tally, true); - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - - // Print info about this combination of filter bins. The stride check - // prevents redundant output. - int indent = 0; - for (auto i = 0; i < tally.filters().size(); ++i) { - if (filter_index % tally.strides(i) == 0) { - auto i_filt = tally.filters(i); - const auto& filt {*model::tally_filters[i_filt]}; - auto& match {simulation::filter_matches[i_filt]}; - tallies_out << std::string(indent+1, ' ') - << filt.text_label(match.i_bin_) << "\n"; - } - indent += 2; - } - - // Loop over all nuclide and score combinations. - int score_index = 0; - for (auto i_nuclide : tally.nuclides_) { - // Write label for this nuclide bin. - if (i_nuclide == -1) { - tallies_out << std::string(indent+1, ' ') << "Total Material\n"; - } else { - if (settings::run_CE) { - tallies_out << std::string(indent+1, ' ') - << data::nuclides[i_nuclide]->name_ << "\n"; - } else { - tallies_out << std::string(indent+1, ' ') - << data::nuclides_MG[i_nuclide].name << "\n"; - } - } - - // Write the score, mean, and uncertainty. - indent += 2; - for (auto score : tally.scores_) { - std::string score_name = score > 0 ? reaction_name(score) - : score_names.at(score); - double mean, stdev; - std::tie(mean, stdev) = mean_stdev( - &tally.results_(filter_index, score_index, 0), tally.n_realizations_); - tallies_out << std::string(indent+1, ' ') << std::left - << std::setw(36) << score_name << " " << mean << " +/- " - << t_value * stdev << "\n"; - score_index += 1; - } - indent -= 2; - } - } - } -} - -} // namespace openmc diff --git a/src/particle.cpp b/src/particle.cpp deleted file mode 100644 index bf107a741..000000000 --- a/src/particle.cpp +++ /dev/null @@ -1,681 +0,0 @@ -#include "openmc/particle.h" - -#include // copy, min -#include // log, abs, copysign -#include - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/geometry.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/physics.h" -#include "openmc/physics_mg.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/surface.h" -#include "openmc/simulation.h" -#include "openmc/tallies/derivative.h" -#include "openmc/tallies/tally.h" -#include "openmc/tallies/tally_scoring.h" -#include "openmc/track_output.h" - -namespace openmc { - -//============================================================================== -// LocalCoord implementation -//============================================================================== - -void -LocalCoord::rotate(const std::vector& rotation) -{ - this->r = this->r.rotate(rotation); - this->u = this->u.rotate(rotation); - this->rotated = true; -} - -void -LocalCoord::reset() -{ - cell = C_NONE; - universe = C_NONE; - lattice = C_NONE; - lattice_x = 0; - lattice_y = 0; - lattice_z = 0; - rotated = false; -} - -//============================================================================== -// Particle implementation -//============================================================================== - -Particle::Particle() -{ - // Create and clear coordinate levels - coord_.resize(model::n_coord_levels); - cell_last_.resize(model::n_coord_levels); - clear(); - - for (int& n : n_delayed_bank_) { - n = 0; - } - - // Create microscopic cross section caches - neutron_xs_.resize(data::nuclides.size()); - photon_xs_.resize(data::elements.size()); -} - -void -Particle::clear() -{ - // reset any coordinate levels - for (auto& level : coord_) level.reset(); - n_coord_ = 1; -} - -void -Particle::create_secondary(Direction u, double E, Type type) -{ - simulation::secondary_bank.emplace_back(); - - auto& bank {simulation::secondary_bank.back()}; - bank.particle = type; - bank.wgt = wgt_; - bank.r = this->r(); - bank.u = u; - bank.E = settings::run_CE ? E : g_; - - n_bank_second_ += 1; -} - -void -Particle::from_source(const Bank* src) -{ - // reset some attributes - this->clear(); - alive_ = true; - surface_ = 0; - cell_born_ = C_NONE; - material_ = C_NONE; - n_collision_ = 0; - fission_ = false; - - // copy attributes from source bank site - type_ = src->particle; - wgt_ = src->wgt; - wgt_last_ = src->wgt; - this->r() = src->r; - this->u() = src->u; - r_last_current_ = src->r; - r_last_ = src->r; - u_last_ = src->u; - if (settings::run_CE) { - E_ = src->E; - g_ = 0; - } else { - g_ = static_cast(src->E); - g_last_ = static_cast(src->E); - E_ = data::energy_bin_avg[g_ - 1]; - } - E_last_ = E_; -} - -void -Particle::transport() -{ - // Display message if high verbosity or trace is on - if (settings::verbosity >= 9 || simulation::trace) { - write_message("Simulating Particle " + std::to_string(id_)); - } - - // Initialize number of events to zero - int n_event = 0; - - // Add paricle's starting weight to count for normalizing tallies later - #pragma omp atomic - simulation::total_weight += wgt_; - - // Force calculation of cross-sections by setting last energy to zero - if (settings::run_CE) { - for (auto& micro : neutron_xs_) micro.last_E = 0.0; - } - - // Prepare to write out particle track. - if (write_track_) add_particle_track(); - - // Every particle starts with no accumulated flux derivative. - if (!model::active_tallies.empty()) zero_flux_derivs(); - - while (true) { - // Set the random number stream - if (type_ == Particle::Type::neutron) { - prn_set_stream(STREAM_TRACKING); - } else { - prn_set_stream(STREAM_PHOTON); - } - - // Store pre-collision particle properties - wgt_last_ = wgt_; - E_last_ = E_; - u_last_ = this->u(); - r_last_ = this->r(); - - // Reset event variables - event_ = EVENT_KILL; - event_nuclide_ = NUCLIDE_NONE; - event_mt_ = REACTION_NONE; - - // If the cell hasn't been determined based on the particle's location, - // initiate a search for the current cell. This generally happens at the - // beginning of the history and again for any secondary particles - if (coord_[n_coord_ - 1].cell == C_NONE) { - if (!find_cell(this, false)) { - this->mark_as_lost("Could not find the cell containing particle " - + std::to_string(id_)); - return; - } - - // set birth cell attribute - if (cell_born_ == C_NONE) cell_born_ = coord_[n_coord_ - 1].cell; - } - - // Write particle track. - if (write_track_) write_particle_track(*this); - - if (settings::check_overlaps) check_cell_overlap(this); - - // Calculate microscopic and macroscopic cross sections - if (material_ != MATERIAL_VOID) { - if (settings::run_CE) { - if (material_ != material_last_ || sqrtkT_ != sqrtkT_last_) { - // If the material is the same as the last material and the - // temperature hasn't changed, we don't need to lookup cross - // sections again. - model::materials[material_]->calculate_xs(*this); - } - } else { - // Get the MG data - calculate_xs_c(material_, g_, sqrtkT_, this->u_local(), - macro_xs_.total, macro_xs_.absorption, macro_xs_.nu_fission); - - // Finally, update the particle group while we have already checked - // for if multi-group - g_last_ = g_; - } - } else { - macro_xs_.total = 0.0; - macro_xs_.absorption = 0.0; - macro_xs_.fission = 0.0; - macro_xs_.nu_fission = 0.0; - } - - // Find the distance to the nearest boundary - auto boundary = distance_to_boundary(this); - - // Sample a distance to collision - double d_collision; - if (type_ == Particle::Type::electron || - type_ == Particle::Type::positron) { - d_collision = 0.0; - } else if (macro_xs_.total == 0.0) { - d_collision = INFINITY; - } else { - d_collision = -std::log(prn()) / macro_xs_.total; - } - - // Select smaller of the two distances - double distance = std::min(boundary.distance, d_collision); - - // Advance particle - for (int j = 0; j < n_coord_; ++j) { - coord_[j].r += distance * coord_[j].u; - } - - // Score track-length tallies - if (!model::active_tracklength_tallies.empty()) { - score_tracklength_tally(this, distance); - } - - // Score track-length estimate of k-eff - if (settings::run_mode == RUN_MODE_EIGENVALUE && - type_ == Particle::Type::neutron) { - global_tally_tracklength += wgt_ * distance * macro_xs_.nu_fission; - } - - // Score flux derivative accumulators for differential tallies. - if (!model::active_tallies.empty()) { - score_track_derivative(this, distance); - } - - if (d_collision > boundary.distance) { - // ==================================================================== - // PARTICLE CROSSES SURFACE - - // Set surface that particle is on and adjust coordinate levels - surface_ = boundary.surface_index; - n_coord_ = boundary.coord_level; - - // Saving previous cell data - for (int j = 0; j < n_coord_; ++j) { - cell_last_[j] = coord_[j].cell; - } - n_coord_last_ = n_coord_; - - if (boundary.lattice_translation[0] != 0 || - boundary.lattice_translation[1] != 0 || - boundary.lattice_translation[2] != 0) { - // Particle crosses lattice boundary - cross_lattice(this, boundary); - event_ = EVENT_LATTICE; - } else { - // Particle crosses surface - this->cross_surface(); - event_ = EVENT_SURFACE; - } - // Score cell to cell partial currents - if (!model::active_surface_tallies.empty()) { - score_surface_tally(this, model::active_surface_tallies); - } - } else { - // ==================================================================== - // PARTICLE HAS COLLISION - - // Score collision estimate of keff - if (settings::run_mode == RUN_MODE_EIGENVALUE && - type_ == Particle::Type::neutron) { - global_tally_collision += wgt_ * macro_xs_.nu_fission - / macro_xs_.total; - } - - // Score surface current tallies -- this has to be done before the collision - // since the direction of the particle will change and we need to use the - // pre-collision direction to figure out what mesh surfaces were crossed - - if (!model::active_meshsurf_tallies.empty()) - score_surface_tally(this, model::active_meshsurf_tallies); - - // Clear surface component - surface_ = 0; - - if (settings::run_CE) { - collision(this); - } else { - collision_mg(this); - } - - // Score collision estimator tallies -- this is done after a collision - // has occurred rather than before because we need information on the - // outgoing energy for any tallies with an outgoing energy filter - if (!model::active_collision_tallies.empty()) score_collision_tally(this); - if (!model::active_analog_tallies.empty()) { - if (settings::run_CE) { - score_analog_tally_ce(this); - } else { - score_analog_tally_mg(this); - } - } - - // Reset banked weight during collision - n_bank_ = 0; - n_bank_second_ = 0; - wgt_bank_ = 0.0; - for (int& v : n_delayed_bank_) v = 0; - - // Reset fission logical - fission_ = false; - - // Save coordinates for tallying purposes - r_last_current_ = this->r(); - - // Set last material to none since cross sections will need to be - // re-evaluated - material_last_ = C_NONE; - - // Set all directions to base level -- right now, after a collision, only - // the base level directions are changed - for (int j = 0; j < n_coord_ - 1; ++j) { - if (coord_[j + 1].rotated) { - // If next level is rotated, apply rotation matrix - const auto& m {model::cells[coord_[j].cell]->rotation_}; - const auto& u {coord_[j].u}; - coord_[j + 1].u = u.rotate(m); - } else { - // Otherwise, copy this level's direction - coord_[j+1].u = coord_[j].u; - } - } - - // Score flux derivative accumulators for differential tallies. - if (!model::active_tallies.empty()) score_collision_derivative(this); - } - - // If particle has too many events, display warning and kill it - ++n_event; - if (n_event == MAX_EVENTS) { - warning("Particle " + std::to_string(id_) + - " underwent maximum number of events."); - alive_ = false; - } - - // Check for secondary particles if this particle is dead - if (!alive_) { - // If no secondary particles, break out of event loop - if (simulation::secondary_bank.empty()) break; - - this->from_source(&simulation::secondary_bank.back()); - simulation::secondary_bank.pop_back(); - n_event = 0; - - // Enter new particle in particle track file - if (write_track_) add_particle_track(); - } - } - - #ifdef DAGMC - if (settings::dagmc) simulation::history.reset(); - #endif - - // Finish particle track output. - if (write_track_) { - write_particle_track(*this); - finalize_particle_track(*this); - } -} - -void -Particle::cross_surface() -{ - int i_surface = std::abs(surface_); - // TODO: off-by-one - const auto& surf {model::surfaces[i_surface - 1].get()}; - if (settings::verbosity >= 10 || simulation::trace) { - write_message(" Crossing surface " + std::to_string(surf->id_)); - } - - if (surf->bc_ == BC_VACUUM && (settings::run_mode != RUN_MODE_PLOTTING)) { - // ======================================================================= - // PARTICLE LEAKS OUT OF PROBLEM - - // Kill particle - alive_ = false; - - // Score any surface current tallies -- note that the particle is moved - // forward slightly so that if the mesh boundary is on the surface, it is - // still processed - - if (!model::active_meshsurf_tallies.empty()) { - // TODO: Find a better solution to score surface currents than - // physically moving the particle forward slightly - - this->r() += TINY_BIT * this->u(); - score_surface_tally(this, model::active_meshsurf_tallies); - } - - // Score to global leakage tally - global_tally_leakage += wgt_; - - // Display message - if (settings::verbosity >= 10 || simulation::trace) { - write_message(" Leaked out of surface " + std::to_string(surf->id_)); - } - return; - - } else if ((surf->bc_ == BC_REFLECT || surf->bc_ == BC_WHITE) - && (settings::run_mode != RUN_MODE_PLOTTING)) { - // ======================================================================= - // PARTICLE REFLECTS FROM SURFACE - - // Do not handle reflective boundary conditions on lower universes - if (n_coord_ != 1) { - this->mark_as_lost("Cannot reflect particle " + std::to_string(id_) + - " off surface in a lower universe."); - return; - } - - // Score surface currents since reflection causes the direction of the - // particle to change. For surface filters, we need to score the tallies - // twice, once before the particle's surface attribute has changed and - // once after. For mesh surface filters, we need to artificially move - // the particle slightly back in case the surface crossing is coincident - // with a mesh boundary - - if (!model::active_surface_tallies.empty()) { - score_surface_tally(this, model::active_surface_tallies); - } - - - if (!model::active_meshsurf_tallies.empty()) { - Position r {this->r()}; - this->r() -= TINY_BIT * this->u(); - score_surface_tally(this, model::active_meshsurf_tallies); - this->r() = r; - } - - Direction u = (surf->bc_ == BC_REFLECT) ? - surf->reflect(this->r(), this->u()) : - surf->diffuse_reflect(this->r(), this->u()); - - // Make sure new particle direction is normalized - this->u() = u / u.norm(); - - // Reassign particle's cell and surface - coord_[0].cell = cell_last_[n_coord_last_ - 1]; - surface_ = -surface_; - - // If a reflective surface is coincident with a lattice or universe - // boundary, it is necessary to redetermine the particle's coordinates in - // the lower universes. - // (unless we're using a dagmc model, which has exactly one universe) - if (!settings::dagmc) { - n_coord_ = 1; - if (!find_cell(this, true)) { - this->mark_as_lost("Couldn't find particle after reflecting from surface " - + std::to_string(surf->id_) + "."); - return; - } - } - - // Set previous coordinate going slightly past surface crossing - r_last_current_ = this->r() + TINY_BIT*this->u(); - - // Diagnostic message - if (settings::verbosity >= 10 || simulation::trace) { - write_message(" Reflected from surface " + std::to_string(surf->id_)); - } - return; - - } else if (surf->bc_ == BC_PERIODIC && settings::run_mode != RUN_MODE_PLOTTING) { - // ======================================================================= - // PERIODIC BOUNDARY - - // Do not handle periodic boundary conditions on lower universes - if (n_coord_ != 1) { - this->mark_as_lost("Cannot transfer particle " + std::to_string(id_) + - " across surface in a lower universe. Boundary conditions must be " - "applied to root universe."); - return; - } - - // Score surface currents since reflection causes the direction of the - // particle to change -- artificially move the particle slightly back in - // case the surface crossing is coincident with a mesh boundary - if (!model::active_meshsurf_tallies.empty()) { - Position r {this->r()}; - this->r() -= TINY_BIT * this->u(); - score_surface_tally(this, model::active_meshsurf_tallies); - this->r() = r; - } - - // Get a pointer to the partner periodic surface - auto surf_p = dynamic_cast(surf); - auto other = dynamic_cast( - model::surfaces[surf_p->i_periodic_].get()); - - // Adjust the particle's location and direction. - bool rotational = other->periodic_translate(surf_p, this->r(), this->u()); - - // Reassign particle's surface - // TODO: off-by-one - surface_ = rotational ? - surf_p->i_periodic_ + 1 : - std::copysign(surf_p->i_periodic_ + 1, surface_); - - // Figure out what cell particle is in now - n_coord_ = 1; - - if (!find_cell(this, true)) { - this->mark_as_lost("Couldn't find particle after hitting periodic " - "boundary on surface " + std::to_string(surf->id_) + "."); - return; - } - - // Set previous coordinate going slightly past surface crossing - r_last_current_ = this->r() + TINY_BIT*this->u(); - - // Diagnostic message - if (settings::verbosity >= 10 || simulation::trace) { - write_message(" Hit periodic boundary on surface " + - std::to_string(surf->id_)); - } - return; - } - - // ========================================================================== - // SEARCH NEIGHBOR LISTS FOR NEXT CELL - -#ifdef DAGMC - if (settings::dagmc) { - auto cellp = dynamic_cast(model::cells[cell_last_[0]].get()); - // TODO: off-by-one - auto surfp = dynamic_cast(model::surfaces[std::abs(surface_) - 1].get()); - int32_t i_cell = next_cell(cellp, surfp) - 1; - // save material and temp - material_last_ = material_; - sqrtkT_last_ = sqrtkT_; - // set new cell value - coord_[0].cell = i_cell; - cell_instance_ = 0; - material_ = model::cells[i_cell]->material_[0]; - sqrtkT_ = model::cells[i_cell]->sqrtkT_[0]; - return; - } -#endif - - if (find_cell(this, true)) return; - - // ========================================================================== - // COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS - - // Remove lower coordinate levels and assignment of surface - surface_ = 0; - n_coord_ = 1; - bool found = find_cell(this, false); - - if (settings::run_mode != RUN_MODE_PLOTTING && (!found)) { - // If a cell is still not found, there are two possible causes: 1) there is - // a void in the model, and 2) the particle hit a surface at a tangent. If - // the particle is really traveling tangent to a surface, if we move it - // forward a tiny bit it should fix the problem. - - n_coord_ = 1; - this->r() += TINY_BIT * this->u(); - - // Couldn't find next cell anywhere! This probably means there is an actual - // undefined region in the geometry. - - if (!find_cell(this, false)) { - this->mark_as_lost("After particle " + std::to_string(id_) + - " crossed surface " + std::to_string(surf->id_) + - " it could not be located in any cell and it did not leak."); - return; - } - } -} - -void -Particle::mark_as_lost(const char* message) -{ - // Print warning and write lost particle file - warning(message); - write_restart(); - - // Increment number of lost particles - alive_ = false; - #pragma omp atomic - simulation::n_lost_particles += 1; - - // Count the total number of simulated particles (on this processor) - auto n = simulation::current_batch * settings::gen_per_batch * - simulation::work_per_rank; - - // Abort the simulation if the maximum number of lost particles has been - // reached - if (simulation::n_lost_particles >= MAX_LOST_PARTICLES && - simulation::n_lost_particles >= REL_MAX_LOST_PARTICLES*n) { - fatal_error("Maximum number of lost particles has been reached."); - } -} - -void -Particle::write_restart() const -{ - // Dont write another restart file if in particle restart mode - if (settings::run_mode == RUN_MODE_PARTICLE) return; - - // Set up file name - std::stringstream filename; - filename << settings::path_output << "particle_" << simulation::current_batch - << '_' << id_ << ".h5"; - - #pragma omp critical (WriteParticleRestart) - { - // Create file - hid_t file_id = file_open(filename.str(), 'w'); - - // Write filetype and version info - write_attribute(file_id, "filetype", "particle restart"); - write_attribute(file_id, "version", VERSION_PARTICLE_RESTART); - write_attribute(file_id, "openmc_version", VERSION); -#ifdef GIT_SHA1 - write_attr_string(file_id, "git_sha1", GIT_SHA1); -#endif - - // Write data to file - write_dataset(file_id, "current_batch", simulation::current_batch); - write_dataset(file_id, "generations_per_batch", settings::gen_per_batch); - write_dataset(file_id, "current_generation", simulation::current_gen); - write_dataset(file_id, "n_particles", settings::n_particles); - switch (settings::run_mode) { - case RUN_MODE_FIXEDSOURCE: - write_dataset(file_id, "run_mode", "fixed source"); - break; - case RUN_MODE_EIGENVALUE: - write_dataset(file_id, "run_mode", "eigenvalue"); - break; - case RUN_MODE_PARTICLE: - write_dataset(file_id, "run_mode", "particle restart"); - break; - } - write_dataset(file_id, "id", id_); - write_dataset(file_id, "type", static_cast(type_)); - - int64_t i = simulation::current_work; - write_dataset(file_id, "weight", simulation::source_bank[i-1].wgt); - write_dataset(file_id, "energy", simulation::source_bank[i-1].E); - write_dataset(file_id, "xyz", simulation::source_bank[i-1].r); - write_dataset(file_id, "uvw", simulation::source_bank[i-1].u); - - // Close file - file_close(file_id); - } // #pragma omp critical -} - -} // namespace openmc diff --git a/src/particle_restart.cpp b/src/particle_restart.cpp deleted file mode 100644 index b2017bbeb..000000000 --- a/src/particle_restart.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "openmc/particle_restart.h" - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/particle.h" -#include "openmc/photon.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/tallies/tally.h" - -#include // for copy -#include -#include -#include - -namespace openmc { - -void read_particle_restart(Particle& p, int& previous_run_mode) -{ - // Write meessage - write_message("Loading particle restart file " + - settings::path_particle_restart + "...", 5); - - // Open file - hid_t file_id = file_open(settings::path_particle_restart, 'r'); - - // Read data from file - read_dataset(file_id, "current_batch", simulation::current_batch); - read_dataset(file_id, "generations_per_batch", settings::gen_per_batch); - read_dataset(file_id, "current_generation", simulation::current_gen); - read_dataset(file_id, "n_particles", settings::n_particles); - std::string mode; - read_dataset(file_id, "run_mode", mode); - if (mode == "eigenvalue") { - previous_run_mode = RUN_MODE_EIGENVALUE; - } else if (mode == "fixed source") { - previous_run_mode = RUN_MODE_FIXEDSOURCE; - } - read_dataset(file_id, "id", p.id_); - int type; - read_dataset(file_id, "type", type); - p.type_ = static_cast(type); - read_dataset(file_id, "weight", p.wgt_); - read_dataset(file_id, "energy", p.E_); - read_dataset(file_id, "xyz", p.r()); - read_dataset(file_id, "uvw", p.u()); - - // Set energy group and average energy in multi-group mode - if (!settings::run_CE) { - p.g_ = p.E_; - p.E_ = data::energy_bin_avg[p.g_ - 1]; - } - - // Set particle last attributes - p.wgt_last_ = p.wgt_; - p.r_last_current_ = p.r(); - p.r_last_ = p.r(); - p.u_last_ = p.u(); - p.E_last_ = p.E_; - p.g_last_ = p.g_; - - // Close hdf5 file - file_close(file_id); -} - -void run_particle_restart() -{ - // Set verbosity high - settings::verbosity = 10; - - // Initialize the particle to be tracked - Particle p; - - // Read in the restart information - int previous_run_mode; - read_particle_restart(p, previous_run_mode); - - // Set all tallies to 0 for now (just tracking errors) - model::tallies.clear(); - - // Compute random number seed - int64_t particle_seed; - switch (previous_run_mode) { - case RUN_MODE_EIGENVALUE: - particle_seed = (simulation::total_gen + overall_generation() - 1)*settings::n_particles + p.id_; - break; - case RUN_MODE_FIXEDSOURCE: - particle_seed = p.id_; - break; - default: - throw std::runtime_error{"Unexpected run mode: " + - std::to_string(previous_run_mode)}; - } - set_particle_seed(particle_seed); - - // Transport neutron - p.transport(); - - // Write output if particle made it - print_particle(&p); -} - -} // namespace openmc diff --git a/src/photon.cpp b/src/photon.cpp deleted file mode 100644 index 929822bfc..000000000 --- a/src/photon.cpp +++ /dev/null @@ -1,779 +0,0 @@ -#include "openmc/photon.h" - -#include "openmc/bremsstrahlung.h" -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/nuclide.h" -#include "openmc/particle.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/settings.h" - -#include "xtensor/xbuilder.hpp" -#include "xtensor/xoperation.hpp" -#include "xtensor/xview.hpp" - -#include -#include -#include // for tie - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { - -xt::xtensor compton_profile_pz; - -std::vector elements; -std::unordered_map element_map; - -} // namespace data - -//============================================================================== -// PhotonInteraction implementation -//============================================================================== - -PhotonInteraction::PhotonInteraction(hid_t group, int i_element) - : i_element_{i_element} -{ - // Get name of nuclide from group, removing leading '/' - name_ = object_name(group).substr(1); - - // Get atomic number - read_attribute(group, "Z", Z_); - - // Determine number of energies and read energy grid - read_dataset(group, "energy", energy_); - - // Read coherent scattering - hid_t rgroup = open_group(group, "coherent"); - read_dataset(rgroup, "xs", coherent_); - - hid_t dset = open_dataset(rgroup, "integrated_scattering_factor"); - coherent_int_form_factor_ = Tabulated1D{dset}; - close_dataset(dset); - - if (object_exists(group, "anomalous_real")) { - dset = open_dataset(rgroup, "anomalous_real"); - coherent_anomalous_real_ = Tabulated1D{dset}; - close_dataset(dset); - } - - if (object_exists(group, "anomalous_imag")) { - dset = open_dataset(rgroup, "anomalous_imag"); - coherent_anomalous_imag_ = Tabulated1D{dset}; - close_dataset(dset); - } - close_group(rgroup); - - // Read incoherent scattering - rgroup = open_group(group, "incoherent"); - read_dataset(rgroup, "xs", incoherent_); - dset = open_dataset(rgroup, "scattering_factor"); - incoherent_form_factor_ = Tabulated1D{dset}; - close_dataset(dset); - close_group(rgroup); - - // Read pair production - rgroup = open_group(group, "pair_production_electron"); - read_dataset(rgroup, "xs", pair_production_electron_); - close_group(rgroup); - - // Read pair production - if (object_exists(group, "pair_production_nuclear")) { - rgroup = open_group(group, "pair_production_nuclear"); - read_dataset(rgroup, "xs", pair_production_nuclear_); - close_group(rgroup); - } else { - pair_production_nuclear_ = xt::zeros_like(energy_); - } - - // Read photoelectric - rgroup = open_group(group, "photoelectric"); - read_dataset(rgroup, "xs", photoelectric_total_); - close_group(rgroup); - - // Read heating - if (object_exists(group, "heating")) { - rgroup = open_group(group, "heating"); - read_dataset(rgroup, "xs", heating_); - close_group(rgroup); - } else { - heating_ = xt::zeros_like(energy_); - } - - // Read subshell photoionization cross section and atomic relaxation data - rgroup = open_group(group, "subshells"); - std::vector designators; - read_attribute(rgroup, "designators", designators); - auto n_shell = designators.size(); - for (int i = 0; i < n_shell; ++i) { - const auto& designator {designators[i]}; - - // TODO: Move to ElectronSubshell constructor - - // Add empty shell - shells_.emplace_back(); - - // Create mapping from designator to index - int j = 1; - for (const auto& subshell : SUBSHELLS) { - if (designator == subshell) { - shell_map_[j] = i; - shells_[i].index_subshell = j; - break; - } - ++j; - } - - // Read binding energy and number of electrons - auto& shell {shells_.back()}; - hid_t tgroup = open_group(rgroup, designator.c_str()); - read_attribute(tgroup, "binding_energy", shell.binding_energy); - read_attribute(tgroup, "num_electrons", shell.n_electrons); - - // Read subshell cross section - dset = open_dataset(tgroup, "xs"); - read_attribute(dset, "threshold_idx", j); - shell.threshold = j; - close_dataset(dset); - read_dataset(tgroup, "xs", shell.cross_section); - - auto& xs = shell.cross_section; - xs = xt::where(xs > 0.0, xt::log(xs), -500.0); - - if (object_exists(tgroup, "transitions")) { - // Determine dimensions of transitions - dset = open_dataset(tgroup, "transitions"); - auto dims = object_shape(dset); - close_dataset(dset); - - int n_transition = dims[0]; - shell.n_transitions = n_transition; - if (n_transition > 0) { - xt::xtensor matrix; - read_dataset(tgroup, "transitions", matrix); - - shell.transition_subshells = xt::view(matrix, xt::all(), xt::range(0, 2)); - shell.transition_energy = xt::view(matrix, xt::all(), 2); - shell.transition_probability = xt::view(matrix, xt::all(), 3); - shell.transition_probability /= xt::sum(shell.transition_probability)(); - } - } else { - shell.n_transitions = 0; - } - close_group(tgroup); - } - close_group(rgroup); - - // Determine number of electron shells - rgroup = open_group(group, "compton_profiles"); - - // Read electron shell PDF and binding energies - read_dataset(rgroup, "num_electrons", electron_pdf_); - electron_pdf_ /= xt::sum(electron_pdf_); - read_dataset(rgroup, "binding_energy", binding_energy_); - - // Read Compton profiles - read_dataset(rgroup, "J", profile_pdf_); - - // Get Compton profile momentum grid. By deafult, an xtensor has a size of 1. - // TODO: Change to zero when xtensor is updated - if (data::compton_profile_pz.size() == 1) { - read_dataset(rgroup, "pz", data::compton_profile_pz); - } - close_group(rgroup); - - // Create Compton profile CDF - auto n_profile = data::compton_profile_pz.size(); - profile_cdf_ = xt::empty({n_shell, n_profile}); - for (int i = 0; i < n_shell; ++i) { - double c = 0.0; - profile_cdf_(i,0) = 0.0; - for (int j = 0; j < n_profile - 1; ++j) { - c += 0.5*(data::compton_profile_pz(j+1) - data::compton_profile_pz(j)) * - (profile_pdf_(i,j) + profile_pdf_(i,j+1)); - profile_cdf_(i,j+1) = c; - } - } - - // Calculate total pair production - pair_production_total_ = pair_production_nuclear_ + pair_production_electron_; - - if (settings::electron_treatment == ELECTRON_TTB) { - // Read bremsstrahlung scaled DCS - rgroup = open_group(group, "bremsstrahlung"); - read_dataset(rgroup, "dcs", dcs_); - auto n_e = dcs_.shape()[0]; - auto n_k = dcs_.shape()[1]; - - // Get energy grids used for bremsstrahlung DCS and for stopping powers - xt::xtensor electron_energy; - read_dataset(rgroup, "electron_energy", electron_energy); - // TODO: Change to zero when xtensor is updated - if (data::ttb_k_grid.size() == 1) { - read_dataset(rgroup, "photon_energy", data::ttb_k_grid); - } - - // Get data used for density effect correction - read_dataset(rgroup, "num_electrons", n_electrons_); - read_dataset(rgroup, "ionization_energy", ionization_energy_); - read_attribute(rgroup, "I", I_); - close_group(rgroup); - - // Truncate the bremsstrahlung data at the cutoff energy - int photon = static_cast(Particle::Type::photon); - const auto& E {electron_energy}; - double cutoff = settings::energy_cutoff[photon]; - if (cutoff > E(0)) { - size_t i_grid = lower_bound_index(E.cbegin(), E.cend(), - settings::energy_cutoff[photon]); - - // calculate interpolation factor - double f = (std::log(cutoff) - std::log(E(i_grid))) / - (std::log(E(i_grid+1)) - std::log(E(i_grid))); - - // Interpolate bremsstrahlung DCS at the cutoff energy and truncate - xt::xtensor dcs({n_e - i_grid, n_k}); - for (int i = 0; i < n_k; ++i) { - double y = std::exp(std::log(dcs_(i_grid,i)) + - f*(std::log(dcs_(i_grid+1,i)) - std::log(dcs_(i_grid,i)))); - auto col_i = xt::view(dcs, xt::all(), i); - col_i(0) = y; - for (int j = i_grid + 1; j < n_e; ++j) { - col_i(j - i_grid) = dcs_(j, i); - } - } - dcs_ = dcs; - - xt::xtensor frst {cutoff}; - electron_energy = xt::concatenate(xt::xtuple( - frst, xt::view(electron_energy, xt::range(i_grid+1, n_e)))); - } - - // Set incident particle energy grid - // TODO: Change to zero when xtensor is updated - if (data::ttb_e_grid.size() == 1) { - data::ttb_e_grid = electron_energy; - } - - // Calculate the radiative stopping power - stopping_power_radiative_ = xt::empty({data::ttb_e_grid.size()}); - for (int i = 0; i < data::ttb_e_grid.size(); ++i) { - // Integrate over reduced photon energy - double c = 0.0; - for (int j = 0; j < data::ttb_k_grid.size() - 1; ++j) { - c += 0.5 * (dcs_(i, j+1) + dcs_(i, j)) * (data::ttb_k_grid(j+1) - - data::ttb_k_grid(j)); - } - double e = data::ttb_e_grid(i); - - // Square of the ratio of the speed of light to the velocity of the - // charged particle - double beta_sq = e * (e + 2.0 * MASS_ELECTRON_EV) / ((e + - MASS_ELECTRON_EV) * (e + MASS_ELECTRON_EV)); - - stopping_power_radiative_(i) = Z_ * Z_ / beta_sq * e * c; - } - } - - // Take logarithm of energies and cross sections since they are log-log - // interpolated - energy_ = xt::log(energy_); - coherent_ = xt::where(coherent_ > 0.0, xt::log(coherent_), -500.0); - incoherent_ = xt::where(incoherent_ > 0.0, xt::log(incoherent_), -500.0); - photoelectric_total_ = xt::where(photoelectric_total_ > 0.0, - xt::log(photoelectric_total_), -500.0); - pair_production_total_ = xt::where(pair_production_total_ > 0.0, - xt::log(pair_production_total_), -500.0); - heating_ = xt::where(heating_ > 0.0, xt::log(heating_), -500.0); -} - -void PhotonInteraction::compton_scatter(double alpha, bool doppler, - double* alpha_out, double* mu, int* i_shell) const -{ - double form_factor_xmax = 0.0; - while (true) { - // Sample Klein-Nishina distribution for trial energy and angle - std::tie(*alpha_out, *mu) = klein_nishina(alpha); - - // Note that the parameter used here does not correspond exactly to the - // momentum transfer q in ENDF-102 Eq. (27.2). Rather, this is the - // parameter as defined by Hubbell, where the actual data comes from - double x = MASS_ELECTRON_EV/PLANCK_C*alpha*std::sqrt(0.5*(1.0 - *mu)); - - // Calculate S(x, Z) and S(x_max, Z) - double form_factor_x = incoherent_form_factor_(x); - if (form_factor_xmax == 0.0) { - form_factor_xmax = incoherent_form_factor_(MASS_ELECTRON_EV/PLANCK_C*alpha); - } - - // Perform rejection on form factor - if (prn() < form_factor_x / form_factor_xmax) { - if (doppler) { - double E_out; - this->compton_doppler(alpha, *mu, &E_out, i_shell); - *alpha_out = E_out/MASS_ELECTRON_EV; - } else { - *i_shell = -1; - } - break; - } - } -} - -void PhotonInteraction::compton_doppler(double alpha, double mu, - double* E_out, int* i_shell) const -{ - auto n = data::compton_profile_pz.size(); - - int shell; // index for shell - while (true) { - // Sample electron shell - double rn = prn(); - double c = 0.0; - for (shell = 0; shell < electron_pdf_.size(); ++shell) { - c += electron_pdf_(shell); - if (rn < c) break; - } - - // Determine binding energy of shell - double E_b = binding_energy_(shell); - - // Determine p_z,max - double E = alpha*MASS_ELECTRON_EV; - if (E < E_b) { - *E_out = alpha/(1 + alpha*(1 - mu))*MASS_ELECTRON_EV; - break; - } - - double pz_max = -FINE_STRUCTURE*(E_b - (E - E_b)*alpha*(1.0 - mu)) / - std::sqrt(2.0*E*(E - E_b)*(1.0 - mu) + E_b*E_b); - if (pz_max < 0.0) { - *E_out = alpha/(1 + alpha*(1 - mu))*MASS_ELECTRON_EV; - break; - } - - // Determine profile cdf value corresponding to p_z,max - double c_max; - if (pz_max > data::compton_profile_pz(n - 1)) { - c_max = profile_cdf_(shell, n - 1); - } else { - int i = lower_bound_index(data::compton_profile_pz.cbegin(), - data::compton_profile_pz.cend(), pz_max); - double pz_l = data::compton_profile_pz(i); - double pz_r = data::compton_profile_pz(i + 1); - double p_l = profile_pdf_(shell, i); - double p_r = profile_pdf_(shell, i + 1); - double c_l = profile_cdf_(shell, i); - if (pz_l == pz_r) { - c_max = c_l; - } else if (p_l == p_r) { - c_max = c_l + (pz_max - pz_l)*p_l; - } else { - double m = (p_l - p_r)/(pz_l - pz_r); - c_max = c_l + (std::pow((m*(pz_max - pz_l) + p_l), 2) - p_l*p_l)/(2.0*m); - } - } - - // Sample value on bounded cdf - c = prn()*c_max; - - // Determine pz corresponding to sampled cdf value - auto cdf_shell = xt::view(profile_cdf_, shell, xt::all()); - int i = lower_bound_index(cdf_shell.cbegin(), cdf_shell.cend(), c); - double pz_l = data::compton_profile_pz(i); - double pz_r = data::compton_profile_pz(i + 1); - double p_l = profile_pdf_(shell, i); - double p_r = profile_pdf_(shell, i + 1); - double c_l = profile_cdf_(shell, i); - double pz; - if (pz_l == pz_r) { - pz = pz_l; - } else if (p_l == p_r) { - pz = pz_l + (c - c_l)/p_l; - } else { - double m = (p_l - p_r)/(pz_l - pz_r); - pz = pz_l + (std::sqrt(p_l*p_l + 2.0*m*(c - c_l)) - p_l)/m; - } - - // Determine outgoing photon energy corresponding to electron momentum - // (solve Eq. 39 in LA-UR-04-0487 for E') - double momentum_sq = std::pow((pz/FINE_STRUCTURE), 2); - double f = 1.0 + alpha*(1.0 - mu); - double a = momentum_sq - f*f; - double b = 2.0*E*(f - momentum_sq*mu); - c = E*E*(momentum_sq - 1.0); - - double quad = b*b - 4.0*a*c; - if (quad < 0) { - *E_out = alpha/(1 + alpha*(1 - mu))*MASS_ELECTRON_EV; - break; - } - quad = std::sqrt(quad); - double E_out1 = -(b + quad)/(2.0*a); - double E_out2 = -(b - quad)/(2.0*a); - - // Determine solution to quadratic equation that is positive - if (E_out1 > 0.0) { - if (E_out2 > 0.0) { - // If both are positive, pick one at random - *E_out = prn() < 0.5 ? E_out1 : E_out2; - } else { - *E_out = E_out1; - } - } else { - if (E_out2 > 0.0) { - *E_out = E_out2; - } else { - // No positive solution -- resample - continue; - } - } - if (*E_out < E - E_b) break; - } - - *i_shell = shell; -} - -void PhotonInteraction::calculate_xs(Particle& p) const -{ - // Perform binary search on the element energy grid in order to determine - // which points to interpolate between - int n_grid = energy_.size(); - double log_E = std::log(p.E_); - int i_grid; - if (log_E <= energy_[0]) { - i_grid = 0; - } else if (log_E > energy_(n_grid - 1)) { - i_grid = n_grid - 2; - } else { - // We use upper_bound_index here because sometimes photons are created with - // energies that exactly match a grid point - i_grid = upper_bound_index(energy_.cbegin(), energy_.cend(), log_E); - } - - // check for case where two energy points are the same - if (energy_(i_grid) == energy_(i_grid+1)) ++i_grid; - - // calculate interpolation factor - double f = (log_E - energy_(i_grid)) / (energy_(i_grid+1) - energy_(i_grid)); - - auto& xs {p.photon_xs_[i_element_]}; - xs.index_grid = i_grid; - xs.interp_factor = f; - - // Calculate microscopic coherent cross section - xs.coherent = std::exp(coherent_(i_grid) + - f*(coherent_(i_grid+1) - coherent_(i_grid))); - - // Calculate microscopic incoherent cross section - xs.incoherent = std::exp(incoherent_(i_grid) + - f*(incoherent_(i_grid+1) - incoherent_(i_grid))); - - // Calculate microscopic photoelectric cross section - xs.photoelectric = 0.0; - for (const auto& shell : shells_) { - // Check threshold of reaction - int i_start = shell.threshold; - if (i_grid < i_start) continue; - - // Evaluation subshell photoionization cross section - xs.photoelectric += - std::exp(shell.cross_section(i_grid-i_start) + - f*(shell.cross_section(i_grid+1-i_start) - - shell.cross_section(i_grid-i_start))); - } - - // Calculate microscopic pair production cross section - xs.pair_production = std::exp( - pair_production_total_(i_grid) + f*( - pair_production_total_(i_grid+1) - - pair_production_total_(i_grid))); - - // Calculate microscopic total cross section - xs.total = xs.coherent + xs.incoherent + xs.photoelectric + xs.pair_production; - xs.last_E = p.E_; -} - -double PhotonInteraction::rayleigh_scatter(double alpha) const -{ - double mu; - while (true) { - // Determine maximum value of x^2 - double x2_max = std::pow(MASS_ELECTRON_EV/PLANCK_C*alpha, 2); - - // Determine F(x^2_max, Z) - double F_max = coherent_int_form_factor_(x2_max); - - // Sample cumulative distribution - double F = prn()*F_max; - - // Determine x^2 corresponding to F - const auto& x {coherent_int_form_factor_.x()}; - const auto& y {coherent_int_form_factor_.y()}; - int i = lower_bound_index(y.cbegin(), y.cend(), F); - double r = (F - y[i]) / (y[i+1] - y[i]); - double x2 = x[i] + r*(x[i+1] - x[i]); - - // Calculate mu - mu = 1.0 - 2.0*x2/x2_max; - - if (prn() < 0.5*(1.0 + mu*mu)) break; - } - return mu; -} - -void PhotonInteraction::pair_production(double alpha, double* E_electron, - double* E_positron, double* mu_electron, double* mu_positron) const -{ - constexpr double r[] { - 122.81, 73.167, 69.228, 67.301, 64.696, 61.228, - 57.524, 54.033, 50.787, 47.851, 46.373, 45.401, - 44.503, 43.815, 43.074, 42.321, 41.586, 40.953, - 40.524, 40.256, 39.756, 39.144, 38.462, 37.778, - 37.174, 36.663, 35.986, 35.317, 34.688, 34.197, - 33.786, 33.422, 33.068, 32.740, 32.438, 32.143, - 31.884, 31.622, 31.438, 31.142, 30.950, 30.758, - 30.561, 30.285, 30.097, 29.832, 29.581, 29.411, - 29.247, 29.085, 28.930, 28.721, 28.580, 28.442, - 28.312, 28.139, 27.973, 27.819, 27.675, 27.496, - 27.285, 27.093, 26.911, 26.705, 26.516, 26.304, - 26.108, 25.929, 25.730, 25.577, 25.403, 25.245, - 25.100, 24.941, 24.790, 24.655, 24.506, 24.391, - 24.262, 24.145, 24.039, 23.922, 23.813, 23.712, - 23.621, 23.523, 23.430, 23.331, 23.238, 23.139, - 23.048, 22.967, 22.833, 22.694, 22.624, 22.545, - 22.446, 22.358, 22.264}; - - // The reduced screening radius r is the ratio of the screening radius to - // the Compton wavelength of the electron, where the screening radius is - // obtained under the assumption that the Coulomb field of the nucleus is - // exponentially screened by atomic electrons. This allows us to use a - // simplified atomic form factor and analytical approximations of the - // screening functions in the pair production DCS instead of computing the - // screening functions numerically. The reduced screening radii above for - // Z = 1-99 come from F. Salvat, J. M. Fernández-Varea, and J. Sempau, - // "PENELOPE-2011: A Code System for Monte Carlo Simulation of Electron and - // Photon Transport," OECD-NEA, Issy-les-Moulineaux, France (2011). - - // Compute the high-energy Coulomb correction - double a = Z_ / FINE_STRUCTURE; - double c = a*a*(1.0/(1.0 + a*a) + 0.202059 + a*a*(-0.03693 + a*a*(0.00835 + - a*a*(-0.00201 + a*a*(0.00049 + a*a*(-0.00012 + a*a*0.00003)))))); - - // The analytical approximation of the DCS underestimates the cross section - // at low energies. The correction factor f compensates for this. - double q = std::sqrt(2.0/alpha); - double f = q*(-0.1774 - 12.10*a + 11.18*a*a) - + q*q*(8.523 + 73.26*a - 44.41*a*a) - + q*q*q*(-13.52 - 121.1*a + 96.41*a*a) - + q*q*q*q*(8.946 + 62.05*a - 63.41*a*a); - - // Calculate phi_1(1/2) and phi_2(1/2). The unnormalized PDF for the reduced - // energy is given by p = 2*(1/2 - e)^2*phi_1(e) + phi_2(e), where phi_1 and - // phi_2 are non-negative and maximum at e = 1/2. - double b = 2.0*r[Z_]/alpha; - double t1 = 2.0*std::log(1.0 + b*b); - double t2 = b*std::atan(1.0/b); - double t3 = b*b*(4.0 - 4.0*t2 - 3.0*std::log(1.0 + 1.0/(b*b))); - double t4 = 4.0*std::log(r[Z_]) - 4.0*c + f; - double phi1_max = 7.0/3.0 - t1 - 6.0*t2 - t3 + t4; - double phi2_max = 11.0/6.0 - t1 - 3.0*t2 + 0.5*t3 + t4; - - // To aid sampling, the unnormalized PDF can be expressed as - // p = u_1*U_1(e)*pi_1(e) + u_2*U_2(e)*pi_2(e), where pi_1 and pi_2 are - // normalized PDFs on the interval (e_min, e_max) from which values of e can - // be sampled using the inverse transform method, and - // U_1 = phi_1(e)/phi_1(1/2) and U_2 = phi_2(e)/phi_2(1/2) are valid - // rejection functions. The reduced energy can now be sampled using a - // combination of the composition and rejection methods. - double u1 = 2.0/3.0*std::pow(0.5 - 1.0/alpha, 2)*phi1_max; - double u2 = phi2_max; - double e; - while (true) { - double rn = prn(); - - // Sample the index i in (1, 2) using the point probabilities - // p(1) = u_1/(u_1 + u_2) and p(2) = u_2/(u_1 + u_2) - int i; - if (prn() < u1/(u1 + u2)) { - i = 1; - - // Sample e from pi_1 using the inverse transform method - e = rn >= 0.5 ? - 0.5 + (0.5 - 1.0/alpha)*std::pow(2.0*rn - 1.0, 1.0/3.0) : - 0.5 - (0.5 - 1.0/alpha)*std::pow(1.0 - 2.0*rn, 1.0/3.0); - } else { - i = 2; - - // Sample e from pi_2 using the inverse transform method - e = 1.0/alpha + (0.5 - 1.0/alpha)*2.0*rn; - } - - // Calculate phi_i(e) and deliver e if rn <= U_i(e) - b = r[Z_]/(2.0*alpha*e*(1.0 - e)); - t1 = 2.0*std::log(1.0 + b*b); - t2 = b*std::atan(1.0/b); - t3 = b*b*(4.0 - 4.0*t2 - 3.0*std::log(1.0 + 1.0/(b*b))); - if (i == 1) { - double phi1 = 7.0/3.0 - t1 - 6.0*t2 - t3 + t4; - if (prn() <= phi1/phi1_max) break; - } else { - double phi2 = 11.0/6.0 - t1 - 3.0*t2 + 0.5*t3 + t4; - if (prn() <= phi2/phi2_max) break; - } - } - - // Compute the kinetic energy of the electron and the positron - *E_electron = (alpha*e - 1.0)*MASS_ELECTRON_EV; - *E_positron = (alpha*(1.0 - e) - 1.0)*MASS_ELECTRON_EV; - - // Sample the scattering angle of the electron. The cosine of the polar - // angle of the direction relative to the incident photon is sampled from - // p(mu) = C/(1 - beta*mu)^2 using the inverse transform method. - double beta = std::sqrt(*E_electron*(*E_electron + 2.0*MASS_ELECTRON_EV)) - / (*E_electron + MASS_ELECTRON_EV) ; - double rn = 2.0*prn() - 1.0; - *mu_electron = (rn + beta)/(rn*beta + 1.0); - - // Sample the scattering angle of the positron - beta = std::sqrt(*E_positron*(*E_positron + 2.0*MASS_ELECTRON_EV)) - / (*E_positron + MASS_ELECTRON_EV); - rn = 2.0*prn() - 1.0; - *mu_positron = (rn + beta)/(rn*beta + 1.0); -} - -void PhotonInteraction::atomic_relaxation(const ElectronSubshell& shell, Particle& p) const -{ - // If no transitions, assume fluorescent photon from captured free electron - if (shell.n_transitions == 0) { - double mu = 2.0*prn() - 1.0; - double phi = 2.0*PI*prn(); - Direction u; - u.x = mu; - u.y = std::sqrt(1.0 - mu*mu)*std::cos(phi); - u.z = std::sqrt(1.0 - mu*mu)*std::sin(phi); - double E = shell.binding_energy; - p.create_secondary(u, E, Particle::Type::photon); - return; - } - - // Sample transition - double rn = prn(); - double c = 0.0; - int i_transition; - for (i_transition = 0; i_transition < shell.n_transitions; ++i_transition) { - c += shell.transition_probability(i_transition); - if (rn < c) break; - } - - // Get primary and secondary subshell designators - int primary = shell.transition_subshells(i_transition, 0); - int secondary = shell.transition_subshells(i_transition, 1); - - // Sample angle isotropically - double mu = 2.0*prn() - 1.0; - double phi = 2.0*PI*prn(); - Direction u; - u.x = mu; - u.y = std::sqrt(1.0 - mu*mu)*std::cos(phi); - u.z = std::sqrt(1.0 - mu*mu)*std::sin(phi); - - // Get the transition energy - double E = shell.transition_energy(i_transition); - - if (secondary != 0) { - // Non-radiative transition -- Auger/Coster-Kronig effect - - // Create auger electron - p.create_secondary(u, E, Particle::Type::electron); - - // Fill hole left by emitted auger electron - int i_hole = shell_map_.at(secondary); - const auto& hole = shells_[i_hole]; - this->atomic_relaxation(hole, p); - } else { - // Radiative transition -- get X-ray energy - - // Create fluorescent photon - p.create_secondary(u, E, Particle::Type::photon); - } - - // Fill hole created by electron transitioning to the photoelectron hole - int i_hole = shell_map_.at(primary); - const auto& hole = shells_[i_hole]; - this->atomic_relaxation(hole, p); -} - -//============================================================================== -// Non-member functions -//============================================================================== - -std::pair klein_nishina(double alpha) -{ - double alpha_out, mu; - double beta = 1.0 + 2.0*alpha; - if (alpha < 3.0) { - // Kahn's rejection method - double t = beta/(beta + 8.0); - double x; - while (true) { - if (prn() < t) { - // Left branch of flow chart - double r = 2.0*prn(); - x = 1.0 + alpha*r; - if (prn() < 4.0/x*(1.0 - 1.0/x)) { - mu = 1 - r; - break; - } - } else { - // Right branch of flow chart - x = beta/(1.0 + 2.0*alpha*prn()); - mu = 1.0 + (1.0 - x)/alpha; - if (prn() < 0.5*(mu*mu + 1.0/x)) break; - } - } - alpha_out = alpha/x; - - } else { - // Koblinger's direct method - double gamma = 1.0 - std::pow(beta, -2); - double s = prn()*(4.0/alpha + 0.5*gamma + - (1.0 - (1.0 + beta)/(alpha*alpha))*std::log(beta)); - if (s <= 2.0/alpha) { - // For first term, x = 1 + 2ar - // Therefore, a' = a/(1 + 2ar) - alpha_out = alpha/(1.0 + 2.0*alpha*prn()); - } else if (s <= 4.0/alpha) { - // For third term, x = beta/(1 + 2ar) - // Therefore, a' = a(1 + 2ar)/beta - alpha_out = alpha*(1.0 + 2.0*alpha*prn())/beta; - } else if (s <= 4.0/alpha + 0.5*gamma) { - // For fourth term, x = 1/sqrt(1 - gamma*r) - // Therefore, a' = a*sqrt(1 - gamma*r) - alpha_out = alpha*std::sqrt(1.0 - gamma*prn()); - } else { - // For third term, x = beta^r - // Therefore, a' = a/beta^r - alpha_out = alpha/std::pow(beta, prn()); - } - - // Calculate cosine of scattering angle based on basic relation - mu = 1.0 + 1.0/alpha - 1.0/alpha_out; - } - return {alpha_out, mu}; -} - -void free_memory_photon() -{ - data::elements.clear(); - data::compton_profile_pz.resize({0}); - data::ttb_e_grid.resize({0}); - data::ttb_k_grid.resize({0}); -} - -} // namespace openmc diff --git a/src/physics.cpp b/src/physics.cpp deleted file mode 100644 index 0eb8c494e..000000000 --- a/src/physics.cpp +++ /dev/null @@ -1,1123 +0,0 @@ -#include "openmc/physics.h" - -#include "openmc/bank.h" -#include "openmc/bremsstrahlung.h" -#include "openmc/constants.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/material.h" -#include "openmc/math_functions.h" -#include "openmc/message_passing.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/physics_common.h" -#include "openmc/random_lcg.h" -#include "openmc/reaction.h" -#include "openmc/secondary_uncorrelated.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/thermal.h" -#include "openmc/tallies/tally.h" - -#include // for max, min, max_element -#include // for sqrt, exp, log, abs, copysign -#include - -namespace openmc { - -//============================================================================== -// Non-member functions -//============================================================================== - -void collision(Particle* p) -{ - // Add to collision counter for particle - ++(p->n_collision_); - - // Sample reaction for the material the particle is in - switch (static_cast(p->type_)) { - case Particle::Type::neutron: - sample_neutron_reaction(p); - break; - case Particle::Type::photon: - sample_photon_reaction(p); - break; - case Particle::Type::electron: - sample_electron_reaction(p); - break; - case Particle::Type::positron: - sample_positron_reaction(p); - break; - } - - // Kill particle if energy falls below cutoff - int type = static_cast(p->type_); - if (p->E_ < settings::energy_cutoff[type]) { - p->alive_ = false; - p->wgt_ = 0.0; - } - - // Display information about collision - if (settings::verbosity >= 10 || simulation::trace) { - std::stringstream msg; - if (p->event_ == EVENT_KILL) { - msg << " Killed. Energy = " << p->E_ << " eV."; - } else if (p->type_ == Particle::Type::neutron) { - msg << " " << reaction_name(p->event_mt_) << " with " << - data::nuclides[p->event_nuclide_]->name_ << ". Energy = " << p->E_ << " eV."; - } else if (p->type_ == Particle::Type::photon) { - msg << " " << reaction_name(p->event_mt_) << " with " << - to_element(data::nuclides[p->event_nuclide_]->name_) << ". Energy = " << p->E_ << " eV."; - } else { - msg << " Disappeared. Energy = " << p->E_ << " eV."; - } - write_message(msg, 1); - } -} - -void sample_neutron_reaction(Particle* p) -{ - // Sample a nuclide within the material - int i_nuclide = sample_nuclide(p); - - // Save which nuclide particle had collision with - p->event_nuclide_ = i_nuclide; - - // Create fission bank sites. Note that while a fission reaction is sampled, - // it never actually "happens", i.e. the weight of the particle does not - // change when sampling fission sites. The following block handles all - // absorption (including fission) - - const auto& nuc {data::nuclides[i_nuclide]}; - - if (nuc->fissionable_) { - Reaction* rx = sample_fission(i_nuclide, p); - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - create_fission_sites(p, i_nuclide, rx, simulation::fission_bank); - } else if (settings::run_mode == RUN_MODE_FIXEDSOURCE && - settings::create_fission_neutrons) { - create_fission_sites(p, i_nuclide, rx, simulation::secondary_bank); - - // Make sure particle population doesn't grow out of control for - // subcritical multiplication problems. - if (simulation::secondary_bank.size() >= 10000) { - fatal_error("The secondary particle bank appears to be growing without " - "bound. You are likely running a subcritical multiplication problem " - "with k-effective close to or greater than one."); - } - } - } - - // Create secondary photons - if (settings::photon_transport) { - prn_set_stream(STREAM_PHOTON); - sample_secondary_photons(p, i_nuclide); - prn_set_stream(STREAM_TRACKING); - } - - // If survival biasing is being used, the following subroutine adjusts the - // weight of the particle. Otherwise, it checks to see if absorption occurs - - if (p->neutron_xs_[i_nuclide].absorption > 0.0) { - absorption(p, i_nuclide); - } else { - p->wgt_absorb_ = 0.0; - } - if (!p->alive_) return; - - // Sample a scattering reaction and determine the secondary energy of the - // exiting neutron - scatter(p, i_nuclide); - - // Advance URR seed stream 'N' times after energy changes - if (p->E_ != p->E_last_) { - prn_set_stream(STREAM_URR_PTABLE); - advance_prn_seed(data::nuclides.size()); - prn_set_stream(STREAM_TRACKING); - } - - // Play russian roulette if survival biasing is turned on - if (settings::survival_biasing) { - russian_roulette(p); - if (!p->alive_) return; - } -} - -void -create_fission_sites(Particle* p, int i_nuclide, const Reaction* rx, - std::vector& bank) -{ - // If uniform fission source weighting is turned on, we increase or decrease - // the expected number of fission sites produced - double weight = settings::ufs_on ? ufs_get_weight(p) : 1.0; - - // Determine the expected number of neutrons produced - double nu_t = p->wgt_ / simulation::keff * weight * p->neutron_xs_[ - i_nuclide].nu_fission / p->neutron_xs_[i_nuclide].total; - - // Sample the number of neutrons produced - int nu = static_cast(nu_t); - if (prn() <= (nu_t - nu)) ++nu; - - // Begin banking the source neutrons - // First, if our bank is full then don't continue - if (nu == 0) return; - - // Initialize the counter of delayed neutrons encountered for each delayed - // group. - double nu_d[MAX_DELAYED_GROUPS] = {0.}; - - p->fission_ = true; - for (int i = 0; i < nu; ++i) { - // Create new bank site and get reference to last element - bank.emplace_back(); - auto& site {bank.back()}; - - // Bank source neutrons by copying the particle data - site.r = p->r(); - site.particle = Particle::Type::neutron; - site.wgt = 1. / weight; - - // Sample delayed group and angle/energy for fission reaction - sample_fission_neutron(i_nuclide, rx, p->E_, &site); - - // Set the delayed group on the particle as well - p->delayed_group_ = site.delayed_group; - - // Increment the number of neutrons born delayed - if (p->delayed_group_ > 0) { - nu_d[p->delayed_group_-1]++; - } - } - - // Store the total weight banked for analog fission tallies - p->n_bank_ = nu; - p->wgt_bank_ = nu / weight; - for (size_t d = 0; d < MAX_DELAYED_GROUPS; d++) { - p->n_delayed_bank_[d] = nu_d[d]; - } -} - -void sample_photon_reaction(Particle* p) -{ - // Kill photon if below energy cutoff -- an extra check is made here because - // photons with energy below the cutoff may have been produced by neutrons - // reactions or atomic relaxation - int photon = static_cast(Particle::Type::photon); - if (p->E_ < settings::energy_cutoff[photon]) { - p->E_ = 0.0; - p->alive_ = false; - return; - } - - // Sample element within material - int i_element = sample_element(p); - const auto& micro {p->photon_xs_[i_element]}; - const auto& element {data::elements[i_element]}; - - // Calculate photon energy over electron rest mass equivalent - double alpha = p->E_/MASS_ELECTRON_EV; - - // For tallying purposes, this routine might be called directly. In that - // case, we need to sample a reaction via the cutoff variable - double prob = 0.0; - double cutoff = prn() * micro.total; - - // Coherent (Rayleigh) scattering - prob += micro.coherent; - if (prob > cutoff) { - double mu = element.rayleigh_scatter(alpha); - p->u() = rotate_angle(p->u(), mu, nullptr); - p->event_ = EVENT_SCATTER; - p->event_mt_ = COHERENT; - return; - } - - // Incoherent (Compton) scattering - prob += micro.incoherent; - if (prob > cutoff) { - double alpha_out, mu; - int i_shell; - element.compton_scatter(alpha, true, &alpha_out, &mu, &i_shell); - - // Determine binding energy of shell. The binding energy is 0.0 if - // doppler broadening is not used. - double e_b; - if (i_shell == -1) { - e_b = 0.0; - } else { - e_b = element.binding_energy_[i_shell]; - } - - // Create Compton electron - double phi = 2.0*PI*prn(); - double E_electron = (alpha - alpha_out)*MASS_ELECTRON_EV - e_b; - int electron = static_cast(Particle::Type::electron); - if (E_electron >= settings::energy_cutoff[electron]) { - double mu_electron = (alpha - alpha_out*mu) - / std::sqrt(alpha*alpha + alpha_out*alpha_out - 2.0*alpha*alpha_out*mu); - Direction u = rotate_angle(p->u(), mu_electron, &phi); - p->create_secondary(u, E_electron, Particle::Type::electron); - } - - // TODO: Compton subshell data does not match atomic relaxation data - // Allow electrons to fill orbital and produce auger electrons - // and fluorescent photons - if (i_shell >= 0) { - const auto& shell = element.shells_[i_shell]; - element.atomic_relaxation(shell, *p); - } - - phi += PI; - p->E_ = alpha_out*MASS_ELECTRON_EV; - p->u() = rotate_angle(p->u(), mu, &phi); - p->event_ = EVENT_SCATTER; - p->event_mt_ = INCOHERENT; - return; - } - - // Photoelectric effect - double prob_after = prob + micro.photoelectric; - if (prob_after > cutoff) { - for (const auto& shell : element.shells_) { - // Get grid index and interpolation factor - int i_grid = micro.index_grid; - double f = micro.interp_factor; - - // Check threshold of reaction - int i_start = shell.threshold; - if (i_grid < i_start) continue; - - // Evaluation subshell photoionization cross section - double xs = std::exp(shell.cross_section(i_grid - i_start) + - f*(shell.cross_section(i_grid + 1 - i_start) - - shell.cross_section(i_grid - i_start))); - - prob += xs; - if (prob > cutoff) { - double E_electron = p->E_ - shell.binding_energy; - - // Sample mu using non-relativistic Sauter distribution. - // See Eqns 3.19 and 3.20 in "Implementing a photon physics - // model in Serpent 2" by Toni Kaltiaisenaho - double mu; - while (true) { - double r = prn(); - if (4.0*(1.0 - r)*r >= prn()) { - double rel_vel = std::sqrt(E_electron * (E_electron + - 2.0*MASS_ELECTRON_EV)) / (E_electron + MASS_ELECTRON_EV); - mu = (2.0*r + rel_vel - 1.0) / (2.0*rel_vel*r - rel_vel + 1.0); - break; - } - } - - double phi = 2.0*PI*prn(); - Direction u; - u.x = mu; - u.y = std::sqrt(1.0 - mu*mu)*std::cos(phi); - u.z = std::sqrt(1.0 - mu*mu)*std::sin(phi); - - // Create secondary electron - p->create_secondary(u, E_electron, Particle::Type::electron); - - // Allow electrons to fill orbital and produce auger electrons - // and fluorescent photons - element.atomic_relaxation(shell, *p); - p->event_ = EVENT_ABSORB; - p->event_mt_ = 533 + shell.index_subshell; - p->alive_ = false; - p->E_ = 0.0; - return; - } - } - } - prob = prob_after; - - // Pair production - prob += micro.pair_production; - if (prob > cutoff) { - double E_electron, E_positron; - double mu_electron, mu_positron; - element.pair_production(alpha, &E_electron, &E_positron, - &mu_electron, &mu_positron); - - // Create secondary electron - Direction u = rotate_angle(p->u(), mu_electron, nullptr); - p->create_secondary(u, E_electron, Particle::Type::electron); - - // Create secondary positron - u = rotate_angle(p->u(), mu_positron, nullptr); - p->create_secondary(u, E_positron, Particle::Type::positron); - - p->event_ = EVENT_ABSORB; - p->event_mt_ = PAIR_PROD; - p->alive_ = false; - p->E_ = 0.0; - } -} - -void sample_electron_reaction(Particle* p) -{ - // TODO: create reaction types - - if (settings::electron_treatment == ELECTRON_TTB) { - double E_lost; - thick_target_bremsstrahlung(*p, &E_lost); - } - - p->E_ = 0.0; - p->alive_ = false; - p->event_ = EVENT_ABSORB; -} - -void sample_positron_reaction(Particle* p) -{ - // TODO: create reaction types - - if (settings::electron_treatment == ELECTRON_TTB) { - double E_lost; - thick_target_bremsstrahlung(*p, &E_lost); - } - - // Sample angle isotropically - double mu = 2.0*prn() - 1.0; - double phi = 2.0*PI*prn(); - Direction u; - u.x = mu; - u.y = std::sqrt(1.0 - mu*mu)*std::cos(phi); - u.z = std::sqrt(1.0 - mu*mu)*std::sin(phi); - - // Create annihilation photon pair traveling in opposite directions - p->create_secondary(u, MASS_ELECTRON_EV, Particle::Type::photon); - p->create_secondary(-u, MASS_ELECTRON_EV, Particle::Type::photon); - - p->E_ = 0.0; - p->alive_ = false; - p->event_ = EVENT_ABSORB; -} - -int sample_nuclide(const Particle* p) -{ - // Sample cumulative distribution function - double cutoff = prn() * p->macro_xs_.total; - - // Get pointers to nuclide/density arrays - const auto& mat {model::materials[p->material_]}; - int n = mat->nuclide_.size(); - - double prob = 0.0; - for (int i = 0; i < n; ++i) { - // Get atom density - int i_nuclide = mat->nuclide_[i]; - double atom_density = mat->atom_density_[i]; - - // Increment probability to compare to cutoff - prob += atom_density * p->neutron_xs_[i_nuclide].total; - if (prob >= cutoff) return i_nuclide; - } - - // If we reach here, no nuclide was sampled - p->write_restart(); - throw std::runtime_error{"Did not sample any nuclide during collision."}; -} - -int sample_element(Particle* p) -{ - // Sample cumulative distribution function - double cutoff = prn() * p->macro_xs_.total; - - // Get pointers to elements, densities - const auto& mat {model::materials[p->material_]}; - - double prob = 0.0; - for (int i = 0; i < mat->element_.size(); ++i) { - // Find atom density - int i_element = mat->element_[i]; - double atom_density = mat->atom_density_[i]; - - // Determine microscopic cross section - double sigma = atom_density * p->photon_xs_[i_element].total; - - // Increment probability to compare to cutoff - prob += sigma; - if (prob > cutoff) { - // Save which nuclide particle had collision with for tally purpose - p->event_nuclide_ = mat->nuclide_[i]; - - return i_element; - } - } - - // If we made it here, no element was sampled - p->write_restart(); - fatal_error("Did not sample any element during collision."); -} - -Reaction* sample_fission(int i_nuclide, const Particle* p) -{ - // Get pointer to nuclide - const auto& nuc {data::nuclides[i_nuclide]}; - - // If we're in the URR, by default use the first fission reaction. We also - // default to the first reaction if we know that there are no partial fission - // reactions - if (p->neutron_xs_[i_nuclide].use_ptable || !nuc->has_partial_fission_) { - return nuc->fission_rx_[0]; - } - - // Check to see if we are in a windowed multipole range. WMP only supports - // the first fission reaction. - if (nuc->multipole_) { - if (p->E_ >= nuc->multipole_->E_min_ && p->E_ <= nuc->multipole_->E_max_) { - return nuc->fission_rx_[0]; - } - } - - // Get grid index and interpolatoin factor and sample fission cdf - int i_temp = p->neutron_xs_[i_nuclide].index_temp; - int i_grid = p->neutron_xs_[i_nuclide].index_grid; - double f = p->neutron_xs_[i_nuclide].interp_factor; - double cutoff = prn() * p->neutron_xs_[i_nuclide].fission; - double prob = 0.0; - - // Loop through each partial fission reaction type - for (auto& rx : nuc->fission_rx_) { - // if energy is below threshold for this reaction, skip it - int threshold = rx->xs_[i_temp].threshold; - if (i_grid < threshold) continue; - - // add to cumulative probability - prob += (1.0 - f) * rx->xs_[i_temp].value[i_grid - threshold] - + f*rx->xs_[i_temp].value[i_grid - threshold + 1]; - - // Create fission bank sites if fission occurs - if (prob > cutoff) return rx; - } - - // If we reached here, no reaction was sampled - throw std::runtime_error{"No fission reaction was sampled for " + nuc->name_}; -} - -void sample_photon_product(int i_nuclide, const Particle* p, int* i_rx, int* i_product) -{ - // Get grid index and interpolation factor and sample photon production cdf - int i_temp = p->neutron_xs_[i_nuclide].index_temp; - int i_grid = p->neutron_xs_[i_nuclide].index_grid; - double f = p->neutron_xs_[i_nuclide].interp_factor; - double cutoff = prn() * p->neutron_xs_[i_nuclide].photon_prod; - double prob = 0.0; - - // Loop through each reaction type - const auto& nuc {data::nuclides[i_nuclide]}; - for (int i = 0; i < nuc->reactions_.size(); ++i) { - const auto& rx = nuc->reactions_[i]; - int threshold = rx->xs_[i_temp].threshold; - - // if energy is below threshold for this reaction, skip it - if (i_grid < threshold) continue; - - // Evaluate neutron cross section - double xs = ((1.0 - f) * rx->xs_[i_temp].value[i_grid - threshold] - + f*(rx->xs_[i_temp].value[i_grid - threshold + 1])); - - for (int j = 0; j < rx->products_.size(); ++j) { - if (rx->products_[j].particle_ == Particle::Type::photon) { - // add to cumulative probability - prob += (*rx->products_[j].yield_)(p->E_) * xs; - - *i_rx = i; - *i_product = j; - if (prob > cutoff) return; - } - } - } -} - -void absorption(Particle* p, int i_nuclide) -{ - if (settings::survival_biasing) { - // Determine weight absorbed in survival biasing - p->wgt_absorb_ = p->wgt_ * p->neutron_xs_[i_nuclide].absorption / - p->neutron_xs_[i_nuclide].total; - - // Adjust weight of particle by probability of absorption - p->wgt_ -= p->wgt_absorb_; - p->wgt_last_ = p->wgt_; - - // Score implicit absorption estimate of keff - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - global_tally_absorption += p->wgt_absorb_ * p->neutron_xs_[ - i_nuclide].nu_fission / p->neutron_xs_[i_nuclide].absorption; - } - } else { - // See if disappearance reaction happens - if (p->neutron_xs_[i_nuclide].absorption > - prn() * p->neutron_xs_[i_nuclide].total) { - // Score absorption estimate of keff - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - global_tally_absorption += p->wgt_ * p->neutron_xs_[ - i_nuclide].nu_fission / p->neutron_xs_[i_nuclide].absorption; - } - - p->alive_ = false; - p->event_ = EVENT_ABSORB; - p->event_mt_ = N_DISAPPEAR; - } - } -} - -void scatter(Particle* p, int i_nuclide) -{ - // copy incoming direction - Direction u_old {p->u()}; - - // Get pointer to nuclide and grid index/interpolation factor - const auto& nuc {data::nuclides[i_nuclide]}; - const auto& micro {p->neutron_xs_[i_nuclide]}; - int i_temp = micro.index_temp; - int i_grid = micro.index_grid; - double f = micro.interp_factor; - - // For tallying purposes, this routine might be called directly. In that - // case, we need to sample a reaction via the cutoff variable - double cutoff = prn() * (micro.total - micro.absorption); - bool sampled = false; - - // Calculate elastic cross section if it wasn't precalculated - if (micro.elastic == CACHE_INVALID) { - nuc->calculate_elastic_xs(*p); - } - - double prob = micro.elastic - micro.thermal; - if (prob > cutoff) { - // ======================================================================= - // NON-S(A,B) ELASTIC SCATTERING - - // Determine temperature - double kT = nuc->multipole_ ? p->sqrtkT_*p->sqrtkT_ : nuc->kTs_[i_temp]; - - // Perform collision physics for elastic scattering - elastic_scatter(i_nuclide, *nuc->reactions_[0], kT, p); - - p->event_mt_ = ELASTIC; - sampled = true; - } - - prob = micro.elastic; - if (prob > cutoff && !sampled) { - // ======================================================================= - // S(A,B) SCATTERING - - sab_scatter(i_nuclide, micro.index_sab, p); - - p->event_mt_ = ELASTIC; - sampled = true; - } - - if (!sampled) { - // ======================================================================= - // INELASTIC SCATTERING - - int j = 0; - int i = 0; - while (prob < cutoff) { - i = nuc->index_inelastic_scatter_[j]; - ++j; - - // Check to make sure inelastic scattering reaction sampled - if (i >= nuc->reactions_.size()) { - p->write_restart(); - fatal_error("Did not sample any reaction for nuclide " + nuc->name_); - } - - // if energy is below threshold for this reaction, skip it - const auto& xs {nuc->reactions_[i]->xs_[i_temp]}; - if (i_grid < xs.threshold) continue; - - // add to cumulative probability - prob += (1.0 - f)*xs.value[i_grid - xs.threshold] + - f*xs.value[i_grid - xs.threshold + 1]; - } - - // Perform collision physics for inelastic scattering - const auto& rx {nuc->reactions_[i]}; - inelastic_scatter(nuc.get(), rx.get(), p); - p->event_mt_ = rx->mt_; - } - - // Set event component - p->event_ = EVENT_SCATTER; - - // Sample new outgoing angle for isotropic-in-lab scattering - const auto& mat {model::materials[p->material_]}; - if (!mat->p0_.empty()) { - int i_nuc_mat = mat->mat_nuclide_index_[i_nuclide]; - if (mat->p0_[i_nuc_mat]) { - // Sample isotropic-in-lab outgoing direction - double mu = 2.0*prn() - 1.0; - double phi = 2.0*PI*prn(); - - // Change direction of particle - p->u().x = mu; - p->u().y = std::sqrt(1.0 - mu*mu)*std::cos(phi); - p->u().z = std::sqrt(1.0 - mu*mu)*std::sin(phi); - p->mu_ = u_old.dot(p->u()); - } - } -} - -void elastic_scatter(int i_nuclide, const Reaction& rx, double kT, - Particle* p) -{ - // get pointer to nuclide - const auto& nuc {data::nuclides[i_nuclide]}; - - double vel = std::sqrt(p->E_); - double awr = nuc->awr_; - - // Neutron velocity in LAB - Direction v_n = vel*p->u(); - - // Sample velocity of target nucleus - Direction v_t {}; - if (!p->neutron_xs_[i_nuclide].use_ptable) { - v_t = sample_target_velocity(nuc.get(), p->E_, p->u(), v_n, - p->neutron_xs_[i_nuclide].elastic, kT); - } - - // Velocity of center-of-mass - Direction v_cm = (v_n + awr*v_t)/(awr + 1.0); - - // Transform to CM frame - v_n -= v_cm; - - // Find speed of neutron in CM - vel = v_n.norm(); - - // Sample scattering angle, checking if it is an ncorrelated angle-energy - // distribution - double mu_cm; - auto& d = rx.products_[0].distribution_[0]; - auto d_ = dynamic_cast(d.get()); - if (d_) { - mu_cm = d_->angle().sample(p->E_); - } else { - mu_cm = 2.0*prn() - 1.0; - } - - // Determine direction cosines in CM - Direction u_cm = v_n/vel; - - // Rotate neutron velocity vector to new angle -- note that the speed of the - // neutron in CM does not change in elastic scattering. However, the speed - // will change when we convert back to LAB - v_n = vel * rotate_angle(u_cm, mu_cm, nullptr); - - // Transform back to LAB frame - v_n += v_cm; - - p->E_ = v_n.dot(v_n); - vel = std::sqrt(p->E_); - - // compute cosine of scattering angle in LAB frame by taking dot product of - // neutron's pre- and post-collision angle - p->mu_ = p->u().dot(v_n) / vel; - - // Set energy and direction of particle in LAB frame - p->u() = v_n / vel; - - // Because of floating-point roundoff, it may be possible for mu_lab to be - // outside of the range [-1,1). In these cases, we just set mu_lab to exactly - // -1 or 1 - if (std::abs(p->mu_) > 1.0) p->mu_ = std::copysign(1.0, p->mu_); -} - -void sab_scatter(int i_nuclide, int i_sab, Particle* p) -{ - // Determine temperature index - const auto& micro {p->neutron_xs_[i_nuclide]}; - int i_temp = micro.index_temp_sab; - - // Sample energy and angle - double E_out; - data::thermal_scatt[i_sab]->data_[i_temp].sample(micro, p->E_, &E_out, &p->mu_); - - // Set energy to outgoing, change direction of particle - p->E_ = E_out; - p->u() = rotate_angle(p->u(), p->mu_, nullptr); -} - -Direction sample_target_velocity(const Nuclide* nuc, double E, Direction u, - Direction v_neut, double xs_eff, double kT) -{ - // check if nuclide is a resonant scatterer - ResScatMethod sampling_method; - if (nuc->resonant_) { - - // sampling method to use - sampling_method = settings::res_scat_method; - - // upper resonance scattering energy bound (target is at rest above this E) - if (E > settings::res_scat_energy_max) { - return {}; - - // lower resonance scattering energy bound (should be no resonances below) - } else if (E < settings::res_scat_energy_min) { - sampling_method = ResScatMethod::cxs; - } - - // otherwise, use free gas model - } else { - if (E >= FREE_GAS_THRESHOLD * kT && nuc->awr_ > 1.0) { - return {}; - } else { - sampling_method = ResScatMethod::cxs; - } - } - - // use appropriate target velocity sampling method - switch (sampling_method) { - case ResScatMethod::cxs: - - // sample target velocity with the constant cross section (cxs) approx. - return sample_cxs_target_velocity(nuc->awr_, E, u, kT); - - case ResScatMethod::dbrc: - case ResScatMethod::rvs: { - double E_red = std::sqrt(nuc->awr_ * E / kT); - double E_low = std::pow(std::max(0.0, E_red - 4.0), 2) * kT / nuc->awr_; - double E_up = (E_red + 4.0)*(E_red + 4.0) * kT / nuc->awr_; - - // find lower and upper energy bound indices - // lower index - int i_E_low; - if (E_low < nuc->energy_0K_.front()) { - i_E_low = 0; - } else if (E_low > nuc->energy_0K_.back()) { - i_E_low = nuc->energy_0K_.size() - 2; - } else { - i_E_low = lower_bound_index(nuc->energy_0K_.begin(), - nuc->energy_0K_.end(), E_low); - } - - // upper index - int i_E_up; - if (E_up < nuc->energy_0K_.front()) { - i_E_up = 0; - } else if (E_up > nuc->energy_0K_.back()) { - i_E_up = nuc->energy_0K_.size() - 2; - } else { - i_E_up = lower_bound_index(nuc->energy_0K_.begin(), - nuc->energy_0K_.end(), E_up); - } - - if (i_E_up == i_E_low) { - // Handle degenerate case -- if the upper/lower bounds occur for the same - // index, then using cxs is probably a good approximation - return sample_cxs_target_velocity(nuc->awr_, E, u, kT); - } - - if (sampling_method == ResScatMethod::dbrc) { - // interpolate xs since we're not exactly at the energy indices - double xs_low = nuc->elastic_0K_[i_E_low]; - double m = (nuc->elastic_0K_[i_E_low + 1] - xs_low) - / (nuc->energy_0K_[i_E_low + 1] - nuc->energy_0K_[i_E_low]); - xs_low += m * (E_low - nuc->energy_0K_[i_E_low]); - double xs_up = nuc->elastic_0K_[i_E_up]; - m = (nuc->elastic_0K_[i_E_up + 1] - xs_up) - / (nuc->energy_0K_[i_E_up + 1] - nuc->energy_0K_[i_E_up]); - xs_up += m * (E_up - nuc->energy_0K_[i_E_up]); - - // get max 0K xs value over range of practical relative energies - double xs_max = *std::max_element(&nuc->elastic_0K_[i_E_low + 1], - &nuc->elastic_0K_[i_E_up + 1]); - xs_max = std::max({xs_low, xs_max, xs_up}); - - while (true) { - double E_rel; - Direction v_target; - while (true) { - // sample target velocity with the constant cross section (cxs) approx. - v_target = sample_cxs_target_velocity(nuc->awr_, E, u, kT); - Direction v_rel = v_neut - v_target; - E_rel = v_rel.dot(v_rel); - if (E_rel < E_up) break; - } - - // perform Doppler broadening rejection correction (dbrc) - double xs_0K = nuc->elastic_xs_0K(E_rel); - double R = xs_0K / xs_max; - if (prn() < R) return v_target; - } - - } else if (sampling_method == ResScatMethod::rvs) { - // interpolate xs CDF since we're not exactly at the energy indices - // cdf value at lower bound attainable energy - double m = (nuc->xs_cdf_[i_E_low] - nuc->xs_cdf_[i_E_low - 1]) - / (nuc->energy_0K_[i_E_low + 1] - nuc->energy_0K_[i_E_low]); - double cdf_low = nuc->xs_cdf_[i_E_low - 1] - + m * (E_low - nuc->energy_0K_[i_E_low]); - if (E_low <= nuc->energy_0K_.front()) cdf_low = 0.0; - - // cdf value at upper bound attainable energy - m = (nuc->xs_cdf_[i_E_up] - nuc->xs_cdf_[i_E_up - 1]) - / (nuc->energy_0K_[i_E_up + 1] - nuc->energy_0K_[i_E_up]); - double cdf_up = nuc->xs_cdf_[i_E_up - 1] - + m*(E_up - nuc->energy_0K_[i_E_up]); - - while (true) { - // directly sample Maxwellian - double E_t = -kT * std::log(prn()); - - // sample a relative energy using the xs cdf - double cdf_rel = cdf_low + prn()*(cdf_up - cdf_low); - int i_E_rel = lower_bound_index(&nuc->xs_cdf_[i_E_low-1], - &nuc->xs_cdf_[i_E_up+1], cdf_rel); - double E_rel = nuc->energy_0K_[i_E_low + i_E_rel]; - double m = (nuc->xs_cdf_[i_E_low + i_E_rel] - - nuc->xs_cdf_[i_E_low + i_E_rel - 1]) - / (nuc->energy_0K_[i_E_low + i_E_rel + 1] - - nuc->energy_0K_[i_E_low + i_E_rel]); - E_rel += (cdf_rel - nuc->xs_cdf_[i_E_low + i_E_rel - 1]) / m; - - // perform rejection sampling on cosine between - // neutron and target velocities - double mu = (E_t + nuc->awr_ * (E - E_rel)) / - (2.0 * std::sqrt(nuc->awr_ * E * E_t)); - - if (std::abs(mu) < 1.0) { - // set and accept target velocity - E_t /= nuc->awr_; - return std::sqrt(E_t) * rotate_angle(u, mu, nullptr); - } - } - } - } // case RVS, DBRC - } // switch (sampling_method) - - UNREACHABLE(); -} - -Direction -sample_cxs_target_velocity(double awr, double E, Direction u, double kT) -{ - double beta_vn = std::sqrt(awr * E / kT); - double alpha = 1.0/(1.0 + std::sqrt(PI)*beta_vn/2.0); - - double beta_vt_sq; - double mu; - while (true) { - // Sample two random numbers - double r1 = prn(); - double r2 = prn(); - - if (prn() < alpha) { - // With probability alpha, we sample the distribution p(y) = - // y*e^(-y). This can be done with sampling scheme C45 frmo the Monte - // Carlo sampler - - beta_vt_sq = -std::log(r1*r2); - - } else { - // With probability 1-alpha, we sample the distribution p(y) = y^2 * - // e^(-y^2). This can be done with sampling scheme C61 from the Monte - // Carlo sampler - - double c = std::cos(PI/2.0 * prn()); - beta_vt_sq = -std::log(r1) - std::log(r2)*c*c; - } - - // Determine beta * vt - double beta_vt = std::sqrt(beta_vt_sq); - - // Sample cosine of angle between neutron and target velocity - mu = 2.0*prn() - 1.0; - - // Determine rejection probability - double accept_prob = std::sqrt(beta_vn*beta_vn + beta_vt_sq - - 2*beta_vn*beta_vt*mu) / (beta_vn + beta_vt); - - // Perform rejection sampling on vt and mu - if (prn() < accept_prob) break; - } - - // Determine speed of target nucleus - double vt = std::sqrt(beta_vt_sq*kT/awr); - - // Determine velocity vector of target nucleus based on neutron's velocity - // and the sampled angle between them - return vt * rotate_angle(u, mu, nullptr); -} - -void sample_fission_neutron(int i_nuclide, const Reaction* rx, double E_in, Particle::Bank* site) -{ - // Sample cosine of angle -- fission neutrons are always emitted - // isotropically. Sometimes in ACE data, fission reactions actually have - // an angular distribution listed, but for those that do, it's simply just - // a uniform distribution in mu - double mu = 2.0 * prn() - 1.0; - - // Sample azimuthal angle uniformly in [0,2*pi) - double phi = 2.0*PI*prn(); - site->u.x = mu; - site->u.y = std::sqrt(1.0 - mu*mu) * std::cos(phi); - site->u.z = std::sqrt(1.0 - mu*mu) * std::sin(phi); - - // Determine total nu, delayed nu, and delayed neutron fraction - const auto& nuc {data::nuclides[i_nuclide]}; - double nu_t = nuc->nu(E_in, Nuclide::EmissionMode::total); - double nu_d = nuc->nu(E_in, Nuclide::EmissionMode::delayed); - double beta = nu_d / nu_t; - - if (prn() < beta) { - // ==================================================================== - // DELAYED NEUTRON SAMPLED - - // sampled delayed precursor group - double xi = prn()*nu_d; - double prob = 0.0; - int group; - for (group = 1; group < nuc->n_precursor_; ++group) { - // determine delayed neutron precursor yield for group j - double yield = (*rx->products_[group].yield_)(E_in); - - // Check if this group is sampled - prob += yield; - if (xi < prob) break; - } - - // if the sum of the probabilities is slightly less than one and the - // random number is greater, j will be greater than nuc % - // n_precursor -- check for this condition - group = std::min(group, nuc->n_precursor_); - - // set the delayed group for the particle born from fission - site->delayed_group = group; - - int n_sample = 0; - while (true) { - // sample from energy/angle distribution -- note that mu has already been - // sampled above and doesn't need to be resampled - rx->products_[group].sample(E_in, site->E, mu); - - // resample if energy is greater than maximum neutron energy - constexpr int neutron = static_cast(Particle::Type::neutron); - if (site->E < data::energy_max[neutron]) break; - - // check for large number of resamples - ++n_sample; - if (n_sample == MAX_SAMPLE) { - // particle_write_restart(p) - fatal_error("Resampled energy distribution maximum number of times " - "for nuclide " + nuc->name_); - } - } - - } else { - // ==================================================================== - // PROMPT NEUTRON SAMPLED - - // set the delayed group for the particle born from fission to 0 - site->delayed_group = 0; - - // sample from prompt neutron energy distribution - int n_sample = 0; - while (true) { - rx->products_[0].sample(E_in, site->E, mu); - - // resample if energy is greater than maximum neutron energy - constexpr int neutron = static_cast(Particle::Type::neutron); - if (site->E < data::energy_max[neutron]) break; - - // check for large number of resamples - ++n_sample; - if (n_sample == MAX_SAMPLE) { - // particle_write_restart(p) - fatal_error("Resampled energy distribution maximum number of times " - "for nuclide " + nuc->name_); - } - } - } -} - -void inelastic_scatter(const Nuclide* nuc, const Reaction* rx, Particle* p) -{ - // copy energy of neutron - double E_in = p->E_; - - // sample outgoing energy and scattering cosine - double E; - double mu; - rx->products_[0].sample(E_in, E, mu); - - // if scattering system is in center-of-mass, transfer cosine of scattering - // angle and outgoing energy from CM to LAB - if (rx->scatter_in_cm_) { - double E_cm = E; - - // determine outgoing energy in lab - double A = nuc->awr_; - E = E_cm + (E_in + 2.0*mu*(A + 1.0) * std::sqrt(E_in*E_cm)) - / ((A + 1.0)*(A + 1.0)); - - // determine outgoing angle in lab - mu = mu*std::sqrt(E_cm/E) + 1.0/(A+1.0) * std::sqrt(E_in/E); - } - - // Because of floating-point roundoff, it may be possible for mu to be - // outside of the range [-1,1). In these cases, we just set mu to exactly -1 - // or 1 - if (std::abs(mu) > 1.0) mu = std::copysign(1.0, mu); - - // Set outgoing energy and scattering angle - p->E_ = E; - p->mu_ = mu; - - // change direction of particle - p->u() = rotate_angle(p->u(), mu, nullptr); - - // evaluate yield - double yield = (*rx->products_[0].yield_)(E_in); - if (std::floor(yield) == yield) { - // If yield is integral, create exactly that many secondary particles - for (int i = 0; i < static_cast(std::round(yield)) - 1; ++i) { - p->create_secondary(p->u(), p->E_, Particle::Type::neutron); - } - } else { - // Otherwise, change weight of particle based on yield - p->wgt_ *= yield; - } -} - -void sample_secondary_photons(Particle* p, int i_nuclide) -{ - // Sample the number of photons produced - double y_t = p->wgt_ * p->neutron_xs_[i_nuclide].photon_prod / - p->neutron_xs_[i_nuclide].total; - int y = static_cast(y_t); - if (prn() <= y_t - y) ++y; - - // Sample each secondary photon - for (int i = 0; i < y; ++i) { - // Sample the reaction and product - int i_rx; - int i_product; - sample_photon_product(i_nuclide, p, &i_rx, &i_product); - - // Sample the outgoing energy and angle - auto& rx = data::nuclides[i_nuclide]->reactions_[i_rx]; - double E; - double mu; - rx->products_[i_product].sample(p->E_, E, mu); - - // Sample the new direction - Direction u = rotate_angle(p->u(), mu, nullptr); - - // Create the secondary photon - p->create_secondary(u, E, Particle::Type::photon); - } -} - -} // namespace openmc diff --git a/src/physics_common.cpp b/src/physics_common.cpp deleted file mode 100644 index 42ddc2ecb..000000000 --- a/src/physics_common.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "openmc/physics_common.h" - -#include "openmc/settings.h" -#include "openmc/random_lcg.h" - -namespace openmc { - -//============================================================================== -// RUSSIAN_ROULETTE -//============================================================================== - -void russian_roulette(Particle* p) -{ - if (p->wgt_ < settings::weight_cutoff) { - if (prn() < p->wgt_ / settings::weight_survive) { - p->wgt_ = settings::weight_survive; - p->wgt_last_ = p->wgt_; - } else { - p->wgt_ = 0.; - p->wgt_last_ = 0.; - p->alive_ = false; - } - } -} - -} //namespace openmc diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp deleted file mode 100644 index f99d15aac..000000000 --- a/src/physics_mg.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include "openmc/physics_mg.h" - -#include -#include - -#include "xtensor/xarray.hpp" - -#include "openmc/bank.h" -#include "openmc/constants.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/material.h" -#include "openmc/math_functions.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/physics_common.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/tallies/tally.h" - -namespace openmc { - -void -collision_mg(Particle* p) -{ - // Add to the collision counter for the particle - p->n_collision_++; - - // Sample the reaction type - sample_reaction(p); - - // Display information about collision - if ((settings::verbosity >= 10) || (simulation::trace)) { - std::stringstream msg; - msg << " Energy Group = " << p->g_; - write_message(msg, 1); - } -} - -void -sample_reaction(Particle* p) -{ - // Create fission bank sites. Note that while a fission reaction is sampled, - // it never actually "happens", i.e. the weight of the particle does not - // change when sampling fission sites. The following block handles all - // absorption (including fission) - - if (model::materials[p->material_]->fissionable_) { - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - create_fission_sites(p, simulation::fission_bank); - } else if ((settings::run_mode == RUN_MODE_FIXEDSOURCE) && - (settings::create_fission_neutrons)) { - create_fission_sites(p, simulation::secondary_bank); - } - } - - // If survival biasing is being used, the following subroutine adjusts the - // weight of the particle. Otherwise, it checks to see if absorption occurs. - if (p->macro_xs_.absorption > 0.) { - absorption(p); - } else { - p->wgt_absorb_ = 0.; - } - if (!p->alive_) return; - - // Sample a scattering event to determine the energy of the exiting neutron - scatter(p); - - // Play Russian roulette if survival biasing is turned on - if (settings::survival_biasing) { - russian_roulette(p); - if (!p->alive_) return; - } -} - -void -scatter(Particle* p) -{ - // Adjust indices for Fortran to C++ indexing - // TODO: Remove when no longer needed - int gin = p->g_last_ - 1; - int gout = p->g_ - 1; - int i_mat = p->material_; - data::macro_xs[i_mat].sample_scatter(gin, gout, p->mu_, p->wgt_); - - // Adjust return value for fortran indexing - // TODO: Remove when no longer needed - p->g_ = gout + 1; - - // Rotate the angle - p->u() = rotate_angle(p->u(), p->mu_, nullptr); - - // Update energy value for downstream compatability (in tallying) - p->E_ = data::energy_bin_avg[gout]; - - // Set event component - p->event_ = EVENT_SCATTER; -} - -void -create_fission_sites(Particle* p, std::vector& bank) -{ - // If uniform fission source weighting is turned on, we increase or decrease - // the expected number of fission sites produced - double weight = settings::ufs_on ? ufs_get_weight(p) : 1.0; - - // Determine the expected number of neutrons produced - double nu_t = p->wgt_ / simulation::keff * weight * - p->macro_xs_.nu_fission / p->macro_xs_.total; - - // Sample the number of neutrons produced - int nu = static_cast(nu_t); - if (prn() <= (nu_t - int(nu_t))) { - nu++; - } - - // Begin banking the source neutrons - // First, if our bank is full then don't continue - if (nu == 0) return; - - // Initialize the counter of delayed neutrons encountered for each delayed - // group. - double nu_d[MAX_DELAYED_GROUPS] = {0.}; - - p->fission_ = true; - for (int i = 0; i < nu; ++i) { - // Create new bank site and get reference to last element - bank.emplace_back(); - auto& site {bank.back()}; - - // Bank source neutrons by copying the particle data - site.r = p->r(); - site.particle = Particle::Type::neutron; - site.wgt = 1. / weight; - - // Sample the cosine of the angle, assuming fission neutrons are emitted - // isotropically - double mu = 2.*prn() - 1.; - - // Sample the azimuthal angle uniformly in [0, 2.pi) - double phi = 2. * PI * prn(); - site.u.x = mu; - site.u.y = std::sqrt(1. - mu * mu) * std::cos(phi); - site.u.z = std::sqrt(1. - mu * mu) * std::sin(phi); - - // Sample secondary energy distribution for the fission reaction and set - // the energy in the fission bank - int dg; - int gout; - data::macro_xs[p->material_].sample_fission_energy(p->g_ - 1, dg, gout); - site.E = gout + 1; - site.delayed_group = dg + 1; - - // Set the delayed group on the particle as well - p->delayed_group_ = dg + 1; - - // Increment the number of neutrons born delayed - if (p->delayed_group_ > 0) { - nu_d[dg]++; - } - } - - // Store the total weight banked for analog fission tallies - p->n_bank_ = nu; - p->wgt_bank_ = nu / weight; - for (size_t d = 0; d < MAX_DELAYED_GROUPS; d++) { - p->n_delayed_bank_[d] = nu_d[d]; - } -} - -void -absorption(Particle* p) -{ - if (settings::survival_biasing) { - // Determine weight absorbed in survival biasing - p->wgt_absorb_ = p->wgt_ * p->macro_xs_.absorption / p->macro_xs_.total; - - // Adjust weight of particle by the probability of absorption - p->wgt_ -= p->wgt_absorb_; - p->wgt_last_ = p->wgt_; - - // Score implicit absorpion estimate of keff - #pragma omp atomic - global_tally_absorption += p->wgt_absorb_ * p->macro_xs_.nu_fission / - p->macro_xs_.absorption; - } else { - if (p->macro_xs_.absorption > prn() * p->macro_xs_.total) { - #pragma omp atomic - global_tally_absorption += p->wgt_ * p->macro_xs_.nu_fission / - p->macro_xs_.absorption; - p->alive_ = false; - p->event_ = EVENT_ABSORB; - } - - } -} - -} //namespace openmc diff --git a/src/plot.cpp b/src/plot.cpp deleted file mode 100644 index 98a3645c7..000000000 --- a/src/plot.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -#include "openmc/plot.h" - -#include -#include -#include - -#include "xtensor/xview.hpp" - -#include "openmc/constants.h" -#include "openmc/file_utils.h" -#include "openmc/geometry.h" -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/mesh.h" -#include "openmc/message_passing.h" -#include "openmc/output.h" -#include "openmc/particle.h" -#include "openmc/progress_bar.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" - -namespace openmc { - -//============================================================================== -// Constants -//============================================================================== - - -constexpr int PLOT_LEVEL_LOWEST {-1}; //!< lower bound on plot universe level -constexpr int32_t NOT_FOUND {-2}; -constexpr int32_t OVERLAP {-3}; - -IdData::IdData(size_t h_res, size_t v_res) - : data_({v_res, h_res, 2}, NOT_FOUND) -{ } - -void -IdData::set_value(size_t y, size_t x, const Particle& p, int level) { - Cell* c = model::cells[p.coord_[level].cell].get(); - data_(y,x,0) = c->id_; - if (p.material_ == MATERIAL_VOID) { - data_(y,x,1) = MATERIAL_VOID; - return; - } else if (c->type_ != FILL_UNIVERSE) { - Material* m = model::materials[p.material_].get(); - data_(y,x,1) = m->id_; - } -} - -void IdData::set_overlap(size_t y, size_t x) { - xt::view(data_, y, x, xt::all()) = OVERLAP; -} - -PropertyData::PropertyData(size_t h_res, size_t v_res) - : data_({v_res, h_res, 2}, NOT_FOUND) -{ } - -void -PropertyData::set_value(size_t y, size_t x, const Particle& p, int level) { - Cell* c = model::cells[p.coord_[level].cell].get(); - data_(y,x,0) = (p.sqrtkT_ * p.sqrtkT_) / K_BOLTZMANN; - if (c->type_ != FILL_UNIVERSE && p.material_ != MATERIAL_VOID) { - Material* m = model::materials[p.material_].get(); - data_(y,x,1) = m->density_gpcc_; - } -} - -void PropertyData::set_overlap(size_t y, size_t x) { - data_(y, x) = OVERLAP; -} - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - -std::vector plots; -std::unordered_map plot_map; - -} // namespace model - -//============================================================================== -// RUN_PLOT controls the logic for making one or many plots -//============================================================================== - -extern "C" -int openmc_plot_geometry() -{ - for (auto pl : model::plots) { - std::stringstream ss; - ss << "Processing plot " << pl.id_ << ": " - << pl.path_plot_ << "..."; - write_message(ss.str(), 5); - - if (PlotType::slice == pl.type_) { - // create 2D image - create_ppm(pl); - } else if (PlotType::voxel == pl.type_) { - // create voxel file for 3D viewing - create_voxel(pl); - } - } - return 0; -} - - -void read_plots_xml() -{ - // Check if plots.xml exists - std::string filename = settings::path_input + "plots.xml"; - if (!file_exists(filename)) { - fatal_error("Plots XML file '" + filename + "' does not exist!"); - } - - write_message("Reading plot XML file...", 5); - - // Parse plots.xml file - pugi::xml_document doc; - doc.load_file(filename.c_str()); - - pugi::xml_node root = doc.document_element(); - for (auto node : root.children("plot")) { - Plot pl(node); - model::plots.push_back(pl); - model::plot_map[pl.id_] = model::plots.size() - 1; - } -} - -//============================================================================== -// CREATE_PPM creates an image based on user input from a plots.xml -// specification in the portable pixmap format (PPM) -//============================================================================== - -void create_ppm(Plot pl) -{ - - size_t width = pl.pixels_[0]; - size_t height = pl.pixels_[1]; - - ImageData data({width, height}, pl.not_found_); - - // generate ids for the plot - auto ids = pl.get_map(); - - // assign colors - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - auto id = ids.data_(y, x, pl.color_by_); - // no setting needed if not found - if (id == NOT_FOUND) { continue; } - if (id == OVERLAP) { - data(x,y) = pl.overlap_color_; - continue; - } - if (PlotColorBy::cells == pl.color_by_) { - data(x,y) = pl.colors_[model::cell_map[id]]; - } else if (PlotColorBy::mats == pl.color_by_) { - if (id == MATERIAL_VOID) { - data(x,y) = WHITE; - continue; - } - data(x,y) = pl.colors_[model::material_map[id]]; - } // color_by if-else - } // x for loop - } // y for loop - - // draw mesh lines if present - if (pl.index_meshlines_mesh_ >= 0) {draw_mesh_lines(pl, data);} - - // write ppm data to file - output_ppm(pl, data); -} - -void -Plot::set_id(pugi::xml_node plot_node) -{ - // Copy data into plots - if (check_for_node(plot_node, "id")) { - id_ = std::stoi(get_node_value(plot_node, "id")); - } else { - fatal_error("Must specify plot id in plots XML file."); - } - - // Check to make sure 'id' hasn't been used - if (model::plot_map.find(id_) != model::plot_map.end()) { - std::stringstream err_msg; - err_msg << "Two or more plots use the same unique ID: " << id_; - fatal_error(err_msg.str()); - } -} - -void -Plot::set_type(pugi::xml_node plot_node) -{ - // Copy plot type - // Default is slice - type_ = PlotType::slice; - // check type specified on plot node - if (check_for_node(plot_node, "type")) { - std::string type_str = get_node_value(plot_node, "type", true); - // set type using node value - if (type_str == "slice") { - type_ = PlotType::slice; - } - else if (type_str == "voxel") { - type_ = PlotType::voxel; - } else { - // if we're here, something is wrong - std::stringstream err_msg; - err_msg << "Unsupported plot type '" << type_str - << "' in plot " << id_; - fatal_error(err_msg.str()); - } - } -} - -void -Plot::set_output_path(pugi::xml_node plot_node) -{ - // Set output file path - std::stringstream filename; - - if (check_for_node(plot_node, "filename")) { - filename << get_node_value(plot_node, "filename"); - } else { - filename << "plot_" << id_; - } - // add appropriate file extension to name - switch(type_) { - case PlotType::slice: - filename << ".ppm"; - break; - case PlotType::voxel: - filename << ".h5"; - break; - } - - path_plot_ = filename.str(); - - // Copy plot pixel size - std::vector pxls = get_node_array(plot_node, "pixels"); - if (PlotType::slice == type_) { - if (pxls.size() == 2) { - pixels_[0] = pxls[0]; - pixels_[1] = pxls[1]; - } else { - std::stringstream err_msg; - err_msg << " must be length 2 in slice plot " - << id_; - fatal_error(err_msg.str()); - } - } else if (PlotType::voxel == type_) { - if (pxls.size() == 3) { - pixels_[0] = pxls[0]; - pixels_[1] = pxls[1]; - pixels_[2] = pxls[2]; - } else { - std::stringstream err_msg; - err_msg << " must be length 3 in voxel plot " - << id_; - fatal_error(err_msg.str()); - } - } -} - -void -Plot::set_bg_color(pugi::xml_node plot_node) -{ - // Copy plot background color - if (check_for_node(plot_node, "background")) { - std::vector bg_rgb = get_node_array(plot_node, "background"); - if (PlotType::voxel == type_) { - if (mpi::master) { - std::stringstream err_msg; - err_msg << "Background color ignored in voxel plot " - << id_; - warning(err_msg.str()); - } - } - if (bg_rgb.size() == 3) { - not_found_ = bg_rgb; - } else { - std::stringstream err_msg; - err_msg << "Bad background RGB in plot " - << id_; - fatal_error(err_msg); - } - } -} - -void -Plot::set_basis(pugi::xml_node plot_node) -{ - // Copy plot basis - if (PlotType::slice == type_) { - std::string pl_basis = "xy"; - if (check_for_node(plot_node, "basis")) { - pl_basis = get_node_value(plot_node, "basis", true); - } - if ("xy" == pl_basis) { - basis_ = PlotBasis::xy; - } else if ("xz" == pl_basis) { - basis_ = PlotBasis::xz; - } else if ("yz" == pl_basis) { - basis_ = PlotBasis::yz; - } else { - std::stringstream err_msg; - err_msg << "Unsupported plot basis '" << pl_basis - << "' in plot " << id_; - fatal_error(err_msg); - } - } -} - -void -Plot::set_origin(pugi::xml_node plot_node) -{ - // Copy plotting origin - auto pl_origin = get_node_array(plot_node, "origin"); - if (pl_origin.size() == 3) { - origin_ = pl_origin; - } else { - std::stringstream err_msg; - err_msg << "Origin must be length 3 in plot " - << id_; - fatal_error(err_msg); - } -} - -void -Plot::set_width(pugi::xml_node plot_node) -{ - // Copy plotting width - std::vector pl_width = get_node_array(plot_node, "width"); - if (PlotType::slice == type_) { - if (pl_width.size() == 2) { - width_.x = pl_width[0]; - width_.y = pl_width[1]; - } else { - std::stringstream err_msg; - err_msg << " must be length 2 in slice plot " - << id_; - fatal_error(err_msg); - } - } else if (PlotType::voxel == type_) { - if (pl_width.size() == 3) { - pl_width = get_node_array(plot_node, "width"); - width_ = pl_width; - } else { - std::stringstream err_msg; - err_msg << " must be length 3 in voxel plot " - << id_; - fatal_error(err_msg); - } - } -} - -void -Plot::set_universe(pugi::xml_node plot_node) -{ - // Copy plot universe level - if (check_for_node(plot_node, "level")) { - level_ = std::stoi(get_node_value(plot_node, "level")); - if (level_ < 0) { - std::stringstream err_msg; - err_msg << "Bad universe level in plot " << id_; - fatal_error(err_msg); - } - } else { - level_ = PLOT_LEVEL_LOWEST; - } -} - -void -Plot::set_default_colors(pugi::xml_node plot_node) -{ - // Copy plot color type and initialize all colors randomly - std::string pl_color_by = "cell"; - if (check_for_node(plot_node, "color_by")) { - pl_color_by = get_node_value(plot_node, "color_by", true); - } - if ("cell" == pl_color_by) { - color_by_ = PlotColorBy::cells; - colors_.resize(model::cells.size()); - } else if("material" == pl_color_by) { - color_by_ = PlotColorBy::mats; - colors_.resize(model::materials.size()); - } else { - std::stringstream err_msg; - err_msg << "Unsupported plot color type '" << pl_color_by - << "' in plot " << id_; - fatal_error(err_msg); - } - - for (auto& c : colors_) { - c = random_color(); - // make sure we don't interfere with some default colors - while (c == RED || c == WHITE) { - c = random_color(); - } - } -} - -void -Plot::set_user_colors(pugi::xml_node plot_node) -{ - if (!plot_node.select_nodes("color").empty() && PlotType::voxel == type_) { - if (mpi::master) { - std::stringstream err_msg; - err_msg << "Color specifications ignored in voxel plot " - << id_; - warning(err_msg); - } - } - - for (auto cn : plot_node.children("color")) { - // Make sure 3 values are specified for RGB - std::vector user_rgb = get_node_array(cn, "rgb"); - if (user_rgb.size() != 3) { - std::stringstream err_msg; - err_msg << "Bad RGB in plot " << id_; - fatal_error(err_msg); - } - // Ensure that there is an id for this color specification - int col_id; - if (check_for_node(cn, "id")) { - col_id = std::stoi(get_node_value(cn, "id")); - } else { - std::stringstream err_msg; - err_msg << "Must specify id for color specification in plot " - << id_; - fatal_error(err_msg); - } - // Add RGB - if (PlotColorBy::cells == color_by_) { - if (model::cell_map.find(col_id) != model::cell_map.end()) { - col_id = model::cell_map[col_id]; - colors_[col_id] = user_rgb; - } else { - std::stringstream err_msg; - err_msg << "Could not find cell " << col_id - << " specified in plot " << id_; - fatal_error(err_msg); - } - } else if (PlotColorBy::mats == color_by_) { - if (model::material_map.find(col_id) != model::material_map.end()) { - col_id = model::material_map[col_id]; - colors_[col_id] = user_rgb; - } else { - std::stringstream err_msg; - err_msg << "Could not find material " << col_id - << " specified in plot " << id_; - fatal_error(err_msg); - } - } - } // color node loop -} - -void -Plot::set_meshlines(pugi::xml_node plot_node) -{ - // Deal with meshlines - pugi::xpath_node_set mesh_line_nodes = plot_node.select_nodes("meshlines"); - - if (!mesh_line_nodes.empty()) { - if (PlotType::voxel == type_) { - std::stringstream msg; - msg << "Meshlines ignored in voxel plot " << id_; - warning(msg); - } - - if (mesh_line_nodes.size() == 1) { - // Get first meshline node - pugi::xml_node meshlines_node = mesh_line_nodes[0].node(); - - // Check mesh type - std::string meshtype; - if (check_for_node(meshlines_node, "meshtype")) { - meshtype = get_node_value(meshlines_node, "meshtype"); - } else { - std::stringstream err_msg; - err_msg << "Must specify a meshtype for meshlines specification in plot " << id_; - fatal_error(err_msg); - } - - // Ensure that there is a linewidth for this meshlines specification - std::string meshline_width; - if (check_for_node(meshlines_node, "linewidth")) { - meshline_width = get_node_value(meshlines_node, "linewidth"); - meshlines_width_ = std::stoi(meshline_width); - } else { - std::stringstream err_msg; - err_msg << "Must specify a linewidth for meshlines specification in plot " << id_; - fatal_error(err_msg); - } - - // Check for color - if (check_for_node(meshlines_node, "color")) { - // Check and make sure 3 values are specified for RGB - std::vector ml_rgb = get_node_array(meshlines_node, "color"); - if (ml_rgb.size() != 3) { - std::stringstream err_msg; - err_msg << "Bad RGB for meshlines color in plot " << id_; - fatal_error(err_msg); - } - meshlines_color_ = ml_rgb; - } - - // Set mesh based on type - if ("ufs" == meshtype) { - if (!simulation::ufs_mesh) { - std::stringstream err_msg; - err_msg << "No UFS mesh for meshlines on plot " << id_; - fatal_error(err_msg); - } else { - for (int i = 0; i < model::meshes.size(); ++i) { - if (const auto* m - = dynamic_cast(model::meshes[i].get())) { - if (m == simulation::ufs_mesh) { - index_meshlines_mesh_ = i; - } - } - } - if (index_meshlines_mesh_ == -1) - fatal_error("Could not find the UFS mesh for meshlines plot"); - } - } else if ("entropy" == meshtype) { - if (!simulation::entropy_mesh) { - std::stringstream err_msg; - err_msg << "No entropy mesh for meshlines on plot " << id_; - fatal_error(err_msg); - } else { - for (int i = 0; i < model::meshes.size(); ++i) { - if (const auto* m - = dynamic_cast(model::meshes[i].get())) { - if (m == simulation::entropy_mesh) { - index_meshlines_mesh_ = i; - } - } - } - if (index_meshlines_mesh_ == -1) - fatal_error("Could not find the entropy mesh for meshlines plot"); - } - } else if ("tally" == meshtype) { - // Ensure that there is a mesh id if the type is tally - int tally_mesh_id; - if (check_for_node(meshlines_node, "id")) { - tally_mesh_id = std::stoi(get_node_value(meshlines_node, "id")); - } else { - std::stringstream err_msg; - err_msg << "Must specify a mesh id for meshlines tally " - << "mesh specification in plot " << id_; - fatal_error(err_msg); - } - // find the tally index - int idx; - int err = openmc_get_mesh_index(tally_mesh_id, &idx); - if (err != 0) { - std::stringstream err_msg; - err_msg << "Could not find mesh " << tally_mesh_id - << " specified in meshlines for plot " << id_; - fatal_error(err_msg); - } - index_meshlines_mesh_ = idx; - } else { - std::stringstream err_msg; - err_msg << "Invalid type for meshlines on plot " << id_ ; - fatal_error(err_msg); - } - } else { - std::stringstream err_msg; - err_msg << "Mutliple meshlines specified in plot " << id_; - fatal_error(err_msg); - } - } -} - -void -Plot::set_mask(pugi::xml_node plot_node) -{ - // Deal with masks - pugi::xpath_node_set mask_nodes = plot_node.select_nodes("mask"); - - if (!mask_nodes.empty()) { - if (PlotType::voxel == type_) { - if (mpi::master) { - std::stringstream wrn_msg; - wrn_msg << "Mask ignored in voxel plot " << id_; - warning(wrn_msg); - } - } - - if (mask_nodes.size() == 1) { - // Get pointer to mask - pugi::xml_node mask_node = mask_nodes[0].node(); - - // Determine how many components there are and allocate - std::vector iarray = get_node_array(mask_node, "components"); - if (iarray.size() == 0) { - std::stringstream err_msg; - err_msg << "Missing in mask of plot " << id_; - fatal_error(err_msg); - } - - // First we need to change the user-specified identifiers to indices - // in the cell and material arrays - for (auto& col_id : iarray) { - if (PlotColorBy::cells == color_by_) { - if (model::cell_map.find(col_id) != model::cell_map.end()) { - col_id = model::cell_map[col_id]; - } - else { - std::stringstream err_msg; - err_msg << "Could not find cell " << col_id - << " specified in the mask in plot " << id_; - fatal_error(err_msg); - } - } else if (PlotColorBy::mats == color_by_) { - if (model::material_map.find(col_id) != model::material_map.end()) { - col_id = model::material_map[col_id]; - } - else { - std::stringstream err_msg; - err_msg << "Could not find material " << col_id - << " specified in the mask in plot " << id_; - fatal_error(err_msg); - } - } - } - - // Alter colors based on mask information - for (int j = 0; j < colors_.size(); j++) { - if (std::find(iarray.begin(), iarray.end(), j) == iarray.end()) { - if (check_for_node(mask_node, "background")) { - std::vector bg_rgb = get_node_array(mask_node, "background"); - colors_[j] = bg_rgb; - } else { - colors_[j] = WHITE; - } - } - } - - } else { - std::stringstream err_msg; - err_msg << "Mutliple masks specified in plot " << id_; - fatal_error(err_msg); - } - } -} - -void Plot::set_overlap_color(pugi::xml_node plot_node) { - color_overlaps_ = false; - if (check_for_node(plot_node, "show_overlaps")) { - color_overlaps_ = get_node_value_bool(plot_node, "show_overlaps"); - // check for custom overlap color - if (check_for_node(plot_node, "overlap_color")) { - if (!color_overlaps_) { - std::stringstream wrn_msg; - wrn_msg << "Overlap color specified in plot " << id_ - << " but overlaps won't be shown."; - warning(wrn_msg); - } - std::vector olap_clr = get_node_array(plot_node, "overlap_color"); - if (olap_clr.size() == 3) { - overlap_color_ = olap_clr; - } else { - std::stringstream err_msg; - err_msg << "Bad overlap RGB in plot " << id_; - fatal_error(err_msg); - } - } - } - - // make sure we allocate the vector for counting overlap checks if - // they're going to be plotted - if (color_overlaps_ && settings::run_mode == RUN_MODE_PLOTTING) { - settings::check_overlaps = true; - model::overlap_check_count.resize(model::cells.size(), 0); - } -} - -Plot::Plot(pugi::xml_node plot_node) - : index_meshlines_mesh_{-1}, overlap_color_{RED} -{ - set_id(plot_node); - set_type(plot_node); - set_output_path(plot_node); - set_bg_color(plot_node); - set_basis(plot_node); - set_origin(plot_node); - set_width(plot_node); - set_universe(plot_node); - set_default_colors(plot_node); - set_user_colors(plot_node); - set_meshlines(plot_node); - set_mask(plot_node); - set_overlap_color(plot_node); -} // End Plot constructor - -//============================================================================== -// OUTPUT_PPM writes out a previously generated image to a PPM file -//============================================================================== - -void output_ppm(Plot pl, const ImageData& data) -{ - // Open PPM file for writing - std::string fname = pl.path_plot_; - fname = strtrim(fname); - std::ofstream of; - - of.open(fname); - - // Write header - of << "P6" << "\n"; - of << pl.pixels_[0] << " " << pl.pixels_[1] << "\n"; - of << "255" << "\n"; - of.close(); - - of.open(fname, std::ios::binary | std::ios::app); - // Write color for each pixel - for (int y = 0; y < pl.pixels_[1]; y++) { - for (int x = 0; x < pl.pixels_[0]; x++) { - RGBColor rgb = data(x,y); - of << rgb.red << rgb.green << rgb.blue; - } - } - - // Close file - // THIS IS HERE TO MATCH FORTRAN VERSION, NOT TECHNICALLY NECESSARY - of << "\n"; - of.close(); -} - -//============================================================================== -// DRAW_MESH_LINES draws mesh line boundaries on an image -//============================================================================== - -void draw_mesh_lines(Plot pl, ImageData& data) -{ - RGBColor rgb; - rgb = pl.meshlines_color_; - - int ax1, ax2; - switch(pl.basis_) { - case PlotBasis::xy : - ax1 = 0; - ax2 = 1; - break; - case PlotBasis::xz : - ax1 = 0; - ax2 = 2; - break; - case PlotBasis::yz : - ax1 = 1; - ax2 = 2; - break; - default: - UNREACHABLE(); - } - - Position ll_plot {pl.origin_}; - Position ur_plot {pl.origin_}; - - ll_plot[ax1] -= pl.width_[0] / 2.; - ll_plot[ax2] -= pl.width_[1] / 2.; - ur_plot[ax1] += pl.width_[0] / 2.; - ur_plot[ax2] += pl.width_[1] / 2.; - - Position width = ur_plot - ll_plot; - - // Find the (axis-aligned) lines of the mesh that intersect this plot. - auto axis_lines = model::meshes[pl.index_meshlines_mesh_] - ->plot(ll_plot, ur_plot); - - // Find the bounds along the second axis (accounting for low-D meshes). - int ax2_min, ax2_max; - if (axis_lines.second.size() > 0) { - double frac = (axis_lines.second.back() - ll_plot[ax2]) / width[ax2]; - ax2_min = (1.0 - frac) * pl.pixels_[1]; - if (ax2_min < 0) ax2_min = 0; - frac = (axis_lines.second.front() - ll_plot[ax2]) / width[ax2]; - ax2_max = (1.0 - frac) * pl.pixels_[1]; - if (ax2_max > pl.pixels_[1]) ax2_max = pl.pixels_[1]; - } else { - ax2_min = 0; - ax2_max = pl.pixels_[1]; - } - - // Iterate across the first axis and draw lines. - for (auto ax1_val : axis_lines.first) { - double frac = (ax1_val - ll_plot[ax1]) / width[ax1]; - int ax1_ind = frac * pl.pixels_[0]; - for (int ax2_ind = ax2_min; ax2_ind < ax2_max; ++ax2_ind) { - for (int plus = 0; plus <= pl.meshlines_width_; plus++) { - if (ax1_ind+plus >= 0 && ax1_ind+plus < pl.pixels_[0]) - data(ax1_ind+plus, ax2_ind) = rgb; - if (ax1_ind-plus >= 0 && ax1_ind-plus < pl.pixels_[0]) - data(ax1_ind-plus, ax2_ind) = rgb; - } - } - } - - // Find the bounds along the first axis. - int ax1_min, ax1_max; - if (axis_lines.first.size() > 0) { - double frac = (axis_lines.first.front() - ll_plot[ax1]) / width[ax1]; - ax1_min = frac * pl.pixels_[0]; - if (ax1_min < 0) ax1_min = 0; - frac = (axis_lines.first.back() - ll_plot[ax1]) / width[ax1]; - ax1_max = frac * pl.pixels_[0]; - if (ax1_max > pl.pixels_[0]) ax1_max = pl.pixels_[0]; - } else { - ax1_min = 0; - ax1_max = pl.pixels_[0]; - } - - // Iterate across the second axis and draw lines. - for (auto ax2_val : axis_lines.second) { - double frac = (ax2_val - ll_plot[ax2]) / width[ax2]; - int ax2_ind = (1.0 - frac) * pl.pixels_[1]; - for (int ax1_ind = ax1_min; ax1_ind < ax1_max; ++ax1_ind) { - for (int plus = 0; plus <= pl.meshlines_width_; plus++) { - if (ax2_ind+plus >= 0 && ax2_ind+plus < pl.pixels_[1]) - data(ax1_ind, ax2_ind+plus) = rgb; - if (ax2_ind-plus >= 0 && ax2_ind-plus < pl.pixels_[1]) - data(ax1_ind, ax2_ind-plus) = rgb; - } - } - } -} - -//============================================================================== -// CREATE_VOXEL outputs a binary file that can be input into silomesh for 3D -// geometry visualization. It works the same way as create_ppm by dragging a -// particle across the geometry for the specified number of voxels. The first 3 -// int's in the binary are the number of x, y, and z voxels. The next 3 -// double's are the widths of the voxels in the x, y, and z directions. The -// next 3 double's are the x, y, and z coordinates of the lower left -// point. Finally the binary is filled with entries of four int's each. Each -// 'row' in the binary contains four int's: 3 for x,y,z position and 1 for -// cell or material id. For 1 million voxels this produces a file of -// approximately 15MB. -// ============================================================================= - -void create_voxel(Plot pl) -{ - // compute voxel widths in each direction - std::array vox; - vox[0] = pl.width_[0]/(double)pl.pixels_[0]; - vox[1] = pl.width_[1]/(double)pl.pixels_[1]; - vox[2] = pl.width_[2]/(double)pl.pixels_[2]; - - // initial particle position - Position ll = pl.origin_ - pl.width_ / 2.; - - // Open binary plot file for writing - std::ofstream of; - std::string fname = std::string(pl.path_plot_); - fname = strtrim(fname); - hid_t file_id = file_open(fname, 'w'); - - // write header info - write_attribute(file_id, "filetype", "voxel"); - write_attribute(file_id, "version", VERSION_VOXEL); - write_attribute(file_id, "openmc_version", VERSION); - -#ifdef GIT_SHA1 - write_attribute(file_id, "git_sha1", GIT_SHA1); -#endif - - // Write current date and time - write_attribute(file_id, "date_and_time", time_stamp().c_str()); - std::array pixels; - std::copy(pl.pixels_.begin(), pl.pixels_.end(), pixels.begin()); - write_attribute(file_id, "num_voxels", pixels); - write_attribute(file_id, "voxel_width", vox); - write_attribute(file_id, "lower_left", ll); - - // Create dataset for voxel data -- note that the dimensions are reversed - // since we want the order in the file to be z, y, x - hsize_t dims[3]; - dims[0] = pl.pixels_[2]; - dims[1] = pl.pixels_[1]; - dims[2] = pl.pixels_[0]; - hid_t dspace, dset, memspace; - voxel_init(file_id, &(dims[0]), &dspace, &dset, &memspace); - - PlotBase pltbase; - pltbase.width_ = pl.width_; - pltbase.origin_ = pl.origin_; - pltbase.basis_ = PlotBasis::xy; - pltbase.pixels_ = pl.pixels_; - pltbase.level_ = -1; // all universes for voxel files - pltbase.color_overlaps_ = pl.color_overlaps_; - - ProgressBar pb; - for (int z = 0; z < pl.pixels_[2]; z++) { - // update progress bar - pb.set_value(100.*(double)z/(double)(pl.pixels_[2]-1)); - - // update z coordinate - pltbase.origin_.z = ll.z + z * vox[2]; - - // generate ids using plotbase - IdData ids = pltbase.get_map(); - - // select only cell ID data and flip the y-axis - xt::xtensor data1 = xt::flip(xt::view(ids.data_, xt::all(), xt::all(), 0), 0); - - // Write to HDF5 dataset - voxel_write_slice(z, dspace, dset, memspace, &(data1(0,0))); - } - - voxel_finalize(dspace, dset, memspace); - file_close(file_id); -} - -void -voxel_init(hid_t file_id, const hsize_t* dims, - hid_t* dspace, hid_t* dset, hid_t* memspace) -{ - // Create dataspace/dataset for voxel data - *dspace = H5Screate_simple(3, dims, nullptr); - *dset = H5Dcreate(file_id, "data", H5T_NATIVE_INT, *dspace, H5P_DEFAULT, - H5P_DEFAULT, H5P_DEFAULT); - - // Create dataspace for a slice of the voxel - hsize_t dims_slice[2] {dims[1], dims[2]}; - *memspace = H5Screate_simple(2, dims_slice, nullptr); - - // Select hyperslab in dataspace - hsize_t start[3] {0, 0, 0}; - hsize_t count[3] {1, dims[1], dims[2]}; - H5Sselect_hyperslab(*dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); -} - - -void -voxel_write_slice(int x, hid_t dspace, hid_t dset, hid_t memspace, void* buf) -{ - hssize_t offset[3] {x, 0, 0}; - H5Soffset_simple(dspace, offset); - H5Dwrite(dset, H5T_NATIVE_INT, memspace, dspace, H5P_DEFAULT, buf); -} - - -void -voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace) -{ - H5Dclose(dset); - H5Sclose(dspace); - H5Sclose(memspace); -} - -RGBColor random_color() { - return {int(prn()*255), int(prn()*255), int(prn()*255)}; -} - -extern "C" int openmc_id_map(const void* plot, int32_t* data_out) -{ - - auto plt = reinterpret_cast(plot); - if (!plt) { - set_errmsg("Invalid slice pointer passed to openmc_id_map"); - return OPENMC_E_INVALID_ARGUMENT; - } - - if (plt->color_overlaps_ && model::overlap_check_count.size() == 0) { - model::overlap_check_count.resize(model::cells.size()); - } - - auto ids = plt->get_map(); - - // write id data to array - std::copy(ids.data_.begin(), ids.data_.end(), data_out); - - return 0; -} - -extern "C" int openmc_property_map(const void* plot, double* data_out) { - - auto plt = reinterpret_cast(plot); - if (!plt) { - set_errmsg("Invalid slice pointer passed to openmc_id_map"); - return OPENMC_E_INVALID_ARGUMENT; - } - - if (plt->color_overlaps_ && model::overlap_check_count.size() == 0) { - model::overlap_check_count.resize(model::cells.size()); - } - - auto props = plt->get_map(); - - // write id data to array - std::copy(props.data_.begin(), props.data_.end(), data_out); - - return 0; -} - - -} // namespace openmc diff --git a/src/position.cpp b/src/position.cpp deleted file mode 100644 index 1215bfb12..000000000 --- a/src/position.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "openmc/position.h" - -namespace openmc { - -//============================================================================== -// Position implementation -//============================================================================== - -Position& -Position::operator+=(Position other) -{ - x += other.x; - y += other.y; - z += other.z; - return *this; -} - -Position& -Position::operator+=(double v) -{ - x += v; - y += v; - z += v; - return *this; -} - -Position& -Position::operator-=(Position other) -{ - x -= other.x; - y -= other.y; - z -= other.z; - return *this; -} - -Position& -Position::operator-=(double v) -{ - x -= v; - y -= v; - z -= v; - return *this; -} - -Position& -Position::operator*=(Position other) -{ - x *= other.x; - y *= other.y; - z *= other.z; - return *this; -} - -Position& -Position::operator*=(double v) -{ - x *= v; - y *= v; - z *= v; - return *this; -} - -Position& -Position::operator/=(Position other) -{ - x /= other.x; - y /= other.y; - z /= other.z; - return *this; -} - -Position& -Position::operator/=(double v) -{ - x /= v; - y /= v; - z /= v; - return *this; -} - -Position -Position::operator-() const -{ - return {-x, -y, -z}; -} - -Position -Position::rotate(const std::vector& rotation) const -{ - return { - x*rotation[3] + y*rotation[4] + z*rotation[5], - x*rotation[6] + y*rotation[7] + z*rotation[8], - x*rotation[9] + y*rotation[10] + z*rotation[11] - }; -} - -std::ostream& -operator<<(std::ostream& os, Position r) -{ - os << "(" << r.x << ", " << r.y << ", " << r.z << ")"; - return os; -} - -} // namespace openmc diff --git a/src/progress_bar.cpp b/src/progress_bar.cpp deleted file mode 100644 index ab77c72f9..000000000 --- a/src/progress_bar.cpp +++ /dev/null @@ -1,67 +0,0 @@ - -#include "openmc/progress_bar.h" - -#include -#include -#include - -#if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) -#include -#endif - -#define BAR_WIDTH 72 - -bool is_terminal() { -#ifdef _POSIX_VERSION - return isatty(STDOUT_FILENO) != 0; -#else - return false; -#endif -} - -ProgressBar::ProgressBar() { - // initialize bar - set_value(0.0); -} - -void -ProgressBar::set_value(double val) { - - if (!is_terminal()) return; - - // set the bar percentage - if (val >= 100.0) { - bar.append("100"); - } else if (val <= 0.0) { - bar.append(" 0"); - } else { - std::stringstream ss; - ss << std::setfill(' ') << std::setw(3) << (int)val; - bar.append(ss.str()); - } - - bar.append("% |"); - // remaining width of the bar - int remaining_width = BAR_WIDTH - bar.size() - 2; - - // set the bar width - if (val >= 100.0) { - bar.append(remaining_width, '='); - } else if (val < 0.0) { - bar.append(remaining_width, ' '); - } else { - int width = (int)((double)remaining_width*val/100); - bar.append(width, '='); - bar.append(1, '>'); - bar.append(remaining_width-width-1, ' '); - } - - bar.append("|+"); - - // write the bar - std::cout << '\r' << bar << std::flush; - if (val >= 100.0) { std::cout << "\n"; } - - // reset the bar value - bar = ""; -} diff --git a/src/random_lcg.cpp b/src/random_lcg.cpp deleted file mode 100644 index 5002b4279..000000000 --- a/src/random_lcg.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "openmc/random_lcg.h" - -#include - - -namespace openmc { - - -// Constants -extern "C" const int N_STREAMS {6}; -extern "C" const int STREAM_TRACKING {0}; -extern "C" const int STREAM_TALLIES {1}; -extern "C" const int STREAM_SOURCE {2}; -extern "C" const int STREAM_URR_PTABLE {3}; -extern "C" const int STREAM_VOLUME {4}; -extern "C" const int STREAM_PHOTON {5}; - -// Starting seed -int64_t seed {1}; - -// LCG parameters -constexpr uint64_t prn_mult {2806196910506780709LL}; // multiplication - // factor, g -constexpr uint64_t prn_add {1}; // additive factor, c -constexpr uint64_t prn_mod {0x8000000000000000}; // 2^63 -constexpr uint64_t prn_mask {0x7fffffffffffffff}; // 2^63 - 1 -constexpr uint64_t prn_stride {152917LL}; // stride between - // particles -constexpr double prn_norm {1.0 / prn_mod}; // 2^-63 - -// Current PRNG state -uint64_t prn_seed[N_STREAMS]; // current seed -int stream; // current RNG stream -#pragma omp threadprivate(prn_seed, stream) - - -//============================================================================== -// PRN -//============================================================================== - -extern "C" double -prn() -{ - // This algorithm uses bit-masking to find the next integer(8) value to be - // used to calculate the random number. - prn_seed[stream] = (prn_mult*prn_seed[stream] + prn_add) & prn_mask; - - // Once the integer is calculated, we just need to divide by 2**m, - // represented here as multiplying by a pre-calculated factor - return prn_seed[stream] * prn_norm; -} - -//============================================================================== -// FUTURE_PRN -//============================================================================== - -extern "C" double -future_prn(int64_t n) -{ - return future_seed(static_cast(n), prn_seed[stream]) * prn_norm; -} - -//============================================================================== -// SET_PARTICLE_SEED -//============================================================================== - -extern "C" void -set_particle_seed(int64_t id) -{ - for (int i = 0; i < N_STREAMS; i++) { - prn_seed[i] = future_seed(static_cast(id) * prn_stride, seed + i); - } -} - -//============================================================================== -// ADVANCE_PRN_SEED -//============================================================================== - -extern "C" void -advance_prn_seed(int64_t n) -{ - prn_seed[stream] = future_seed(static_cast(n), prn_seed[stream]); -} - -//============================================================================== -// FUTURE_SEED -//============================================================================== - -uint64_t -future_seed(uint64_t n, uint64_t seed) -{ - // Make sure nskip is less than 2^M. - n &= prn_mask; - - // The algorithm here to determine the parameters used to skip ahead is - // described in F. Brown, "Random Number Generation with Arbitrary Stride," - // Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in - // O(log2(N)) operations instead of O(N). Basically, it computes parameters G - // and C which can then be used to find x_N = G*x_0 + C mod 2^M. - - // Initialize constants - uint64_t g {prn_mult}; - uint64_t c {prn_add}; - uint64_t g_new {1}; - uint64_t c_new {0}; - - while (n > 0) { - // Check if the least significant bit is 1. - if (n & 1) { - g_new *= g; - c_new = c_new * g + c; - } - c *= (g + 1); - g *= g; - - // Move bits right, dropping least significant bit. - n >>= 1; - } - - // With G and C, we can now find the new seed. - return (g_new * seed + c_new) & prn_mask; -} - -//============================================================================== -// PRN_SET_STREAM -//============================================================================== - -extern "C" void -prn_set_stream(int i) -{ - stream = i; // Shift by one to move from Fortran to C indexing. -} - -//============================================================================== -// API FUNCTIONS -//============================================================================== - -extern "C" int64_t openmc_get_seed() {return seed;} - -extern "C" void -openmc_set_seed(int64_t new_seed) -{ - seed = new_seed; - #pragma omp parallel - { - for (int i = 0; i < N_STREAMS; i++) { - prn_seed[i] = seed + i; - } - prn_set_stream(STREAM_TRACKING); - } -} - -} // namespace openmc diff --git a/src/reaction.cpp b/src/reaction.cpp deleted file mode 100644 index f7f1e87ac..000000000 --- a/src/reaction.cpp +++ /dev/null @@ -1,277 +0,0 @@ -#include "openmc/reaction.h" - -#include -#include // for move - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/endf.h" -#include "openmc/random_lcg.h" -#include "openmc/secondary_uncorrelated.h" - -namespace openmc { - -//============================================================================== -// Reaction implementation -//============================================================================== - -Reaction::Reaction(hid_t group, const std::vector& temperatures) -{ - read_attribute(group, "Q_value", q_value_); - read_attribute(group, "mt", mt_); - int tmp; - read_attribute(group, "center_of_mass", tmp); - scatter_in_cm_ = (tmp == 1); - - // Checks if redudant attribute exists before loading - // (for compatibiltiy with legacy .h5 libraries) - if (attribute_exists(group, "redundant")) { - read_attribute(group, "redundant", tmp); - redundant_ = (tmp == 1); - } else { - redundant_ = false; - } - - // Read cross section and threshold_idx data - for (auto t : temperatures) { - // Get group corresponding to temperature - std::string temp_str {std::to_string(t) + "K"}; - hid_t temp_group = open_group(group, temp_str.c_str()); - hid_t dset = open_dataset(temp_group, "xs"); - - // Get threshold index - TemperatureXS xs; - read_attribute(dset, "threshold_idx", xs.threshold); - - // Read cross section values - read_dataset(dset, xs.value); - close_dataset(dset); - close_group(temp_group); - - // create new entry in xs vector - xs_.push_back(std::move(xs)); - } - - // Read products - for (const auto& name : group_names(group)) { - if (name.rfind("product_", 0) == 0) { - hid_t pgroup = open_group(group, name.c_str()); - products_.emplace_back(pgroup); - close_group(pgroup); - } - } - - // <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<< - // Before the secondary distribution refactor, when the angle/energy - // distribution was uncorrelated, no angle was actually sampled. With - // the refactor, an angle is always sampled for an uncorrelated - // distribution even when no angle distribution exists in the ACE file - // (isotropic is assumed). To preserve the RNG stream, we explicitly - // mark fission reactions so that we avoid the angle sampling. - if (is_fission(mt_)) { - for (auto& p : products_) { - if (p.particle_ == Particle::Type::neutron) { - for (auto& d : p.distribution_) { - auto d_ = dynamic_cast(d.get()); - if (d_) d_->fission() = true; - } - } - } - } - // <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<< -} - -//============================================================================== -// Non-member functions -//============================================================================== - -std::string reaction_name(int mt) -{ - if (mt == SCORE_FLUX) { - return "flux"; - } else if (mt == SCORE_TOTAL) { - return "total"; - } else if (mt == SCORE_SCATTER) { - return "scatter"; - } else if (mt == SCORE_NU_SCATTER) { - return "nu-scatter"; - } else if (mt == SCORE_ABSORPTION) { - return "absorption"; - } else if (mt == SCORE_FISSION) { - return "fission"; - } else if (mt == SCORE_NU_FISSION) { - return "nu-fission"; - } else if (mt == SCORE_DECAY_RATE) { - return "decay-rate"; - } else if (mt == SCORE_DELAYED_NU_FISSION) { - return "delayed-nu-fission"; - } else if (mt == SCORE_PROMPT_NU_FISSION) { - return "prompt-nu-fission"; - } else if (mt == SCORE_KAPPA_FISSION) { - return "kappa-fission"; - } else if (mt == SCORE_CURRENT) { - return "current"; - } else if (mt == SCORE_EVENTS) { - return "events"; - } else if (mt == SCORE_INVERSE_VELOCITY) { - return "inverse-velocity"; - } else if (mt == SCORE_FISS_Q_PROMPT) { - return "fission-q-prompt"; - } else if (mt == SCORE_FISS_Q_RECOV) { - return "fission-q-recoverable"; - - // Normal ENDF-based reactions - } else if (mt == TOTAL_XS) { - return "(n,total)"; - } else if (mt == ELASTIC) { - return "(n,elastic)"; - } else if (mt == N_LEVEL) { - return "(n,level)"; - } else if (mt == N_2ND) { - return "(n,2nd)"; - } else if (mt == N_2N) { - return "(n,2n)"; - } else if (mt == N_3N) { - return "(n,3n)"; - } else if (mt == N_FISSION) { - return "(n,fission)"; - } else if (mt == N_F) { - return "(n,f)"; - } else if (mt == N_NF) { - return "(n,nf)"; - } else if (mt == N_2NF) { - return "(n,2nf)"; - } else if (mt == N_NA) { - return "(n,na)"; - } else if (mt == N_N3A) { - return "(n,n3a)"; - } else if (mt == N_2NA) { - return "(n,2na)"; - } else if (mt == N_3NA) { - return "(n,3na)"; - } else if (mt == N_NP) { - return "(n,np)"; - } else if (mt == N_N2A) { - return "(n,n2a)"; - } else if (mt == N_2N2A) { - return "(n,2n2a)"; - } else if (mt == N_ND) { - return "(n,nd)"; - } else if (mt == N_NT) { - return "(n,nt)"; - } else if (mt == N_N3HE) { - return "(n,nHe-3)"; - } else if (mt == N_ND2A) { - return "(n,nd2a)"; - } else if (mt == N_NT2A) { - return "(n,nt2a)"; - } else if (mt == N_4N) { - return "(n,4n)"; - } else if (mt == N_3NF) { - return "(n,3nf)"; - } else if (mt == N_2NP) { - return "(n,2np)"; - } else if (mt == N_3NP) { - return "(n,3np)"; - } else if (mt == N_N2P) { - return "(n,n2p)"; - } else if (mt == N_NPA) { - return "(n,npa)"; - } else if (N_N1 <= mt && mt <= N_N40) { - return "(n,n" + std::to_string(mt-50) + ")"; - } else if (mt == N_NC) { - return "(n,nc)"; - } else if (mt == N_DISAPPEAR) { - return "(n,disappear)"; - } else if (mt == N_GAMMA) { - return "(n,gamma)"; - } else if (mt == N_P) { - return "(n,p)"; - } else if (mt == N_D) { - return "(n,d)"; - } else if (mt == N_T) { - return "(n,t)"; - } else if (mt == N_3HE) { - return "(n,3He)"; - } else if (mt == N_A) { - return "(n,a)"; - } else if (mt == N_2A) { - return "(n,2a)"; - } else if (mt == N_3A) { - return "(n,3a)"; - } else if (mt == N_2P) { - return "(n,2p)"; - } else if (mt == N_PA) { - return "(n,pa)"; - } else if (mt == N_T2A) { - return "(n,t2a)"; - } else if (mt == N_D2A) { - return "(n,d2a)"; - } else if (mt == N_PD) { - return "(n,pd)"; - } else if (mt == N_PT) { - return "(n,pt)"; - } else if (mt == N_DA) { - return "(n,da)"; - } else if (mt == 201) { - return "(n,Xn)"; - } else if (mt == 202) { - return "(n,Xgamma)"; - } else if (mt == N_XP) { - return "(n,Xp)"; - } else if (mt == N_XD) { - return "(n,Xd)"; - } else if (mt == N_XT) { - return "(n,Xt)"; - } else if (mt == N_X3HE) { - return "(n,X3He)"; - } else if (mt == N_XA) { - return "(n,Xa)"; - } else if (mt == HEATING) { - return "heating"; - } else if (mt == DAMAGE_ENERGY) { - return "damage-energy"; - } else if (mt == COHERENT) { - return "coherent scatter"; - } else if (mt == INCOHERENT) { - return "incoherent scatter"; - } else if (mt == PAIR_PROD_ELEC) { - return "pair production, electron"; - } else if (mt == PAIR_PROD) { - return "pair production"; - } else if (mt == PAIR_PROD_NUC) { - return "pair production, nuclear"; - } else if (mt == PHOTOELECTRIC) { - return "photoelectric"; - } else if (534 <= mt && mt <= 572) { - std::stringstream name; - name << "photoelectric, " << SUBSHELLS[mt - 534] << " subshell"; - return name.str(); - } else if (600 <= mt && mt <= 648) { - return "(n,p" + std::to_string(mt-600) + ")"; - } else if (mt == 649) { - return "(n,pc)"; - } else if (650 <= mt && mt <= 698) { - return "(n,d" + std::to_string(mt-650) + ")"; - } else if (mt == 699) { - return "(n,dc)"; - } else if (700 <= mt && mt <= 748) { - return "(n,t" + std::to_string(mt-700) + ")"; - } else if (mt == 749) { - return "(n,tc)"; - } else if (750 <= mt && mt <= 798) { - return "(n,3He" + std::to_string(mt-750) + ")"; - } else if (mt == 799) { - return "(n,3Hec)"; - } else if (800 <= mt && mt <= 848) { - return "(n,a" + std::to_string(mt-800) + ")"; - } else if (mt == 849) { - return "(n,ac)"; - } else if (mt == HEATING_LOCAL) { - return "heating-local"; - } else { - return "MT=" + std::to_string(mt); - } -} - -} // namespace openmc diff --git a/src/reaction_product.cpp b/src/reaction_product.cpp deleted file mode 100644 index 34680a773..000000000 --- a/src/reaction_product.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "openmc/reaction_product.h" - -#include // for unique_ptr -#include // for string - -#include "openmc/endf.h" -#include "openmc/hdf5_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/secondary_correlated.h" -#include "openmc/secondary_kalbach.h" -#include "openmc/secondary_nbody.h" -#include "openmc/secondary_uncorrelated.h" - -namespace openmc { - -//============================================================================== -// ReactionProduct implementation -//============================================================================== - -ReactionProduct::ReactionProduct(hid_t group) -{ - // Read particle type - std::string temp; - read_attribute(group, "particle", temp); - if (temp == "neutron") { - particle_ = Particle::Type::neutron; - } else if (temp == "photon") { - particle_ = Particle::Type::photon; - } - - // Read emission mode and decay rate - read_attribute(group, "emission_mode", temp); - if (temp == "prompt") { - emission_mode_ = EmissionMode::prompt; - } else if (temp == "delayed") { - emission_mode_ = EmissionMode::delayed; - } else if (temp == "total") { - emission_mode_ = EmissionMode::total; - } - - // Read decay rate for delayed emission - if (emission_mode_ == EmissionMode::delayed) - read_attribute(group, "decay_rate", decay_rate_); - - // Read secondary particle yield - yield_ = read_function(group, "yield"); - - int n; - read_attribute(group, "n_distribution", n); - - for (int i = 0; i < n; ++i) { - std::string s {"distribution_"}; - s.append(std::to_string(i)); - hid_t dgroup = open_group(group, s.c_str()); - - // Read applicability - if (n > 1) { - hid_t app = open_dataset(dgroup, "applicability"); - applicability_.emplace_back(app); - close_dataset(app); - } - - // Determine distribution type and read data - read_attribute(dgroup, "type", temp); - if (temp == "uncorrelated") { - distribution_.push_back(std::make_unique(dgroup)); - } else if (temp == "correlated") { - distribution_.push_back(std::make_unique(dgroup)); - } else if (temp == "nbody") { - distribution_.push_back(std::make_unique(dgroup)); - } else if (temp == "kalbach-mann") { - distribution_.push_back(std::make_unique(dgroup)); - } - - close_group(dgroup); - } -} - -void ReactionProduct::sample(double E_in, double& E_out, double& mu) const -{ - auto n = applicability_.size(); - if (n > 1) { - double prob = 0.0; - double c = prn(); - for (int i = 0; i < n; ++i) { - // Determine probability that i-th energy distribution is sampled - prob += applicability_[i](E_in); - - // If i-th distribution is sampled, sample energy from the distribution - if (c <= prob) { - distribution_[i]->sample(E_in, E_out, mu); - break; - } - } - } else { - // If only one distribution is present, go ahead and sample it - distribution_[0]->sample(E_in, E_out, mu); - } -} - -} diff --git a/src/relaxng/cross_sections.rnc b/src/relaxng/cross_sections.rnc deleted file mode 100644 index 7fbc610a2..000000000 --- a/src/relaxng/cross_sections.rnc +++ /dev/null @@ -1,12 +0,0 @@ -element cross_sections { - element library { - (element materials { xsd:string } | - attribute materials { xsd:string }) & - (element type { xsd:string } | - attribute type { xsd:string }) & - (element path { xsd:string } | - attribute path { xsd:string }) - }* & - - element directory { xsd:string { maxLength = "255" } }? -} \ No newline at end of file diff --git a/src/relaxng/cross_sections.rng b/src/relaxng/cross_sections.rng deleted file mode 100644 index 435f7fa84..000000000 --- a/src/relaxng/cross_sections.rng +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 255 - - - - - diff --git a/src/relaxng/geometry.rnc b/src/relaxng/geometry.rnc deleted file mode 100644 index e3c88c445..000000000 --- a/src/relaxng/geometry.rnc +++ /dev/null @@ -1,55 +0,0 @@ -element geometry { - element cell { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element universe { xsd:int } | attribute universe { xsd:int })? & - ( - (element fill { xsd:int } | attribute fill { xsd:int }) | - (element material { list { ( xsd:int | "void" )+ } } | - attribute material { list { ( xsd:int | "void" )+ } }) - ) & - (element temperature { list { xsd:double+ } } | - attribute temperature { list { xsd:double+ } } )? & - (element region { xsd:string } | attribute region { xsd:string })? & - (element rotation { list { xsd:double+ } } | attribute rotation { list { xsd:double+ } })? & - (element translation { list { xsd:double+ } } | attribute translation { list { xsd:double+ } })? - }* - - & element surface { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element type { xsd:string { maxLength = "15" } } | - attribute type { xsd:string { maxLength = "15" } }) & - (element coeffs { list { xsd:double+ } } | attribute coeffs { list { xsd:double+ } }) & - (element boundary { ( "transmit" | "reflective" | "vacuum" | "periodic" ) } | - attribute boundary { ( "transmit" | "reflective" | "vacuum" | "periodic" ) })? & - (element periodic_surface_id { xsd:int } | attribute periodic_surface_id { xsd:int })? - }* - - & element lattice { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | attribute lower_left { list { xsd:double+ } }) & - (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & - (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outer { xsd:int } | attribute outer { xsd:int })? - }* - - & element hex_lattice { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element n_rings { xsd:int } | attribute n_rings { xsd:int }) & - (element n_axial { xsd:int } | attribute n_axial { xsd:int })? & - (element center { list { xsd:double+ } } | attribute center { list { xsd:double+ } }) & - (element pitch { list { xsd:double+ } } | attribute pitch { list { xsd:double+ } }) & - (element orientation { ( "x" | "y" ) } | attribute orientation { ( "x" | "y" ) })? & - (element universes { list { xsd:int+ } } | attribute universes { list { xsd:int+ } }) & - (element outer { xsd:int } | attribute outer { xsd:int })? - }* -} diff --git a/src/relaxng/geometry.rng b/src/relaxng/geometry.rng deleted file mode 100644 index 56bf38580..000000000 --- a/src/relaxng/geometry.rng +++ /dev/null @@ -1,447 +0,0 @@ - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void - - - - - - - - - - void - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - 15 - - - - - 15 - - - - - - - - - - - - - - - - - - - - - - - - transmit - reflective - vacuum - periodic - - - - - transmit - reflective - vacuum - periodic - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x - y - - - - - x - y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/materials.rnc b/src/relaxng/materials.rnc deleted file mode 100644 index c82ecfeaa..000000000 --- a/src/relaxng/materials.rnc +++ /dev/null @@ -1,41 +0,0 @@ -element materials { - element material { - (element id { xsd:int } | attribute id { xsd:int }) & - - (element name { xsd:string } | attribute name { xsd:string })? & - - (element depletable { xsd:boolean } | attribute depletable { xsd:boolean })? & - - (element volume { xsd:double } | attribute volume { xsd:double })? & - - (element temperature { xsd:double } | attribute temperature { xsd:double })? & - - element density { - (element value { xsd:double } | attribute value { xsd:double })? & - (element units { xsd:string { maxLength = "10" } } | - attribute units { xsd:string { maxLength = "10" } }) - } & - - element nuclide { - (element name { xsd:string } | attribute name { xsd:string }) & - ( - (element ao { xsd:double } | attribute ao { xsd:double }) | - (element wo { xsd:double } | attribute wo { xsd:double }) - ) - }* & - - element isotropic { xsd:string }? & - - element macroscopic { - (element name { xsd:string } | - attribute name { xsd:string }) - }* & - - element sab { - (element name { xsd:string } | attribute name { xsd:string }) & - (element fraction { xsd:double } | attribute fraction { xsd:double })? - }* - }+ & - - element cross_sections { xsd:string { maxLength = "255" } }? -} diff --git a/src/relaxng/materials.rng b/src/relaxng/materials.rng deleted file mode 100644 index e99fb7adf..000000000 --- a/src/relaxng/materials.rng +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 - - - - - 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 255 - - - - - diff --git a/src/relaxng/mg_cross_sections.rnc b/src/relaxng/mg_cross_sections.rnc deleted file mode 100644 index b2aaec4d4..000000000 --- a/src/relaxng/mg_cross_sections.rnc +++ /dev/null @@ -1,61 +0,0 @@ -element cross_sections { - - element groups { xsd:int } & - - element group_structure { list { xsd:double+ } } & - - element inverse_velocities { list { xsd:double+ } }? & - - element xsdata { - (element name { xsd:string { maxLength = "15" } } | - attribute name { xsd:string { maxLength = "15" } }) & - (element alias { xsd:string { maxLength = "15" } } | - attribute alias { xsd:string { maxLength = "15" } })? & - (element kT { xsd:double } | attribute kT { xsd:double })? & - (element fissionable { ( "true" | "false" ) } | - attribute fissionable { ( "true" | "false" ) }) & - (element representation { ( "isotropic" | "angle" ) } | - attribute representation { ( "isotropic" | "angle" ) })? & - (element num_azimuthal { xsd:positiveInteger } | - attribute num_azimuthal { xsd:positiveInteger })? & - (element num_polar { xsd:positiveInteger } | - attribute num_polar { xsd:positiveInteger })? & - (element scatt_type { ( "legendre" | "histogram" | "tabular" ) } | - attribute scatt_type { ( "legendre" | "histogram" | "tabular" ) })? & - (element order { xsd:positiveInteger } | - attribute order { xsd:positiveInteger }) & - element tabular_legendre { - (element enable { ( "true" | "false" ) } | - attribute enable { ( "true" | "false" ) })? & - (element num_points { xsd:positiveInteger } | - attribute num_points { xsd:positiveInteger })? - }? & - - (element total { list { xsd:double+ } } | - attribute total { list { xsd:double+ } })? & - - (element absorption { list { xsd:double+ } } | - attribute absorption { list { xsd:double+ } }) & - - (element scatter { list { xsd:double+ } } | - attribute scatter { list { xsd:double+ } }) & - - (element fission { list { xsd:double+ } } | - attribute fission { list { xsd:double+ } })? & - - (element fission { list { xsd:double+ } } | - attribute fission { list { xsd:double+ } })? & - - (element k_fission { list { xsd:double+ } } | - attribute k_fission { list { xsd:double+ } })? & - - (element chi { list { xsd:double+ } } | - attribute chi { list { xsd:double+ } })? & - - (element nu_fission { list { xsd:double+ } } | - attribute nu_fission { list { xsd:double+ } })? - - }* - - -} \ No newline at end of file diff --git a/src/relaxng/mg_cross_sections.rng b/src/relaxng/mg_cross_sections.rng deleted file mode 100644 index b293cddbe..000000000 --- a/src/relaxng/mg_cross_sections.rng +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 - - - - - 15 - - - - - - - - 15 - - - - - 15 - - - - - - - - - - - - - - - - - - true - false - - - - - true - false - - - - - - - - isotropic - angle - - - - - isotropic - angle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - legendre - histogram - tabular - - - - - legendre - histogram - tabular - - - - - - - - - - - - - - - - - - - - true - false - - - - - true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/plots.rnc b/src/relaxng/plots.rnc deleted file mode 100644 index e53cc15f7..000000000 --- a/src/relaxng/plots.rnc +++ /dev/null @@ -1,41 +0,0 @@ -element plots { - element plot { - (element id { xsd:int } | attribute id { xsd:int })? & - (element filename { xsd:string { maxLength = "50" } } | - attribute filename { xsd:string { maxLength = "50" } })? & - (element type { "slice" | "voxel" } | - attribute type { "slice" | "voxel" })? & - (element color_by { ( "cell" | "material" ) } | - attribute color_by { ( "cell" | "material" ) })? & - (element level { xsd:int } | attribute level { xsd:int })? & - (element origin { list { xsd:double+ } } | - attribute origin { list { xsd:double+ } })? & - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } })? & - (element basis { ( "xy" | "yz" | "xz" ) } | - attribute basis { ( "xy" | "yz" | "xz" ) })? & - (element pixels { list { xsd:int+ } } | - attribute pixels { list { xsd:int+ } })? & - (element background { list { xsd:int+ } } | - attribute background { list { xsd:int+ } })? & - element color { - (element id { xsd:int } | attribute id { xsd:int }) & - (element rgb { list { xsd:int+ } } | - attribute rgb { list { xsd:int+ } }) - }* & - element mask { - (element components { list { xsd:int+ } } | - attribute components { list { xsd:int+ } }) & - (element background { list { xsd:int+ } } | - attribute background { list { xsd:int+ } }) - }* & - element meshlines { - (element meshtype { ( "tally" | "entropy" | "ufs" | "cmfd" ) } | - attribute meshtype { ( "tally" | "entropy" | "ufs" | "cmfd" ) }) & - (element id { xsd:int } | attribute id { xsd:int })? & - (element linewidth { xsd:int } | attribute linewidth { xsd:int }) & - (element color { list { xsd:int+ } } | - attribute color { list { xsd:int+ } })? - }* - }* -} diff --git a/src/relaxng/plots.rng b/src/relaxng/plots.rng deleted file mode 100644 index 55d69008e..000000000 --- a/src/relaxng/plots.rng +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - - - - - - - - - - 50 - - - - - 50 - - - - - - - - - slice - voxel - - - - - slice - voxel - - - - - - - - - cell - material - - - - - cell - material - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xy - yz - xz - - - - - xy - yz - xz - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tally - entropy - ufs - cmfd - - - - - tally - entropy - ufs - cmfd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/readme.rst b/src/relaxng/readme.rst deleted file mode 100644 index 9660e3f8c..000000000 --- a/src/relaxng/readme.rst +++ /dev/null @@ -1,19 +0,0 @@ -===================== -Editing RelaxNG files -===================== - -All direct edits to RelaxNG files should be in the .rnc files. The program -TRANG_ should be used to generate a correcsponding .rng file. For Ubuntu, you -can install with: - -.. code-block:: bash - - sudo apt-get install trang - -To convert the .rnc file to .rng, use the following syntax: - -.. code-block:: bash - - trang {filename}.rnc {filename}.rng - -.. _TRANG: http://www.thaiopensource.com/relaxng/trang.html diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc deleted file mode 100644 index 731aa70a9..000000000 --- a/src/relaxng/settings.rnc +++ /dev/null @@ -1,172 +0,0 @@ -element settings { - element batches { xsd:positiveInteger }? & - - element confidence_intervals { xsd:boolean }? & - - element create_fission_neutrons { xsd:boolean }? & - - element cutoff { - (element weight { xsd:double } | attribute weight { xsd:double })? & - (element weight_avg { xsd:double } | attribute weight_avg { xsd:double })? - }? & - - element energy_grid { ( "nuclide" | "log" | "logarithm" | "logarithmic" | "material-union" | "union" ) }? & - - element energy_mode { ( "continuous-energy" | "ce" | "CE" | "multi-group" | "mg" | "MG" ) }? & - - element entropy_mesh { xsd:positiveInteger }? & - - element generations_per_batch { xsd:positiveInteger }? & - - element inactive { xsd:nonNegativeInteger }? & - - element keff_trigger { - (element type { xsd:string } | attribute type { xsd:string }) & - (element threshold { xsd:double} | attribute threshold { xsd:double }) - }? & - - element log_grid_bins { xsd:positiveInteger }? & - - element max_order { xsd:nonNegativeInteger }? & - - element mesh { - (element id { xsd:int } | attribute id { xsd:int }) & - (element type { ( "regular" ) } | - attribute type { ( "regular" ) })? & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - ( - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) | - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } }) - ) - }* & - - element no_reduce { xsd:boolean }? & - - element output { - (element summary { xsd:boolean } | attribute summary { xsd:boolean })? & - (element tallies { xsd:boolean } | attribute tallies { xsd:boolean })? & - (element path { xsd:string } | attribute path { xsd:string })? - }? & - - element particles { xsd:positiveInteger }? & - - element ptables { xsd:boolean }? & - - element dagmc { xsd:boolean }? & - - element run_mode { xsd:string }? & - - element seed { xsd:positiveInteger }? & - - element source { - grammar { - start = - (element particle { xsd:string } | attribute particle { xsd:string })? & - (element strength { xsd:double } | attribute strength { xsd:double })? & - (element file { xsd:string } | attribute file { xsd:string })? & - element space { - (element type { xsd:string } | attribute type { xsd:string }) & - (element parameters { list { xsd:double+ } } | - attribute parameters { list { xsd:double+ } })? & - element x { distribution }? & - element y { distribution }? & - element z { distribution }? - }? & - element angle { - (element type { xsd:string } | attribute type { xsd:string }) & - (element reference_uvw { list { xsd:double, xsd:double, xsd:double } } | - attribute reference_uvw { list { xsd:double, xsd:double, xsd:double } })? & - element mu { distribution }? & - element phi { distribution }? - }? & - element energy { distribution }? & - (element write_initial { xsd:boolean } | attribute write_initial { xsd:boolean })? - distribution = - (element type { xsd:string { maxLength = "16" } } | - attribute type { xsd:string { maxLength = "16" } }) & - (element interpolation { xsd:string } | - attribute interpolation { xsd:string })? & - (element parameters { list { xsd:double+ } } | - attribute parameters { list { xsd:double+ } })? - } - }* & - - element state_point { - ( - (element batches { list { xsd:positiveInteger+ } } | - attribute batches { list { xsd:positiveInteger+ } }) | - (element interval { xsd:positiveInteger } | - attribute interval { xsd:positiveInteger }) - ) - }? & - - element source_point { - ( - (element batches { list { xsd:positiveInteger+ } } | - attribute batches { list { xsd:positiveInteger+ } }) | - (element interval { xsd:positiveInteger } | - attribute interval { xsd:positiveInteger }) - )? & - (element separate { xsd:boolean } | - attribute separate { xsd:boolean })? & - (element write { xsd:boolean } | - attribute write { xsd:boolean })? & - (element overwrite_latest { xsd:boolean} | - attribute overwrite_latest {xsd:boolean})? - }? & - - element survival_biasing { xsd:boolean }? & - - element temperature_default { xsd:double }? & - - element temperature_method { xsd:string }? & - - element temperature_multipole { xsd:boolean }? & - - element temperature_range { list { xsd:double, xsd:double } }? & - - element temperature_tolerance { xsd:double }? & - - element threads { xsd:positiveInteger }? & - - element trace { list { xsd:positiveInteger+ } }? & - - element track { list { xsd:positiveInteger+ } }? & - - element trigger { - (element active { xsd:boolean } | attribute active { xsd:boolean }) & - (element max_batches { xsd:positiveInteger } | attribute max_batches { xsd:positiveInteger }) & - (element batch_interval { xsd:positiveInteger } | attribute batch_interval { xsd:positiveInteger })? - }? & - - element ufs_mesh { xsd:positiveInteger }? & - - element verbosity { xsd:positiveInteger }? & - - element volume_calc { - (element domain_type { xsd:string } | - attribute domain_type { xsd:string }) & - (element domain_ids { list { xsd:integer+ } } | - attribute domain_ids { list { xsd:integer+ } }) & - (element samples { xsd:positiveInteger } | - attribute samples { xsd:positiveInteger }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) - }* & - - element resonance_scattering { - (element enable { xsd:boolean } | attribute enable { xsd:boolean })? & - (element method { xsd:string } | attribute method { xsd:string })? & - (element energy_min { xsd:double } | attribute energy_min { xsd:double })? & - (element energy_max { xsd:double } | attribute energy_max { xsd:double })? & - (element nuclides { list { xsd:string+ } } | - attribute nuclides { list { xsd:string+ } })? - }? -} diff --git a/src/relaxng/settings.rng b/src/relaxng/settings.rng deleted file mode 100644 index 3ed15c3ed..000000000 --- a/src/relaxng/settings.rng +++ /dev/null @@ -1,787 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nuclide - log - logarithm - logarithmic - material-union - union - - - - - - - continuous-energy - ce - CE - multi-group - mg - MG - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - regular - - - regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 - - - - - 16 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc deleted file mode 100644 index ec511481f..000000000 --- a/src/relaxng/tallies.rnc +++ /dev/null @@ -1,96 +0,0 @@ -element tallies { - element mesh { - (element id { xsd:int } | attribute id { xsd:int }) & - ( - ( - (element type { ( "regular" ) } | - attribute type { ( "regular" ) }) & - (element dimension { list { xsd:positiveInteger+ } } | - attribute dimension { list { xsd:positiveInteger+ } }) & - (element lower_left { list { xsd:double+ } } | - attribute lower_left { list { xsd:double+ } }) & - ( - (element upper_right { list { xsd:double+ } } | - attribute upper_right { list { xsd:double+ } }) | - (element width { list { xsd:double+ } } | - attribute width { list { xsd:double+ } }) - ) - ) | ( - (element type { ( "rectilinear" ) } | - attribute type { ( "rectilinear" ) }) & - (element x_grid { list { xsd:double+ } } | - attribute x_grid { list { xsd:double+ } }) & - (element y_grid { list { xsd:double+ } } | - attribute y_grid { list { xsd:double+ } }) & - (element z_grid { list { xsd:double+ } } | - attribute z_grid { list { xsd:double+ } }) - ) - ) - }* & - - element derivative { - (element id { xsd:int } | attribute id { xsd:int }) & - (element material { xsd:int } | attribute material { xsd:int }) & - ( (element variable { ( "density") } - | attribute variable { ( "density" ) } ) | - ( - (element variable { ( "nuclide_density" ) } - | attribute variable { ( "nuclide_density" ) } ) - & - (element nuclide { xsd:string { maxLength = "12" } } - | attribute nuclide { xsd:string { maxLength = "12" } } ) - ) | - (element variable { ( "temperature") } - | attribute variable { ( "temperature" ) } ) - ) - }* & - - element filter { - (element id { xsd:int } | attribute id { xsd:int }) & - ( - ( (element type { ( "cell" | "cellfrom" | "cellborn" | "material" | - "universe" | "surface" | "distribcell" | "mesh" | "energy" | - "energyout" | "mu" | "polar" | "azimuthal" | "delayedgroup" | - "energyfunction" | "meshsurface") } | - attribute type { ( "cell" | "cellfrom" | "cellborn" | "material" | - "universe" | "surface" | "distribcell" | "mesh" | "energy" | - "energyout" | "mu" | "polar" | "azimuthal" | "delayedgroup" | - "energyfunction" | "meshsurface") }) & - (element bins { list { xsd:double+ } } | - attribute bins { list { xsd:double+ } }) - ) | - ( - (element type { ("energyfunction") } | - attribute type { ("energyfunction") }) & - (element energy { list { xsd:double+ } } | - attribute energy { list { xsd:double+ } }) & - (element y { list { xsd:double+ } } | - attribute y { list { xsd:double+ } }) - ) - ) - }* & - - element tally { - (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element estimator { ( "analog" | "tracklength" | "collision" ) } | - attribute estimator { ( "analog" | "tracklength" | "collision" ) })? & - (element filters { list { xsd:int+ } } | - attribute filters { list { xsd:int+ } })? & - element nuclides { - list { xsd:string { maxLength = "12" }+ } - }? & - element scores { - list { xsd:string { maxLength = "20" }+ } - } & - element trigger { - (element type { xsd:string } | attribute type { xsd:string }) & - (element threshold { xsd:double} | attribute threshold { xsd:double }) & - (element scores { list { xsd:string { maxLength = "20" }+ } } | attribute scores { list { xsd:string { maxLength = "20"}+ } } )? - }* & - (element derivative { xsd:int } | attribute derivative { xsd:int } )? - }* & - - element assume_separate { xsd:boolean }? -} diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng deleted file mode 100644 index 98a48eeb8..000000000 --- a/src/relaxng/tallies.rng +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - - - - - - - - - - - - - - regular - - - regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rectilinear - - - rectilinear - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - density - - - density - - - - - - nuclide_density - - - nuclide_density - - - - - - 12 - - - - - 12 - - - - - - - temperature - - - temperature - - - - - - - - - - - - - - - - - - - - - - - cell - cellfrom - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - meshsurface - - - - - cell - cellfrom - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - meshsurface - - - - - - - - - - - - - - - - - - - - - - - - energyfunction - - - energyfunction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 - - - - - 52 - - - - - - - - - analog - tracklength - collision - - - - - analog - tracklength - collision - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - - - - - - - - - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 20 - - - - - - - - - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/scattdata.cpp b/src/scattdata.cpp deleted file mode 100644 index a8f63d0f6..000000000 --- a/src/scattdata.cpp +++ /dev/null @@ -1,916 +0,0 @@ -#include "openmc/scattdata.h" - -#include -#include -#include - -#include "xtensor/xbuilder.hpp" - -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" - -namespace openmc { - -//============================================================================== -// ScattData base-class methods -//============================================================================== - -void -ScattData::base_init(int order, const xt::xtensor& in_gmin, - const xt::xtensor& in_gmax, const double_2dvec& in_energy, - const double_2dvec& in_mult) -{ - size_t groups = in_energy.size(); - - gmin = in_gmin; - gmax = in_gmax; - energy.resize(groups); - mult.resize(groups); - dist.resize(groups); - - for (int gin = 0; gin < groups; gin++) { - // Store the inputted data - energy[gin] = in_energy[gin]; - mult[gin] = in_mult[gin]; - - // Make sure the energy is normalized - double norm = std::accumulate(energy[gin].begin(), energy[gin].end(), 0.); - - if (norm != 0.) { - for (auto& n : energy[gin]) n /= norm; - } - - // Initialize the distribution data - dist[gin].resize(in_gmax[gin] - in_gmin[gin] + 1); - for (auto& v : dist[gin]) { - v.resize(order); - } - } -} - -//============================================================================== - -void -ScattData::base_combine(size_t max_order, - const std::vector& those_scatts, const std::vector& scalars, - xt::xtensor& in_gmin, xt::xtensor& in_gmax, double_2dvec& sparse_mult, - double_3dvec& sparse_scatter) -{ - size_t groups = those_scatts[0] -> energy.size(); - - // Now allocate and zero our storage spaces - xt::xtensor this_matrix({groups, groups, max_order}, 0.); - xt::xtensor mult_numer({groups, groups}, 0.); - xt::xtensor mult_denom({groups, groups}, 0.); - - // Build the dense scattering and multiplicity matrices - // Get the multiplicity_matrix - // To combine from nuclidic data we need to use the final relationship - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / - // sum_i(N_i*(nuscatt_{i,g,g'} / mult_{i,g,g'})) - // Developed as follows: - // mult_{gg'} = nuScatt{g,g'} / Scatt{g,g'} - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / sum(N_i*scatt_{i,g,g'}) - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / - // sum_i(N_i*(nuscatt_{i,g,g'} / mult_{i,g,g'})) - // nuscatt_{i,g,g'} can be reconstructed from the energy and scattxs member - // variables - for (int i = 0; i < those_scatts.size(); i++) { - ScattData* that = those_scatts[i]; - - // Build the dense matrix for that object - xt::xtensor that_matrix = that->get_matrix(max_order); - - // Now add that to this for the scattering and multiplicity - for (int gin = 0; gin < groups; gin++) { - // Only spend time adding that's gmin to gmax data since the rest will - // be zeros - int i_gout = 0; - for (int gout = that->gmin(gin); gout <= that->gmax(gin); gout++) { - // Do the scattering matrix - for (int l = 0; l < max_order; l++) { - this_matrix(gin, gout, l) += scalars[i] * that_matrix(gin, gout, l); - } - - // Incorporate that's contribution to the multiplicity matrix data - double nuscatt = that->scattxs(gin) * that->energy[gin][i_gout]; - mult_numer(gin, gout) += scalars[i] * nuscatt; - if (that->mult[gin][i_gout] > 0.) { - mult_denom(gin, gout) += scalars[i] * nuscatt / that->mult[gin][i_gout]; - } else { - mult_denom(gin, gout) += scalars[i]; - } - i_gout++; - } - } - } - - // Combine mult_numer and mult_denom into the combined multiplicity matrix - xt::xtensor this_mult({groups, groups}, 1.); - this_mult = xt::nan_to_num(mult_numer / mult_denom); - - // We have the data, now we need to convert to a jagged array and then use - // the initialize function to store it on the object. - for (int gin = 0; gin < groups; gin++) { - // Find the minimum and maximum group boundaries - int gmin_; - for (gmin_ = 0; gmin_ < groups; gmin_++) { - bool non_zero = false; - for (int l = 0; l < this_matrix.shape()[2]; l++) { - if (this_matrix(gin, gmin_, l) != 0.) { - non_zero = true; - break; - } - } - if (non_zero) break; - } - int gmax_; - for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) { - bool non_zero = false; - for (int l = 0; l < this_matrix.shape()[2]; l++) { - if (this_matrix(gin, gmax_, l) != 0.) { - non_zero = true; - break; - } - } - if (non_zero) break; - } - - // treat the case of all values being 0 - if (gmin_ > gmax_) { - gmin_ = gin; - gmax_ = gin; - } - - // Store the group bounds - in_gmin[gin] = gmin_; - in_gmax[gin] = gmax_; - - // Store the data in the compressed format - sparse_scatter[gin].resize(gmax_ - gmin_ + 1); - sparse_mult[gin].resize(gmax_ - gmin_ + 1); - int i_gout = 0; - for (int gout = gmin_; gout <= gmax_; gout++) { - sparse_scatter[gin][i_gout].resize(this_matrix.shape()[2]); - for (int l = 0; l < this_matrix.shape()[2]; l++) { - sparse_scatter[gin][i_gout][l] = this_matrix(gin, gout, l); - } - sparse_mult[gin][i_gout] = this_mult(gin, gout); - i_gout++; - } - } -} - -//============================================================================== - -void -ScattData::sample_energy(int gin, int& gout, int& i_gout) -{ - // Sample the outgoing group - double xi = prn(); - - i_gout = 0; - gout = gmin[gin]; - double prob = energy[gin][i_gout]; - while((prob < xi) && (gout < gmax[gin])) { - gout++; - i_gout++; - prob += energy[gin][i_gout]; - } -} - -//============================================================================== - -double -ScattData::get_xs(int xstype, int gin, const int* gout, const double* mu) -{ - // Set the outgoing group offset index as needed - int i_gout = 0; - if (gout != nullptr) { - // short circuit the function if gout is from a zero portion of the - // scattering matrix - if ((*gout < gmin[gin]) || (*gout > gmax[gin])) { // > gmax? - return 0.; - } - i_gout = *gout - gmin[gin]; - } - - double val = scattxs[gin]; - switch(xstype) { - case MG_GET_XS_SCATTER: - if (gout != nullptr) val *= energy[gin][i_gout]; - break; - case MG_GET_XS_SCATTER_MULT: - if (gout != nullptr) { - val *= energy[gin][i_gout] / mult[gin][i_gout]; - } else { - val /= std::inner_product(mult[gin].begin(), mult[gin].end(), - energy[gin].begin(), 0.0); - } - break; - case MG_GET_XS_SCATTER_FMU_MULT: - if ((gout != nullptr) && (mu != nullptr)) { - val *= energy[gin][i_gout] * calc_f(gin, *gout, *mu); - } else { - // This is not an expected path (asking for f_mu without asking for a - // group or mu is not useful - fatal_error("Invalid call to get_xs"); - } - break; - case MG_GET_XS_SCATTER_FMU: - if ((gout != nullptr) && (mu != nullptr)) { - val *= energy[gin][i_gout] * calc_f(gin, *gout, *mu) / mult[gin][i_gout]; - } else { - // This is not an expected path (asking for f_mu without asking for a - // group or mu is not useful - fatal_error("Invalid call to get_xs"); - } - break; - } - return val; -} - -//============================================================================== -// ScattDataLegendre methods -//============================================================================== - -void -ScattDataLegendre::init(const xt::xtensor& in_gmin, - const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs) -{ - size_t groups = coeffs.size(); - size_t order = coeffs[0][0].size(); - - // make a copy of coeffs that we can use to both extract data and normalize - double_3dvec matrix = coeffs; - - // Get the scattering cross section value by summing the un-normalized P0 - // coefficient in the variable matrix over all outgoing groups. - scattxs = xt::zeros({groups}); - for (int gin = 0; gin < groups; gin++) { - int num_groups = in_gmax[gin] - in_gmin[gin] + 1; - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - scattxs[gin] += matrix[gin][i_gout][0]; - } - } - - // Build the energy transfer matrix from data in the variable matrix while - // also normalizing the variable matrix itself - // (forcing the CDF of f(mu=1) == 1) - double_2dvec in_energy; - in_energy.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = in_gmax[gin] - in_gmin[gin] + 1; - in_energy[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - double norm = matrix[gin][i_gout][0]; - in_energy[gin][i_gout] = norm; - if (norm != 0.) { - for (auto& n : matrix[gin][i_gout]) n /= norm; - } - } - } - - // Initialize the base class attributes - ScattData::base_init(order, in_gmin, in_gmax, in_energy, in_mult); - - // Set the distribution (sdata.dist) values and initialize max_val - max_val.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = gmax[gin] - gmin[gin] + 1; - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - dist[gin][i_gout] = matrix[gin][i_gout]; - } - max_val[gin].resize(num_groups); - for (auto& n : max_val[gin]) n = 0.; - } - - // Now update the maximum value - update_max_val(); -} - -//============================================================================== - -void -ScattDataLegendre::update_max_val() -{ - size_t groups = max_val.size(); - // Step through the polynomial with fixed number of points to identify the - // maximal value - int Nmu = 1001; - double dmu = 2. / (Nmu - 1); - for (int gin = 0; gin < groups; gin++) { - int num_groups = gmax[gin] - gmin[gin] + 1; - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - for (int imu = 0; imu < Nmu; imu++) { - double mu; - if (imu == 0) { - mu = -1.; - } else if (imu == (Nmu - 1)) { - mu = 1.; - } else { - mu = -1. + (imu - 1) * dmu; - } - - // Calculate probability - double f = evaluate_legendre(dist[gin][i_gout].size() - 1, - dist[gin][i_gout].data(), mu); - - // if this is a new maximum, store it - if (f > max_val[gin][i_gout]) max_val[gin][i_gout] = f; - } // end imu loop - - // Since we may not have caught the true max, add 10% margin - max_val[gin][i_gout] *= 1.1; - } - } -} - -//============================================================================== - -double -ScattDataLegendre::calc_f(int gin, int gout, double mu) -{ - double f; - if ((gout < gmin[gin]) || (gout > gmax[gin])) { - f = 0.; - } else { - int i_gout = gout - gmin[gin]; - f = evaluate_legendre(dist[gin][i_gout].size() - 1, - dist[gin][i_gout].data(), mu); - } - return f; -} - -//============================================================================== - -void -ScattDataLegendre::sample(int gin, int& gout, double& mu, double& wgt) -{ - // Sample the outgoing energy using the base-class method - int i_gout; - sample_energy(gin, gout, i_gout); - - // Now we can sample mu using the scattering kernel using rejection - // sampling from a rectangular bounding box - double M = max_val[gin][i_gout]; - int samples = 0; - - while(true) { - mu = 2. * prn() - 1.; - double f = calc_f(gin, gout, mu); - if (f > 0.) { - double u = prn() * M; - if (u <= f) break; - } - samples++; - if (samples > MAX_SAMPLE) { - fatal_error("Maximum number of Legendre expansion samples reached"); - } - }; - - // Update the weight to reflect neutron multiplicity - wgt *= mult[gin][i_gout]; -} - -//============================================================================== - -void -ScattDataLegendre::combine(const std::vector& those_scatts, - const std::vector& scalars) -{ - // Find the max order in the data set and make sure we can combine the sets - size_t max_order = 0; - for (int i = 0; i < those_scatts.size(); i++) { - // Lets also make sure these items are combineable - ScattDataLegendre* that = dynamic_cast(those_scatts[i]); - if (!that) { - fatal_error("Cannot combine the ScattData objects!"); - } - size_t that_order = that->get_order(); - if (that_order > max_order) max_order = that_order; - } - max_order++; // Add one since this is a Legendre - - size_t groups = those_scatts[0] -> energy.size(); - - xt::xtensor in_gmin({groups}, 0); - xt::xtensor in_gmax({groups}, 0); - double_3dvec sparse_scatter(groups); - double_2dvec sparse_mult(groups); - - // The rest of the steps do not depend on the type of angular representation - // so we use a base class method to sum up xs and create new energy and mult - // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); - - // Got everything we need, store it. - init(in_gmin, in_gmax, sparse_mult, sparse_scatter); -} - -//============================================================================== - -xt::xtensor -ScattDataLegendre::get_matrix(size_t max_order) -{ - // Get the sizes and initialize the data to 0 - size_t groups = energy.size(); - size_t order_dim = max_order + 1; - xt::xtensor matrix({groups, groups, order_dim}, 0.); - - for (int gin = 0; gin < groups; gin++) { - for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) { - int gout = i_gout + gmin[gin]; - for (int l = 0; l < order_dim; l++) { - matrix(gin, gout, l) = scattxs[gin] * energy[gin][i_gout] * - dist[gin][i_gout][l]; - } - } - } - return matrix; -} - -//============================================================================== -// ScattDataHistogram methods -//============================================================================== - -void -ScattDataHistogram::init(const xt::xtensor& in_gmin, - const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs) -{ - size_t groups = coeffs.size(); - size_t order = coeffs[0][0].size(); - - // make a copy of coeffs that we can use to both extract data and normalize - double_3dvec matrix = coeffs; - - // Get the scattering cross section value by summing the distribution - // over all the histogram bins in angle and outgoing energy groups - scattxs = xt::zeros({groups}); - for (int gin = 0; gin < groups; gin++) { - for (int i_gout = 0; i_gout < matrix[gin].size(); i_gout++) { - scattxs[gin] += std::accumulate(matrix[gin][i_gout].begin(), - matrix[gin][i_gout].end(), 0.); - } - } - - // Build the energy transfer matrix from data in the variable matrix - double_2dvec in_energy; - in_energy.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = in_gmax[gin] - in_gmin[gin] + 1; - in_energy[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - double norm = std::accumulate(matrix[gin][i_gout].begin(), - matrix[gin][i_gout].end(), 0.); - in_energy[gin][i_gout] = norm; - if (norm != 0.) { - for (auto& n : matrix[gin][i_gout]) n /= norm; - } - } - } - - // Initialize the base class attributes - ScattData::base_init(order, in_gmin, in_gmax, in_energy, in_mult); - - // Build the angular distribution mu values - mu = xt::linspace(-1., 1., order + 1); - dmu = 2. / order; - - // Calculate f(mu) and integrate it so we can avoid rejection sampling - fmu.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = gmax[gin] - gmin[gin] + 1; - fmu[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - fmu[gin][i_gout].resize(order); - // The variable matrix contains f(mu); so directly assign it - fmu[gin][i_gout] = matrix[gin][i_gout]; - - // Integrate the histogram - dist[gin][i_gout][0] = dmu * matrix[gin][i_gout][0]; - for (int imu = 1; imu < order; imu++) { - dist[gin][i_gout][imu] = dmu * matrix[gin][i_gout][imu] + - dist[gin][i_gout][imu - 1]; - } - - // Now re-normalize for integral to unity - double norm = dist[gin][i_gout][order - 1]; - if (norm > 0.) { - for (int imu = 0; imu < order; imu++) { - fmu[gin][i_gout][imu] /= norm; - dist[gin][i_gout][imu] /= norm; - } - } - } - } -} - -//============================================================================== - -double -ScattDataHistogram::calc_f(int gin, int gout, double mu) -{ - double f; - if ((gout < gmin[gin]) || (gout > gmax[gin])) { - f = 0.; - } else { - // Find mu bin - int i_gout = gout - gmin[gin]; - int imu; - if (mu == 1.) { - // use size -2 to have the index one before the end - imu = this->mu.shape()[0] - 2; - } else { - imu = std::floor((mu + 1.) / dmu + 1.) - 1; - } - - f = fmu[gin][i_gout][imu]; - } - return f; -} - -//============================================================================== - -void -ScattDataHistogram::sample(int gin, int& gout, double& mu, double& wgt) -{ - // Sample the outgoing energy using the base-class method - int i_gout; - sample_energy(gin, gout, i_gout); - - // Determine the outgoing cosine bin - double xi = prn(); - - int imu; - if (xi < dist[gin][i_gout][0]) { - imu = 0; - } else { - imu = std::upper_bound(dist[gin][i_gout].begin(), - dist[gin][i_gout].end(), xi) - - dist[gin][i_gout].begin(); - } - - // Randomly select mu within the imu bin - mu = prn() * dmu + this->mu[imu]; - - if (mu < -1.) { - mu = -1.; - } else if (mu > 1.) { - mu = 1.; - } - - // Update the weight to reflect neutron multiplicity - wgt *= mult[gin][i_gout]; -} - -//============================================================================== - -xt::xtensor -ScattDataHistogram::get_matrix(size_t max_order) -{ - // Get the sizes and initialize the data to 0 - size_t groups = energy.size(); - // We ignore the requested order for Histogram and Tabular representations - size_t order_dim = get_order(); - xt::xtensor matrix({groups, groups, order_dim}, 0); - - for (int gin = 0; gin < groups; gin++) { - for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) { - int gout = i_gout + gmin[gin]; - for (int l = 0; l < order_dim; l++) { - matrix(gin, gout, l) = scattxs[gin] * energy[gin][i_gout] * - fmu[gin][i_gout][l]; - } - } - } - return matrix; -} - -//============================================================================== - -void -ScattDataHistogram::combine(const std::vector& those_scatts, - const std::vector& scalars) -{ - // Find the max order in the data set and make sure we can combine the sets - size_t max_order = those_scatts[0]->get_order(); - for (int i = 0; i < those_scatts.size(); i++) { - // Lets also make sure these items are combineable - ScattDataHistogram* that = dynamic_cast(those_scatts[i]); - if (!that) { - fatal_error("Cannot combine the ScattData objects!"); - } - if (max_order != that->get_order()) { - fatal_error("Cannot combine the ScattData objects!"); - } - } - - size_t groups = those_scatts[0] -> energy.size(); - - xt::xtensor in_gmin({groups}, 0); - xt::xtensor in_gmax({groups}, 0); - double_3dvec sparse_scatter(groups); - double_2dvec sparse_mult(groups); - - // The rest of the steps do not depend on the type of angular representation - // so we use a base class method to sum up xs and create new energy and mult - // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); - - // Got everything we need, store it. - init(in_gmin, in_gmax, sparse_mult, sparse_scatter); -} - -//============================================================================== -// ScattDataTabular methods -//============================================================================== - -void -ScattDataTabular::init(const xt::xtensor& in_gmin, - const xt::xtensor& in_gmax, const double_2dvec& in_mult, - const double_3dvec& coeffs) -{ - size_t groups = coeffs.size(); - size_t order = coeffs[0][0].size(); - - // make a copy of coeffs that we can use to both extract data and normalize - double_3dvec matrix = coeffs; - - // Build the angular distribution mu values - mu = xt::linspace(-1., 1., order); - dmu = 2. / (order - 1); - - // Get the scattering cross section value by integrating the distribution - // over all mu points and then combining over all outgoing groups - scattxs = xt::zeros({groups}); - for (int gin = 0; gin < groups; gin++) { - for (int i_gout = 0; i_gout < matrix[gin].size(); i_gout++) { - for (int imu = 1; imu < order; imu++) { - scattxs[gin] += 0.5 * dmu * (matrix[gin][i_gout][imu - 1] + - matrix[gin][i_gout][imu]); - } - } - } - - // Build the energy transfer matrix from data in the variable matrix - double_2dvec in_energy(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = in_gmax[gin] - in_gmin[gin] + 1; - in_energy[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - double norm = 0.; - for (int imu = 1; imu < order; imu++) { - norm += 0.5 * dmu * (matrix[gin][i_gout][imu - 1] + - matrix[gin][i_gout][imu]); - } - in_energy[gin][i_gout] = norm; - } - } - - // Initialize the base class attributes - ScattData::base_init(order, in_gmin, in_gmax, in_energy, in_mult); - - // Calculate f(mu) and integrate it so we can avoid rejection sampling - fmu.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = gmax[gin] - gmin[gin] + 1; - fmu[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - fmu[gin][i_gout].resize(order); - // The variable matrix contains f(mu); so directly assign it - fmu[gin][i_gout] = matrix[gin][i_gout]; - - // Ensure positivity - for (auto& val : fmu[gin][i_gout]) { - if (val < 0.) val = 0.; - } - - // Now re-normalize for numerical integration issues and to take care of - // the above negative fix-up. Also accrue the CDF - double norm = 0.; - for (int imu = 1; imu < order; imu++) { - norm += 0.5 * dmu * (fmu[gin][i_gout][imu - 1] + - fmu[gin][i_gout][imu]); - // incorporate to the CDF - dist[gin][i_gout][imu] = norm; - } - - // now do the normalization - if (norm > 0.) { - for (int imu = 0; imu < order; imu++) { - fmu[gin][i_gout][imu] /= norm; - dist[gin][i_gout][imu] /= norm; - } - } - } - } -} - -//============================================================================== - -double -ScattDataTabular::calc_f(int gin, int gout, double mu) -{ - double f; - if ((gout < gmin[gin]) || (gout > gmax[gin])) { - f = 0.; - } else { - // Find mu bin - int i_gout = gout - gmin[gin]; - int imu; - if (mu == 1.) { - // use size -2 to have the index one before the end - imu = this->mu.shape()[0] - 2; - } else { - imu = std::floor((mu + 1.) / dmu + 1.) - 1; - } - - double r = (mu - this->mu[imu]) / (this->mu[imu + 1] - this->mu[imu]); - f = (1. - r) * fmu[gin][i_gout][imu] + r * fmu[gin][i_gout][imu + 1]; - } - return f; -} - -//============================================================================== - -void -ScattDataTabular::sample(int gin, int& gout, double& mu, double& wgt) -{ - // Sample the outgoing energy using the base-class method - int i_gout; - sample_energy(gin, gout, i_gout); - - // Determine the outgoing cosine bin - int NP = this->mu.shape()[0]; - double xi = prn(); - - double c_k = dist[gin][i_gout][0]; - int k; - for (k = 0; k < NP - 1; k++) { - double c_k1 = dist[gin][i_gout][k + 1]; - if (xi < c_k1) break; - c_k = c_k1; - } - - // Check to make sure k is <= NP - 1 - k = std::min(k, NP - 2); - - // Find the pdf values we want - double p0 = fmu[gin][i_gout][k]; - double mu0 = this -> mu[k]; - double p1 = fmu[gin][i_gout][k + 1]; - double mu1 = this -> mu[k + 1]; - - if (p0 == p1) { - mu = mu0 + (xi - c_k) / p0; - } else { - double frac = (p1 - p0) / (mu1 - mu0); - mu = mu0 + (std::sqrt(std::max(0., p0 * p0 + 2. * frac * (xi - c_k))) - - p0) / frac; - } - - if (mu < -1.) { - mu = -1.; - } else if (mu > 1.) { - mu = 1.; - } - - // Update the weight to reflect neutron multiplicity - wgt *= mult[gin][i_gout]; -} - -//============================================================================== - -xt::xtensor -ScattDataTabular::get_matrix(size_t max_order) -{ - // Get the sizes and initialize the data to 0 - size_t groups = energy.size(); - // We ignore the requested order for Histogram and Tabular representations - size_t order_dim = get_order(); - xt::xtensor matrix({groups, groups, order_dim}, 0.); - - for (int gin = 0; gin < groups; gin++) { - for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) { - int gout = i_gout + gmin[gin]; - for (int l = 0; l < order_dim; l++) { - matrix(gin, gout, l) = scattxs[gin] * energy[gin][i_gout] * - fmu[gin][i_gout][l]; - } - } - } - return matrix; -} - -//============================================================================== - -void -ScattDataTabular::combine(const std::vector& those_scatts, - const std::vector& scalars) -{ - // Find the max order in the data set and make sure we can combine the sets - size_t max_order = those_scatts[0]->get_order(); - for (int i = 0; i < those_scatts.size(); i++) { - // Lets also make sure these items are combineable - ScattDataTabular* that = dynamic_cast(those_scatts[i]); - if (!that) { - fatal_error("Cannot combine the ScattData objects!"); - } - if (max_order != that->get_order()) { - fatal_error("Cannot combine the ScattData objects!"); - } - } - - size_t groups = those_scatts[0] -> energy.size(); - - xt::xtensor in_gmin({groups}, 0); - xt::xtensor in_gmax({groups}, 0); - double_3dvec sparse_scatter(groups); - double_2dvec sparse_mult(groups); - - // The rest of the steps do not depend on the type of angular representation - // so we use a base class method to sum up xs and create new energy and mult - // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); - - // Got everything we need, store it. - init(in_gmin, in_gmax, sparse_mult, sparse_scatter); -} - -//============================================================================== -// module-level methods -//============================================================================== - -void -convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab) -{ - // See if the user wants us to figure out how many points to use - int n_mu = settings::legendre_to_tabular_points; - if (n_mu == C_NONE) { - // then we will use 2 pts if its P0, or the default if a higher order - // TODO use an error minimization algorithm that also picks n_mu - if (leg.get_order() == 0) { - n_mu = 2; - } else { - n_mu = DEFAULT_NMU; - } - } - - tab.base_init(n_mu, leg.gmin, leg.gmax, leg.energy, leg.mult); - tab.scattxs = leg.scattxs; - - // Build mu and dmu - tab.mu = xt::linspace(-1., 1., n_mu); - tab.dmu = 2. / (n_mu - 1); - - // Calculate f(mu) and integrate it so we can avoid rejection sampling - size_t groups = tab.energy.size(); - tab.fmu.resize(groups); - for (int gin = 0; gin < groups; gin++) { - int num_groups = tab.gmax[gin] - tab.gmin[gin] + 1; - tab.fmu[gin].resize(num_groups); - for (int i_gout = 0; i_gout < num_groups; i_gout++) { - tab.fmu[gin][i_gout].resize(n_mu); - for (int imu = 0; imu < n_mu; imu++) { - tab.fmu[gin][i_gout][imu] = - evaluate_legendre(leg.dist[gin][i_gout].size() - 1, - leg.dist[gin][i_gout].data(), tab.mu[imu]); - } - - // Ensure positivity - for (auto& val : tab.fmu[gin][i_gout]) { - if (val < 0.) val = 0.; - } - - // Now re-normalize for numerical integration issues and to take care of - // the above negative fix-up. Also accrue the CDF - double norm = 0.; - tab.dist[gin][i_gout][0] = 0.; - for (int imu = 1; imu < n_mu; imu++) { - norm += 0.5 * tab.dmu * (tab.fmu[gin][i_gout][imu - 1] + - tab.fmu[gin][i_gout][imu]); - // incorporate to the CDF - tab.dist[gin][i_gout][imu] = norm; - } - - // now do the normalization - if (norm > 0.) { - for (int imu = 0; imu < n_mu; imu++) { - tab.fmu[gin][i_gout][imu] /= norm; - tab.dist[gin][i_gout][imu] /= norm; - } - } - } - } -} - -} // namespace openmc diff --git a/src/secondary_correlated.cpp b/src/secondary_correlated.cpp deleted file mode 100644 index 0a5d8804d..000000000 --- a/src/secondary_correlated.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "openmc/secondary_correlated.h" - -#include // for copy -#include -#include // for size_t -#include // for back_inserter - -#include "xtensor/xarray.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/hdf5_interface.h" -#include "openmc/endf.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" - -namespace openmc { - -//============================================================================== -//! CorrelatedAngleEnergy implementation -//============================================================================== - -CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group) -{ - // Open incoming energy dataset - hid_t dset = open_dataset(group, "energy"); - - // Get interpolation parameters - xt::xarray temp; - read_attribute(dset, "interpolation", temp); - - auto temp_b = xt::view(temp, 0); // view of breakpoints - auto temp_i = xt::view(temp, 1); // view of interpolation parameters - - std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_)); - for (const auto i : temp_i) - interpolation_.push_back(int2interp(i)); - n_region_ = breakpoints_.size(); - - // Get incoming energies - read_dataset(dset, energy_); - std::size_t n_energy = energy_.size(); - close_dataset(dset); - - // Get outgoing energy distribution data - dset = open_dataset(group, "energy_out"); - std::vector offsets; - std::vector interp; - std::vector n_discrete; - read_attribute(dset, "offsets", offsets); - read_attribute(dset, "interpolation", interp); - read_attribute(dset, "n_discrete_lines", n_discrete); - - xt::xarray eout; - read_dataset(dset, eout); - close_dataset(dset); - - // Read angle distributions - xt::xarray mu; - read_dataset(group, "mu", mu); - - for (int i = 0; i < n_energy; ++i) { - // Determine number of outgoing energies - int j = offsets[i]; - int n; - if (i < n_energy - 1) { - n = offsets[i+1] - j; - } else { - n = eout.shape()[1] - j; - } - - // Assign interpolation scheme and number of discrete lines - CorrTable d; - d.interpolation = int2interp(interp[i]); - d.n_discrete = n_discrete[i]; - - // Copy data - d.e_out = xt::view(eout, 0, xt::range(j, j+n)); - d.p = xt::view(eout, 1, xt::range(j, j+n)); - d.c = xt::view(eout, 2, xt::range(j, j+n)); - - // To get answers that match ACE data, for now we still use the tabulated - // CDF values that were passed through to the HDF5 library. At a later - // time, we can remove the CDF values from the HDF5 library and - // reconstruct them using the PDF - if (false) { - // Calculate cumulative distribution function -- discrete portion - for (int k = 0; k < d.n_discrete; ++k) { - if (k == 0) { - d.c[k] = d.p[k]; - } else { - d.c[k] = d.c[k-1] + d.p[k]; - } - } - - // Continuous portion - for (int k = d.n_discrete; k < n; ++k) { - if (k == d.n_discrete) { - d.c[k] = d.c[k-1] + d.p[k]; - } else { - if (d.interpolation == Interpolation::histogram) { - d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]); - } else if (d.interpolation == Interpolation::lin_lin) { - d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) * - (d.e_out[k] - d.e_out[k-1]); - } - } - } - - // Normalize density and distribution functions - d.p /= d.c[n - 1]; - d.c /= d.c[n - 1]; - } - - for (j = 0; j < n; ++j) { - // Get interpolation scheme - int interp_mu = std::lround(eout(3, offsets[i] + j)); - - // Determine offset and size of distribution - int offset_mu = std::lround(eout(4, offsets[i] + j)); - int m; - if (offsets[i] + j + 1 < eout.shape()[1]) { - m = std::lround(eout(4, offsets[i]+j+1)) - offset_mu; - } else { - m = mu.shape()[1] - offset_mu; - } - - // For incoherent inelastic thermal scattering, the angle distributions - // may be given as discrete mu values. In this case, interpolation values - // of zero appear in the HDF5 file. Here we change it to a 1 so that - // int2interp doesn't fail. - if (interp_mu == 0) interp_mu = 1; - - auto interp = int2interp(interp_mu); - auto xs = xt::view(mu, 0, xt::range(offset_mu, offset_mu + m)); - auto ps = xt::view(mu, 1, xt::range(offset_mu, offset_mu + m)); - auto cs = xt::view(mu, 2, xt::range(offset_mu, offset_mu + m)); - - std::vector x {xs.begin(), xs.end()}; - std::vector p {ps.begin(), ps.end()}; - std::vector c {cs.begin(), cs.end()}; - - // To get answers that match ACE data, for now we still use the tabulated - // CDF values that were passed through to the HDF5 library. At a later - // time, we can remove the CDF values from the HDF5 library and - // reconstruct them using the PDF - Tabular* mudist = new Tabular{x.data(), p.data(), m, interp, c.data()}; - - d.angle.emplace_back(mudist); - } // outgoing energies - - distribution_.push_back(std::move(d)); - } // incoming energies -} - -void CorrelatedAngleEnergy::sample(double E_in, double& E_out, double& mu) const -{ - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - // Before the secondary distribution refactor, an isotropic polar cosine was - // always sampled but then overwritten with the polar cosine sampled from the - // correlated distribution. To preserve the random number stream, we keep - // this dummy sampling here but can remove it later (will change answers) - mu = 2.0*prn() - 1.0; - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - - // Find energy bin and calculate interpolation factor -- if the energy is - // outside the range of the tabulated energies, choose the first or last bins - auto n_energy_in = energy_.size(); - int i; - double r; - if (E_in < energy_[0]) { - i = 0; - r = 0.0; - } else if (E_in > energy_[n_energy_in - 1]) { - i = n_energy_in - 2; - r = 1.0; - } else { - i = lower_bound_index(energy_.begin(), energy_.end(), E_in); - r = (E_in - energy_[i]) / (energy_[i+1] - energy_[i]); - } - - // Sample between the ith and [i+1]th bin - int l = r > prn() ? i + 1 : i; - - // Interpolation for energy E1 and EK - int n_energy_out = distribution_[i].e_out.size(); - int n_discrete = distribution_[i].n_discrete; - double E_i_1 = distribution_[i].e_out[n_discrete]; - double E_i_K = distribution_[i].e_out[n_energy_out - 1]; - - n_energy_out = distribution_[i+1].e_out.size(); - n_discrete = distribution_[i+1].n_discrete; - double E_i1_1 = distribution_[i+1].e_out[n_discrete]; - double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1]; - - double E_1 = E_i_1 + r*(E_i1_1 - E_i_1); - double E_K = E_i_K + r*(E_i1_K - E_i_K); - - // Determine outgoing energy bin - n_energy_out = distribution_[l].e_out.size(); - n_discrete = distribution_[l].n_discrete; - double r1 = prn(); - double c_k = distribution_[l].c[0]; - int k = 0; - int end = n_energy_out - 2; - - // Discrete portion - for (int j = 0; j < n_discrete; ++j) { - k = j; - c_k = distribution_[l].c[k]; - if (r1 < c_k) { - end = j; - break; - } - } - - // Continuous portion - double c_k1; - for (int j = n_discrete; j < end; ++j) { - k = j; - c_k1 = distribution_[l].c[k+1]; - if (r1 < c_k1) break; - k = j + 1; - c_k = c_k1; - } - - double E_l_k = distribution_[l].e_out[k]; - double p_l_k = distribution_[l].p[k]; - if (distribution_[l].interpolation == Interpolation::histogram) { - // Histogram interpolation - if (p_l_k > 0.0 && k >= n_discrete) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k; - } - - } else if (distribution_[l].interpolation == Interpolation::lin_lin) { - // Linear-linear interpolation - double E_l_k1 = distribution_[l].e_out[k+1]; - double p_l_k1 = distribution_[l].p[k+1]; - - double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k); - if (frac == 0.0) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k + - 2.0*frac*(r1 - c_k))) - p_l_k)/frac; - } - - } - - // Now interpolate between incident energy bins i and i + 1 - if (k >= n_discrete){ - if (l == i) { - E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1); - } else { - E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1); - } - } - - // Find correlated angular distribution for closest outgoing energy bin - if (r1 - c_k < c_k1 - r1) { - mu = distribution_[l].angle[k]->sample(); - } else { - mu = distribution_[l].angle[k + 1]->sample(); - } -} - -} // namespace openmc diff --git a/src/secondary_kalbach.cpp b/src/secondary_kalbach.cpp deleted file mode 100644 index e3974f357..000000000 --- a/src/secondary_kalbach.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "openmc/secondary_kalbach.h" - -#include // for copy, move -#include // for log, sqrt, sinh -#include // for size_t -#include // for back_inserter -#include - -#include "xtensor/xarray.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/hdf5_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" - -namespace openmc { - -//============================================================================== -//! KalbachMann implementation -//============================================================================== - -KalbachMann::KalbachMann(hid_t group) -{ - // Open incoming energy dataset - hid_t dset = open_dataset(group, "energy"); - - // Get interpolation parameters - xt::xarray temp; - read_attribute(dset, "interpolation", temp); - - auto temp_b = xt::view(temp, 0); // view of breakpoints - auto temp_i = xt::view(temp, 1); // view of interpolation parameters - - std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_)); - for (const auto i : temp_i) - interpolation_.push_back(int2interp(i)); - n_region_ = breakpoints_.size(); - - // Get incoming energies - read_dataset(dset, energy_); - std::size_t n_energy = energy_.size(); - close_dataset(dset); - - // Get outgoing energy distribution data - dset = open_dataset(group, "distribution"); - std::vector offsets; - std::vector interp; - std::vector n_discrete; - read_attribute(dset, "offsets", offsets); - read_attribute(dset, "interpolation", interp); - read_attribute(dset, "n_discrete_lines", n_discrete); - - xt::xarray eout; - read_dataset(dset, eout); - close_dataset(dset); - - for (int i = 0; i < n_energy; ++i) { - // Determine number of outgoing energies - int j = offsets[i]; - int n; - if (i < n_energy - 1) { - n = offsets[i+1] - j; - } else { - n = eout.shape()[1] - j; - } - - // Assign interpolation scheme and number of discrete lines - KMTable d; - d.interpolation = int2interp(interp[i]); - d.n_discrete = n_discrete[i]; - - // Copy data - d.e_out = xt::view(eout, 0, xt::range(j, j+n)); - d.p = xt::view(eout, 1, xt::range(j, j+n)); - d.c = xt::view(eout, 2, xt::range(j, j+n)); - d.r = xt::view(eout, 3, xt::range(j, j+n)); - d.a = xt::view(eout, 4, xt::range(j, j+n)); - - // To get answers that match ACE data, for now we still use the tabulated - // CDF values that were passed through to the HDF5 library. At a later - // time, we can remove the CDF values from the HDF5 library and - // reconstruct them using the PDF - if (false) { - // Calculate cumulative distribution function -- discrete portion - for (int k = 0; k < d.n_discrete; ++k) { - if (k == 0) { - d.c[k] = d.p[k]; - } else { - d.c[k] = d.c[k-1] + d.p[k]; - } - } - - // Continuous portion - for (int k = d.n_discrete; k < n; ++k) { - if (k == d.n_discrete) { - d.c[k] = d.c[k-1] + d.p[k]; - } else { - if (d.interpolation == Interpolation::histogram) { - d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]); - } else if (d.interpolation == Interpolation::lin_lin) { - d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) * - (d.e_out[k] - d.e_out[k-1]); - } - } - } - - // Normalize density and distribution functions - d.p /= d.c[n - 1]; - d.c /= d.c[n - 1]; - } - - distribution_.push_back(std::move(d)); - } // incoming energies -} - -void KalbachMann::sample(double E_in, double& E_out, double& mu) const -{ - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - // Before the secondary distribution refactor, an isotropic polar cosine was - // always sampled but then overwritten with the polar cosine sampled from the - // correlated distribution. To preserve the random number stream, we keep - // this dummy sampling here but can remove it later (will change answers) - mu = 2.0*prn() - 1.0; - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - - // Find energy bin and calculate interpolation factor -- if the energy is - // outside the range of the tabulated energies, choose the first or last bins - auto n_energy_in = energy_.size(); - int i; - double r; - if (E_in < energy_[0]) { - i = 0; - r = 0.0; - } else if (E_in > energy_[n_energy_in - 1]) { - i = n_energy_in - 2; - r = 1.0; - } else { - i = lower_bound_index(energy_.begin(), energy_.end(), E_in); - r = (E_in - energy_[i]) / (energy_[i+1] - energy_[i]); - } - - // Sample between the ith and [i+1]th bin - int l = r > prn() ? i + 1 : i; - - // Interpolation for energy E1 and EK - int n_energy_out = distribution_[i].e_out.size(); - int n_discrete = distribution_[i].n_discrete; - double E_i_1 = distribution_[i].e_out[n_discrete]; - double E_i_K = distribution_[i].e_out[n_energy_out - 1]; - - n_energy_out = distribution_[i+1].e_out.size(); - n_discrete = distribution_[i+1].n_discrete; - double E_i1_1 = distribution_[i+1].e_out[n_discrete]; - double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1]; - - double E_1 = E_i_1 + r*(E_i1_1 - E_i_1); - double E_K = E_i_K + r*(E_i1_K - E_i_K); - - // Determine outgoing energy bin - n_energy_out = distribution_[l].e_out.size(); - n_discrete = distribution_[l].n_discrete; - double r1 = prn(); - double c_k = distribution_[l].c[0]; - int k = 0; - int end = n_energy_out - 2; - - // Discrete portion - for (int j = 0; j < n_discrete; ++j) { - k = j; - c_k = distribution_[l].c[k]; - if (r1 < c_k) { - end = j; - break; - } - } - - // Continuous portion - double c_k1; - for (int j = n_discrete; j < end; ++j) { - k = j; - c_k1 = distribution_[l].c[k+1]; - if (r1 < c_k1) break; - k = j + 1; - c_k = c_k1; - } - - double E_l_k = distribution_[l].e_out[k]; - double p_l_k = distribution_[l].p[k]; - double km_r, km_a; - if (distribution_[l].interpolation == Interpolation::histogram) { - // Histogram interpolation - if (p_l_k > 0.0 && k >= n_discrete) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k; - } - - // Determine Kalbach-Mann parameters - km_r = distribution_[l].r[k]; - km_a = distribution_[l].a[k]; - - } else { - // Linear-linear interpolation - double E_l_k1 = distribution_[l].e_out[k+1]; - double p_l_k1 = distribution_[l].p[k+1]; - - double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k); - if (frac == 0.0) { - E_out = E_l_k + (r1 - c_k)/p_l_k; - } else { - E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k + - 2.0*frac*(r1 - c_k))) - p_l_k)/frac; - } - - // Determine Kalbach-Mann parameters - km_r = distribution_[l].r[k] + (E_out - E_l_k)/(E_l_k1 - E_l_k) * - (distribution_[l].r[k+1] - distribution_[l].r[k]); - km_a = distribution_[l].a[k] + (E_out - E_l_k)/(E_l_k1 - E_l_k) * - (distribution_[l].a[k+1] - distribution_[l].a[k]); - } - - // Now interpolate between incident energy bins i and i + 1 - if (k >= n_discrete) { - if (l == i) { - E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1); - } else { - E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1); - } - } - - // Sampled correlated angle from Kalbach-Mann parameters - if (prn() > km_r) { - double T = (2.0*prn() - 1.0) * std::sinh(km_a); - mu = std::log(T + std::sqrt(T*T + 1.0))/km_a; - } else { - double r1 = prn(); - mu = std::log(r1*std::exp(km_a) + (1.0 - r1)*std::exp(-km_a))/km_a; - } -} - -} diff --git a/src/secondary_nbody.cpp b/src/secondary_nbody.cpp deleted file mode 100644 index 564fca73d..000000000 --- a/src/secondary_nbody.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "openmc/secondary_nbody.h" - -#include // for log - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/math_functions.h" -#include "openmc/random_lcg.h" - -namespace openmc { - -//============================================================================== -// NBodyPhaseSpace implementation -//============================================================================== - -NBodyPhaseSpace::NBodyPhaseSpace(hid_t group) -{ - read_attribute(group, "n_particles", n_bodies_); - read_attribute(group, "total_mass", mass_ratio_); - read_attribute(group, "atomic_weight_ratio", A_); - read_attribute(group, "q_value", Q_); -} - -void NBodyPhaseSpace::sample(double E_in, double& E_out, double& mu) const -{ - // By definition, the distribution of the angle is isotropic for an N-body - // phase space distribution - mu = 2.0*prn() - 1.0; - - // Determine E_max parameter - double Ap = mass_ratio_; - double E_max = (Ap - 1.0)/Ap * (A_/(A_ + 1.0)*E_in + Q_); - - // x is essentially a Maxwellian distribution - double x = maxwell_spectrum(1.0); - - double y; - double r1, r2, r3, r4, r5, r6; - switch (n_bodies_) { - case 3: - y = maxwell_spectrum(1.0); - break; - case 4: - r1 = prn(); - r2 = prn(); - r3 = prn(); - y = -std::log(r1*r2*r3); - break; - case 5: - r1 = prn(); - r2 = prn(); - r3 = prn(); - r4 = prn(); - r5 = prn(); - r6 = prn(); - y = -std::log(r1*r2*r3*r4) - std::log(r5) * std::pow(std::cos(PI/2.0*r6), 2); - break; - default: - throw std::runtime_error{"N-body phase space with >5 bodies."}; - } - - // Now determine v and E_out - double v = x/(x + y); - E_out = E_max * v; -} - -} // namespace openmc diff --git a/src/secondary_thermal.cpp b/src/secondary_thermal.cpp deleted file mode 100644 index 8c9cc6967..000000000 --- a/src/secondary_thermal.cpp +++ /dev/null @@ -1,327 +0,0 @@ -#include "openmc/secondary_thermal.h" - -#include "openmc/hdf5_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" - -#include "xtensor/xview.hpp" - -#include // for log, exp - -namespace openmc { - -// Helper function to get index on incident energy grid -void -get_energy_index(const std::vector& energies, double E, int& i, double& f) -{ - // Get index and interpolation factor for elastic grid - i = 0; - f = 0.0; - if (E >= energies.front()) { - i = lower_bound_index(energies.begin(), energies.end(), E); - f = (E - energies[i]) / (energies[i+1] - energies[i]); - } -} - -//============================================================================== -// CoherentElasticAE implementation -//============================================================================== - -CoherentElasticAE::CoherentElasticAE(const CoherentElasticXS& xs) - : xs_{xs} -{ } - -void -CoherentElasticAE::sample(double E_in, double& E_out, double& mu) const -{ - // Get index and interpolation factor for elastic grid - int i; - double f; - const auto& energies {xs_.bragg_edges()}; - get_energy_index(energies, E_in, i, f); - - // Sample a Bragg edge between 1 and i - const auto& factors = xs_.factors(); - double prob = prn() * factors[i+1]; - int k = 0; - if (prob >= factors.front()) { - k = lower_bound_index(factors.begin(), factors.begin() + (i+1), prob); - } - - // Characteristic scattering cosine for this Bragg edge (ENDF-102, Eq. 7-2) - mu = 1.0 - 2.0*energies[k] / E_in; - - // Energy doesn't change in elastic scattering (ENDF-102, Eq. 7-1) - E_out = E_in; -} - -//============================================================================== -// IncoherentElasticAE implementation -//============================================================================== - -IncoherentElasticAE::IncoherentElasticAE(hid_t group) -{ - read_dataset(group, "debye_waller", debye_waller_); -} - -void -IncoherentElasticAE::sample(double E_in, double& E_out, double& mu) const -{ - // Sample angle by inverting the distribution in ENDF-102, Eq. 7.4 - double c = 2 * E_in * debye_waller_; - mu = std::log(1.0 + prn()*(std::exp(2.0*c) - 1))/c - 1.0; - - // Energy doesn't change in elastic scattering (ENDF-102, Eq. 7.4) - E_out = E_in; -} - -//============================================================================== -// IncoherentElasticAEDiscrete implementation -//============================================================================== - -IncoherentElasticAEDiscrete::IncoherentElasticAEDiscrete(hid_t group, - const std::vector& energy) - : energy_{energy} -{ - read_dataset(group, "mu_out", mu_out_); -} - -void -IncoherentElasticAEDiscrete::sample(double E_in, double& E_out, double& mu) const -{ - // Get index and interpolation factor for elastic grid - int i; - double f; - get_energy_index(energy_, E_in, i, f); - - // Interpolate between two discrete cosines corresponding to neighboring - // incoming energies. - - // Sample outgoing cosine bin - int k = prn() * mu_out_.shape()[1]; - - // Determine outgoing cosine corresponding to E_in[i] and E_in[i+1] - double mu_ik = mu_out_(i, k); - double mu_i1k = mu_out_(i+1, k); - - // Cosine of angle between incoming and outgoing neutron - mu = (1 - f)*mu_ik + f*mu_i1k; - - // Energy doesn't change in elastic scattering - E_out = E_in; -} - -//============================================================================== -// IncoherentInelasticAEDiscrete implementation -//============================================================================== - -IncoherentInelasticAEDiscrete::IncoherentInelasticAEDiscrete(hid_t group, - const std::vector& energy) - : energy_{energy} -{ - read_dataset(group, "energy_out", energy_out_); - read_dataset(group, "mu_out", mu_out_); - read_dataset(group, "skewed", skewed_); -} - -void -IncoherentInelasticAEDiscrete::sample(double E_in, double& E_out, double& mu) const -{ - // Get index and interpolation factor for inelastic grid - int i; - double f; - get_energy_index(energy_, E_in, i, f); - - // Now that we have an incoming energy bin, we need to determine the outgoing - // energy bin. This will depend on whether the outgoing energy distribution is - // skewed. If it is skewed, then the first two and last two bins have lower - // probabilities than the other bins (0.1 for the first and last bins and 0.4 - // for the second and second to last bins, relative to a normal bin - // probability of 1). Otherwise, each bin is equally probable. - - int j; - int n = energy_out_.shape()[1]; - if (!skewed_) { - // All bins equally likely - j = prn() * n; - } else { - // Distribution skewed away from edge points - double r = prn() * (n - 3); - if (r > 1.0) { - // equally likely N-4 middle bins - j = r + 1; - } else if (r > 0.6) { - // second to last bin has relative probability of 0.4 - j = n - 2; - } else if (r > 0.5) { - // last bin has relative probability of 0.1 - j = n - 1; - } else if (r > 0.1) { - // second bin has relative probability of 0.4 - j = 1; - } else { - // first bin has relative probability of 0.1 - j = 0; - } - } - - // Determine outgoing energy corresponding to E_in[i] and E_in[i+1] - double E_ij = energy_out_(i, j); - double E_i1j = energy_out_(i+1, j); - - // Outgoing energy - E_out = (1 - f)*E_ij + f*E_i1j; - - // Sample outgoing cosine bin - int m = mu_out_.shape()[2]; - int k = prn() * m; - - // Determine outgoing cosine corresponding to E_in[i] and E_in[i+1] - double mu_ijk = mu_out_(i, j, k); - double mu_i1jk = mu_out_(i+1, j, k); - - // Cosine of angle between incoming and outgoing neutron - mu = (1 - f)*mu_ijk + f*mu_i1jk; -} - -//============================================================================== -// IncoherentInelasticAE implementation -//============================================================================== - -IncoherentInelasticAE::IncoherentInelasticAE(hid_t group) -{ - // Read correlated angle-energy distribution - CorrelatedAngleEnergy dist {group}; - - // Copy incident energies - energy_ = dist.energy(); - - // Convert to S(a,b) native format - for (const auto& edist : dist.distribution()) { - // Create temporary distribution - DistEnergySab d; - - // Copy outgoing energy distribution - d.n_e_out = edist.e_out.size(); - d.e_out = edist.e_out; - d.e_out_pdf = edist.p; - d.e_out_cdf = edist.c; - - for (int j = 0; j < d.n_e_out; ++j) { - auto adist = dynamic_cast(edist.angle[j].get()); - if (adist) { - // On first pass, allocate space for angles - if (j == 0) { - auto n_mu = adist->x().size(); - d.mu = xt::empty({d.n_e_out, n_mu}); - } - - // Copy outgoing angles - auto mu_j = xt::view(d.mu, j); - std::copy(adist->x().begin(), adist->x().end(), mu_j.begin()); - } - } - - distribution_.emplace_back(std::move(d)); - } - -} - -void -IncoherentInelasticAE::sample(double E_in, double& E_out, double& mu) const -{ - // Get index and interpolation factor for inelastic grid - int i; - double f; - get_energy_index(energy_, E_in, i, f); - - // Sample between ith and [i+1]th bin - int l = f > prn() ? i + 1 : i; - - // Determine endpoints on grid i - auto n = distribution_[i].e_out.size(); - double E_i_1 = distribution_[i].e_out[0]; - double E_i_J = distribution_[i].e_out[n - 1]; - - // Determine endpoints on grid i + 1 - n = distribution_[i + 1].e_out.size(); - double E_i1_1 = distribution_[i + 1].e_out[0]; - double E_i1_J = distribution_[i + 1].e_out[n - 1]; - - double E_1 = E_i_1 + f * (E_i1_1 - E_i_1); - double E_J = E_i_J + f * (E_i1_J - E_i_J); - - // Determine outgoing energy bin - // (First reset n_energy_out to the right value) - n = distribution_[l].n_e_out; - double r1 = prn(); - double c_j = distribution_[l].e_out_cdf[0]; - double c_j1; - std::size_t j; - for (j = 0; j < n - 1; ++j) { - c_j1 = distribution_[l].e_out_cdf[j + 1]; - if (r1 < c_j1) break; - c_j = c_j1; - } - - // check to make sure j is <= n_energy_out - 2 - j = std::min(j, n - 2); - - // Get the data to interpolate between - double E_l_j = distribution_[l].e_out[j]; - double p_l_j = distribution_[l].e_out_pdf[j]; - - // Next part assumes linear-linear interpolation in standard - double E_l_j1 = distribution_[l].e_out[j + 1]; - double p_l_j1 = distribution_[l].e_out_pdf[j + 1]; - - // Find secondary energy (variable E) - double frac = (p_l_j1 - p_l_j) / (E_l_j1 - E_l_j); - if (frac == 0.0) { - E_out = E_l_j + (r1 - c_j) / p_l_j; - } else { - E_out = E_l_j + (std::sqrt(std::max(0.0, p_l_j*p_l_j + - 2.0*frac*(r1 - c_j))) - p_l_j) / frac; - } - - // Now interpolate between incident energy bins i and i + 1 - if (l == i) { - E_out = E_1 + (E_out - E_i_1) * (E_J - E_1) / (E_i_J - E_i_1); - } else { - E_out = E_1 + (E_out - E_i1_1) * (E_J - E_1) / (E_i1_J - E_i1_1); - } - - // Sample outgoing cosine bin - int n_mu = distribution_[l].mu.shape()[1]; - std::size_t k = prn() * n_mu; - - // Rather than use the sampled discrete mu directly, it is smeared over - // a bin of width min(mu[k] - mu[k-1], mu[k+1] - mu[k]) centered on the - // discrete mu value itself. - const auto& mu_l = distribution_[l].mu; - f = (r1 - c_j)/(c_j1 - c_j); - - // Determine (k-1)th mu value - double mu_left; - if (k == 0) { - mu_left = -1.0; - } else { - mu_left = mu_l(j, k-1) + f*(mu_l(j+1, k-1) - mu_l(j, k-1)); - } - - // Determine kth mu value - mu = mu_l(j, k) + f*(mu_l(j+1, k) - mu_l(j, k)); - - // Determine (k+1)th mu value - double mu_right; - if (k == n_mu - 1) { - mu_right = 1.0; - } else { - mu_right = mu_l(j, k+1) + f*(mu_l(j+1, k+1) - mu_l(j, k+1)); - } - - // Smear angle - mu += std::min(mu - mu_left, mu_right - mu)*(prn() - 0.5); -} - -} // namespace openmc diff --git a/src/secondary_uncorrelated.cpp b/src/secondary_uncorrelated.cpp deleted file mode 100644 index 3192c1e04..000000000 --- a/src/secondary_uncorrelated.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "openmc/secondary_uncorrelated.h" - -#include // for stringstream -#include // for string - -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/random_lcg.h" - -namespace openmc { - -//============================================================================== -// UncorrelatedAngleEnergy implementation -//============================================================================== - -UncorrelatedAngleEnergy::UncorrelatedAngleEnergy(hid_t group) -{ - // Check if angle group is present & read - if (object_exists(group, "angle")) { - hid_t angle_group = open_group(group, "angle"); - angle_ = AngleDistribution{angle_group}; - close_group(angle_group); - } - - // Check if energy group is present & read - if (object_exists(group, "energy")) { - hid_t energy_group = open_group(group, "energy"); - - std::string type; - read_attribute(energy_group, "type", type); - using UPtrEDist = std::unique_ptr; - if (type == "discrete_photon") { - energy_ = UPtrEDist{new DiscretePhoton{energy_group}}; - } else if (type == "level") { - energy_ = UPtrEDist{new LevelInelastic{energy_group}}; - } else if (type == "continuous") { - energy_ = UPtrEDist{new ContinuousTabular{energy_group}}; - } else if (type == "maxwell") { - energy_ = UPtrEDist{new MaxwellEnergy{energy_group}}; - } else if (type == "evaporation") { - energy_ = UPtrEDist{new Evaporation{energy_group}}; - } else if (type == "watt") { - energy_ = UPtrEDist{new WattEnergy{energy_group}}; - } else { - std::stringstream msg; - msg << "Energy distribution type '" << type << "' not implemented."; - warning(msg); - } - close_group(energy_group); - } - -} - -void -UncorrelatedAngleEnergy::sample(double E_in, double& E_out, double& mu) const -{ - // Sample cosine of scattering angle - if (fission_) { - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - // For fission, the angle is not used, so just assign a dummy value - mu = 1.0; - // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<< - } else if (!angle_.empty()) { - mu = angle_.sample(E_in); - } else { - // no angle distribution given => assume isotropic for all energies - mu = 2.0*prn() - 1.0; - } - - // Sample outgoing energy - E_out = energy_->sample(E_in); -} - -} // namespace openmc diff --git a/src/settings.cpp b/src/settings.cpp deleted file mode 100644 index 796a2862a..000000000 --- a/src/settings.cpp +++ /dev/null @@ -1,788 +0,0 @@ -#include "openmc/settings.h" - -#include // for ceil, pow -#include // for numeric_limits -#include -#include - -#ifdef _OPENMP -#include -#endif - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/container_util.h" -#include "openmc/distribution.h" -#include "openmc/distribution_multi.h" -#include "openmc/distribution_spatial.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/mesh.h" -#include "openmc/message_passing.h" -#include "openmc/output.h" -#include "openmc/random_lcg.h" -#include "openmc/simulation.h" -#include "openmc/source.h" -#include "openmc/string_utils.h" -#include "openmc/tallies/trigger.h" -#include "openmc/volume_calc.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace settings { - -// Default values for boolean flags -bool assume_separate {false}; -bool check_overlaps {false}; -bool cmfd_run {false}; -bool confidence_intervals {false}; -bool create_fission_neutrons {true}; -bool dagmc {false}; -bool entropy_on {false}; -bool legendre_to_tabular {true}; -bool output_summary {true}; -bool output_tallies {true}; -bool particle_restart_run {false}; -bool photon_transport {false}; -bool reduce_tallies {true}; -bool res_scat_on {false}; -bool restart_run {false}; -bool run_CE {true}; -bool source_latest {false}; -bool source_separate {false}; -bool source_write {true}; -bool survival_biasing {false}; -bool temperature_multipole {false}; -bool trigger_on {false}; -bool trigger_predict {false}; -bool ufs_on {false}; -bool urr_ptables_on {true}; -bool write_all_tracks {false}; -bool write_initial_source {false}; - -std::string path_cross_sections; -std::string path_input; -std::string path_output; -std::string path_particle_restart; -std::string path_source; -std::string path_sourcepoint; -std::string path_statepoint; - -int32_t n_batches; -int32_t n_inactive {0}; -int32_t gen_per_batch {1}; -int64_t n_particles {-1}; - -int electron_treatment {ELECTRON_TTB}; -std::array energy_cutoff {0.0, 1000.0, 0.0, 0.0}; -int legendre_to_tabular_points {C_NONE}; -int max_order {0}; -int n_log_bins {8000}; -int n_max_batches; -ResScatMethod res_scat_method {ResScatMethod::rvs}; -double res_scat_energy_min {0.01}; -double res_scat_energy_max {1000.0}; -std::vector res_scat_nuclides; -int run_mode {-1}; -std::unordered_set sourcepoint_batch; -std::unordered_set statepoint_batch; -int temperature_method {TEMPERATURE_NEAREST}; -double temperature_tolerance {10.0}; -double temperature_default {293.6}; -std::array temperature_range {0.0, 0.0}; -int trace_batch; -int trace_gen; -int64_t trace_particle; -std::vector> track_identifiers; -int trigger_batch_interval {1}; -int verbosity {7}; -double weight_cutoff {0.25}; -double weight_survive {1.0}; - -} // namespace settings - -//============================================================================== -// Functions -//============================================================================== - -void get_run_parameters(pugi::xml_node node_base) -{ - using namespace settings; - using namespace pugi; - - // Check number of particles - if (!check_for_node(node_base, "particles")) { - fatal_error("Need to specify number of particles."); - } - - // Get number of particles if it wasn't specified as a command-line argument - if (n_particles == -1) { - n_particles = std::stoll(get_node_value(node_base, "particles")); - } - - // Get number of basic batches - if (check_for_node(node_base, "batches")) { - n_batches = std::stoi(get_node_value(node_base, "batches")); - } - if (!trigger_on) n_max_batches = n_batches; - - // Get number of inactive batches - if (run_mode == RUN_MODE_EIGENVALUE) { - if (check_for_node(node_base, "inactive")) { - n_inactive = std::stoi(get_node_value(node_base, "inactive")); - } - if (check_for_node(node_base, "generations_per_batch")) { - gen_per_batch = std::stoi(get_node_value(node_base, "generations_per_batch")); - } - - // Preallocate space for keff and entropy by generation - int m = settings::n_max_batches * settings::gen_per_batch; - simulation::k_generation.reserve(m); - simulation::entropy.reserve(m); - - // Get the trigger information for keff - if (check_for_node(node_base, "keff_trigger")) { - xml_node node_keff_trigger = node_base.child("keff_trigger"); - - if (check_for_node(node_keff_trigger, "type")) { - auto temp = get_node_value(node_keff_trigger, "type", true, true); - if (temp == "std_dev") { - keff_trigger.metric = TriggerMetric::standard_deviation; - } else if (temp == "variance") { - keff_trigger.metric = TriggerMetric::variance; - } else if (temp == "rel_err") { - keff_trigger.metric = TriggerMetric::relative_error; - } else { - fatal_error("Unrecognized keff trigger type " + temp); - } - } else { - fatal_error("Specify keff trigger type in settings XML"); - } - - if (check_for_node(node_keff_trigger, "threshold")) { - keff_trigger.threshold = std::stod(get_node_value( - node_keff_trigger, "threshold")); - } else { - fatal_error("Specify keff trigger threshold in settings XML"); - } - } - } -} - -void read_settings_xml() -{ - using namespace settings; - using namespace pugi; - - // Check if settings.xml exists - std::string filename = path_input + "settings.xml"; - if (!file_exists(filename)) { - if (run_mode != RUN_MODE_PLOTTING) { - std::stringstream msg; - msg << "Settings XML file '" << filename << "' does not exist! In order " - "to run OpenMC, you first need a set of input files; at a minimum, this " - "includes settings.xml, geometry.xml, and materials.xml. Please consult " - "the user's guide at http://openmc.readthedocs.io for further " - "information."; - fatal_error(msg); - } else { - // The settings.xml file is optional if we just want to make a plot. - return; - } - } - - // Parse settings.xml file - xml_document doc; - auto result = doc.load_file(filename.c_str()); - if (!result) { - fatal_error("Error processing settings.xml file."); - } - - // Get root element - xml_node root = doc.document_element(); - - // Verbosity - if (check_for_node(root, "verbosity")) { - verbosity = std::stoi(get_node_value(root, "verbosity")); - } - - // DAGMC geometry check - if (check_for_node(root, "dagmc")) { - dagmc = get_node_value_bool(root, "dagmc"); - } - -#ifndef DAGMC - if (dagmc) { - fatal_error("DAGMC mode unsupported for this build of OpenMC"); - } -#endif - - // To this point, we haven't displayed any output since we didn't know what - // the verbosity is. Now that we checked for it, show the title if necessary - if (mpi::master) { - if (verbosity >= 2) title(); - } - write_message("Reading settings XML file...", 5); - - // Find if a multi-group or continuous-energy simulation is desired - if (check_for_node(root, "energy_mode")) { - std::string temp_str = get_node_value(root, "energy_mode", true, true); - if (temp_str == "mg" || temp_str == "multi-group") { - run_CE = false; - } else if (temp_str == "ce" || temp_str == "continuous-energy") { - run_CE = true; - } - } - - // Look for deprecated cross_sections.xml file in settings.xml - if (check_for_node(root, "cross_sections")) { - warning("Setting cross_sections in settings.xml has been deprecated." - " The cross_sections are now set in materials.xml and the " - "cross_sections input to materials.xml and the OPENMC_CROSS_SECTIONS" - " environment variable will take precendent over setting " - "cross_sections in settings.xml."); - path_cross_sections = get_node_value(root, "cross_sections"); - } - - if (!run_CE) { - // Scattering Treatments - if (check_for_node(root, "max_order")) { - max_order = std::stoi(get_node_value(root, "max_order")); - } else { - // Set to default of largest int - 1, which means to use whatever is - // contained in library. This is largest int - 1 because for legendre - // scattering, a value of 1 is added to the order; adding 1 to the largest - // int gets you the largest negative integer, which is not what we want. - max_order = std::numeric_limits::max() - 1; - } - } - - // Check for a trigger node and get trigger information - if (check_for_node(root, "trigger")) { - xml_node node_trigger = root.child("trigger"); - - // Check if trigger(s) are to be turned on - trigger_on = get_node_value_bool(node_trigger, "active"); - - if (trigger_on) { - if (check_for_node(node_trigger, "max_batches") ){ - n_max_batches = std::stoi(get_node_value(node_trigger, "max_batches")); - } else { - fatal_error(" must be specified with triggers"); - } - - // Get the batch interval to check triggers - if (!check_for_node(node_trigger, "batch_interval")){ - trigger_predict = true; - } else { - trigger_batch_interval = std::stoi(get_node_value(node_trigger, "batch_interval")); - if (trigger_batch_interval <= 0) { - fatal_error("Trigger batch interval must be greater than zero"); - } - } - } - } - - // Check run mode if it hasn't been set from the command line - xml_node node_mode; - if (run_mode == C_NONE) { - if (check_for_node(root, "run_mode")) { - std::string temp_str = get_node_value(root, "run_mode", true, true); - if (temp_str == "eigenvalue") { - run_mode = RUN_MODE_EIGENVALUE; - } else if (temp_str == "fixed source") { - run_mode = RUN_MODE_FIXEDSOURCE; - } else if (temp_str == "plot") { - run_mode = RUN_MODE_PLOTTING; - } else if (temp_str == "particle restart") { - run_mode = RUN_MODE_PARTICLE; - } else if (temp_str == "volume") { - run_mode = RUN_MODE_VOLUME; - } else { - fatal_error("Unrecognized run mode: " + temp_str); - } - - // Assume XML specifies , , etc. directly - node_mode = root; - } else { - warning(" should be specified."); - - // Make sure that either eigenvalue or fixed source was specified - node_mode = root.child("eigenvalue"); - if (node_mode) { - run_mode = RUN_MODE_EIGENVALUE; - } else { - node_mode = root.child("fixed_source"); - if (node_mode) { - run_mode = RUN_MODE_FIXEDSOURCE; - } else { - fatal_error(" or not specified."); - } - } - } - } - - if (run_mode == RUN_MODE_EIGENVALUE || run_mode == RUN_MODE_FIXEDSOURCE) { - // Read run parameters - get_run_parameters(node_mode); - - // Check number of active batches, inactive batches, and particles - if (n_batches <= n_inactive) { - fatal_error("Number of active batches must be greater than zero."); - } else if (n_inactive < 0) { - fatal_error("Number of inactive batches must be non-negative."); - } else if (n_particles <= 0) { - fatal_error("Number of particles must be greater than zero."); - } - } - - // Copy random number seed if specified - if (check_for_node(root, "seed")) { - auto seed = std::stoll(get_node_value(root, "seed")); - openmc_set_seed(seed); - } - - // Check for electron treatment - if (check_for_node(root, "electron_treatment")) { - auto temp_str = get_node_value(root, "electron_treatment", true, true); - if (temp_str == "led") { - electron_treatment = ELECTRON_LED; - } else if (temp_str == "ttb") { - electron_treatment = ELECTRON_TTB; - } else { - fatal_error("Unrecognized electron treatment: " + temp_str + "."); - } - } - - // Check for photon transport - if (check_for_node(root, "photon_transport")) { - photon_transport = get_node_value_bool(root, "photon_transport"); - - if (!run_CE && photon_transport) { - fatal_error("Photon transport is not currently supported in " - "multigroup mode"); - } - } - - // Number of bins for logarithmic grid - if (check_for_node(root, "log_grid_bins")) { - n_log_bins = std::stoi(get_node_value(root, "log_grid_bins")); - if (n_log_bins < 1) { - fatal_error("Number of bins for logarithmic grid must be greater " - "than zero."); - } - } - - // Number of OpenMP threads - if (check_for_node(root, "threads")) { - if (mpi::master) warning("The element has been deprecated. Use " - "the OMP_NUM_THREADS environment variable to set the number of threads."); - } - - // ========================================================================== - // EXTERNAL SOURCE - - // Get point to list of elements and make sure there is at least one - for (pugi::xml_node node : root.children("source")) { - model::external_sources.emplace_back(node); - } - - // If no source specified, default to isotropic point source at origin with Watt spectrum - if (model::external_sources.empty()) { - SourceDistribution source { - UPtrSpace{new SpatialPoint({0.0, 0.0, 0.0})}, - UPtrAngle{new Isotropic()}, - UPtrDist{new Watt(0.988e6, 2.249e-6)} - }; - model::external_sources.push_back(std::move(source)); - } - - // Check if we want to write out source - if (check_for_node(root, "write_initial_source")) { - write_initial_source = get_node_value_bool(root, "write_initial_source"); - } - - // Survival biasing - if (check_for_node(root, "survival_biasing")) { - survival_biasing = get_node_value_bool(root, "survival_biasing"); - } - - // Probability tables - if (check_for_node(root, "ptables")) { - urr_ptables_on = get_node_value_bool(root, "ptables"); - } - - // Cutoffs - if (check_for_node(root, "cutoff")) { - xml_node node_cutoff = root.child("cutoff"); - if (check_for_node(node_cutoff, "weight")) { - weight_cutoff = std::stod(get_node_value(node_cutoff, "weight")); - } - if (check_for_node(node_cutoff, "weight_avg")) { - weight_survive = std::stod(get_node_value(node_cutoff, "weight_avg")); - } - if (check_for_node(node_cutoff, "energy_neutron")) { - energy_cutoff[0] = std::stod(get_node_value(node_cutoff, "energy_neutron")); - } else if (check_for_node(node_cutoff, "energy")) { - warning("The use of an cutoff is deprecated and should " - "be replaced by ."); - energy_cutoff[0] = std::stod(get_node_value(node_cutoff, "energy")); - } - if (check_for_node(node_cutoff, "energy_photon")) { - energy_cutoff[1] = std::stod(get_node_value(node_cutoff, "energy_photon")); - } - if (check_for_node(node_cutoff, "energy_electron")) { - energy_cutoff[2] = std::stof(get_node_value(node_cutoff, "energy_electron")); - } - if (check_for_node(node_cutoff, "energy_positron")) { - energy_cutoff[3] = std::stod(get_node_value(node_cutoff, "energy_positron")); - } - } - - // Particle trace - if (check_for_node(root, "trace")) { - auto temp = get_node_array(root, "trace"); - if (temp.size() != 3) { - fatal_error("Must provide 3 integers for that specify the " - "batch, generation, and particle number."); - } - trace_batch = temp.at(0); - trace_gen = temp.at(1); - trace_particle = temp.at(2); - } - - // Particle tracks - if (check_for_node(root, "track")) { - // Get values and make sure there are three per particle - auto temp = get_node_array(root, "track"); - if (temp.size() % 3 != 0) { - fatal_error("Number of integers specified in 'track' is not " - "divisible by 3. Please provide 3 integers per particle to be " - "tracked."); - } - - // Reshape into track_identifiers - int n_tracks = temp.size() / 3; - for (int i = 0; i < n_tracks; ++i) { - track_identifiers.push_back({temp[3*i], temp[3*i + 1], - temp[3*i + 2]}); - } - } - - // Read meshes - read_meshes(root); - - // Shannon Entropy mesh - int32_t index_entropy_mesh = -1; - if (check_for_node(root, "entropy_mesh")) { - int temp = std::stoi(get_node_value(root, "entropy_mesh")); - if (model::mesh_map.find(temp) == model::mesh_map.end()) { - std::stringstream msg; - msg << "Mesh " << temp << " specified for Shannon entropy does not exist."; - fatal_error(msg); - } - index_entropy_mesh = model::mesh_map.at(temp); - - } else if (check_for_node(root, "entropy")) { - warning("Specifying a Shannon entropy mesh via the element " - "is deprecated. Please create a mesh using and then reference " - "it by specifying its ID in an element."); - - // Read entropy mesh from - auto node_entropy = root.child("entropy"); - model::meshes.push_back(std::make_unique(node_entropy)); - - // Set entropy mesh index - index_entropy_mesh = model::meshes.size() - 1; - - // Assign ID and set mapping - model::meshes.back()->id_ = 10000; - model::mesh_map[10000] = index_entropy_mesh; - } - - if (index_entropy_mesh >= 0) { - auto* m = dynamic_cast( - model::meshes[index_entropy_mesh].get()); - if (!m) fatal_error("Only regular meshes can be used as an entropy mesh"); - simulation::entropy_mesh = m; - - // TODO: Change to zero when xtensor is updated - if (m->shape_.size() == 1) { - // If the user did not specify how many mesh cells are to be used in - // each direction, we automatically determine an appropriate number of - // cells - int n = std::ceil(std::pow(n_particles / 20.0, 1.0/3.0)); - m->shape_ = {n, n, n}; - m->n_dimension_ = 3; - - // Calculate width - m->width_ = (m->upper_right_ - m->lower_left_) / m->shape_; - } - - // Turn on Shannon entropy calculation - entropy_on = true; - } - - // Uniform fission source weighting mesh - int32_t i_ufs_mesh = -1; - if (check_for_node(root, "ufs_mesh")) { - auto temp = std::stoi(get_node_value(root, "ufs_mesh")); - if (model::mesh_map.find(temp) == model::mesh_map.end()) { - std::stringstream msg; - msg << "Mesh " << temp << " specified for uniform fission site method " - "does not exist."; - fatal_error(msg); - } - i_ufs_mesh = model::mesh_map.at(temp); - - } else if (check_for_node(root, "uniform_fs")) { - warning("Specifying a UFS mesh via the element " - "is deprecated. Please create a mesh using and then reference " - "it by specifying its ID in a element."); - - // Read entropy mesh from - auto node_ufs = root.child("uniform_fs"); - model::meshes.push_back(std::make_unique(node_ufs)); - - // Set entropy mesh index - i_ufs_mesh = model::meshes.size() - 1; - - // Assign ID and set mapping - model::meshes.back()->id_ = 10001; - model::mesh_map[10001] = index_entropy_mesh; - } - - if (i_ufs_mesh >= 0) { - auto* m = dynamic_cast(model::meshes[i_ufs_mesh].get()); - if (!m) fatal_error("Only regular meshes can be used as a UFS mesh"); - simulation::ufs_mesh = m; - - // Turn on uniform fission source weighting - ufs_on = true; - } - - // Check if the user has specified to write state points - if (check_for_node(root, "state_point")) { - - // Get pointer to state_point node - auto node_sp = root.child("state_point"); - - // Determine number of batches at which to store state points - if (check_for_node(node_sp, "batches")) { - // User gave specific batches to write state points - auto temp = get_node_array(node_sp, "batches"); - for (const auto& b : temp) { - statepoint_batch.insert(b); - } - } else { - // If neither were specified, write state point at last batch - statepoint_batch.insert(n_batches); - } - } else { - // If no tag was present, by default write state point at - // last batch only - statepoint_batch.insert(n_batches); - } - - // Check if the user has specified to write source points - if (check_for_node(root, "source_point")) { - // Get source_point node - xml_node node_sp = root.child("source_point"); - - // Determine batches at which to store source points - if (check_for_node(node_sp, "batches")) { - // User gave specific batches to write source points - auto temp = get_node_array(node_sp, "batches"); - for (const auto& b : temp) { - sourcepoint_batch.insert(b); - } - } else { - // If neither were specified, write source points with state points - sourcepoint_batch = statepoint_batch; - } - - // Check if the user has specified to write binary source file - if (check_for_node(node_sp, "separate")) { - source_separate = get_node_value_bool(node_sp, "separate"); - } - if (check_for_node(node_sp, "write")) { - source_write = get_node_value_bool(node_sp, "write"); - } - if (check_for_node(node_sp, "overwrite_latest")) { - source_latest = get_node_value_bool(node_sp, "overwrite_latest"); - source_separate = source_latest; - } - } else { - // If no tag was present, by default we keep source bank in - // statepoint file and write it out at statepoints intervals - source_separate = false; - sourcepoint_batch = statepoint_batch; - } - - // If source is not seperate and is to be written out in the statepoint file, - // make sure that the sourcepoint batch numbers are contained in the - // statepoint list - if (!source_separate) { - for (const auto& b : sourcepoint_batch) { - if (!contains(statepoint_batch, b)) { - fatal_error("Sourcepoint batches are not a subset of statepoint batches."); - } - } - } - - // Check if the user has specified to not reduce tallies at the end of every - // batch - if (check_for_node(root, "no_reduce")) { - reduce_tallies = get_node_value_bool(root, "no_reduce"); - } - - // Check if the user has specified to use confidence intervals for - // uncertainties rather than standard deviations - if (check_for_node(root, "confidence_intervals")) { - confidence_intervals = get_node_value_bool(root, "confidence_intervals"); - } - - // Check for output options - if (check_for_node(root, "output")) { - // Get pointer to output node - pugi::xml_node node_output = root.child("output"); - - // Check for summary option - if (check_for_node(node_output, "summary")) { - output_summary = get_node_value_bool(node_output, "summary"); - } - - // Check for ASCII tallies output option - if (check_for_node(node_output, "tallies")) { - output_tallies = get_node_value_bool(node_output, "tallies"); - } - - // Set output directory if a path has been specified - if (check_for_node(node_output, "path")) { - path_output = get_node_value(node_output, "path"); - if (!ends_with(path_output, "/")) { - path_output += "/"; - } - } - } - - // Resonance scattering parameters - if (check_for_node(root, "resonance_scattering")) { - xml_node node_res_scat = root.child("resonance_scattering"); - - // See if resonance scattering is enabled - if (check_for_node(node_res_scat, "enable")) { - res_scat_on = get_node_value_bool(node_res_scat, "enable"); - } else { - res_scat_on = true; - } - - // Determine what method is used - if (check_for_node(node_res_scat, "method")) { - auto temp = get_node_value(node_res_scat, "method", true, true); - if (temp == "rvs") { - res_scat_method = ResScatMethod::rvs; - } else if (temp == "dbrc") { - res_scat_method = ResScatMethod::dbrc; - } else { - fatal_error("Unrecognized resonance elastic scattering method: " - + temp + "."); - } - } - - // Minimum energy for resonance scattering - if (check_for_node(node_res_scat, "energy_min")) { - res_scat_energy_min = std::stod(get_node_value(node_res_scat, "energy_min")); - } - if (res_scat_energy_min < 0.0) { - fatal_error("Lower resonance scattering energy bound is negative"); - } - - // Maximum energy for resonance scattering - if (check_for_node(node_res_scat, "energy_max")) { - res_scat_energy_max = std::stod(get_node_value(node_res_scat, "energy_max")); - } - if (res_scat_energy_max < res_scat_energy_min) { - fatal_error("Upper resonance scattering energy bound is below the " - "lower resonance scattering energy bound."); - } - - // Get resonance scattering nuclides - if (check_for_node(node_res_scat, "nuclides")) { - res_scat_nuclides = get_node_array(node_res_scat, "nuclides"); - } - } - - // Get volume calculations - for (pugi::xml_node node_vol : root.children("volume_calc")) { - model::volume_calcs.emplace_back(node_vol); - } - - // Get temperature settings - if (check_for_node(root, "temperature_default")) { - temperature_default = std::stod(get_node_value(root, "temperature_default")); - } - if (check_for_node(root, "temperature_method")) { - auto temp = get_node_value(root, "temperature_method", true, true); - if (temp == "nearest") { - temperature_method = TEMPERATURE_NEAREST; - } else if (temp == "interpolation") { - temperature_method = TEMPERATURE_INTERPOLATION; - } else { - fatal_error("Unknown temperature method: " + temp); - } - } - if (check_for_node(root, "temperature_tolerance")) { - temperature_tolerance = std::stod(get_node_value(root, "temperature_tolerance")); - } - if (check_for_node(root, "temperature_multipole")) { - temperature_multipole = get_node_value_bool(root, "temperature_multipole"); - } - if (check_for_node(root, "temperature_range")) { - auto range = get_node_array(root, "temperature_range"); - temperature_range[0] = range.at(0); - temperature_range[1] = range.at(1); - } - - // Check for tabular_legendre options - if (check_for_node(root, "tabular_legendre")) { - // Get pointer to tabular_legendre node - xml_node node_tab_leg = root.child("tabular_legendre"); - - // Check for enable option - if (check_for_node(node_tab_leg, "enable")) { - legendre_to_tabular = get_node_value_bool(node_tab_leg, "enable"); - } - - // Check for the number of points - if (check_for_node(node_tab_leg, "num_points")) { - legendre_to_tabular_points = std::stoi(get_node_value( - node_tab_leg, "num_points")); - if (legendre_to_tabular_points <= 1 && !run_CE) { - fatal_error("The 'num_points' subelement/attribute of the " - " element must contain a value greater than 1"); - } - } - } - - // Check whether create fission sites - if (run_mode == RUN_MODE_FIXEDSOURCE) { - if (check_for_node(root, "create_fission_neutrons")) { - create_fission_neutrons = get_node_value_bool(root, "create_fission_neutrons"); - } - } -} - -void free_memory_settings() { - settings::statepoint_batch.clear(); - settings::sourcepoint_batch.clear(); - settings::res_scat_nuclides.clear(); -} - -} // namespace openmc diff --git a/src/simulation.cpp b/src/simulation.cpp deleted file mode 100644 index 8de1e7fbc..000000000 --- a/src/simulation.cpp +++ /dev/null @@ -1,573 +0,0 @@ -#include "openmc/simulation.h" - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/container_util.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/particle.h" -#include "openmc/photon.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/source.h" -#include "openmc/state_point.h" -#include "openmc/timer.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/tally.h" -#include "openmc/tallies/trigger.h" - -#ifdef _OPENMP -#include -#endif -#include "xtensor/xview.hpp" - -#include -#include - -//============================================================================== -// C API functions -//============================================================================== - -// OPENMC_RUN encompasses all the main logic where iterations are performed -// over the batches, generations, and histories in a fixed source or k-eigenvalue -// calculation. - -int openmc_run() -{ - openmc_simulation_init(); - - int err = 0; - int status = 0; - while (status == 0 && err == 0) { - err = openmc_next_batch(&status); - } - - openmc_simulation_finalize(); - return err; -} - -int openmc_simulation_init() -{ - using namespace openmc; - - // Skip if simulation has already been initialized - if (simulation::initialized) return 0; - - // Determine how much work each process should do - calculate_work(); - - // Allocate array for matching filter bins - #pragma omp parallel - { - simulation::filter_matches.resize(model::tally_filters.size()); - } - - // Allocate source bank, and for eigenvalue simulations also allocate the - // fission bank - allocate_banks(); - - // Allocate tally results arrays if they're not allocated yet - for (auto& t : model::tallies) { - t->init_results(); - } - - // Set up material nuclide index mapping - for (auto& mat : model::materials) { - mat->init_nuclide_index(); - } - - // Reset global variables -- this is done before loading state point (as that - // will potentially populate k_generation and entropy) - simulation::current_batch = 0; - simulation::k_generation.clear(); - simulation::entropy.clear(); - simulation::need_depletion_rx = false; - openmc_reset(); - - // If this is a restart run, load the state point data and binary source - // file - if (settings::restart_run) { - load_state_point(); - write_message("Resuming simulation...", 6); - } else { - initialize_source(); - } - - // Display header - if (mpi::master) { - if (settings::run_mode == RUN_MODE_FIXEDSOURCE) { - header("FIXED SOURCE TRANSPORT SIMULATION", 3); - } else if (settings::run_mode == RUN_MODE_EIGENVALUE) { - header("K EIGENVALUE SIMULATION", 3); - if (settings::verbosity >= 7) print_columns(); - } - } - - // Set flag indicating initialization is done - simulation::initialized = true; - return 0; -} - -int openmc_simulation_finalize() -{ - using namespace openmc; - - // Skip if simulation was never run - if (!simulation::initialized) return 0; - - // Stop active batch timer and start finalization timer - simulation::time_active.stop(); - simulation::time_finalize.start(); - - // Clear material nuclide mapping - for (auto& mat : model::materials) { - mat->mat_nuclide_index_.clear(); - } - - // Increment total number of generations - simulation::total_gen += simulation::current_batch*settings::gen_per_batch; - -#ifdef OPENMC_MPI - broadcast_results(); -#endif - - // Write tally results to tallies.out - if (settings::output_tallies && mpi::master) write_tallies(); - - #pragma omp parallel - { - simulation::filter_matches.clear(); - } - - // Deactivate all tallies - for (auto& t : model::tallies) { - t->active_ = false; - } - - // Stop timers and show timing statistics - simulation::time_finalize.stop(); - simulation::time_total.stop(); - if (mpi::master) { - if (settings::verbosity >= 6) print_runtime(); - if (settings::verbosity >= 4) print_results(); - } - if (settings::check_overlaps) print_overlap_check(); - - // Reset flags - simulation::need_depletion_rx = false; - simulation::initialized = false; - return 0; -} - -int openmc_next_batch(int* status) -{ - using namespace openmc; - using openmc::simulation::current_gen; - - // Make sure simulation has been initialized - if (!simulation::initialized) { - set_errmsg("Simulation has not been initialized yet."); - return OPENMC_E_ALLOCATE; - } - - initialize_batch(); - - // ======================================================================= - // LOOP OVER GENERATIONS - for (current_gen = 1; current_gen <= settings::gen_per_batch; ++current_gen) { - - initialize_generation(); - - // Start timer for transport - simulation::time_transport.start(); - - // ==================================================================== - // LOOP OVER PARTICLES - - #pragma omp parallel for schedule(runtime) - for (int64_t i_work = 1; i_work <= simulation::work_per_rank; ++i_work) { - simulation::current_work = i_work; - - // grab source particle from bank - Particle p; - initialize_history(&p, simulation::current_work); - - // transport particle - p.transport(); - } - - // Accumulate time for transport - simulation::time_transport.stop(); - - finalize_generation(); - } - - finalize_batch(); - - // Check simulation ending criteria - if (status) { - if (simulation::current_batch == settings::n_max_batches) { - *status = STATUS_EXIT_MAX_BATCH; - } else if (simulation::satisfy_triggers) { - *status = STATUS_EXIT_ON_TRIGGER; - } else { - *status = STATUS_EXIT_NORMAL; - } - } - return 0; -} - -bool openmc_is_statepoint_batch() { - using namespace openmc; - using openmc::simulation::current_gen; - - if (!simulation::initialized) - return false; - else - return contains(settings::statepoint_batch, simulation::current_batch); -} - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -int current_batch; -int current_gen; -int64_t current_work; -bool initialized {false}; -double keff {1.0}; -double keff_std; -double k_col_abs {0.0}; -double k_col_tra {0.0}; -double k_abs_tra {0.0}; -double log_spacing; -int n_lost_particles {0}; -bool need_depletion_rx {false}; -int restart_batch; -bool satisfy_triggers {false}; -int total_gen {0}; -double total_weight; -int64_t work_per_rank; - -const RegularMesh* entropy_mesh {nullptr}; -const RegularMesh* ufs_mesh {nullptr}; - -std::vector k_generation; -std::vector work_index; - -// Threadprivate variables -bool trace; //!< flag to show debug information - -} // namespace simulation - -//============================================================================== -// Non-member functions -//============================================================================== - -void allocate_banks() -{ - // Allocate source bank - simulation::source_bank.resize(simulation::work_per_rank); - - if (settings::run_mode == RUN_MODE_EIGENVALUE) { -#ifdef _OPENMP - // If OpenMP is being used, each thread needs its own private fission - // bank. Since the private fission banks need to be combined at the end of - // a generation, there is also a 'master_fission_bank' that is used to - // collect the sites from each thread. - - #pragma omp parallel - { - if (omp_get_thread_num() == 0) { - simulation::fission_bank.reserve(3*simulation::work_per_rank); - } else { - int n_threads = omp_get_num_threads(); - simulation::fission_bank.reserve(3*simulation::work_per_rank / n_threads); - } - } - simulation::master_fission_bank.reserve(3*simulation::work_per_rank); -#else - simulation::fission_bank.reserve(3*simulation::work_per_rank); -#endif - } -} - -void initialize_batch() -{ - // Increment current batch - ++simulation::current_batch; - - if (settings::run_mode == RUN_MODE_FIXEDSOURCE) { - int b = simulation::current_batch; - write_message("Simulating batch " + std::to_string(b), 6); - } - - // Reset total starting particle weight used for normalizing tallies - simulation::total_weight = 0.0; - - // Determine if this batch is the first inactive or active batch. - bool first_inactive = false; - bool first_active = false; - if (!settings::restart_run) { - first_inactive = settings::n_inactive > 0 && simulation::current_batch == 1; - first_active = simulation::current_batch == settings::n_inactive + 1; - } else if (simulation::current_batch == simulation::restart_batch + 1){ - first_inactive = simulation::restart_batch < settings::n_inactive; - first_active = !first_inactive; - } - - // Manage active/inactive timers and activate tallies if necessary. - if (first_inactive) { - simulation::time_inactive.start(); - } else if (first_active) { - simulation::time_inactive.stop(); - simulation::time_active.start(); - for (auto& t : model::tallies) { - t->active_ = true; - } - } - - // Add user tallies to active tallies list - setup_active_tallies(); -} - -void finalize_batch() -{ - // Reduce tallies onto master process and accumulate - simulation::time_tallies.start(); - accumulate_tallies(); - simulation::time_tallies.stop(); - - // Reset global tally results - if (simulation::current_batch <= settings::n_inactive) { - xt::view(simulation::global_tallies, xt::all()) = 0.0; - simulation::n_realizations = 0; - } - - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - // Write batch output - if (mpi::master && settings::verbosity >= 7) print_batch_keff(); - } - - // Check_triggers - if (mpi::master) check_triggers(); -#ifdef OPENMC_MPI - MPI_Bcast(&simulation::satisfy_triggers, 1, MPI_C_BOOL, 0, mpi::intracomm); -#endif - if (simulation::satisfy_triggers || (settings::trigger_on && - simulation::current_batch == settings::n_max_batches)) { - settings::statepoint_batch.insert(simulation::current_batch); - } - - // Write out state point if it's been specified for this batch and is not - // a CMFD run instance - if (contains(settings::statepoint_batch, simulation::current_batch) - && !settings::cmfd_run) { - if (contains(settings::sourcepoint_batch, simulation::current_batch) - && settings::source_write && !settings::source_separate) { - bool b = true; - openmc_statepoint_write(nullptr, &b); - } else { - bool b = false; - openmc_statepoint_write(nullptr, &b); - } - } - - // Write out a separate source point if it's been specified for this batch - if (contains(settings::sourcepoint_batch, simulation::current_batch) - && settings::source_write && settings::source_separate) { - write_source_point(nullptr); - } - - // Write a continously-overwritten source point if requested. - if (settings::source_latest) { - auto filename = settings::path_output + "source.h5"; - write_source_point(filename.c_str()); - } -} - -void initialize_generation() -{ - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - // Clear out the fission bank - simulation::fission_bank.clear(); - - // Count source sites if using uniform fission source weighting - if (settings::ufs_on) ufs_count_sites(); - - // Store current value of tracklength k - simulation::keff_generation = simulation::global_tallies( - K_TRACKLENGTH, RESULT_VALUE); - } -} - -void finalize_generation() -{ - auto& gt = simulation::global_tallies; - - // Update global tallies with the omp private accumulation variables - #pragma omp parallel - { - #pragma omp critical(increment_global_tallies) - { - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - gt(K_COLLISION, RESULT_VALUE) += global_tally_collision; - gt(K_ABSORPTION, RESULT_VALUE) += global_tally_absorption; - gt(K_TRACKLENGTH, RESULT_VALUE) += global_tally_tracklength; - } - gt(LEAKAGE, RESULT_VALUE) += global_tally_leakage; - } - - // reset threadprivate tallies - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - global_tally_collision = 0.0; - global_tally_absorption = 0.0; - global_tally_tracklength = 0.0; - } - global_tally_leakage = 0.0; - } - - - if (settings::run_mode == RUN_MODE_EIGENVALUE) { -#ifdef _OPENMP - // Join the fission bank from each thread into one global fission bank - join_bank_from_threads(); -#endif - - // Distribute fission bank across processors evenly - synchronize_bank(); - - // Calculate shannon entropy - if (settings::entropy_on) shannon_entropy(); - - // Collect results and statistics - calculate_generation_keff(); - calculate_average_keff(); - - // Write generation output - if (mpi::master && settings::verbosity >= 7) { - if (simulation::current_gen != settings::gen_per_batch) { - print_generation(); - } - } - - } else if (settings::run_mode == RUN_MODE_FIXEDSOURCE) { - // For fixed-source mode, we need to sample the external source - fill_source_bank_fixedsource(); - } -} - -void initialize_history(Particle* p, int64_t index_source) -{ - // set defaults - p->from_source(&simulation::source_bank[index_source - 1]); - - // set identifier for particle - p->id_ = simulation::work_index[mpi::rank] + index_source; - - // set random number seed - int64_t particle_seed = (simulation::total_gen + overall_generation() - 1) - * settings::n_particles + p->id_; - set_particle_seed(particle_seed); - - // set particle trace - simulation::trace = false; - if (simulation::current_batch == settings::trace_batch && - simulation::current_gen == settings::trace_gen && - p->id_ == settings::trace_particle) simulation::trace = true; - - // Set particle track. - p->write_track_ = false; - if (settings::write_all_tracks) { - p->write_track_ = true; - } else if (settings::track_identifiers.size() > 0) { - for (const auto& t : settings::track_identifiers) { - if (simulation::current_batch == t[0] && - simulation::current_gen == t[1] && - p->id_ == t[2]) { - p->write_track_ = true; - break; - } - } - } -} - -int overall_generation() -{ - using namespace simulation; - return settings::gen_per_batch*(current_batch - 1) + current_gen; -} - -void calculate_work() -{ - // Determine minimum amount of particles to simulate on each processor - int64_t min_work = settings::n_particles / mpi::n_procs; - - // Determine number of processors that have one extra particle - int64_t remainder = settings::n_particles % mpi::n_procs; - - int64_t i_bank = 0; - simulation::work_index.resize(mpi::n_procs + 1); - simulation::work_index[0] = 0; - for (int i = 0; i < mpi::n_procs; ++i) { - // Number of particles for rank i - int64_t work_i = i < remainder ? min_work + 1 : min_work; - - // Set number of particles - if (mpi::rank == i) simulation::work_per_rank = work_i; - - // Set index into source bank for rank i - i_bank += work_i; - simulation::work_index[i + 1] = i_bank; - } -} - -#ifdef OPENMC_MPI -void broadcast_results() { - // Broadcast tally results so that each process has access to results - for (auto& t : model::tallies) { - // Create a new datatype that consists of all values for a given filter - // bin and then use that to broadcast. This is done to minimize the - // chance of the 'count' argument of MPI_BCAST exceeding 2**31 - auto& results = t->results_; - - auto shape = results.shape(); - int count_per_filter = shape[1] * shape[2]; - MPI_Datatype result_block; - MPI_Type_contiguous(count_per_filter, MPI_DOUBLE, &result_block); - MPI_Type_commit(&result_block); - MPI_Bcast(results.data(), shape[0], result_block, 0, mpi::intracomm); - MPI_Type_free(&result_block); - } - - // Also broadcast global tally results - auto& gt = simulation::global_tallies; - MPI_Bcast(gt.data(), gt.size(), MPI_DOUBLE, 0, mpi::intracomm); - - // These guys are needed so that non-master processes can calculate the - // combined estimate of k-effective - double temp[] {simulation::k_col_abs, simulation::k_col_tra, - simulation::k_abs_tra}; - MPI_Bcast(temp, 3, MPI_DOUBLE, 0, mpi::intracomm); - simulation::k_col_abs = temp[0]; - simulation::k_col_tra = temp[1]; - simulation::k_abs_tra = temp[2]; -} - -#endif - -void free_memory_simulation() -{ - simulation::k_generation.clear(); - simulation::entropy.clear(); -} - -} // namespace openmc diff --git a/src/source.cpp b/src/source.cpp deleted file mode 100644 index 0baa21b17..000000000 --- a/src/source.cpp +++ /dev/null @@ -1,345 +0,0 @@ -#include "openmc/source.h" - -#include // for move -#include // for stringstream - -#include "xtensor/xadapt.hpp" - -#include "openmc/bank.h" -#include "openmc/cell.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/capi.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/state_point.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - -std::vector external_sources; - -} - -//============================================================================== -// SourceDistribution implementation -//============================================================================== - -SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy) - : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { } - -SourceDistribution::SourceDistribution(pugi::xml_node node) -{ - // Check for particle type - if (check_for_node(node, "particle")) { - auto temp_str = get_node_value(node, "particle", true, true); - if (temp_str == "neutron") { - particle_ = Particle::Type::neutron; - } else if (temp_str == "photon") { - particle_ = Particle::Type::photon; - settings::photon_transport = true; - } else { - fatal_error(std::string("Unknown source particle type: ") + temp_str); - } - } - - // Check for source strength - if (check_for_node(node, "strength")) { - strength_ = std::stod(get_node_value(node, "strength")); - } - - // Check for external source file - if (check_for_node(node, "file")) { - // Copy path of source file - settings::path_source = get_node_value(node, "file", false, true); - - // Check if source file exists - if (!file_exists(settings::path_source)) { - std::stringstream msg; - msg << "Source file '" << settings::path_source << "' does not exist."; - fatal_error(msg); - } - - } else { - - // Spatial distribution for external source - if (check_for_node(node, "space")) { - // Get pointer to spatial distribution - pugi::xml_node node_space = node.child("space"); - - // Check for type of spatial distribution and read - std::string type; - if (check_for_node(node_space, "type")) - type = get_node_value(node_space, "type", true, true); - if (type == "cartesian") { - space_ = UPtrSpace{new CartesianIndependent(node_space)}; - } else if (type == "box") { - space_ = UPtrSpace{new SpatialBox(node_space)}; - } else if (type == "fission") { - space_ = UPtrSpace{new SpatialBox(node_space, true)}; - } else if (type == "point") { - space_ = UPtrSpace{new SpatialPoint(node_space)}; - } else { - std::stringstream msg; - msg << "Invalid spatial distribution for external source: " << type; - fatal_error(msg); - } - - } else { - // If no spatial distribution specified, make it a point source - space_ = UPtrSpace{new SpatialPoint()}; - } - - // Determine external source angular distribution - if (check_for_node(node, "angle")) { - // Get pointer to angular distribution - pugi::xml_node node_angle = node.child("angle"); - - // Check for type of angular distribution - std::string type; - if (check_for_node(node_angle, "type")) - type = get_node_value(node_angle, "type", true, true); - if (type == "isotropic") { - angle_ = UPtrAngle{new Isotropic()}; - } else if (type == "monodirectional") { - angle_ = UPtrAngle{new Monodirectional(node_angle)}; - } else if (type == "mu-phi") { - angle_ = UPtrAngle{new PolarAzimuthal(node_angle)}; - } else { - std::stringstream msg; - msg << "Invalid angular distribution for external source: " << type; - fatal_error(msg); - } - - } else { - angle_ = UPtrAngle{new Isotropic()}; - } - - // Determine external source energy distribution - if (check_for_node(node, "energy")) { - pugi::xml_node node_dist = node.child("energy"); - energy_ = distribution_from_xml(node_dist); - } else { - // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1 - energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)}; - } - } -} - - -Particle::Bank SourceDistribution::sample() const -{ - Particle::Bank site; - - // Set weight to one by default - site.wgt = 1.0; - - // Repeat sampling source location until a good site has been found - bool found = false; - int n_reject = 0; - static int n_accept = 0; - while (!found) { - // Set particle type - site.particle = particle_; - - // Sample spatial distribution - site.r = space_->sample(); - double xyz[] {site.r.x, site.r.y, site.r.z}; - - // Now search to see if location exists in geometry - int32_t cell_index, instance; - int err = openmc_find_cell(xyz, &cell_index, &instance); - found = (err != OPENMC_E_GEOMETRY); - - // Check if spatial site is in fissionable material - if (found) { - auto space_box = dynamic_cast(space_.get()); - if (space_box) { - if (space_box->only_fissionable()) { - // Determine material - const auto& c = model::cells[cell_index]; - auto mat_index = c->material_.size() == 1 - ? c->material_[0] : c->material_[instance]; - - if (mat_index == MATERIAL_VOID) { - found = false; - } else { - if (!model::materials[mat_index]->fissionable_) found = false; - } - } - } - } - - // Check for rejection - if (!found) { - ++n_reject; - if (n_reject >= EXTSRC_REJECT_THRESHOLD && - static_cast(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) { - fatal_error("More than 95% of external source sites sampled were " - "rejected. Please check your external source definition."); - } - } - } - - // Increment number of accepted samples - ++n_accept; - - // Sample angle - site.u = angle_->sample(); - - // Check for monoenergetic source above maximum particle energy - auto p = static_cast(particle_); - auto energy_ptr = dynamic_cast(energy_.get()); - if (energy_ptr) { - auto energies = xt::adapt(energy_ptr->x()); - if (xt::any(energies > data::energy_max[p])) { - fatal_error("Source energy above range of energies of at least " - "one cross section table"); - } else if (xt::any(energies < data::energy_min[p])) { - fatal_error("Source energy below range of energies of at least " - "one cross section table"); - } - } - - while (true) { - // Sample energy spectrum - site.E = energy_->sample(); - - // Resample if energy falls outside minimum or maximum particle energy - if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break; - } - - // Set delayed group - site.delayed_group = 0; - - return site; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void initialize_source() -{ - write_message("Initializing source particles...", 5); - - if (settings::path_source != "") { - // Read the source from a binary file instead of sampling from some - // assumed source distribution - - std::stringstream msg; - msg << "Reading source file from " << settings::path_source << "..."; - write_message(msg, 6); - - // Open the binary file - hid_t file_id = file_open(settings::path_source, 'r', true); - - // Read the file type - std::string filetype; - read_attribute(file_id, "filetype", filetype); - - // Check to make sure this is a source file - if (filetype != "source" && filetype != "statepoint") { - fatal_error("Specified starting source file not a source file type."); - } - - // Read in the source bank - read_source_bank(file_id); - - // Close file - file_close(file_id); - - } else { - // Generation source sites from specified distribution in user input - for (int64_t i = 0; i < simulation::work_per_rank; ++i) { - // initialize random number seed - int64_t id = simulation::total_gen*settings::n_particles + - simulation::work_index[mpi::rank] + i + 1; - set_particle_seed(id); - - // sample external source distribution - simulation::source_bank[i] = sample_external_source(); - } - } - - // Write out initial source - if (settings::write_initial_source) { - write_message("Writing out initial source...", 5); - std::string filename = settings::path_output + "initial_source.h5"; - hid_t file_id = file_open(filename, 'w', true); - write_source_bank(file_id); - file_close(file_id); - } -} - -Particle::Bank sample_external_source() -{ - // Set the random number generator to the source stream. - prn_set_stream(STREAM_SOURCE); - - // Determine total source strength - double total_strength = 0.0; - for (auto& s : model::external_sources) - total_strength += s.strength(); - - // Sample from among multiple source distributions - int i = 0; - if (model::external_sources.size() > 1) { - double xi = prn()*total_strength; - double c = 0.0; - for (; i < model::external_sources.size(); ++i) { - c += model::external_sources[i].strength(); - if (xi < c) break; - } - } - - // Sample source site from i-th source distribution - Particle::Bank site {model::external_sources[i].sample()}; - - // If running in MG, convert site % E to group - if (!settings::run_CE) { - site.E = lower_bound_index(data::rev_energy_bins.begin(), - data::rev_energy_bins.end(), site.E); - site.E = data::num_energy_groups - site.E; - } - - // Set the random number generator back to the tracking stream. - prn_set_stream(STREAM_TRACKING); - - return site; -} - -void free_memory_source() -{ - model::external_sources.clear(); -} - -void fill_source_bank_fixedsource() -{ - if (settings::path_source.empty()) { - for (int64_t i = 0; i < simulation::work_per_rank; ++i) { - // initialize random number seed - int64_t id = (simulation::total_gen + overall_generation()) * - settings::n_particles + simulation::work_index[mpi::rank] + i + 1; - set_particle_seed(id); - - // sample external source distribution - simulation::source_bank[i] = sample_external_source(); - } - } -} - -} // namespace openmc diff --git a/src/state_point.cpp b/src/state_point.cpp deleted file mode 100644 index cd2c475d8..000000000 --- a/src/state_point.cpp +++ /dev/null @@ -1,778 +0,0 @@ -#include "openmc/state_point.h" - -#include -#include // for int64_t -#include // for setfill, setw -#include -#include - -#include "xtensor/xbuilder.hpp" // for empty_like -#include "xtensor/xview.hpp" - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/eigenvalue.h" -#include "openmc/error.h" -#include "openmc/hdf5_interface.h" -#include "openmc/mesh.h" -#include "openmc/message_passing.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/tallies/derivative.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/tally.h" -#include "openmc/timer.h" - -namespace openmc { - -extern "C" int -openmc_statepoint_write(const char* filename, bool* write_source) -{ - // Set the filename - std::string filename_; - if (filename) { - filename_ = filename; - } else { - // Determine width for zero padding - int w = std::to_string(settings::n_max_batches).size(); - - // Set filename for state point - std::stringstream ss; - ss << settings::path_output << "statepoint." << std::setfill('0') - << std::setw(w) << simulation::current_batch << ".h5"; - filename_ = ss.str(); - } - - // Determine whether or not to write the source bank - bool write_source_ = write_source ? *write_source : true; - - // Write message - write_message("Creating state point " + filename_ + "...", 5); - - hid_t file_id; - if (mpi::master) { - // Create statepoint file - file_id = file_open(filename_, 'w'); - - // Write file type - write_attribute(file_id, "filetype", "statepoint"); - - // Write revision number for state point file - write_attribute(file_id, "version", VERSION_STATEPOINT); - - // Write OpenMC version - write_attribute(file_id, "openmc_version", VERSION); -#ifdef GIT_SHA1 - write_attribute(file_id, "git_sha1", GIT_SHA1); -#endif - - // Write current date and time - write_attribute(file_id, "date_and_time", time_stamp()); - - // Write path to input - write_attribute(file_id, "path", settings::path_input); - - // Write out random number seed - write_dataset(file_id, "seed", openmc_get_seed()); - - // Write run information - write_dataset(file_id, "energy_mode", settings::run_CE ? - "continuous-energy" : "multi-group"); - switch (settings::run_mode) { - case RUN_MODE_FIXEDSOURCE: - write_dataset(file_id, "run_mode", "fixed source"); - break; - case RUN_MODE_EIGENVALUE: - write_dataset(file_id, "run_mode", "eigenvalue"); - break; - } - write_attribute(file_id, "photon_transport", settings::photon_transport); - write_dataset(file_id, "n_particles", settings::n_particles); - write_dataset(file_id, "n_batches", settings::n_batches); - - // Write out current batch number - write_dataset(file_id, "current_batch", simulation::current_batch); - - // Indicate whether source bank is stored in statepoint - write_attribute(file_id, "source_present", write_source_); - - // Write out information for eigenvalue run - if (settings::run_mode == RUN_MODE_EIGENVALUE) - write_eigenvalue_hdf5(file_id); - - hid_t tallies_group = create_group(file_id, "tallies"); - - // Write meshes - meshes_to_hdf5(tallies_group); - - // Write information for derivatives - if (!model::tally_derivs.empty()) { - hid_t derivs_group = create_group(tallies_group, "derivatives"); - for (const auto& deriv : model::tally_derivs) { - hid_t deriv_group = create_group(derivs_group, - "derivative " + std::to_string(deriv.id)); - write_dataset(deriv_group, "material", deriv.diff_material); - if (deriv.variable == DIFF_DENSITY) { - write_dataset(deriv_group, "independent variable", "density"); - } else if (deriv.variable == DIFF_NUCLIDE_DENSITY) { - write_dataset(deriv_group, "independent variable", "nuclide_density"); - write_dataset(deriv_group, "nuclide", - data::nuclides[deriv.diff_nuclide]->name_); - } else if (deriv.variable == DIFF_TEMPERATURE) { - write_dataset(deriv_group, "independent variable", "temperature"); - } else { - fatal_error("Independent variable for derivative " - + std::to_string(deriv.id) + " not defined in state_point.cpp"); - } - close_group(deriv_group); - } - close_group(derivs_group); - } - - // Write information for filters - hid_t filters_group = create_group(tallies_group, "filters"); - write_attribute(filters_group, "n_filters", model::tally_filters.size()); - if (!model::tally_filters.empty()) { - // Write filter IDs - std::vector filter_ids; - filter_ids.reserve(model::tally_filters.size()); - for (const auto& filt : model::tally_filters) - filter_ids.push_back(filt->id()); - write_attribute(filters_group, "ids", filter_ids); - - // Write info for each filter - for (const auto& filt : model::tally_filters) { - hid_t filter_group = create_group(filters_group, - "filter " + std::to_string(filt->id())); - filt->to_statepoint(filter_group); - close_group(filter_group); - } - } - close_group(filters_group); - - // Write information for tallies - write_attribute(tallies_group, "n_tallies", model::tallies.size()); - if (!model::tallies.empty()) { - // Write tally IDs - std::vector tally_ids; - tally_ids.reserve(model::tallies.size()); - for (const auto& tally : model::tallies) - tally_ids.push_back(tally->id_); - write_attribute(tallies_group, "ids", tally_ids); - - // Write all tally information except results - for (const auto& tally : model::tallies) { - hid_t tally_group = create_group(tallies_group, - "tally " + std::to_string(tally->id_)); - - write_dataset(tally_group, "name", tally->name_); - - if (tally->writable_) { - write_attribute(tally_group, "internal", 0); - } else { - write_attribute(tally_group, "internal", 1); - close_group(tally_group); - continue; - } - - if (tally->estimator_ == ESTIMATOR_ANALOG) { - write_dataset(tally_group, "estimator", "analog"); - } else if (tally->estimator_ == ESTIMATOR_TRACKLENGTH) { - write_dataset(tally_group, "estimator", "tracklength"); - } else if (tally->estimator_ == ESTIMATOR_COLLISION) { - write_dataset(tally_group, "estimator", "collision"); - } - - write_dataset(tally_group, "n_realizations", tally->n_realizations_); - - // Write the ID of each filter attached to this tally - write_dataset(tally_group, "n_filters", tally->filters().size()); - if (!tally->filters().empty()) { - std::vector filter_ids; - filter_ids.reserve(tally->filters().size()); - for (auto i_filt : tally->filters()) - filter_ids.push_back(model::tally_filters[i_filt]->id()); - write_dataset(tally_group, "filters", filter_ids); - } - - // Write the nuclides this tally scores - std::vector nuclides; - for (auto i_nuclide : tally->nuclides_) { - if (i_nuclide == -1) { - nuclides.push_back("total"); - } else { - if (settings::run_CE) { - nuclides.push_back(data::nuclides[i_nuclide]->name_); - } else { - nuclides.push_back(data::nuclides_MG[i_nuclide].name); - } - } - } - write_dataset(tally_group, "nuclides", nuclides); - - if (tally->deriv_ != C_NONE) write_dataset(tally_group, "derivative", - model::tally_derivs[tally->deriv_].id); - - // Write the tally score bins - std::vector scores; - for (auto sc : tally->scores_) scores.push_back(reaction_name(sc)); - write_dataset(tally_group, "n_score_bins", scores.size()); - write_dataset(tally_group, "score_bins", scores); - - close_group(tally_group); - } - - } - - if (settings::reduce_tallies) { - // Write global tallies - write_dataset(file_id, "global_tallies", simulation::global_tallies); - - // Write tallies - if (model::active_tallies.size() > 0) { - // Indicate that tallies are on - write_attribute(file_id, "tallies_present", 1); - - // Write all tally results - for (const auto& tally : model::tallies) { - if (!tally->writable_) continue; - // Write sum and sum_sq for each bin - std::string name = "tally " + std::to_string(tally->id_); - hid_t tally_group = open_group(tallies_group, name.c_str()); - auto& results = tally->results_; - write_tally_results(tally_group, results.shape()[0], - results.shape()[1], results.data()); - close_group(tally_group); - } - } else { - // Indicate tallies are off - write_attribute(file_id, "tallies_present", 0); - } - } - - close_group(tallies_group); - } - - // Check for the no-tally-reduction method - if (!settings::reduce_tallies) { - // If using the no-tally-reduction method, we need to collect tally - // results before writing them to the state point file. - write_tally_results_nr(file_id); - - } else if (mpi::master) { - // Write number of global realizations - write_dataset(file_id, "n_realizations", simulation::n_realizations); - - // Write out the runtime metrics. - using namespace simulation; - hid_t runtime_group = create_group(file_id, "runtime"); - write_dataset(runtime_group, "total initialization", time_initialize.elapsed()); - write_dataset(runtime_group, "reading cross sections", time_read_xs.elapsed()); - write_dataset(runtime_group, "simulation", time_inactive.elapsed() - + time_active.elapsed()); - write_dataset(runtime_group, "transport", time_transport.elapsed()); - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - write_dataset(runtime_group, "inactive batches", time_inactive.elapsed()); - } - write_dataset(runtime_group, "active batches", time_active.elapsed()); - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - write_dataset(runtime_group, "synchronizing fission bank", time_bank.elapsed()); - write_dataset(runtime_group, "sampling source sites", time_bank_sample.elapsed()); - write_dataset(runtime_group, "SEND-RECV source sites", time_bank_sendrecv.elapsed()); - } - write_dataset(runtime_group, "accumulating tallies", time_tallies.elapsed()); - write_dataset(runtime_group, "total", time_total.elapsed()); - close_group(runtime_group); - - file_close(file_id); - } - -#ifdef PHDF5 - bool parallel = true; -#else - bool parallel = false; -#endif - - // Write the source bank if desired - if (write_source_) { - if (mpi::master || parallel) file_id = file_open(filename_, 'a', true); - write_source_bank(file_id); - if (mpi::master || parallel) file_close(file_id); - } - - return 0; -} - -void restart_set_keff() -{ - if (simulation::restart_batch > settings::n_inactive) { - for (int i = settings::n_inactive; i < simulation::restart_batch; ++i) { - simulation::k_sum[0] += simulation::k_generation[i]; - simulation::k_sum[1] += std::pow(simulation::k_generation[i], 2); - } - int n = settings::gen_per_batch*simulation::n_realizations; - simulation::keff = simulation::k_sum[0] / n; - } else { - simulation::keff = simulation::k_generation.back(); - } -} - -void load_state_point() -{ - // Write message - write_message("Loading state point " + settings::path_statepoint + "...", 5); - - // Open file for reading - hid_t file_id = file_open(settings::path_statepoint.c_str(), 'r', true); - - // Read filetype - std::string word; - read_attribute(file_id, "filetype", word); - if (word != "statepoint") { - fatal_error("OpenMC tried to restart from a non-statepoint file."); - } - - // Read revision number for state point file and make sure it matches with - // current version - std::array array; - read_attribute(file_id, "version", array); - if (array != VERSION_STATEPOINT) { - fatal_error("State point version does not match current version in OpenMC."); - } - - // Read and overwrite random number seed - int64_t seed; - read_dataset(file_id, "seed", seed); - openmc_set_seed(seed); - - // It is not impossible for a state point to be generated from a CE run but - // to be loaded in to an MG run (or vice versa), check to prevent that. - read_dataset(file_id, "energy_mode", word); - if (word == "multi-group" && settings::run_CE) { - fatal_error("State point file is from multigroup run but current run is " - "continous energy."); - } else if (word == "continuous-energy" && !settings::run_CE) { - fatal_error("State point file is from continuous-energy run but current " - "run is multigroup!"); - } - - // Read and overwrite run information except number of batches - read_dataset(file_id, "run_mode", word); - if (word == "fixed source") { - settings::run_mode = RUN_MODE_FIXEDSOURCE; - } else if (word == "eigenvalue") { - settings::run_mode = RUN_MODE_EIGENVALUE; - } - read_attribute(file_id, "photon_transport", settings::photon_transport); - read_dataset(file_id, "n_particles", settings::n_particles); - int temp; - read_dataset(file_id, "n_batches", temp); - - // Take maximum of statepoint n_batches and input n_batches - settings::n_batches = std::max(settings::n_batches, temp); - - // Read batch number to restart at - read_dataset(file_id, "current_batch", simulation::restart_batch); - - // Check for source in statepoint if needed - bool source_present; - read_attribute(file_id, "source_present", source_present); - - if (simulation::restart_batch > settings::n_batches) { - fatal_error("The number batches specified in settings.xml is fewer " - " than the number of batches in the given statepoint file."); - } - - // Read information specific to eigenvalue run - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - read_dataset(file_id, "n_inactive", temp); - read_eigenvalue_hdf5(file_id); - - // Take maximum of statepoint n_inactive and input n_inactive - settings::n_inactive = std::max(settings::n_inactive, temp); - } - - // Read number of realizations for global tallies - read_dataset(file_id, "n_realizations", simulation::n_realizations); - - // Set k_sum, keff, and current_batch based on whether restart file is part - // of active cycle or inactive cycle - restart_set_keff(); - simulation::current_batch = simulation::restart_batch; - - // Check to make sure source bank is present - if (settings::path_sourcepoint == settings::path_statepoint && - !source_present) { - fatal_error("Source bank must be contained in statepoint restart file"); - } - - // Read tallies to master. If we are using Parallel HDF5, all processes - // need to be included in the HDF5 calls. -#ifdef PHDF5 - if (true) { -#else - if (mpi::master) { -#endif - // Read global tally data - read_dataset(file_id, "global_tallies", H5T_NATIVE_DOUBLE, - simulation::global_tallies.data(), false); - - // Check if tally results are present - bool present; - read_attribute(file_id, "tallies_present", present); - - // Read in sum and sum squared - if (present) { - hid_t tallies_group = open_group(file_id, "tallies"); - - for (auto& tally : model::tallies) { - // Read sum, sum_sq, and N for each bin - std::string name = "tally " + std::to_string(tally->id_); - hid_t tally_group = open_group(tallies_group, name.c_str()); - - int internal=0; - if (attribute_exists(tally_group, "internal")) { - read_attribute(tally_group, "internal", internal); - } - if (internal) { - tally->writable_ = false; - } else { - - auto& results = tally->results_; - read_tally_results(tally_group, results.shape()[0], - results.shape()[1], results.data()); - read_dataset(tally_group, "n_realizations", tally->n_realizations_); - close_group(tally_group); - } - } - - close_group(tallies_group); - } - } - - // Read source if in eigenvalue mode - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - - // Check if source was written out separately - if (!source_present) { - - // Close statepoint file - file_close(file_id); - - // Write message - write_message("Loading source file " + settings::path_sourcepoint - + "...", 5); - - // Open source file - file_id = file_open(settings::path_source.c_str(), 'r', true); - } - - // Read source - read_source_bank(file_id); - - } - - // Close file - file_close(file_id); -} - - -hid_t h5banktype() { - // Create compound type for position - hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position)); - H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE); - H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE); - H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE); - - // Create bank datatype - hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct Particle::Bank)); - H5Tinsert(banktype, "r", HOFFSET(Particle::Bank, r), postype); - H5Tinsert(banktype, "u", HOFFSET(Particle::Bank, u), postype); - H5Tinsert(banktype, "E", HOFFSET(Particle::Bank, E), H5T_NATIVE_DOUBLE); - H5Tinsert(banktype, "wgt", HOFFSET(Particle::Bank, wgt), H5T_NATIVE_DOUBLE); - H5Tinsert(banktype, "delayed_group", HOFFSET(Particle::Bank, delayed_group), H5T_NATIVE_INT); - H5Tinsert(banktype, "particle", HOFFSET(Particle::Bank, particle), H5T_NATIVE_INT); - - H5Tclose(postype); - return banktype; -} - -void -write_source_point(const char* filename) -{ - // When using parallel HDF5, the file is written to collectively by all - // processes. With MPI-only, the file is opened and written by the master - // (note that the call to write_source_bank is by all processes since slave - // processes need to send source bank data to the master. -#ifdef PHDF5 - bool parallel = true; -#else - bool parallel = false; -#endif - - std::string filename_; - if (filename) { - filename_ = filename; - } else { - // Determine width for zero padding - int w = std::to_string(settings::n_max_batches).size(); - - std::stringstream s; - s << settings::path_output << "source." << std::setfill('0') - << std::setw(w) << simulation::current_batch << ".h5"; - filename_ = s.str(); - } - - hid_t file_id; - if (mpi::master || parallel) { - file_id = file_open(filename_, 'w', true); - write_attribute(file_id, "filetype", "source"); - } - - // Get pointer to source bank and write to file - write_source_bank(file_id); - - if (mpi::master || parallel) file_close(file_id); -} - -void -write_source_bank(hid_t group_id) -{ - hid_t banktype = h5banktype(); - -#ifdef PHDF5 - // Set size of total dataspace for all procs and rank - hsize_t dims[] {static_cast(settings::n_particles)}; - hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - // Create another data space but for each proc individually - hsize_t count[] {static_cast(simulation::work_per_rank)}; - hid_t memspace = H5Screate_simple(1, count, nullptr); - - // Select hyperslab for this dataspace - hsize_t start[] {static_cast(simulation::work_index[mpi::rank])}; - H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Set up the property list for parallel writing - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); - - // Write data to file in parallel - H5Dwrite(dset, banktype, memspace, dspace, plist, simulation::source_bank.data()); - - // Free resources - H5Sclose(dspace); - H5Sclose(memspace); - H5Dclose(dset); - H5Pclose(plist); - -#else - - if (mpi::master) { - // Create dataset big enough to hold all source sites - hsize_t dims[] {static_cast(settings::n_particles)}; - hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - // Save source bank sites since the souce_bank array is overwritten below -#ifdef OPENMC_MPI - std::vector temp_source {simulation::source_bank.begin(), - simulation::source_bank.begin() + simulation::work_per_rank}; -#endif - - for (int i = 0; i < mpi::n_procs; ++i) { - // Create memory space - hsize_t count[] {static_cast(simulation::work_index[i+1] - - simulation::work_index[i])}; - hid_t memspace = H5Screate_simple(1, count, nullptr); - -#ifdef OPENMC_MPI - // Receive source sites from other processes - if (i > 0) - MPI_Recv(simulation::source_bank.data(), count[0], mpi::bank, i, i, - mpi::intracomm, MPI_STATUS_IGNORE); -#endif - - // Select hyperslab for this dataspace - dspace = H5Dget_space(dset); - hsize_t start[] {static_cast(simulation::work_index[i])}; - H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Write data to hyperslab - H5Dwrite(dset, banktype, memspace, dspace, H5P_DEFAULT, - simulation::source_bank.data()); - - H5Sclose(memspace); - H5Sclose(dspace); - } - - // Close all ids - H5Dclose(dset); - -#ifdef OPENMC_MPI - // Restore state of source bank - std::copy(temp_source.begin(), temp_source.end(), simulation::source_bank.begin()); -#endif - } else { -#ifdef OPENMC_MPI - MPI_Send(simulation::source_bank.data(), simulation::work_per_rank, mpi::bank, - 0, mpi::rank, mpi::intracomm); -#endif - } -#endif - - H5Tclose(banktype); -} - - -void read_source_bank(hid_t group_id) -{ - hid_t banktype = h5banktype(); - - // Open the dataset - hid_t dset = H5Dopen(group_id, "source_bank", H5P_DEFAULT); - - // Create another data space but for each proc individually - hsize_t dims[] {static_cast(simulation::work_per_rank)}; - hid_t memspace = H5Screate_simple(1, dims, nullptr); - - // Make sure source bank is big enough - hid_t dspace = H5Dget_space(dset); - hsize_t dims_all[1]; - H5Sget_simple_extent_dims(dspace, dims_all, nullptr); - if (simulation::work_index[mpi::n_procs] > dims_all[0]) { - fatal_error("Number of source sites in source file is less " - "than number of source particles per generation."); - } - - // Select hyperslab for each process - hsize_t start[] {static_cast(simulation::work_index[mpi::rank])}; - H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, dims, nullptr); - -#ifdef PHDF5 - // Read data in parallel - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); - H5Dread(dset, banktype, memspace, dspace, plist, simulation::source_bank.data()); - H5Pclose(plist); -#else - H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, simulation::source_bank.data()); -#endif - - // Close all ids - H5Sclose(dspace); - H5Sclose(memspace); - H5Dclose(dset); - H5Tclose(banktype); -} - -void write_tally_results_nr(hid_t file_id) -{ - // ========================================================================== - // COLLECT AND WRITE GLOBAL TALLIES - - hid_t tallies_group; - if (mpi::master) { - // Write number of realizations - write_dataset(file_id, "n_realizations", simulation::n_realizations); - - // Write number of global tallies - write_dataset(file_id, "n_global_tallies", N_GLOBAL_TALLIES); - - tallies_group = open_group(file_id, "tallies"); - } - - // Get global tallies - auto& gt = simulation::global_tallies; - -#ifdef OPENMC_MPI - // Reduce global tallies - xt::xtensor gt_reduced = xt::empty_like(gt); - MPI_Reduce(gt.data(), gt_reduced.data(), gt.size(), MPI_DOUBLE, - MPI_SUM, 0, mpi::intracomm); - - // Transfer values to value on master - if (mpi::master) { - if (simulation::current_batch == settings::n_max_batches || - simulation::satisfy_triggers) { - std::copy(gt_reduced.begin(), gt_reduced.end(), gt.begin()); - } - } -#endif - - // Write out global tallies sum and sum_sq - if (mpi::master) { - write_dataset(file_id, "global_tallies", gt); - } - - for (const auto& t : model::tallies) { - // Skip any tallies that are not active - if (!t->active_) continue; - if (!t->writable_) continue; - - if (mpi::master && !object_exists(file_id, "tallies_present")) { - write_attribute(file_id, "tallies_present", 1); - } - - // Get view of accumulated tally values - auto values_view = xt::view(t->results_, xt::all(), xt::all(), - xt::range(RESULT_SUM, RESULT_SUM_SQ + 1)); - - // Make copy of tally values in contiguous array - xt::xtensor values = values_view; - - if (mpi::master) { - // Open group for tally - std::string groupname {"tally " + std::to_string(t->id_)}; - hid_t tally_group = open_group(tallies_group, groupname.c_str()); - - // The MPI_IN_PLACE specifier allows the master to copy values into - // a receive buffer without having a temporary variable -#ifdef OPENMC_MPI - MPI_Reduce(MPI_IN_PLACE, values.data(), values.size(), MPI_DOUBLE, - MPI_SUM, 0, mpi::intracomm); -#endif - - // At the end of the simulation, store the results back in the - // regular TallyResults array - if (simulation::current_batch == settings::n_max_batches || - simulation::satisfy_triggers) { - values_view = values; - } - - // Put in temporary tally result - xt::xtensor results_copy = xt::zeros_like(t->results_); - auto copy_view = xt::view(results_copy, xt::all(), xt::all(), - xt::range(RESULT_SUM, RESULT_SUM_SQ + 1)); - copy_view = values; - - // Write reduced tally results to file - auto shape = results_copy.shape(); - write_tally_results(tally_group, shape[0], shape[1], results_copy.data()); - - close_group(tally_group); - } else { - // Receive buffer not significant at other processors -#ifdef OPENMC_MPI - MPI_Reduce(values.data(), nullptr, values.size(), MPI_DOUBLE, MPI_SUM, - 0, mpi::intracomm); -#endif - } - } - - if (mpi::master) { - if (!object_exists(file_id, "tallies_present")) { - // Indicate that tallies are off - write_dataset(file_id, "tallies_present", 0); - } - } -} - -} // namespace openmc diff --git a/src/string_utils.cpp b/src/string_utils.cpp deleted file mode 100644 index 614e38767..000000000 --- a/src/string_utils.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "openmc/string_utils.h" - -#include // for equal -#include // for tolower, isspace -#include - -namespace openmc { - -std::string& strtrim(std::string& s) -{ - const char* t = " \t\n\r\f\v"; - s.erase(s.find_last_not_of(t) + 1); - s.erase(0, s.find_first_not_of(t)); - return s; -} - - -char* strtrim(char* c_str) -{ - std::string std_str; - std_str.assign(c_str); - strtrim(std_str); - int length = std_str.copy(c_str, std_str.size()); - c_str[length] = '\0'; - return c_str; -} - - -std::string to_element(const std::string& name) { - int pos = name.find_first_of("0123456789"); - return name.substr(0, pos); -} - - -void to_lower(std::string& str) -{ - for (int i = 0; i < str.size(); i++) str[i] = std::tolower(str[i]); -} - -int word_count(std::string const& str) -{ - std::stringstream stream(str); - std::string dum; - int count = 0; - while (stream >> dum) {count++;} - return count; -} - -std::vector split(const std::string& in) -{ - std::vector out; - - for (int i = 0; i < in.size(); ) { - // Increment i until we find a non-whitespace character. - if (std::isspace(in[i])) { - i++; - - } else { - // Find the next whitespace character at j. - int j = i + 1; - while (j < in.size() && std::isspace(in[j]) == 0) {j++;} - - // Push-back everything between i and j. - out.push_back(in.substr(i, j-i)); - i = j + 1; // j is whitespace so leapfrog to j+1 - } - } - - return out; -} - -bool ends_with(const std::string& value, const std::string& ending) -{ - if (ending.size() > value.size()) return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); -} - -bool starts_with(const std::string& value, const std::string& beginning) -{ - if (beginning.size() > value.size()) return false; - return std::equal(beginning.begin(), beginning.end(), value.begin()); -} - -} // namespace openmc diff --git a/src/summary.cpp b/src/summary.cpp deleted file mode 100644 index d2721f97e..000000000 --- a/src/summary.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "openmc/summary.h" - -#include "openmc/cell.h" -#include "openmc/hdf5_interface.h" -#include "openmc/lattice.h" -#include "openmc/material.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/surface.h" -#include "openmc/settings.h" - -namespace openmc { - -void write_summary() -{ - // Display output message - write_message("Writing summary.h5 file...", 5); - - // Create a new file using default properties. - hid_t file = file_open("summary.h5", 'w'); - - write_header(file); - write_nuclides(file); - write_geometry(file); - write_materials(file); - - // Terminate access to the file. - file_close(file); -} - -void write_header(hid_t file) -{ - // Write filetype and version info - write_attribute(file, "filetype", "summary"); - write_attribute(file, "version", VERSION_SUMMARY); - write_attribute(file, "openmc_version", VERSION); -#ifdef GIT_SHA1 - write_attribute(file, "git_sha1", GIT_SHA1); -#endif - - // Write current date and time - write_attribute(file, "date_and_time", time_stamp()); -} - -void write_nuclides(hid_t file) -{ - // Build vectors of nuclide names and awrs while only sorting nuclides from - // macroscopics - std::vector nuc_names; - std::vector macro_names; - std::vector awrs; - - for (int i = 0; i < data::nuclides.size(); ++i) { - if (settings::run_CE) { - const auto& nuc {data::nuclides[i]}; - nuc_names.push_back(nuc->name_); - awrs.push_back(nuc->awr_); - } else { - const auto& nuc {data::nuclides_MG[i]}; - if (nuc.awr != MACROSCOPIC_AWR) { - nuc_names.push_back(nuc.name); - awrs.push_back(nuc.awr); - } else { - macro_names.push_back(nuc.name); - } - } - } - - hid_t nuclide_group = create_group(file, "nuclides"); - write_attribute(nuclide_group, "n_nuclides", nuc_names.size()); - hid_t macro_group = create_group(file, "macroscopics"); - write_attribute(macro_group, "n_macroscopics", macro_names.size()); - // Write nuclide names and awrs - if (!nuc_names.empty()) { - // Write useful data from nuclide objects - write_dataset(nuclide_group, "names", nuc_names); - write_dataset(nuclide_group, "awrs", awrs); - } - if (!macro_names.empty()) { - // Write useful data from macroscopic objects - write_dataset(macro_group, "names", macro_names); - } - close_group(nuclide_group); - close_group(macro_group); -} - -void write_geometry(hid_t file) -{ - auto geom_group = create_group(file, "geometry"); - -#ifdef DAGMC - if (settings::dagmc) { - write_attribute(geom_group, "dagmc", 1); - close_group(geom_group); - return; - } -#endif - - write_attribute(geom_group, "n_cells", model::cells.size()); - write_attribute(geom_group, "n_surfaces", model::surfaces.size()); - write_attribute(geom_group, "n_universes", model::universes.size()); - write_attribute(geom_group, "n_lattices", model::lattices.size()); - - auto cells_group = create_group(geom_group, "cells"); - for (const auto& c : model::cells) c->to_hdf5(cells_group); - close_group(cells_group); - - auto surfaces_group = create_group(geom_group, "surfaces"); - for (const auto& surf : model::surfaces) surf->to_hdf5(surfaces_group); - close_group(surfaces_group); - - auto universes_group = create_group(geom_group, "universes"); - for (const auto& u : model::universes) u->to_hdf5(universes_group); - close_group(universes_group); - - auto lattices_group = create_group(geom_group, "lattices"); - for (const auto& lat : model::lattices) lat->to_hdf5(lattices_group); - close_group(lattices_group); - - close_group(geom_group); -} - -void write_materials(hid_t file) -{ - // write number of materials - write_dataset(file, "n_materials", model::materials.size()); - - hid_t materials_group = create_group(file, "materials"); - for (const auto& mat : model::materials) { - mat->to_hdf5(materials_group); - } - close_group(materials_group); -} - -} // namespace openmc diff --git a/src/surface.cpp b/src/surface.cpp deleted file mode 100644 index 235465952..000000000 --- a/src/surface.cpp +++ /dev/null @@ -1,1330 +0,0 @@ -#include "openmc/surface.h" - -#include -#include -#include -#include - -#include "openmc/error.h" -#include "openmc/dagmc.h" -#include "openmc/hdf5_interface.h" -#include "openmc/settings.h" -#include "openmc/string_utils.h" -#include "openmc/xml_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/math_functions.h" - -namespace openmc { - -//============================================================================== -// Module constant definitions -//============================================================================== - -extern "C" const int BC_TRANSMIT {0}; -extern "C" const int BC_VACUUM {1}; -extern "C" const int BC_REFLECT {2}; -extern "C" const int BC_PERIODIC {3}; -extern "C" const int BC_WHITE {4}; -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - std::vector> surfaces; - std::unordered_map surface_map; -} // namespace model - -//============================================================================== -// Helper functions for reading the "coeffs" node of an XML surface element -//============================================================================== - -void read_coeffs(pugi::xml_node surf_node, int surf_id, double &c1) -{ - // Check the given number of coefficients. - std::string coeffs = get_node_value(surf_node, "coeffs"); - int n_words = word_count(coeffs); - if (n_words != 1) { - std::stringstream err_msg; - err_msg << "Surface " << surf_id << " expects 1 coeff but was given " - << n_words; - fatal_error(err_msg); - } - - // Parse the coefficients. - int stat = sscanf(coeffs.c_str(), "%lf", &c1); - if (stat != 1) { - fatal_error("Something went wrong reading surface coeffs"); - } -} - -void read_coeffs(pugi::xml_node surf_node, int surf_id, double &c1, double &c2, - double &c3) -{ - // Check the given number of coefficients. - std::string coeffs = get_node_value(surf_node, "coeffs"); - int n_words = word_count(coeffs); - if (n_words != 3) { - std::stringstream err_msg; - err_msg << "Surface " << surf_id << " expects 3 coeffs but was given " - << n_words; - fatal_error(err_msg); - } - - // Parse the coefficients. - int stat = sscanf(coeffs.c_str(), "%lf %lf %lf", &c1, &c2, &c3); - if (stat != 3) { - fatal_error("Something went wrong reading surface coeffs"); - } -} - -void read_coeffs(pugi::xml_node surf_node, int surf_id, double &c1, double &c2, - double &c3, double &c4) -{ - // Check the given number of coefficients. - std::string coeffs = get_node_value(surf_node, "coeffs"); - int n_words = word_count(coeffs); - if (n_words != 4) { - std::stringstream err_msg; - err_msg << "Surface " << surf_id << " expects 4 coeffs but was given " - << n_words; - fatal_error(err_msg); - } - - // Parse the coefficients. - int stat = sscanf(coeffs.c_str(), "%lf %lf %lf %lf", &c1, &c2, &c3, &c4); - if (stat != 4) { - fatal_error("Something went wrong reading surface coeffs"); - } -} - -void read_coeffs(pugi::xml_node surf_node, int surf_id, double &c1, double &c2, - double &c3, double &c4, double &c5, double &c6, double &c7, - double &c8, double &c9, double &c10) -{ - // Check the given number of coefficients. - std::string coeffs = get_node_value(surf_node, "coeffs"); - int n_words = word_count(coeffs); - if (n_words != 10) { - std::stringstream err_msg; - err_msg << "Surface " << surf_id << " expects 10 coeffs but was given " - << n_words; - fatal_error(err_msg); - } - - // Parse the coefficients. - int stat = sscanf(coeffs.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", - &c1, &c2, &c3, &c4, &c5, &c6, &c7, &c8, &c9, &c10); - if (stat != 10) { - fatal_error("Something went wrong reading surface coeffs"); - } -} - -//============================================================================== -// Surface implementation -//============================================================================== - -Surface::Surface() {} // empty constructor - -Surface::Surface(pugi::xml_node surf_node) -{ - if (check_for_node(surf_node, "id")) { - id_ = std::stoi(get_node_value(surf_node, "id")); - } else { - fatal_error("Must specify id of surface in geometry XML file."); - } - - if (check_for_node(surf_node, "name")) { - name_ = get_node_value(surf_node, "name", false); - } - - if (check_for_node(surf_node, "boundary")) { - std::string surf_bc = get_node_value(surf_node, "boundary", true, true); - - if (surf_bc == "transmission" || surf_bc == "transmit" ||surf_bc.empty()) { - bc_ = BC_TRANSMIT; - - } else if (surf_bc == "vacuum") { - bc_ = BC_VACUUM; - - } else if (surf_bc == "reflective" || surf_bc == "reflect" - || surf_bc == "reflecting") { - bc_ = BC_REFLECT; - } else if (surf_bc == "white") { - bc_ = BC_WHITE; - } else if (surf_bc == "periodic") { - bc_ = BC_PERIODIC; - } else { - std::stringstream err_msg; - err_msg << "Unknown boundary condition \"" << surf_bc - << "\" specified on surface " << id_; - fatal_error(err_msg); - } - - } else { - bc_ = BC_TRANSMIT; - } - -} - -bool -Surface::sense(Position r, Direction u) const -{ - // Evaluate the surface equation at the particle's coordinates to determine - // which side the particle is on. - const double f = evaluate(r); - - // Check which side of surface the point is on. - if (std::abs(f) < FP_COINCIDENT) { - // Particle may be coincident with this surface. To determine the sense, we - // look at the direction of the particle relative to the surface normal (by - // default in the positive direction) via their dot product. - return u.dot(normal(r)) > 0.0; - } - return f > 0.0; -} - -Direction -Surface::reflect(Position r, Direction u) const -{ - // Determine projection of direction onto normal and squared magnitude of - // normal. - Direction n = normal(r); - const double projection = n.dot(u); - const double magnitude = n.dot(n); - - // Reflect direction according to normal. - return u -= (2.0 * projection / magnitude) * n; -} - -Direction -Surface::diffuse_reflect(Position r, Direction u) const -{ - // Diffuse reflect direction according to the normal. - // cosine distribution - - Direction n = this->normal(r); - n /= n.norm(); - const double projection = n.dot(u); - - // sample from inverse function, u=sqrt(rand) since p(u)=2u, so F(u)=u^2 - const double mu = (projection>=0.0) ? - -std::sqrt(prn()) : std::sqrt(prn()); - - // sample azimuthal distribution uniformly - u = rotate_angle(n, mu, nullptr); - - // normalize the direction - return u/u.norm(); -} - -CSGSurface::CSGSurface() : Surface{} {}; -CSGSurface::CSGSurface(pugi::xml_node surf_node) : Surface{surf_node} {}; - -void -CSGSurface::to_hdf5(hid_t group_id) const -{ - std::string group_name {"surface "}; - group_name += std::to_string(id_); - - hid_t surf_group = create_group(group_id, group_name); - - switch(bc_) { - case BC_TRANSMIT : - write_string(surf_group, "boundary_type", "transmission", false); - break; - case BC_VACUUM : - write_string(surf_group, "boundary_type", "vacuum", false); - break; - case BC_REFLECT : - write_string(surf_group, "boundary_type", "reflective", false); - break; - case BC_WHITE : - write_string(surf_group, "boundary_type", "white", false); - break; - case BC_PERIODIC : - write_string(surf_group, "boundary_type", "periodic", false); - break; - } - - if (!name_.empty()) { - write_string(surf_group, "name", name_, false); - } - - to_hdf5_inner(surf_group); - - close_group(surf_group); -} - -//============================================================================== -// DAGSurface implementation -//============================================================================== -#ifdef DAGMC -DAGSurface::DAGSurface() : Surface{} {} // empty constructor - -double DAGSurface::evaluate(Position r) const -{ - return 0.0; -} - -double -DAGSurface::distance(Position r, Direction u, bool coincident) const -{ - moab::ErrorCode rval; - moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); - moab::EntityHandle hit_surf; - double dist; - double pnt[3] = {r.x, r.y, r.z}; - double dir[3] = {u.x, u.y, u.z}; - rval = dagmc_ptr_->ray_fire(surf, pnt, dir, hit_surf, dist, NULL, 0, 0); - MB_CHK_ERR_CONT(rval); - if (dist < 0.0) dist = INFTY; - return dist; -} - -Direction DAGSurface::normal(Position r) const -{ - moab::ErrorCode rval; - moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_); - double pnt[3] = {r.x, r.y, r.z}; - double dir[3]; - rval = dagmc_ptr_->get_angle(surf, pnt, dir); - MB_CHK_ERR_CONT(rval); - return dir; -} - -Direction DAGSurface::reflect(Position r, Direction u) const -{ - simulation::history.reset_to_last_intersection(); - simulation::last_dir = Surface::reflect(r, u); - return simulation::last_dir; -} - -void DAGSurface::to_hdf5(hid_t group_id) const {} - -#endif -//============================================================================== -// PeriodicSurface implementation -//============================================================================== - -PeriodicSurface::PeriodicSurface(pugi::xml_node surf_node) - : CSGSurface {surf_node} -{ - if (check_for_node(surf_node, "periodic_surface_id")) { - i_periodic_ = std::stoi(get_node_value(surf_node, "periodic_surface_id")); - } -} - -//============================================================================== -// Generic functions for x-, y-, and z-, planes. -//============================================================================== - -// The template parameter indicates the axis normal to the plane. -template double -axis_aligned_plane_distance(Position r, Direction u, bool coincident, double offset) -{ - const double f = offset - r[i]; - if (coincident || std::abs(f) < FP_COINCIDENT || u[i] == 0.0) return INFTY; - const double d = f / u[i]; - if (d < 0.0) return INFTY; - return d; -} - -//============================================================================== -// SurfaceXPlane implementation -//============================================================================== - -SurfaceXPlane::SurfaceXPlane(pugi::xml_node surf_node) - : PeriodicSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_); -} - -double SurfaceXPlane::evaluate(Position r) const -{ - return r.x - x0_; -} - -double SurfaceXPlane::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_plane_distance<0>(r, u, coincident, x0_); -} - -Direction SurfaceXPlane::normal(Position r) const -{ - return {1., 0., 0.}; -} - -void SurfaceXPlane::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "x-plane", false); - std::array coeffs {{x0_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -bool SurfaceXPlane::periodic_translate(const PeriodicSurface* other, - Position& r, Direction& u) const -{ - Direction other_n = other->normal(r); - if (other_n.x == 1 && other_n.y == 0 && other_n.z == 0) { - r.x = x0_; - return false; - } else { - // Assume the partner is an YPlane (the only supported partner). Use the - // evaluate function to find y0, then adjust position/Direction for - // rotational symmetry. - double y0_ = -other->evaluate({0., 0., 0.}); - r.y = r.x - x0_ + y0_; - r.x = x0_; - - double ux = u.x; - u.x = -u.y; - u.y = ux; - - return true; - } -} - -BoundingBox -SurfaceXPlane::bounding_box(bool pos_side) const -{ - if (pos_side) { - return {x0_, INFTY, -INFTY, INFTY, -INFTY, INFTY}; - } else { - return {-INFTY, x0_, -INFTY, INFTY, -INFTY, INFTY}; - } -} - -//============================================================================== -// SurfaceYPlane implementation -//============================================================================== - -SurfaceYPlane::SurfaceYPlane(pugi::xml_node surf_node) - : PeriodicSurface(surf_node) -{ - read_coeffs(surf_node, id_, y0_); -} - -double SurfaceYPlane::evaluate(Position r) const -{ - return r.y - y0_; -} - -double SurfaceYPlane::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_plane_distance<1>(r, u, coincident, y0_); -} - -Direction SurfaceYPlane::normal(Position r) const -{ - return {0., 1., 0.}; -} - -void SurfaceYPlane::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "y-plane", false); - std::array coeffs {{y0_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -bool SurfaceYPlane::periodic_translate(const PeriodicSurface* other, - Position& r, Direction& u) const -{ - Direction other_n = other->normal(r); - if (other_n.x == 0 && other_n.y == 1 && other_n.z == 0) { - // The periodic partner is also aligned along y. Just change the y coord. - r.y = y0_; - return false; - } else { - // Assume the partner is an XPlane (the only supported partner). Use the - // evaluate function to find x0, then adjust position/Direction for rotational - // symmetry. - double x0_ = -other->evaluate({0., 0., 0.}); - r.x = r.y - y0_ + x0_; - r.y = y0_; - - double ux = u.x; - u.x = u.y; - u.y = -ux; - - return true; - } -} - -BoundingBox -SurfaceYPlane::bounding_box(bool pos_side) const -{ - if (pos_side) { - return {-INFTY, INFTY, y0_, INFTY, -INFTY, INFTY}; - } else { - return {-INFTY, INFTY, -INFTY, y0_, -INFTY, INFTY}; - } -} - -//============================================================================== -// SurfaceZPlane implementation -//============================================================================== - -SurfaceZPlane::SurfaceZPlane(pugi::xml_node surf_node) - : PeriodicSurface(surf_node) -{ - read_coeffs(surf_node, id_, z0_); -} - -double SurfaceZPlane::evaluate(Position r) const -{ - return r.z - z0_; -} - -double SurfaceZPlane::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_plane_distance<2>(r, u, coincident, z0_); -} - -Direction SurfaceZPlane::normal(Position r) const -{ - return {0., 0., 1.}; -} - -void SurfaceZPlane::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "z-plane", false); - std::array coeffs {{z0_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -bool SurfaceZPlane::periodic_translate(const PeriodicSurface* other, - Position& r, Direction& u) const -{ - // Assume the other plane is aligned along z. Just change the z coord. - r.z = z0_; - return false; -} - -BoundingBox -SurfaceZPlane::bounding_box(bool pos_side) const -{ - if (pos_side) { - return {-INFTY, INFTY, -INFTY, INFTY, z0_, INFTY}; - } else { - return {-INFTY, INFTY, -INFTY, INFTY, -INFTY, z0_}; - } -} - -//============================================================================== -// SurfacePlane implementation -//============================================================================== - -SurfacePlane::SurfacePlane(pugi::xml_node surf_node) - : PeriodicSurface(surf_node) -{ - read_coeffs(surf_node, id_, A_, B_, C_, D_); -} - -double -SurfacePlane::evaluate(Position r) const -{ - return A_*r.x + B_*r.y + C_*r.z - D_; -} - -double -SurfacePlane::distance(Position r, Direction u, bool coincident) const -{ - const double f = A_*r.x + B_*r.y + C_*r.z - D_; - const double projection = A_*u.x + B_*u.y + C_*u.z; - if (coincident || std::abs(f) < FP_COINCIDENT || projection == 0.0) { - return INFTY; - } else { - const double d = -f / projection; - if (d < 0.0) return INFTY; - return d; - } -} - -Direction -SurfacePlane::normal(Position r) const -{ - return {A_, B_, C_}; -} - -void SurfacePlane::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "plane", false); - std::array coeffs {{A_, B_, C_, D_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -bool SurfacePlane::periodic_translate(const PeriodicSurface* other, Position& r, - Direction& u) const -{ - // This function assumes the other plane shares this plane's normal direction. - - // Determine the distance to intersection. - double d = evaluate(r) / (A_*A_ + B_*B_ + C_*C_); - - // Move the particle that distance along the normal vector. - r.x -= d * A_; - r.y -= d * B_; - r.z -= d * C_; - - return false; -} - -//============================================================================== -// Generic functions for x-, y-, and z-, cylinders -//============================================================================== - -// The template parameters indicate the axes perpendicular to the axis of the -// cylinder. offset1 and offset2 should correspond with i1 and i2, -// respectively. -template double -axis_aligned_cylinder_evaluate(Position r, double offset1, - double offset2, double radius) -{ - const double r1 = r[i1] - offset1; - const double r2 = r[i2] - offset2; - return r1*r1 + r2*r2 - radius*radius; -} - -// The first template parameter indicates which axis the cylinder is aligned to. -// The other two parameters indicate the other two axes. offset1 and offset2 -// should correspond with i2 and i3, respectively. -template double -axis_aligned_cylinder_distance(Position r, Direction u, - bool coincident, double offset1, double offset2, double radius) -{ - const double a = 1.0 - u[i1]*u[i1]; // u^2 + v^2 - if (a == 0.0) return INFTY; - - const double r2 = r[i2] - offset1; - const double r3 = r[i3] - offset2; - const double k = r2 * u[i2] + r3 * u[i3]; - const double c = r2*r2 + r3*r3 - radius*radius; - const double quad = k*k - a*c; - - if (quad < 0.0) { - // No intersection with cylinder. - return INFTY; - - } else if (coincident || std::abs(c) < FP_COINCIDENT) { - // Particle is on the cylinder, thus one distance is positive/negative - // and the other is zero. The sign of k determines if we are facing in or - // out. - if (k >= 0.0) { - return INFTY; - } else { - return (-k + sqrt(quad)) / a; - } - - } else if (c < 0.0) { - // Particle is inside the cylinder, thus one distance must be negative - // and one must be positive. The positive distance will be the one with - // negative sign on sqrt(quad). - return (-k + sqrt(quad)) / a; - - } else { - // Particle is outside the cylinder, thus both distances are either - // positive or negative. If positive, the smaller distance is the one - // with positive sign on sqrt(quad). - const double d = (-k - sqrt(quad)) / a; - if (d < 0.0) return INFTY; - return d; - } -} - -// The first template parameter indicates which axis the cylinder is aligned to. -// The other two parameters indicate the other two axes. offset1 and offset2 -// should correspond with i2 and i3, respectively. -template Direction -axis_aligned_cylinder_normal(Position r, double offset1, double offset2) -{ - Direction u; - u[i2] = 2.0 * (r[i2] - offset1); - u[i3] = 2.0 * (r[i3] - offset2); - u[i1] = 0.0; - return u; -} - -//============================================================================== -// SurfaceXCylinder implementation -//============================================================================== - -SurfaceXCylinder::SurfaceXCylinder(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, y0_, z0_, radius_); -} - -double SurfaceXCylinder::evaluate(Position r) const -{ - return axis_aligned_cylinder_evaluate<1, 2>(r, y0_, z0_, radius_); -} - -double SurfaceXCylinder::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cylinder_distance<0, 1, 2>(r, u, coincident, y0_, z0_, - radius_); -} - -Direction SurfaceXCylinder::normal(Position r) const -{ - return axis_aligned_cylinder_normal<0, 1, 2>(r, y0_, z0_); -} - -void SurfaceXCylinder::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "x-cylinder", false); - std::array coeffs {{y0_, z0_, radius_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -BoundingBox SurfaceXCylinder::bounding_box(bool pos_side) const { - if (!pos_side) { - return {-INFTY, INFTY, y0_ - radius_, y0_ + radius_, z0_ - radius_, z0_ + radius_}; - } else { - return {}; - } -} -//============================================================================== -// SurfaceYCylinder implementation -//============================================================================== - -SurfaceYCylinder::SurfaceYCylinder(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, z0_, radius_); -} - -double SurfaceYCylinder::evaluate(Position r) const -{ - return axis_aligned_cylinder_evaluate<0, 2>(r, x0_, z0_, radius_); -} - -double SurfaceYCylinder::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cylinder_distance<1, 0, 2>(r, u, coincident, x0_, z0_, - radius_); -} - -Direction SurfaceYCylinder::normal(Position r) const -{ - return axis_aligned_cylinder_normal<1, 0, 2>(r, x0_, z0_); -} - -void SurfaceYCylinder::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "y-cylinder", false); - std::array coeffs {{x0_, z0_, radius_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -BoundingBox SurfaceYCylinder::bounding_box(bool pos_side) const { - if (!pos_side) { - return {x0_ - radius_, x0_ + radius_, -INFTY, INFTY, z0_ - radius_, z0_ + radius_}; - } else { - return {}; - } -} - -//============================================================================== -// SurfaceZCylinder implementation -//============================================================================== - -SurfaceZCylinder::SurfaceZCylinder(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, y0_, radius_); -} - -double SurfaceZCylinder::evaluate(Position r) const -{ - return axis_aligned_cylinder_evaluate<0, 1>(r, x0_, y0_, radius_); -} - -double SurfaceZCylinder::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cylinder_distance<2, 0, 1>(r, u, coincident, x0_, y0_, - radius_); -} - -Direction SurfaceZCylinder::normal(Position r) const -{ - return axis_aligned_cylinder_normal<2, 0, 1>(r, x0_, y0_); -} - -void SurfaceZCylinder::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "z-cylinder", false); - std::array coeffs {{x0_, y0_, radius_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -BoundingBox SurfaceZCylinder::bounding_box(bool pos_side) const { - if (!pos_side) { - return {x0_ - radius_, x0_ + radius_, y0_ - radius_, y0_ + radius_, -INFTY, INFTY}; - } else { - return {}; - } -} - - -//============================================================================== -// SurfaceSphere implementation -//============================================================================== - -SurfaceSphere::SurfaceSphere(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, y0_, z0_, radius_); -} - -double SurfaceSphere::evaluate(Position r) const -{ - const double x = r.x - x0_; - const double y = r.y - y0_; - const double z = r.z - z0_; - return x*x + y*y + z*z - radius_*radius_; -} - -double SurfaceSphere::distance(Position r, Direction u, bool coincident) const -{ - const double x = r.x - x0_; - const double y = r.y - y0_; - const double z = r.z - z0_; - const double k = x*u.x + y*u.y + z*u.z; - const double c = x*x + y*y + z*z - radius_*radius_; - const double quad = k*k - c; - - if (quad < 0.0) { - // No intersection with sphere. - return INFTY; - - } else if (coincident || std::abs(c) < FP_COINCIDENT) { - // Particle is on the sphere, thus one distance is positive/negative and - // the other is zero. The sign of k determines if we are facing in or out. - if (k >= 0.0) { - return INFTY; - } else { - return -k + sqrt(quad); - } - - } else if (c < 0.0) { - // Particle is inside the sphere, thus one distance must be negative and - // one must be positive. The positive distance will be the one with - // negative sign on sqrt(quad) - return -k + sqrt(quad); - - } else { - // Particle is outside the sphere, thus both distances are either positive - // or negative. If positive, the smaller distance is the one with positive - // sign on sqrt(quad). - const double d = -k - sqrt(quad); - if (d < 0.0) return INFTY; - return d; - } -} - -Direction SurfaceSphere::normal(Position r) const -{ - return {2.0*(r.x - x0_), 2.0*(r.y - y0_), 2.0*(r.z - z0_)}; -} - -void SurfaceSphere::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "sphere", false); - std::array coeffs {{x0_, y0_, z0_, radius_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -BoundingBox SurfaceSphere::bounding_box(bool pos_side) const { - if (!pos_side) { - return {x0_ - radius_, x0_ + radius_, - y0_ - radius_, y0_ + radius_, - z0_ - radius_, z0_ + radius_}; - } else { - return {}; - } -} - -//============================================================================== -// Generic functions for x-, y-, and z-, cones -//============================================================================== - -// The first template parameter indicates which axis the cone is aligned to. -// The other two parameters indicate the other two axes. offset1, offset2, -// and offset3 should correspond with i1, i2, and i3, respectively. -template double -axis_aligned_cone_evaluate(Position r, double offset1, - double offset2, double offset3, double radius_sq) -{ - const double r1 = r[i1] - offset1; - const double r2 = r[i2] - offset2; - const double r3 = r[i3] - offset3; - return r2*r2 + r3*r3 - radius_sq*r1*r1; -} - -// The first template parameter indicates which axis the cone is aligned to. -// The other two parameters indicate the other two axes. offset1, offset2, -// and offset3 should correspond with i1, i2, and i3, respectively. -template double -axis_aligned_cone_distance(Position r, Direction u, - bool coincident, double offset1, double offset2, double offset3, - double radius_sq) -{ - const double r1 = r[i1] - offset1; - const double r2 = r[i2] - offset2; - const double r3 = r[i3] - offset3; - const double a = u[i2]*u[i2] + u[i3]*u[i3] - - radius_sq*u[i1]*u[i1]; - const double k = r2*u[i2] + r3*u[i3] - radius_sq*r1*u[i1]; - const double c = r2*r2 + r3*r3 - radius_sq*r1*r1; - double quad = k*k - a*c; - - double d; - - if (quad < 0.0) { - // No intersection with cone. - return INFTY; - - } else if (coincident || std::abs(c) < FP_COINCIDENT) { - // Particle is on the cone, thus one distance is positive/negative - // and the other is zero. The sign of k determines if we are facing in or - // out. - if (k >= 0.0) { - d = (-k - sqrt(quad)) / a; - } else { - d = (-k + sqrt(quad)) / a; - } - - } else { - // Calculate both solutions to the quadratic. - quad = sqrt(quad); - d = (-k - quad) / a; - const double b = (-k + quad) / a; - - // Determine the smallest positive solution. - if (d < 0.0) { - if (b > 0.0) d = b; - } else { - if (b > 0.0) { - if (b < d) d = b; - } - } - } - - // If the distance was negative, set boundary distance to infinity. - if (d <= 0.0) return INFTY; - return d; -} - -// The first template parameter indicates which axis the cone is aligned to. -// The other two parameters indicate the other two axes. offset1, offset2, -// and offset3 should correspond with i1, i2, and i3, respectively. -template Direction -axis_aligned_cone_normal(Position r, double offset1, double offset2, - double offset3, double radius_sq) -{ - Direction u; - u[i1] = -2.0 * radius_sq * (r[i1] - offset1); - u[i2] = 2.0 * (r[i2] - offset2); - u[i3] = 2.0 * (r[i3] - offset3); - return u; -} - -//============================================================================== -// SurfaceXCone implementation -//============================================================================== - -SurfaceXCone::SurfaceXCone(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, y0_, z0_, radius_sq_); -} - -double SurfaceXCone::evaluate(Position r) const -{ - return axis_aligned_cone_evaluate<0, 1, 2>(r, x0_, y0_, z0_, radius_sq_); -} - -double SurfaceXCone::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cone_distance<0, 1, 2>(r, u, coincident, x0_, y0_, z0_, - radius_sq_); -} - -Direction SurfaceXCone::normal(Position r) const -{ - return axis_aligned_cone_normal<0, 1, 2>(r, x0_, y0_, z0_, radius_sq_); -} - -void SurfaceXCone::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "x-cone", false); - std::array coeffs {{x0_, y0_, z0_, radius_sq_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -//============================================================================== -// SurfaceYCone implementation -//============================================================================== - -SurfaceYCone::SurfaceYCone(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, y0_, z0_, radius_sq_); -} - -double SurfaceYCone::evaluate(Position r) const -{ - return axis_aligned_cone_evaluate<1, 0, 2>(r, y0_, x0_, z0_, radius_sq_); -} - -double SurfaceYCone::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cone_distance<1, 0, 2>(r, u, coincident, y0_, x0_, z0_, - radius_sq_); -} - -Direction SurfaceYCone::normal(Position r) const -{ - return axis_aligned_cone_normal<1, 0, 2>(r, y0_, x0_, z0_, radius_sq_); -} - -void SurfaceYCone::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "y-cone", false); - std::array coeffs {{x0_, y0_, z0_, radius_sq_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -//============================================================================== -// SurfaceZCone implementation -//============================================================================== - -SurfaceZCone::SurfaceZCone(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, x0_, y0_, z0_, radius_sq_); -} - -double SurfaceZCone::evaluate(Position r) const -{ - return axis_aligned_cone_evaluate<2, 0, 1>(r, z0_, x0_, y0_, radius_sq_); -} - -double SurfaceZCone::distance(Position r, Direction u, bool coincident) const -{ - return axis_aligned_cone_distance<2, 0, 1>(r, u, coincident, z0_, x0_, y0_, - radius_sq_); -} - -Direction SurfaceZCone::normal(Position r) const -{ - return axis_aligned_cone_normal<2, 0, 1>(r, z0_, x0_, y0_, radius_sq_); -} - -void SurfaceZCone::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "z-cone", false); - std::array coeffs {{x0_, y0_, z0_, radius_sq_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -//============================================================================== -// SurfaceQuadric implementation -//============================================================================== - -SurfaceQuadric::SurfaceQuadric(pugi::xml_node surf_node) - : CSGSurface(surf_node) -{ - read_coeffs(surf_node, id_, A_, B_, C_, D_, E_, F_, G_, H_, J_, K_); -} - -double -SurfaceQuadric::evaluate(Position r) const -{ - const double x = r.x; - const double y = r.y; - const double z = r.z; - return x*(A_*x + D_*y + G_) + - y*(B_*y + E_*z + H_) + - z*(C_*z + F_*x + J_) + K_; -} - -double -SurfaceQuadric::distance(Position r, Direction ang, bool coincident) const -{ - const double &x = r.x; - const double &y = r.y; - const double &z = r.z; - const double &u = ang.x; - const double &v = ang.y; - const double &w = ang.z; - - const double a = A_*u*u + B_*v*v + C_*w*w + D_*u*v + E_*v*w + F_*u*w; - const double k = A_*u*x + B_*v*y + C_*w*z + 0.5*(D_*(u*y + v*x) - + E_*(v*z + w*y) + F_*(w*x + u*z) + G_*u + H_*v + J_*w); - const double c = A_*x*x + B_*y*y + C_*z*z + D_*x*y + E_*y*z + F_*x*z + G_*x - + H_*y + J_*z + K_; - double quad = k*k - a*c; - - double d; - - if (quad < 0.0) { - // No intersection with surface. - return INFTY; - - } else if (coincident || std::abs(c) < FP_COINCIDENT) { - // Particle is on the surface, thus one distance is positive/negative and - // the other is zero. The sign of k determines which distance is zero and - // which is not. - if (k >= 0.0) { - d = (-k - sqrt(quad)) / a; - } else { - d = (-k + sqrt(quad)) / a; - } - - } else { - // Calculate both solutions to the quadratic. - quad = sqrt(quad); - d = (-k - quad) / a; - double b = (-k + quad) / a; - - // Determine the smallest positive solution. - if (d < 0.0) { - if (b > 0.0) d = b; - } else { - if (b > 0.0) { - if (b < d) d = b; - } - } - } - - // If the distance was negative, set boundary distance to infinity. - if (d <= 0.0) return INFTY; - return d; -} - -Direction -SurfaceQuadric::normal(Position r) const -{ - const double &x = r.x; - const double &y = r.y; - const double &z = r.z; - return {2.0*A_*x + D_*y + F_*z + G_, - 2.0*B_*y + D_*x + E_*z + H_, - 2.0*C_*z + E_*y + F_*x + J_}; -} - -void SurfaceQuadric::to_hdf5_inner(hid_t group_id) const -{ - write_string(group_id, "type", "quadric", false); - std::array coeffs {{A_, B_, C_, D_, E_, F_, G_, H_, J_, K_}}; - write_dataset(group_id, "coefficients", coeffs); -} - -//============================================================================== - -void read_surfaces(pugi::xml_node node) -{ - // Count the number of surfaces. - int n_surfaces = 0; - for (pugi::xml_node surf_node : node.children("surface")) {n_surfaces++;} - if (n_surfaces == 0) { - fatal_error("No surfaces found in geometry.xml!"); - } - - // Loop over XML surface elements and populate the array. - model::surfaces.reserve(n_surfaces); - { - pugi::xml_node surf_node; - int i_surf; - for (surf_node = node.child("surface"), i_surf = 0; surf_node; - surf_node = surf_node.next_sibling("surface"), i_surf++) { - std::string surf_type = get_node_value(surf_node, "type", true, true); - - if (surf_type == "x-plane") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "y-plane") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "z-plane") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "plane") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "x-cylinder") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "y-cylinder") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "z-cylinder") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "sphere") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "x-cone") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "y-cone") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "z-cone") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else if (surf_type == "quadric") { - model::surfaces.push_back(std::make_unique(surf_node)); - - } else { - std::stringstream err_msg; - err_msg << "Invalid surface type, \"" << surf_type << "\""; - fatal_error(err_msg); - } - } - } - - // Fill the surface map. - for (int i_surf = 0; i_surf < model::surfaces.size(); i_surf++) { - int id = model::surfaces[i_surf]->id_; - auto in_map = model::surface_map.find(id); - if (in_map == model::surface_map.end()) { - model::surface_map[id] = i_surf; - } else { - std::stringstream err_msg; - err_msg << "Two or more surfaces use the same unique ID: " << id; - fatal_error(err_msg); - } - } - - // Find the global bounding box (of periodic BC surfaces). - double xmin {INFTY}, xmax {-INFTY}, ymin {INFTY}, ymax {-INFTY}, - zmin {INFTY}, zmax {-INFTY}; - int i_xmin, i_xmax, i_ymin, i_ymax, i_zmin, i_zmax; - for (int i_surf = 0; i_surf < model::surfaces.size(); i_surf++) { - if (model::surfaces[i_surf]->bc_ == BC_PERIODIC) { - // Downcast to the PeriodicSurface type. - Surface* surf_base = model::surfaces[i_surf].get(); - auto surf = dynamic_cast(surf_base); - - // Make sure this surface inherits from PeriodicSurface. - if (!surf) { - std::stringstream err_msg; - err_msg << "Periodic boundary condition not supported for surface " - << surf_base->id_ - << ". Periodic BCs are only supported for planar surfaces."; - fatal_error(err_msg); - } - - // See if this surface makes part of the global bounding box. - auto bb = surf->bounding_box(true) & surf->bounding_box(false); - if (bb.xmin > -INFTY && bb.xmin < xmin) { - xmin = bb.xmin; - i_xmin = i_surf; - } - if (bb.xmax < INFTY && bb.xmax > xmax) { - xmax = bb.xmax; - i_xmax = i_surf; - } - if (bb.ymin > -INFTY && bb.ymin < ymin) { - ymin = bb.ymin; - i_ymin = i_surf; - } - if (bb.ymax < INFTY && bb.ymax > ymax) { - ymax = bb.ymax; - i_ymax = i_surf; - } - if (bb.zmin > -INFTY && bb.zmin < zmin) { - zmin = bb.zmin; - i_zmin = i_surf; - } - if (bb.zmax < INFTY && bb.zmax > zmax) { - zmax = bb.zmax; - i_zmax = i_surf; - } - } - } - - // Set i_periodic for periodic BC surfaces. - for (int i_surf = 0; i_surf < model::surfaces.size(); i_surf++) { - if (model::surfaces[i_surf]->bc_ == BC_PERIODIC) { - // Downcast to the PeriodicSurface type. - Surface* surf_base = model::surfaces[i_surf].get(); - auto surf = dynamic_cast(surf_base); - - // Also try downcasting to the SurfacePlane type (which must be handled - // differently). - SurfacePlane* surf_p = dynamic_cast(surf); - - if (!surf_p) { - // This is not a SurfacePlane. - if (surf->i_periodic_ == C_NONE) { - // The user did not specify the matching periodic surface. See if we - // can find the partnered surface from the bounding box information. - if (i_surf == i_xmin) { - surf->i_periodic_ = i_xmax; - } else if (i_surf == i_xmax) { - surf->i_periodic_ = i_xmin; - } else if (i_surf == i_ymin) { - surf->i_periodic_ = i_ymax; - } else if (i_surf == i_ymax) { - surf->i_periodic_ = i_ymin; - } else if (i_surf == i_zmin) { - surf->i_periodic_ = i_zmax; - } else if (i_surf == i_zmax) { - surf->i_periodic_ = i_zmin; - } else { - fatal_error("Periodic boundary condition applied to interior " - "surface"); - } - } else { - // Convert the surface id to an index. - surf->i_periodic_ = model::surface_map[surf->i_periodic_]; - } - } else { - // This is a SurfacePlane. We won't try to find it's partner if the - // user didn't specify one. - if (surf->i_periodic_ == C_NONE) { - std::stringstream err_msg; - err_msg << "No matching periodic surface specified for periodic " - "boundary condition on surface " << surf->id_; - fatal_error(err_msg); - } else { - // Convert the surface id to an index. - surf->i_periodic_ = model::surface_map[surf->i_periodic_]; - } - } - - // Make sure the opposite surface is also periodic. - if (model::surfaces[surf->i_periodic_]->bc_ != BC_PERIODIC) { - std::stringstream err_msg; - err_msg << "Could not find matching surface for periodic boundary " - "condition on surface " << surf->id_; - fatal_error(err_msg); - } - } - } - - // Check to make sure a boundary condition was applied to at least one - // surface - bool boundary_exists = false; - for (const auto& surf : model::surfaces) { - if (surf->bc_ != BC_TRANSMIT) { - boundary_exists = true; - break; - } - } - if (settings::run_mode != RUN_MODE_PLOTTING && !boundary_exists) { - fatal_error("No boundary conditions were applied to any surfaces!"); - } -} - -void free_memory_surfaces() -{ - model::surfaces.clear(); - model::surface_map.clear(); -} - -} // namespace openmc diff --git a/src/tallies/derivative.cpp b/src/tallies/derivative.cpp deleted file mode 100644 index 290d09384..000000000 --- a/src/tallies/derivative.cpp +++ /dev/null @@ -1,687 +0,0 @@ -#include "openmc/tallies/derivative.h" - -#include "openmc/error.h" -#include "openmc/material.h" -#include "openmc/nuclide.h" -#include "openmc/settings.h" -#include "openmc/tallies/tally.h" -#include "openmc/xml_interface.h" - -#include - -template class std::vector; - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - std::vector tally_derivs; - std::unordered_map tally_deriv_map; -} - -//============================================================================== -// TallyDerivative implementation -//============================================================================== - -TallyDerivative::TallyDerivative(pugi::xml_node node) -{ - if (check_for_node(node, "id")) { - id = std::stoi(get_node_value(node, "id")); - } else { - fatal_error("Must specify an ID for elements in the tally " - "XML file"); - } - - if (id <= 0) - fatal_error(" IDs must be an integer greater than zero"); - - std::string variable_str = get_node_value(node, "variable"); - - if (variable_str == "density") { - variable = DIFF_DENSITY; - - } else if (variable_str == "nuclide_density") { - variable = DIFF_NUCLIDE_DENSITY; - - std::string nuclide_name = get_node_value(node, "nuclide"); - bool found = false; - for (auto i = 0; i < data::nuclides.size(); ++i) { - if (data::nuclides[i]->name_ == nuclide_name) { - found = true; - diff_nuclide = i; - } - } - if (!found) { - std::stringstream out; - out << "Could not find the nuclide \"" << nuclide_name - << "\" specified in derivative " << id << " in any material."; - fatal_error(out); - } - - } else if (variable_str == "temperature") { - variable = DIFF_TEMPERATURE; - - } else { - std::stringstream out; - out << "Unrecognized variable \"" << variable_str - << "\" on derivative " << id; - fatal_error(out); - } - - diff_material = std::stoi(get_node_value(node, "material")); -} - -//============================================================================== -// Non-method functions -//============================================================================== - -void -read_tally_derivatives(pugi::xml_node node) -{ - // Populate the derivatives array. This must be done in parallel because - // the derivatives are threadprivate. - #pragma omp parallel - { - for (auto deriv_node : node.children("derivative")) - model::tally_derivs.emplace_back(deriv_node); - } - - // Fill the derivative map. - for (auto i = 0; i < model::tally_derivs.size(); ++i) { - auto id = model::tally_derivs[i].id; - auto search = model::tally_deriv_map.find(id); - if (search == model::tally_deriv_map.end()) { - model::tally_deriv_map[id] = i; - } else { - fatal_error("Two or more derivatives use the same unique ID: " - + std::to_string(id)); - } - } - - // Make sure derivatives were not requested for an MG run. - if (!settings::run_CE && !model::tally_derivs.empty()) - fatal_error("Differential tallies not supported in multi-group mode"); -} - -void -apply_derivative_to_score(const Particle* p, int i_tally, int i_nuclide, - double atom_density, int score_bin, double& score) -{ - const Tally& tally {*model::tallies[i_tally]}; - - if (score == 0.0) return; - - // If our score was previously c then the new score is - // c * (1/f * d_f/d_p + 1/c * d_c/d_p) - // where (1/f * d_f/d_p) is the (logarithmic) flux derivative and p is the - // perturbated variable. - - const auto& deriv {model::tally_derivs[tally.deriv_]}; - auto flux_deriv = deriv.flux_deriv; - - // Handle special cases where we know that d_c/d_p must be zero. - if (score_bin == SCORE_FLUX) { - score *= flux_deriv; - return; - } else if (p->material_ == MATERIAL_VOID) { - score *= flux_deriv; - return; - } - const Material& material {*model::materials[p->material_]}; - if (material.id_ != deriv.diff_material) { - score *= flux_deriv; - return; - } - - switch (deriv.variable) { - - //============================================================================ - // Density derivative: - // c = Sigma_MT - // c = sigma_MT * N - // c = sigma_MT * rho * const - // d_c / d_rho = sigma_MT * const - // (1 / c) * (d_c / d_rho) = 1 / rho - - case DIFF_DENSITY: - switch (tally.estimator_) { - - case ESTIMATOR_ANALOG: - case ESTIMATOR_COLLISION: - switch (score_bin) { - - case SCORE_TOTAL: - case SCORE_SCATTER: - case SCORE_ABSORPTION: - case SCORE_FISSION: - case SCORE_NU_FISSION: - score *= flux_deriv + 1. / material.density_gpcc_; - break; - - default: - fatal_error("Tally derivative not defined for a score on tally " - + std::to_string(tally.id_)); - } - break; - - default: - fatal_error("Differential tallies are only implemented for analog and " - "collision estimators."); - } - break; - - //============================================================================ - // Nuclide density derivative: - // If we are scoring a reaction rate for a single nuclide then - // c = Sigma_MT_i - // c = sigma_MT_i * N_i - // d_c / d_N_i = sigma_MT_i - // (1 / c) * (d_c / d_N_i) = 1 / N_i - // If the score is for the total material (i_nuclide = -1) - // c = Sum_i(Sigma_MT_i) - // d_c / d_N_i = sigma_MT_i - // (1 / c) * (d_c / d_N) = sigma_MT_i / Sigma_MT - // where i is the perturbed nuclide. - - case DIFF_NUCLIDE_DENSITY: - switch (tally.estimator_) { - - case ESTIMATOR_ANALOG: - if (p->event_nuclide_ != deriv.diff_nuclide) { - score *= flux_deriv; - return; - } - - switch (score_bin) { - - case SCORE_TOTAL: - case SCORE_SCATTER: - case SCORE_ABSORPTION: - case SCORE_FISSION: - case SCORE_NU_FISSION: - { - // Find the index of the perturbed nuclide. - int i; - for (i = 0; i < material.nuclide_.size(); ++i) - if (material.nuclide_[i] == deriv.diff_nuclide) break; - score *= flux_deriv + 1. / material.atom_density_(i); - } - break; - - default: - fatal_error("Tally derivative not defined for a score on tally " - + std::to_string(tally.id_)); - } - break; - - case ESTIMATOR_COLLISION: - switch (score_bin) { - - case SCORE_TOTAL: - if (i_nuclide == -1 && p->macro_xs_.total > 0.0) { - score *= flux_deriv - + p->neutron_xs_[deriv.diff_nuclide].total - / p->macro_xs_.total; - } else if (i_nuclide == deriv.diff_nuclide - && p->neutron_xs_[i_nuclide].total) { - score *= flux_deriv + 1. / atom_density; - } else { - score *= flux_deriv; - } - break; - - case SCORE_SCATTER: - if (i_nuclide == -1 && (p->macro_xs_.total - - p->macro_xs_.absorption) > 0.0) { - score *= flux_deriv - + (p->neutron_xs_[deriv.diff_nuclide].total - - p->neutron_xs_[deriv.diff_nuclide].absorption) - / (p->macro_xs_.total - - p->macro_xs_.absorption); - } else if (i_nuclide == deriv.diff_nuclide) { - score *= flux_deriv + 1. / atom_density; - } else { - score *= flux_deriv; - } - break; - - case SCORE_ABSORPTION: - if (i_nuclide == -1 && p->macro_xs_.absorption > 0.0) { - score *= flux_deriv - + p->neutron_xs_[deriv.diff_nuclide].absorption - / p->macro_xs_.absorption; - } else if (i_nuclide == deriv.diff_nuclide - && p->neutron_xs_[i_nuclide].absorption) { - score *= flux_deriv + 1. / atom_density; - } else { - score *= flux_deriv; - } - break; - - case SCORE_FISSION: - if (i_nuclide == -1 && p->macro_xs_.fission > 0.0) { - score *= flux_deriv - + p->neutron_xs_[deriv.diff_nuclide].fission - / p->macro_xs_.fission; - } else if (i_nuclide == deriv.diff_nuclide - && p->neutron_xs_[i_nuclide].fission) { - score *= flux_deriv + 1. / atom_density; - } else { - score *= flux_deriv; - } - break; - - case SCORE_NU_FISSION: - if (i_nuclide == -1 && p->macro_xs_.nu_fission > 0.0) { - score *= flux_deriv - + p->neutron_xs_[deriv.diff_nuclide].nu_fission - / p->macro_xs_.nu_fission; - } else if (i_nuclide == deriv.diff_nuclide - && p->neutron_xs_[i_nuclide].nu_fission) { - score *= flux_deriv + 1. / atom_density; - } else { - score *= flux_deriv; - } - break; - - default: - fatal_error("Tally derivative not defined for a score on tally " - + std::to_string(tally.id_)); - } - break; - - default: - fatal_error("Differential tallies are only implemented for analog and " - "collision estimators."); - } - break; - - //============================================================================ - // Temperature derivative: - // If we are scoring a reaction rate for a single nuclide then - // c = Sigma_MT_i - // c = sigma_MT_i * N_i - // d_c / d_T = (d_sigma_Mt_i / d_T) * N_i - // (1 / c) * (d_c / d_T) = (d_sigma_MT_i / d_T) / sigma_MT_i - // If the score is for the total material (i_nuclide = -1) - // (1 / c) * (d_c / d_T) = Sum_i((d_sigma_MT_i / d_T) * N_i) / Sigma_MT_i - // where i is the perturbed nuclide. The d_sigma_MT_i / d_T term is - // computed by multipole_deriv_eval. It only works for the resolved - // resonance range and requires multipole data. - - case DIFF_TEMPERATURE: - switch (tally.estimator_) { - - case ESTIMATOR_ANALOG: - { - // Find the index of the event nuclide. - int i; - for (i = 0; i < material.nuclide_.size(); ++i) - if (material.nuclide_[i] == p->event_nuclide_) break; - - const auto& nuc {*data::nuclides[p->event_nuclide_]}; - if (!multipole_in_range(&nuc, p->E_last_)) { - score *= flux_deriv; - break; - } - - switch (score_bin) { - - case SCORE_TOTAL: - if (p->neutron_xs_[p->event_nuclide_].total) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + (dsig_s + dsig_a) * material.atom_density_(i) - / p->macro_xs_.total; - } else { - score *= flux_deriv; - } - break; - - case SCORE_SCATTER: - if (p->neutron_xs_[p->event_nuclide_].total - - p->neutron_xs_[p->event_nuclide_].absorption) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + dsig_s * material.atom_density_(i) - / (p->macro_xs_.total - - p->macro_xs_.absorption); - } else { - score *= flux_deriv; - } - break; - - case SCORE_ABSORPTION: - if (p->neutron_xs_[p->event_nuclide_].absorption) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + dsig_a * material.atom_density_(i) - / p->macro_xs_.absorption; - } else { - score *= flux_deriv; - } - break; - - case SCORE_FISSION: - if (p->neutron_xs_[p->event_nuclide_].fission) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + dsig_f * material.atom_density_(i) - / p->macro_xs_.fission; - } else { - score *= flux_deriv; - } - break; - - case SCORE_NU_FISSION: - if (p->neutron_xs_[p->event_nuclide_].fission) { - double nu = p->neutron_xs_[p->event_nuclide_].nu_fission - / p->neutron_xs_[p->event_nuclide_].fission; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + nu * dsig_f * material.atom_density_(i) - / p->macro_xs_.nu_fission; - } else { - score *= flux_deriv; - } - break; - - default: - fatal_error("Tally derivative not defined for a score on tally " - + std::to_string(tally.id_)); - } - } - break; - - case ESTIMATOR_COLLISION: - if (i_nuclide != -1) { - const auto& nuc {data::nuclides[i_nuclide]}; - if (!multipole_in_range(nuc.get(), p->E_last_)) { - score *= flux_deriv; - return; - } - } - - switch (score_bin) { - - case SCORE_TOTAL: - if (i_nuclide == -1 && p->macro_xs_.total > 0.0) { - double cum_dsig = 0; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuc = material.nuclide_[i]; - const auto& nuc {*data::nuclides[i_nuc]}; - if (multipole_in_range(&nuc, p->E_last_) - && p->neutron_xs_[i_nuc].total) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - cum_dsig += (dsig_s + dsig_a) * material.atom_density_(i); - } - } - score *= flux_deriv + cum_dsig / p->macro_xs_.total; - } else if (p->neutron_xs_[i_nuclide].total) { - const auto& nuc {*data::nuclides[i_nuclide]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv - + (dsig_s + dsig_a) / p->neutron_xs_[i_nuclide].total; - } else { - score *= flux_deriv; - } - break; - - case SCORE_SCATTER: - if (i_nuclide == -1 && (p->macro_xs_.total - - p->macro_xs_.absorption)) { - double cum_dsig = 0; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuc = material.nuclide_[i]; - const auto& nuc {*data::nuclides[i_nuc]}; - if (multipole_in_range(&nuc, p->E_last_) - && (p->neutron_xs_[i_nuc].total - - p->neutron_xs_[i_nuc].absorption)) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - cum_dsig += dsig_s * material.atom_density_(i); - } - } - score *= flux_deriv + cum_dsig / (p->macro_xs_.total - - p->macro_xs_.absorption); - } else if (p->neutron_xs_[i_nuclide].total - - p->neutron_xs_[i_nuclide].absorption) { - const auto& nuc {*data::nuclides[i_nuclide]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv + dsig_s / (p->neutron_xs_[i_nuclide].total - - p->neutron_xs_[i_nuclide].absorption); - } else { - score *= flux_deriv; - } - break; - - case SCORE_ABSORPTION: - if (i_nuclide == -1 && p->macro_xs_.absorption > 0.0) { - double cum_dsig = 0; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuc = material.nuclide_[i]; - const auto& nuc {*data::nuclides[i_nuc]}; - if (multipole_in_range(&nuc, p->E_last_) - && p->neutron_xs_[i_nuc].absorption) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - cum_dsig += dsig_a * material.atom_density_(i); - } - } - score *= flux_deriv + cum_dsig / p->macro_xs_.absorption; - } else if (p->neutron_xs_[i_nuclide].absorption) { - const auto& nuc {*data::nuclides[i_nuclide]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv - + dsig_a / p->neutron_xs_[i_nuclide].absorption; - } else { - score *= flux_deriv; - } - break; - - case SCORE_FISSION: - if (i_nuclide == -1 && p->macro_xs_.fission > 0.0) { - double cum_dsig = 0; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuc = material.nuclide_[i]; - const auto& nuc {*data::nuclides[i_nuc]}; - if (multipole_in_range(&nuc, p->E_last_) - && p->neutron_xs_[i_nuc].fission) { - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - cum_dsig += dsig_f * material.atom_density_(i); - } - } - score *= flux_deriv + cum_dsig / p->macro_xs_.fission; - } else if (p->neutron_xs_[i_nuclide].fission) { - const auto& nuc {*data::nuclides[i_nuclide]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv - + dsig_f / p->neutron_xs_[i_nuclide].fission; - } else { - score *= flux_deriv; - } - break; - - case SCORE_NU_FISSION: - if (i_nuclide == -1 && p->macro_xs_.nu_fission > 0.0) { - double cum_dsig = 0; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuc = material.nuclide_[i]; - const auto& nuc {*data::nuclides[i_nuc]}; - if (multipole_in_range(&nuc, p->E_last_) - && p->neutron_xs_[i_nuc].fission) { - double nu = p->neutron_xs_[i_nuc].nu_fission - / p->neutron_xs_[i_nuc].fission; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - cum_dsig += nu * dsig_f * material.atom_density_(i); - } - } - score *= flux_deriv + cum_dsig / p->macro_xs_.nu_fission; - } else if (p->neutron_xs_[i_nuclide].fission) { - const auto& nuc {*data::nuclides[i_nuclide]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - score *= flux_deriv - + dsig_f / p->neutron_xs_[i_nuclide].fission; - } else { - score *= flux_deriv; - } - break; - - default: - break; - } - break; - - default: - fatal_error("Differential tallies are only implemented for analog and " - "collision estimators."); - } - break; - } -} - -void -score_track_derivative(const Particle* p, double distance) -{ - // A void material cannot be perturbed so it will not affect flux derivatives. - if (p->material_ == MATERIAL_VOID) return; - const Material& material {*model::materials[p->material_]}; - - for (auto& deriv : model::tally_derivs) { - if (deriv.diff_material != material.id_) continue; - - switch (deriv.variable) { - - case DIFF_DENSITY: - // phi is proportional to e^(-Sigma_tot * dist) - // (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist - // (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist - deriv.flux_deriv -= distance * p->macro_xs_.total - / material.density_gpcc_; - break; - - case DIFF_NUCLIDE_DENSITY: - // phi is proportional to e^(-Sigma_tot * dist) - // (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist - // (1 / phi) * (d_phi / d_N) = - sigma_tot * dist - deriv.flux_deriv -= distance - * p->neutron_xs_[deriv.diff_nuclide].total; - break; - - case DIFF_TEMPERATURE: - for (auto i = 0; i < material.nuclide_.size(); ++i) { - const auto& nuc {*data::nuclides[material.nuclide_[i]]}; - if (multipole_in_range(&nuc, p->E_last_)) { - // phi is proportional to e^(-Sigma_tot * dist) - // (1 / phi) * (d_phi / d_T) = - (d_Sigma_tot / d_T) * dist - // (1 / phi) * (d_phi / d_T) = - N (d_sigma_tot / d_T) * dist - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_, p->sqrtkT_); - deriv.flux_deriv -= distance * (dsig_s + dsig_a) - * material.atom_density_(i); - } - } - break; - } - } -} - -void score_collision_derivative(const Particle* p) -{ - // A void material cannot be perturbed so it will not affect flux derivatives. - if (p->material_ == MATERIAL_VOID) return; - const Material& material {*model::materials[p->material_]}; - - for (auto& deriv : model::tally_derivs) { - if (deriv.diff_material != material.id_) continue; - - switch (deriv.variable) { - - case DIFF_DENSITY: - // phi is proportional to Sigma_s - // (1 / phi) * (d_phi / d_rho) = (d_Sigma_s / d_rho) / Sigma_s - // (1 / phi) * (d_phi / d_rho) = 1 / rho - deriv.flux_deriv += 1. / material.density_gpcc_; - break; - - case DIFF_NUCLIDE_DENSITY: - if (p->event_nuclide_ != deriv.diff_nuclide) continue; - // Find the index in this material for the diff_nuclide. - int i; - for (i = 0; i < material.nuclide_.size(); ++i) - if (material.nuclide_[i] == deriv.diff_nuclide) break; - // Make sure we found the nuclide. - if (material.nuclide_[i] != deriv.diff_nuclide) { - std::stringstream err_msg; - err_msg << "Could not find nuclide " - << data::nuclides[deriv.diff_nuclide]->name_ << " in material " - << material.id_ << " for tally derivative " << deriv.id; - fatal_error(err_msg); - } - // phi is proportional to Sigma_s - // (1 / phi) * (d_phi / d_N) = (d_Sigma_s / d_N) / Sigma_s - // (1 / phi) * (d_phi / d_N) = sigma_s / Sigma_s - // (1 / phi) * (d_phi / d_N) = 1 / N - deriv.flux_deriv += 1. / material.atom_density_(i); - break; - - case DIFF_TEMPERATURE: - // Loop over the material's nuclides until we find the event nuclide. - for (auto i_nuc : material.nuclide_) { - const auto& nuc {*data::nuclides[i_nuc]}; - if (i_nuc == p->event_nuclide_ && multipole_in_range(&nuc, p->E_last_)) { - // phi is proportional to Sigma_s - // (1 / phi) * (d_phi / d_T) = (d_Sigma_s / d_T) / Sigma_s - // (1 / phi) * (d_phi / d_T) = (d_sigma_s / d_T) / sigma_s - const auto& micro_xs {p->neutron_xs_[i_nuc]}; - double dsig_s, dsig_a, dsig_f; - std::tie(dsig_s, dsig_a, dsig_f) - = nuc.multipole_->evaluate_deriv(p->E_last_, p->sqrtkT_); - deriv.flux_deriv += dsig_s / (micro_xs.total - micro_xs.absorption); - // Note that this is an approximation! The real scattering cross - // section is - // Sigma_s(E'->E, u'->u) = Sigma_s(E') * P(E'->E, u'->u). - // We are assuming that d_P(E'->E, u'->u) / d_T = 0 and only - // computing d_S(E') / d_T. Using this approximation in the vicinity - // of low-energy resonances causes errors (~2-5% for PWR pincell - // eigenvalue derivatives). - } - } - break; - } - } -} - -void zero_flux_derivs() -{ - for (auto& deriv : model::tally_derivs) deriv.flux_deriv = 0.; -} - -}// namespace openmc diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp deleted file mode 100644 index c67eec830..000000000 --- a/src/tallies/filter.cpp +++ /dev/null @@ -1,249 +0,0 @@ -#include "openmc/tallies/filter.h" - -#include // for max -#include // for strcpy -#include - -#include "openmc/capi.h" -#include "openmc/constants.h" // for MAX_LINE_LEN; -#include "openmc/error.h" -#include "openmc/xml_interface.h" -#include "openmc/tallies/filter_azimuthal.h" -#include "openmc/tallies/filter_cell.h" -#include "openmc/tallies/filter_cellborn.h" -#include "openmc/tallies/filter_cellfrom.h" -#include "openmc/tallies/filter_delayedgroup.h" -#include "openmc/tallies/filter_distribcell.h" -#include "openmc/tallies/filter_energyfunc.h" -#include "openmc/tallies/filter_energy.h" -#include "openmc/tallies/filter_legendre.h" -#include "openmc/tallies/filter_material.h" -#include "openmc/tallies/filter_mesh.h" -#include "openmc/tallies/filter_meshsurface.h" -#include "openmc/tallies/filter_mu.h" -#include "openmc/tallies/filter_particle.h" -#include "openmc/tallies/filter_polar.h" -#include "openmc/tallies/filter_sph_harm.h" -#include "openmc/tallies/filter_sptl_legendre.h" -#include "openmc/tallies/filter_surface.h" -#include "openmc/tallies/filter_universe.h" -#include "openmc/tallies/filter_zernike.h" - -// explicit template instantiation definition -template class std::vector; - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - std::vector filter_matches; -} - -namespace model { - std::vector> tally_filters; - std::unordered_map filter_map; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -extern "C" size_t tally_filters_size() -{ - return model::tally_filters.size(); -} - -//============================================================================== -// Filter implementation -//============================================================================== - -Filter::Filter() : index_{model::tally_filters.size()} -{ } - -Filter::~Filter() -{ - model::filter_map.erase(id_); -} - -Filter* Filter::create(pugi::xml_node node) -{ - // Copy filter id - if (!check_for_node(node, "id")) { - fatal_error("Must specify id for filter in tally XML file."); - } - int filter_id = std::stoi(get_node_value(node, "id")); - - // Convert filter type to lower case - std::string s; - if (check_for_node(node, "type")) { - s = get_node_value(node, "type", true); - } - - // Allocate according to the filter type - auto f = Filter::create(s, filter_id); - - // Read filter data from XML - f->from_xml(node); - return f; -} - -Filter* Filter::create(const std::string& type, int32_t id) -{ - if (type == "azimuthal") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "cell") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "cellborn") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "cellfrom") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "distribcell") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "delayedgroup") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "energyfunction") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "energy") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "energyout") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "legendre") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "material") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "mesh") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "meshsurface") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "mu") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "particle") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "polar") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "surface") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "spatiallegendre") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "sphericalharmonics") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "universe") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "zernike") { - model::tally_filters.push_back(std::make_unique()); - } else if (type == "zernikeradial") { - model::tally_filters.push_back(std::make_unique()); - } else { - throw std::runtime_error{"Unknown filter type: " + type}; - } - - // Assign ID - model::tally_filters.back()->set_id(id); - - return model::tally_filters.back().get(); -} - -void Filter::set_id(int32_t id) -{ - Expects(id >= -1); - - // Clear entry in filter map if an ID was already assigned before - if (id_ != -1) { - model::filter_map.erase(id_); - id_ = -1; - } - - // Make sure no other filter has same ID - if (model::filter_map.find(id) != model::filter_map.end()) { - throw std::runtime_error{"Two filters have the same ID: " + std::to_string(id)}; - } - - // If no ID specified, auto-assign next ID in sequence - if (id == -1) { - id = 0; - for (const auto& f : model::tally_filters) { - id = std::max(id, f->id_); - } - ++id; - } - - // Update ID and entry in filter map - id_ = id; - model::filter_map[id] = index_; -} - -//============================================================================== -// C API functions -//============================================================================== - -int verify_filter(int32_t index) -{ - if (index < 0 || index >= model::tally_filters.size()) { - set_errmsg("Filter index is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - return 0; -} - -extern "C" int -openmc_filter_get_id(int32_t index, int32_t* id) -{ - if (int err = verify_filter(index)) return err; - - *id = model::tally_filters[index]->id(); - return 0; -} - -extern "C" int -openmc_filter_set_id(int32_t index, int32_t id) -{ - if (int err = verify_filter(index)) return err; - - model::tally_filters[index]->set_id(id); - return 0; -} - -extern "C" int -openmc_filter_get_type(int32_t index, char* type) -{ - if (int err = verify_filter(index)) return err; - - std::strcpy(type, model::tally_filters[index]->type().c_str()); - return 0; -} - -extern "C" int -openmc_get_filter_index(int32_t id, int32_t* index) -{ - auto it = model::filter_map.find(id); - if (it == model::filter_map.end()) { - set_errmsg("No filter exists with ID=" + std::to_string(id) + "."); - return OPENMC_E_INVALID_ID; - } - - *index = it->second; - return 0; -} - -extern "C" void -openmc_get_filter_next_id(int32_t* id) -{ - int32_t largest_filter_id = 0; - for (const auto& t : model::tally_filters) { - largest_filter_id = std::max(largest_filter_id, t->id()); - } - *id = largest_filter_id + 1; -} - -extern "C" int -openmc_new_filter(const char* type, int32_t* index) -{ - *index = model::tally_filters.size(); - Filter::create(type); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_azimuthal.cpp b/src/tallies/filter_azimuthal.cpp deleted file mode 100644 index eb02319c2..000000000 --- a/src/tallies/filter_azimuthal.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "openmc/tallies/filter_azimuthal.h" - -#include -#include - -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/search.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -AzimuthalFilter::from_xml(pugi::xml_node node) -{ - auto bins = get_node_array(node, "bins"); - - if (bins.size() == 1) { - // Allow a user to input a lone number which will mean that you subdivide - // [-pi,pi) evenly with the input being the number of bins - - int n_angle = bins[0]; - if (n_angle <= 1) throw std::runtime_error{ - "Number of bins for azimuthal filter must be greater than 1."}; - - double d_angle = 2.0 * PI / n_angle; - bins.resize(n_angle + 1); - for (int i = 0; i < n_angle; i++) bins[i] = -PI + i * d_angle; - bins[n_angle] = PI; - } - - this->set_bins(bins); -} - -void AzimuthalFilter::set_bins(gsl::span bins) -{ - // Clear existing bins - bins_.clear(); - bins_.reserve(bins.size()); - - // Copy bins, ensuring they are valid - for (gsl::index i = 0; i < bins.size(); ++i) { - if (i > 0 && bins[i] <= bins[i-1]) { - throw std::runtime_error{"Azimuthal bins must be monotonically increasing."}; - } - bins_.push_back(bins[i]); - } - - n_bins_ = bins_.size() - 1; -} - -void -AzimuthalFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - double phi; - if (estimator == ESTIMATOR_TRACKLENGTH) { - phi = std::atan2(p->u().y, p->u().x); - } else { - phi = std::atan2(p->u_last_.y, p->u_last_.x); - } - - if (phi >= bins_.front() && phi <= bins_.back()) { - auto bin = lower_bound_index(bins_.begin(), bins_.end(), phi); - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } -} - -void -AzimuthalFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", bins_); -} - -std::string -AzimuthalFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Azimuthal Angle [" << bins_[bin] << ", " << bins_[bin+1] << ")"; - return out.str(); -} - -} // namespace openmc diff --git a/src/tallies/filter_cell.cpp b/src/tallies/filter_cell.cpp deleted file mode 100644 index 7cc007756..000000000 --- a/src/tallies/filter_cell.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "openmc/tallies/filter_cell.h" - -#include - -#include "openmc/capi.h" -#include "openmc/cell.h" -#include "openmc/error.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -CellFilter::from_xml(pugi::xml_node node) -{ - // Get cell IDs and convert into indices into the global cells vector - auto cells = get_node_array(node, "bins"); - for (auto& c : cells) { - auto search = model::cell_map.find(c); - if (search == model::cell_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find cell " << c - << " specified on tally filter."; - throw std::runtime_error{err_msg.str()}; - } - c = search->second; - } - - this->set_cells(cells); -} - -void -CellFilter::set_cells(gsl::span cells) -{ - // Clear existing cells - cells_.clear(); - cells_.reserve(cells.size()); - map_.clear(); - - // Update cells and mapping - for (auto& index : cells) { - Expects(index >= 0); - Expects(index < model::cells.size()); - cells_.push_back(index); - map_[index] = cells_.size() - 1; - } - - n_bins_ = cells_.size(); -} - -void -CellFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - for (int i = 0; i < p->n_coord_; i++) { - auto search = map_.find(p->coord_[i].cell); - if (search != map_.end()) { - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } - } -} - -void -CellFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - std::vector cell_ids; - for (auto c : cells_) cell_ids.push_back(model::cells[c]->id_); - write_dataset(filter_group, "bins", cell_ids); -} - -std::string -CellFilter::text_label(int bin) const -{ - return "Cell " + std::to_string(model::cells[cells_[bin]]->id_); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_cell_filter_get_bins(int32_t index, const int32_t** cells, int32_t* n) -{ - if (int err = verify_filter(index)) return err; - - const auto& filt = model::tally_filters[index].get(); - if (filt->type() != "cell") { - set_errmsg("Tried to get cells from a non-cell filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto cell_filt = static_cast(filt); - *cells = cell_filt->cells().data(); - *n = cell_filt->cells().size(); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_cellborn.cpp b/src/tallies/filter_cellborn.cpp deleted file mode 100644 index 150962297..000000000 --- a/src/tallies/filter_cellborn.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "openmc/tallies/filter_cellborn.h" - -#include "openmc/cell.h" - -namespace openmc { - -void -CellbornFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - auto search = map_.find(p->cell_born_); - if (search != map_.end()) { - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } -} - -std::string -CellbornFilter::text_label(int bin) const -{ - return "Birth Cell " + std::to_string(model::cells[cells_[bin]]->id_); -} - -} // namespace openmc diff --git a/src/tallies/filter_cellfrom.cpp b/src/tallies/filter_cellfrom.cpp deleted file mode 100644 index b8e5d0b07..000000000 --- a/src/tallies/filter_cellfrom.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "openmc/tallies/filter_cellfrom.h" - -#include "openmc/cell.h" - -namespace openmc { - -void -CellFromFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - for (int i = 0; i < p->n_coord_last_; i++) { - auto search = map_.find(p->cell_last_[i]); - if (search != map_.end()) { - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } - } -} - -std::string -CellFromFilter::text_label(int bin) const -{ - return "Cell from " + std::to_string(model::cells[cells_[bin]]->id_); -} - -} // namespace openmc diff --git a/src/tallies/filter_delayedgroup.cpp b/src/tallies/filter_delayedgroup.cpp deleted file mode 100644 index 2b6978308..000000000 --- a/src/tallies/filter_delayedgroup.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "openmc/tallies/filter_delayedgroup.h" - -#include "openmc/error.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -DelayedGroupFilter::from_xml(pugi::xml_node node) -{ - auto groups = get_node_array(node, "bins"); - this->set_groups(groups); -} - -void -DelayedGroupFilter::set_groups(gsl::span groups) -{ - // Clear existing groups - groups_.clear(); - groups_.reserve(groups.size()); - - // Make sure all the group index values are valid. - // TODO: do these need to be decremented for zero-based indexing? - for (auto group : groups) { - if (group < 1) { - throw std::invalid_argument{"Encountered delayedgroup bin with index " - + std::to_string(group) + " which is less than 1"}; - } else if (group > MAX_DELAYED_GROUPS) { - throw std::invalid_argument{"Encountered delayedgroup bin with index " - + std::to_string(group) + " which is greater than MAX_DELATED_GROUPS (" - + std::to_string(MAX_DELAYED_GROUPS) + ")"}; - } - groups_.push_back(group); - } - - n_bins_ = groups_.size(); -} - -void -DelayedGroupFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - match.bins_.push_back(0); - match.weights_.push_back(1.0); -} - -void -DelayedGroupFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", groups_); -} - -std::string -DelayedGroupFilter::text_label(int bin) const -{ - return "Delayed Group " + std::to_string(groups_[bin]); -} - -} // namespace openmc diff --git a/src/tallies/filter_distribcell.cpp b/src/tallies/filter_distribcell.cpp deleted file mode 100644 index f9c7ab4d6..000000000 --- a/src/tallies/filter_distribcell.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "openmc/tallies/filter_distribcell.h" - -#include "openmc/cell.h" -#include "openmc/error.h" -#include "openmc/geometry_aux.h" // For distribcell_path -#include "openmc/lattice.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -DistribcellFilter::from_xml(pugi::xml_node node) -{ - auto cells = get_node_array(node, "bins"); - if (cells.size() != 1) { - fatal_error("Only one cell can be specified per distribcell filter."); - } - - // Find index in global cells vector corresponding to cell ID - auto search = model::cell_map.find(cells[0]); - if (search == model::cell_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find cell " << cell_ - << " specified on tally filter."; - throw std::runtime_error{err_msg.str()}; - } - - this->set_cell(search->second); -} - -void -DistribcellFilter::set_cell(int32_t cell) -{ - Expects(cell >= 0); - Expects(cell < model::cells.size()); - cell_ = cell; - n_bins_ = model::cells[cell]->n_instances_; -} - -void -DistribcellFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - int offset = 0; - auto distribcell_index = model::cells[cell_]->distribcell_index_; - for (int i = 0; i < p->n_coord_; i++) { - auto& c {*model::cells[p->coord_[i].cell]}; - if (c.type_ == FILL_UNIVERSE) { - offset += c.offset_[distribcell_index]; - } else if (c.type_ == FILL_LATTICE) { - auto& lat {*model::lattices[p->coord_[i+1].lattice]}; - int i_xyz[3] {p->coord_[i+1].lattice_x, - p->coord_[i+1].lattice_y, - p->coord_[i+1].lattice_z}; - if (lat.are_valid_indices(i_xyz)) { - offset += lat.offset(distribcell_index, i_xyz); - } - } - if (cell_ == p->coord_[i].cell) { - match.bins_.push_back(offset); - match.weights_.push_back(1.0); - return; - } - } -} - -void -DistribcellFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", model::cells[cell_]->id_); -} - -std::string -DistribcellFilter::text_label(int bin) const -{ - auto map = model::cells[cell_]->distribcell_index_; - auto path = distribcell_path(cell_, map, bin); - return "Distributed Cell " + path; -} - -} // namespace openmc diff --git a/src/tallies/filter_energy.cpp b/src/tallies/filter_energy.cpp deleted file mode 100644 index dde9b692a..000000000 --- a/src/tallies/filter_energy.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "openmc/tallies/filter_energy.h" - -#include "openmc/capi.h" -#include "openmc/constants.h" // For F90_NONE -#include "openmc/mgxs_interface.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// EnergyFilter implementation -//============================================================================== - -void -EnergyFilter::from_xml(pugi::xml_node node) -{ - auto bins = get_node_array(node, "bins"); - this->set_bins(bins); -} - -void -EnergyFilter::set_bins(gsl::span bins) -{ - // Clear existing bins - bins_.clear(); - bins_.reserve(bins.size()); - - // Copy bins, ensuring they are valid - for (gsl::index i = 0; i < bins.size(); ++i) { - if (i > 0 && bins[i] <= bins[i-1]) { - throw std::runtime_error{"Energy bins must be monotonically increasing."}; - } - bins_.push_back(bins[i]); - } - - n_bins_ = bins_.size() - 1; - - // In MG mode, check if the filter bins match the transport bins. - // We can save tallying time if we know that the tally bins match the energy - // group structure. In that case, the matching bin index is simply the group - // (after flipping for the different ordering of the library and tallying - // systems). - if (!settings::run_CE) { - if (n_bins_ == data::num_energy_groups) { - matches_transport_groups_ = true; - for (gsl::index i = 0; i < n_bins_ + 1; ++i) { - if (data::rev_energy_bins[i] != bins_[i]) { - matches_transport_groups_ = false; - break; - } - } - } - } -} - -void -EnergyFilter::get_all_bins(const Particle* p, int estimator, FilterMatch& match) -const -{ - if (p->g_ != F90_NONE && matches_transport_groups_) { - if (estimator == ESTIMATOR_TRACKLENGTH) { - match.bins_.push_back(data::num_energy_groups - p->g_); - } else { - match.bins_.push_back(data::num_energy_groups - p->g_last_); - } - match.weights_.push_back(1.0); - - } else { - // Get the pre-collision energy of the particle. - auto E = p->E_last_; - - // Bin the energy. - if (E >= bins_.front() && E <= bins_.back()) { - auto bin = lower_bound_index(bins_.begin(), bins_.end(), E); - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } - } -} - -void -EnergyFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", bins_); -} - -std::string -EnergyFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Incoming Energy [" << bins_[bin] << ", " << bins_[bin+1] << ")"; - return out.str(); -} - -//============================================================================== -// EnergyoutFilter implementation -//============================================================================== - -void -EnergyoutFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - if (p->g_ != F90_NONE && matches_transport_groups_) { - match.bins_.push_back(data::num_energy_groups - p->g_); - match.weights_.push_back(1.0); - - } else { - if (p->E_ >= bins_.front() && p->E_ <= bins_.back()) { - auto bin = lower_bound_index(bins_.begin(), bins_.end(), p->E_); - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } - } -} - -std::string -EnergyoutFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Outgoing Energy [" << bins_[bin] << ", " << bins_[bin+1] << ")"; - return out.str(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern"C" int -openmc_energy_filter_get_bins(int32_t index, const double** energies, size_t* n) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to get energy bins on a non-energy filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Output the bins. - *energies = filt->bins().data(); - *n = filt->bins().size(); - return 0; -} - -extern "C" int -openmc_energy_filter_set_bins(int32_t index, size_t n, const double* energies) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to set energy bins on a non-energy filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Update the filter. - filt->set_bins({energies, n}); - return 0; -} - -}// namespace openmc diff --git a/src/tallies/filter_energyfunc.cpp b/src/tallies/filter_energyfunc.cpp deleted file mode 100644 index 3e3fbd909..000000000 --- a/src/tallies/filter_energyfunc.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "openmc/tallies/filter_energyfunc.h" - -#include // for setprecision -#include // for scientific -#include - -#include "openmc/error.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -EnergyFunctionFilter::from_xml(pugi::xml_node node) -{ - if (!settings::run_CE) - fatal_error("EnergyFunction filters are only supported for " - "continuous-energy transport calculations"); - - if (!check_for_node(node, "energy")) - fatal_error("Energy grid not specified for EnergyFunction filter."); - - auto energy = get_node_array(node, "energy"); - - if (!check_for_node(node, "y")) - fatal_error("y values not specified for EnergyFunction filter."); - - auto y = get_node_array(node, "y"); - - this->set_data(energy, y); -} - -void -EnergyFunctionFilter::set_data(gsl::span energy, - gsl::span y) -{ - // Check for consistent sizes with new data - if (energy.size() != y.size()) { - fatal_error("Energy grid and y values are not consistent"); - } - energy_.clear(); - energy_.reserve(energy.size()); - y_.clear(); - y_.reserve(y.size()); - - // Copy over energy values, ensuring they are valid - for (gsl::index i = 0; i < energy.size(); ++i) { - if (i > 0 && energy[i] <= energy[i - 1]) { - throw std::runtime_error{"Energy bins must be monotonically increasing."}; - } - energy_.push_back(energy[i]); - y_.push_back(y[i]); - } -} - -void -EnergyFunctionFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - if (p->E_last_ >= energy_.front() && p->E_last_ <= energy_.back()) { - // Search for the incoming energy bin. - auto i = lower_bound_index(energy_.begin(), energy_.end(), p->E_last_); - - // Compute the interpolation factor between the nearest bins. - double f = (p->E_last_ - energy_[i]) / (energy_[i+1] - energy_[i]); - - // Interpolate on the lin-lin grid. - match.bins_.push_back(0); - match.weights_.push_back((1-f) * y_[i] + f * y_[i+1]); - } -} - -void -EnergyFunctionFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "energy", energy_); - write_dataset(filter_group, "y", y_); -} - -std::string -EnergyFunctionFilter::text_label(int bin) const -{ - std::stringstream out; - out << std::scientific << std::setprecision(1) - << "Energy Function f" - << "([ " << energy_.front() << ", ..., " << energy_.back() << "]) = " - << "[" << y_.front() << ", ..., " << y_.back() << "]"; - return out.str(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_energyfunc_filter_set_data(int32_t index, size_t n, const double* energy, - const double* y) -{ - // Ensure this is a valid index to allocated filter - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter - const auto& filt_base = model::tally_filters[index].get(); - // Downcast to EnergyFunctionFilter - auto* filt = dynamic_cast(filt_base); - - // Check if a valid filter was produced - if (!filt) { - set_errmsg("Tried to set interpolation data for non-energy function filter."); - return OPENMC_E_INVALID_TYPE; - } - - filt->set_data({energy, n}, {y, n}); - return 0; -} - -extern "C" int -openmc_energyfunc_filter_get_energy(int32_t index, size_t *n, const double** energy) -{ - // ensure this is a valid index to allocated filter - if (int err = verify_filter(index)) return err; - - // get a pointer to the filter - const auto& filt_base = model::tally_filters[index].get(); - // downcast to EnergyFunctionFilter - auto* filt = dynamic_cast(filt_base); - - // check if a valid filter was produced - if (!filt) { - set_errmsg("Tried to set interpolation data for non-energy function filter."); - return OPENMC_E_INVALID_TYPE; - } - *energy = filt->energy().data(); - *n = filt->energy().size(); - return 0; -} - -extern "C" int -openmc_energyfunc_filter_get_y(int32_t index, size_t *n, const double** y) -{ - // ensure this is a valid index to allocated filter - if (int err = verify_filter(index)) return err; - - // get a pointer to the filter - const auto& filt_base = model::tally_filters[index].get(); - // downcast to EnergyFunctionFilter - auto* filt = dynamic_cast(filt_base); - - // check if a valid filter was produced - if (!filt) { - set_errmsg("Tried to set interpolation data for non-energy function filter."); - return OPENMC_E_INVALID_TYPE; - } - *y = filt->y().data(); - *n = filt->y().size(); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_legendre.cpp b/src/tallies/filter_legendre.cpp deleted file mode 100644 index 3961e06d4..000000000 --- a/src/tallies/filter_legendre.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "openmc/tallies/filter_legendre.h" - -#include "openmc/capi.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -LegendreFilter::from_xml(pugi::xml_node node) -{ - this->set_order(std::stoi(get_node_value(node, "order"))); -} - -void -LegendreFilter::set_order(int order) -{ - if (order < 0) { - throw std::invalid_argument{"Legendre order must be non-negative."}; - } - order_ = order; - n_bins_ = order_ + 1; -} - -void -LegendreFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - std::vector wgt(n_bins_); - calc_pn_c(order_, p->mu_, wgt.data()); - for (int i = 0; i < n_bins_; i++) { - match.bins_.push_back(i); - match.weights_.push_back(wgt[i]); - } -} - -void -LegendreFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "order", order_); -} - -std::string -LegendreFilter::text_label(int bin) const -{ - return "Legendre expansion, P" + std::to_string(bin); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_legendre_filter_get_order(int32_t index, int* order) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Not a legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Output the order. - *order = filt->order(); - return 0; -} - -extern "C" int -openmc_legendre_filter_set_order(int32_t index, int order) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Not a legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Update the filter. - filt->set_order(order); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_material.cpp b/src/tallies/filter_material.cpp deleted file mode 100644 index bfc216244..000000000 --- a/src/tallies/filter_material.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "openmc/tallies/filter_material.h" - -#include - -#include "openmc/capi.h" -#include "openmc/material.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -MaterialFilter::from_xml(pugi::xml_node node) -{ - // Get material IDs and convert to indices in the global materials vector - auto mats = get_node_array(node, "bins"); - for (auto& m : mats) { - auto search = model::material_map.find(m); - if (search == model::material_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find material " << m - << " specified on tally filter."; - throw std::runtime_error{err_msg.str()}; - } - m = search->second; - } - - this->set_materials(mats); -} - -void -MaterialFilter::set_materials(gsl::span materials) -{ - // Clear existing materials - materials_.clear(); - materials_.reserve(materials.size()); - map_.clear(); - - // Update materials and mapping - for (auto& index : materials) { - Expects(index >= 0); - Expects(index < model::materials.size()); - materials_.push_back(index); - map_[index] = materials_.size() - 1; - } - - n_bins_ = materials_.size(); -} - -void -MaterialFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - auto search = map_.find(p->material_); - if (search != map_.end()) { - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } -} - -void -MaterialFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - std::vector material_ids; - for (auto c : materials_) material_ids.push_back(model::materials[c]->id_); - write_dataset(filter_group, "bins", material_ids); -} - -std::string -MaterialFilter::text_label(int bin) const -{ - return "Material " + std::to_string(model::materials[materials_[bin]]->id_); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_material_filter_get_bins(int32_t index, const int32_t** bins, size_t* n) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to get material filter bins on a non-material filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Output the bins. - *bins = filt->materials().data(); - *n = filt->materials().size(); - return 0; -} - -extern "C" int -openmc_material_filter_set_bins(int32_t index, size_t n, const int32_t* bins) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to set material filter bins on a non-material filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Update the filter. - filt->set_materials({bins, n}); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_mesh.cpp b/src/tallies/filter_mesh.cpp deleted file mode 100644 index e6fdad31e..000000000 --- a/src/tallies/filter_mesh.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "openmc/tallies/filter_mesh.h" - -#include - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/mesh.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -MeshFilter::from_xml(pugi::xml_node node) -{ - auto bins_ = get_node_array(node, "bins"); - if (bins_.size() != 1) { - fatal_error("Only one mesh can be specified per " + type() - + " mesh filter."); - } - - auto id = bins_[0]; - auto search = model::mesh_map.find(id); - if (search != model::mesh_map.end()) { - set_mesh(search->second); - } else{ - std::stringstream err_msg; - err_msg << "Could not find mesh " << id << " specified on tally filter."; - fatal_error(err_msg); - } -} - -void -MeshFilter::get_all_bins(const Particle* p, int estimator, FilterMatch& match) -const -{ - if (estimator != ESTIMATOR_TRACKLENGTH) { - auto bin = model::meshes[mesh_]->get_bin(p->r()); - if (bin >= 0) { - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } - } else { - model::meshes[mesh_]->bins_crossed(p, match.bins_, match.weights_); - } -} - -void -MeshFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", model::meshes[mesh_]->id_); -} - -std::string -MeshFilter::text_label(int bin) const -{ - auto& mesh = *model::meshes[mesh_]; - int n_dim = mesh.n_dimension_; - - std::vector ijk(n_dim); - mesh.get_indices_from_bin(bin, ijk.data()); - - std::stringstream out; - out << "Mesh Index (" << ijk[0]; - if (n_dim > 1) out << ", " << ijk[1]; - if (n_dim > 2) out << ", " << ijk[2]; - out << ")"; - - return out.str(); -} - -void -MeshFilter::set_mesh(int32_t mesh) -{ - mesh_ = mesh; - n_bins_ = model::meshes[mesh_]->n_bins(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to get mesh on a non-mesh filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Output the mesh. - *index_mesh = filt->mesh(); - return 0; -} - -extern "C" int -openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh) -{ - // Make sure this is a valid index to an allocated filter. - if (int err = verify_filter(index)) return err; - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Tried to set mesh on a non-mesh filter."); - return OPENMC_E_INVALID_TYPE; - } - - // Check the mesh index. - if (index_mesh < 0 || index_mesh >= model::meshes.size()) { - set_errmsg("Index in 'meshes' array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - // Update the filter. - filt->set_mesh(index_mesh); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_meshsurface.cpp b/src/tallies/filter_meshsurface.cpp deleted file mode 100644 index edb0492e9..000000000 --- a/src/tallies/filter_meshsurface.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "openmc/tallies/filter_meshsurface.h" - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/mesh.h" - -namespace openmc { - -void -MeshSurfaceFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - model::meshes[mesh_]->surface_bins_crossed(p, match.bins_); - for (auto b : match.bins_) match.weights_.push_back(1.0); -} - -std::string -MeshSurfaceFilter::text_label(int bin) const -{ - auto& mesh = *model::meshes[mesh_]; - int n_dim = mesh.n_dimension_; - - // Get flattend mesh index and surface index. - int i_mesh = bin / (4 * n_dim); - int i_surf = (bin % (4 * n_dim)) + 1; - - // Get mesh index part of label. - std::string out = MeshFilter::text_label(i_mesh); - - // Get surface part of label. - switch (i_surf) { - case OUT_LEFT: - out += " Outgoing, x-min"; - break; - case IN_LEFT: - out += " Incoming, x-min"; - break; - case OUT_RIGHT: - out += " Outgoing, x-max"; - break; - case IN_RIGHT: - out += " Incoming, x-max"; - break; - case OUT_BACK: - out += " Outgoing, y-min"; - break; - case IN_BACK: - out += " Incoming, y-min"; - break; - case OUT_FRONT: - out += " Outgoing, y-max"; - break; - case IN_FRONT: - out += " Incoming, y-max"; - break; - case OUT_BOTTOM: - out += " Outgoing, z-min"; - break; - case IN_BOTTOM: - out += " Incoming, z-min"; - break; - case OUT_TOP: - out += " Outgoing, z-max"; - break; - case IN_TOP: - out += " Incoming, z-max"; - break; - } - - return out; -} - -void -MeshSurfaceFilter::set_mesh(int32_t mesh) -{ - mesh_ = mesh; - n_bins_ = model::meshes[mesh_]->n_surface_bins(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern"C" int -openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh) -{return openmc_mesh_filter_get_mesh(index, index_mesh);} - -extern"C" int -openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh) -{return openmc_mesh_filter_set_mesh(index, index_mesh);} - -} // namespace openmc diff --git a/src/tallies/filter_mu.cpp b/src/tallies/filter_mu.cpp deleted file mode 100644 index 9aaebea8c..000000000 --- a/src/tallies/filter_mu.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "openmc/tallies/filter_mu.h" - -#include - -#include "openmc/error.h" -#include "openmc/search.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -MuFilter::from_xml(pugi::xml_node node) -{ - auto bins = get_node_array(node, "bins"); - - if (bins.size() == 1) { - // Allow a user to input a lone number which will mean that you subdivide - // [-1,1) evenly with the input being the number of bins - - int n_angle = bins[0]; - if (n_angle <= 1) throw std::runtime_error{ - "Number of bins for mu filter must be greater than 1."}; - - double d_angle = 2.0 / n_angle; - bins.resize(n_angle + 1); - for (int i = 0; i < n_angle; i++) bins[i] = -1 + i * d_angle; - bins[n_angle] = 1; - } - - this->set_bins(bins); -} - -void -MuFilter::set_bins(gsl::span bins) -{ - // Clear existing bins - bins_.clear(); - bins_.reserve(bins.size()); - - // Copy bins, ensuring they are valid - for (gsl::index i = 0; i < bins.size(); ++i) { - if (i > 0 && bins[i] <= bins[i-1]) { - throw std::runtime_error{"Mu bins must be monotonically increasing."}; - } - bins_.push_back(bins[i]); - } - - n_bins_ = bins_.size() - 1; -} - -void -MuFilter::get_all_bins(const Particle* p, int estimator, FilterMatch& match) -const -{ - if (p->mu_ >= bins_.front() && p->mu_ <= bins_.back()) { - auto bin = lower_bound_index(bins_.begin(), bins_.end(), p->mu_); - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } -} - -void -MuFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", bins_); -} - -std::string -MuFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Change-in-Angle [" << bins_[bin] << ", " << bins_[bin+1] << ")"; - return out.str(); -} - -} // namespace openmc diff --git a/src/tallies/filter_particle.cpp b/src/tallies/filter_particle.cpp deleted file mode 100644 index eb419fec9..000000000 --- a/src/tallies/filter_particle.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "openmc/tallies/filter_particle.h" - -#include "openmc/xml_interface.h" - -namespace openmc { - -void -ParticleFilter::from_xml(pugi::xml_node node) -{ - auto particles = get_node_array(node, "bins"); - - // Convert to vector of Particle::Type - std::vector types; - for (auto& p : particles) { - if (p == "neutron") { - types.push_back(Particle::Type::neutron); - } else if (p == "photon") { - types.push_back(Particle::Type::photon); - } else if (p == "electron") { - types.push_back(Particle::Type::electron); - } else if (p == "positron") { - types.push_back(Particle::Type::positron); - } - } - this->set_particles(types); -} - -void -ParticleFilter::set_particles(gsl::span particles) -{ - // Clear existing particles - particles_.clear(); - particles_.reserve(particles.size()); - - // Set particles and number of bins - for (auto p : particles) { - particles_.push_back(p); - } - n_bins_ = particles_.size(); -} - -void -ParticleFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - for (auto i = 0; i < particles_.size(); i++) { - if (particles_[i] == p->type_) { - match.bins_.push_back(i); - match.weights_.push_back(1.0); - } - } -} - -void -ParticleFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - std::vector particles; - for (auto p : particles_) { - switch (p) { - case Particle::Type::neutron: - particles.push_back("neutron"); - break; - case Particle::Type::photon: - particles.push_back("photon"); - break; - case Particle::Type::electron: - particles.push_back("electron"); - break; - case Particle::Type::positron: - particles.push_back("positron"); - break; - } - } - write_dataset(filter_group, "bins", particles); -} - -std::string -ParticleFilter::text_label(int bin) const -{ - switch (particles_[bin]) { - case Particle::Type::neutron: - return "Particle: neutron"; - case Particle::Type::photon: - return "Particle: photon"; - case Particle::Type::electron: - return "Particle: electron"; - case Particle::Type::positron: - return "Particle: positron"; - } - UNREACHABLE(); -} - -} // namespace openmc diff --git a/src/tallies/filter_polar.cpp b/src/tallies/filter_polar.cpp deleted file mode 100644 index edbbc8922..000000000 --- a/src/tallies/filter_polar.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "openmc/tallies/filter_polar.h" - -#include - -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/search.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -PolarFilter::from_xml(pugi::xml_node node) -{ - auto bins = get_node_array(node, "bins"); - - if (bins.size() == 1) { - // Allow a user to input a lone number which will mean that you subdivide - // [0,pi] evenly with the input being the number of bins - - int n_angle = bins[0]; - if (n_angle <= 1) throw std::runtime_error{ - "Number of bins for polar filter must be greater than 1."}; - - double d_angle = PI / n_angle; - bins.resize(n_angle + 1); - for (int i = 0; i < n_angle; i++) bins[i] = i * d_angle; - bins[n_angle] = PI; - } - - this->set_bins(bins); -} - -void -PolarFilter::set_bins(gsl::span bins) -{ - // Clear existing bins - bins_.clear(); - bins_.reserve(bins.size()); - - // Copy bins, ensuring they are valid - for (gsl::index i = 0; i < bins.size(); ++i) { - if (i > 0 && bins[i] <= bins[i-1]) { - throw std::runtime_error{"Polar bins must be monotonically increasing."}; - } - bins_.push_back(bins[i]); - } - - n_bins_ = bins_.size() - 1; -} - -void -PolarFilter::get_all_bins(const Particle* p, int estimator, FilterMatch& match) -const -{ - double theta; - if (estimator == ESTIMATOR_TRACKLENGTH) { - theta = std::acos(p->u().z); - } else { - theta = std::acos(p->u_last_.z); - } - - if (theta >= bins_.front() && theta <= bins_.back()) { - auto bin = lower_bound_index(bins_.begin(), bins_.end(), theta); - match.bins_.push_back(bin); - match.weights_.push_back(1.0); - } -} - -void -PolarFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "bins", bins_); -} - -std::string -PolarFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Polar Angle [" << bins_[bin] << ", " << bins_[bin+1] << ")"; - return out.str(); -} - -} // namespace openmc diff --git a/src/tallies/filter_sph_harm.cpp b/src/tallies/filter_sph_harm.cpp deleted file mode 100644 index 80d6878b7..000000000 --- a/src/tallies/filter_sph_harm.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "openmc/tallies/filter_sph_harm.h" - -#include // For pair - -#include "openmc/capi.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -SphericalHarmonicsFilter::from_xml(pugi::xml_node node) -{ - this->set_order(std::stoi(get_node_value(node, "order"))); - if (check_for_node(node, "cosine")) { - this->set_cosine(get_node_value(node, "cosine", true)); - } -} - -void -SphericalHarmonicsFilter::set_order(int order) -{ - if (order < 0) { - throw std::invalid_argument{"Spherical harmonics order must be non-negative."}; - } - order_ = order; - n_bins_ = (order_ + 1) * (order_ + 1); -} - -void -SphericalHarmonicsFilter::set_cosine(gsl::cstring_span cosine) -{ - if (cosine == "scatter") { - cosine_ = SphericalHarmonicsCosine::scatter; - } else if (cosine == "particle") { - cosine_ = SphericalHarmonicsCosine::particle; - } else { - std::stringstream err_msg; - err_msg << "Unrecognized cosine type, \"" << cosine - << "\" in spherical harmonics filter"; - throw std::invalid_argument{err_msg.str()}; - } -} - -void -SphericalHarmonicsFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - // Determine cosine term for scatter expansion if necessary - std::vector wgt(order_ + 1); - if (cosine_ == SphericalHarmonicsCosine::scatter) { - calc_pn_c(order_, p->mu_, wgt.data()); - } else { - for (int i = 0; i < order_ + 1; i++) wgt[i] = 1; - } - - // Find the Rn,m values - std::vector rn(n_bins_); - calc_rn(order_, p->u_last_, rn.data()); - - int j = 0; - for (int n = 0; n < order_ + 1; n++) { - // Calculate n-th order spherical harmonics for (u,v,w) - int num_nm = 2*n + 1; - - // Append the matching (bin,weight) for each moment - for (int i = 0; i < num_nm; i++) { - match.weights_.push_back(wgt[n] * rn[j]); - match.bins_.push_back(j); - ++j; - } - } -} - -void -SphericalHarmonicsFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "order", order_); - if (cosine_ == SphericalHarmonicsCosine::scatter) { - write_dataset(filter_group, "cosine", "scatter"); - } else { - write_dataset(filter_group, "cosine", "particle"); - } -} - -std::string -SphericalHarmonicsFilter::text_label(int bin) const -{ - std::stringstream out; - for (int n = 0; n < order_ + 1; n++) { - if (bin < (n + 1) * (n + 1)) { - int m = (bin - n*n) - n; - out << "Spherical harmonic expansion, Y" << n << "," << m; - break; - } - } - return out.str(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -std::pair -check_sphharm_filter(int32_t index) -{ - // Make sure this is a valid index to an allocated filter. - int err = verify_filter(index); - if (err) { - return {err, nullptr}; - } - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Not a spherical harmonics filter."); - err = OPENMC_E_INVALID_TYPE; - } - return {err, filt}; -} - -extern "C" int -openmc_sphharm_filter_get_order(int32_t index, int* order) -{ - // Check the filter. - auto check_result = check_sphharm_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the order. - *order = filt->order(); - return 0; -} - -extern "C" int -openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]) -{ - // Check the filter. - auto check_result = check_sphharm_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the cosine. - if (filt->cosine() == SphericalHarmonicsCosine::scatter) { - strcpy(cosine, "scatter"); - } else { - strcpy(cosine, "particle"); - } - return 0; -} - -extern "C" int -openmc_sphharm_filter_set_order(int32_t index, int order) -{ - // Check the filter. - auto check_result = check_sphharm_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - filt->set_order(order); - return 0; -} - -extern "C" int -openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]) -{ - // Check the filter. - auto check_result = check_sphharm_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - try { - filt->set_cosine(cosine); - } catch (const std::invalid_argument& e) { - set_errmsg(e.what()); - return OPENMC_E_INVALID_ARGUMENT; - } - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_sptl_legendre.cpp b/src/tallies/filter_sptl_legendre.cpp deleted file mode 100644 index 40d82f4c1..000000000 --- a/src/tallies/filter_sptl_legendre.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include "openmc/tallies/filter_sptl_legendre.h" - -#include // For pair - -#include "openmc/capi.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -SpatialLegendreFilter::from_xml(pugi::xml_node node) -{ - this->set_order(std::stoi(get_node_value(node, "order"))); - - auto axis = get_node_value(node, "axis"); - switch (axis[0]) { - case 'x': - this->set_axis(LegendreAxis::x); - break; - case 'y': - this->set_axis(LegendreAxis::y); - break; - case 'z': - this->set_axis(LegendreAxis::z); - break; - default: - throw std::runtime_error{"Axis for SpatialLegendreFilter must be 'x', 'y', or 'z'"}; - } - - double min = std::stod(get_node_value(node, "min")); - double max = std::stod(get_node_value(node, "max")); - this->set_minmax(min, max); -} - -void -SpatialLegendreFilter::set_order(int order) -{ - if (order < 0) { - throw std::invalid_argument{"Legendre order must be non-negative."}; - } - order_ = order; - n_bins_ = order_ + 1; -} - -void -SpatialLegendreFilter::set_axis(LegendreAxis axis) -{ - axis_ = axis; -} - -void -SpatialLegendreFilter::set_minmax(double min, double max) -{ - if (max < min) { - throw std::invalid_argument{"Maximum value must be greater than minimum value"}; - } - min_ = min; - max_ = max; -} - -void -SpatialLegendreFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - // Get the coordinate along the axis of interest. - double x; - if (axis_ == LegendreAxis::x) { - x = p->r().x; - } else if (axis_ == LegendreAxis::y) { - x = p->r().y; - } else { - x = p->r().z; - } - - if (x >= min_ && x <= max_) { - // Compute the normalized coordinate value. - double x_norm = 2.0*(x - min_) / (max_ - min_) - 1.0; - - // Compute and return the Legendre weights. - std::vector wgt(order_ + 1); - calc_pn_c(order_, x_norm, wgt.data()); - for (int i = 0; i < order_ + 1; i++) { - match.bins_.push_back(i); - match.weights_.push_back(wgt[i]); - } - } -} - -void -SpatialLegendreFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "order", order_); - if (axis_ == LegendreAxis::x) { - write_dataset(filter_group, "axis", "x"); - } else if (axis_ == LegendreAxis::y) { - write_dataset(filter_group, "axis", "y"); - } else { - write_dataset(filter_group, "axis", "z"); - } - write_dataset(filter_group, "min", min_); - write_dataset(filter_group, "max", max_); -} - -std::string -SpatialLegendreFilter::text_label(int bin) const -{ - std::stringstream out; - out << "Legendre expansion, "; - if (axis_ == LegendreAxis::x) { - out << "x"; - } else if (axis_ == LegendreAxis::y) { - out << "y"; - } else { - out << "z"; - } - out << " axis, P" << std::to_string(bin); - return out.str(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -std::pair -check_sptl_legendre_filter(int32_t index) -{ - // Make sure this is a valid index to an allocated filter. - int err = verify_filter(index); - if (err) { - return {err, nullptr}; - } - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Not a spatial Legendre filter."); - err = OPENMC_E_INVALID_TYPE; - } - return {err, filt}; -} - -extern "C" int -openmc_spatial_legendre_filter_get_order(int32_t index, int* order) -{ - // Check the filter. - auto check_result = check_sptl_legendre_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the order. - *order = filt->order(); - return 0; -} - -extern "C" int -openmc_spatial_legendre_filter_get_params(int32_t index, int* axis, - double* min, double* max) -{ - // Check the filter. - auto check_result = check_sptl_legendre_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the params. - *axis = static_cast(filt->axis()); - *min = filt->min(); - *max = filt->max(); - return 0; -} - -extern "C" int -openmc_spatial_legendre_filter_set_order(int32_t index, int order) -{ - // Check the filter. - auto check_result = check_sptl_legendre_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - filt->set_order(order); - return 0; -} - -extern "C" int -openmc_spatial_legendre_filter_set_params(int32_t index, const int* axis, - const double* min, const double* max) -{ - // Check the filter. - auto check_result = check_sptl_legendre_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - if (axis) filt->set_axis(static_cast(*axis)); - if (min && max) filt->set_minmax(*min, *max); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/filter_surface.cpp b/src/tallies/filter_surface.cpp deleted file mode 100644 index 72b356f21..000000000 --- a/src/tallies/filter_surface.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "openmc/tallies/filter_surface.h" - -#include - -#include "openmc/error.h" -#include "openmc/surface.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -SurfaceFilter::from_xml(pugi::xml_node node) -{ - auto surfaces = get_node_array(node, "bins"); - - // Convert surface IDs to indices of the global surfaces vector. - for (auto& s : surfaces) { - auto search = model::surface_map.find(s); - if (search == model::surface_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find surface " << s - << " specified on tally filter."; - throw std::runtime_error{err_msg.str()}; - } - - s = search->second; - } - - this->set_surfaces(surfaces); -} - -void -SurfaceFilter::set_surfaces(gsl::span surfaces) -{ - // Clear existing surfaces - surfaces_.clear(); - surfaces_.reserve(surfaces.size()); - map_.clear(); - - // Update surfaces and mapping - for (auto& index : surfaces) { - Expects(index >= 0); - Expects(index < model::surfaces.size()); - surfaces_.push_back(index); - map_[index] = surfaces_.size() - 1; - } - - n_bins_ = surfaces_.size(); -} - -void -SurfaceFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - auto search = map_.find(std::abs(p->surface_)-1); - if (search != map_.end()) { - match.bins_.push_back(search->second); - if (p->surface_ < 0) { - match.weights_.push_back(-1.0); - } else { - match.weights_.push_back(1.0); - } - } -} - -void -SurfaceFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - std::vector surface_ids; - for (auto c : surfaces_) surface_ids.push_back(model::surfaces[c]->id_); - write_dataset(filter_group, "bins", surface_ids); -} - -std::string -SurfaceFilter::text_label(int bin) const -{ - return "Surface " + std::to_string(model::surfaces[surfaces_[bin]]->id_); -} - -} // namespace openmc diff --git a/src/tallies/filter_universe.cpp b/src/tallies/filter_universe.cpp deleted file mode 100644 index dffdee621..000000000 --- a/src/tallies/filter_universe.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "openmc/tallies/filter_universe.h" - -#include - -#include "openmc/cell.h" -#include "openmc/error.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -void -UniverseFilter::from_xml(pugi::xml_node node) -{ - // Get material IDs and convert to indices in the global materials vector - auto universes = get_node_array(node, "bins"); - for (auto& u : universes) { - auto search = model::universe_map.find(u); - if (search == model::universe_map.end()) { - std::stringstream err_msg; - err_msg << "Could not find universe " << u - << " specified on tally filter."; - throw std::runtime_error{err_msg.str()}; - } - u = search->second; - } - - this->set_universes(universes); -} - -void -UniverseFilter::set_universes(gsl::span universes) -{ - // Clear existing universes - universes_.clear(); - universes_.reserve(universes.size()); - map_.clear(); - - // Update universes and mapping - for (auto& index : universes) { - Expects(index >= 0); - Expects(index < model::universes.size()); - universes_.push_back(index); - map_[index] = universes_.size() - 1; - } - - n_bins_ = universes_.size(); -} - -void -UniverseFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - for (int i = 0; i < p->n_coord_; i++) { - auto search = map_.find(p->coord_[i].universe); - if (search != map_.end()) { - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } - } -} - -void -UniverseFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - std::vector universe_ids; - for (auto u : universes_) universe_ids.push_back(model::universes[u]->id_); - write_dataset(filter_group, "bins", universe_ids); -} - -std::string -UniverseFilter::text_label(int bin) const -{ - return "Universe " + std::to_string(model::universes[universes_[bin]]->id_); -} - -} // namespace openmc diff --git a/src/tallies/filter_zernike.cpp b/src/tallies/filter_zernike.cpp deleted file mode 100644 index b732ef793..000000000 --- a/src/tallies/filter_zernike.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "openmc/tallies/filter_zernike.h" - -#include -#include -#include // For pair - -#include "openmc/capi.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/xml_interface.h" - -namespace openmc { - -//============================================================================== -// ZernikeFilter implementation -//============================================================================== - -void -ZernikeFilter::from_xml(pugi::xml_node node) -{ - set_order(std::stoi(get_node_value(node, "order"))); - x_ = std::stod(get_node_value(node, "x")); - y_ = std::stod(get_node_value(node, "y")); - r_ = std::stod(get_node_value(node, "r")); -} - -void -ZernikeFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - // Determine the normalized (r,theta) coordinates. - double x = p->r().x - x_; - double y = p->r().y - y_; - double r = std::sqrt(x*x + y*y) / r_; - double theta = std::atan2(y, x); - - if (r <= 1.0) { - // Compute and return the Zernike weights. - std::vector zn(n_bins_); - calc_zn(order_, r, theta, zn.data()); - for (int i = 0; i < n_bins_; i++) { - match.bins_.push_back(i); - match.weights_.push_back(zn[i]); - } - } -} - -void -ZernikeFilter::to_statepoint(hid_t filter_group) const -{ - Filter::to_statepoint(filter_group); - write_dataset(filter_group, "order", order_); - write_dataset(filter_group, "x", x_); - write_dataset(filter_group, "y", y_); - write_dataset(filter_group, "r", r_); -} - -std::string -ZernikeFilter::text_label(int bin) const -{ - std::stringstream out; - for (int n = 0; n < order_+1; n++) { - int last = (n + 1) * (n + 2) / 2; - if (bin < last) { - int first = last - (n + 1); - int m = -n + (bin - first) * 2; - out << "Zernike expansion, Z" << n << "," << m; - break; - } - } - return out.str(); -} - -void -ZernikeFilter::set_order(int order) -{ - if (order < 0) { - throw std::invalid_argument{"Zernike order must be non-negative."}; - } - order_ = order; - n_bins_ = ((order+1) * (order+2)) / 2; -} - -//============================================================================== -// ZernikeRadialFilter implementation -//============================================================================== - -void -ZernikeRadialFilter::get_all_bins(const Particle* p, int estimator, - FilterMatch& match) const -{ - // Determine the normalized radius coordinate. - double x = p->r().x - x_; - double y = p->r().y - y_; - double r = std::sqrt(x*x + y*y) / r_; - - if (r <= 1.0) { - // Compute and return the Zernike weights. - std::vector zn(n_bins_); - calc_zn_rad(order_, r, zn.data()); - for (int i = 0; i < n_bins_; i++) { - match.bins_.push_back(i); - match.weights_.push_back(zn[i]); - } - } -} - -std::string -ZernikeRadialFilter::text_label(int bin) const -{ - return "Zernike expansion, Z" + std::to_string(2*bin) + ",0"; -} - -void -ZernikeRadialFilter::set_order(int order) -{ - ZernikeFilter::set_order(order); - n_bins_ = order / 2 + 1; -} - -//============================================================================== -// C-API functions -//============================================================================== - -std::pair -check_zernike_filter(int32_t index) -{ - // Make sure this is a valid index to an allocated filter. - int err = verify_filter(index); - if (err) { - return {err, nullptr}; - } - - // Get a pointer to the filter and downcast. - const auto& filt_base = model::tally_filters[index].get(); - auto* filt = dynamic_cast(filt_base); - - // Check the filter type. - if (!filt) { - set_errmsg("Not a Zernike filter."); - err = OPENMC_E_INVALID_TYPE; - } - return {err, filt}; -} - -extern "C" int -openmc_zernike_filter_get_order(int32_t index, int* order) -{ - // Check the filter. - auto check_result = check_zernike_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the order. - *order = filt->order(); - return 0; -} - -extern "C" int -openmc_zernike_filter_get_params(int32_t index, double* x, double* y, - double* r) -{ - // Check the filter. - auto check_result = check_zernike_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Output the params. - *x = filt->x(); - *y = filt->y(); - *r = filt->r(); - return 0; -} - -extern "C" int -openmc_zernike_filter_set_order(int32_t index, int order) -{ - // Check the filter. - auto check_result = check_zernike_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - filt->set_order(order); - return 0; -} - -extern "C" int -openmc_zernike_filter_set_params(int32_t index, const double* x, - const double* y, const double* r) -{ - // Check the filter. - auto check_result = check_zernike_filter(index); - auto err = check_result.first; - auto filt = check_result.second; - if (err) return err; - - // Update the filter. - if (x) filt->set_x(*x); - if (y) filt->set_y(*y); - if (r) filt->set_r(*r); - return 0; -} - -} // namespace openmc diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp deleted file mode 100644 index f84387411..000000000 --- a/src/tallies/tally.cpp +++ /dev/null @@ -1,1425 +0,0 @@ -#include "openmc/tallies/tally.h" - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/file_utils.h" -#include "openmc/message_passing.h" -#include "openmc/mesh.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/particle.h" -#include "openmc/reaction.h" -#include "openmc/reaction_product.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/source.h" -#include "openmc/tallies/derivative.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/filter_cell.h" -#include "openmc/tallies/filter_cellfrom.h" -#include "openmc/tallies/filter_delayedgroup.h" -#include "openmc/tallies/filter_energy.h" -#include "openmc/tallies/filter_legendre.h" -#include "openmc/tallies/filter_mesh.h" -#include "openmc/tallies/filter_meshsurface.h" -#include "openmc/tallies/filter_particle.h" -#include "openmc/tallies/filter_sph_harm.h" -#include "openmc/tallies/filter_surface.h" -#include "openmc/xml_interface.h" - -#include "xtensor/xadapt.hpp" -#include "xtensor/xbuilder.hpp" // for empty_like -#include "xtensor/xview.hpp" - -#include // for max -#include -#include // for size_t -#include -#include - -namespace openmc { - -//============================================================================== -// Global variable definitions -//============================================================================== - -namespace model { - std::vector> tallies; - std::vector active_tallies; - std::vector active_analog_tallies; - std::vector active_tracklength_tallies; - std::vector active_collision_tallies; - std::vector active_meshsurf_tallies; - std::vector active_surface_tallies; - std::unordered_map tally_map; -} - -namespace simulation { - xt::xtensor_fixed> global_tallies; - int32_t n_realizations {0}; -} - -double global_tally_absorption; -double global_tally_collision; -double global_tally_tracklength; -double global_tally_leakage; - -int -score_str_to_int(std::string score_str) -{ - if (score_str == "flux") - return SCORE_FLUX; - - if (score_str == "total" || score_str == "(n,total)") - return SCORE_TOTAL; - - if (score_str == "scatter") - return SCORE_SCATTER; - - if (score_str == "nu-scatter") - return SCORE_NU_SCATTER; - - if (score_str == "absorption") - return SCORE_ABSORPTION; - - if (score_str == "fission" || score_str == "18") - return SCORE_FISSION; - - if (score_str == "nu-fission") - return SCORE_NU_FISSION; - - if (score_str == "decay-rate") - return SCORE_DECAY_RATE; - - if (score_str == "delayed-nu-fission") - return SCORE_DELAYED_NU_FISSION; - - if (score_str == "prompt-nu-fission") - return SCORE_PROMPT_NU_FISSION; - - if (score_str == "kappa-fission") - return SCORE_KAPPA_FISSION; - - if (score_str == "inverse-velocity") - return SCORE_INVERSE_VELOCITY; - - if (score_str == "fission-q-prompt") - return SCORE_FISS_Q_PROMPT; - - if (score_str == "fission-q-recoverable") - return SCORE_FISS_Q_RECOV; - - if (score_str == "heating") - return HEATING; - - if (score_str == "heating-local") - return HEATING_LOCAL; - - if (score_str == "current") - return SCORE_CURRENT; - - if (score_str == "events") - return SCORE_EVENTS; - - if (score_str == "elastic" || score_str == "(n,elastic)") - return ELASTIC; - - if (score_str == "n2n" || score_str == "(n,2n)") - return N_2N; - - if (score_str == "n3n" || score_str == "(n,3n)") - return N_3N; - - if (score_str == "n4n" || score_str == "(n,4n)") - return N_4N; - - if (score_str == "(n,2nd)") - return N_2ND; - if (score_str == "(n,na)") - return N_2NA; - if (score_str == "(n,n3a)") - return N_N3A; - if (score_str == "(n,2na)") - return N_2NA; - if (score_str == "(n,3na)") - return N_3NA; - if (score_str == "(n,np)") - return N_NP; - if (score_str == "(n,n2a)") - return N_N2A; - if (score_str == "(n,2n2a)") - return N_2N2A; - if (score_str == "(n,nd)") - return N_ND; - if (score_str == "(n,nt)") - return N_NT; - if (score_str == "(n,nHe-3)") - return N_N3HE; - if (score_str == "(n,nd2a)") - return N_ND2A; - if (score_str == "(n,nt2a)") - return N_NT2A; - if (score_str == "(n,3nf)") - return N_3NF; - if (score_str == "(n,2np)") - return N_2NP; - if (score_str == "(n,3np)") - return N_3NP; - if (score_str == "(n,n2p)") - return N_N2P; - if (score_str == "(n,npa)") - return N_NPA; - if (score_str == "(n,n1)") - return N_N1; - if (score_str == "(n,nc)") - return N_NC; - if (score_str == "(n,gamma)") - return N_GAMMA; - if (score_str == "(n,p)") - return N_P; - if (score_str == "(n,d)") - return N_D; - if (score_str == "(n,t)") - return N_T; - if (score_str == "(n,3He)") - return N_3HE; - if (score_str == "(n,a)") - return N_A; - if (score_str == "(n,2a)") - return N_2A; - if (score_str == "(n,3a)") - return N_3A; - if (score_str == "(n,2p)") - return N_2P; - if (score_str == "(n,pa)") - return N_PA; - if (score_str == "(n,t2a)") - return N_T2A; - if (score_str == "(n,d2a)") - return N_D2A; - if (score_str == "(n,pd)") - return N_PD; - if (score_str == "(n,pt)") - return N_PT; - if (score_str == "(n,da)") - return N_DA; - if (score_str == "(n,Xp)" || score_str == "H1-production") - return N_XP; - if (score_str == "(n,Xd)" || score_str == "H2-production") - return N_XD; - if (score_str == "(n,Xt)" || score_str == "H3-production") - return N_XT; - if (score_str == "(n,X3He)" || score_str == "He3-production") - return N_X3HE; - if (score_str == "(n,Xa)" || score_str == "He4-production") - return N_XA; - if (score_str == "damage-energy") - return DAMAGE_ENERGY; - - // So far we have not identified this score string. Check to see if it is a - // deprecated score. - if (score_str.rfind("scatter-", 0) == 0 - || score_str.rfind("nu-scatter-", 0) == 0 - || score_str.rfind("total-y", 0) == 0 - || score_str.rfind("flux-y", 0) == 0) - fatal_error(score_str + " is no longer an available score"); - - - // Assume the given string is a reaction MT number. Make sure it's a natural - // number then return. - int MT; - try { - MT = std::stoi(score_str); - } catch (const std::invalid_argument& ex) { - throw std::invalid_argument("Invalid tally score \"" + score_str + "\""); - } - if (MT < 1) - throw std::invalid_argument("Invalid tally score \"" + score_str + "\""); - return MT; -} - -//============================================================================== -// Tally object implementation -//============================================================================== - -Tally::Tally(int32_t id) - : index_{model::tallies.size()} -{ - this->set_id(id); - this->set_filters({}); -} - -Tally::Tally(pugi::xml_node node) - : index_{model::tallies.size()} -{ - // Copy and set tally id - if (!check_for_node(node, "id")) { - throw std::runtime_error{"Must specify id for tally in tally XML file."}; - } - int32_t id = std::stoi(get_node_value(node, "id")); - this->set_id(id); - - if (check_for_node(node, "name")) name_ = get_node_value(node, "name"); - - // ======================================================================= - // READ DATA FOR FILTERS - - // Check if user is using old XML format and throw an error if so - if (check_for_node(node, "filter")) { - throw std::runtime_error{"Tally filters must be specified independently of " - "tallies in a element. The element itself should " - "have a list of filters that apply, e.g., 1 2 " - "where 1 and 2 are the IDs of filters specified outside of " - "."}; - } - - // Determine number of filters - std::vector filter_ids; - if (check_for_node(node, "filters")) { - filter_ids = get_node_array(node, "filters"); - } - - // Allocate and store filter user ids - std::vector filters; - for (int filter_id : filter_ids) { - // Determine if filter ID is valid - auto it = model::filter_map.find(filter_id); - if (it == model::filter_map.end()) { - throw std::runtime_error{"Could not find filter " + std::to_string(filter_id) - + " specified on tally " + std::to_string(id_)}; - } - - // Store the index of the filter - filters.push_back(model::tally_filters[it->second].get()); - } - - // Set the filters - this->set_filters(filters); - - // Check for the presence of certain filter types - bool has_energyout = energyout_filter_ >= 0; - int particle_filter_index = C_NONE; - for (gsl::index j = 0; j < filters_.size(); ++j) { - int i_filter = filters_[j]; - const auto& f = model::tally_filters[i_filter].get(); - - auto pf = dynamic_cast(f); - if (pf) particle_filter_index = i_filter; - - // Change the tally estimator if a filter demands it - std::string filt_type = f->type(); - if (filt_type == "energyout" || filt_type == "legendre") { - estimator_ = ESTIMATOR_ANALOG; - } else if (filt_type == "sphericalharmonics") { - auto sf = dynamic_cast(f); - if (sf->cosine() == SphericalHarmonicsCosine::scatter) { - estimator_ = ESTIMATOR_ANALOG; - } - } else if (filt_type == "spatiallegendre" || filt_type == "zernike" - || filt_type == "zernikeradial") { - estimator_ = ESTIMATOR_COLLISION; - } - } - - // ======================================================================= - // READ DATA FOR NUCLIDES - - this->set_nuclides(node); - - // ======================================================================= - // READ DATA FOR SCORES - - this->set_scores(node); - - if (!check_for_node(node, "scores")) { - fatal_error("No scores specified on tally " + std::to_string(id_) - + "."); - } - - // Check if tally is compatible with particle type - if (settings::photon_transport) { - if (particle_filter_index == C_NONE) { - for (int score : scores_) { - switch (score) { - case SCORE_INVERSE_VELOCITY: - fatal_error("Particle filter must be used with photon " - "transport on and inverse velocity score"); - break; - case SCORE_FLUX: - case SCORE_TOTAL: - case SCORE_SCATTER: - case SCORE_NU_SCATTER: - case SCORE_ABSORPTION: - case SCORE_FISSION: - case SCORE_NU_FISSION: - case SCORE_CURRENT: - case SCORE_EVENTS: - case SCORE_DELAYED_NU_FISSION: - case SCORE_PROMPT_NU_FISSION: - case SCORE_DECAY_RATE: - warning("Particle filter is not used with photon transport" - " on and " + reaction_name(score) + " score."); - break; - } - } - } else { - const auto& f = model::tally_filters[particle_filter_index].get(); - auto pf = dynamic_cast(f); - for (auto p : pf->particles()) { - if (p == Particle::Type::electron || - p == Particle::Type::positron) { - estimator_ = ESTIMATOR_ANALOG; - } - } - } - } else { - if (particle_filter_index >= 0) { - const auto& f = model::tally_filters[particle_filter_index].get(); - auto pf = dynamic_cast(f); - for (auto p : pf->particles()) { - if (p != Particle::Type::neutron) { - warning("Particle filter other than NEUTRON used with photon " - "transport turned off. All tallies for particle type " + - std::to_string(static_cast(p)) + " will have no scores"); - } - } - } - } - - // Check for a tally derivative. - if (check_for_node(node, "derivative")) { - int deriv_id = std::stoi(get_node_value(node, "derivative")); - - // Find the derivative with the given id, and store it's index. - auto it = model::tally_deriv_map.find(deriv_id); - if (it == model::tally_deriv_map.end()) { - fatal_error("Could not find derivative " + std::to_string(deriv_id) - + " specified on tally " + std::to_string(id_)); - } - - deriv_ = it->second; - - // Only analog or collision estimators are supported for differential - // tallies. - if (estimator_ == ESTIMATOR_TRACKLENGTH) { - estimator_ = ESTIMATOR_COLLISION; - } - - const auto& deriv = model::tally_derivs[deriv_]; - if (deriv.variable == DIFF_NUCLIDE_DENSITY - || deriv.variable == DIFF_TEMPERATURE) { - for (int i_nuc : nuclides_) { - if (has_energyout && i_nuc == -1) { - fatal_error("Error on tally " + std::to_string(id_) - + ": Cannot use a 'nuclide_density' or 'temperature' " - "derivative on a tally with an outgoing energy filter and " - "'total' nuclide rate. Instead, tally each nuclide in the " - "material individually."); - // Note that diff tallies with these characteristics would work - // correctly if no tally events occur in the perturbed material - // (e.g. pertrubing moderator but only tallying fuel), but this - // case would be hard to check for by only reading inputs. - } - } - } - } - - // If settings.xml trigger is turned on, create tally triggers - if (settings::trigger_on) { - this->init_triggers(node); - } - - // ======================================================================= - // SET TALLY ESTIMATOR - - // Check if user specified estimator - if (check_for_node(node, "estimator")) { - std::string est = get_node_value(node, "estimator"); - if (est == "analog") { - estimator_ = ESTIMATOR_ANALOG; - } else if (est == "tracklength" || est == "track-length" - || est == "pathlength" || est == "path-length") { - // If the estimator was set to an analog estimator, this means the - // tally needs post-collision information - if (estimator_ == ESTIMATOR_ANALOG) { - throw std::runtime_error{"Cannot use track-length estimator for tally " - + std::to_string(id_)}; - } - - // Set estimator to track-length estimator - estimator_ = ESTIMATOR_TRACKLENGTH; - - } else if (est == "collision") { - // If the estimator was set to an analog estimator, this means the - // tally needs post-collision information - if (estimator_ == ESTIMATOR_ANALOG) { - throw std::runtime_error{"Cannot use collision estimator for tally " + - std::to_string(id_)}; - } - - // Set estimator to collision estimator - estimator_ = ESTIMATOR_COLLISION; - - } else { - throw std::runtime_error{"Invalid estimator '" + est + "' on tally " + - std::to_string(id_)}; - } - } -} - -Tally::~Tally() -{ - model::tally_map.erase(id_); -} - -Tally* -Tally::create(int32_t id) -{ - model::tallies.push_back(std::make_unique(id)); - return model::tallies.back().get(); -} - -void -Tally::set_id(int32_t id) -{ - Expects(id >= -1); - - // Clear entry in tally map if an ID was already assigned before - if (id_ != -1) { - model::tally_map.erase(id_); - id_ = -1; - } - - // Make sure no other tally has the same ID - if (model::tally_map.find(id) != model::tally_map.end()) { - throw std::runtime_error{"Two tallies have the same ID: " + std::to_string(id)}; - } - - // If no ID specified, auto-assign next ID in sequence - if (id == -1) { - id = 0; - for (const auto& t : model::tallies) { - id = std::max(id, t->id_); - } - ++id; - } - - // Update ID and entry in tally map - id_ = id; - model::tally_map[id] = index_; -} - -void -Tally::set_filters(gsl::span filters) -{ - // Clear old data. - filters_.clear(); - strides_.clear(); - - // Copy in the given filter indices. - auto n = filters.size(); - filters_.reserve(n); - - for (int i = 0; i < n; ++i) { - // Add index to vector of filters - auto& f {filters[i]}; - filters_.push_back(model::filter_map.at(f->id())); - - // Keep track of indices for special filters. - if (dynamic_cast(f)) { - energyout_filter_ = i; - } else if (dynamic_cast(f)) { - delayedgroup_filter_ = i; - } - } - - // Set the strides. Filters are traversed in reverse so that the last filter - // has the shortest stride in memory and the first filter has the longest - // stride. - strides_.resize(n, 0); - int stride = 1; - for (int i = n-1; i >= 0; --i) { - strides_[i] = stride; - stride *= model::tally_filters[filters_[i]]->n_bins(); - } - n_filter_bins_ = stride; -} - -void -Tally::set_scores(pugi::xml_node node) -{ - if (!check_for_node(node, "scores")) - fatal_error("No scores specified on tally " + std::to_string(id_)); - - auto scores = get_node_array(node, "scores"); - set_scores(scores); -} - -void -Tally::set_scores(const std::vector& scores) -{ - // Reset state and prepare for the new scores. - scores_.clear(); - depletion_rx_ = false; - scores_.reserve(scores.size()); - - // Check for the presence of certain restrictive filters. - bool energyout_present = energyout_filter_ != C_NONE; - bool legendre_present = false; - bool cell_present = false; - bool cellfrom_present = false; - bool surface_present = false; - bool meshsurface_present = false; - for (auto i_filt : filters_) { - const auto* filt {model::tally_filters[i_filt].get()}; - if (dynamic_cast(filt)) { - legendre_present = true; - } else if (dynamic_cast(filt)) { - cellfrom_present = true; - } else if (dynamic_cast(filt)) { - cell_present = true; - } else if (dynamic_cast(filt)) { - surface_present = true; - } else if (dynamic_cast(filt)) { - meshsurface_present = true; - } - } - - // Iterate over the given scores. - for (auto score_str : scores) { - // Make sure a delayed group filter wasn't used with an incompatible score. - if (delayedgroup_filter_ != C_NONE) { - if (score_str != "delayed-nu-fission" && score_str != "decay-rate") - fatal_error("Cannot tally " + score_str + "with a delayedgroup filter"); - } - - auto score = score_str_to_int(score_str); - - switch (score) { - case SCORE_FLUX: - if (!nuclides_.empty()) - if (!(nuclides_.size() == 1 && nuclides_[0] == -1)) - fatal_error("Cannot tally flux for an individual nuclide."); - if (energyout_present) - fatal_error("Cannot tally flux with an outgoing energy filter."); - break; - - case SCORE_TOTAL: - case SCORE_ABSORPTION: - case SCORE_FISSION: - if (energyout_present) - fatal_error("Cannot tally " + score_str + " reaction rate with an " - "outgoing energy filter"); - break; - - case SCORE_SCATTER: - if (legendre_present) - estimator_ = ESTIMATOR_ANALOG; - case SCORE_NU_FISSION: - case SCORE_DELAYED_NU_FISSION: - case SCORE_PROMPT_NU_FISSION: - if (energyout_present) - estimator_ = ESTIMATOR_ANALOG; - break; - - case SCORE_NU_SCATTER: - if (settings::run_CE) { - estimator_ = ESTIMATOR_ANALOG; - } else { - if (energyout_present || legendre_present) - estimator_ = ESTIMATOR_ANALOG; - } - break; - - case N_2N: - case N_3N: - case N_4N: - case N_GAMMA: - case N_P: - case N_A: - depletion_rx_ = true; - break; - - case SCORE_CURRENT: - // Check which type of current is desired: mesh or surface currents. - if (surface_present || cell_present || cellfrom_present) { - if (meshsurface_present) - fatal_error("Cannot tally mesh surface currents in the same tally as " - "normal surface currents"); - type_ = TALLY_SURFACE; - } else if (meshsurface_present) { - type_ = TALLY_MESH_SURFACE; - } else { - fatal_error("Cannot tally currents without surface type filters"); - } - break; - } - - scores_.push_back(score); - } - - // Make sure that no duplicate scores exist. - for (auto it1 = scores_.begin(); it1 != scores_.end(); ++it1) { - for (auto it2 = it1 + 1; it2 != scores_.end(); ++it2) { - if (*it1 == *it2) - fatal_error("Duplicate score of type \"" + reaction_name(*it1) - + "\" found in tally " + std::to_string(id_)); - } - } - - // Make sure all scores are compatible with multigroup mode. - if (!settings::run_CE) { - for (auto sc : scores_) - if (sc > 0) - fatal_error("Cannot tally " + reaction_name(sc) + " reaction rate " - "in multi-group mode"); - } - - // Make sure current scores are not mixed in with volumetric scores. - if (type_ == TALLY_SURFACE || type_ == TALLY_MESH_SURFACE) { - if (scores_.size() != 1) - fatal_error("Cannot tally other scores in the same tally as surface " - "currents"); - } -} - -void -Tally::set_nuclides(pugi::xml_node node) -{ - nuclides_.clear(); - - // By default, we tally just the total material rates. - if (!check_for_node(node, "nuclides")) { - nuclides_.push_back(-1); - return; - } - - if (get_node_value(node, "nuclides") == "all") { - // This tally should bin every nuclide in the problem. It should also bin - // the total material rates. To achieve this, set the nuclides_ vector to - // 0, 1, 2, ..., -1. - nuclides_.reserve(data::nuclides.size() + 1); - for (auto i = 0; i < data::nuclides.size(); ++i) - nuclides_.push_back(i); - nuclides_.push_back(-1); - all_nuclides_ = true; - - } else { - // The user provided specifics nuclides. Parse it as an array with either - // "total" or a nuclide name like "U-235" in each position. - auto words = get_node_array(node, "nuclides"); - this->set_nuclides(words); - } -} - -void -Tally::set_nuclides(const std::vector& nuclides) -{ - nuclides_.clear(); - - for (const auto& nuc : nuclides) { - if (nuc == "total") { - nuclides_.push_back(-1); - } else { - auto search = data::nuclide_map.find(nuc); - if (search == data::nuclide_map.end()) - fatal_error("Could not find the nuclide " + nuc - + " specified in tally " + std::to_string(id_) - + " in any material"); - nuclides_.push_back(search->second); - } - } -} - -void -Tally::init_triggers(pugi::xml_node node) -{ - for (auto trigger_node: node.children("trigger")) { - // Read the trigger type. - TriggerMetric metric; - if (check_for_node(trigger_node, "type")) { - auto type_str = get_node_value(trigger_node, "type"); - if (type_str == "std_dev") { - metric = TriggerMetric::standard_deviation; - } else if (type_str == "variance") { - metric = TriggerMetric::variance; - } else if (type_str == "rel_err") { - metric = TriggerMetric::relative_error; - } else { - std::stringstream msg; - msg << "Unknown trigger type \"" << type_str << "\" in tally " << id_; - fatal_error(msg); - } - } else { - std::stringstream msg; - msg << "Must specify trigger type for tally " << id_ - << " in tally XML file"; - fatal_error(msg); - } - - // Read the trigger threshold. - double threshold; - if (check_for_node(trigger_node, "threshold")) { - threshold = std::stod(get_node_value(trigger_node, "threshold")); - } else { - std::stringstream msg; - msg << "Must specify trigger threshold for tally " << id_ - << " in tally XML file"; - fatal_error(msg); - } - - // Read the trigger scores. - std::vector trigger_scores; - if (check_for_node(trigger_node, "scores")) { - trigger_scores = get_node_array(trigger_node, "scores"); - } else { - trigger_scores.push_back("all"); - } - - // Parse the trigger scores and populate the triggers_ vector. - for (auto score_str : trigger_scores) { - if (score_str == "all") { - triggers_.reserve(triggers_.size() + this->scores_.size()); - for (auto i_score = 0; i_score < this->scores_.size(); ++i_score) { - triggers_.push_back({metric, threshold, i_score}); - } - } else { - int i_score = 0; - for (; i_score < this->scores_.size(); ++i_score) { - if (reaction_name(this->scores_[i_score]) == score_str) break; - } - if (i_score == this->scores_.size()) { - std::stringstream msg; - msg << "Could not find the score \"" << score_str << "\" in tally " - << id_ << " but it was listed in a trigger on that tally"; - fatal_error(msg); - } - triggers_.push_back({metric, threshold, i_score}); - } - } - } -} - -void Tally::init_results() -{ - int n_scores = scores_.size() * nuclides_.size(); - results_ = xt::empty({n_filter_bins_, n_scores, 3}); -} - -void Tally::reset() -{ - n_realizations_ = 0; - // TODO: Change to zero when xtensor is updated - if (results_.size() != 1) { - xt::view(results_, xt::all()) = 0.0; - } -} - -void Tally::accumulate() -{ - // Increment number of realizations - n_realizations_ += settings::reduce_tallies ? 1 : mpi::n_procs; - - if (mpi::master || !settings::reduce_tallies) { - // Calculate total source strength for normalization - double total_source = 0.0; - if (settings::run_mode == RUN_MODE_FIXEDSOURCE) { - for (const auto& s : model::external_sources) { - total_source += s.strength(); - } - } else { - total_source = 1.0; - } - - // Accumulate each result - for (int i = 0; i < results_.shape()[0]; ++i) { - for (int j = 0; j < results_.shape()[1]; ++j) { - double val = results_(i, j, RESULT_VALUE) / - simulation::total_weight * total_source; - results_(i, j, RESULT_VALUE) = 0.0; - results_(i, j, RESULT_SUM) += val; - results_(i, j, RESULT_SUM_SQ) += val*val; - } - } - } -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void read_tallies_xml() -{ - // Check if tallies.xml exists. If not, just return since it is optional - std::string filename = settings::path_input + "tallies.xml"; - if (!file_exists(filename)) return; - - write_message("Reading tallies XML file...", 5); - - // Parse tallies.xml file - pugi::xml_document doc; - doc.load_file(filename.c_str()); - pugi::xml_node root = doc.document_element(); - - // Check for setting - if (check_for_node(root, "assume_separate")) { - settings::assume_separate = get_node_value_bool(root, "assume_separate"); - } - - // Check for user meshes and allocate - read_meshes(root); - - // We only need the mesh info for plotting - if (settings::run_mode == RUN_MODE_PLOTTING) return; - - // Read data for tally derivatives - read_tally_derivatives(root); - - // ========================================================================== - // READ FILTER DATA - - // Check for user filters and allocate - for (auto node_filt : root.children("filter")) { - auto f = Filter::create(node_filt); - } - - // ========================================================================== - // READ TALLY DATA - - // Check for user tallies - int n = 0; - for (auto node : root.children("tally")) ++n; - if (n == 0 && mpi::master) { - warning("No tallies present in tallies.xml file."); - } - - for (auto node_tal : root.children("tally")) { - model::tallies.push_back(std::make_unique(node_tal)); - } -} - -#ifdef OPENMC_MPI -void reduce_tally_results() -{ - for (int i_tally : model::active_tallies) { - // Skip any tallies that are not active - auto& tally {model::tallies[i_tally]}; - - // Get view of accumulated tally values - auto values_view = xt::view(tally->results_, xt::all(), xt::all(), RESULT_VALUE); - - // Make copy of tally values in contiguous array - xt::xtensor values = values_view; - xt::xtensor values_reduced = xt::empty_like(values); - - // Reduce contiguous set of tally results - MPI_Reduce(values.data(), values_reduced.data(), values.size(), - MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm); - - // Transfer values on master and reset on other ranks - if (mpi::master) { - values_view = values_reduced; - } else { - values_view = 0.0; - } - } - - // Get view of global tally values - auto& gt = simulation::global_tallies; - auto gt_values_view = xt::view(gt, xt::all(), RESULT_VALUE); - - // Make copy of values in contiguous array - xt::xtensor gt_values = gt_values_view; - xt::xtensor gt_values_reduced = xt::empty_like(gt_values); - - // Reduce contiguous data - MPI_Reduce(gt_values.data(), gt_values_reduced.data(), N_GLOBAL_TALLIES, - MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm); - - // Transfer values on master and reset on other ranks - if (mpi::master) { - gt_values_view = gt_values_reduced; - } else { - gt_values_view = 0.0; - } - - // We also need to determine the total starting weight of particles from the - // last realization - double weight_reduced; - MPI_Reduce(&simulation::total_weight, &weight_reduced, 1, MPI_DOUBLE, MPI_SUM, - 0, mpi::intracomm); - if (mpi::master) simulation::total_weight = weight_reduced; -} -#endif - -void -accumulate_tallies() -{ -#ifdef OPENMC_MPI - // Combine tally results onto master process - if (settings::reduce_tallies) reduce_tally_results(); -#endif - - // Increase number of realizations (only used for global tallies) - simulation::n_realizations += settings::reduce_tallies ? 1 : mpi::n_procs; - - // Accumulate on master only unless run is not reduced then do it on all - if (mpi::master || !settings::reduce_tallies) { - auto& gt = simulation::global_tallies; - - if (settings::run_mode == RUN_MODE_EIGENVALUE) { - if (simulation::current_batch > settings::n_inactive) { - // Accumulate products of different estimators of k - double k_col = gt(K_COLLISION, RESULT_VALUE) / simulation::total_weight; - double k_abs = gt(K_ABSORPTION, RESULT_VALUE) / simulation::total_weight; - double k_tra = gt(K_TRACKLENGTH, RESULT_VALUE) / simulation::total_weight; - simulation::k_col_abs += k_col * k_abs; - simulation::k_col_tra += k_col * k_tra; - simulation::k_abs_tra += k_abs * k_tra; - } - } - - // Accumulate results for global tallies - for (int i = 0; i < N_GLOBAL_TALLIES; ++i) { - double val = gt(i, RESULT_VALUE)/simulation::total_weight; - gt(i, RESULT_VALUE) = 0.0; - gt(i, RESULT_SUM) += val; - gt(i, RESULT_SUM_SQ) += val*val; - } - } - - // Accumulate results for each tally - for (int i_tally : model::active_tallies) { - auto& tally {model::tallies[i_tally]}; - tally->accumulate(); - } -} - -void -setup_active_tallies() -{ - model::active_tallies.clear(); - model::active_analog_tallies.clear(); - model::active_tracklength_tallies.clear(); - model::active_collision_tallies.clear(); - model::active_meshsurf_tallies.clear(); - model::active_surface_tallies.clear(); - - for (auto i = 0; i < model::tallies.size(); ++i) { - const auto& tally {*model::tallies[i]}; - - if (tally.active_) { - model::active_tallies.push_back(i); - switch (tally.type_) { - - case TALLY_VOLUME: - switch (tally.estimator_) { - case ESTIMATOR_ANALOG: - model::active_analog_tallies.push_back(i); - break; - case ESTIMATOR_TRACKLENGTH: - model::active_tracklength_tallies.push_back(i); - break; - case ESTIMATOR_COLLISION: - model::active_collision_tallies.push_back(i); - } - break; - - case TALLY_MESH_SURFACE: - model::active_meshsurf_tallies.push_back(i); - break; - - case TALLY_SURFACE: - model::active_surface_tallies.push_back(i); - } - - // Check if tally contains depletion reactions and if so, set flag - if (tally.depletion_rx_) simulation::need_depletion_rx = true; - } - } -} - -void -free_memory_tally() -{ - #pragma omp parallel - { - model::tally_derivs.clear(); - } - - model::tally_filters.clear(); - model::filter_map.clear(); - - model::tallies.clear(); - - model::active_tallies.clear(); - model::active_analog_tallies.clear(); - model::active_tracklength_tallies.clear(); - model::active_collision_tallies.clear(); - model::active_meshsurf_tallies.clear(); - model::active_surface_tallies.clear(); - - model::tally_map.clear(); -} - -//============================================================================== -// C-API functions -//============================================================================== - -extern "C" int -openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end) -{ - if (index_start) *index_start = model::tallies.size(); - if (index_end) *index_end = model::tallies.size() + n - 1; - for (int i = 0; i < n; ++i) { - model::tallies.push_back(std::make_unique(-1)); - } - return 0; -} - -extern "C" int -openmc_get_tally_index(int32_t id, int32_t* index) -{ - auto it = model::tally_map.find(id); - if (it == model::tally_map.end()) { - set_errmsg("No tally exists with ID=" + std::to_string(id) + "."); - return OPENMC_E_INVALID_ID; - } - - *index = it->second; - return 0; -} - -extern "C" void -openmc_get_tally_next_id(int32_t* id) -{ - int32_t largest_tally_id = 0; - for (const auto& t : model::tallies) { - largest_tally_id = std::max(largest_tally_id, t->id_); - } - *id = largest_tally_id + 1; -} - -extern "C" int -openmc_tally_get_estimator(int32_t index, int* estimator) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *estimator = model::tallies[index]->estimator_; - return 0; -} - -extern "C" int -openmc_tally_set_estimator(int32_t index, const char* estimator) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - auto& t {model::tallies[index]}; - - std::string est = estimator; - if (est == "analog") { - t->estimator_ = ESTIMATOR_ANALOG; - } else if (est == "collision") { - t->estimator_ = ESTIMATOR_COLLISION; - } else if (est == "tracklength") { - t->estimator_ = ESTIMATOR_TRACKLENGTH; - } else { - set_errmsg("Unknown tally estimator: " + est); - return OPENMC_E_INVALID_ARGUMENT; - } - return 0; -} - -extern "C" int -openmc_tally_get_id(int32_t index, int32_t* id) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *id = model::tallies[index]->id_; - return 0; -} - -extern "C" int -openmc_tally_set_id(int32_t index, int32_t id) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - model::tallies[index]->set_id(id); - return 0; -} - -extern "C" int -openmc_tally_get_type(int32_t index, int32_t* type) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - *type = model::tallies[index]->type_; - - return 0; -} - -extern "C" int -openmc_tally_set_type(int32_t index, const char* type) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - if (strcmp(type, "volume") == 0) { - model::tallies[index]->type_ = TALLY_VOLUME; - } else if (strcmp(type, "mesh-surface") == 0) { - model::tallies[index]->type_ = TALLY_MESH_SURFACE; - } else if (strcmp(type, "surface") == 0) { - model::tallies[index]->type_ = TALLY_SURFACE; - } else { - std::stringstream errmsg; - errmsg << "Unknown tally type: " << type; - set_errmsg(errmsg); - return OPENMC_E_INVALID_ARGUMENT; - } - - return 0; -} - -extern "C" int -openmc_tally_get_active(int32_t index, bool* active) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - *active = model::tallies[index]->active_; - - return 0; -} - -extern "C" int -openmc_tally_set_active(int32_t index, bool active) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - model::tallies[index]->active_ = active; - - return 0; -} - -extern "C" int -openmc_tally_get_writable(int32_t index, bool* writable) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - *writable = model::tallies[index]->writable(); - - return 0; -} - -extern "C" int -openmc_tally_set_writable(int32_t index, bool writable) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - model::tallies[index]->set_writable(writable); - - return 0; -} - -extern "C" int -openmc_tally_get_scores(int32_t index, int** scores, int* n) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *scores = model::tallies[index]->scores_.data(); - *n = model::tallies[index]->scores_.size(); - return 0; -} - -extern "C" int -openmc_tally_set_scores(int32_t index, int n, const char** scores) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - std::vector scores_str(scores, scores+n); - try { - model::tallies[index]->set_scores(scores_str); - } catch (const std::invalid_argument& ex) { - set_errmsg(ex.what()); - return OPENMC_E_INVALID_ARGUMENT; - } - - return 0; -} - -extern "C" int -openmc_tally_get_nuclides(int32_t index, int** nuclides, int* n) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *n = model::tallies[index]->nuclides_.size(); - *nuclides = model::tallies[index]->nuclides_.data(); - - return 0; -} - -extern "C" int -openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - std::vector words(nuclides, nuclides+n); - std::vector nucs; - for (auto word : words){ - if (word == "total") { - nucs.push_back(-1); - } else { - auto search = data::nuclide_map.find(word); - if (search == data::nuclide_map.end()) { - set_errmsg("Nuclide \"" + word + "\" has not been loaded yet"); - return OPENMC_E_DATA; - } - nucs.push_back(search->second); - } - } - - model::tallies[index]->nuclides_ = nucs; - - return 0; -} - -extern "C" int -openmc_tally_get_filters(int32_t index, const int32_t** indices, size_t* n) -{ - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *indices = model::tallies[index]->filters().data(); - *n = model::tallies[index]->filters().size(); - return 0; -} - -extern "C" int -openmc_tally_set_filters(int32_t index, size_t n, const int32_t* indices) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - // Set the filters. - try { - // Convert indices to filter pointers - std::vector filters; - for (gsl::index i = 0; i < n; ++i) { - int32_t i_filt = indices[i]; - filters.push_back(model::tally_filters.at(i_filt).get()); - } - model::tallies[index]->set_filters(filters); - } catch (const std::out_of_range& ex) { - set_errmsg("Index in tally filter array out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - return 0; -} - -//! Reset tally results and number of realizations -extern "C" int -openmc_tally_reset(int32_t index) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - model::tallies[index]->reset(); - return 0; -} - -extern "C" int -openmc_tally_get_n_realizations(int32_t index, int32_t* n) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - *n = model::tallies[index]->n_realizations_; - return 0; -} - -//! \brief Returns a pointer to a tally results array along with its shape. This -//! allows a user to obtain in-memory tally results from Python directly. -extern "C" int -openmc_tally_results(int32_t index, double** results, size_t* shape) -{ - // Make sure the index fits in the array bounds. - if (index < 0 || index >= model::tallies.size()) { - set_errmsg("Index in tallies array is out of bounds."); - return OPENMC_E_OUT_OF_BOUNDS; - } - - const auto& t {model::tallies[index]}; - // TODO: Change to zero when xtensor is updated - if (t->results_.size() == 1) { - set_errmsg("Tally results have not been allocated yet."); - return OPENMC_E_ALLOCATE; - } - - // Set pointer to results and copy shape - *results = t->results_.data(); - auto s = t->results_.shape(); - shape[0] = s[0]; - shape[1] = s[1]; - shape[2] = s[2]; - return 0; -} - -extern "C" int -openmc_global_tallies(double** ptr) -{ - *ptr = simulation::global_tallies.data(); - return 0; -} - -extern "C" size_t tallies_size() { return model::tallies.size(); } - -} // namespace openmc diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp deleted file mode 100644 index 37310070f..000000000 --- a/src/tallies/tally_scoring.cpp +++ /dev/null @@ -1,2347 +0,0 @@ -#include "openmc/tallies/tally_scoring.h" - -#include "openmc/bank.h" -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/material.h" -#include "openmc/mgxs_interface.h" -#include "openmc/nuclide.h" -#include "openmc/photon.h" -#include "openmc/reaction_product.h" -#include "openmc/search.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/string_utils.h" -#include "openmc/tallies/derivative.h" -#include "openmc/tallies/filter.h" -#include "openmc/tallies/filter_delayedgroup.h" -#include "openmc/tallies/filter_energy.h" - -#include - -namespace openmc { - -//============================================================================== -// FilterBinIter implementation -//============================================================================== - -FilterBinIter::FilterBinIter(const Tally& tally, const Particle* p) - : tally_{tally} -{ - // Find all valid bins in each relevant filter if they have not already been - // found for this event. - for (auto i_filt : tally_.filters()) { - auto& match {simulation::filter_matches[i_filt]}; - if (!match.bins_present_) { - match.bins_.clear(); - match.weights_.clear(); - model::tally_filters[i_filt]->get_all_bins(p, tally_.estimator_, match); - match.bins_present_ = true; - } - - // If there are no valid bins for this filter, then there are no valid - // filter bin combinations so all iterators are end iterators. - if (match.bins_.size() == 0) { - index_ = -1; - return; - } - - // Set the index of the bin used in the first filter combination - match.i_bin_ = 0; - } - - // Compute the initial index and weight. - this->compute_index_weight(); -} - -FilterBinIter::FilterBinIter(const Tally& tally, bool end) - : tally_{tally} -{ - // Handle the special case for an iterator that points to the end. - if (end) { - index_ = -1; - return; - } - - for (auto i_filt : tally_.filters()) { - auto& match {simulation::filter_matches[i_filt]}; - if (!match.bins_present_) { - match.bins_.clear(); - match.weights_.clear(); - for (auto i = 0; i < model::tally_filters[i_filt]->n_bins(); ++i) { - match.bins_.push_back(i); - match.weights_.push_back(1.0); - } - match.bins_present_ = true; - } - - if (match.bins_.size() == 0) { - index_ = -1; - return; - } - - match.i_bin_ = 0; - } - - // Compute the initial index and weight. - this->compute_index_weight(); -} - -FilterBinIter& -FilterBinIter::operator++() -{ - // Find the next valid combination of filter bins. To do this, we search - // backwards through the filters until we find the first filter whose bins - // can be incremented. - bool done_looping = true; - for (int i = tally_.filters().size()-1; i >= 0; --i) { - auto i_filt = tally_.filters(i); - auto& match {simulation::filter_matches[i_filt]}; - if (match.i_bin_ < match.bins_.size()-1) { - // The bin for this filter can be incremented. Increment it and do not - // touch any of the remaining filters. - ++match.i_bin_; - done_looping = false; - break; - } else { - // This bin cannot be incremented so reset it and continue to the next - // filter. - match.i_bin_ = 0; - } - } - - if (done_looping) { - // We have visited every valid combination. All done! - index_ = -1; - } else { - // The loop found a new valid combination. Compute the corresponding - // index and weight. - compute_index_weight(); - } - - return *this; -} - -void -FilterBinIter::compute_index_weight() -{ - index_ = 0; - weight_ = 1.; - for (auto i = 0; i < tally_.filters().size(); ++i) { - auto i_filt = tally_.filters(i); - auto& match {simulation::filter_matches[i_filt]}; - auto i_bin = match.i_bin_; - index_ += match.bins_[i_bin] * tally_.strides(i); - weight_ *= match.weights_[i_bin]; - } -} - -//============================================================================== -// Non-member functions -//============================================================================== - -//! Helper function used to increment tallies with a delayed group filter. - -void -score_fission_delayed_dg(int i_tally, int d_bin, double score, int score_index) -{ - // Save the original delayed group bin - auto& tally {*model::tallies[i_tally]}; - auto i_filt = tally.filters(tally.delayedgroup_filter_); - auto& dg_match {simulation::filter_matches[i_filt]}; - auto i_bin = dg_match.i_bin_; - auto original_bin = dg_match.bins_[i_bin]; - dg_match.bins_[i_bin] = d_bin; - - // Determine the filter scoring index - auto filter_index = 0; - for (auto i = 0; i < tally.filters().size(); ++i) { - auto i_filt = tally.filters(i); - auto& match {simulation::filter_matches[i_filt]}; - auto i_bin = match.i_bin_; - filter_index += match.bins_[i_bin] * tally.strides(i); - } - - // Update the tally result - #pragma omp atomic - tally.results_(filter_index, score_index, RESULT_VALUE) += score; - - // Reset the original delayed group bin - dg_match.bins_[i_bin] = original_bin; -} - -//! Helper function to retrieve fission q value from a nuclide - -double get_nuc_fission_q(const Nuclide& nuc, const Particle* p, int score_bin) -{ - if (score_bin == SCORE_FISS_Q_PROMPT) { - if (nuc.fission_q_prompt_) { - return (*nuc.fission_q_prompt_)(p->E_last_); - } - } else if (score_bin == SCORE_FISS_Q_RECOV) { - if (nuc.fission_q_recov_) { - return (*nuc.fission_q_recov_)(p->E_last_); - } - } - return 0.0; -} - -//! Helper function to score fission energy -// -//! Pulled out to support both the fission_q scores and energy deposition -//! score - -double score_fission_q(const Particle* p, int score_bin, const Tally& tally, - double flux, int i_nuclide, double atom_density) -{ - if (tally.estimator_ == ESTIMATOR_ANALOG) { - const Nuclide& nuc {*data::nuclides[p->event_nuclide_]}; - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission scaled by the Q-value - if (p->neutron_xs_[p->event_nuclide_].absorption > 0) { - return p->wgt_absorb_ * get_nuc_fission_q(nuc, p, score_bin) - * p->neutron_xs_[p->event_nuclide_].fission * flux - / p->neutron_xs_[p->event_nuclide_].absorption; - } - } else { - // Skip any non-absorption events - if (p->event_ == EVENT_SCATTER) return 0.0; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - if (p->neutron_xs_[p->event_nuclide_].absorption > 0) { - return p->wgt_last_ * get_nuc_fission_q(nuc, p, score_bin) - * p->neutron_xs_[p->event_nuclide_].fission * flux - / p->neutron_xs_[p->event_nuclide_].absorption; - } - } - } else { - if (i_nuclide >= 0) { - const Nuclide& nuc {*data::nuclides[i_nuclide]}; - return get_nuc_fission_q(nuc, p, score_bin) * atom_density * flux - * p->neutron_xs_[i_nuclide].fission; - } else { - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - double score {0.0}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const Nuclide& nuc {*data::nuclides[j_nuclide]}; - score += get_nuc_fission_q(nuc, p, score_bin) * atom_density - * p->neutron_xs_[j_nuclide].fission; - } - return score * flux; - } - } - } - return 0.0; -} - -//! Helper function to obtain the kerma coefficient for a given nuclide - -double get_nuclide_neutron_heating(const Particle* p, const Nuclide& nuc, - int rxn_index, int i_nuclide) -{ - size_t mt = nuc.reaction_index_[rxn_index]; - if (mt == C_NONE) return 0.0; - auto i_temp = p->neutron_xs_[i_nuclide].index_temp; - if (i_temp < 0) return 0.0; // Can be true due to multipole - const auto& rxn {*nuc.reactions_[mt]}; - const auto& xs {rxn.xs_[i_temp]}; - auto i_grid = p->neutron_xs_[i_nuclide].index_grid; - if (i_grid < xs.threshold) return 0.0; - auto f = p->neutron_xs_[i_nuclide].interp_factor; - return (1.0 - f) * xs.value[i_grid-xs.threshold] - + f * xs.value[i_grid-xs.threshold+1]; -} - -//! Helper function to obtain neutron heating [eV] - -double score_neutron_heating(const Particle* p, const Tally& tally, double flux, - int rxn_bin, int i_nuclide, double atom_density) -{ - double score; - // Get heating macroscopic "cross section" - double heating_xs; - if (i_nuclide >= 0) { - const Nuclide& nuc {*data::nuclides[i_nuclide]}; - heating_xs = get_nuclide_neutron_heating(p, nuc, rxn_bin, i_nuclide); - if (tally.estimator_ == ESTIMATOR_ANALOG) { - heating_xs /= p->neutron_xs_[i_nuclide].total; - } else { - heating_xs *= atom_density; - } - } else { - if (p->material_ != MATERIAL_VOID) { - heating_xs = 0.0; - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i< material.nuclide_.size(); ++i) { - int j_nuclide = material.nuclide_[i]; - double atom_density {material.atom_density_(i)}; - const Nuclide& nuc {*data::nuclides[j_nuclide]}; - heating_xs += atom_density * get_nuclide_neutron_heating(p, nuc, rxn_bin, j_nuclide); - } - if (tally.estimator_ == ESTIMATOR_ANALOG) { - heating_xs /= p->macro_xs_.total; - } - } - } - score = heating_xs * flux; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events score to a heating tally bin. We actually use a - // collision estimator in place of an analog one since there is no - // reaction-wise heating cross section - if (settings::survival_biasing) { - // Account for the fact that some weight has been absorbed - score *= p->wgt_last_ + p->wgt_absorb_; - } else { - score *= p->wgt_last_; - } - } - return score; -} - -//! Helper function for nu-fission tallies with energyout filters. -// -//! In this case, we may need to score to multiple bins if there were multiple -//! neutrons produced with different energies. - -void -score_fission_eout(const Particle* p, int i_tally, int i_score, int score_bin) -{ - auto& tally {*model::tallies[i_tally]}; - auto i_eout_filt = tally.filters()[tally.energyout_filter_]; - auto i_bin = simulation::filter_matches[i_eout_filt].i_bin_; - auto bin_energyout = simulation::filter_matches[i_eout_filt].bins_[i_bin]; - - const EnergyoutFilter& eo_filt - {*dynamic_cast(model::tally_filters[i_eout_filt].get())}; - - // Note that the score below is weighted by keff. Since the creation of - // fission sites is weighted such that it is expected to create n_particles - // sites, we need to multiply the score by keff to get the true nu-fission - // rate. Otherwise, the sum of all nu-fission rates would be ~1.0. - - // loop over number of particles banked - for (auto i = 0; i < p->n_bank_; ++i) { - auto i_bank = simulation::fission_bank.size() - p->n_bank_ + i; - const auto& bank = simulation::fission_bank[i_bank]; - - // get the delayed group - auto g = bank.delayed_group; - - // determine score based on bank site weight and keff - double score = simulation::keff * bank.wgt; - - // Add derivative information for differential tallies. Note that the - // i_nuclide and atom_density arguments do not matter since this is an - // analog estimator. - if (tally.deriv_ != C_NONE) - apply_derivative_to_score(p, i_tally, 0, 0., SCORE_NU_FISSION, score); - - if (!settings::run_CE && eo_filt.matches_transport_groups()) { - - // determine outgoing energy group from fission bank - auto g_out = static_cast(bank.E); - - // modify the value so that g_out = 1 corresponds to the highest energy - // bin - g_out = eo_filt.n_bins() - g_out; - - // change outgoing energy bin - simulation::filter_matches[i_eout_filt].bins_[i_bin] = g_out; - - } else { - - double E_out; - if (settings::run_CE) { - E_out = bank.E; - } else { - E_out = data::energy_bin_avg[static_cast(bank.E)]; - } - - // Set EnergyoutFilter bin index - if (E_out < eo_filt.bins().front() || E_out > eo_filt.bins().back()) { - continue; - } else { - auto i_match = lower_bound_index(eo_filt.bins().begin(), - eo_filt.bins().end(), E_out); - simulation::filter_matches[i_eout_filt].bins_[i_bin] = i_match; - } - - } - - // Case for tallying prompt neutrons - if (score_bin == SCORE_NU_FISSION - || (score_bin == SCORE_PROMPT_NU_FISSION && g == 0)) { - - // Find the filter scoring index for this filter combination - //TODO: should this include a weight? - int filter_index = 0; - for (auto j = 0; j < tally.filters().size(); ++j) { - auto i_filt = tally.filters(j); - auto& match {simulation::filter_matches[i_filt]}; - auto i_bin = match.i_bin_; - filter_index += match.bins_[i_bin] * tally.strides(j); - } - - // Update tally results - #pragma omp atomic - tally.results_(filter_index, i_score, RESULT_VALUE) += score; - - } else if (score_bin == SCORE_DELAYED_NU_FISSION && g != 0) { - - // If the delayed group filter is present, tally to corresponding delayed - // group bin if it exists - if (tally.delayedgroup_filter_ >= 0) { - - // Get the index of the delayed group filter - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - - const DelayedGroupFilter& dg_filt {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - - // Loop over delayed group bins until the corresponding bin is found - for (auto d_bin = 0; d_bin < dg_filt.n_bins(); ++d_bin) { - if (dg_filt.groups()[d_bin] == g) { - // Find the filter index and weight for this filter combination - double filter_weight = 1.; - for (auto j = 0; j < tally.filters().size(); ++j) { - auto i_filt = tally.filters(j); - auto& match {simulation::filter_matches[i_filt]}; - auto i_bin = match.i_bin_; - filter_weight *= match.weights_[i_bin]; - } - - score_fission_delayed_dg(i_tally, d_bin, score*filter_weight, - i_score); - } - } - - // If the delayed group filter is not present, add score to tally - } else { - - // Find the filter index and weight for this filter combination - int filter_index = 0; - double filter_weight = 1.; - for (auto j = 0; j < tally.filters().size(); ++j) { - auto i_filt = tally.filters(j); - auto& match {simulation::filter_matches[i_filt]}; - auto i_bin = match.i_bin_; - filter_index += match.bins_[i_bin] * tally.strides(j); - filter_weight *= match.weights_[i_bin]; - } - - // Update tally results - #pragma omp atomic - tally.results_(filter_index, i_score, RESULT_VALUE) += score*filter_weight; - } - } - } - - // Reset outgoing energy bin and score index - simulation::filter_matches[i_eout_filt].bins_[i_bin] = bin_energyout; -} - -//! Update tally results for continuous-energy tallies with any estimator. -// -//! For analog tallies, the flux estimate depends on the score type so the flux -//! argument is really just used for filter weights. The atom_density argument -//! is not used for analog tallies. - -void -score_general_ce(Particle* p, int i_tally, int start_index, - int filter_index, int i_nuclide, double atom_density, double flux) -{ - Tally& tally {*model::tallies[i_tally]}; - - // Get the pre-collision energy of the particle. - auto E = p->E_last_; - - for (auto i = 0; i < tally.scores_.size(); ++i) { - auto score_bin = tally.scores_[i]; - auto score_index = start_index + i; - - double score; - - switch (score_bin) { - - - case SCORE_FLUX: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events score to a flux bin. We actually use a collision estimator - // in place of an analog one since there is no way to count 'events' - // exactly for the flux - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p->wgt_last_ + p->wgt_absorb_; - } else { - score = p->wgt_last_; - } - - if (p->type_ == Particle::Type::neutron || - p->type_ == Particle::Type::photon) { - score *= flux / p->macro_xs_.total; - } else { - score = 0.; - } - } else { - score = flux; - } - break; - - - case SCORE_TOTAL: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events will score to the total reaction rate. We can just use - // use the weight of the particle entering the collision as the score - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = (p->wgt_last_ + p->wgt_absorb_) * flux; - } else { - score = p->wgt_last_ * flux; - } - - } else { - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].total * atom_density * flux; - } else { - score = p->macro_xs_.total * flux; - } - } - break; - - - case SCORE_INVERSE_VELOCITY: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events score to an inverse velocity bin. We actually use a - // collision estimator in place of an analog one since there is no way - // to count 'events' exactly for the inverse velocity - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p->wgt_last_ + p->wgt_absorb_; - } else { - score = p->wgt_last_; - } - score *= flux / p->macro_xs_.total; - } else { - score = flux; - } - // Score inverse velocity in units of s/cm. - score /= std::sqrt(2. * E / MASS_NEUTRON_EV) * C_LIGHT * 100.; - break; - - - case SCORE_SCATTER: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Skip any event where the particle didn't scatter - if (p->event_ != EVENT_SCATTER) continue; - // Since only scattering events make it here, again we can use the - // weight entering the collision as the estimator for the reaction rate - score = p->wgt_last_ * flux; - } else { - if (i_nuclide >= 0) { - score = (p->neutron_xs_[i_nuclide].total - - p->neutron_xs_[i_nuclide].absorption) * atom_density * flux; - } else { - score = (p->macro_xs_.total - - p->macro_xs_.absorption) * flux; - } - } - break; - - - case SCORE_NU_SCATTER: - // Only analog estimators are available. - // Skip any event where the particle didn't scatter - if (p->event_ != EVENT_SCATTER) continue; - // For scattering production, we need to use the pre-collision weight - // times the yield as the estimate for the number of neutrons exiting a - // reaction with neutrons in the exit channel - if (p->event_mt_ == ELASTIC || p->event_mt_ == N_LEVEL || - (p->event_mt_ >= N_N1 && p->event_mt_ <= N_NC)) { - // Don't waste time on very common reactions we know have - // multiplicities of one. - score = p->wgt_last_ * flux; - } else { - // Get yield and apply to score - auto m = - data::nuclides[p->event_nuclide_]->reaction_index_[p->event_mt_]; - const auto& rxn {*data::nuclides[p->event_nuclide_]->reactions_[m]}; - score = p->wgt_last_ * flux * (*rxn.products_[0].yield_)(E); - } - break; - - - case SCORE_ABSORPTION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No absorption events actually occur if survival biasing is on -- - // just use weight absorbed in survival biasing - score = p->wgt_absorb_ * flux; - } else { - // Skip any event where the particle wasn't absorbed - if (p->event_ == EVENT_SCATTER) continue; - // All fission and absorption events will contribute here, so we - // can just use the particle's weight entering the collision - score = p->wgt_last_ * flux; - } - } else { - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].absorption * atom_density - * flux; - } else { - score = p->macro_xs_.absorption * flux; - } - } - break; - - - case SCORE_FISSION: - if (p->macro_xs_.absorption == 0) continue; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission - if (p->neutron_xs_[p->event_nuclide_].absorption > 0) { - score = p->wgt_absorb_ - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } else { - score = 0.; - } - } else { - // Skip any non-absorption events - if (p->event_ == EVENT_SCATTER) continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - score = p->wgt_last_ - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } - } else { - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].fission * atom_density * flux; - } else { - score = p->macro_xs_.fission * flux; - } - } - break; - - - case SCORE_NU_FISSION: - if (p->macro_xs_.absorption == 0) continue; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // nu-fission - if (p->neutron_xs_[p->event_nuclide_].absorption > 0) { - score = p->wgt_absorb_ - * p->neutron_xs_[p->event_nuclide_].nu_fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } else { - score = 0.; - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - score = simulation::keff * p->wgt_bank_ * flux; - } - } else { - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].nu_fission * atom_density - * flux; - } else { - score = p->macro_xs_.nu_fission * flux; - } - } - break; - - - case SCORE_PROMPT_NU_FISSION: - if (p->macro_xs_.absorption == 0) continue; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // prompt-nu-fission - if (p->neutron_xs_[p->event_nuclide_].absorption > 0) { - score = p->wgt_absorb_ - * p->neutron_xs_[p->event_nuclide_].fission - * data::nuclides[p->event_nuclide_] - ->nu(E, ReactionProduct::EmissionMode::prompt) - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } else { - score = 0.; - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - auto n_delayed = std::accumulate(p->n_delayed_bank_, - p->n_delayed_bank_+MAX_DELAYED_GROUPS, 0); - auto prompt_frac = 1. - n_delayed / static_cast(p->n_bank_); - score = simulation::keff * p->wgt_bank_ * prompt_frac * flux; - } - } else { - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].fission - * data::nuclides[i_nuclide] - ->nu(E, ReactionProduct::EmissionMode::prompt) - * atom_density * flux; - } else { - score = 0.; - // Add up contributions from each nuclide in the material. - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += p->neutron_xs_[j_nuclide].fission - * data::nuclides[j_nuclide] - ->nu(E, ReactionProduct::EmissionMode::prompt) - * atom_density * flux; - } - } - } - } - break; - - - case SCORE_DELAYED_NU_FISSION: - if (p->macro_xs_.absorption == 0) continue; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - if (p->neutron_xs_[p->event_nuclide_].absorption > 0 - && data::nuclides[p->event_nuclide_]->fissionable_) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = data::nuclides[p->event_nuclide_] - ->nu(E, ReactionProduct::EmissionMode::delayed, d); - score = p->wgt_absorb_ * yield - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs - score = p->wgt_absorb_ - * p->neutron_xs_[p->event_nuclide_].fission - * data::nuclides[p->event_nuclide_] - ->nu(E, ReactionProduct::EmissionMode::delayed) - / p->neutron_xs_[p->event_nuclide_].absorption *flux; - } - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - score = simulation::keff * p->wgt_bank_ / p->n_bank_ - * p->n_delayed_bank_[d-1] * flux; - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - // Add the contribution from all delayed groups - auto n_delayed = std::accumulate(p->n_delayed_bank_, - p->n_delayed_bank_+MAX_DELAYED_GROUPS, 0); - score = simulation::keff * p->wgt_bank_ / p->n_bank_ * n_delayed - * flux; - } - } - } else { - if (i_nuclide >= 0) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = data::nuclides[i_nuclide] - ->nu(E, ReactionProduct::EmissionMode::delayed, d); - score = p->neutron_xs_[i_nuclide].fission * yield - * atom_density * flux; - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the delayed-nu-fission macro xs by the flux - score = p->neutron_xs_[i_nuclide].fission - * data::nuclides[i_nuclide] - ->nu(E, ReactionProduct::EmissionMode::delayed) - * atom_density * flux; - } - } else { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield = data::nuclides[j_nuclide] - ->nu(E, ReactionProduct::EmissionMode::delayed, d); - score = p->neutron_xs_[j_nuclide].fission * yield - * atom_density * flux; - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - } - } - continue; - } else { - score = 0.; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += p->neutron_xs_[j_nuclide].fission - * data::nuclides[j_nuclide] - ->nu(E, ReactionProduct::EmissionMode::delayed) - * atom_density * flux; - } - } - } - } - } - break; - - - case SCORE_DECAY_RATE: - if (p->macro_xs_.absorption == 0) continue; - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - const auto& nuc {*data::nuclides[p->event_nuclide_]}; - if (p->neutron_xs_[p->event_nuclide_].absorption > 0 - && nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p->wgt_absorb_ * yield - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption - * rate * flux; - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs for all delayed - // groups - score = 0.; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d+1); - auto rate = rxn.products_[d+1].decay_rate_; - score += rate * p->wgt_absorb_ - * p->neutron_xs_[p->event_nuclide_].fission * yield - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } - } - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. - score = 0.; - for (auto i = 0; i < p->n_bank_; ++i) { - auto i_bank = simulation::fission_bank.size() - p->n_bank_ + i; - const auto& bank = simulation::fission_bank[i_bank]; - auto g = bank.delayed_group; - if (g != 0) { - const auto& nuc {*data::nuclides[p->event_nuclide_]}; - const auto& rxn {*nuc.fission_rx_[0]}; - auto rate = rxn.products_[g].decay_rate_; - score += simulation::keff * bank.wgt * rate * flux; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Find the corresponding filter bin and then score - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - if (d == g) - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - score = 0.; - } - } - } - } - } else { - if (i_nuclide >= 0) { - const auto& nuc {*data::nuclides[i_nuclide]}; - if (!nuc.fissionable_) continue; - const auto& rxn {*nuc.fission_rx_[0]}; - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p->neutron_xs_[i_nuclide].fission * yield * flux - * atom_density * rate; - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - score = 0.; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d+1); - auto rate = rxn.products_[d+1].decay_rate_; - score += p->neutron_xs_[i_nuclide].fission * flux - * yield * atom_density * rate; - } - } - } else { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d); - auto rate = rxn.products_[d].decay_rate_; - score = p->neutron_xs_[j_nuclide].fission * yield - * flux * atom_density * rate; - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - } - } - } - continue; - } else { - score = 0.; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - // We need to be careful not to overshoot the number of - // delayed groups since this could cause the range of the - // rxn.products_ array to be exceeded. Hence, we use the size - // of this array and not the MAX_DELAYED_GROUPS constant for - // this loop. - for (auto d = 0; d < rxn.products_.size() - 2; ++d) { - auto yield - = nuc.nu(E, ReactionProduct::EmissionMode::delayed, d+1); - auto rate = rxn.products_[d+1].decay_rate_; - score += p->neutron_xs_[j_nuclide].fission - * yield * atom_density * flux * rate; - } - } - } - } - } - } - } - break; - - - case SCORE_KAPPA_FISSION: - if (p->macro_xs_.absorption == 0.) continue; - score = 0.; - // Kappa-fission values are determined from the Q-value listed for the - // fission cross section. - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission scaled by the Q-value - const auto& nuc {*data::nuclides[p->event_nuclide_]}; - if (p->neutron_xs_[p->event_nuclide_].absorption > 0 - && nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score = p->wgt_absorb_ * rxn.q_value_ - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } - } else { - // Skip any non-absorption events - if (p->event_ == EVENT_SCATTER) continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - const auto& nuc {*data::nuclides[p->event_nuclide_]}; - if (p->neutron_xs_[p->event_nuclide_].absorption > 0 - && nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score = p->wgt_last_ * rxn.q_value_ - * p->neutron_xs_[p->event_nuclide_].fission - / p->neutron_xs_[p->event_nuclide_].absorption * flux; - } - } - } else { - if (i_nuclide >= 0) { - const auto& nuc {*data::nuclides[i_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score = rxn.q_value_ * p->neutron_xs_[i_nuclide].fission - * atom_density * flux; - } - } else { - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - if (nuc.fissionable_) { - const auto& rxn {*nuc.fission_rx_[0]}; - score += rxn.q_value_ * p->neutron_xs_[j_nuclide].fission - * atom_density * flux; - } - } - } - } - } - break; - - - case SCORE_EVENTS: - // Simply count the number of scoring events - score = 1.; - break; - - - case ELASTIC: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Check if event MT matches - if (p->event_mt_ != ELASTIC) continue; - score = p->wgt_last_ * flux; - } else { - if (i_nuclide >= 0) { - if (p->neutron_xs_[i_nuclide].elastic == CACHE_INVALID) - data::nuclides[i_nuclide]->calculate_elastic_xs(*p); - score = p->neutron_xs_[i_nuclide].elastic * atom_density * flux; - } else { - score = 0.; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - if (p->neutron_xs_[j_nuclide].elastic == CACHE_INVALID) - data::nuclides[j_nuclide]->calculate_elastic_xs(*p); - score += p->neutron_xs_[j_nuclide].elastic * atom_density - * flux; - } - } - } - } - break; - - case SCORE_FISS_Q_PROMPT: - case SCORE_FISS_Q_RECOV: - if (p->macro_xs_.absorption == 0.) continue; - score = score_fission_q(p, score_bin, tally, flux, i_nuclide, atom_density); - break; - - - case N_2N: - case N_3N: - case N_4N: - case N_GAMMA: - case N_P: - case N_A: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Check if the event MT matches - if (p->event_mt_ != score_bin) continue; - score = p->wgt_last_ * flux; - } else { - int m; - switch (score_bin) { - case N_GAMMA: m = 0; break; - case N_P: m = 1; break; - case N_A: m = 2; break; - case N_2N: m = 3; break; - case N_3N: m = 4; break; - case N_4N: m = 5; break; - } - if (i_nuclide >= 0) { - score = p->neutron_xs_[i_nuclide].reaction[m] * atom_density - * flux; - } else { - score = 0.; - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - score += p->neutron_xs_[j_nuclide].reaction[m] - * atom_density * flux; - } - } - } - } - break; - - - case HEATING: - score = 0.; - if (p->type_ == Particle::Type::neutron) { - score = score_neutron_heating(p, tally, flux, HEATING, - i_nuclide, atom_density); - } else if (p->type_ == Particle::Type::photon) { - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Score direct energy deposition in the collision - score = E - p->E_; - // We need to substract the energy of the secondary particles since - // they will be transported individually later - for (auto i = 0; i < p->n_bank_second_; ++i) { - auto i_bank = simulation::secondary_bank.size() - p->n_bank_second_ + i; - const auto& bank = simulation::secondary_bank[i_bank]; - if (bank.particle == Particle::Type::photon || - bank.particle == Particle::Type::neutron) { - score -= bank.E; - } else if (bank.particle == Particle::Type::positron) { - // Annihilation of the positron will produce two new photons - score -= 2*MASS_ELECTRON_EV; - } - } - score *= p->wgt_last_ * flux; - } else { - // Calculate photon heating cross section on-the-fly - if (i_nuclide >= 0) { - // Find the element corresponding to the nuclide - auto name = data::nuclides[i_nuclide]->name_; - std::string element = to_element(name); - int i_element = data::element_map[element]; - auto& heating {data::elements[i_element].heating_}; - auto i_grid = p->photon_xs_[i_element].index_grid; - auto f = p->photon_xs_[i_element].interp_factor; - score = std::exp(heating(i_grid) + f * (heating(i_grid+1) - - heating(i_grid))) * atom_density * flux; - } else { - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_element = material.element_[i]; - auto atom_density = material.atom_density_(i); - auto& heating {data::elements[i_element].heating_}; - auto i_grid = p->photon_xs_[i_element].index_grid; - auto f = p->photon_xs_[i_element].interp_factor; - score += std::exp(heating(i_grid) + f * (heating(i_grid+1) - - heating(i_grid))) * atom_density * flux; - } - } - } - } - } - break; - - default: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Any other score is assumed to be a MT number. Thus, we just need - // to check if it matches the MT number of the event - if (p->event_mt_ != score_bin) continue; - score = p->wgt_last_*flux; - } else { - // Any other cross section has to be calculated on-the-fly - if (score_bin < 2) fatal_error("Invalid score type on tally " - + std::to_string(tally.id_)); - score = 0.; - if (i_nuclide >= 0) { - const auto& nuc {*data::nuclides[i_nuclide]}; - auto m = nuc.reaction_index_[score_bin]; - if (m == C_NONE) continue; - const auto& rxn {*nuc.reactions_[m]}; - auto i_temp = p->neutron_xs_[i_nuclide].index_temp; - if (i_temp >= 0) { // Can be false due to multipole - auto i_grid = p->neutron_xs_[i_nuclide].index_grid; - auto f = p->neutron_xs_[i_nuclide].interp_factor; - const auto& xs {rxn.xs_[i_temp]}; - if (i_grid >= xs.threshold) { - score = ((1.0 - f) * xs.value[i_grid-xs.threshold] - + f * xs.value[i_grid-xs.threshold+1]) * atom_density * flux; - } - } - } else { - if (p->material_ != MATERIAL_VOID) { - const Material& material {*model::materials[p->material_]}; - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto j_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - const auto& nuc {*data::nuclides[j_nuclide]}; - auto m = nuc.reaction_index_[score_bin]; - if (m == C_NONE) continue; - const auto& rxn {*nuc.reactions_[m]}; - auto i_temp = p->neutron_xs_[j_nuclide].index_temp; - if (i_temp >= 0) { // Can be false due to multipole - auto i_grid = p->neutron_xs_[j_nuclide].index_grid; - auto f = p->neutron_xs_[j_nuclide].interp_factor; - const auto& xs {rxn.xs_[i_temp]}; - if (i_grid >= xs.threshold) { - score += ((1.0 - f) * xs.value[i_grid-xs.threshold] - + f * xs.value[i_grid-xs.threshold+1]) * atom_density - * flux; - } - } - } - } - } - } - } - - // Add derivative information on score for differnetial tallies. - if (tally.deriv_ != C_NONE) - apply_derivative_to_score(p, i_tally, i_nuclide, atom_density, score_bin, - score); - - // Update tally results - #pragma omp atomic - tally.results_(filter_index, score_index, RESULT_VALUE) += score; - } -} - -//! Update tally results for multigroup tallies with any estimator. -// -//! For analog tallies, the flux estimate depends on the score type so the flux -//! argument is really just used for filter weights. - -void -score_general_mg(const Particle* p, int i_tally, int start_index, - int filter_index, int i_nuclide, double atom_density, double flux) -{ - auto& tally {*model::tallies[i_tally]}; - - // Set the direction and group to use with get_xs - Direction p_u; - int p_g; - if (tally.estimator_ == ESTIMATOR_ANALOG - || tally.estimator_ == ESTIMATOR_COLLISION) { - - if (settings::survival_biasing) { - - // Then we either are alive and had a scatter (and so g changed), - // or are dead and g did not change - if (p->alive_) { - p_u = p->u_last_; - p_g = p->g_last_; - } else { - p_u = p->u_local(); - p_g = p->g_; - } - } else if (p->event_ == EVENT_SCATTER) { - - // Then the energy group has been changed by the scattering routine - // meaning gin is now in p % last_g - p_u = p->u_last_; - p_g = p->g_last_; - } else { - - // No scatter, no change in g. - p_u = p->u_local(); - p_g = p->g_; - } - } else { - - // No actual collision so g has not changed. - p_u = p->u_local(); - p_g = p->g_; - } - - // To significantly reduce de-referencing, point matxs to the macroscopic - // Mgxs for the material of interest - data::macro_xs[p->material_].set_angle_index(p_u); - - // Do same for nucxs, point it to the microscopic nuclide data of interest - if (i_nuclide >= 0) { - // And since we haven't calculated this temperature index yet, do so now - data::nuclides_MG[i_nuclide].set_temperature_index(p->sqrtkT_); - data::nuclides_MG[i_nuclide].set_angle_index(p_u); - } - - for (auto i = 0; i < tally.scores_.size(); ++i) { - auto score_bin = tally.scores_[i]; - auto score_index = start_index + i; - - double score; - - switch (score_bin) { - - - case SCORE_FLUX: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events score to a flux bin. We actually use a collision estimator - // in place of an analog one since there is no way to count 'events' - // exactly for the flux - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p->wgt_last_ + p->wgt_absorb_; - } else { - score = p->wgt_last_; - } - score *= flux / p->macro_xs_.total; - } else { - score = flux; - } - break; - - - case SCORE_TOTAL: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // All events will score to the total reaction rate. We can just use - // use the weight of the particle entering the collision as the score - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p->wgt_last_ + p->wgt_absorb_; - } else { - score = p->wgt_last_; - } - //TODO: should flux be multiplied in above instead of below? - if (i_nuclide >= 0) { - score *= flux * atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_TOTAL, p_g) - / get_macro_xs(p->material_, MG_GET_XS_TOTAL, p_g); - } - } else { - if (i_nuclide >= 0) { - score = get_nuclide_xs(i_nuclide, MG_GET_XS_TOTAL, p_g) - * atom_density * flux; - } else { - score = p->macro_xs_.total * flux; - } - } - break; - - - case SCORE_INVERSE_VELOCITY: - if (tally.estimator_ == ESTIMATOR_ANALOG - || tally.estimator_ == ESTIMATOR_COLLISION) { - // All events score to an inverse velocity bin. We actually use a - // collision estimator in place of an analog one since there is no way - // to count 'events' exactly for the inverse velocity - if (settings::survival_biasing) { - // We need to account for the fact that some weight was already - // absorbed - score = p->wgt_last_ + p->wgt_absorb_; - } else { - score = p->wgt_last_; - } - if (i_nuclide >= 0) { - score *= flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_INVERSE_VELOCITY, p_g) - / get_macro_xs(p->material_, MG_GET_XS_TOTAL, p_g); - } else { - score *= flux - * get_macro_xs(p->material_, MG_GET_XS_INVERSE_VELOCITY, p_g) - / get_macro_xs(p->material_, MG_GET_XS_TOTAL, p_g); - } - } else { - if (i_nuclide >= 0) { - score = flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_INVERSE_VELOCITY, p_g); - } else { - score = flux - * get_macro_xs(p->material_, MG_GET_XS_INVERSE_VELOCITY, p_g); - } - } - break; - - - case SCORE_SCATTER: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Skip any event where the particle didn't scatter - if (p->event_ != EVENT_SCATTER) continue; - // Since only scattering events make it here, again we can use the - // weight entering the collision as the estimator for the reaction rate - score = p->wgt_last_ * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_SCATTER_FMU_MULT, - p->g_last_, &p->g_, &p->mu_, nullptr) - / get_macro_xs(p->material_, MG_GET_XS_SCATTER_FMU_MULT, - p->g_last_, &p->g_, &p->mu_, nullptr); - } - } else { - if (i_nuclide >= 0) { - score = atom_density * flux * get_nuclide_xs( - i_nuclide, MG_GET_XS_SCATTER_MULT, p_g, nullptr, &p->mu_, nullptr); - } else { - score = flux * get_macro_xs( - p->material_, MG_GET_XS_SCATTER_MULT, p_g, nullptr, &p->mu_, nullptr); - } - } - break; - - - case SCORE_NU_SCATTER: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - // Skip any event where the particle didn't scatter - if (p->event_ != EVENT_SCATTER) continue; - // For scattering production, we need to use the pre-collision weight - // times the multiplicity as the estimate for the number of neutrons - // exiting a reaction with neutrons in the exit channel - score = p->wgt_ * flux; - // Since we transport based on material data, the angle selected - // was not selected from the f(mu) for the nuclide. Therefore - // adjust the score by the actual probability for that nuclide. - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_SCATTER_FMU, - p->g_last_, &p->g_, &p->mu_, nullptr) - / get_macro_xs(p->material_, MG_GET_XS_SCATTER_FMU, - p->g_last_, &p->g_, &p->mu_, nullptr); - } - } else { - if (i_nuclide >= 0) { - score = atom_density * flux * get_nuclide_xs( - i_nuclide, MG_GET_XS_SCATTER, p_g); - } else { - score = flux * get_macro_xs(p->material_, MG_GET_XS_SCATTER, p_g); - } - } - break; - - - case SCORE_ABSORPTION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No absorption events actually occur if survival biasing is on -- - // just use weight absorbed in survival biasing - score = p->wgt_absorb_ * flux; - } else { - // Skip any event where the particle wasn't absorbed - if (p->event_ == EVENT_SCATTER) continue; - // All fission and absorption events will contribute here, so we - // can just use the particle's weight entering the collision - score = p->wgt_last_ * flux; - } - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_ABSORPTION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } else { - if (i_nuclide >= 0) { - score = atom_density * flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_ABSORPTION, p_g); - } else { - score = p->macro_xs_.absorption * flux; - } - } - break; - - - case SCORE_FISSION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission - score = p->wgt_absorb_ * flux; - } else { - // Skip any non-absorption events - if (p->event_ == EVENT_SCATTER) continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - score = p->wgt_last_ * flux; - } - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } else { - if (i_nuclide >= 0) { - score = get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - * atom_density * flux; - } else { - score = get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g) * flux; - } - } - break; - - - case SCORE_NU_FISSION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // nu-fission - score = p->wgt_absorb_ * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - score = simulation::keff * p->wgt_bank_ * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g); - } - } - } else { - if (i_nuclide >= 0) { - score = get_nuclide_xs(i_nuclide, MG_GET_XS_NU_FISSION, p_g) - * atom_density * flux; - } else { - score = get_macro_xs(p->material_, MG_GET_XS_NU_FISSION, p_g) * flux; - } - } - break; - - - case SCORE_PROMPT_NU_FISSION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // prompt-nu-fission - score = p->wgt_absorb_ * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_PROMPT_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_PROMPT_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. - auto n_delayed = std::accumulate(p->n_delayed_bank_, - p->n_delayed_bank_+MAX_DELAYED_GROUPS, 0); - auto prompt_frac = 1. - n_delayed / static_cast(p->n_bank_); - score = simulation::keff * p->wgt_bank_ * prompt_frac * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g); - } - } - } else { - if (i_nuclide >= 0) { - score = get_nuclide_xs(i_nuclide, MG_GET_XS_PROMPT_NU_FISSION, p_g) - * atom_density * flux; - } else { - score = get_macro_xs(p->material_, MG_GET_XS_PROMPT_NU_FISSION, p_g) - * flux; - } - } - break; - - - case SCORE_DELAYED_NU_FISSION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing || p->fission_) { - if (tally.energyout_filter_ != C_NONE) { - // Fission has multiple outgoing neutrons so this helper function - // is used to handle scoring the multiple filter bins. - score_fission_eout(p, i_tally, score_index, score_bin); - continue; - } - } - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - if (get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g) > 0) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - score = p->wgt_absorb_ * flux; - if (i_nuclide >= 0) { - score *= - get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs - score = p->wgt_absorb_ * flux; - if (i_nuclide >= 0) { - score *= - get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - score = simulation::keff * p->wgt_bank_ / p->n_bank_ - * p->n_delayed_bank_[d-1] * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g); - } - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - // Add the contribution from all delayed groups - auto n_delayed = std::accumulate(p->n_delayed_bank_, - p->n_delayed_bank_+MAX_DELAYED_GROUPS, 0); - score = simulation::keff * p->wgt_bank_ / p->n_bank_ * n_delayed - * flux; - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g); - } - } - } - } else { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - if (i_nuclide >= 0) { - score = flux * atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } else { - score = flux - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - if (i_nuclide >= 0) { - score = flux * atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, p_g); - } else { - score = flux - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, p_g); - } - } - } - break; - - - case SCORE_DECAY_RATE: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // delayed-nu-fission - if (get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g) > 0) { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - score = p->wgt_absorb_ * flux; - if (i_nuclide >= 0) { - score *= - get_nuclide_xs(i_nuclide, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - continue; - } else { - // If the delayed group filter is not present, compute the score - // by multiplying the absorbed weight by the fraction of the - // delayed-nu-fission xs to the absorption xs for all delayed - // groups - score = 0.; - for (auto d = 0; d < data::num_delayed_groups; ++d) { - if (i_nuclide >= 0) { - score += p->wgt_absorb_ * flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score += p->wgt_absorb_ * flux - * get_macro_xs(p->material_, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } - } - } - } else { - // Skip any non-fission events - if (!p->fission_) continue; - // If there is no outgoing energy filter, than we only need to score - // to one bin. For the score to be 'analog', we need to score the - // number of particles that were banked in the fission bank. Since - // this was weighted by 1/keff, we multiply by keff to get the proper - // score. Loop over the neutrons produced from fission and check which - // ones are delayed. If a delayed neutron is encountered, add its - // contribution to the fission bank to the score. - score = 0.; - for (auto i = 0; i < p->n_bank_; ++i) { - auto i_bank = simulation::fission_bank.size() - p->n_bank_ + i; - const auto& bank = simulation::fission_bank[i_bank]; - auto g = bank.delayed_group; - if (g != 0) { - if (i_nuclide >= 0) { - score += simulation::keff * atom_density * bank.wgt * flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_DECAY_RATE, p_g, - nullptr, nullptr, &g) - * get_nuclide_xs(i_nuclide, MG_GET_XS_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_FISSION, p_g); - } else { - score += simulation::keff * bank.wgt * flux - * get_macro_xs(p->material_, MG_GET_XS_DECAY_RATE, p_g, - nullptr, nullptr, &g); - } - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Find the corresponding filter bin and then score - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - if (d == g) - score_fission_delayed_dg(i_tally, d_bin, score, - score_index); - } - score = 0.; - } - } - } - if (tally.delayedgroup_filter_ != C_NONE) continue; - } - } else { - if (tally.delayedgroup_filter_ != C_NONE) { - auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; - const DelayedGroupFilter& filt - {*dynamic_cast( - model::tally_filters[i_dg_filt].get())}; - // Tally each delayed group bin individually - for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { - auto d = filt.groups()[d_bin]; - if (i_nuclide >= 0) { - score += atom_density * flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } else { - score += flux - * get_macro_xs(p->material_, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } - score_fission_delayed_dg(i_tally, d_bin, score, score_index); - } - continue; - } else { - score = 0.; - for (auto d = 0; d < data::num_delayed_groups; ++d) { - if (i_nuclide >= 0) { - score += atom_density * flux - * get_nuclide_xs(i_nuclide, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_nuclide_xs(i_nuclide, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } else { - score += flux - * get_macro_xs(p->material_, MG_GET_XS_DECAY_RATE, - p_g, nullptr, nullptr, &d) - * get_macro_xs(p->material_, MG_GET_XS_DELAYED_NU_FISSION, - p_g, nullptr, nullptr, &d); - } - } - } - } - break; - - - case SCORE_KAPPA_FISSION: - if (tally.estimator_ == ESTIMATOR_ANALOG) { - if (settings::survival_biasing) { - // No fission events occur if survival biasing is on -- need to - // calculate fraction of absorptions that would have resulted in - // fission scaled by the Q-value - score = p->wgt_absorb_ * flux; - } else { - // Skip any non-absorption events - if (p->event_ == EVENT_SCATTER) continue; - // All fission events will contribute, so again we can use particle's - // weight entering the collision as the estimate for the fission - // reaction rate - score = p->wgt_last_ * flux; - } - if (i_nuclide >= 0) { - score *= atom_density - * get_nuclide_xs(i_nuclide, MG_GET_XS_KAPPA_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } else { - score *= - get_macro_xs(p->material_, MG_GET_XS_KAPPA_FISSION, p_g) - / get_macro_xs(p->material_, MG_GET_XS_ABSORPTION, p_g); - } - } else { - if (i_nuclide >= 0) { - score = get_nuclide_xs(i_nuclide, MG_GET_XS_KAPPA_FISSION, p_g) - * atom_density * flux; - } else { - score = get_macro_xs(p->material_, MG_GET_XS_KAPPA_FISSION, p_g) - * flux; - } - } - break; - - - case SCORE_EVENTS: - // Simply count the number of scoring events - score = 1.; - break; - - - default: - continue; - } - - // Update tally results - #pragma omp atomic - tally.results_(filter_index, score_index, RESULT_VALUE) += score; - } -} - -//! Tally rates for when the user requests a tally on all nuclides. - -void -score_all_nuclides(Particle* p, int i_tally, double flux, - int filter_index) -{ - const Tally& tally {*model::tallies[i_tally]}; - const Material& material {*model::materials[p->material_]}; - - // Score all individual nuclide reaction rates. - for (auto i = 0; i < material.nuclide_.size(); ++i) { - auto i_nuclide = material.nuclide_[i]; - auto atom_density = material.atom_density_(i); - - //TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i_nuclide*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, i_nuclide*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux); - } - } - - // Score total material reaction rates. - int i_nuclide = -1; - double atom_density = 0.; - auto n_nuclides = data::nuclides.size(); - //TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, n_nuclides*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux); - } else { - score_general_mg(p, i_tally, n_nuclides*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux); - } -} - -void score_analog_tally_ce(Particle* p) -{ - for (auto i_tally : model::active_analog_tallies) { - const Tally& tally {*model::tallies[i_tally]}; - - // Initialize an iterator over valid filter bin combinations. If there are - // no valid combinations, use a continue statement to ensure we skip the - // assume_separate break below. - auto filter_iter = FilterBinIter(tally, p); - auto end = FilterBinIter(tally, true); - if (filter_iter == end) continue; - - // Loop over filter bins. - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - auto filter_weight = filter_iter.weight_; - - // Loop over nuclide bins. - if (!tally.all_nuclides_) { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; - - // Tally this event in the present nuclide bin if that bin represents - // the event nuclide or the total material. Note that the atomic - // density argument for score_general is not used for analog tallies. - if (i_nuclide == p->event_nuclide_ || i_nuclide == -1) - score_general_ce(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, -1., filter_weight); - } - - } else { - // In the case that the user has requested to tally all nuclides, we - // can take advantage of the fact that we know exactly how nuclide - // bins correspond to nuclide indices. First, tally the nuclide. - auto i = p->event_nuclide_; - score_general_ce(p, i_tally, i*tally.scores_.size(), filter_index, - -1, -1., filter_weight); - - // Now tally the total material. - i = tally.nuclides_.size(); - score_general_ce(p, i_tally, i*tally.scores_.size(), filter_index, - -1, -1., filter_weight); - } - } - - // If the user has specified that we can assume all tallies are spatially - // separate, this implies that once a tally has been scored to, we needn't - // check the others. This cuts down on overhead when there are many - // tallies specified - if (settings::assume_separate) break; - } - - // Reset all the filter matches for the next tally event. - for (auto& match : simulation::filter_matches) - match.bins_present_ = false; -} - -void score_analog_tally_mg(const Particle* p) -{ - for (auto i_tally : model::active_analog_tallies) { - const Tally& tally {*model::tallies[i_tally]}; - - // Initialize an iterator over valid filter bin combinations. If there are - // no valid combinations, use a continue statement to ensure we skip the - // assume_separate break below. - auto filter_iter = FilterBinIter(tally, p); - auto end = FilterBinIter(tally, true); - if (filter_iter == end) continue; - - // Loop over filter bins. - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - auto filter_weight = filter_iter.weight_; - - // Loop over nuclide bins. - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; - - double atom_density = 0.; - if (i_nuclide >= 0) { - auto j = model::materials[p->material_]->mat_nuclide_index_[i_nuclide]; - if (j == C_NONE) continue; - atom_density = model::materials[p->material_]->atom_density_(j); - } - - score_general_mg(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, atom_density, filter_weight); - } - } - - // If the user has specified that we can assume all tallies are spatially - // separate, this implies that once a tally has been scored to, we needn't - // check the others. This cuts down on overhead when there are many - // tallies specified - if (settings::assume_separate) break; - } - - // Reset all the filter matches for the next tally event. - for (auto& match : simulation::filter_matches) - match.bins_present_ = false; -} - -void -score_tracklength_tally(Particle* p, double distance) -{ - // Determine the tracklength estimate of the flux - double flux = p->wgt_ * distance; - - for (auto i_tally : model::active_tracklength_tallies) { - const Tally& tally {*model::tallies[i_tally]}; - - // Initialize an iterator over valid filter bin combinations. If there are - // no valid combinations, use a continue statement to ensure we skip the - // assume_separate break below. - auto filter_iter = FilterBinIter(tally, p); - auto end = FilterBinIter(tally, true); - if (filter_iter == end) continue; - - // Loop over filter bins. - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - auto filter_weight = filter_iter.weight_; - - // Loop over nuclide bins. - if (tally.all_nuclides_) { - if (p->material_ != MATERIAL_VOID) - score_all_nuclides(p, i_tally, flux*filter_weight, filter_index); - - } else { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; - - double atom_density = 0.; - if (i_nuclide >= 0) { - if (p->material_ != MATERIAL_VOID) { - auto j = model::materials[p->material_]->mat_nuclide_index_[i_nuclide]; - if (j == C_NONE) continue; - atom_density = model::materials[p->material_]->atom_density_(j); - } - } - - //TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux*filter_weight); - } else { - score_general_mg(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux*filter_weight); - } - } - } - - } - - // If the user has specified that we can assume all tallies are spatially - // separate, this implies that once a tally has been scored to, we needn't - // check the others. This cuts down on overhead when there are many - // tallies specified - if (settings::assume_separate) break; - } - - // Reset all the filter matches for the next tally event. - for (auto& match : simulation::filter_matches) - match.bins_present_ = false; -} - -void score_collision_tally(Particle* p) -{ - // Determine the collision estimate of the flux - double flux; - if (!settings::survival_biasing) { - flux = p->wgt_last_ / p->macro_xs_.total; - } else { - flux = (p->wgt_last_ + p->wgt_absorb_) / p->macro_xs_.total; - } - - for (auto i_tally : model::active_collision_tallies) { - const Tally& tally {*model::tallies[i_tally]}; - - // Initialize an iterator over valid filter bin combinations. If there are - // no valid combinations, use a continue statement to ensure we skip the - // assume_separate break below. - auto filter_iter = FilterBinIter(tally, p); - auto end = FilterBinIter(tally, true); - if (filter_iter == end) continue; - - // Loop over filter bins. - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - auto filter_weight = filter_iter.weight_; - - // Loop over nuclide bins. - if (tally.all_nuclides_) { - score_all_nuclides(p, i_tally, flux*filter_weight, filter_index); - - } else { - for (auto i = 0; i < tally.nuclides_.size(); ++i) { - auto i_nuclide = tally.nuclides_[i]; - - double atom_density = 0.; - if (i_nuclide >= 0) { - auto j = model::materials[p->material_]->mat_nuclide_index_[i_nuclide]; - if (j == C_NONE) continue; - atom_density = model::materials[p->material_]->atom_density_(j); - } - - //TODO: consider replacing this "if" with pointers or templates - if (settings::run_CE) { - score_general_ce(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux*filter_weight); - } else { - score_general_mg(p, i_tally, i*tally.scores_.size(), filter_index, - i_nuclide, atom_density, flux*filter_weight); - } - } - } - } - - // If the user has specified that we can assume all tallies are spatially - // separate, this implies that once a tally has been scored to, we needn't - // check the others. This cuts down on overhead when there are many - // tallies specified - if (settings::assume_separate) break; - } - - // Reset all the filter matches for the next tally event. - for (auto& match : simulation::filter_matches) - match.bins_present_ = false; -} - -void -score_surface_tally(const Particle* p, const std::vector& tallies) -{ - // No collision, so no weight change when survival biasing - double flux = p->wgt_; - - for (auto i_tally : tallies) { - auto& tally {*model::tallies[i_tally]}; - - // Initialize an iterator over valid filter bin combinations. If there are - // no valid combinations, use a continue statement to ensure we skip the - // assume_separate break below. - auto filter_iter = FilterBinIter(tally, p); - auto end = FilterBinIter(tally, true); - if (filter_iter == end) continue; - - // Loop over filter bins. - for (; filter_iter != end; ++filter_iter) { - auto filter_index = filter_iter.index_; - auto filter_weight = filter_iter.weight_; - - // Loop over scores. - // There is only one score type for current tallies so there is no need - // for a further scoring function. - double score = flux * filter_weight; - for (auto score_index = 0; score_index < tally.scores_.size(); - ++score_index) { - #pragma omp atomic - tally.results_(filter_index, score_index, RESULT_VALUE) += score; - } - } - - // If the user has specified that we can assume all tallies are spatially - // separate, this implies that once a tally has been scored to, we needn't - // check the others. This cuts down on overhead when there are many - // tallies specified - if (settings::assume_separate) break; - } - - // Reset all the filter matches for the next tally event. - for (auto& match : simulation::filter_matches) - match.bins_present_ = false; -} - -} // namespace openmc diff --git a/src/tallies/trigger.cpp b/src/tallies/trigger.cpp deleted file mode 100644 index ebf3d83bb..000000000 --- a/src/tallies/trigger.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include "openmc/tallies/trigger.h" - -#include -#include -#include // for std::pair - -#include "openmc/capi.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/reaction.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" -#include "openmc/tallies/tally.h" - -namespace openmc { - -//============================================================================== -// Global variable definitions -//============================================================================== - -namespace settings { - KTrigger keff_trigger; -} - -//============================================================================== -// Non-member functions -//============================================================================== - -std::pair -get_tally_uncertainty(int i_tally, int score_index, int filter_index) -{ - const auto& tally {model::tallies[i_tally]}; - - auto sum = tally->results_(filter_index, score_index, RESULT_SUM); - auto sum_sq = tally->results_(filter_index, score_index, RESULT_SUM_SQ); - - int n = tally->n_realizations_; - auto mean = sum / n; - double std_dev = std::sqrt((sum_sq/n - mean*mean) / (n-1)); - double rel_err = (mean != 0.) ? std_dev / std::abs(mean) : 0.; - - return {std_dev, rel_err}; -} - -//! Find the limiting limiting tally trigger. -// -//! param[out] ratio The uncertainty/threshold ratio for the most limiting -//! tally trigger -//! param[out] tally_id The ID number of the most limiting tally -//! param[out] score The most limiting tally score bin - -void -check_tally_triggers(double& ratio, int& tally_id, int& score) -{ - ratio = 0.; - for (auto i_tally = 0; i_tally < model::tallies.size(); ++i_tally) { - const Tally& t {*model::tallies[i_tally]}; - - // Ignore tallies with less than two realizations. - if (t.n_realizations_ < 2) continue; - - for (const auto& trigger : t.triggers_) { - const auto& results = t.results_; - for (auto filter_index = 0; filter_index < results.shape()[0]; - ++filter_index) { - for (auto score_index = 0; score_index < results.shape()[1]; - ++score_index) { - // Compute the tally uncertainty metrics. - auto uncert_pair = get_tally_uncertainty(i_tally, score_index, - filter_index); - double std_dev = uncert_pair.first; - double rel_err = uncert_pair.second; - - // Pick out the relevant uncertainty metric for this trigger. - double uncertainty; - switch (trigger.metric) { - case TriggerMetric::variance: - uncertainty = std_dev * std_dev; - break; - case TriggerMetric::standard_deviation: - uncertainty = std_dev; - break; - case TriggerMetric::relative_error: - uncertainty = rel_err; - break; - case TriggerMetric::not_active: - uncertainty = 0.0; - break; - } - - // Compute the uncertainty / threshold ratio. - double this_ratio = uncertainty / trigger.threshold; - if (trigger.metric == TriggerMetric::variance) { - this_ratio = std::sqrt(ratio); - } - - // If this is the most uncertain value, set the output variables. - if (this_ratio > ratio) { - ratio = this_ratio; - score = t.scores_[trigger.score_index]; - tally_id = t.id_; - } - } - } - } - } -} - -//! Compute the uncertainty/threshold ratio for the eigenvalue trigger. - -double -check_keff_trigger() -{ - if (settings::run_mode != RUN_MODE_EIGENVALUE) return 0.0; - - double k_combined[2]; - openmc_get_keff(k_combined); - - double uncertainty = 0.; - switch (settings::keff_trigger.metric) { - case TriggerMetric::variance: - uncertainty = k_combined[1] * k_combined[1]; - break; - case TriggerMetric::standard_deviation: - uncertainty = k_combined[1]; - break; - case TriggerMetric::relative_error: - uncertainty = k_combined[1] / k_combined[0]; - break; - default: - // If it's an unrecognized TriggerMetric or no keff trigger is on, - // return 0 to stop division by zero where "ratio" is calculated. - return 0.0; - } - - double ratio = uncertainty / settings::keff_trigger.threshold; - if (settings::keff_trigger.metric == TriggerMetric::variance) - ratio = std::sqrt(ratio); - return ratio; -} - -//! See if tally and eigenvalue uncertainties are under trigger thresholds. - -void -check_triggers() -{ - // Make some aliases. - const auto current_batch {simulation::current_batch}; - const auto n_batches {settings::n_batches}; - const auto interval {settings::trigger_batch_interval}; - - // See if the current batch is one for which the triggers must be checked. - if (!settings::trigger_on) return; - if (current_batch < n_batches) return; - if (((current_batch - n_batches) % interval) != 0) return; - - // Check the eigenvalue and tally triggers. - double keff_ratio = check_keff_trigger(); - double tally_ratio; - int tally_id, score; - check_tally_triggers(tally_ratio, tally_id, score); - - // If all the triggers are satisfied, alert the user and return. - if (std::max(keff_ratio, tally_ratio) <= 1.) { - simulation::satisfy_triggers = true; - write_message("Triggers satisfied for batch " - + std::to_string(current_batch), 7); - return; - } - - // At least one trigger is unsatisfied. Let the user know which one. - simulation::satisfy_triggers = false; - std::stringstream msg; - msg << "Triggers unsatisfied, max unc./thresh. is "; - if (keff_ratio >= tally_ratio) { - msg << keff_ratio << " for eigenvalue"; - } else { - msg << tally_ratio << " for " << reaction_name(score) << " in tally " - << tally_id; - } - write_message(msg, 7); - - // Estimate batches til triggers are satisfied. - if (settings::trigger_predict) { - // This calculation assumes tally variance is proportional to 1/N where N is - // the number of batches. - auto max_ratio = std::max(keff_ratio, tally_ratio); - auto n_active = current_batch - settings::n_inactive; - auto n_pred_batches = static_cast(n_active * max_ratio * max_ratio) - + settings::n_inactive + 1; - - std::stringstream msg; - msg << "The estimated number of batches is " << n_pred_batches; - if (n_pred_batches > settings::n_max_batches) { - msg << " --- greater than max batches"; - warning(msg); - } else { - write_message(msg, 7); - } - } -} - -} // namespace openmc diff --git a/src/thermal.cpp b/src/thermal.cpp deleted file mode 100644 index 49b522376..000000000 --- a/src/thermal.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include "openmc/thermal.h" - -#include // for sort, move, min, max, find -#include // for round, sqrt, abs -#include // for stringstream - -#include "xtensor/xarray.hpp" -#include "xtensor/xbuilder.hpp" -#include "xtensor/xmath.hpp" -#include "xtensor/xsort.hpp" -#include "xtensor/xtensor.hpp" -#include "xtensor/xview.hpp" - -#include "openmc/constants.h" -#include "openmc/endf.h" -#include "openmc/error.h" -#include "openmc/random_lcg.h" -#include "openmc/search.h" -#include "openmc/secondary_correlated.h" -#include "openmc/secondary_thermal.h" -#include "openmc/settings.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace data { -std::vector> thermal_scatt; -std::unordered_map thermal_scatt_map; -} - -//============================================================================== -// ThermalScattering implementation -//============================================================================== - -ThermalScattering::ThermalScattering(hid_t group, const std::vector& temperature) -{ - // Get name of table from group - name_ = object_name(group); - - // Get rid of leading '/' - name_ = name_.substr(1); - - read_attribute(group, "atomic_weight_ratio", awr_); - read_attribute(group, "energy_max", energy_max_); - read_attribute(group, "nuclides", nuclides_); - - // Read temperatures - hid_t kT_group = open_group(group, "kTs"); - - // Determine temperatures available - auto dset_names = dataset_names(kT_group); - auto n = dset_names.size(); - auto temps_available = xt::empty({n}); - for (int i = 0; i < dset_names.size(); ++i) { - // Read temperature value - double T; - read_dataset(kT_group, dset_names[i].data(), T); - temps_available[i] = T / K_BOLTZMANN; - } - std::sort(temps_available.begin(), temps_available.end()); - - // Determine actual temperatures to read -- start by checking whether a - // temperature range was given, in which case all temperatures in the range - // are loaded irrespective of what temperatures actually appear in the model - std::vector temps_to_read; - if (settings::temperature_range[1] > 0.0) { - for (const auto& T : temps_available) { - if (settings::temperature_range[0] <= T && - T <= settings::temperature_range[1]) { - temps_to_read.push_back(std::round(T)); - } - } - } - - switch (settings::temperature_method) { - case TEMPERATURE_NEAREST: - // Determine actual temperatures to read - for (const auto& T : temperature) { - - auto i_closest = xt::argmin(xt::abs(temps_available - T))[0]; - auto temp_actual = temps_available[i_closest]; - if (std::abs(temp_actual - T) < settings::temperature_tolerance) { - if (std::find(temps_to_read.begin(), temps_to_read.end(), std::round(temp_actual)) - == temps_to_read.end()) { - temps_to_read.push_back(std::round(temp_actual)); - } - } else { - std::stringstream msg; - msg << "Nuclear data library does not contain cross sections for " - << name_ << " at or near " << std::round(T) << " K."; - fatal_error(msg); - } - } - break; - - case TEMPERATURE_INTERPOLATION: - // If temperature interpolation or multipole is selected, get a list of - // bounding temperatures for each actual temperature present in the model - for (const auto& T : temperature) { - bool found = false; - for (int j = 0; j < temps_available.size() - 1; ++j) { - if (temps_available[j] <= T && T < temps_available[j + 1]) { - int T_j = std::round(temps_available[j]); - int T_j1 = std::round(temps_available[j + 1]); - if (std::find(temps_to_read.begin(), temps_to_read.end(), T_j) == temps_to_read.end()) { - temps_to_read.push_back(T_j); - } - if (std::find(temps_to_read.begin(), temps_to_read.end(), T_j1) == temps_to_read.end()) { - temps_to_read.push_back(T_j1); - } - found = true; - } - } - if (!found) { - std::stringstream msg; - msg << "Nuclear data library does not contain cross sections for " - << name_ << " at temperatures that bound " << std::round(T) << " K."; - fatal_error(msg); - } - } - } - - // Sort temperatures to read - std::sort(temps_to_read.begin(), temps_to_read.end()); - - auto n_temperature = temps_to_read.size(); - kTs_.reserve(n_temperature); - data_.reserve(n_temperature); - - for (auto T : temps_to_read) { - // Get temperature as a string - std::string temp_str = std::to_string(T) + "K"; - - // Read exact temperature value - double kT; - read_dataset(kT_group, temp_str.data(), kT); - kTs_.push_back(kT); - - // Open group for temperature i - hid_t T_group = open_group(group, temp_str.data()); - data_.emplace_back(T_group); - close_group(T_group); - } - - close_group(kT_group); -} - -void -ThermalScattering::calculate_xs(double E, double sqrtkT, int* i_temp, - double* elastic, double* inelastic) const -{ - // Determine temperature for S(a,b) table - double kT = sqrtkT*sqrtkT; - int i; - if (settings::temperature_method == TEMPERATURE_NEAREST) { - // If using nearest temperature, do linear search on temperature - for (i = 0; i < kTs_.size(); ++i) { - if (std::abs(kTs_[i] - kT) < K_BOLTZMANN*settings::temperature_tolerance) { - break; - } - } - } else { - // Find temperatures that bound the actual temperature - for (i = 0; i < kTs_.size() - 1; ++i) { - if (kTs_[i] <= kT && kT < kTs_[i+1]) { - break; - } - } - - // Randomly sample between temperature i and i+1 - double f = (kT - kTs_[i]) / (kTs_[i+1] - kTs_[i]); - if (f > prn()) ++i; - } - - // Set temperature index - *i_temp = i; - - // Calculate cross sections for ith temperature - data_[i].calculate_xs(E, elastic, inelastic); -} - -bool -ThermalScattering::has_nuclide(const char* name) const -{ - std::string nuc {name}; - return std::find(nuclides_.begin(), nuclides_.end(), nuc) != nuclides_.end(); -} - -//============================================================================== -// ThermalData implementation -//============================================================================== - -ThermalData::ThermalData(hid_t group) -{ - // Coherent/incoherent elastic data - if (object_exists(group, "elastic")) { - // Read cross section data - hid_t elastic_group = open_group(group, "elastic"); - - // Read elastic cross section - elastic_.xs = read_function(elastic_group, "xs"); - - // Read angle-energy distribution - hid_t dgroup = open_group(elastic_group, "distribution"); - std::string temp; - read_attribute(dgroup, "type", temp); - if (temp == "coherent_elastic") { - auto xs = dynamic_cast(elastic_.xs.get()); - elastic_.distribution = std::make_unique(*xs); - } else { - if (temp == "incoherent_elastic") { - elastic_.distribution = std::make_unique(dgroup); - } else if (temp == "incoherent_elastic_discrete") { - auto xs = dynamic_cast(elastic_.xs.get()); - elastic_.distribution = std::make_unique( - dgroup, xs->x() - ); - } - } - - close_group(elastic_group); - } - - // Inelastic data - if (object_exists(group, "inelastic")) { - // Read type of inelastic data - hid_t inelastic_group = open_group(group, "inelastic"); - - // Read inelastic cross section - inelastic_.xs = read_function(inelastic_group, "xs"); - - // Read angle-energy distribution - hid_t dgroup = open_group(inelastic_group, "distribution"); - std::string temp; - read_attribute(dgroup, "type", temp); - if (temp == "incoherent_inelastic") { - inelastic_.distribution = std::make_unique(dgroup); - } else if (temp == "incoherent_inelastic_discrete") { - auto xs = dynamic_cast(inelastic_.xs.get()); - inelastic_.distribution = std::make_unique( - dgroup, xs->x() - ); - } - - close_group(inelastic_group); - } -} - -void -ThermalData::calculate_xs(double E, double* elastic, double* inelastic) const -{ - // Calculate thermal elastic scattering cross section - if (elastic_.xs) { - *elastic = (*elastic_.xs)(E); - } else { - *elastic = 0.0; - } - - // Calculate thermal inelastic scattering cross section - *inelastic = (*inelastic_.xs)(E); -} - -void -ThermalData::sample(const NuclideMicroXS& micro_xs, double E, - double* E_out, double* mu) -{ - // Determine whether inelastic or elastic scattering will occur - if (prn() < micro_xs.thermal_elastic / micro_xs.thermal) { - elastic_.distribution->sample(E, *E_out, *mu); - } else { - inelastic_.distribution->sample(E, *E_out, *mu); - } - - // Because of floating-point roundoff, it may be possible for mu to be - // outside of the range [-1,1). In these cases, we just set mu to exactly - // -1 or 1 - if (std::abs(*mu) > 1.0) *mu = std::copysign(1.0, *mu); -} - -void free_memory_thermal() -{ - data::thermal_scatt.clear(); - data::thermal_scatt_map.clear(); -} - -} // namespace openmc diff --git a/src/timer.cpp b/src/timer.cpp deleted file mode 100644 index 2303c6090..000000000 --- a/src/timer.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "openmc/timer.h" - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace simulation { - -Timer time_active; -Timer time_bank; -Timer time_bank_sample; -Timer time_bank_sendrecv; -Timer time_finalize; -Timer time_inactive; -Timer time_initialize; -Timer time_read_xs; -Timer time_tallies; -Timer time_total; -Timer time_transport; - -} // namespace simulation - -//============================================================================== -// Timer implementation -//============================================================================== - -void Timer::start () -{ - running_ = true; - start_ = clock::now(); -} - -void Timer::stop() -{ - elapsed_ = elapsed(); - running_ = false; -} - -void Timer::reset() -{ - running_ = false; - elapsed_ = 0.0; -} - -double Timer::elapsed() -{ - if (running_) { - std::chrono::duration diff = clock::now() - start_; - return elapsed_ + diff.count(); - } else { - return elapsed_; - } -} - -//============================================================================== -// Non-member functions -//============================================================================== - -void reset_timers() -{ - simulation::time_active.reset(); - simulation::time_bank.reset(); - simulation::time_bank_sample.reset(); - simulation::time_bank_sendrecv.reset(); - simulation::time_finalize.reset(); - simulation::time_inactive.reset(); - simulation::time_initialize.reset(); - simulation::time_read_xs.reset(); - simulation::time_tallies.reset(); - simulation::time_total.reset(); - simulation::time_transport.reset(); -} - -} // namespace openmc diff --git a/src/track_output.cpp b/src/track_output.cpp deleted file mode 100644 index 50d6d1ef6..000000000 --- a/src/track_output.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "openmc/track_output.h" - -#include "openmc/constants.h" -#include "openmc/hdf5_interface.h" -#include "openmc/position.h" -#include "openmc/settings.h" -#include "openmc/simulation.h" - -#include "xtensor/xtensor.hpp" - -#include // for size_t -#include -#include -#include - -// Explicit vector template specialization of threadprivate variable outside of -// the openmc namespace for the picky Intel compiler. -template class std::vector>; - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -// Forward declaration needed in order to declare tracks as threadprivate -extern std::vector> tracks; -#pragma omp threadprivate(tracks) - -std::vector> tracks; - -//============================================================================== -// Non-member functions -//============================================================================== - -void add_particle_track() -{ - tracks.emplace_back(); -} - -void write_particle_track(const Particle& p) -{ - tracks.back().push_back(p.r()); -} - -void finalize_particle_track(const Particle& p) -{ - std::stringstream filename; - filename << settings::path_output << "track_" << simulation::current_batch - << '_' << simulation::current_gen << '_' << p.id_ << ".h5"; - - // Determine number of coordinates for each particle - std::vector n_coords; - for (auto& coords : tracks) { - n_coords.push_back(coords.size()); - } - - #pragma omp critical (FinalizeParticleTrack) - { - hid_t file_id = file_open(filename.str().c_str(), 'w'); - write_attribute(file_id, "filetype", "track"); - write_attribute(file_id, "version", VERSION_TRACK); - write_attribute(file_id, "n_particles", tracks.size()); - write_attribute(file_id, "n_coords", n_coords); - for (int i = 1; i <= tracks.size(); ++i) { - const auto& t {tracks[i-1]}; - size_t n = t.size(); - xt::xtensor data({n,3}); - for (int j = 0; j < n; ++j) { - data(j, 0) = t[j].x; - data(j, 1) = t[j].y; - data(j, 2) = t[j].z; - } - std::string name = "coordinates_" + std::to_string(i); - write_dataset(file_id, name.c_str(), data); - } - file_close(file_id); - } - - // Clear particle tracks - tracks.clear(); -} - -} // namespace openmc diff --git a/src/urr.cpp b/src/urr.cpp deleted file mode 100644 index 28ad2505f..000000000 --- a/src/urr.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "openmc/urr.h" - -#include - -namespace openmc { - -UrrData::UrrData(hid_t group_id) -{ - // Read interpolation and other flags - int interp_temp; - read_attribute(group_id, "interpolation", interp_temp); - interp_ = static_cast(interp_temp); - - // read the metadata - read_attribute(group_id, "inelastic", inelastic_flag_); - read_attribute(group_id, "absorption", absorption_flag_); - int temp_multiply_smooth; - read_attribute(group_id, "multiply_smooth", temp_multiply_smooth); - multiply_smooth_ = (temp_multiply_smooth == 1); - - // read the energies at which tables exist - read_dataset(group_id, "energy", energy_); - - // Set n_energy_ - n_energy_ = energy_.shape()[0]; - - // Read URR tables - read_dataset(group_id, "table", prob_); -} - -} \ No newline at end of file diff --git a/src/volume_calc.cpp b/src/volume_calc.cpp deleted file mode 100644 index 6c1c48932..000000000 --- a/src/volume_calc.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include "openmc/volume_calc.h" - -#include "openmc/capi.h" -#include "openmc/cell.h" -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/geometry.h" -#include "openmc/hdf5_interface.h" -#include "openmc/material.h" -#include "openmc/message_passing.h" -#include "openmc/nuclide.h" -#include "openmc/output.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" -#include "openmc/timer.h" -#include "openmc/xml_interface.h" - -#ifdef _OPENMP -#include -#endif -#include "xtensor/xadapt.hpp" -#include "xtensor/xview.hpp" - -#include // for copy -#include // for pow, sqrt -#include -#include - -namespace openmc { - -//============================================================================== -// Global variables -//============================================================================== - -namespace model { - std::vector volume_calcs; -} - -//============================================================================== -// VolumeCalculation implementation -//============================================================================== - -VolumeCalculation::VolumeCalculation(pugi::xml_node node) -{ - // Read domain type (cell, material or universe) - std::string domain_type = get_node_value(node, "domain_type"); - if (domain_type == "cell") { - domain_type_ = FILTER_CELL; - } else if (domain_type == "material") { - domain_type_ = FILTER_MATERIAL; - } else if (domain_type == "universe") { - domain_type_ = FILTER_UNIVERSE; - } else { - fatal_error(std::string("Unrecognized domain type for stochastic " - "volume calculation: " + domain_type)); - } - - // Read domain IDs, bounding corodinates and number of samples - domain_ids_ = get_node_array(node, "domain_ids"); - lower_left_ = get_node_array(node, "lower_left"); - upper_right_ = get_node_array(node, "upper_right"); - n_samples_ = std::stoi(get_node_value(node, "samples")); - - // Ensure there are no duplicates by copying elements to a set and then - // comparing the length with the original vector - std::unordered_set unique_ids(domain_ids_.cbegin(), domain_ids_.cend()); - if (unique_ids.size() != domain_ids_.size()) { - throw std::runtime_error{"Domain IDs for a volume calculation " - "must be unique."}; - } - -} - -std::vector VolumeCalculation::execute() const -{ - // Shared data that is collected from all threads - int n = domain_ids_.size(); - std::vector> master_indices(n); // List of material indices for each domain - std::vector> master_hits(n); // Number of hits for each material in each domain - - // Divide work over MPI processes - int min_samples = n_samples_ / mpi::n_procs; - int remainder = n_samples_ % mpi::n_procs; - int i_start, i_end; - if (mpi::rank < remainder) { - i_start = (min_samples + 1)*mpi::rank; - i_end = i_start + min_samples + 1; - } else { - i_start = (min_samples + 1)*remainder + (mpi::rank - remainder)*min_samples; - i_end = i_start + min_samples; - } - - #pragma omp parallel - { - // Variables that are private to each thread - std::vector> indices(n); - std::vector> hits(n); - Particle p; - - prn_set_stream(STREAM_VOLUME); - - // Sample locations and count hits - #pragma omp for - for (int i = i_start; i < i_end; i++) { - set_particle_seed(i); - - p.n_coord_ = 1; - Position xi {prn(), prn(), prn()}; - p.r() = lower_left_ + xi*(upper_right_ - lower_left_); - p.u() = {0.5, 0.5, 0.5}; - - // If this location is not in the geometry at all, move on to next block - if (!find_cell(&p, false)) continue; - - if (domain_type_ == FILTER_MATERIAL) { - if (p.material_ != MATERIAL_VOID) { - for (int i_domain = 0; i_domain < n; i_domain++) { - if (model::materials[p.material_]->id_ == domain_ids_[i_domain]) { - this->check_hit(p.material_, indices[i_domain], hits[i_domain]); - break; - } - } - } - } else if (domain_type_ == FILTER_CELL) { - for (int level = 0; level < p.n_coord_; ++level) { - for (int i_domain=0; i_domain < n; i_domain++) { - if (model::cells[p.coord_[level].cell]->id_ == domain_ids_[i_domain]) { - this->check_hit(p.material_, indices[i_domain], hits[i_domain]); - break; - } - } - } - } else if (domain_type_ == FILTER_UNIVERSE) { - for (int level = 0; level < p.n_coord_; ++level) { - for (int i_domain = 0; i_domain < n; ++i_domain) { - if (model::universes[p.coord_[level].universe]->id_ == domain_ids_[i_domain]) { - check_hit(p.material_, indices[i_domain], hits[i_domain]); - break; - } - } - } - } - } - - // At this point, each thread has its own pair of index/hits lists and we now - // need to reduce them. OpenMP is not nearly smart enough to do this on its own, - // so we have to manually reduce them - -#ifdef _OPENMP - #pragma omp for ordered schedule(static) - for (int i = 0; i < omp_get_num_threads(); ++i) { - #pragma omp ordered - for (int i_domain = 0; i_domain < n; ++i_domain) { - for (int j = 0; j < indices[i_domain].size(); ++j) { - // Check if this material has been added to the master list and if so, - // accumulate the number of hits - bool already_added = false; - for (int k = 0; k < master_indices[i_domain].size(); k++) { - if (indices[i_domain][j] == master_indices[i_domain][k]) { - master_hits[i_domain][k] += hits[i_domain][j]; - already_added = true; - } - } - if (!already_added) { - // If we made it here, the material hasn't yet been added to the master - // list, so add entries to the master indices and master hits lists - master_indices[i_domain].push_back(indices[i_domain][j]); - master_hits[i_domain].push_back(hits[i_domain][j]); - } - } - } - } -#else - master_indices = indices; - master_hits = hits; -#endif - - prn_set_stream(STREAM_TRACKING); - } // omp parallel - - // Reduce hits onto master process - - // Determine volume of bounding box - Position d {upper_right_ - lower_left_}; - double volume_sample = d.x*d.y*d.z; - - // Set size for members of the Result struct - std::vector results(n); - - for (int i_domain = 0; i_domain < n; ++i_domain) { - // Get reference to result for this domain - auto& result {results[i_domain]}; - - // Create 2D array to store atoms/uncertainty for each nuclide. Later this - // is compressed into vectors storing only those nuclides that are non-zero - auto n_nuc = data::nuclides.size(); - xt::xtensor atoms({n_nuc, 2}, 0.0); - -#ifdef OPENMC_MPI - if (mpi::master) { - for (int j = 1; j < mpi::n_procs; j++) { - int q; - MPI_Recv(&q, 1, MPI_INTEGER, j, 0, mpi::intracomm, MPI_STATUS_IGNORE); - int buffer[2*q]; - MPI_Recv(&buffer[0], 2*q, MPI_INTEGER, j, 1, mpi::intracomm, MPI_STATUS_IGNORE); - for (int k = 0; k < q; ++k) { - for (int m = 0; m < master_indices[i_domain].size(); ++m) { - if (buffer[2*k] == master_indices[i_domain][m]) { - master_hits[i_domain][m] += buffer[2*k + 1]; - break; - } - } - } - } - } else { - int q = master_indices[i_domain].size(); - int buffer[2*q]; - for (int k = 0; k < q; ++k) { - buffer[2*k] = master_indices[i_domain][k]; - buffer[2*k + 1] = master_hits[i_domain][k]; - } - - MPI_Send(&q, 1, MPI_INTEGER, 0, 0, mpi::intracomm); - MPI_Send(&buffer[0], 2*q, MPI_INTEGER, 0, 1, mpi::intracomm); - } -#endif - - if (mpi::master) { - int total_hits = 0; - for (int j = 0; j < master_indices[i_domain].size(); ++j) { - total_hits += master_hits[i_domain][j]; - double f = static_cast(master_hits[i_domain][j]) / n_samples_; - double var_f = f*(1.0 - f)/n_samples_; - - int i_material = master_indices[i_domain][j]; - if (i_material == MATERIAL_VOID) continue; - - const auto& mat = model::materials[i_material]; - for (int k = 0; k < mat->nuclide_.size(); ++k) { - // Accumulate nuclide density - int i_nuclide = mat->nuclide_[k]; - atoms(i_nuclide, 0) += mat->atom_density_[k] * f; - atoms(i_nuclide, 1) += std::pow(mat->atom_density_[k], 2) * var_f; - } - } - - // Determine volume - result.volume[0] = static_cast(total_hits) / n_samples_ * volume_sample; - result.volume[1] = std::sqrt(result.volume[0] - * (volume_sample - result.volume[0]) / n_samples_); - - for (int j = 0; j < n_nuc; ++j) { - // Determine total number of atoms. At this point, we have values in - // atoms/b-cm. To get to atoms we multiply by 10^24 V. - double mean = 1.0e24 * volume_sample * atoms(j, 0); - double stdev = 1.0e24 * volume_sample * std::sqrt(atoms(j, 1)); - - // Convert full arrays to vectors - if (mean > 0.0) { - result.nuclides.push_back(j); - result.atoms.push_back(mean); - result.uncertainty.push_back(stdev); - } - } - } - } - - return results; -} - -void VolumeCalculation::to_hdf5(const std::string& filename, - const std::vector& results) const -{ - // Create HDF5 file - hid_t file_id = file_open(filename, 'w'); - - // Write header info - write_attribute(file_id, "filetype", "volume"); - write_attribute(file_id, "version", VERSION_VOLUME); - write_attribute(file_id, "openmc_version", VERSION); -#ifdef GIT_SHA1 - write_attribute(file_id, "git_sha1", GIT_SHA1); -#endif - - // Write current date and time - write_attribute(file_id, "date_and_time", time_stamp()); - - // Write basic metadata - write_attribute(file_id, "samples", n_samples_); - write_attribute(file_id, "lower_left", lower_left_); - write_attribute(file_id, "upper_right", upper_right_); - if (domain_type_ == FILTER_CELL) { - write_attribute(file_id, "domain_type", "cell"); - } - else if (domain_type_ == FILTER_MATERIAL) { - write_attribute(file_id, "domain_type", "material"); - } - else if (domain_type_ == FILTER_UNIVERSE) { - write_attribute(file_id, "domain_type", "universe"); - } - - for (int i = 0; i < domain_ids_.size(); ++i) - { - hid_t group_id = create_group(file_id, "domain_" - + std::to_string(domain_ids_[i])); - - // Write volume for domain - const auto& result {results[i]}; - write_dataset(group_id, "volume", result.volume); - - // Create array of nuclide names from the vector - auto n_nuc = result.nuclides.size(); - - std::vector nucnames; - for (int i_nuc : result.nuclides) { - nucnames.push_back(data::nuclides[i_nuc]->name_); - } - - // Create array of total # of atoms with uncertainty for each nuclide - xt::xtensor atom_data({n_nuc, 2}); - xt::view(atom_data, xt::all(), 0) = xt::adapt(result.atoms); - xt::view(atom_data, xt::all(), 1) = xt::adapt(result.uncertainty); - - // Write results - write_dataset(group_id, "nuclides", nucnames); - write_dataset(group_id, "atoms", atom_data); - - close_group(group_id); - } - - file_close(file_id); -} - -void VolumeCalculation::check_hit(int i_material, std::vector& indices, - std::vector& hits) const -{ - - // Check if this material was previously hit and if so, increment count - bool already_hit = false; - for (int j = 0; j < indices.size(); j++) { - if (indices[j] == i_material) { - hits[j]++; - already_hit = true; - } - } - - // If the material was not previously hit, append an entry to the material - // indices and hits lists - if (!already_hit) { - indices.push_back(i_material); - hits.push_back(1); - } -} - -void free_memory_volume() -{ - openmc::model::volume_calcs.clear(); -} - -} // namespace openmc - -//============================================================================== -// OPENMC_CALCULATE_VOLUMES runs each of the stochastic volume calculations -// that the user has specified and writes results to HDF5 files -//============================================================================== - -int openmc_calculate_volumes() { - using namespace openmc; - - if (mpi::master) { - header("STOCHASTIC VOLUME CALCULATION", 3); - } - Timer time_volume; - time_volume.start(); - - for (int i = 0; i < model::volume_calcs.size(); ++i) { - if (mpi::master) { - write_message("Running volume calculation " + std::to_string(i+1) + "...", 4); - } - - // Run volume calculation - const auto& vol_calc {model::volume_calcs[i]}; - auto results = vol_calc.execute(); - - if (mpi::master) { - std::string domain_type; - if (vol_calc.domain_type_ == FILTER_CELL) { - domain_type = " Cell "; - } else if (vol_calc.domain_type_ == FILTER_MATERIAL) { - domain_type = " Material "; - } else { - domain_type = " Universe "; - } - - // Display domain volumes - for (int j = 0; j < vol_calc.domain_ids_.size(); j++) { - std::stringstream msg; - msg << domain_type << vol_calc.domain_ids_[j] << ": " << - results[j].volume[0] << " +/- " << results[j].volume[1] << " cm^3"; - write_message(msg, 4); - } - - // Write volumes to HDF5 file - std::string filename = settings::path_output + "volume_" - + std::to_string(i+1) + ".h5"; - vol_calc.to_hdf5(filename, results); - } - - } - - // Show elapsed time - time_volume.stop(); - if (mpi::master) { - write_message("Elapsed time: " + std::to_string(time_volume.elapsed()) - + " s", 6); - } - - return 0; -} diff --git a/src/wmp.cpp b/src/wmp.cpp deleted file mode 100644 index f514b9e83..000000000 --- a/src/wmp.cpp +++ /dev/null @@ -1,243 +0,0 @@ -#include "openmc/wmp.h" - -#include "openmc/constants.h" -#include "openmc/cross_sections.h" -#include "openmc/hdf5_interface.h" -#include "openmc/math_functions.h" -#include "openmc/nuclide.h" - -#include -#include - -namespace openmc { - -//======================================================================== -// WindowedeMultipole implementation -//======================================================================== - -WindowedMultipole::WindowedMultipole(hid_t group) -{ - // Get name of nuclide from group, removing leading '/' - name_ = object_name(group).substr(1); - - // Read scalar values. - read_dataset(group, "spacing", spacing_); - read_dataset(group, "sqrtAWR", sqrt_awr_); - read_dataset(group, "E_min", E_min_); - read_dataset(group, "E_max", E_max_); - - // Read the "data" array. Use its shape to figure out the number of poles - // and residue types in this data. - read_dataset(group, "data", data_); - int n_residues = data_.shape()[1] - 1; - - // Check to see if this data includes fission residues. - fissionable_ = (n_residues == 3); - - // Read the "windows" array and use its shape to figure out the number of - // windows. - read_dataset(group, "windows", windows_); - int n_windows = windows_.shape()[0]; - - // Read the "broaden_poly" arrays. - read_dataset(group, "broaden_poly", broaden_poly_); - if (n_windows != broaden_poly_.shape()[0]) { - fatal_error("broaden_poly array shape is not consistent with the windows " - "array shape in WMP library for " + name_ + "."); - } - - // Read the "curvefit" array. - read_dataset(group, "curvefit", curvefit_); - if (n_windows != broaden_poly_.shape()[0]) { - fatal_error("curvefit array shape is not consistent with the windows " - "array shape in WMP library for " + name_ + "."); - } - fit_order_ = curvefit_.shape()[1] - 1; -} - -std::tuple -WindowedMultipole::evaluate(double E, double sqrtkT) -{ - using namespace std::complex_literals; - - // ========================================================================== - // Bookkeeping - - // Define some frequently used variables. - double sqrtE = std::sqrt(E); - double invE = 1.0 / E; - - // Locate window containing energy - int i_window = (sqrtE - std::sqrt(E_min_)) / spacing_; - int startw = windows_(i_window, 0) - 1; - int endw = windows_(i_window, 1) - 1; - - // Initialize the ouptut cross sections - double sig_s = 0.0; - double sig_a = 0.0; - double sig_f = 0.0; - - // ========================================================================== - // Add the contribution from the curvefit polynomial. - - if (sqrtkT > 0.0 && broaden_poly_(i_window)) { - // Broaden the curvefit. - double dopp = sqrt_awr_ / sqrtkT; - std::vector broadened_polynomials(fit_order_ + 1); - broaden_wmp_polynomials(E, dopp, fit_order_ + 1, broadened_polynomials.data()); - for (int i_poly = 0; i_poly < fit_order_ + 1; ++i_poly) { - sig_s += curvefit_(i_window, i_poly, FIT_S) * broadened_polynomials[i_poly]; - sig_a += curvefit_(i_window, i_poly, FIT_A) * broadened_polynomials[i_poly]; - if (fissionable_) { - sig_f += curvefit_(i_window, i_poly, FIT_F) * broadened_polynomials[i_poly]; - } - } - } else { - // Evaluate as if it were a polynomial - double temp = invE; - for (int i_poly = 0; i_poly < fit_order_ + 1; ++i_poly) { - sig_s += curvefit_(i_window, i_poly, FIT_S) * temp; - sig_a += curvefit_(i_window, i_poly, FIT_A) * temp; - if (fissionable_) { - sig_f += curvefit_(i_window, i_poly, FIT_F) * temp; - } - temp *= sqrtE; - } - } - - // ========================================================================== - // Add the contribution from the poles in this window. - - if (sqrtkT == 0.0) { - // If at 0K, use asymptotic form. - for (int i_pole = startw; i_pole <= endw; ++i_pole) { - std::complex psi_chi = -1.0i / (data_(i_pole, MP_EA) - sqrtE); - std::complex c_temp = psi_chi / E; - sig_s += (data_(i_pole, MP_RS) * c_temp).real(); - sig_a += (data_(i_pole, MP_RA) * c_temp).real(); - if (fissionable_) { - sig_f += (data_(i_pole, MP_RF) * c_temp).real(); - } - } - } else { - // At temperature, use Faddeeva function-based form. - double dopp = sqrt_awr_ / sqrtkT; - if (endw >= startw) { - for (int i_pole = startw; i_pole <= endw; ++i_pole) { - std::complex z = (sqrtE - data_(i_pole, MP_EA)) * dopp; - std::complex w_val = faddeeva(z) * dopp * invE * SQRT_PI; - sig_s += (data_(i_pole, MP_RS) * w_val).real(); - sig_a += (data_(i_pole, MP_RA) * w_val).real(); - if (fissionable_) { - sig_f += (data_(i_pole, MP_RF) * w_val).real(); - } - } - } - } - - return std::make_tuple(sig_s, sig_a, sig_f); -} - -std::tuple -WindowedMultipole::evaluate_deriv(double E, double sqrtkT) -{ - // ========================================================================== - // Bookkeeping - - // Define some frequently used variables. - double sqrtE = std::sqrt(E); - double invE = 1.0 / E; - double T = sqrtkT*sqrtkT / K_BOLTZMANN; - - if (sqrtkT == 0.0) { - fatal_error("Windowed multipole temperature derivatives are not implemented" - " for 0 Kelvin cross sections."); - } - - // Locate us - int i_window = (sqrtE - std::sqrt(E_min_)) / spacing_; - int startw = windows_(i_window, 0) - 1; - int endw = windows_(i_window, 1) - 1; - - // Initialize the ouptut cross sections. - double sig_s = 0.0; - double sig_a = 0.0; - double sig_f = 0.0; - - // TODO Polynomials: Some of the curvefit polynomials Doppler broaden so - // rigorously we should be computing the derivative of those. But in - // practice, those derivatives are only large at very low energy and they - // have no effect on reactor calculations. - - // ========================================================================== - // Add the contribution from the poles in this window. - - double dopp = sqrt_awr_ / sqrtkT; - if (endw >= startw) { - for (int i_pole = startw; i_pole <= endw; ++i_pole) { - std::complex z = (sqrtE - data_(i_pole, MP_EA)) * dopp; - std::complex w_val = -invE * SQRT_PI * 0.5 * w_derivative(z, 2); - sig_s += (data_(i_pole, MP_RS) * w_val).real(); - sig_a += (data_(i_pole, MP_RA) * w_val).real(); - if (fissionable_) { - sig_f += (data_(i_pole, MP_RF) * w_val).real(); - } - } - sig_s *= -0.5*sqrt_awr_ / std::sqrt(K_BOLTZMANN) * std::pow(T, -1.5); - sig_a *= -0.5*sqrt_awr_ / std::sqrt(K_BOLTZMANN) * std::pow(T, -1.5); - sig_f *= -0.5*sqrt_awr_ / std::sqrt(K_BOLTZMANN) * std::pow(T, -1.5); - } - - return std::make_tuple(sig_s, sig_a, sig_f); -} - -//======================================================================== -// Non-member functions -//======================================================================== - -void check_wmp_version(hid_t file) -{ - if (attribute_exists(file, "version")) { - std::array version; - read_attribute(file, "version", version); - if (version[0] != WMP_VERSION[0]) { - std::stringstream msg; - msg << "WMP data format uses version " << version[0] << "." << - version[1] << " whereas your installation of OpenMC expects version " - << WMP_VERSION[0] << ".x data."; - fatal_error(msg); - } - } else { - fatal_error("WMP data does not indicate a version. Your installation of " - "OpenMC expects version " + std::to_string(WMP_VERSION[0]) + ".x data."); - } -} - -void read_multipole_data(int i_nuclide) -{ - // Look for WMP data in cross_sections.xml - const auto& nuc {data::nuclides[i_nuclide]}; - auto it = data::library_map.find({Library::Type::wmp, nuc->name_}); - - // If no WMP library for this nuclide, just return - if (it == data::library_map.end()) return; - - // Check if WMP library exists - int idx = it->second; - std::string& filename = data::libraries[idx].path_; - - // Display message - write_message("Reading " + nuc->name_ + " WMP data from " + filename, 6); - - // Open file and make sure version is sufficient - hid_t file = file_open(filename, 'r'); - check_wmp_version(file); - - // Read nuclide data from HDF5 - hid_t group = open_group(file, nuc->name_.c_str()); - nuc->multipole_ = std::make_unique(group); - close_group(group); - file_close(file); -} - -} // namespace openmc diff --git a/src/xml_interface.cpp b/src/xml_interface.cpp deleted file mode 100644 index 60ae7ffca..000000000 --- a/src/xml_interface.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "openmc/xml_interface.h" - -#include // for transform -#include - -#include "openmc/error.h" - - -namespace openmc { - -std::string -get_node_value(pugi::xml_node node, const char* name, bool lowercase, - bool strip) -{ - // Search for either an attribute or child tag and get the data as a char*. - const pugi::char_t* value_char; - if (node.attribute(name)) { - value_char = node.attribute(name).value(); - } else if (node.child(name)) { - value_char = node.child_value(name); - } else { - std::stringstream err_msg; - err_msg << "Node \"" << name << "\" is not a member of the \"" - << node.name() << "\" XML node"; - fatal_error(err_msg); - } - std::string value {value_char}; - - // Convert to lower-case if needed - if (lowercase) { - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - } - - // Strip leading/trailing whitespace if needed - if (strip) { - value.erase(0, value.find_first_not_of(" \t\r\n")); - value.erase(value.find_last_not_of(" \t\r\n") + 1); - } - - return value; -} - -bool -get_node_value_bool(pugi::xml_node node, const char* name) -{ - if (node.attribute(name)) { - return node.attribute(name).as_bool(); - } else if (node.child(name)) { - return node.child(name).text().as_bool(); - } else { - std::stringstream err_msg; - err_msg << "Node \"" << name << "\" is not a member of the \"" - << node.name() << "\" XML node"; - fatal_error(err_msg); - } - return false; -} - -} // namespace openmc diff --git a/src/xsdata.cpp b/src/xsdata.cpp deleted file mode 100644 index cee36a938..000000000 --- a/src/xsdata.cpp +++ /dev/null @@ -1,575 +0,0 @@ -#include "openmc/xsdata.h" - -#include -#include -#include -#include - -#include "xtensor/xview.hpp" -#include "xtensor/xindex_view.hpp" -#include "xtensor/xmath.hpp" -#include "xtensor/xbuilder.hpp" - -#include "openmc/constants.h" -#include "openmc/error.h" -#include "openmc/math_functions.h" -#include "openmc/mgxs_interface.h" -#include "openmc/random_lcg.h" -#include "openmc/settings.h" - - -namespace openmc { - -//============================================================================== -// XsData class methods -//============================================================================== - -XsData::XsData(bool fissionable, int scatter_format, int n_pol, int n_azi) -{ - size_t n_ang = n_pol * n_azi; - size_t n_dg = data::num_delayed_groups; - size_t n_g = data::num_energy_groups; - - // check to make sure scatter format is OK before we allocate - if (scatter_format != ANGLE_HISTOGRAM && scatter_format != ANGLE_TABULAR && - scatter_format != ANGLE_LEGENDRE) { - fatal_error("Invalid scatter_format!"); - } - // allocate all [temperature][angle][in group] quantities - std::vector shape {n_ang, n_g}; - total = xt::zeros(shape); - absorption = xt::zeros(shape); - inverse_velocity = xt::zeros(shape); - if (fissionable) { - fission = xt::zeros(shape); - nu_fission = xt::zeros(shape); - prompt_nu_fission = xt::zeros(shape); - kappa_fission = xt::zeros(shape); - } - - // allocate decay_rate; [temperature][angle][delayed group] - shape[1] = n_dg; - decay_rate = xt::zeros(shape); - - if (fissionable) { - shape = {n_ang, n_dg, n_g}; - // allocate delayed_nu_fission; [temperature][angle][delay group][in group] - delayed_nu_fission = xt::zeros(shape); - - // chi_prompt; [temperature][angle][in group][out group] - shape = {n_ang, n_g, n_g}; - chi_prompt = xt::zeros(shape); - - // chi_delayed; [temperature][angle][delay group][in group][out group] - shape = {n_ang, n_dg, n_g, n_g}; - chi_delayed = xt::zeros(shape); - } - - - for (int a = 0; a < n_ang; a++) { - if (scatter_format == ANGLE_HISTOGRAM) { - scatter.emplace_back(new ScattDataHistogram); - } else if (scatter_format == ANGLE_TABULAR) { - scatter.emplace_back(new ScattDataTabular); - } else if (scatter_format == ANGLE_LEGENDRE) { - scatter.emplace_back(new ScattDataLegendre); - } - } -} - -//============================================================================== - -void -XsData::from_hdf5(hid_t xsdata_grp, bool fissionable, int scatter_format, - int final_scatter_format, int order_data, bool is_isotropic, int n_pol, int n_azi) -{ - // Reconstruct the dimension information so it doesn't need to be passed - size_t n_ang = n_pol * n_azi; - size_t energy_groups = total.shape()[1]; - - // Set the fissionable-specific data - if (fissionable) { - fission_from_hdf5(xsdata_grp, n_ang, is_isotropic); - } - // Get the non-fission-specific data - read_nd_vector(xsdata_grp, "decay rate", decay_rate); - read_nd_vector(xsdata_grp, "absorption", absorption, true); - read_nd_vector(xsdata_grp, "inverse-velocity", inverse_velocity); - - // Get scattering data - scatter_from_hdf5(xsdata_grp, n_ang, scatter_format, - final_scatter_format, order_data); - - // Check absorption to ensure it is not 0 since it is often the - // denominator in tally methods - xt::filtration(absorption, xt::equal(absorption, 0.)) = 1.e-10; - - // Get or calculate the total x/s - if (object_exists(xsdata_grp, "total")) { - read_nd_vector(xsdata_grp, "total", total); - } else { - for (size_t a = 0; a < n_ang; a++) { - for (size_t gin = 0; gin < energy_groups; gin++) { - total(a, gin) = absorption(a, gin) + scatter[a]->scattxs[gin]; - } - } - } - - // Fix if total is 0, since it is in the denominator when tallying - xt::filtration(total, xt::equal(total, 0.)) = 1.e-10; -} - -//============================================================================== - -void -XsData::fission_vector_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, - bool is_isotropic) -{ - // Data is provided as nu-fission and chi with a beta for delayed info - - size_t n_g = data::num_energy_groups; - size_t n_dg = data::num_delayed_groups; - - // Get chi - xt::xtensor temp_chi({n_ang, n_g}, 0.); - read_nd_vector(xsdata_grp, "chi", temp_chi, true); - - // Normalize chi by summing over the outgoing groups for each incoming angle - temp_chi /= xt::view(xt::sum(temp_chi, {1}), xt::all(), xt::newaxis()); - - // Now every incoming group in prompt_chi and delayed_chi is the normalized - // chi we just made - chi_prompt = xt::view(temp_chi, xt::all(), xt::newaxis(), xt::all()); - chi_delayed = xt::view(temp_chi, xt::all(), xt::newaxis(), xt::newaxis(), - xt::all()); - - // Get nu-fission - xt::xtensor temp_nufiss({n_ang, n_g}, 0.); - read_nd_vector(xsdata_grp, "nu-fission", temp_nufiss, true); - - // Get beta (strategy will depend upon the number of dimensions in beta) - hid_t beta_dset = open_dataset(xsdata_grp, "beta"); - int beta_ndims = dataset_ndims(beta_dset); - close_dataset(beta_dset); - int ndim_target = 1; - if (!is_isotropic) ndim_target += 2; - if (beta_ndims == ndim_target) { - xt::xtensor temp_beta({n_ang, n_dg}, 0.); - read_nd_vector(xsdata_grp, "beta", temp_beta, true); - - // Set prompt_nu_fission = (1. - beta_total)*nu_fission - prompt_nu_fission = temp_nufiss * (1. - xt::sum(temp_beta, {1})); - - // Set delayed_nu_fission as beta * nu_fission - delayed_nu_fission = - xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis()) * - xt::view(temp_nufiss, xt::all(), xt::newaxis(), xt::all()); - } else if (beta_ndims == ndim_target + 1) { - xt::xtensor temp_beta({n_ang, n_dg, n_g}, 0.); - read_nd_vector(xsdata_grp, "beta", temp_beta, true); - - // Set prompt_nu_fission = (1. - beta_total)*nu_fission - prompt_nu_fission = temp_nufiss * (1. - xt::sum(temp_beta, {1})); - - // Set delayed_nu_fission as beta * nu_fission - delayed_nu_fission = temp_beta * - xt::view(temp_nufiss, xt::all(), xt::newaxis(), xt::all()); - } -} - -void -XsData::fission_vector_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang) -{ - // Data is provided separately as prompt + delayed nu-fission and chi - - size_t n_g = data::num_energy_groups; - size_t n_dg = data::num_delayed_groups; - - // Get chi-prompt - xt::xtensor temp_chi_p({n_ang, n_g}, 0.); - read_nd_vector(xsdata_grp, "chi-prompt", temp_chi_p, true); - - // Normalize chi by summing over the outgoing groups for each incoming angle - temp_chi_p /= xt::view(xt::sum(temp_chi_p, {1}), xt::all(), xt::newaxis()); - - // Get chi-delayed - xt::xtensor temp_chi_d({n_ang, n_dg, n_g}, 0.); - read_nd_vector(xsdata_grp, "chi-delayed", temp_chi_d, true); - - // Normalize chi by summing over the outgoing groups for each incoming angle - temp_chi_d /= xt::view(xt::sum(temp_chi_d, {2}), - xt::all(), xt::all(), xt::newaxis()); - - // Now assign the prompt and delayed chis by replicating for each incoming group - chi_prompt = xt::view(temp_chi_p, xt::all(), xt::newaxis(), xt::all()); - chi_delayed = xt::view(temp_chi_d, xt::all(), xt::all(), xt::newaxis(), - xt::all()); - - // Get prompt and delayed nu-fission directly - read_nd_vector(xsdata_grp, "prompt-nu-fission", prompt_nu_fission, - true); - read_nd_vector(xsdata_grp, "delayed-nu-fission", - delayed_nu_fission, true); -} - -void -XsData::fission_vector_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang) -{ - // No beta is provided and there is no prompt/delay distinction. - // Therefore, the code only considers the data as prompt. - - size_t n_g = data::num_energy_groups; - - // Get chi - xt::xtensor temp_chi({n_ang, n_g}, 0.); - read_nd_vector(xsdata_grp, "chi", temp_chi, true); - - // Normalize chi by summing over the outgoing groups for each incoming angle - temp_chi /= xt::view(xt::sum(temp_chi, {1}), xt::all(), xt::newaxis()); - - // Now every incoming group in self.chi is the normalized chi we just made - chi_prompt = xt::view(temp_chi, xt::all(), xt::newaxis(), xt::all()); - - // Get nu-fission directly - read_nd_vector(xsdata_grp, "nu-fission", prompt_nu_fission, true); -} - -//============================================================================== - -void -XsData::fission_matrix_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic) -{ - // Data is provided as nu-fission and chi with a beta for delayed info - - size_t n_g = data::num_energy_groups; - size_t n_dg = data::num_delayed_groups; - - // Get nu-fission matrix - xt::xtensor temp_matrix({n_ang, n_g, n_g}, 0.); - read_nd_vector(xsdata_grp, "nu-fission", temp_matrix, true); - - // Get beta (strategy will depend upon the number of dimensions in beta) - hid_t beta_dset = open_dataset(xsdata_grp, "beta"); - int beta_ndims = dataset_ndims(beta_dset); - close_dataset(beta_dset); - int ndim_target = 1; - if (!is_isotropic) ndim_target += 2; - if (beta_ndims == ndim_target) { - xt::xtensor temp_beta({n_ang, n_dg}, 0.); - read_nd_vector(xsdata_grp, "beta", temp_beta, true); - - xt::xtensor temp_beta_sum({n_ang}, 0.); - temp_beta_sum = xt::sum(temp_beta, {1}); - - // prompt_nu_fission is the sum of this matrix over outgoing groups and - // multiplied by (1 - beta_sum) - prompt_nu_fission = xt::sum(temp_matrix, {2}) * (1. - temp_beta_sum); - - // Store chi-prompt - chi_prompt = xt::view(1.0 - temp_beta_sum, xt::all(), xt::newaxis(), - xt::newaxis()) * temp_matrix; - - // delayed_nu_fission is the sum of this matrix over outgoing groups and - // multiplied by beta - delayed_nu_fission = - xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis()) * - xt::view(xt::sum(temp_matrix, {2}), xt::all(), xt::newaxis(), xt::all()); - - // Store chi-delayed - chi_delayed = - xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis(), xt::newaxis()) * - xt::view(temp_matrix, xt::all(), xt::newaxis(), xt::all(), xt::all()); - - } else if (beta_ndims == ndim_target + 1) { - xt::xtensor temp_beta({n_ang, n_dg, n_g}, 0.); - read_nd_vector(xsdata_grp, "beta", temp_beta, true); - - xt::xtensor temp_beta_sum({n_ang, n_g}, 0.); - temp_beta_sum = xt::sum(temp_beta, {1}); - - // prompt_nu_fission is the sum of this matrix over outgoing groups and - // multiplied by (1 - beta_sum) - prompt_nu_fission = xt::sum(temp_matrix, {2}) * (1. - temp_beta_sum); - - // Store chi-prompt - chi_prompt = xt::view(1.0 - temp_beta_sum, xt::all(), xt::all(), - xt::newaxis()) * temp_matrix; - - // delayed_nu_fission is the sum of this matrix over outgoing groups and - // multiplied by beta - delayed_nu_fission = temp_beta * - xt::view(xt::sum(temp_matrix, {2}), xt::all(), xt::newaxis(), xt::all()); - - // Store chi-delayed - chi_delayed = - xt::view(temp_beta, xt::all(), xt::all(), xt::all(), xt::newaxis()) * - xt::view(temp_matrix, xt::all(), xt::newaxis(), xt::all(), xt::all()); - } - - //Normalize both chis - chi_prompt /= xt::view(xt::sum(chi_prompt, {2}), - xt::all(), xt::all(), xt::newaxis()); - - chi_delayed /= xt::view(xt::sum(chi_delayed, {3}), - xt::all(), xt::all(), xt::all(), xt::newaxis()); -} - -void -XsData::fission_matrix_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang) -{ - // Data is provided separately as prompt + delayed nu-fission and chi - - size_t n_g = data::num_energy_groups; - size_t n_dg = data::num_delayed_groups; - - // Get the prompt nu-fission matrix - xt::xtensor temp_matrix_p({n_ang, n_g, n_g}, 0.); - read_nd_vector(xsdata_grp, "prompt-nu-fission", temp_matrix_p, true); - - // prompt_nu_fission is the sum over outgoing groups - prompt_nu_fission = xt::sum(temp_matrix_p, {2}); - - // chi_prompt is this matrix but normalized over outgoing groups, which we - // have already stored in prompt_nu_fission - chi_prompt = temp_matrix_p / - xt::view(prompt_nu_fission, xt::all(), xt::all(), xt::newaxis()); - - // Get the delayed nu-fission matrix - xt::xtensor temp_matrix_d({n_ang, n_dg, n_g, n_g}, 0.); - read_nd_vector(xsdata_grp, "delayed-nu-fission", temp_matrix_d, true); - - // delayed_nu_fission is the sum over outgoing groups - delayed_nu_fission = xt::sum(temp_matrix_d, {3}); - - // chi_prompt is this matrix but normalized over outgoing groups, which we - // have already stored in prompt_nu_fission - chi_delayed = temp_matrix_d / - xt::view(delayed_nu_fission, xt::all(), xt::all(), xt::all(), xt::newaxis()); -} - -void -XsData::fission_matrix_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang) -{ - // No beta is provided and there is no prompt/delay distinction. - // Therefore, the code only considers the data as prompt. - - size_t n_g = data::num_energy_groups; - - // Get nu-fission matrix - xt::xtensor temp_matrix({n_ang, n_g, n_g}, 0.); - read_nd_vector(xsdata_grp, "nu-fission", temp_matrix, true); - - // prompt_nu_fission is the sum over outgoing groups - prompt_nu_fission = xt::sum(temp_matrix, {2}); - - // chi_prompt is this matrix but normalized over outgoing groups, which we - // have already stored in prompt_nu_fission - chi_prompt = temp_matrix / xt::view(prompt_nu_fission, xt::all(), xt::all(), - xt::newaxis()); -} - -//============================================================================== - -void -XsData::fission_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic) -{ - // Get the fission and kappa_fission data xs; these are optional - read_nd_vector(xsdata_grp, "fission", fission); - read_nd_vector(xsdata_grp, "kappa-fission", kappa_fission); - - // Get the data; the strategy for doing so depends on if the data is provided - // as a nu-fission matrix or a set of chi and nu-fission vectors - if (object_exists(xsdata_grp, "chi") || - object_exists(xsdata_grp, "chi-prompt")) { - if (data::num_delayed_groups == 0) { - fission_vector_no_delayed_from_hdf5(xsdata_grp, n_ang); - } else { - if (object_exists(xsdata_grp, "beta")) { - fission_vector_beta_from_hdf5(xsdata_grp, n_ang, is_isotropic); - } else { - fission_vector_no_beta_from_hdf5(xsdata_grp, n_ang); - } - } - } else { - if (data::num_delayed_groups == 0) { - fission_matrix_no_delayed_from_hdf5(xsdata_grp, n_ang); - } else { - if (object_exists(xsdata_grp, "beta")) { - fission_matrix_beta_from_hdf5(xsdata_grp, n_ang, is_isotropic); - } else { - fission_matrix_no_beta_from_hdf5(xsdata_grp, n_ang); - } - } - } - - // Combine prompt_nu_fission and delayed_nu_fission into nu_fission - if (data::num_delayed_groups == 0) { - nu_fission = prompt_nu_fission; - } else { - nu_fission = prompt_nu_fission + xt::sum(delayed_nu_fission, {1}); - } -} - -//============================================================================== - -void -XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang, - int scatter_format, int final_scatter_format, int order_data) -{ - if (!object_exists(xsdata_grp, "scatter_data")) { - fatal_error("Must provide scatter_data group!"); - } - hid_t scatt_grp = open_group(xsdata_grp, "scatter_data"); - - // Get the outgoing group boundary indices - size_t n_g = data::num_energy_groups; - xt::xtensor gmin({n_ang, n_g}, 0.); - read_nd_vector(scatt_grp, "g_min", gmin, true); - xt::xtensor gmax({n_ang, n_g}, 0.); - read_nd_vector(scatt_grp, "g_max", gmax, true); - - // Make gmin and gmax start from 0 vice 1 as they do in the library - gmin -= 1; - gmax -= 1; - - // Now use this info to find the length of a vector to hold the flattened - // data. - size_t length = order_data * xt::sum(gmax - gmin + 1)(); - - double_4dvec input_scatt(n_ang, double_3dvec(n_g)); - xt::xtensor temp_arr({length}, 0.); - read_nd_vector(scatt_grp, "scatter_matrix", temp_arr, true); - - // Compare the number of orders given with the max order of the problem; - // strip off the superfluous orders if needed - int order_dim; - if (scatter_format == ANGLE_LEGENDRE) { - order_dim = std::min(order_data - 1, settings::max_order) + 1; - } else { - order_dim = order_data; - } - - // convert the flattened temp_arr to a jagged array for passing to - // scatt data - size_t temp_idx = 0; - for (size_t a = 0; a < n_ang; a++) { - for (size_t gin = 0; gin < n_g; gin++) { - input_scatt[a][gin].resize(gmax(a, gin) - gmin(a, gin) + 1); - for (size_t i_gout = 0; i_gout < input_scatt[a][gin].size(); i_gout++) { - input_scatt[a][gin][i_gout].resize(order_dim); - for (size_t l = 0; l < order_dim; l++) { - input_scatt[a][gin][i_gout][l] = temp_arr[temp_idx++]; - } - // Adjust index for the orders we didnt take - temp_idx += (order_data - order_dim); - } - } - } - - // Get multiplication matrix - double_3dvec temp_mult(n_ang, double_2dvec(n_g)); - if (object_exists(scatt_grp, "multiplicity_matrix")) { - temp_arr.resize({length / order_data}); - read_nd_vector(scatt_grp, "multiplicity_matrix", temp_arr); - - // convert the flat temp_arr to a jagged array for passing to scatt data - size_t temp_idx = 0; - for (size_t a = 0; a < n_ang; a++) { - for (size_t gin = 0; gin < n_g; gin++) { - temp_mult[a][gin].resize(gmax(a, gin) - gmin(a, gin) + 1); - for (size_t i_gout = 0; i_gout < temp_mult[a][gin].size(); i_gout++) { - temp_mult[a][gin][i_gout] = temp_arr[temp_idx++]; - } - } - } - } else { - // Use a default: multiplicities are 1.0. - for (size_t a = 0; a < n_ang; a++) { - for (size_t gin = 0; gin < n_g; gin++) { - temp_mult[a][gin].resize(gmax(a, gin) - gmin(a, gin) + 1); - for (size_t i_gout = 0; i_gout < temp_mult[a][gin].size(); i_gout++) { - temp_mult[a][gin][i_gout] = 1.; - } - } - } - } - close_group(scatt_grp); - - // Finally, convert the Legendre data to tabular, if needed - if (scatter_format == ANGLE_LEGENDRE && - final_scatter_format == ANGLE_TABULAR) { - for (size_t a = 0; a < n_ang; a++) { - ScattDataLegendre legendre_scatt; - xt::xtensor in_gmin = xt::view(gmin, a, xt::all()); - xt::xtensor in_gmax = xt::view(gmax, a, xt::all()); - - legendre_scatt.init(in_gmin, in_gmax, - temp_mult[a], input_scatt[a]); - - // Now create a tabular version of legendre_scatt - convert_legendre_to_tabular(legendre_scatt, - *static_cast(scatter[a].get())); - - scatter_format = final_scatter_format; - } - } else { - // We are sticking with the current representation - // Initialize the ScattData object with this data - for (size_t a = 0; a < n_ang; a++) { - xt::xtensor in_gmin = xt::view(gmin, a, xt::all()); - xt::xtensor in_gmax = xt::view(gmax, a, xt::all()); - scatter[a]->init(in_gmin, in_gmax, temp_mult[a], input_scatt[a]); - } - } -} - -//============================================================================== - -void -XsData::combine(const std::vector& those_xs, - const std::vector& scalars) -{ - // Combine the non-scattering data - for (size_t i = 0; i < those_xs.size(); i++) { - XsData* that = those_xs[i]; - if (!equiv(*that)) fatal_error("Cannot combine the XsData objects!"); - double scalar = scalars[i]; - total += scalar * that->total; - absorption += scalar * that->absorption; - if (i == 0) { - inverse_velocity = that->inverse_velocity; - } - if (that->prompt_nu_fission.shape()[0] > 0) { - nu_fission += scalar * that->nu_fission; - prompt_nu_fission += scalar * that->prompt_nu_fission; - kappa_fission += scalar * that->kappa_fission; - fission += scalar * that->fission; - delayed_nu_fission += scalar * that->delayed_nu_fission; - chi_prompt += scalar * that->chi_prompt; - chi_delayed += scalar * that->chi_delayed; - } - decay_rate += scalar * that->decay_rate; - } - - // Allow the ScattData object to combine itself - for (size_t a = 0; a < total.shape()[0]; a++) { - // Build vector of the scattering objects to incorporate - std::vector those_scatts(those_xs.size()); - for (size_t i = 0; i < those_xs.size(); i++) { - those_scatts[i] = those_xs[i]->scatter[a].get(); - } - - // Now combine these guys - scatter[a]->combine(those_scatts, scalars); - } -} - -//============================================================================== - -bool -XsData::equiv(const XsData& that) -{ - return (absorption.shape() == that.absorption.shape()); -} - -} //namespace openmc diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index 5c21cd938..000000000 --- a/tests/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from contextlib import contextmanager -import os -import tempfile - - -@contextmanager -def cdtemp(): - """Context manager to change to/return from a tmpdir.""" - with tempfile.TemporaryDirectory() as tmpdir: - cwd = os.getcwd() - try: - os.chdir(tmpdir) - yield - finally: - os.chdir(cwd) diff --git a/tests/chain_simple.xml b/tests/chain_simple.xml deleted file mode 100644 index c2e50a370..000000000 --- a/tests/chain_simple.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 1.093250e-04 2.087260e-04 2.780820e-02 6.759540e-03 2.392300e-02 4.356330e-05 - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 6.142710e-5 1.483250e-04 0.0292737 0.002566345 0.0219242 4.9097e-6 - - - - - - - 2.53000e-02 - - Gd157 Gd156 I135 Xe135 Xe136 Cs135 - 4.141120e-04 7.605360e-04 0.0135457 0.00026864 0.0024432 3.7100E-07 - - - - diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index dc55e8e1e..000000000 --- a/tests/conftest.py +++ /dev/null @@ -1,28 +0,0 @@ -import pytest - -from tests.regression_tests import config as regression_config - - -def pytest_addoption(parser): - parser.addoption('--exe') - parser.addoption('--mpi', action='store_true') - parser.addoption('--mpiexec') - parser.addoption('--mpi-np') - parser.addoption('--update', action='store_true') - parser.addoption('--build-inputs', action='store_true') - - -def pytest_configure(config): - opts = ['exe', 'mpi', 'mpiexec', 'mpi_np', 'update', 'build_inputs'] - for opt in opts: - if config.getoption(opt) is not None: - regression_config[opt] = config.getoption(opt) - - -@pytest.fixture -def run_in_tmpdir(tmpdir): - orig = tmpdir.chdir() - try: - yield - finally: - orig.chdir() diff --git a/tests/dummy_operator.py b/tests/dummy_operator.py deleted file mode 100644 index 35a526c30..000000000 --- a/tests/dummy_operator.py +++ /dev/null @@ -1,243 +0,0 @@ -from collections import namedtuple - -import numpy as np -import scipy.sparse as sp -from uncertainties import ufloat - -from openmc.deplete.reaction_rates import ReactionRates -from openmc.deplete.abc import TransportOperator, OperatorResult -from openmc.deplete import ( - CECMIntegrator, PredictorIntegrator, CELIIntegrator, LEQIIntegrator, - EPCRK4Integrator, CF4Integrator, SICELIIntegrator, SILEQIIntegrator -) - -# Bundle for nicely passing test data to depletion unit tests -# solver should be a concrete subclass of openmc.deplete.abc.Integrator -# atoms_1 should be the number of atoms of type 1 through the simulation -# similar for atoms_2, but for type 2. This includes the first step -# Solutions should be the exact solution that can be obtained using -# the DummyOperator depletion matrix with two 0.75 second time steps -DepletionSolutionTuple = namedtuple( - "DepletionSolutionTuple", "solver atoms_1 atoms_2") - - -predictor_solution = DepletionSolutionTuple( - PredictorIntegrator, np.array([1.0, 2.46847546272295, 4.11525874568034]), - np.array([1.0, 0.986431226850467, -0.0581692232513460])) - - -cecm_solution = DepletionSolutionTuple( - CECMIntegrator, np.array([1.0, 1.86872629872102, 2.18097439443550]), - np.array([1.0, 1.395525772416039, 2.69429754646747])) - - -cf4_solution = DepletionSolutionTuple( - CF4Integrator, np.array([1.0, 2.06101629, 2.57241318]), - np.array([1.0, 1.37783588, 2.63731630])) - - -epc_rk4_solution = DepletionSolutionTuple( - EPCRK4Integrator, np.array([1.0, 2.01978516, 2.05246421]), - np.array([1.0, 1.42038037, 3.06177191])) - - -celi_solution = DepletionSolutionTuple( - CELIIntegrator, np.array([1.0, 1.82078767, 2.68441779]), - np.array([1.0, 0.97122898, 0.05125966])) - - -si_celi_solution = DepletionSolutionTuple( - SICELIIntegrator, np.array([1.0, 2.03325094, 2.69291933]), - np.array([1.0, 1.16826254, 0.37907772])) - - -leqi_solution = DepletionSolutionTuple( - LEQIIntegrator, np.array([1.0, 1.82078767, 2.74526197]), - np.array([1.0, 0.97122898, 0.23339915])) - - -si_leqi_solution = DepletionSolutionTuple( - SILEQIIntegrator, np.array([1.0, 2.03325094, 2.92711288]), - np.array([1.0, 1.16826254, 0.53753236])) - - -SCHEMES = { - "predictor": predictor_solution, - "cecm": cecm_solution, - "celi": celi_solution, - "cf4": cf4_solution, - "epc_rk4": epc_rk4_solution, - "leqi": leqi_solution, - "si_leqi": si_leqi_solution, - "si_celi": si_celi_solution, -} - - -class TestChain(object): - """Empty chain to assist with unit testing depletion routines - - Only really provides the form_matrix function, but acts like - a real Chain - """ - - fission_yields = [None] - - @staticmethod - def get_default_fission_yields(): - return None - - def form_matrix(self, rates, _fission_yields=None): - """Forms the f(y) matrix in y' = f(y)y. - - Nominally a depletion matrix, this is abstracted on the off chance - that the function f has nothing to do with depletion at all. - - Parameters - ---------- - rates : numpy.ndarray - Slice of reaction rates for a single material - _fission_yields : optional - Not used - - Returns - ------- - scipy.sparse.csr_matrix - Sparse matrix representing f(y). - """ - - y_1 = rates[0, 0] - y_2 = rates[1, 0] - - a11 = np.sin(y_2) - a12 = np.cos(y_1) - a21 = -np.cos(y_2) - a22 = np.sin(y_1) - - return sp.csr_matrix(np.array([[a11, a12], [a21, a22]])) - - -class DummyOperator(TransportOperator): - """This is a dummy operator class with no statistical uncertainty. - - y_1' = sin(y_2) y_1 + cos(y_1) y_2 - y_2' = -cos(y_2) y_1 + sin(y_1) y_2 - - y_1(0) = 1 - y_2(0) = 1 - - y_1(1.5) ~ 2.3197067076743316 - y_2(1.5) ~ 3.1726475740397628 - - """ - def __init__(self, previous_results=None): - self.prev_res = previous_results - self.chain = TestChain() - self.output_dir = "." - - def __call__(self, vec, power, print_out=False): - """Evaluates F(y) - - Parameters - ---------- - vec : list of numpy.array - Total atoms to be used in function. - power : float - Power in [W] - print_out : bool, optional, ignored - Whether or not to print out time. - - Returns - ------- - openmc.deplete.OperatorResult - Result of transport operator - - """ - mats = ["1"] - nuclides = ["1", "2"] - reactions = ["1"] - - reaction_rates = ReactionRates(mats, nuclides, reactions) - - reaction_rates[0, 0, 0] = vec[0][0] - reaction_rates[0, 1, 0] = vec[0][1] - - # Create a fake rates object - return OperatorResult(ufloat(0.0, 0.0), reaction_rates) - - @property - def volume(self): - """ - volume : dict of str float - Volumes of material - """ - - return {"1": 0.0} - - @property - def nuc_list(self): - """ - nuc_list : list of str - A list of all nuclide names. Used for sorting the simulation. - """ - - return ["1", "2"] - - @property - def local_mats(self): - """ - local_mats : list of str - A list of all material IDs to be burned. Used for sorting the - simulation. - """ - - return ["1"] - - @property - def burnable_mats(self): - """Maps cell name to index in global geometry.""" - return self.local_mats - - @staticmethod - def write_bos_data(_step): - """Empty method but avoids calls to C API""" - - @property - def reaction_rates(self): - """ - reaction_rates : ReactionRates - Reaction rates from the last operator step. - """ - mats = ["1"] - nuclides = ["1", "2"] - reactions = ["1"] - - return ReactionRates(mats, nuclides, reactions) - - def initial_condition(self): - """Returns initial vector. - - Returns - ------- - list of numpy.array - Total density for initial conditions. - """ - - return [np.array((1.0, 1.0))] - - def get_results_info(self): - """Returns volume list, cell 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 cell IDs to be burned. Used for sorting the - simulation. - full_burn_list : OrderedDict of str to int - Maps cell name to index in global geometry. - - """ - return self.volume, self.nuc_list, self.local_mats, self.burnable_mats diff --git a/tests/readme.rst b/tests/readme.rst deleted file mode 100644 index 5e4b0227b..000000000 --- a/tests/readme.rst +++ /dev/null @@ -1 +0,0 @@ -See docs/source/devguide/tests.rst for information on the OpenMC test suite. diff --git a/tests/regression_tests/__init__.py b/tests/regression_tests/__init__.py deleted file mode 100644 index 965a7f94d..000000000 --- a/tests/regression_tests/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# Test configuration options for regression tests -config = { - 'exe': 'openmc', - 'mpi': False, - 'mpiexec': 'mpiexec', - 'mpi_np': '2', - 'update': False, - 'build_inputs': False -} diff --git a/tests/regression_tests/asymmetric_lattice/__init__.py b/tests/regression_tests/asymmetric_lattice/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/asymmetric_lattice/inputs_true.dat b/tests/regression_tests/asymmetric_lattice/inputs_true.dat deleted file mode 100644 index bbdc79715..000000000 --- a/tests/regression_tests/asymmetric_lattice/inputs_true.dat +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 3 3 - -32.13 -32.13 - -8 7 7 -8 8 8 -7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -32 -32 0 32 32 32 - - - - - - - 27 - - - 1 - nu-fission - - diff --git a/tests/regression_tests/asymmetric_lattice/results_true.dat b/tests/regression_tests/asymmetric_lattice/results_true.dat deleted file mode 100644 index 43f59aa5d..000000000 --- a/tests/regression_tests/asymmetric_lattice/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -4401f503237c94e9d9cfc9f60e0269d5ae5bb67be3225e18c5510ed08616482964e2962a06268751f66a455fac3ddd5faf91555638dfb56fcd09eee60219edff \ No newline at end of file diff --git a/tests/regression_tests/asymmetric_lattice/test.py b/tests/regression_tests/asymmetric_lattice/test.py deleted file mode 100644 index 7ed0293ce..000000000 --- a/tests/regression_tests/asymmetric_lattice/test.py +++ /dev/null @@ -1,93 +0,0 @@ -import os -import glob -import hashlib - -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class AsymmetricLatticeTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Extract universes encapsulating fuel and water assemblies - geometry = self._model.geometry - water = geometry.get_universes_by_name('water assembly (hot)')[0] - fuel = geometry.get_universes_by_name('fuel assembly (hot)')[0] - - # Construct a 3x3 lattice of fuel assemblies - core_lat = openmc.RectLattice(name='3x3 Core Lattice', lattice_id=202) - core_lat.lower_left = (-32.13, -32.13) - core_lat.pitch = (21.42, 21.42) - core_lat.universes = [[fuel, water, water], - [fuel, fuel, fuel], - [water, water, water]] - - # Create bounding surfaces - min_x = openmc.XPlane(-32.13, 'reflective') - max_x = openmc.XPlane(+32.13, 'reflective') - min_y = openmc.YPlane(-32.13, 'reflective') - max_y = openmc.YPlane(+32.13, 'reflective') - min_z = openmc.ZPlane(0, 'reflective') - max_z = openmc.ZPlane(+32.13, 'reflective') - - # Define root universe - root_univ = openmc.Universe(universe_id=0, name='root universe') - root_cell = openmc.Cell(cell_id=1) - root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z - root_cell.fill = core_lat - root_univ.add_cell(root_cell) - - # Over-ride geometry in the input set with this 3x3 lattice - self._model.geometry.root_universe = root_univ - - # Initialize a "distribcell" filter for the fuel pin cell - distrib_filter = openmc.DistribcellFilter(27) - - # Initialize the tallies - tally = openmc.Tally(name='distribcell tally', tally_id=27) - tally.filters.append(distrib_filter) - tally.scores.append('nu-fission') - - # Assign the tallies file to the input set - self._model.tallies.append(tally) - - # Specify summary output and correct source sampling box - self._model.settings.source = openmc.Source(space=openmc.stats.Box( - [-32, -32, 0], [32, 32, 32], only_fissionable = True)) - - def _get_results(self, hash_output=True): - """Digest info in statepoint and summary and return as a string.""" - - # Read the statepoint file - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] - sp = openmc.StatePoint(statepoint) - - # Extract the tally of interest - tally = sp.get_tally(name='distribcell tally') - - # Create a string of all mean, std. dev. values for both tallies - outstr = '' - outstr += '\n'.join(map('{:.8e}'.format, tally.mean.flatten())) + '\n' - outstr += '\n'.join(map('{:.8e}'.format, tally.std_dev.flatten())) + '\n' - - # Extract fuel assembly lattices from the summary - cells = sp.summary.geometry.get_all_cells() - fuel_cell = cells[27] - - # Append a string of lattice distribcell offsets to the string - outstr += '\n'.join(fuel_cell.paths) + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_asymmetric_lattice(): - harness = AsymmetricLatticeTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/cmfd_feed/__init__.py b/tests/regression_tests/cmfd_feed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed/geometry.xml b/tests/regression_tests/cmfd_feed/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed/materials.xml b/tests/regression_tests/cmfd_feed/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed/results_true.dat b/tests/regression_tests/cmfd_feed/results_true.dat deleted file mode 100644 index 4a2c6eea2..000000000 --- a/tests/regression_tests/cmfd_feed/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.169891E+00 6.289489E-03 -tally 1: -1.173922E+01 -1.385461E+01 -2.164076E+01 -4.699368E+01 -2.906462E+01 -8.464937E+01 -3.382312E+01 -1.147095E+02 -3.632006E+01 -1.323878E+02 -3.655413E+01 -1.341064E+02 -3.347757E+01 -1.124264E+02 -2.931336E+01 -8.607239E+01 -2.182947E+01 -4.789565E+01 -1.147668E+01 -1.325716E+01 -tally 2: -2.298190E+01 -2.667071E+01 -1.600292E+01 -1.293670E+01 -4.268506E+01 -9.161216E+01 -3.022909E+01 -4.598915E+01 -5.680399E+01 -1.623879E+02 -4.033805E+01 -8.196263E+01 -6.814742E+01 -2.331778E+02 -4.851618E+01 -1.182330E+02 -7.392923E+01 -2.740255E+02 -5.253586E+01 -1.384152E+02 -7.332860E+01 -2.698608E+02 -5.227405E+01 -1.371810E+02 -6.830172E+01 -2.340687E+02 -4.867159E+01 -1.188724E+02 -5.885634E+01 -1.736180E+02 -4.170434E+01 -8.719622E+01 -4.371848E+01 -9.592893E+01 -3.106403E+01 -4.844308E+01 -2.338413E+01 -2.752467E+01 -1.636713E+01 -1.347770E+01 -tally 3: -1.538752E+01 -1.196478E+01 -1.079685E+00 -6.010786E-02 -2.911906E+01 -4.269070E+01 -1.822657E+00 -1.671850E-01 -3.885421E+01 -7.608218E+01 -2.541516E+00 -3.262451E-01 -4.673300E+01 -1.097036E+02 -2.885307E+00 -4.214444E-01 -5.059247E+01 -1.283984E+02 -3.222796E+00 -5.237329E-01 -5.034856E+01 -1.272538E+02 -3.230225E+00 -5.273424E-01 -4.688476E+01 -1.103152E+02 -2.941287E+00 -4.363749E-01 -4.013746E+01 -8.077506E+01 -2.634234E+00 -3.520270E-01 -2.996887E+01 -4.509953E+01 -1.946504E+00 -1.919104E-01 -1.575260E+01 -1.248707E+01 -1.020705E+00 -5.413569E-02 -tally 4: -3.049469E+00 -4.677325E-01 -0.000000E+00 -0.000000E+00 -2.770358E+00 -3.879191E-01 -5.514939E+00 -1.528899E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.514939E+00 -1.528899E+00 -2.770358E+00 -3.879191E-01 -5.032131E+00 -1.275040E+00 -7.294002E+00 -2.675589E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.294002E+00 -2.675589E+00 -5.032131E+00 -1.275040E+00 -7.036008E+00 -2.490718E+00 -8.668860E+00 -3.776102E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.668860E+00 -3.776102E+00 -7.036008E+00 -2.490718E+00 -8.352414E+00 -3.501945E+00 -9.345868E+00 -4.380719E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.345868E+00 -4.380719E+00 -8.352414E+00 -3.501945E+00 -9.093766E+00 -4.158282E+00 -9.223771E+00 -4.270120E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.223771E+00 -4.270120E+00 -9.093766E+00 -4.158282E+00 -9.219150E+00 -4.264346E+00 -8.530966E+00 -3.651778E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.530966E+00 -3.651778E+00 -9.219150E+00 -4.264346E+00 -8.690373E+00 -3.785262E+00 -7.204424E+00 -2.604203E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.204424E+00 -2.604203E+00 -8.690373E+00 -3.785262E+00 -7.513640E+00 -2.833028E+00 -5.326721E+00 -1.426975E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.326721E+00 -1.426975E+00 -7.513640E+00 -2.833028E+00 -5.662215E+00 -1.607757E+00 -2.848381E+00 -4.093396E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.848381E+00 -4.093396E-01 -5.662215E+00 -1.607757E+00 -3.025812E+00 -4.597241E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -1.538652E+01 -1.196332E+01 -2.252427E+00 -2.605738E-01 -2.911344E+01 -4.267319E+01 -3.873926E+00 -7.615035E-01 -3.884516E+01 -7.604619E+01 -5.280610E+00 -1.414008E+00 -4.672391E+01 -1.096625E+02 -6.261805E+00 -1.983205E+00 -5.058447E+01 -1.283588E+02 -6.733810E+00 -2.278242E+00 -5.033589E+01 -1.271898E+02 -6.714658E+00 -2.273652E+00 -4.687563E+01 -1.102719E+02 -6.215002E+00 -1.956978E+00 -4.013134E+01 -8.075062E+01 -5.253064E+00 -1.396224E+00 -2.996497E+01 -4.508839E+01 -3.818076E+00 -7.509442E-01 -1.574994E+01 -1.248291E+01 -2.219928E+00 -2.515492E-01 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.170416E+00 -1.172966E+00 -1.165537E+00 -1.170979E+00 -1.161922E+00 -1.157523E+00 -1.158873E+00 -1.162877E+00 -1.167101E+00 -1.168130E+00 -1.170570E+00 -1.168115E+00 -1.174081E+00 -1.169458E+00 -1.167848E+00 -1.165116E+00 -cmfd entropy -3.203643E+00 -3.207943E+00 -3.213367E+00 -3.214360E+00 -3.219634E+00 -3.222232E+00 -3.221744E+00 -3.224544E+00 -3.225990E+00 -3.227769E+00 -3.227417E+00 -3.230728E+00 -3.231662E+00 -3.233316E+00 -3.233193E+00 -3.232564E+00 -cmfd balance -4.00906E-03 -4.43177E-03 -3.15267E-03 -3.51038E-03 -2.05209E-03 -2.06865E-03 -1.50243E-03 -1.58983E-03 -1.56602E-03 -1.17001E-03 -9.50759E-04 -9.07259E-04 -1.00900E-03 -1.06470E-03 -1.16361E-03 -9.75631E-04 -cmfd dominance ratio -5.397E-01 -5.425E-01 -5.481E-01 -5.473E-01 -5.503E-01 -5.502E-01 -5.483E-01 -5.520E-01 -5.505E-01 -3.216E-01 -5.373E-01 -5.517E-01 -5.508E-01 -5.524E-01 -5.524E-01 -5.523E-01 -cmfd openmc source comparison -6.959834E-03 -5.655657E-03 -3.886186E-03 -4.035116E-03 -3.043277E-03 -5.455474E-03 -4.515310E-03 -2.439840E-03 -2.114032E-03 -2.673132E-03 -2.431749E-03 -4.330928E-03 -3.404647E-03 -3.680298E-03 -3.309620E-03 -3.705541E-03 -cmfd source -4.697085E-02 -7.920706E-02 -1.107968E-01 -1.250932E-01 -1.383930E-01 -1.380648E-01 -1.246874E-01 -1.113705E-01 -8.203754E-02 -4.337882E-02 diff --git a/tests/regression_tests/cmfd_feed/settings.xml b/tests/regression_tests/cmfd_feed/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed/tallies.xml b/tests/regression_tests/cmfd_feed/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed/test.py b/tests/regression_tests/cmfd_feed/test.py deleted file mode 100644 index 906c631ec..000000000 --- a/tests/regression_tests/cmfd_feed/test.py +++ /dev/null @@ -1,142 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd -import numpy as np -import scipy.sparse - - -def test_cmfd_physical_adjoint(): - """Test physical adjoint functionality of CMFD - - This test runs CMFD with a physical adjoint calculation and asserts that - the adjoint k-effective and flux vector are equal to the non-adjoint - k-effective and flux vector at the last batch (equivalent for 1 group - problems). - - """ - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run_adjoint = True - cmfd_run.adjoint_type = 'physical' - cmfd_run.run() - assert(np.all(cmfd_run._phi == cmfd_run._adj_phi)) - assert(cmfd_run._adj_keff == cmfd_run._keff) - - -def test_cmfd_math_adjoint(): - """Test mathematical adjoint functionality of CMFD - - This test runs CMFD with a mathematical adjoint calculation and asserts - that the adjoint k-effective and flux vector are equal to the non-adjoint - k-effective and flux vector at the last batch (equivalent for 1 group - problems). - - """ - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run_adjoint = True - cmfd_run.adjoint_type = 'math' - cmfd_run.run() - assert(np.all(cmfd_run._phi == cmfd_run._adj_phi)) - assert(cmfd_run._adj_keff == cmfd_run._keff) - - -def test_cmfd_write_matrices(): - """Test write matrices functionality of CMFD - - This test runs CMFD with feedback and loads the loss/production matrices - and flux vector that are saved to disk, and checks to make sure these - values are consistent with each other and simulation results. - - """ - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.display = {'dominance': True} - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.write_matrices = True - cmfd_run.run() - - # Load loss matrix from numpy output file - loss_np = scipy.sparse.load_npz('loss.npz').todense() - # Load loss matrix from data file - loss_dat = np.loadtxt("loss.dat", delimiter=',') - - # Go through each element of loss_dat and compare to loss_np - for elem in loss_dat: - assert(np.isclose(loss_np[int(elem[0]), int(elem[1])], elem[2])) - - # Load production matrix from numpy output file - prod_np = scipy.sparse.load_npz('prod.npz').todense() - # Load production matrix from data file - prod_dat = np.loadtxt("prod.dat", delimiter=',') - - # Go through each element of prod_dat and compare to prod_np - for elem in prod_dat: - assert(np.isclose(prod_np[int(elem[0]), int(elem[1])], elem[2])) - - # Load flux vector from numpy output file - flux_np = np.load('fluxvec.npy') - # Load flux from data file - flux_dat = np.loadtxt("fluxvec.dat", delimiter='\n') - - # Compare flux from numpy file, .dat file, and from simulation - assert(np.all(np.isclose(flux_np, cmfd_run._phi))) - assert(np.all(np.isclose(flux_np, flux_dat))) - - -def test_cmfd_feed(): - """Test 1 group CMFD solver with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.display = {'dominance': True} - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_feed_2g/__init__.py b/tests/regression_tests/cmfd_feed_2g/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed_2g/geometry.xml b/tests/regression_tests/cmfd_feed_2g/geometry.xml deleted file mode 100644 index 9fdd2ddcb..000000000 --- a/tests/regression_tests/cmfd_feed_2g/geometry.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - 2 2 - -1.25984 -1.25984 - 1.25984 1.25984 - - 763 763 - 763 763 - - - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_2g/materials.xml b/tests/regression_tests/cmfd_feed_2g/materials.xml deleted file mode 100644 index bfa2d8842..000000000 --- a/tests/regression_tests/cmfd_feed_2g/materials.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - 300 - - - - - - 300 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 300 - - - - - - - - - - 300 - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_2g/results_true.dat b/tests/regression_tests/cmfd_feed_2g/results_true.dat deleted file mode 100644 index f16d82309..000000000 --- a/tests/regression_tests/cmfd_feed_2g/results_true.dat +++ /dev/null @@ -1,434 +0,0 @@ -k-combined: -1.038883E+00 1.017030E-02 -tally 1: -1.167304E+02 -1.362680E+03 -1.157179E+02 -1.339273E+03 -1.167087E+02 -1.362782E+03 -1.164493E+02 -1.356411E+03 -tally 2: -4.400233E+01 -9.698989E+01 -6.541957E+01 -2.144299E+02 -1.863245E+02 -1.738212E+03 -1.038047E+02 -5.390768E+02 -4.368854E+01 -9.564001E+01 -6.489620E+01 -2.109923E+02 -1.836691E+02 -1.687792E+03 -1.022706E+02 -5.232407E+02 -4.433402E+01 -9.859049E+01 -6.548060E+01 -2.150470E+02 -1.839219E+02 -1.692209E+03 -1.031634E+02 -5.323852E+02 -4.380686E+01 -9.606723E+01 -6.480355E+01 -2.103905E+02 -1.868847E+02 -1.747254E+03 -1.038109E+02 -5.391360E+02 -tally 3: -6.192979E+01 -1.921761E+02 -0.000000E+00 -0.000000E+00 -2.033842E-02 -4.375294E-05 -4.296339E+00 -9.280716E-01 -3.493776E+00 -6.157094E-01 -0.000000E+00 -0.000000E+00 -9.876716E+01 -4.880113E+02 -9.043140E-01 -4.156054E-02 -6.138292E+01 -1.887853E+02 -0.000000E+00 -0.000000E+00 -1.591722E-02 -2.328432E-05 -4.296798E+00 -9.289349E-01 -3.584967E+00 -6.444749E-01 -0.000000E+00 -0.000000E+00 -9.717439E+01 -4.724254E+02 -8.435691E-01 -3.666152E-02 -6.192881E+01 -1.924016E+02 -0.000000E+00 -0.000000E+00 -1.796382E-02 -3.190855E-05 -4.343238E+00 -9.514040E-01 -3.504683E+00 -6.157615E-01 -0.000000E+00 -0.000000E+00 -9.818871E+01 -4.822799E+02 -8.401346E-01 -3.664038E-02 -6.130607E+01 -1.882837E+02 -0.000000E+00 -0.000000E+00 -1.220252E-02 -1.711667E-05 -4.245413E+00 -9.056738E-01 -3.468894E+00 -6.033679E-01 -0.000000E+00 -0.000000E+00 -9.885292E+01 -4.888720E+02 -9.509199E-01 -4.670952E-02 -tally 4: -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.200260E+00 -4.243011E+00 -3.728022E+01 -6.953801E+01 -9.178009E+00 -4.218903E+00 -3.738925E+01 -6.993833E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.019225E+00 -4.079528E+00 -3.709185E+01 -6.883085E+01 -9.037478E+00 -4.095846E+00 -3.710303E+01 -6.888447E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.178009E+00 -4.218903E+00 -3.738925E+01 -6.993833E+01 -9.200260E+00 -4.243011E+00 -3.728022E+01 -6.953801E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.097360E+00 -4.147125E+00 -3.700603E+01 -6.851110E+01 -9.003417E+00 -4.059372E+00 -3.717266E+01 -6.912709E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.042233E+00 -4.097018E+00 -3.711597E+01 -6.891834E+01 -9.107597E+00 -4.161211E+00 -3.715168E+01 -6.904544E+01 -9.037478E+00 -4.095846E+00 -3.710303E+01 -6.888447E+01 -9.019225E+00 -4.079528E+00 -3.709185E+01 -6.883085E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.107597E+00 -4.161211E+00 -3.715168E+01 -6.904544E+01 -9.042233E+00 -4.097018E+00 -3.711597E+01 -6.891834E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.003417E+00 -4.059372E+00 -3.717266E+01 -6.912709E+01 -9.097360E+00 -4.147125E+00 -3.700603E+01 -6.851110E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -6.195013E+01 -1.923032E+02 -1.022516E+02 -5.230716E+02 -1.418310E+01 -1.011490E+01 -4.677537E+01 -1.094859E+02 -6.139884E+01 -1.888834E+02 -1.007512E+02 -5.078162E+02 -1.403236E+01 -9.884347E+00 -4.598486E+01 -1.058070E+02 -6.194677E+01 -1.925125E+02 -1.016864E+02 -5.172531E+02 -1.407797E+01 -9.971785E+00 -4.623118E+01 -1.069663E+02 -6.131828E+01 -1.883600E+02 -1.023107E+02 -5.236668E+02 -1.375796E+01 -9.501501E+00 -4.638162E+01 -1.076532E+02 -cmfd indices -2.000000E+00 -2.000000E+00 -1.000000E+00 -2.000000E+00 -k cmfd -1.034617E+00 -1.034521E+00 -1.036479E+00 -1.035658E+00 -1.032505E+00 -1.027277E+00 -1.029326E+00 -1.029881E+00 -1.035579E+00 -1.034753E+00 -1.031963E+00 -1.034797E+00 -1.035383E+00 -1.035908E+00 -1.035629E+00 -1.036034E+00 -cmfd entropy -1.999493E+00 -1.999058E+00 -1.999331E+00 -1.999370E+00 -1.999383E+00 -1.999455E+00 -1.999640E+00 -1.999810E+00 -1.999881E+00 -1.999937E+00 -1.999973E+00 -1.999965E+00 -1.999972E+00 -1.999982E+00 -1.999998E+00 -1.999984E+00 -cmfd balance -3.99304E-04 -4.16856E-04 -6.38469E-04 -3.92822E-04 -3.78984E-04 -2.68486E-04 -4.84991E-04 -1.08402E-03 -1.09177E-03 -5.45977E-04 -4.45554E-04 -4.01147E-04 -3.71025E-04 -3.57715E-04 -3.84599E-04 -3.90067E-04 -cmfd dominance ratio -6.239E-03 -6.303E-03 -6.347E-03 -6.388E-03 -6.340E-03 -6.334E-03 -6.270E-03 -6.173E-03 -6.068E-03 -6.061E-03 -6.016E-03 -6.108E-03 -6.117E-03 -6.074E-03 -6.005E-03 -5.996E-03 -cmfd openmc source comparison -1.931386E-05 -2.839161E-05 -1.407963E-05 -6.718156E-06 -9.164199E-06 -1.382540E-05 -2.871606E-05 -4.192300E-05 -5.327515E-05 -6.566500E-05 -6.655540E-05 -6.034977E-05 -6.004677E-05 -5.711622E-05 -6.271263E-05 -6.425362E-05 -cmfd source -2.510278E-01 -2.480592E-01 -2.501750E-01 -2.507380E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_2g/settings.xml b/tests/regression_tests/cmfd_feed_2g/settings.xml deleted file mode 100644 index 9e483e6a0..000000000 --- a/tests/regression_tests/cmfd_feed_2g/settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - -1.25984 -1.25984 -1 1.25984 1.25984 1 - - - - - - 2 2 1 - -1.25984 -1.25984 -1.0 - 1.25984 1.25984 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_2g/tallies.xml b/tests/regression_tests/cmfd_feed_2g/tallies.xml deleted file mode 100644 index 477a07833..000000000 --- a/tests/regression_tests/cmfd_feed_2g/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -1.25984 -1.25984 -1.0 - 1.25984 1.25984 1.0 - 2 2 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_2g/test.py b/tests/regression_tests/cmfd_feed_2g/test.py deleted file mode 100644 index ba4d21609..000000000 --- a/tests/regression_tests/cmfd_feed_2g/test.py +++ /dev/null @@ -1,29 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd -import numpy as np - - -def test_cmfd_feed_2g(): - """Test 2 group CMFD solver results with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-1.25984, -1.25984, -1.0) - cmfd_mesh.upper_right = (1.25984, 1.25984, 1.0) - cmfd_mesh.dimension = (2, 2, 1) - cmfd_mesh.energy = (0.0, 0.625, 20000000) - cmfd_mesh.albedo = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.display = {'dominance': True} - cmfd_run.feedback = True - cmfd_run.downscatter = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_feed_expanding_window/__init__.py b/tests/regression_tests/cmfd_feed_expanding_window/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml b/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/materials.xml b/tests/regression_tests/cmfd_feed_expanding_window/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat deleted file mode 100644 index b67bef0f7..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.165403E+00 1.129918E-02 -tally 1: -1.141961E+01 -1.307497E+01 -2.075941E+01 -4.316095E+01 -2.834539E+01 -8.063510E+01 -3.513869E+01 -1.238515E+02 -3.699858E+01 -1.372516E+02 -3.612668E+01 -1.310763E+02 -3.373368E+01 -1.140458E+02 -2.836844E+01 -8.075759E+01 -2.158837E+01 -4.674848E+01 -1.141868E+01 -1.310648E+01 -tally 2: -1.126626E+00 -1.269287E+00 -7.749042E-01 -6.004765E-01 -1.991608E+00 -3.966503E+00 -1.411775E+00 -1.993108E+00 -2.978264E+00 -8.870057E+00 -2.130066E+00 -4.537180E+00 -3.708857E+00 -1.375562E+01 -2.698010E+00 -7.279259E+00 -4.233192E+00 -1.791991E+01 -3.023990E+00 -9.144518E+00 -4.062113E+00 -1.650076E+01 -2.910472E+00 -8.470848E+00 -3.506681E+00 -1.229681E+01 -2.497751E+00 -6.238760E+00 -2.974675E+00 -8.848690E+00 -2.121163E+00 -4.499332E+00 -2.329248E+00 -5.425398E+00 -1.658233E+00 -2.749736E+00 -1.158552E+00 -1.342242E+00 -8.282698E-01 -6.860309E-01 -tally 3: -7.459301E-01 -5.564117E-01 -4.877614E-02 -2.379112E-03 -1.356702E+00 -1.840641E+00 -8.361624E-02 -6.991675E-03 -2.047332E+00 -4.191570E+00 -1.521351E-01 -2.314509E-02 -2.610287E+00 -6.813596E+00 -1.718778E-01 -2.954199E-02 -2.911379E+00 -8.476127E+00 -1.823299E-01 -3.324418E-02 -2.806920E+00 -7.878801E+00 -2.090406E-01 -4.369797E-02 -2.415727E+00 -5.835736E+00 -1.486511E-01 -2.209715E-02 -2.051064E+00 -4.206862E+00 -1.196177E-01 -1.430839E-02 -1.593746E+00 -2.540026E+00 -1.126497E-01 -1.268994E-02 -7.994935E-01 -6.391898E-01 -5.806683E-02 -3.371757E-03 -tally 4: -1.341719E-01 -1.800210E-02 -0.000000E+00 -0.000000E+00 -1.420707E-01 -2.018410E-02 -2.633150E-01 -6.933479E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.633150E-01 -6.933479E-02 -1.420707E-01 -2.018410E-02 -2.628613E-01 -6.909608E-02 -3.590382E-01 -1.289084E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.590382E-01 -1.289084E-01 -2.628613E-01 -6.909608E-02 -3.851599E-01 -1.483482E-01 -4.595809E-01 -2.112146E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.595809E-01 -2.112146E-01 -3.851599E-01 -1.483482E-01 -4.679967E-01 -2.190209E-01 -4.970187E-01 -2.470276E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.970187E-01 -2.470276E-01 -4.679967E-01 -2.190209E-01 -4.909661E-01 -2.410477E-01 -4.838785E-01 -2.341384E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.838785E-01 -2.341384E-01 -4.909661E-01 -2.410477E-01 -5.152690E-01 -2.655021E-01 -4.788649E-01 -2.293116E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.788649E-01 -2.293116E-01 -5.152690E-01 -2.655021E-01 -4.266876E-01 -1.820623E-01 -3.401342E-01 -1.156913E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.401342E-01 -1.156913E-01 -4.266876E-01 -1.820623E-01 -3.724186E-01 -1.386956E-01 -2.560013E-01 -6.553669E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.560013E-01 -6.553669E-02 -3.724186E-01 -1.386956E-01 -2.892134E-01 -8.364439E-02 -1.556176E-01 -2.421685E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.556176E-01 -2.421685E-02 -2.892134E-01 -8.364439E-02 -1.497744E-01 -2.243237E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -7.459301E-01 -5.564117E-01 -1.149820E-01 -1.322085E-02 -1.356702E+00 -1.840641E+00 -1.801102E-01 -3.243968E-02 -2.047332E+00 -4.191570E+00 -2.627497E-01 -6.903740E-02 -2.609217E+00 -6.808012E+00 -3.360314E-01 -1.129171E-01 -2.909457E+00 -8.464941E+00 -4.095451E-01 -1.677272E-01 -2.805131E+00 -7.868760E+00 -3.957627E-01 -1.566281E-01 -2.415727E+00 -5.835736E+00 -3.196414E-01 -1.021706E-01 -2.049859E+00 -4.201923E+00 -3.162399E-01 -1.000077E-01 -1.593746E+00 -2.540026E+00 -2.169985E-01 -4.708836E-02 -7.994935E-01 -6.391898E-01 -1.002481E-01 -1.004969E-02 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.143597E+00 -1.163387E+00 -1.173384E+00 -1.171035E+00 -1.147196E+00 -1.122260E+00 -1.106380E+00 -1.124693E+00 -1.133192E+00 -1.134435E+00 -1.142380E+00 -1.132168E+00 -1.132560E+00 -1.153781E+00 -1.170308E+00 -1.184540E+00 -cmfd entropy -3.212002E+00 -3.206393E+00 -3.223984E+00 -3.222764E+00 -3.232123E+00 -3.242083E+00 -3.246067E+00 -3.238869E+00 -3.235585E+00 -3.234611E+00 -3.233575E+00 -3.236922E+00 -3.229545E+00 -3.225232E+00 -3.221485E+00 -3.219108E+00 -cmfd balance -8.26180E-03 -4.27338E-03 -2.22686E-03 -1.93026E-03 -1.96979E-03 -2.13756E-03 -2.01479E-03 -1.74519E-03 -2.09248E-03 -1.25545E-03 -1.48370E-03 -1.75963E-03 -1.98194E-03 -1.87306E-03 -1.24780E-03 -1.15560E-03 -cmfd dominance ratio -5.404E-01 -5.406E-01 -5.449E-01 -5.473E-01 -5.534E-01 -5.623E-01 -5.738E-01 -5.611E-01 -5.569E-01 -5.556E-01 -5.555E-01 -5.583E-01 -5.544E-01 -5.486E-01 -5.412E-01 -5.383E-01 -cmfd openmc source comparison -1.575499E-02 -1.293688E-02 -3.531746E-03 -8.281178E-03 -5.771681E-03 -7.459013E-03 -5.012869E-03 -1.770224E-03 -5.242540E-03 -3.888027E-03 -6.653433E-03 -8.839928E-03 -5.456904E-03 -5.668412E-03 -4.016377E-03 -4.179381E-03 -cmfd source -4.116210E-02 -7.797480E-02 -1.062822E-01 -1.333719E-01 -1.481091E-01 -1.370422E-01 -1.299765E-01 -9.887040E-02 -8.228753E-02 -4.492330E-02 diff --git a/tests/regression_tests/cmfd_feed_expanding_window/settings.xml b/tests/regression_tests/cmfd_feed_expanding_window/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml b/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_expanding_window/test.py b/tests/regression_tests/cmfd_feed_expanding_window/test.py deleted file mode 100644 index e8671e95c..000000000 --- a/tests/regression_tests/cmfd_feed_expanding_window/test.py +++ /dev/null @@ -1,26 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd - - -def test_cmfd_feed_rolling_window(): - """Test 1 group CMFD solver with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 10 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.window_type = 'expanding' - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_feed_ng/__init__.py b/tests/regression_tests/cmfd_feed_ng/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed_ng/geometry.xml b/tests/regression_tests/cmfd_feed_ng/geometry.xml deleted file mode 100644 index 9fdd2ddcb..000000000 --- a/tests/regression_tests/cmfd_feed_ng/geometry.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - 2 2 - -1.25984 -1.25984 - 1.25984 1.25984 - - 763 763 - 763 763 - - - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_ng/materials.xml b/tests/regression_tests/cmfd_feed_ng/materials.xml deleted file mode 100644 index bfa2d8842..000000000 --- a/tests/regression_tests/cmfd_feed_ng/materials.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - 300 - - - - - - 300 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 300 - - - - - - - - - - 300 - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_ng/results_true.dat b/tests/regression_tests/cmfd_feed_ng/results_true.dat deleted file mode 100644 index d62fb5b4b..000000000 --- a/tests/regression_tests/cmfd_feed_ng/results_true.dat +++ /dev/null @@ -1,621 +0,0 @@ -k-combined: -1.029540E+00 1.765357E-02 -tally 1: -1.144958E+02 -1.311468E+03 -1.156179E+02 -1.337279E+03 -1.150532E+02 -1.324445E+03 -1.151074E+02 -1.325687E+03 -tally 2: -3.465741E+01 -7.535177E+01 -5.111161E+01 -1.637703E+02 -1.077835E+01 -7.306380E+00 -9.069631E+00 -5.159419E+00 -1.367406E+02 -1.170393E+03 -7.339832E+01 -3.371470E+02 -3.562570E+01 -7.967278E+01 -5.270792E+01 -1.745991E+02 -1.036807E+01 -6.781874E+00 -8.681747E+00 -4.745685E+00 -1.356820E+02 -1.151355E+03 -7.286142E+01 -3.320255E+02 -3.538463E+01 -7.862285E+01 -5.236063E+01 -1.723667E+02 -1.054863E+01 -7.042669E+00 -8.940285E+00 -5.055491E+00 -1.392130E+02 -1.214087E+03 -7.370365E+01 -3.397160E+02 -3.523551E+01 -7.794325E+01 -5.202347E+01 -1.700797E+02 -1.028117E+01 -6.655678E+00 -8.538920E+00 -4.585368E+00 -1.366887E+02 -1.169157E+03 -7.333804E+01 -3.363693E+02 -tally 3: -4.838342E+01 -1.467669E+02 -0.000000E+00 -0.000000E+00 -9.528018E-03 -1.989268E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.248228E+00 -6.666986E-01 -2.521640E+00 -3.997992E-01 -0.000000E+00 -0.000000E+00 -6.409424E+00 -2.580559E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.132877E-01 -1.324578E-03 -2.859604E-01 -5.376390E-03 -0.000000E+00 -0.000000E+00 -2.639920E+00 -4.380416E-01 -0.000000E+00 -0.000000E+00 -6.939496E+01 -3.014077E+02 -6.294737E-01 -2.532146E-02 -4.991526E+01 -1.566280E+02 -0.000000E+00 -0.000000E+00 -2.046458E-02 -4.809372E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.463364E+00 -7.583727E-01 -2.430263E+00 -3.746875E-01 -0.000000E+00 -0.000000E+00 -6.122700E+00 -2.364648E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.905302E-02 -7.522016E-04 -3.093670E-01 -6.756039E-03 -0.000000E+00 -0.000000E+00 -2.632761E+00 -4.384843E-01 -0.000000E+00 -0.000000E+00 -6.885265E+01 -2.965191E+02 -6.537575E-01 -2.783733E-02 -4.958341E+01 -1.546656E+02 -0.000000E+00 -0.000000E+00 -1.104672E-02 -2.296190E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.430503E+00 -7.448601E-01 -2.530174E+00 -4.079173E-01 -0.000000E+00 -0.000000E+00 -6.274274E+00 -2.498200E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.479111E-02 -8.398250E-04 -3.294639E-01 -7.117117E-03 -0.000000E+00 -0.000000E+00 -2.509698E+00 -3.981073E-01 -0.000000E+00 -0.000000E+00 -6.980298E+01 -3.047163E+02 -5.942566E-01 -2.324911E-02 -4.923505E+01 -1.524105E+02 -0.000000E+00 -0.000000E+00 -8.227938E-03 -1.354400E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.469466E+00 -7.613187E-01 -2.362792E+00 -3.532280E-01 -0.000000E+00 -0.000000E+00 -6.039916E+00 -2.302934E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.082199E-01 -9.467140E-04 -3.168219E-01 -6.900253E-03 -0.000000E+00 -0.000000E+00 -2.552623E+00 -4.095459E-01 -0.000000E+00 -0.000000E+00 -6.925085E+01 -2.999309E+02 -6.137602E-01 -2.534680E-02 -tally 4: -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.242831E+00 -3.304033E+00 -2.049900E+00 -2.662637E-01 -2.719284E+01 -4.625227E+01 -7.106615E+00 -3.182962E+00 -2.092906E+00 -2.757959E-01 -2.714938E+01 -4.610188E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.098381E+00 -3.169308E+00 -2.239283E+00 -3.166544E-01 -2.718623E+01 -4.622986E+01 -7.155181E+00 -3.223545E+00 -2.207036E+00 -3.075514E-01 -2.738538E+01 -4.691471E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.106615E+00 -3.182962E+00 -2.092906E+00 -2.757959E-01 -2.714938E+01 -4.610188E+01 -7.242831E+00 -3.304033E+00 -2.049900E+00 -2.662637E-01 -2.719284E+01 -4.625227E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.311265E+00 -3.366747E+00 -2.082480E+00 -2.748257E-01 -2.755422E+01 -4.749248E+01 -7.228075E+00 -3.276572E+00 -2.031308E+00 -2.619010E-01 -2.738542E+01 -4.691635E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.340922E+00 -3.389303E+00 -2.057125E+00 -2.684644E-01 -2.738205E+01 -4.690167E+01 -7.315301E+00 -3.364365E+00 -2.170144E+00 -2.965160E-01 -2.757366E+01 -4.755684E+01 -7.155181E+00 -3.223545E+00 -2.207036E+00 -3.075514E-01 -2.738538E+01 -4.691471E+01 -7.098381E+00 -3.169308E+00 -2.239283E+00 -3.166544E-01 -2.718623E+01 -4.622986E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.315301E+00 -3.364365E+00 -2.170144E+00 -2.965160E-01 -2.757366E+01 -4.755684E+01 -7.340922E+00 -3.389303E+00 -2.057125E+00 -2.684644E-01 -2.738205E+01 -4.690167E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.228075E+00 -3.276572E+00 -2.031308E+00 -2.619010E-01 -2.738542E+01 -4.691635E+01 -7.311265E+00 -3.366747E+00 -2.082480E+00 -2.748257E-01 -2.755422E+01 -4.749248E+01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -4.839295E+01 -1.468255E+02 -8.931064E+00 -5.003633E+00 -7.231756E+01 -3.273024E+02 -1.088865E+01 -7.436517E+00 -4.139343E+00 -1.078084E+00 -3.295902E+01 -6.798023E+01 -4.993572E+01 -1.567557E+02 -8.552963E+00 -4.606265E+00 -7.178811E+01 -3.223267E+02 -1.087522E+01 -7.441404E+00 -3.965469E+00 -9.946937E-01 -3.244312E+01 -6.588480E+01 -4.959446E+01 -1.547357E+02 -8.804447E+00 -4.904770E+00 -7.263395E+01 -3.299329E+02 -1.105711E+01 -7.709583E+00 -4.082202E+00 -1.057954E+00 -3.316528E+01 -6.882214E+01 -4.924327E+01 -1.524623E+02 -8.402708E+00 -4.441938E+00 -7.211875E+01 -3.252784E+02 -1.130536E+01 -8.069378E+00 -3.817575E+00 -9.236385E-01 -3.272602E+01 -6.700774E+01 -cmfd indices -2.000000E+00 -2.000000E+00 -1.000000E+00 -3.000000E+00 -k cmfd -1.029991E+00 -1.037713E+00 -1.038248E+00 -1.035411E+00 -1.039580E+00 -1.031827E+00 -1.026250E+00 -1.026011E+00 -1.026544E+00 -1.031482E+00 -1.031761E+00 -cmfd entropy -1.998652E+00 -1.999218E+00 -1.999186E+00 -1.999177E+00 -1.999248E+00 -1.999637E+00 -1.999721E+00 -1.999648E+00 -1.999631E+00 -1.999572E+00 -1.999693E+00 -cmfd balance -8.98944E-04 -4.45874E-04 -2.18562E-04 -2.83412E-04 -3.60924E-04 -2.53288E-04 -3.38843E-04 -3.17072E-04 -3.25867E-04 -2.27001E-04 -2.41723E-04 -cmfd dominance ratio -3.768E-03 -3.706E-03 -2.572E-03 -2.757E-03 -3.815E-03 -3.951E-03 -3.826E-03 -3.829E-03 -3.902E-03 -3.952E-03 -3.885E-03 -cmfd openmc source comparison -3.292759E-05 -2.585546E-05 -2.217204E-05 -2.121913E-05 -9.253928E-06 -2.940947E-05 -3.083596E-05 -2.547491E-05 -2.602691E-05 -2.561169E-05 -2.816825E-05 -cmfd source -2.417661E-01 -2.547768E-01 -2.495653E-01 -2.538918E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_ng/settings.xml b/tests/regression_tests/cmfd_feed_ng/settings.xml deleted file mode 100644 index 990160275..000000000 --- a/tests/regression_tests/cmfd_feed_ng/settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 600 - - - - - -1.25984 -1.25984 -1 1.25984 1.25984 1 - - - - - - 2 2 1 - -1.25984 -1.25984 -1.0 - 1.25984 1.25984 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_ng/tallies.xml b/tests/regression_tests/cmfd_feed_ng/tallies.xml deleted file mode 100644 index 477a07833..000000000 --- a/tests/regression_tests/cmfd_feed_ng/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -1.25984 -1.25984 -1.0 - 1.25984 1.25984 1.0 - 2 2 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_ng/test.py b/tests/regression_tests/cmfd_feed_ng/test.py deleted file mode 100644 index dce674f90..000000000 --- a/tests/regression_tests/cmfd_feed_ng/test.py +++ /dev/null @@ -1,30 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd -import numpy as np - - -def test_cmfd_feed_ng(): - """Test n group CMFD solver with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-1.25984, -1.25984, -1.0) - cmfd_mesh.upper_right = (1.25984, 1.25984, 1.0) - cmfd_mesh.dimension = (2, 2, 1) - cmfd_mesh.energy = (0.0, 0.625, 5.53080, 20000000) - cmfd_mesh.albedo = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.reset = [5] - cmfd_run.tally_begin = 10 - cmfd_run.feedback_begin = 10 - cmfd_run.display = {'dominance': True} - cmfd_run.feedback = True - cmfd_run.downscatter = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_feed_ref_d/__init__.py b/tests/regression_tests/cmfd_feed_ref_d/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed_ref_d/geometry.xml b/tests/regression_tests/cmfd_feed_ref_d/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/materials.xml b/tests/regression_tests/cmfd_feed_ref_d/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat deleted file mode 100644 index 06440d81f..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.165408E+00 1.127320E-02 -tally 1: -1.141009E+01 -1.305436E+01 -2.074878E+01 -4.311543E+01 -2.834824E+01 -8.065180E+01 -3.513901E+01 -1.238542E+02 -3.699846E+01 -1.372507E+02 -3.612638E+01 -1.310741E+02 -3.373329E+01 -1.140431E+02 -2.836806E+01 -8.075546E+01 -2.158796E+01 -4.674672E+01 -1.141841E+01 -1.310586E+01 -tally 2: -1.126662E+00 -1.269368E+00 -7.749275E-01 -6.005127E-01 -1.991651E+00 -3.966673E+00 -1.411802E+00 -1.993185E+00 -2.978294E+00 -8.870233E+00 -2.130084E+00 -4.537258E+00 -3.708845E+00 -1.375553E+01 -2.698001E+00 -7.279210E+00 -4.233143E+00 -1.791950E+01 -3.023958E+00 -9.144324E+00 -4.062060E+00 -1.650033E+01 -2.910435E+00 -8.470632E+00 -3.506628E+00 -1.229644E+01 -2.497713E+00 -6.238573E+00 -2.974637E+00 -8.848463E+00 -2.121135E+00 -4.499215E+00 -2.329228E+00 -5.425303E+00 -1.658218E+00 -2.749687E+00 -1.158542E+00 -1.342220E+00 -8.282626E-01 -6.860190E-01 -tally 3: -7.459525E-01 -5.564451E-01 -4.877161E-02 -2.378670E-03 -1.356729E+00 -1.840713E+00 -8.360848E-02 -6.990377E-03 -2.047350E+00 -4.191641E+00 -1.521210E-01 -2.314079E-02 -2.610278E+00 -6.813552E+00 -1.718619E-01 -2.953650E-02 -2.911348E+00 -8.475950E+00 -1.823129E-01 -3.323800E-02 -2.806884E+00 -7.878600E+00 -2.090212E-01 -4.368986E-02 -2.415690E+00 -5.835559E+00 -1.486373E-01 -2.209304E-02 -2.051037E+00 -4.206752E+00 -1.196066E-01 -1.430573E-02 -1.593732E+00 -2.539980E+00 -1.126392E-01 -1.268759E-02 -7.994865E-01 -6.391786E-01 -5.806144E-02 -3.371131E-03 -tally 4: -1.341763E-01 -1.800329E-02 -0.000000E+00 -0.000000E+00 -1.420749E-01 -2.018527E-02 -2.633206E-01 -6.933776E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.633206E-01 -6.933776E-02 -1.420749E-01 -2.018527E-02 -2.628684E-01 -6.909981E-02 -3.590428E-01 -1.289117E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.590428E-01 -1.289117E-01 -2.628684E-01 -6.909981E-02 -3.851638E-01 -1.483512E-01 -4.595776E-01 -2.112116E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.595776E-01 -2.112116E-01 -3.851638E-01 -1.483512E-01 -4.679953E-01 -2.190196E-01 -4.970127E-01 -2.470216E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.970127E-01 -2.470216E-01 -4.679953E-01 -2.190196E-01 -4.909606E-01 -2.410423E-01 -4.838733E-01 -2.341333E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.838733E-01 -2.341333E-01 -4.909606E-01 -2.410423E-01 -5.152620E-01 -2.654949E-01 -4.788580E-01 -2.293049E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.788580E-01 -2.293049E-01 -5.152620E-01 -2.654949E-01 -4.266812E-01 -1.820568E-01 -3.401298E-01 -1.156883E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.401298E-01 -1.156883E-01 -4.266812E-01 -1.820568E-01 -3.724142E-01 -1.386923E-01 -2.559996E-01 -6.553579E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.559996E-01 -6.553579E-02 -3.724142E-01 -1.386923E-01 -2.892105E-01 -8.364271E-02 -1.556166E-01 -2.421652E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.556166E-01 -2.421652E-02 -2.892105E-01 -8.364271E-02 -1.497731E-01 -2.243198E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -7.459525E-01 -5.564451E-01 -1.149859E-01 -1.322177E-02 -1.356729E+00 -1.840713E+00 -1.801152E-01 -3.244149E-02 -2.047350E+00 -4.191641E+00 -2.627538E-01 -6.903954E-02 -2.609208E+00 -6.807967E+00 -3.360312E-01 -1.129170E-01 -2.909427E+00 -8.464765E+00 -4.095398E-01 -1.677229E-01 -2.805095E+00 -7.868559E+00 -3.957580E-01 -1.566244E-01 -2.415690E+00 -5.835559E+00 -3.196366E-01 -1.021676E-01 -2.049833E+00 -4.201813E+00 -3.162366E-01 -1.000056E-01 -1.593732E+00 -2.539980E+00 -2.169968E-01 -4.708761E-02 -7.994865E-01 -6.391786E-01 -1.002479E-01 -1.004964E-02 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.143785E+00 -1.163460E+00 -1.173453E+00 -1.171056E+00 -1.147214E+00 -1.122230E+00 -1.106385E+00 -1.124706E+00 -1.133207E+00 -1.134453E+00 -1.142355E+00 -1.132121E+00 -1.132479E+00 -1.153657E+00 -1.170183E+00 -1.184408E+00 -cmfd entropy -3.211758E+00 -3.206356E+00 -3.223933E+00 -3.222754E+00 -3.232110E+00 -3.242098E+00 -3.246062E+00 -3.238858E+00 -3.235577E+00 -3.234604E+00 -3.233582E+00 -3.236922E+00 -3.229563E+00 -3.225265E+00 -3.221498E+00 -3.219126E+00 -cmfd balance -8.26180E-03 -4.27338E-03 -2.22686E-03 -1.93026E-03 -1.96979E-03 -2.13756E-03 -2.01521E-03 -1.74538E-03 -2.09240E-03 -1.25495E-03 -1.49542E-03 -1.76968E-03 -1.99174E-03 -1.87753E-03 -1.24170E-03 -1.15645E-03 -cmfd dominance ratio -5.408E-01 -5.374E-01 -5.420E-01 -5.444E-01 -5.513E-01 -5.613E-01 -5.722E-01 -5.592E-01 -5.542E-01 -5.537E-01 -5.541E-01 -5.579E-01 -5.543E-01 -5.487E-01 -5.413E-01 -5.381E-01 -cmfd openmc source comparison -1.597982E-02 -1.276493E-02 -3.495229E-03 -8.157807E-03 -5.715330E-03 -7.433111E-03 -5.006211E-03 -1.766072E-03 -5.184425E-03 -3.864321E-03 -6.617152E-03 -8.841210E-03 -5.454747E-03 -5.652690E-03 -4.006767E-03 -4.167617E-03 -cmfd source -4.116746E-02 -7.798354E-02 -1.062881E-01 -1.333681E-01 -1.481008E-01 -1.370408E-01 -1.299726E-01 -9.886814E-02 -8.228698E-02 -4.492338E-02 diff --git a/tests/regression_tests/cmfd_feed_ref_d/settings.xml b/tests/regression_tests/cmfd_feed_ref_d/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/tallies.xml b/tests/regression_tests/cmfd_feed_ref_d/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_ref_d/test.py b/tests/regression_tests/cmfd_feed_ref_d/test.py deleted file mode 100644 index d033ab8dd..000000000 --- a/tests/regression_tests/cmfd_feed_ref_d/test.py +++ /dev/null @@ -1,27 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd - - -def test_cmfd_feed_rolling_window(): - """Test 1 group CMFD solver with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 10 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.window_type = 'expanding' - cmfd_run.ref_d = [0.542] - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_feed_rolling_window/__init__.py b/tests/regression_tests/cmfd_feed_rolling_window/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml b/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/materials.xml b/tests/regression_tests/cmfd_feed_rolling_window/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat deleted file mode 100644 index 518052683..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.172120E+00 9.761693E-03 -tally 1: -1.131066E+01 -1.287315E+01 -2.035268E+01 -4.162146E+01 -2.839961E+01 -8.098764E+01 -3.405187E+01 -1.164951E+02 -3.712390E+01 -1.380899E+02 -3.687780E+01 -1.363090E+02 -3.380903E+01 -1.147695E+02 -2.903657E+01 -8.489183E+01 -2.121421E+01 -4.519765E+01 -1.112628E+01 -1.245629E+01 -tally 2: -1.114845E+00 -1.242879E+00 -8.000235E-01 -6.400375E-01 -1.852141E+00 -3.430427E+00 -1.324803E+00 -1.755104E+00 -2.585263E+00 -6.683587E+00 -1.840969E+00 -3.389167E+00 -3.737263E+00 -1.396714E+01 -2.674345E+00 -7.152122E+00 -3.989056E+00 -1.591257E+01 -2.843382E+00 -8.084820E+00 -3.951710E+00 -1.561601E+01 -2.838216E+00 -8.055468E+00 -3.734018E+00 -1.394289E+01 -2.676071E+00 -7.161356E+00 -3.241209E+00 -1.050543E+01 -2.315684E+00 -5.362392E+00 -2.459493E+00 -6.049108E+00 -1.734344E+00 -3.007949E+00 -1.079306E+00 -1.164902E+00 -7.536940E-01 -5.680547E-01 -tally 3: -7.728275E-01 -5.972624E-01 -5.550061E-02 -3.080318E-03 -1.272034E+00 -1.618070E+00 -7.284456E-02 -5.306329E-03 -1.779821E+00 -3.167762E+00 -1.110012E-01 -1.232127E-02 -2.586020E+00 -6.687502E+00 -1.618768E-01 -2.620410E-02 -2.726552E+00 -7.434084E+00 -1.965647E-01 -3.863767E-02 -2.741747E+00 -7.517178E+00 -1.907834E-01 -3.639829E-02 -2.564084E+00 -6.574527E+00 -1.503142E-01 -2.259435E-02 -2.233122E+00 -4.986832E+00 -1.456891E-01 -2.122532E-02 -1.682929E+00 -2.832250E+00 -9.828234E-02 -9.659418E-03 -7.232788E-01 -5.231322E-01 -6.128193E-02 -3.755475E-03 -tally 4: -1.326662E-01 -1.760031E-02 -0.000000E+00 -0.000000E+00 -1.369313E-01 -1.875018E-02 -2.569758E-01 -6.603657E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.569758E-01 -6.603657E-02 -1.369313E-01 -1.875018E-02 -2.494513E-01 -6.222596E-02 -3.551002E-01 -1.260962E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.551002E-01 -1.260962E-01 -2.494513E-01 -6.222596E-02 -3.610027E-01 -1.303230E-01 -4.252566E-01 -1.808432E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.252566E-01 -1.808432E-01 -3.610027E-01 -1.303230E-01 -4.673502E-01 -2.184162E-01 -5.073957E-01 -2.574504E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.073957E-01 -2.574504E-01 -4.673502E-01 -2.184162E-01 -4.818855E-01 -2.322136E-01 -4.949753E-01 -2.450006E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.949753E-01 -2.450006E-01 -4.818855E-01 -2.322136E-01 -5.176611E-01 -2.679730E-01 -4.756654E-01 -2.262576E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.756654E-01 -2.262576E-01 -5.176611E-01 -2.679730E-01 -4.591191E-01 -2.107904E-01 -3.930251E-01 -1.544688E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.930251E-01 -1.544688E-01 -4.591191E-01 -2.107904E-01 -4.201532E-01 -1.765287E-01 -3.188250E-01 -1.016494E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.188250E-01 -1.016494E-01 -4.201532E-01 -1.765287E-01 -2.898817E-01 -8.403142E-02 -1.509185E-01 -2.277639E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.509185E-01 -2.277639E-02 -2.898817E-01 -8.403142E-02 -1.482175E-01 -2.196844E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -7.719619E-01 -5.959252E-01 -8.168322E-02 -6.672148E-03 -1.272034E+00 -1.618070E+00 -1.458271E-01 -2.126554E-02 -1.779821E+00 -3.167762E+00 -2.705917E-01 -7.321987E-02 -2.584069E+00 -6.677414E+00 -3.176497E-01 -1.009013E-01 -2.726552E+00 -7.434084E+00 -3.562714E-01 -1.269293E-01 -2.740788E+00 -7.511919E+00 -3.690107E-01 -1.361689E-01 -2.563145E+00 -6.569715E+00 -3.296244E-01 -1.086523E-01 -2.233122E+00 -4.986832E+00 -3.106254E-01 -9.648813E-02 -1.682929E+00 -2.832250E+00 -2.709632E-01 -7.342104E-02 -7.232788E-01 -5.231322E-01 -9.343486E-02 -8.730073E-03 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.143597E+00 -1.163387E+00 -1.162391E+00 -1.163351E+00 -1.145721E+00 -1.134785E+00 -1.119048E+00 -1.116124E+00 -1.109085E+00 -1.126581E+00 -1.158559E+00 -1.163719E+00 -1.162162E+00 -1.160856E+00 -1.166709E+00 -1.167223E+00 -cmfd entropy -3.212002E+00 -3.206393E+00 -3.222109E+00 -3.221996E+00 -3.229978E+00 -3.234615E+00 -3.246512E+00 -3.244634E+00 -3.244312E+00 -3.236922E+00 -3.232693E+00 -3.221849E+00 -3.215716E+00 -3.215968E+00 -3.203758E+00 -3.201798E+00 -cmfd balance -8.26180E-03 -4.27338E-03 -2.62159E-03 -2.40301E-03 -2.08484E-03 -1.58351E-03 -1.59196E-03 -1.87591E-03 -1.94451E-03 -1.91803E-03 -1.90044E-03 -1.87968E-03 -2.55363E-03 -2.39932E-03 -2.25515E-03 -1.53613E-03 -cmfd dominance ratio -5.404E-01 -5.406E-01 -5.432E-01 -5.454E-01 -5.507E-01 -5.578E-01 -5.679E-01 -5.671E-01 -5.690E-01 -5.637E-01 -5.575E-01 -5.474E-01 -5.480E-01 -5.467E-01 -5.374E-01 -5.321E-01 -cmfd openmc source comparison -1.575499E-02 -1.293688E-02 -5.920734E-03 -9.746850E-03 -7.183896E-03 -7.693485E-03 -4.158805E-03 -2.962505E-03 -4.415044E-03 -2.304495E-03 -7.921580E-03 -8.609203E-03 -8.945198E-03 -8.054204E-03 -1.164189E-02 -5.945645E-03 -cmfd source -4.077779E-02 -6.659143E-02 -1.017198E-01 -1.172269E-01 -1.458410E-01 -1.559801E-01 -1.337001E-01 -1.137262E-01 -8.397376E-02 -4.046290E-02 diff --git a/tests/regression_tests/cmfd_feed_rolling_window/settings.xml b/tests/regression_tests/cmfd_feed_rolling_window/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml b/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_feed_rolling_window/test.py b/tests/regression_tests/cmfd_feed_rolling_window/test.py deleted file mode 100644 index 802b5b700..000000000 --- a/tests/regression_tests/cmfd_feed_rolling_window/test.py +++ /dev/null @@ -1,27 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd - - -def test_cmfd_feed_rolling_window(): - """Test 1 group CMFD solver with CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 10 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.window_type = 'rolling' - cmfd_run.window_size = 5 - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_nofeed/__init__.py b/tests/regression_tests/cmfd_nofeed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_nofeed/geometry.xml b/tests/regression_tests/cmfd_nofeed/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_nofeed/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_nofeed/materials.xml b/tests/regression_tests/cmfd_nofeed/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_nofeed/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_nofeed/results_true.dat b/tests/regression_tests/cmfd_nofeed/results_true.dat deleted file mode 100644 index 81907cba2..000000000 --- a/tests/regression_tests/cmfd_nofeed/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.167381E+00 9.433835E-03 -tally 1: -1.196137E+01 -1.442469E+01 -2.133858E+01 -4.600709E+01 -2.874353E+01 -8.287541E+01 -3.400779E+01 -1.158949E+02 -3.736442E+01 -1.398466E+02 -3.705095E+01 -1.376767E+02 -3.486173E+01 -1.220362E+02 -2.910935E+01 -8.507178E+01 -2.034762E+01 -4.156717E+01 -1.074969E+01 -1.160731E+01 -tally 2: -2.321994E+01 -2.726751E+01 -1.624000E+01 -1.334217E+01 -4.184801E+01 -8.813954E+01 -2.955600E+01 -4.401685E+01 -5.620224E+01 -1.589242E+02 -3.981400E+01 -7.983679E+01 -6.834724E+01 -2.342245E+02 -4.869600E+01 -1.189597E+02 -7.481522E+01 -2.802998E+02 -5.346500E+01 -1.431835E+02 -7.381412E+01 -2.733775E+02 -5.269700E+01 -1.393729E+02 -6.907776E+01 -2.396752E+02 -4.918500E+01 -1.215909E+02 -5.783261E+01 -1.680814E+02 -4.107800E+01 -8.480751E+01 -4.120212E+01 -8.516647E+01 -2.930300E+01 -4.310295E+01 -2.228419E+01 -2.504034E+01 -1.554100E+01 -1.217931E+01 -tally 3: -1.561100E+01 -1.233967E+01 -1.095984E+00 -6.181385E-02 -2.847800E+01 -4.088161E+01 -1.815209E+00 -1.669969E-01 -3.834200E+01 -7.408022E+01 -2.446116E+00 -3.017833E-01 -4.687600E+01 -1.102381E+02 -2.954924E+00 -4.412808E-01 -5.155100E+01 -1.331461E+02 -3.204713E+00 -5.178543E-01 -5.067700E+01 -1.289238E+02 -3.246709E+00 -5.326372E-01 -4.738600E+01 -1.128834E+02 -3.035962E+00 -4.640209E-01 -3.953600E+01 -7.858196E+01 -2.507574E+00 -3.186455E-01 -2.819300E+01 -3.991455E+01 -1.846612E+00 -1.725570E-01 -1.497500E+01 -1.131312E+01 -9.213727E-01 -4.422000E-02 -tally 4: -3.090000E+00 -4.810640E-01 -0.000000E+00 -0.000000E+00 -2.833000E+00 -4.078910E-01 -5.555000E+00 -1.551579E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.555000E+00 -1.551579E+00 -2.833000E+00 -4.078910E-01 -5.095000E+00 -1.310819E+00 -7.271000E+00 -2.659755E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.271000E+00 -2.659755E+00 -5.095000E+00 -1.310819E+00 -7.026000E+00 -2.486552E+00 -8.577000E+00 -3.703215E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.577000E+00 -3.703215E+00 -7.026000E+00 -2.486552E+00 -8.572000E+00 -3.680852E+00 -9.393000E+00 -4.422429E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.393000E+00 -4.422429E+00 -8.572000E+00 -3.680852E+00 -9.261000E+00 -4.304411E+00 -9.265000E+00 -4.305625E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.265000E+00 -4.305625E+00 -9.261000E+00 -4.304411E+00 -9.303000E+00 -4.350791E+00 -8.535000E+00 -3.659395E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.535000E+00 -3.659395E+00 -9.303000E+00 -4.350791E+00 -8.693000E+00 -3.799545E+00 -7.104000E+00 -2.544182E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.104000E+00 -2.544182E+00 -8.693000E+00 -3.799545E+00 -7.334000E+00 -2.700052E+00 -5.168000E+00 -1.344390E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.168000E+00 -1.344390E+00 -7.334000E+00 -2.700052E+00 -5.416000E+00 -1.471086E+00 -2.724000E+00 -3.745680E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.724000E+00 -3.745680E-01 -5.416000E+00 -1.471086E+00 -2.960000E+00 -4.397840E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -1.560800E+01 -1.233482E+01 -2.239367E+00 -2.607315E-01 -2.847600E+01 -4.087518E+01 -3.937924E+00 -7.877545E-01 -3.833600E+01 -7.405661E+01 -5.183337E+00 -1.367303E+00 -4.686600E+01 -1.101919E+02 -6.288549E+00 -1.997858E+00 -5.154500E+01 -1.331141E+02 -6.691123E+00 -2.252645E+00 -5.067000E+01 -1.288871E+02 -6.846095E+00 -2.360683E+00 -4.737700E+01 -1.128379E+02 -6.400076E+00 -2.073871E+00 -3.952800E+01 -7.854943E+01 -5.269220E+00 -1.404986E+00 -2.818600E+01 -3.989536E+01 -3.730803E+00 -7.015777E-01 -1.497300E+01 -1.131008E+01 -2.126451E+00 -2.315275E-01 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.170416E+00 -1.172572E+00 -1.171159E+00 -1.170281E+00 -1.159698E+00 -1.151967E+00 -1.146706E+00 -1.147136E+00 -1.152154E+00 -1.156980E+00 -1.156370E+00 -1.155974E+00 -1.155295E+00 -1.154881E+00 -1.153714E+00 -1.159485E+00 -cmfd entropy -3.203643E+00 -3.204555E+00 -3.210935E+00 -3.213980E+00 -3.219204E+00 -3.222234E+00 -3.226210E+00 -3.226808E+00 -3.224445E+00 -3.222460E+00 -3.222458E+00 -3.222447E+00 -3.220832E+00 -3.220841E+00 -3.221580E+00 -3.220523E+00 -cmfd balance -4.00906E-03 -4.86966E-03 -2.99729E-03 -2.71119E-03 -1.68833E-03 -1.85540E-03 -1.40398E-03 -1.39843E-03 -1.81840E-03 -1.45825E-03 -1.43788E-03 -1.27684E-03 -1.28904E-03 -1.33030E-03 -1.14000E-03 -1.23365E-03 -cmfd dominance ratio -5.397E-01 -5.405E-01 -5.412E-01 -5.428E-01 -5.460E-01 -4.530E-01 -5.528E-01 -5.531E-01 -5.493E-01 -5.468E-01 -5.482E-01 -5.487E-01 -5.471E-01 -5.465E-01 -5.461E-01 -5.443E-01 -cmfd openmc source comparison -6.959834E-03 -5.494667E-03 -4.076255E-03 -4.451119E-03 -3.035588E-03 -3.391772E-03 -1.907994E-03 -2.482495E-03 -2.994916E-03 -3.104682E-03 -2.309343E-03 -2.151358E-03 -2.348849E-03 -1.976731E-03 -2.080638E-03 -2.301327E-03 -cmfd source -4.638920E-02 -7.751172E-02 -1.056089E-01 -1.282509E-01 -1.396713E-01 -1.415740E-01 -1.323405E-01 -1.092839E-01 -7.981779E-02 -3.955174E-02 diff --git a/tests/regression_tests/cmfd_nofeed/settings.xml b/tests/regression_tests/cmfd_nofeed/settings.xml deleted file mode 100644 index 24b0b6ab5..000000000 --- a/tests/regression_tests/cmfd_nofeed/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - diff --git a/tests/regression_tests/cmfd_nofeed/tallies.xml b/tests/regression_tests/cmfd_nofeed/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_nofeed/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_nofeed/test.py b/tests/regression_tests/cmfd_nofeed/test.py deleted file mode 100644 index 7d0895c2f..000000000 --- a/tests/regression_tests/cmfd_nofeed/test.py +++ /dev/null @@ -1,26 +0,0 @@ -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd -import numpy as np - - -def test_cmfd_nofeed(): - """Test 1 group CMFD solver without CMFD feedback""" - # Initialize and set CMFD mesh - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - - # Initialize and run CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.display = {'dominance': True} - cmfd_run.feedback = False - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run() - - # Initialize and run CMFD test harness - harness = CMFDTestHarness('statepoint.20.h5', cmfd_run) - harness.main() diff --git a/tests/regression_tests/cmfd_restart/__init__.py b/tests/regression_tests/cmfd_restart/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/cmfd_restart/geometry.xml b/tests/regression_tests/cmfd_restart/geometry.xml deleted file mode 100644 index 73ea679c4..000000000 --- a/tests/regression_tests/cmfd_restart/geometry.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - 0 - -1 2 -3 4 -5 6 - 1 - - - - - x-plane - 10 - vacuum - - - x-plane - -10 - vacuum - - - y-plane - 1 - reflective - - - y-plane - -1 - reflective - - - z-plane - 1 - reflective - - - z-plane - -1 - reflective - - - diff --git a/tests/regression_tests/cmfd_restart/materials.xml b/tests/regression_tests/cmfd_restart/materials.xml deleted file mode 100644 index 70580e3a8..000000000 --- a/tests/regression_tests/cmfd_restart/materials.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/regression_tests/cmfd_restart/results_true.dat b/tests/regression_tests/cmfd_restart/results_true.dat deleted file mode 100644 index 4a2c6eea2..000000000 --- a/tests/regression_tests/cmfd_restart/results_true.dat +++ /dev/null @@ -1,488 +0,0 @@ -k-combined: -1.169891E+00 6.289489E-03 -tally 1: -1.173922E+01 -1.385461E+01 -2.164076E+01 -4.699368E+01 -2.906462E+01 -8.464937E+01 -3.382312E+01 -1.147095E+02 -3.632006E+01 -1.323878E+02 -3.655413E+01 -1.341064E+02 -3.347757E+01 -1.124264E+02 -2.931336E+01 -8.607239E+01 -2.182947E+01 -4.789565E+01 -1.147668E+01 -1.325716E+01 -tally 2: -2.298190E+01 -2.667071E+01 -1.600292E+01 -1.293670E+01 -4.268506E+01 -9.161216E+01 -3.022909E+01 -4.598915E+01 -5.680399E+01 -1.623879E+02 -4.033805E+01 -8.196263E+01 -6.814742E+01 -2.331778E+02 -4.851618E+01 -1.182330E+02 -7.392923E+01 -2.740255E+02 -5.253586E+01 -1.384152E+02 -7.332860E+01 -2.698608E+02 -5.227405E+01 -1.371810E+02 -6.830172E+01 -2.340687E+02 -4.867159E+01 -1.188724E+02 -5.885634E+01 -1.736180E+02 -4.170434E+01 -8.719622E+01 -4.371848E+01 -9.592893E+01 -3.106403E+01 -4.844308E+01 -2.338413E+01 -2.752467E+01 -1.636713E+01 -1.347770E+01 -tally 3: -1.538752E+01 -1.196478E+01 -1.079685E+00 -6.010786E-02 -2.911906E+01 -4.269070E+01 -1.822657E+00 -1.671850E-01 -3.885421E+01 -7.608218E+01 -2.541516E+00 -3.262451E-01 -4.673300E+01 -1.097036E+02 -2.885307E+00 -4.214444E-01 -5.059247E+01 -1.283984E+02 -3.222796E+00 -5.237329E-01 -5.034856E+01 -1.272538E+02 -3.230225E+00 -5.273424E-01 -4.688476E+01 -1.103152E+02 -2.941287E+00 -4.363749E-01 -4.013746E+01 -8.077506E+01 -2.634234E+00 -3.520270E-01 -2.996887E+01 -4.509953E+01 -1.946504E+00 -1.919104E-01 -1.575260E+01 -1.248707E+01 -1.020705E+00 -5.413569E-02 -tally 4: -3.049469E+00 -4.677325E-01 -0.000000E+00 -0.000000E+00 -2.770358E+00 -3.879191E-01 -5.514939E+00 -1.528899E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.514939E+00 -1.528899E+00 -2.770358E+00 -3.879191E-01 -5.032131E+00 -1.275040E+00 -7.294002E+00 -2.675589E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.294002E+00 -2.675589E+00 -5.032131E+00 -1.275040E+00 -7.036008E+00 -2.490718E+00 -8.668860E+00 -3.776102E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.668860E+00 -3.776102E+00 -7.036008E+00 -2.490718E+00 -8.352414E+00 -3.501945E+00 -9.345868E+00 -4.380719E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.345868E+00 -4.380719E+00 -8.352414E+00 -3.501945E+00 -9.093766E+00 -4.158282E+00 -9.223771E+00 -4.270120E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.223771E+00 -4.270120E+00 -9.093766E+00 -4.158282E+00 -9.219150E+00 -4.264346E+00 -8.530966E+00 -3.651778E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.530966E+00 -3.651778E+00 -9.219150E+00 -4.264346E+00 -8.690373E+00 -3.785262E+00 -7.204424E+00 -2.604203E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.204424E+00 -2.604203E+00 -8.690373E+00 -3.785262E+00 -7.513640E+00 -2.833028E+00 -5.326721E+00 -1.426975E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.326721E+00 -1.426975E+00 -7.513640E+00 -2.833028E+00 -5.662215E+00 -1.607757E+00 -2.848381E+00 -4.093396E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.848381E+00 -4.093396E-01 -5.662215E+00 -1.607757E+00 -3.025812E+00 -4.597241E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 5: -1.538652E+01 -1.196332E+01 -2.252427E+00 -2.605738E-01 -2.911344E+01 -4.267319E+01 -3.873926E+00 -7.615035E-01 -3.884516E+01 -7.604619E+01 -5.280610E+00 -1.414008E+00 -4.672391E+01 -1.096625E+02 -6.261805E+00 -1.983205E+00 -5.058447E+01 -1.283588E+02 -6.733810E+00 -2.278242E+00 -5.033589E+01 -1.271898E+02 -6.714658E+00 -2.273652E+00 -4.687563E+01 -1.102719E+02 -6.215002E+00 -1.956978E+00 -4.013134E+01 -8.075062E+01 -5.253064E+00 -1.396224E+00 -2.996497E+01 -4.508839E+01 -3.818076E+00 -7.509442E-01 -1.574994E+01 -1.248291E+01 -2.219928E+00 -2.515492E-01 -cmfd indices -1.000000E+01 -1.000000E+00 -1.000000E+00 -1.000000E+00 -k cmfd -1.170416E+00 -1.172966E+00 -1.165537E+00 -1.170979E+00 -1.161922E+00 -1.157523E+00 -1.158873E+00 -1.162877E+00 -1.167101E+00 -1.168130E+00 -1.170570E+00 -1.168115E+00 -1.174081E+00 -1.169458E+00 -1.167848E+00 -1.165116E+00 -cmfd entropy -3.203643E+00 -3.207943E+00 -3.213367E+00 -3.214360E+00 -3.219634E+00 -3.222232E+00 -3.221744E+00 -3.224544E+00 -3.225990E+00 -3.227769E+00 -3.227417E+00 -3.230728E+00 -3.231662E+00 -3.233316E+00 -3.233193E+00 -3.232564E+00 -cmfd balance -4.00906E-03 -4.43177E-03 -3.15267E-03 -3.51038E-03 -2.05209E-03 -2.06865E-03 -1.50243E-03 -1.58983E-03 -1.56602E-03 -1.17001E-03 -9.50759E-04 -9.07259E-04 -1.00900E-03 -1.06470E-03 -1.16361E-03 -9.75631E-04 -cmfd dominance ratio -5.397E-01 -5.425E-01 -5.481E-01 -5.473E-01 -5.503E-01 -5.502E-01 -5.483E-01 -5.520E-01 -5.505E-01 -3.216E-01 -5.373E-01 -5.517E-01 -5.508E-01 -5.524E-01 -5.524E-01 -5.523E-01 -cmfd openmc source comparison -6.959834E-03 -5.655657E-03 -3.886186E-03 -4.035116E-03 -3.043277E-03 -5.455474E-03 -4.515310E-03 -2.439840E-03 -2.114032E-03 -2.673132E-03 -2.431749E-03 -4.330928E-03 -3.404647E-03 -3.680298E-03 -3.309620E-03 -3.705541E-03 -cmfd source -4.697085E-02 -7.920706E-02 -1.107968E-01 -1.250932E-01 -1.383930E-01 -1.380648E-01 -1.246874E-01 -1.113705E-01 -8.203754E-02 -4.337882E-02 diff --git a/tests/regression_tests/cmfd_restart/settings.xml b/tests/regression_tests/cmfd_restart/settings.xml deleted file mode 100644 index ba5495911..000000000 --- a/tests/regression_tests/cmfd_restart/settings.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - eigenvalue - 20 - 10 - 1000 - - - - - box - -10 -1 -1 10 1 1 - - - - - - 10 1 1 - -10.0 -1.0 -1.0 - 10.0 1.0 1.0 - - 10 - - - - diff --git a/tests/regression_tests/cmfd_restart/tallies.xml b/tests/regression_tests/cmfd_restart/tallies.xml deleted file mode 100644 index c86971114..000000000 --- a/tests/regression_tests/cmfd_restart/tallies.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - regular - -10 -1 -1 - 10 1 1 - 10 1 1 - - - - mesh - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/cmfd_restart/test.py b/tests/regression_tests/cmfd_restart/test.py deleted file mode 100644 index 7ed92d024..000000000 --- a/tests/regression_tests/cmfd_restart/test.py +++ /dev/null @@ -1,72 +0,0 @@ -import glob -import os -import copy - -from tests.testing_harness import CMFDTestHarness -from openmc import cmfd -import numpy as np - - -class CMFDRestartTestHarness(CMFDTestHarness): - def __init__(self, final_sp, restart_sp, cmfd_run1, cmfd_run2): - super().__init__(final_sp, cmfd_run1) - self._cmfd_restart_run = cmfd_run2 - self._restart_sp = restart_sp - - def execute_test(self): - try: - # Compare results from first CMFD run - self._test_output_created() - results = self._get_results() - results += self._cmfdrun_results - self._write_results(results) - self._compare_results() - - # Run CMFD from restart file - statepoint = glob.glob(os.path.join(os.getcwd(), self._restart_sp)) - assert len(statepoint) == 1 - statepoint = statepoint[0] - self._cmfd_restart_run.run(args=['-r', statepoint]) - - # Compare results from second CMFD run - self._test_output_created() - self._create_cmfd_result_str(self._cmfd_restart_run) - results = self._get_results() - results += self._cmfdrun_results - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - -def test_cmfd_restart(): - """Test 1 group CMFD solver with restart run""" - # Initialize and set CMFD mesh, create a copy for second run - cmfd_mesh = cmfd.CMFDMesh() - cmfd_mesh.lower_left = (-10.0, -1.0, -1.0) - cmfd_mesh.upper_right = (10.0, 1.0, 1.0) - cmfd_mesh.dimension = (10, 1, 1) - cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0) - cmfd_mesh2 = copy.deepcopy(cmfd_mesh) - - # Initialize and run first CMFDRun object - cmfd_run = cmfd.CMFDRun() - cmfd_run.mesh = cmfd_mesh - cmfd_run.tally_begin = 5 - cmfd_run.feedback_begin = 5 - cmfd_run.feedback = True - cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20] - cmfd_run.run() - - # Initialize second CMFDRun object which will be run from restart file - cmfd_run2 = cmfd.CMFDRun() - cmfd_run2.mesh = cmfd_mesh2 - cmfd_run2.tally_begin = 5 - cmfd_run2.feedback_begin = 5 - cmfd_run2.feedback = True - cmfd_run2.gauss_seidel_tolerance = [1.e-15, 1.e-20] - - # Initialize and run CMFD restart test harness - harness = CMFDRestartTestHarness('statepoint.20.h5', 'statepoint.15.h5', - cmfd_run, cmfd_run2) - harness.main() diff --git a/tests/regression_tests/complex_cell/__init__.py b/tests/regression_tests/complex_cell/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/complex_cell/geometry.xml b/tests/regression_tests/complex_cell/geometry.xml deleted file mode 100644 index a695396e0..000000000 --- a/tests/regression_tests/complex_cell/geometry.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/complex_cell/materials.xml b/tests/regression_tests/complex_cell/materials.xml deleted file mode 100644 index 69abdc96f..000000000 --- a/tests/regression_tests/complex_cell/materials.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/complex_cell/results_true.dat b/tests/regression_tests/complex_cell/results_true.dat deleted file mode 100644 index be81989f5..000000000 --- a/tests/regression_tests/complex_cell/results_true.dat +++ /dev/null @@ -1,11 +0,0 @@ -k-combined: -2.511523E-01 2.296778E-03 -tally 1: -2.578905E+00 -1.331155E+00 -2.688693E+00 -1.447929E+00 -9.863773E-01 -1.948548E-01 -1.123802E-01 -2.527537E-03 diff --git a/tests/regression_tests/complex_cell/settings.xml b/tests/regression_tests/complex_cell/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/complex_cell/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/complex_cell/tallies.xml b/tests/regression_tests/complex_cell/tallies.xml deleted file mode 100644 index e0509e6a8..000000000 --- a/tests/regression_tests/complex_cell/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - cell - 1 2 3 4 - - - - 1 - total - - - diff --git a/tests/regression_tests/complex_cell/test.py b/tests/regression_tests/complex_cell/test.py deleted file mode 100755 index 77cbd6cb7..000000000 --- a/tests/regression_tests/complex_cell/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_complex_cell(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/confidence_intervals/__init__.py b/tests/regression_tests/confidence_intervals/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/confidence_intervals/geometry.xml b/tests/regression_tests/confidence_intervals/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/confidence_intervals/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/confidence_intervals/materials.xml b/tests/regression_tests/confidence_intervals/materials.xml deleted file mode 100644 index 0965c8783..000000000 --- a/tests/regression_tests/confidence_intervals/materials.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 294 - - - - - diff --git a/tests/regression_tests/confidence_intervals/results_true.dat b/tests/regression_tests/confidence_intervals/results_true.dat deleted file mode 100644 index e519180c8..000000000 --- a/tests/regression_tests/confidence_intervals/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -2.955487E-01 7.001017E-03 -tally 1: -6.492201E+01 -5.290724E+02 diff --git a/tests/regression_tests/confidence_intervals/settings.xml b/tests/regression_tests/confidence_intervals/settings.xml deleted file mode 100644 index 09e53927d..000000000 --- a/tests/regression_tests/confidence_intervals/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - true - - eigenvalue - 10 - 2 - 100 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/confidence_intervals/tallies.xml b/tests/regression_tests/confidence_intervals/tallies.xml deleted file mode 100644 index 65ff255fb..000000000 --- a/tests/regression_tests/confidence_intervals/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - cell - 1 - - - - 1 - flux - - - diff --git a/tests/regression_tests/confidence_intervals/test.py b/tests/regression_tests/confidence_intervals/test.py deleted file mode 100755 index 322741828..000000000 --- a/tests/regression_tests/confidence_intervals/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_confidence_intervals(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/conftest.py b/tests/regression_tests/conftest.py deleted file mode 100644 index b4a764476..000000000 --- a/tests/regression_tests/conftest.py +++ /dev/null @@ -1,23 +0,0 @@ -import numpy as np -import openmc -from pkg_resources import parse_version -import pytest - - -@pytest.fixture(scope='module', autouse=True) -def numpy_version_requirement(): - assert parse_version(np.__version__) >= parse_version("1.14"), \ - "Regression tests require NumPy 1.14 or greater" - - -@pytest.fixture(scope='module', autouse=True) -def setup_regression_test(request): - # Reset autogenerated IDs assigned to OpenMC objects - openmc.reset_auto_ids() - - # Change to test directory - olddir = request.fspath.dirpath().chdir() - try: - yield - finally: - olddir.chdir() diff --git a/tests/regression_tests/create_fission_neutrons/__init__.py b/tests/regression_tests/create_fission_neutrons/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/create_fission_neutrons/inputs_true.dat b/tests/regression_tests/create_fission_neutrons/inputs_true.dat deleted file mode 100644 index b0ca89647..000000000 --- a/tests/regression_tests/create_fission_neutrons/inputs_true.dat +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - -1 -1 -1 1 1 1 - - - - false - - - - - flux - - diff --git a/tests/regression_tests/create_fission_neutrons/results_true.dat b/tests/regression_tests/create_fission_neutrons/results_true.dat deleted file mode 100644 index be7c5c438..000000000 --- a/tests/regression_tests/create_fission_neutrons/results_true.dat +++ /dev/null @@ -1,3 +0,0 @@ -tally 1: -sum = 2.056839E+02 -sum_sq = 4.244628E+03 diff --git a/tests/regression_tests/create_fission_neutrons/test.py b/tests/regression_tests/create_fission_neutrons/test.py deleted file mode 100755 index f1c1d072c..000000000 --- a/tests/regression_tests/create_fission_neutrons/test.py +++ /dev/null @@ -1,70 +0,0 @@ -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class CreateFissionNeutronsTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Material is composed of H-1 and U-235 - mat = openmc.Material(material_id=1, name='mat') - mat.set_density('atom/b-cm', 0.069335) - mat.add_nuclide('H1', 40.0) - mat.add_nuclide('U235', 1.0) - materials_file = openmc.Materials([mat]) - materials_file.export_to_xml() - - # Cell is box with reflective boundary - x1 = openmc.XPlane(surface_id=1, x0=-1) - x2 = openmc.XPlane(surface_id=2, x0=1) - y1 = openmc.YPlane(surface_id=3, y0=-1) - y2 = openmc.YPlane(surface_id=4, y0=1) - z1 = openmc.ZPlane(surface_id=5, z0=-1) - z2 = openmc.ZPlane(surface_id=6, z0=1) - for surface in [x1, x2, y1, y2, z1, z2]: - surface.boundary_type = 'reflective' - box = openmc.Cell(cell_id=1, name='box') - box.region = +x1 & -x2 & +y1 & -y2 & +z1 & -z2 - box.fill = mat - root = openmc.Universe(universe_id=0, name='root universe') - root.add_cell(box) - geometry = openmc.Geometry(root) - geometry.export_to_xml() - - # Set the running parameters - settings_file = openmc.Settings() - settings_file.run_mode = 'fixed source' - settings_file.batches = 10 - settings_file.particles = 100 - settings_file.create_fission_neutrons = False - bounds = [-1, -1, -1, 1, 1, 1] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) - watt_dist = openmc.stats.Watt() - settings_file.source = openmc.source.Source(space=uniform_dist, - energy=watt_dist) - settings_file.export_to_xml() - - # Create tallies - tallies = openmc.Tallies() - tally = openmc.Tally(1) - tally.scores = ['flux'] - tallies.append(tally) - tallies.export_to_xml() - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Write out tally data. - outstr = '' - t = sp.get_tally() - outstr += 'tally {}:\n'.format(t.id) - outstr += 'sum = {:12.6E}\n'.format(t.sum[0, 0, 0]) - outstr += 'sum_sq = {:12.6E}\n'.format(t.sum_sq[0, 0, 0]) - - return outstr - - -def test_create_fission_neutrons(): - harness = CreateFissionNeutronsTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/dagmc/__init__.py b/tests/regression_tests/dagmc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/dagmc/legacy/__init__.py b/tests/regression_tests/dagmc/legacy/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/dagmc/legacy/dagmc.h5m b/tests/regression_tests/dagmc/legacy/dagmc.h5m deleted file mode 100644 index fbbe9a34a..000000000 Binary files a/tests/regression_tests/dagmc/legacy/dagmc.h5m and /dev/null differ diff --git a/tests/regression_tests/dagmc/legacy/inputs_true.dat b/tests/regression_tests/dagmc/legacy/inputs_true.dat deleted file mode 100644 index 8ca49c324..000000000 --- a/tests/regression_tests/dagmc/legacy/inputs_true.dat +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - true - - - - - 1 - - - 1 - total - - diff --git a/tests/regression_tests/dagmc/legacy/results_true.dat b/tests/regression_tests/dagmc/legacy/results_true.dat deleted file mode 100644 index 36475c5bf..000000000 --- a/tests/regression_tests/dagmc/legacy/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -1.028803E+00 3.340602E-02 -tally 1: -8.346847E+00 -1.453407E+01 diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py deleted file mode 100644 index 963e73226..000000000 --- a/tests/regression_tests/dagmc/legacy/test.py +++ /dev/null @@ -1,49 +0,0 @@ -import openmc -import openmc.lib - -import pytest -from tests.testing_harness import PyAPITestHarness - -pytestmark = pytest.mark.skipif( - not openmc.lib._dagmc_enabled(), - reason="DAGMC CAD geometry is not enabled.") - -def test_dagmc(): - model = openmc.model.Model() - - # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 - - source_box = openmc.stats.Box([-4, -4, -4], - [ 4, 4, 4]) - source = openmc.Source(space=source_box) - - model.settings.source = source - - model.settings.dagmc = True - - # tally - tally = openmc.Tally() - tally.scores = ['total'] - tally.filters = [openmc.CellFilter(1)] - model.tallies = [tally] - - # materials - u235 = openmc.Material(name="fuel") - u235.add_nuclide('U235', 1.0, 'ao') - u235.set_density('g/cc', 11) - u235.id = 40 - - water = openmc.Material(name="water") - water.add_nuclide('H1', 2.0, 'ao') - water.add_nuclide('O16', 1.0, 'ao') - water.set_density('g/cc', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - water.id = 41 - - mats = openmc.Materials([u235, water]) - model.materials = mats - - model.export_to_xml() diff --git a/tests/regression_tests/dagmc/refl/__init__.py b/tests/regression_tests/dagmc/refl/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/dagmc/refl/dagmc.h5m b/tests/regression_tests/dagmc/refl/dagmc.h5m deleted file mode 100644 index ac788d2de..000000000 Binary files a/tests/regression_tests/dagmc/refl/dagmc.h5m and /dev/null differ diff --git a/tests/regression_tests/dagmc/refl/inputs_true.dat b/tests/regression_tests/dagmc/refl/inputs_true.dat deleted file mode 100644 index 87ceb944d..000000000 --- a/tests/regression_tests/dagmc/refl/inputs_true.dat +++ /dev/null @@ -1,23 +0,0 @@ - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - true - - - - - 1 - - - 1 - total - - diff --git a/tests/regression_tests/dagmc/refl/results_true.dat b/tests/regression_tests/dagmc/refl/results_true.dat deleted file mode 100644 index ed67e2f93..000000000 --- a/tests/regression_tests/dagmc/refl/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -2.053871E+00 7.718195E-03 -tally 1: -1.171003E+01 -2.864565E+01 diff --git a/tests/regression_tests/dagmc/refl/test.py b/tests/regression_tests/dagmc/refl/test.py deleted file mode 100644 index c451b6125..000000000 --- a/tests/regression_tests/dagmc/refl/test.py +++ /dev/null @@ -1,40 +0,0 @@ -import openmc -import openmc.lib -from openmc.stats import Box - -import pytest -from tests.testing_harness import PyAPITestHarness - -pytestmark = pytest.mark.skipif( - not openmc.lib._dagmc_enabled(), - reason="DAGMC CAD geometry is not enabled.") - -class UWUWTest(PyAPITestHarness): - - def _build_inputs(self): - model = openmc.model.Model() - - # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 - - source = openmc.Source(space=Box([-4, -4, -4], - [ 4, 4, 4])) - model.settings.source = source - - model.settings.dagmc = True - - model.settings.export_to_xml() - - # tally - tally = openmc.Tally() - tally.scores = ['total'] - tally.filters = [openmc.CellFilter(1)] - model.tallies = [tally] - - model.tallies.export_to_xml() - -def test_refl(): - harness = UWUWTest('statepoint.5.h5') - harness.main() diff --git a/tests/regression_tests/dagmc/uwuw/__init__.py b/tests/regression_tests/dagmc/uwuw/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/dagmc/uwuw/dagmc.h5m b/tests/regression_tests/dagmc/uwuw/dagmc.h5m deleted file mode 100644 index 4fbba3bb6..000000000 Binary files a/tests/regression_tests/dagmc/uwuw/dagmc.h5m and /dev/null differ diff --git a/tests/regression_tests/dagmc/uwuw/inputs_true.dat b/tests/regression_tests/dagmc/uwuw/inputs_true.dat deleted file mode 100644 index 87ceb944d..000000000 --- a/tests/regression_tests/dagmc/uwuw/inputs_true.dat +++ /dev/null @@ -1,23 +0,0 @@ - - - eigenvalue - 100 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - true - - - - - 1 - - - 1 - total - - diff --git a/tests/regression_tests/dagmc/uwuw/results_true.dat b/tests/regression_tests/dagmc/uwuw/results_true.dat deleted file mode 120000 index f09f75fa5..000000000 --- a/tests/regression_tests/dagmc/uwuw/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -../legacy/results_true.dat \ No newline at end of file diff --git a/tests/regression_tests/dagmc/uwuw/test.py b/tests/regression_tests/dagmc/uwuw/test.py deleted file mode 100644 index b4391d8e7..000000000 --- a/tests/regression_tests/dagmc/uwuw/test.py +++ /dev/null @@ -1,40 +0,0 @@ -import openmc -import openmc.lib -from openmc.stats import Box - -import pytest -from tests.testing_harness import PyAPITestHarness - -pytestmark = pytest.mark.skipif( - not openmc.lib._dagmc_enabled(), - reason="DAGMC CAD geometry is not enabled.") - -class UWUWTest(PyAPITestHarness): - - def _build_inputs(self): - model = openmc.model.Model() - - # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 - - source = openmc.Source(space=Box([-4, -4, -4], - [ 4, 4, 4])) - model.settings.source = source - - model.settings.dagmc = True - - model.settings.export_to_xml() - - # tally - tally = openmc.Tally() - tally.scores = ['total'] - tally.filters = [openmc.CellFilter(1)] - model.tallies = [tally] - - model.tallies.export_to_xml() - -def test_uwuw(): - harness = UWUWTest('statepoint.5.h5') - harness.main() diff --git a/tests/regression_tests/density/__init__.py b/tests/regression_tests/density/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/density/geometry.xml b/tests/regression_tests/density/geometry.xml deleted file mode 100644 index c305754da..000000000 --- a/tests/regression_tests/density/geometry.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/density/materials.xml b/tests/regression_tests/density/materials.xml deleted file mode 100644 index 7b49233ed..000000000 --- a/tests/regression_tests/density/materials.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/density/results_true.dat b/tests/regression_tests/density/results_true.dat deleted file mode 100644 index b8eda3af8..000000000 --- a/tests/regression_tests/density/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.102244E+00 1.114945E-02 diff --git a/tests/regression_tests/density/settings.xml b/tests/regression_tests/density/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/density/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/density/test.py b/tests/regression_tests/density/test.py deleted file mode 100644 index f3ae6b414..000000000 --- a/tests/regression_tests/density/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_density(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/deplete/example_geometry.py b/tests/regression_tests/deplete/example_geometry.py deleted file mode 100644 index f79044558..000000000 --- a/tests/regression_tests/deplete/example_geometry.py +++ /dev/null @@ -1,377 +0,0 @@ -"""An example file showing how to make a geometry. - -This particular example creates a 3x3 geometry, with 8 regular pins and one -Gd-157 2 wt-percent enriched. All pins are segmented. -""" - -from collections import OrderedDict -import math - -import numpy as np -import openmc - - -def density_to_mat(dens_dict): - """Generates an OpenMC material from a cell ID and self.number_density. - - Parameters - ---------- - dens_dict : dict - Dictionary mapping nuclide names to densities - - Returns - ------- - openmc.Material - The OpenMC material filled with nuclides. - - """ - mat = openmc.Material() - for key in dens_dict: - mat.add_nuclide(key, 1.0e-24*dens_dict[key]) - mat.set_density('sum') - - return mat - - -def generate_initial_number_density(): - """ Generates initial number density. - - These results were from a CASMO5 run in which the gadolinium pin was - loaded with 2 wt percent of Gd-157. - """ - - # Concentration to be used for all fuel pins - fuel_dict = OrderedDict() - fuel_dict['U235'] = 1.05692e21 - fuel_dict['U234'] = 1.00506e19 - fuel_dict['U238'] = 2.21371e22 - fuel_dict['O16'] = 4.62954e22 - fuel_dict['O17'] = 1.127684e20 - fuel_dict['Xe135'] = 1.0e10 - fuel_dict['Xe136'] = 1.0e10 - fuel_dict['Gd156'] = 1.0e10 - fuel_dict['Gd157'] = 1.0e10 - # fuel_dict['O18'] = 9.51352e19 # Does not exist in ENDF71, merged into 17 - - # Concentration to be used for the gadolinium fuel pin - fuel_gd_dict = OrderedDict() - fuel_gd_dict['U235'] = 1.03579e21 - fuel_gd_dict['U238'] = 2.16943e22 - fuel_gd_dict['Gd156'] = 3.95517E+10 - fuel_gd_dict['Gd157'] = 1.08156e20 - fuel_gd_dict['O16'] = 4.64035e22 - fuel_dict['Xe136'] = 1.0e10 - fuel_dict['Xe135'] = 1.0e10 - # There are a whole bunch of 1e-10 stuff here. - - # Concentration to be used for cladding - clad_dict = OrderedDict() - clad_dict['O16'] = 3.07427e20 - clad_dict['O17'] = 7.48868e17 - clad_dict['Cr50'] = 3.29620e18 - clad_dict['Cr52'] = 6.35639e19 - clad_dict['Cr53'] = 7.20763e18 - clad_dict['Cr54'] = 1.79413e18 - clad_dict['Fe54'] = 5.57350e18 - clad_dict['Fe56'] = 8.74921e19 - clad_dict['Fe57'] = 2.02057e18 - clad_dict['Fe58'] = 2.68901e17 - clad_dict['Cr50'] = 3.29620e18 - clad_dict['Cr52'] = 6.35639e19 - clad_dict['Cr53'] = 7.20763e18 - clad_dict['Cr54'] = 1.79413e18 - clad_dict['Ni58'] = 2.51631e19 - clad_dict['Ni60'] = 9.69278e18 - clad_dict['Ni61'] = 4.21338e17 - clad_dict['Ni62'] = 1.34341e18 - clad_dict['Ni64'] = 3.43127e17 - clad_dict['Zr90'] = 2.18320e22 - clad_dict['Zr91'] = 4.76104e21 - clad_dict['Zr92'] = 7.27734e21 - clad_dict['Zr94'] = 7.37494e21 - clad_dict['Zr96'] = 1.18814e21 - clad_dict['Sn112'] = 4.67352e18 - clad_dict['Sn114'] = 3.17992e18 - clad_dict['Sn115'] = 1.63814e18 - clad_dict['Sn116'] = 7.00546e19 - clad_dict['Sn117'] = 3.70027e19 - clad_dict['Sn118'] = 1.16694e20 - clad_dict['Sn119'] = 4.13872e19 - clad_dict['Sn120'] = 1.56973e20 - clad_dict['Sn122'] = 2.23076e19 - clad_dict['Sn124'] = 2.78966e19 - - # Gap concentration - # Funny enough, the example problem uses air. - gap_dict = OrderedDict() - gap_dict['O16'] = 7.86548e18 - gap_dict['O17'] = 2.99548e15 - gap_dict['N14'] = 3.38646e19 - gap_dict['N15'] = 1.23717e17 - - # Concentration to be used for coolant - # No boron - cool_dict = OrderedDict() - cool_dict['H1'] = 4.68063e22 - cool_dict['O16'] = 2.33427e22 - cool_dict['O17'] = 8.89086e18 - - # Store these dictionaries in the initial conditions dictionary - initial_density = OrderedDict() - initial_density['fuel_gd'] = fuel_gd_dict - initial_density['fuel'] = fuel_dict - initial_density['gap'] = gap_dict - initial_density['clad'] = clad_dict - initial_density['cool'] = cool_dict - - # Set up libraries to use - temperature = OrderedDict() - sab = OrderedDict() - - # Toggle betweeen MCNP and NNDC data - MCNP = False - - if MCNP: - temperature['fuel_gd'] = 900.0 - temperature['fuel'] = 900.0 - # We approximate temperature of everything as 600K, even though it was - # actually 580K. - temperature['gap'] = 600.0 - temperature['clad'] = 600.0 - temperature['cool'] = 600.0 - else: - temperature['fuel_gd'] = 293.6 - temperature['fuel'] = 293.6 - temperature['gap'] = 293.6 - temperature['clad'] = 293.6 - temperature['cool'] = 293.6 - - sab['cool'] = 'c_H_in_H2O' - - # Set up burnable materials - burn = OrderedDict() - burn['fuel_gd'] = True - burn['fuel'] = True - burn['gap'] = False - burn['clad'] = False - burn['cool'] = False - - return temperature, sab, initial_density, burn - - -def segment_pin(n_rings, n_wedges, r_fuel, r_gap, r_clad): - """ Calculates a segmented pin. - - Separates a pin with n_rings and n_wedges. All cells have equal volume. - Pin is centered at origin. - """ - - # Calculate all the volumes of interest - v_fuel = math.pi * r_fuel**2 - v_gap = math.pi * r_gap**2 - v_fuel - v_clad = math.pi * r_clad**2 - v_fuel - v_gap - v_ring = v_fuel / n_rings - v_segment = v_ring / n_wedges - - # Compute ring radiuses - r_rings = np.zeros(n_rings) - - for i in range(n_rings): - r_rings[i] = math.sqrt(1.0/(math.pi) * v_ring * (i+1)) - - # Compute thetas - theta = np.linspace(0, 2*math.pi, n_wedges + 1) - - # Compute surfaces - fuel_rings = [openmc.ZCylinder(x0=0, y0=0, r=r_rings[i]) - for i in range(n_rings)] - - fuel_wedges = [openmc.Plane(a=math.cos(theta[i]), b=math.sin(theta[i])) - for i in range(n_wedges)] - - gap_ring = openmc.ZCylinder(x0=0, y0=0, r=r_gap) - clad_ring = openmc.ZCylinder(x0=0, y0=0, r=r_clad) - - # Create cells - fuel_cells = [] - if n_wedges == 1: - for i in range(n_rings): - cell = openmc.Cell(name='fuel') - if i == 0: - cell.region = -fuel_rings[0] - else: - cell.region = +fuel_rings[i-1] & -fuel_rings[i] - fuel_cells.append(cell) - else: - for i in range(n_rings): - for j in range(n_wedges): - cell = openmc.Cell(name='fuel') - if i == 0: - if j != n_wedges-1: - cell.region = (-fuel_rings[0] - & +fuel_wedges[j] - & -fuel_wedges[j+1]) - else: - cell.region = (-fuel_rings[0] - & +fuel_wedges[j] - & -fuel_wedges[0]) - else: - if j != n_wedges-1: - cell.region = (+fuel_rings[i-1] - & -fuel_rings[i] - & +fuel_wedges[j] - & -fuel_wedges[j+1]) - else: - cell.region = (+fuel_rings[i-1] - & -fuel_rings[i] - & +fuel_wedges[j] - & -fuel_wedges[0]) - fuel_cells.append(cell) - - # Gap ring - gap_cell = openmc.Cell(name='gap') - gap_cell.region = +fuel_rings[-1] & -gap_ring - fuel_cells.append(gap_cell) - - # Clad ring - clad_cell = openmc.Cell(name='clad') - clad_cell.region = +gap_ring & -clad_ring - fuel_cells.append(clad_cell) - - # Moderator - mod_cell = openmc.Cell(name='cool') - mod_cell.region = +clad_ring - fuel_cells.append(mod_cell) - - # Form universe - fuel_u = openmc.Universe() - fuel_u.add_cells(fuel_cells) - - return fuel_u, v_segment, v_gap, v_clad - - -def generate_geometry(n_rings, n_wedges): - """ Generates example geometry. - - This function creates the initial geometry, a 9 pin reflective problem. - One pin, containing gadolinium, is discretized into sectors. - - In addition to what one would do with the general OpenMC geometry code, it - is necessary to create a dictionary, volume, that maps a cell ID to a - volume. Further, by naming cells the same as the above materials, the code - can automatically handle the mapping. - - Parameters - ---------- - n_rings : int - Number of rings to generate for the geometry - n_wedges : int - Number of wedges to generate for the geometry - """ - - pitch = 1.26197 - r_fuel = 0.412275 - r_gap = 0.418987 - r_clad = 0.476121 - - n_pin = 3 - - # This table describes the 'fuel' to actual type mapping - # It's not necessary to do it this way. Just adjust the initial conditions - # below. - mapping = ['fuel', 'fuel', 'fuel', - 'fuel', 'fuel_gd', 'fuel', - 'fuel', 'fuel', 'fuel'] - - # Form pin cell - fuel_u, v_segment, v_gap, v_clad = segment_pin(n_rings, n_wedges, r_fuel, r_gap, r_clad) - - # Form lattice - all_water_c = openmc.Cell(name='cool') - all_water_u = openmc.Universe(cells=(all_water_c, )) - - lattice = openmc.RectLattice() - lattice.pitch = [pitch]*2 - lattice.lower_left = [-pitch*n_pin/2, -pitch*n_pin/2] - lattice_array = [[fuel_u for i in range(n_pin)] for j in range(n_pin)] - lattice.universes = lattice_array - lattice.outer = all_water_u - - # Bound universe - x_low = openmc.XPlane(-pitch*n_pin/2, 'reflective') - x_high = openmc.XPlane(pitch*n_pin/2, 'reflective') - y_low = openmc.YPlane(-pitch*n_pin/2, 'reflective') - y_high = openmc.YPlane(pitch*n_pin/2, 'reflective') - z_low = openmc.ZPlane(-10, 'reflective') - z_high = openmc.ZPlane(10, 'reflective') - - # Compute bounding box - lower_left = [-pitch*n_pin/2, -pitch*n_pin/2, -10] - upper_right = [pitch*n_pin/2, pitch*n_pin/2, 10] - - root_c = openmc.Cell(fill=lattice) - root_c.region = (+x_low & -x_high - & +y_low & -y_high - & +z_low & -z_high) - root_u = openmc.Universe(universe_id=0, cells=(root_c, )) - geometry = openmc.Geometry(root_u) - - v_cool = pitch**2 - (v_gap + v_clad + n_rings * n_wedges * v_segment) - - # Store volumes for later usage - volume = {'fuel': v_segment, 'gap': v_gap, 'clad': v_clad, 'cool': v_cool} - - return geometry, volume, mapping, lower_left, upper_right - - -def generate_problem(n_rings=5, n_wedges=8): - """ Merges geometry and materials. - - This function initializes the materials for each cell using the dictionaries - provided by generate_initial_number_density. It is assumed a cell named - 'fuel' will have further region differentiation (see mapping). - - Parameters - ---------- - n_rings : int, optional - Number of rings to generate for the geometry - n_wedges : int, optional - Number of wedges to generate for the geometry - """ - - # Get materials dictionary, geometry, and volumes - temperature, sab, initial_density, burn = generate_initial_number_density() - geometry, volume, mapping, lower_left, upper_right = generate_geometry(n_rings, n_wedges) - - # Apply distribmats, fill geometry - cells = geometry.root_universe.get_all_cells() - for cell_id in cells: - cell = cells[cell_id] - if cell.name == 'fuel': - - omc_mats = [] - - for cell_type in mapping: - omc_mat = density_to_mat(initial_density[cell_type]) - - if cell_type in sab: - omc_mat.add_s_alpha_beta(sab[cell_type]) - omc_mat.temperature = temperature[cell_type] - omc_mat.depletable = burn[cell_type] - omc_mat.volume = volume['fuel'] - - omc_mats.append(omc_mat) - - cell.fill = omc_mats - elif cell.name != '': - omc_mat = density_to_mat(initial_density[cell.name]) - - if cell.name in sab: - omc_mat.add_s_alpha_beta(sab[cell.name]) - omc_mat.temperature = temperature[cell.name] - omc_mat.depletable = burn[cell.name] - omc_mat.volume = volume[cell.name] - - cell.fill = omc_mat - - return geometry, lower_left, upper_right diff --git a/tests/regression_tests/deplete/test.py b/tests/regression_tests/deplete/test.py deleted file mode 100644 index 01ce21c01..000000000 --- a/tests/regression_tests/deplete/test.py +++ /dev/null @@ -1,124 +0,0 @@ -""" Full system test suite. """ - -from math import floor -import shutil -from pathlib import Path - -import numpy as np -import openmc -from openmc.data import JOULE_PER_EV -import openmc.deplete - -from tests.regression_tests import config -from example_geometry import generate_problem - - -def test_full(run_in_tmpdir): - """Full system test suite. - - Runs an entire OpenMC simulation with depletion coupling and verifies - that the outputs match a reference file. Sensitive to changes in - OpenMC. - - This test runs a complete OpenMC simulation and tests the outputs. - It will take a while. - - """ - - n_rings = 2 - n_wedges = 4 - - # Load geometry from example - geometry, lower_left, upper_right = generate_problem(n_rings, n_wedges) - - # OpenMC-specific settings - settings = openmc.Settings() - settings.particles = 100 - settings.batches = 10 - settings.inactive = 0 - space = openmc.stats.Box(lower_left, upper_right) - settings.source = openmc.Source(space=space) - settings.seed = 1 - settings.verbosity = 1 - - # Create operator - chain_file = Path(__file__).parents[2] / 'chain_simple.xml' - op = openmc.deplete.Operator(geometry, settings, chain_file) - op.round_number = True - - # Power and timesteps - dt1 = 15.*24*60*60 # 15 days - dt2 = 1.5*30*24*60*60 # 1.5 months - N = floor(dt2/dt1) - dt = np.full(N, dt1) - power = 2.337e15*4*JOULE_PER_EV*1e6 # MeV/second cm from CASMO - - # Perform simulation using the predictor algorithm - openmc.deplete.PredictorIntegrator(op, dt, power).integrate() - - # Get path to test and reference results - path_test = op.output_dir / 'depletion_results.h5' - path_reference = Path(__file__).with_name('test_reference.h5') - - # If updating results, do so and return - if config['update']: - shutil.copyfile(str(path_test), str(path_reference)) - return - - # Load the reference/test results - res_test = openmc.deplete.ResultsList.from_hdf5(path_test) - res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference) - - # Assert same mats - for mat in res_ref[0].mat_to_ind: - assert mat in res_test[0].mat_to_ind, \ - "Material {} not in new results.".format(mat) - for nuc in res_ref[0].nuc_to_ind: - assert nuc in res_test[0].nuc_to_ind, \ - "Nuclide {} not in new results.".format(nuc) - - for mat in res_test[0].mat_to_ind: - assert mat in res_ref[0].mat_to_ind, \ - "Material {} not in old results.".format(mat) - for nuc in res_test[0].nuc_to_ind: - assert nuc in res_ref[0].nuc_to_ind, \ - "Nuclide {} not in old results.".format(nuc) - - tol = 1.0e-6 - for mat in res_test[0].mat_to_ind: - for nuc in res_test[0].nuc_to_ind: - _, y_test = res_test.get_atoms(mat, nuc) - _, y_old = res_ref.get_atoms(mat, nuc) - - # Test each point - correct = True - for i, ref in enumerate(y_old): - if ref != y_test[i]: - if ref != 0.0: - correct = np.abs(y_test[i] - ref) / ref <= tol - else: - correct = False - - assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format( - mat, nuc, y_old, y_test) - - # Compare statepoint files with depletion results - - t_test, k_test = res_test.get_eigenvalue() - t_ref, k_ref = res_ref.get_eigenvalue() - k_state = np.empty_like(k_ref) - - n_tallies = np.empty(N + 1, dtype=int) - - # Get statepoint files for all BOS points and EOL - for n in range(N + 1): - statepoint = openmc.StatePoint("openmc_simulation_n{}.h5".format(n)) - k_n = statepoint.k_combined - k_state[n] = [k_n.nominal_value, k_n.std_dev] - n_tallies[n] = len(statepoint.tallies) - # Look for exact match pulling from statepoint and depletion_results - assert np.all(k_state == k_test) - assert np.allclose(k_test, k_ref) - - # Check that no additional tallies are loaded from the files - assert np.all(n_tallies == 0) diff --git a/tests/regression_tests/deplete/test_reference.h5 b/tests/regression_tests/deplete/test_reference.h5 deleted file mode 100644 index 3ee9d4447..000000000 Binary files a/tests/regression_tests/deplete/test_reference.h5 and /dev/null differ diff --git a/tests/regression_tests/diff_tally/__init__.py b/tests/regression_tests/diff_tally/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/diff_tally/inputs_true.dat b/tests/regression_tests/diff_tally/inputs_true.dat deleted file mode 100644 index 909475f96..000000000 --- a/tests/regression_tests/diff_tally/inputs_true.dat +++ /dev/null @@ -1,439 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 3 - 0 - - - -160 -160 -183 160 160 183 - - - true - - - - - 1 3 - - - 0.0 0.625 20000000.0 - - - 1 - flux - 1 - - - 1 - flux - 2 - - - 1 - flux - 3 - - - 1 - flux - 4 - - - 1 - flux - 5 - - - 1 - total U235 - total absorption scatter fission nu-fission - 1 - - - 1 - total U235 - total absorption scatter fission nu-fission - 2 - - - 1 - total U235 - total absorption scatter fission nu-fission - 3 - - - 1 - total U235 - total absorption scatter fission nu-fission - 4 - - - 1 - total U235 - total absorption scatter fission nu-fission - 5 - - - 1 - absorption - analog - 1 - - - 1 - absorption - analog - 2 - - - 1 - absorption - analog - 3 - - - 1 - absorption - analog - 4 - - - 1 - absorption - analog - 5 - - - 1 2 - total U235 - nu-fission scatter - 1 - - - 1 2 - total U235 - nu-fission scatter - 2 - - - 1 2 - U235 - nu-fission scatter - 3 - - - 1 2 - U235 - nu-fission scatter - 4 - - - 1 2 - U235 - nu-fission scatter - 5 - - - - - - - diff --git a/tests/regression_tests/diff_tally/results_true.dat b/tests/regression_tests/diff_tally/results_true.dat deleted file mode 100644 index f4c0b3d22..000000000 --- a/tests/regression_tests/diff_tally/results_true.dat +++ /dev/null @@ -1,177 +0,0 @@ -d_material,d_nuclide,d_variable,score,mean,std. dev. -3,,density,flux,-4.7291290e+00,8.8503901e-01 -3,,density,flux,-1.0533184e+01,3.0256001e+00 -1,,density,flux,-4.9634223e-01,1.3190338e-01 -1,,density,flux,-4.7458622e-01,5.6426916e-02 -1,O16,nuclide_density,flux,-1.4897399e+01,1.3583122e+01 -1,O16,nuclide_density,flux,-2.2389753e+01,1.5574833e+01 -1,U235,nuclide_density,flux,-2.8858701e+03,4.7033287e+02 -1,U235,nuclide_density,flux,-2.4203468e+03,3.2197255e+02 -1,,temperature,flux,-1.1195282e-04,3.5426553e-04 -1,,temperature,flux,-4.4294257e-04,5.4687257e-04 -3,,density,total,-1.5555916e+00,5.3353204e-01 -3,,density,absorption,1.4925823e-01,2.3501173e-01 -3,,density,scatter,-1.7048499e+00,3.3363896e-01 -3,,density,fission,1.3210038e-01,1.6377610e-01 -3,,density,nu-fission,3.1732288e-01,3.9893191e-01 -3,,density,total,1.4744448e-01,2.0435075e-01 -3,,density,absorption,1.6665433e-01,1.9696442e-01 -3,,density,scatter,-1.9209851e-02,7.8974769e-03 -3,,density,fission,1.4878594e-01,1.6616312e-01 -3,,density,nu-fission,3.6225815e-01,4.0486140e-01 -3,,density,total,1.2662462e+01,6.2596594e+00 -3,,density,absorption,2.2864287e-01,1.3031728e-01 -3,,density,scatter,1.2433820e+01,6.1294912e+00 -3,,density,fission,0.0000000e+00,0.0000000e+00 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,total,0.0000000e+00,0.0000000e+00 -3,,density,absorption,0.0000000e+00,0.0000000e+00 -3,,density,scatter,0.0000000e+00,0.0000000e+00 -3,,density,fission,0.0000000e+00,0.0000000e+00 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,total,2.9404312e-01,7.0116815e-02 -1,,density,absorption,-1.1851195e-03,1.6943078e-03 -1,,density,scatter,2.9522824e-01,6.8519874e-02 -1,,density,fission,-4.4865589e-03,2.3660449e-03 -1,,density,nu-fission,-1.0266898e-02,5.7956130e-03 -1,,density,total,-3.6990352e-03,3.5138725e-03 -1,,density,absorption,-7.0064347e-03,2.7205092e-03 -1,,density,scatter,3.3073996e-03,7.9802046e-04 -1,,density,fission,-6.3630709e-03,2.3832611e-03 -1,,density,nu-fission,-1.5466339e-02,5.8086647e-03 -1,,density,total,-5.5743331e-01,6.1625011e-02 -1,,density,absorption,-9.1430499e-03,4.0831822e-03 -1,,density,scatter,-5.4829026e-01,5.7756113e-02 -1,,density,fission,0.0000000e+00,0.0000000e+00 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,total,0.0000000e+00,0.0000000e+00 -1,,density,absorption,0.0000000e+00,0.0000000e+00 -1,,density,scatter,0.0000000e+00,0.0000000e+00 -1,,density,fission,0.0000000e+00,0.0000000e+00 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,total,3.9360816e+01,6.1390337e+00 -1,O16,nuclide_density,absorption,-6.8169613e-01,4.5302456e-01 -1,O16,nuclide_density,scatter,4.0042512e+01,6.4069240e+00 -1,O16,nuclide_density,fission,-6.1275244e-01,2.5764187e-01 -1,O16,nuclide_density,nu-fission,-1.5090099e+00,6.3048791e-01 -1,O16,nuclide_density,total,-7.5872288e-01,3.4843447e-01 -1,O16,nuclide_density,absorption,-6.7382099e-01,3.1002267e-01 -1,O16,nuclide_density,scatter,-8.4901894e-02,6.5286818e-02 -1,O16,nuclide_density,fission,-5.5597011e-01,2.7085418e-01 -1,O16,nuclide_density,nu-fission,-1.3555055e+00,6.6014209e-01 -1,O16,nuclide_density,total,-1.5539606e+01,2.3345398e+01 -1,O16,nuclide_density,absorption,-8.5880170e-02,5.0677339e-01 -1,O16,nuclide_density,scatter,-1.5453725e+01,2.2838892e+01 -1,O16,nuclide_density,fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,total,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,absorption,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,total,-7.9766848e+02,2.3476486e+02 -1,U235,nuclide_density,absorption,2.2136536e+02,5.7727802e+01 -1,U235,nuclide_density,scatter,-1.0190338e+03,1.7827380e+02 -1,U235,nuclide_density,fission,3.0782358e+02,2.4835876e+01 -1,U235,nuclide_density,nu-fission,7.5106928e+02,6.0668638e+01 -1,U235,nuclide_density,total,4.9643664e+02,3.6425359e+01 -1,U235,nuclide_density,absorption,3.8860811e+02,3.5290173e+01 -1,U235,nuclide_density,scatter,1.0782853e+02,1.9206965e+00 -1,U235,nuclide_density,fission,3.0827647e+02,2.4266512e+01 -1,U235,nuclide_density,nu-fission,7.5228267e+02,5.9109738e+01 -1,U235,nuclide_density,total,-4.7231732e+03,7.5353357e+02 -1,U235,nuclide_density,absorption,-1.1580370e+02,1.8531790e+01 -1,U235,nuclide_density,scatter,-4.6073695e+03,7.3502264e+02 -1,U235,nuclide_density,fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,total,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,absorption,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,temperature,total,5.7228698e-05,1.7465295e-04 -1,,temperature,absorption,2.9495471e-05,3.1637786e-05 -1,,temperature,scatter,2.7733227e-05,1.4323068e-04 -1,,temperature,fission,-5.6710690e-06,1.2800905e-05 -1,,temperature,nu-fission,-1.3819116e-05,3.1189136e-05 -1,,temperature,total,-5.8315815e-06,1.8705738e-05 -1,,temperature,absorption,-5.3204427e-06,1.6688104e-05 -1,,temperature,scatter,-5.1113882e-07,2.0213875e-06 -1,,temperature,fission,-5.6723578e-06,1.2800214e-05 -1,,temperature,nu-fission,-1.3822264e-05,3.1187458e-05 -1,,temperature,total,-5.5283703e-04,7.6408422e-04 -1,,temperature,absorption,-6.2179157e-06,1.0365194e-05 -1,,temperature,scatter,-5.4661912e-04,7.5373133e-04 -1,,temperature,fission,0.0000000e+00,0.0000000e+00 -1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 -1,,temperature,total,0.0000000e+00,0.0000000e+00 -1,,temperature,absorption,0.0000000e+00,0.0000000e+00 -1,,temperature,scatter,0.0000000e+00,0.0000000e+00 -1,,temperature,fission,0.0000000e+00,0.0000000e+00 -1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,absorption,3.1512670e-02,2.4627803e-01 -3,,density,absorption,1.1452915e-01,1.5733776e-01 -1,,density,absorption,-1.4010827e-03,5.7414887e-03 -1,,density,absorption,-8.9116087e-03,7.6054344e-03 -1,O16,nuclide_density,absorption,-1.0238429e+00,3.5596764e-01 -1,O16,nuclide_density,absorption,-5.4386638e-01,6.3275232e-01 -1,U235,nuclide_density,absorption,1.9740455e+02,1.1770740e+02 -1,U235,nuclide_density,absorption,-1.3873202e+02,3.0030411e+01 -1,,temperature,absorption,5.0340072e-06,2.9911538e-05 -1,,temperature,absorption,-3.7625680e-05,2.4883845e-05 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,2.5895299e-01,3.3093831e-01 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,2.4380993e-02,2.4380993e-02 -3,,density,nu-fission,1.3982705e-01,4.0427820e-01 -3,,density,scatter,-1.8460573e+00,1.6126524e-01 -3,,density,nu-fission,1.7650022e-01,4.0560218e-01 -3,,density,scatter,3.9711501e-02,4.4405692e-02 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,7.8960553e+00,4.4763896e+00 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,0.0000000e+00,0.0000000e+00 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,4.6518780e+00,1.6862698e+00 -3,,density,nu-fission,0.0000000e+00,0.0000000e+00 -3,,density,scatter,0.0000000e+00,0.0000000e+00 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,-1.4155379e-02,7.8989014e-03 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,1.0449664e-03,5.7043392e-04 -1,,density,nu-fission,-1.3723983e-02,1.5246898e-02 -1,,density,scatter,3.0959958e-01,5.7651589e-02 -1,,density,nu-fission,-1.9529210e-02,1.4804175e-02 -1,,density,scatter,5.1063052e-04,1.7748731e-03 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,-3.4116700e-01,1.4433252e-01 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,0.0000000e+00,0.0000000e+00 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,-2.0735470e-01,8.6865144e-02 -1,,density,nu-fission,0.0000000e+00,0.0000000e+00 -1,,density,scatter,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,scatter,1.4017611e-01,9.5507870e-02 -1,O16,nuclide_density,nu-fission,-8.8199871e-01,1.6570982e+00 -1,O16,nuclide_density,scatter,-1.5442745e-01,1.3136597e-01 -1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,O16,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,scatter,8.1567193e+00,5.7077716e+00 -1,U235,nuclide_density,nu-fission,7.1482113e+02,1.4806072e+02 -1,U235,nuclide_density,scatter,5.2848809e+01,1.3486619e+01 -1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,nu-fission,0.0000000e+00,0.0000000e+00 -1,U235,nuclide_density,scatter,0.0000000e+00,0.0000000e+00 -1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 -1,,temperature,scatter,-2.9956385e-07,2.8883252e-07 -1,,temperature,nu-fission,-2.1023382e-05,4.9883940e-05 -1,,temperature,scatter,5.9452821e-09,8.7655524e-09 -1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 -1,,temperature,scatter,0.0000000e+00,0.0000000e+00 -1,,temperature,nu-fission,0.0000000e+00,0.0000000e+00 -1,,temperature,scatter,0.0000000e+00,0.0000000e+00 diff --git a/tests/regression_tests/diff_tally/test.py b/tests/regression_tests/diff_tally/test.py deleted file mode 100644 index b688e6d23..000000000 --- a/tests/regression_tests/diff_tally/test.py +++ /dev/null @@ -1,118 +0,0 @@ -import glob -import os - -import pandas as pd -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -class DiffTallyTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Set settings explicitly - self._model.settings.batches = 3 - self._model.settings.inactive = 0 - self._model.settings.particles = 100 - self._model.settings.source = openmc.Source(space=openmc.stats.Box( - [-160, -160, -183], [160, 160, 183])) - self._model.settings.temperature['multipole'] = True - - filt_mats = openmc.MaterialFilter((1, 3)) - filt_eout = openmc.EnergyoutFilter((0.0, 0.625, 20.0e6)) - - # We want density derivatives for both water and fuel to get coverage - # for both fissile and non-fissile materials. - d1 = openmc.TallyDerivative(derivative_id=1) - d1.variable = 'density' - d1.material = 3 - d2 = openmc.TallyDerivative(derivative_id=2) - d2.variable = 'density' - d2.material = 1 - - # O-16 is a good nuclide to test against because it is present in both - # water and fuel. Some routines need to recognize that they have the - # perturbed nuclide but not the perturbed material. - d3 = openmc.TallyDerivative(derivative_id=3) - d3.variable = 'nuclide_density' - d3.material = 1 - d3.nuclide = 'O16' - - # A fissile nuclide, just for good measure. - d4 = openmc.TallyDerivative(derivative_id=4) - d4.variable = 'nuclide_density' - d4.material = 1 - d4.nuclide = 'U235' - - # Temperature derivatives. - d5 = openmc.TallyDerivative(derivative_id=5) - d5.variable = 'temperature' - d5.material = 1 - - derivs = [d1, d2, d3, d4, d5] - - # Cover the flux score. - for i in range(5): - t = openmc.Tally() - t.scores = ['flux'] - t.filters = [filt_mats] - t.derivative = derivs[i] - self._model.tallies.append(t) - - # Cover supported scores with a collision estimator. - for i in range(5): - t = openmc.Tally() - t.scores = ['total', 'absorption', 'scatter', 'fission', 'nu-fission'] - t.filters = [filt_mats] - t.nuclides = ['total', 'U235'] - t.derivative = derivs[i] - self._model.tallies.append(t) - - # Cover an analog estimator. - for i in range(5): - t = openmc.Tally() - t.scores = ['absorption'] - t.filters = [filt_mats] - t.estimator = 'analog' - t.derivative = derivs[i] - self._model.tallies.append(t) - - # Energyout filter and total nuclide for the density derivatives. - for i in range(2): - t = openmc.Tally() - t.scores = ['nu-fission', 'scatter'] - t.filters = [filt_mats, filt_eout] - t.nuclides = ['total', 'U235'] - t.derivative = derivs[i] - self._model.tallies.append(t) - - # Energyout filter without total nuclide for other derivatives. - for i in range(2, 5): - t = openmc.Tally() - t.scores = ['nu-fission', 'scatter'] - t.filters = [filt_mats, filt_eout] - t.nuclides = ['U235'] - t.derivative = derivs[i] - self._model.tallies.append(t) - - def _get_results(self): - # Read the statepoint and summary files. - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] - sp = openmc.StatePoint(statepoint) - - # Extract the tally data as a Pandas DataFrame. - df = pd.DataFrame() - for t in sp.tallies.values(): - df = df.append(t.get_pandas_dataframe(), ignore_index=True) - - # Extract the relevant data as a CSV string. - cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', - 'std. dev.') - return df.to_csv(None, columns=cols, index=False, float_format='%.7e') - - -def test_diff_tally(): - harness = DiffTallyTestHarness('statepoint.3.h5') - harness.main() diff --git a/tests/regression_tests/distribmat/__init__.py b/tests/regression_tests/distribmat/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/distribmat/inputs_true.dat b/tests/regression_tests/distribmat/inputs_true.dat deleted file mode 100644 index a1c1e8311..000000000 --- a/tests/regression_tests/distribmat/inputs_true.dat +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - 2.0 2.0 - 1 - 2 2 - -2.0 -2.0 - -11 11 -11 11 - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - -1 -1 -1 1 1 1 - - - - - - - 0 0 0 - 7 7 - 400 400 - - - 0 0 0 - 7 7 - 400 400 - - diff --git a/tests/regression_tests/distribmat/results_true.dat b/tests/regression_tests/distribmat/results_true.dat deleted file mode 100644 index e0143f0ff..000000000 --- a/tests/regression_tests/distribmat/results_true.dat +++ /dev/null @@ -1,9 +0,0 @@ -k-combined: -1.291341E+00 1.269393E-02 -Cell - ID = 11 - Name = - Fill = [2, None, 3, 2] - Region = -9 - Rotation = None - Translation = None diff --git a/tests/regression_tests/distribmat/test.py b/tests/regression_tests/distribmat/test.py deleted file mode 100644 index 33f64ba03..000000000 --- a/tests/regression_tests/distribmat/test.py +++ /dev/null @@ -1,104 +0,0 @@ -import openmc - -from tests.testing_harness import TestHarness, PyAPITestHarness - - -class DistribmatTestHarness(PyAPITestHarness): - def _build_inputs(self): - #################### - # Materials - #################### - - moderator = openmc.Material(material_id=1) - moderator.set_density('g/cc', 1.0) - moderator.add_nuclide('H1', 2.0) - moderator.add_nuclide('O16', 1.0) - - dense_fuel = openmc.Material(material_id=2) - dense_fuel.set_density('g/cc', 4.5) - dense_fuel.add_nuclide('U235', 1.0) - - light_fuel = openmc.Material(material_id=3) - light_fuel.set_density('g/cc', 2.0) - light_fuel.add_nuclide('U235', 1.0) - - mats_file = openmc.Materials([moderator, dense_fuel, light_fuel]) - mats_file.export_to_xml() - - #################### - # Geometry - #################### - - c1 = openmc.Cell(cell_id=1, fill=moderator) - mod_univ = openmc.Universe(universe_id=1, cells=[c1]) - - r0 = openmc.ZCylinder(r=0.3) - c11 = openmc.Cell(cell_id=11, region=-r0) - c11.fill = [dense_fuel, None, light_fuel, dense_fuel] - c12 = openmc.Cell(cell_id=12, region=+r0, fill=moderator) - fuel_univ = openmc.Universe(universe_id=11, cells=[c11, c12]) - - lat = openmc.RectLattice(lattice_id=101) - lat.lower_left = [-2.0, -2.0] - lat.pitch = [2.0, 2.0] - lat.universes = [[fuel_univ]*2]*2 - lat.outer = mod_univ - - x0 = openmc.XPlane(x0=-3.0) - x1 = openmc.XPlane(x0=3.0) - y0 = openmc.YPlane(y0=-3.0) - y1 = openmc.YPlane(y0=3.0) - for s in [x0, x1, y0, y1]: - s.boundary_type = 'reflective' - c101 = openmc.Cell(cell_id=101, fill=lat) - c101.region = +x0 & -x1 & +y0 & -y1 - root_univ = openmc.Universe(universe_id=0, cells=[c101]) - - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() - - #################### - # Settings - #################### - - sets_file = openmc.Settings() - sets_file.batches = 5 - sets_file.inactive = 0 - sets_file.particles = 1000 - sets_file.source = openmc.Source(space=openmc.stats.Box( - [-1, -1, -1], [1, 1, 1])) - sets_file.export_to_xml() - - #################### - # Plots - #################### - - plot1 = openmc.Plot(plot_id=1) - plot1.basis = 'xy' - plot1.color_by = 'cell' - plot1.filename = 'cellplot' - plot1.origin = (0, 0, 0) - plot1.width = (7, 7) - plot1.pixels = (400, 400) - - plot2 = openmc.Plot(plot_id=2) - plot2.basis = 'xy' - plot2.color_by = 'material' - plot2.filename = 'matplot' - plot2.origin = (0, 0, 0) - plot2.width = (7, 7) - plot2.pixels = (400, 400) - - plots = openmc.Plots([plot1, plot2]) - plots.export_to_xml() - - def _get_results(self): - outstr = super()._get_results() - su = openmc.Summary('summary.h5') - outstr += str(su.geometry.get_all_cells()[11]) - return outstr - - -def test_distribmat(): - harness = DistribmatTestHarness('statepoint.5.h5') - harness.main() diff --git a/tests/regression_tests/eigenvalue_genperbatch/__init__.py b/tests/regression_tests/eigenvalue_genperbatch/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/eigenvalue_genperbatch/geometry.xml b/tests/regression_tests/eigenvalue_genperbatch/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/eigenvalue_genperbatch/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/eigenvalue_genperbatch/materials.xml b/tests/regression_tests/eigenvalue_genperbatch/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/eigenvalue_genperbatch/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/eigenvalue_genperbatch/results_true.dat b/tests/regression_tests/eigenvalue_genperbatch/results_true.dat deleted file mode 100644 index c635f03ce..000000000 --- a/tests/regression_tests/eigenvalue_genperbatch/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.001411E-01 2.669758E-03 diff --git a/tests/regression_tests/eigenvalue_genperbatch/settings.xml b/tests/regression_tests/eigenvalue_genperbatch/settings.xml deleted file mode 100644 index fefc2d059..000000000 --- a/tests/regression_tests/eigenvalue_genperbatch/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - eigenvalue - 7 - 3 - 1000 - 3 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/eigenvalue_genperbatch/test.py b/tests/regression_tests/eigenvalue_genperbatch/test.py deleted file mode 100644 index 0dfb11242..000000000 --- a/tests/regression_tests/eigenvalue_genperbatch/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_eigenvalue_genperbatch(): - harness = TestHarness('statepoint.7.h5') - harness.main() diff --git a/tests/regression_tests/eigenvalue_no_inactive/__init__.py b/tests/regression_tests/eigenvalue_no_inactive/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/eigenvalue_no_inactive/geometry.xml b/tests/regression_tests/eigenvalue_no_inactive/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/eigenvalue_no_inactive/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/eigenvalue_no_inactive/materials.xml b/tests/regression_tests/eigenvalue_no_inactive/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/eigenvalue_no_inactive/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/eigenvalue_no_inactive/results_true.dat b/tests/regression_tests/eigenvalue_no_inactive/results_true.dat deleted file mode 100644 index b43590022..000000000 --- a/tests/regression_tests/eigenvalue_no_inactive/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.080573E-01 6.889652E-03 diff --git a/tests/regression_tests/eigenvalue_no_inactive/settings.xml b/tests/regression_tests/eigenvalue_no_inactive/settings.xml deleted file mode 100644 index f13a1665e..000000000 --- a/tests/regression_tests/eigenvalue_no_inactive/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 0 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/eigenvalue_no_inactive/test.py b/tests/regression_tests/eigenvalue_no_inactive/test.py deleted file mode 100644 index 5ab490015..000000000 --- a/tests/regression_tests/eigenvalue_no_inactive/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_eigenvalue_no_inactive(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/energy_cutoff/__init__.py b/tests/regression_tests/energy_cutoff/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/energy_cutoff/inputs_true.dat b/tests/regression_tests/energy_cutoff/inputs_true.dat deleted file mode 100644 index bb02369dc..000000000 --- a/tests/regression_tests/energy_cutoff/inputs_true.dat +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - -1 -1 -1 1 1 1 - - - - - 4.0 - - - - - - 0.0 4.0 - - - 1 - flux - - diff --git a/tests/regression_tests/energy_cutoff/results_true.dat b/tests/regression_tests/energy_cutoff/results_true.dat deleted file mode 100644 index 5ad463b77..000000000 --- a/tests/regression_tests/energy_cutoff/results_true.dat +++ /dev/null @@ -1,3 +0,0 @@ -tally 1: -sum = 0.000000E+00 -sum_sq = 0.000000E+00 diff --git a/tests/regression_tests/energy_cutoff/test.py b/tests/regression_tests/energy_cutoff/test.py deleted file mode 100755 index d76edd9a0..000000000 --- a/tests/regression_tests/energy_cutoff/test.py +++ /dev/null @@ -1,74 +0,0 @@ -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class EnergyCutoffTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Set energy cutoff - energy_cutoff = 4.0 - - # Material is composed of H-1 - mat = openmc.Material(material_id=1, name='mat') - mat.set_density('atom/b-cm', 0.069335) - mat.add_nuclide('H1', 40.0) - materials_file = openmc.Materials([mat]) - materials_file.export_to_xml() - - # Cell is box with reflective boundary - x1 = openmc.XPlane(surface_id=1, x0=-1) - x2 = openmc.XPlane(surface_id=2, x0=1) - y1 = openmc.YPlane(surface_id=3, y0=-1) - y2 = openmc.YPlane(surface_id=4, y0=1) - z1 = openmc.ZPlane(surface_id=5, z0=-1) - z2 = openmc.ZPlane(surface_id=6, z0=1) - for surface in [x1, x2, y1, y2, z1, z2]: - surface.boundary_type = 'reflective' - box = openmc.Cell(cell_id=1, name='box') - box.region = +x1 & -x2 & +y1 & -y2 & +z1 & -z2 - box.fill = mat - root = openmc.Universe(universe_id=0, name='root universe') - root.add_cell(box) - geometry = openmc.Geometry(root) - geometry.export_to_xml() - - # Set the running parameters - settings_file = openmc.Settings() - settings_file.run_mode = 'fixed source' - settings_file.batches = 10 - settings_file.particles = 100 - settings_file.cutoff = {'energy_neutron': energy_cutoff} - bounds = [-1, -1, -1, 1, 1, 1] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) - watt_dist = openmc.stats.Watt() - settings_file.source = openmc.source.Source(space=uniform_dist, - energy=watt_dist) - settings_file.export_to_xml() - - # Tally flux under energy cutoff - tallies = openmc.Tallies() - tally = openmc.Tally(1) - tally.scores = ['flux'] - energy_filter = openmc.filter.EnergyFilter((0.0, energy_cutoff)) - tally.filters = [energy_filter] - tallies.append(tally) - tallies.export_to_xml() - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Write out tally data. - outstr = '' - t = sp.get_tally() - outstr += 'tally {}:\n'.format(t.id) - outstr += 'sum = {:12.6E}\n'.format(t.sum[0, 0, 0]) - outstr += 'sum_sq = {:12.6E}\n'.format(t.sum_sq[0, 0, 0]) - - return outstr - - -def test_energy_cutoff(): - harness = EnergyCutoffTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/energy_grid/__init__.py b/tests/regression_tests/energy_grid/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/energy_grid/geometry.xml b/tests/regression_tests/energy_grid/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/energy_grid/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/energy_grid/materials.xml b/tests/regression_tests/energy_grid/materials.xml deleted file mode 100644 index 87a3b8fe1..000000000 --- a/tests/regression_tests/energy_grid/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/energy_grid/results_true.dat b/tests/regression_tests/energy_grid/results_true.dat deleted file mode 100644 index ee0a72c9d..000000000 --- a/tests/regression_tests/energy_grid/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.330787E-01 2.216487E-03 diff --git a/tests/regression_tests/energy_grid/settings.xml b/tests/regression_tests/energy_grid/settings.xml deleted file mode 100644 index 4b8d4fceb..000000000 --- a/tests/regression_tests/energy_grid/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - 20000 - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/energy_grid/test.py b/tests/regression_tests/energy_grid/test.py deleted file mode 100644 index 889bdfbc6..000000000 --- a/tests/regression_tests/energy_grid/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_energy_grid(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/energy_laws/__init__.py b/tests/regression_tests/energy_laws/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/energy_laws/inputs_true.dat b/tests/regression_tests/energy_laws/inputs_true.dat deleted file mode 100644 index 2320b21d5..000000000 --- a/tests/regression_tests/energy_laws/inputs_true.dat +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - diff --git a/tests/regression_tests/energy_laws/results_true.dat b/tests/regression_tests/energy_laws/results_true.dat deleted file mode 100644 index ce93d6c82..000000000 --- a/tests/regression_tests/energy_laws/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.466441E+00 1.500183E-02 diff --git a/tests/regression_tests/energy_laws/test.py b/tests/regression_tests/energy_laws/test.py deleted file mode 100644 index 1746b2d31..000000000 --- a/tests/regression_tests/energy_laws/test.py +++ /dev/null @@ -1,52 +0,0 @@ -"""The purpose of this test is to provide coverage of energy distributions that -are not covered in other tests. It has a single material with the following -nuclides: - -U233: Only nuclide that has a Watt fission spectrum - -Am244: One of a few nuclides that has a Maxwell fission spectrum - -H2: Only nuclide that has an N-body phase space distribution, in this case for -(n,2n) - -Na23: Has an evaporation spectrum and also has reactions that have multiple -angle-energy distributions, so it provides coverage for both of those -situations. - -Ta181: One of a few nuclides that has reactions with Kalbach-Mann distributions -that use linear-linear interpolation. - -""" - -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - m = openmc.Material() - m.set_density('g/cm3', 20.0) - m.add_nuclide('U233', 1.0) - m.add_nuclide('Am244', 1.0) - m.add_nuclide('H2', 1.0) - m.add_nuclide('Na23', 1.0) - m.add_nuclide('Ta181', 1.0) - - s = openmc.Sphere(r=100.0, boundary_type='reflective') - c = openmc.Cell(fill=m, region=-s) - model.geometry = openmc.Geometry([c]) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 1000 - - return model - - -def test_energy_laws(model): - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/enrichment/__init__.py b/tests/regression_tests/enrichment/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/enrichment/test.py b/tests/regression_tests/enrichment/test.py deleted file mode 100644 index a20838c7c..000000000 --- a/tests/regression_tests/enrichment/test.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import sys - -import numpy as np - -from openmc import Material -from openmc.data import NATURAL_ABUNDANCE, atomic_mass - - -def test_enrichment(): - # This test doesn't require an OpenMC run. We just need to make sure the - # element.expand() method expands Uranium to the proper enrichment. - - uranium = Material() - uranium.add_element('U', 1.0, 'wo', 4.95) - densities = uranium.get_nuclide_densities() - - sum_densities = 0. - for nuc in densities.keys(): - assert nuc in ('U234', 'U235', 'U236', 'U238') - sum_densities += densities[nuc][1] - - # Compute the weight percent U235 - enrichment = densities['U235'][1] / sum_densities - assert np.isclose(enrichment, 0.0495, rtol=1.e-8) - - # Compute the ratio of U234/U235 - u234_to_u235 = densities['U234'][1] / densities['U235'][1] - assert np.isclose(u234_to_u235, 0.0089, rtol=1.e-8) - - # Compute the ratio of U236/U235 - u236_to_u235 = densities['U236'][1] / densities['U235'][1] - assert np.isclose(u236_to_u235, 0.0046, rtol=1.e-8) diff --git a/tests/regression_tests/entropy/__init__.py b/tests/regression_tests/entropy/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/entropy/geometry.xml b/tests/regression_tests/entropy/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/entropy/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/entropy/materials.xml b/tests/regression_tests/entropy/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/entropy/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/entropy/results_true.dat b/tests/regression_tests/entropy/results_true.dat deleted file mode 100644 index d7901d395..000000000 --- a/tests/regression_tests/entropy/results_true.dat +++ /dev/null @@ -1,13 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 -entropy: -7.601626E+00 -8.085658E+00 -8.263983E+00 -8.284792E+00 -8.420379E+00 -8.302840E+00 -8.316079E+00 -8.299781E+00 -8.329297E+00 -8.361325E+00 diff --git a/tests/regression_tests/entropy/settings.xml b/tests/regression_tests/entropy/settings.xml deleted file mode 100644 index 493da7223..000000000 --- a/tests/regression_tests/entropy/settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - - 10 10 10 - -10. -10. -10. - 10. 10. 10. - - - 1 - - diff --git a/tests/regression_tests/entropy/test.py b/tests/regression_tests/entropy/test.py deleted file mode 100644 index 10a11e300..000000000 --- a/tests/regression_tests/entropy/test.py +++ /dev/null @@ -1,29 +0,0 @@ -import glob -import os - -from openmc import StatePoint - -from tests.testing_harness import TestHarness - - -class EntropyTestHarness(TestHarness): - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] - with StatePoint(statepoint) as sp: - # Write out k-combined. - outstr = 'k-combined:\n' - outstr += '{:12.6E} {:12.6E}\n'.format(sp.k_combined.n, sp.k_combined.s) - - # Write out entropy data. - outstr += 'entropy:\n' - results = ['{:12.6E}'.format(x) for x in sp.entropy] - outstr += '\n'.join(results) + '\n' - - return outstr - - -def test_entropy(): - harness = EntropyTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/filter_distribcell/__init__.py b/tests/regression_tests/filter_distribcell/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/filter_distribcell/case-1/geometry.xml b/tests/regression_tests/filter_distribcell/case-1/geometry.xml deleted file mode 100644 index 34e636e9f..000000000 --- a/tests/regression_tests/filter_distribcell/case-1/geometry.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - 2 2 - -2.0 -2.0 - 2.0 2.0 - 3 - - 2 2 - 2 2 - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-1/materials.xml b/tests/regression_tests/filter_distribcell/case-1/materials.xml deleted file mode 100644 index e7108b477..000000000 --- a/tests/regression_tests/filter_distribcell/case-1/materials.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-1/results_true.dat b/tests/regression_tests/filter_distribcell/case-1/results_true.dat deleted file mode 100644 index 80036a7c4..000000000 --- a/tests/regression_tests/filter_distribcell/case-1/results_true.dat +++ /dev/null @@ -1,14 +0,0 @@ -k-combined: -5.497140E-02 INF -tally 1: -1.548980E-02 -2.399339E-04 -1.426319E-02 -2.034385E-04 -1.278781E-02 -1.635280E-04 -1.018927E-02 -1.038213E-04 -tally 2: -5.273007E-02 -2.780460E-03 diff --git a/tests/regression_tests/filter_distribcell/case-1/settings.xml b/tests/regression_tests/filter_distribcell/case-1/settings.xml deleted file mode 100644 index 14c6f3020..000000000 --- a/tests/regression_tests/filter_distribcell/case-1/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 1 - 0 - 1000 - - - - -1 -1 -1 1 1 1 - - - - diff --git a/tests/regression_tests/filter_distribcell/case-1/tallies.xml b/tests/regression_tests/filter_distribcell/case-1/tallies.xml deleted file mode 100644 index 1e7061f21..000000000 --- a/tests/regression_tests/filter_distribcell/case-1/tallies.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - distribcell - 201 - - - - cell - 201 - - - - 1 - total - - - - 2 - total - - - diff --git a/tests/regression_tests/filter_distribcell/case-2/geometry.xml b/tests/regression_tests/filter_distribcell/case-2/geometry.xml deleted file mode 100644 index e3aeedd64..000000000 --- a/tests/regression_tests/filter_distribcell/case-2/geometry.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - 2 2 - -2.0 -2.0 - 2.0 2.0 - - 20 21 - 22 23 - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-2/materials.xml b/tests/regression_tests/filter_distribcell/case-2/materials.xml deleted file mode 100644 index 794d410a3..000000000 --- a/tests/regression_tests/filter_distribcell/case-2/materials.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-2/results_true.dat b/tests/regression_tests/filter_distribcell/case-2/results_true.dat deleted file mode 100644 index bbf38b3d1..000000000 --- a/tests/regression_tests/filter_distribcell/case-2/results_true.dat +++ /dev/null @@ -1,11 +0,0 @@ -k-combined: -2.149726E-02 INF -tally 1: -7.588170E-03 -5.758032E-05 -8.402485E-03 -7.060176E-05 -8.682517E-03 -7.538611E-05 -8.119996E-03 -6.593434E-05 diff --git a/tests/regression_tests/filter_distribcell/case-2/settings.xml b/tests/regression_tests/filter_distribcell/case-2/settings.xml deleted file mode 100644 index 14c6f3020..000000000 --- a/tests/regression_tests/filter_distribcell/case-2/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 1 - 0 - 1000 - - - - -1 -1 -1 1 1 1 - - - - diff --git a/tests/regression_tests/filter_distribcell/case-2/tallies.xml b/tests/regression_tests/filter_distribcell/case-2/tallies.xml deleted file mode 100644 index b2efa76a5..000000000 --- a/tests/regression_tests/filter_distribcell/case-2/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - cell - 201 203 205 207 - - - - 1 - total - - - diff --git a/tests/regression_tests/filter_distribcell/case-3/geometry.xml b/tests/regression_tests/filter_distribcell/case-3/geometry.xml deleted file mode 100644 index f6f067aad..000000000 --- a/tests/regression_tests/filter_distribcell/case-3/geometry.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 - 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - 17 17 - -10.71 -10.71 - 1.26 1.26 - - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 - 3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 - 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 - 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 - 5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - - - - 21 21 - -224.91 -224.91 - 21.42 21.42 - - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 - 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 - 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 - 7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - diff --git a/tests/regression_tests/filter_distribcell/case-3/materials.xml b/tests/regression_tests/filter_distribcell/case-3/materials.xml deleted file mode 100644 index 588912271..000000000 --- a/tests/regression_tests/filter_distribcell/case-3/materials.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-3/results_true.dat b/tests/regression_tests/filter_distribcell/case-3/results_true.dat deleted file mode 100644 index be197b5e9..000000000 --- a/tests/regression_tests/filter_distribcell/case-3/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -2ee0162762999f71ad2178936509fd9e054928023a9e0e90c078cede3ecf6583267069486adf15f1b02188333d1bfe1fc41b341bc00aab53feddd1395441f1f8 \ No newline at end of file diff --git a/tests/regression_tests/filter_distribcell/case-3/settings.xml b/tests/regression_tests/filter_distribcell/case-3/settings.xml deleted file mode 100644 index ac716f320..000000000 --- a/tests/regression_tests/filter_distribcell/case-3/settings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - eigenvalue - 3 - 0 - 100 - - - - - -160 -160 -183 - 160 160 183 - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-3/tallies.xml b/tests/regression_tests/filter_distribcell/case-3/tallies.xml deleted file mode 100644 index aed192854..000000000 --- a/tests/regression_tests/filter_distribcell/case-3/tallies.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - cell - 1 - - - - distribcell - 1 - - - - cell - 60 - - - - distribcell - 60 - - - - cell - 27 - - - - distribcell - 27 - - - - 1 - total - - - - 2 - total - - - - 3 - total - - - - 4 - total - - - - 5 - total - - - - 6 - total - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/geometry.xml b/tests/regression_tests/filter_distribcell/case-4/geometry.xml deleted file mode 100644 index c835218bc..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/geometry.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - 1.0 - 3 -
0.0 0.0
- - 1 -1 1 - 1 -1 1 - 1 -
- - - - - -
diff --git a/tests/regression_tests/filter_distribcell/case-4/materials.xml b/tests/regression_tests/filter_distribcell/case-4/materials.xml deleted file mode 100644 index 2eb744fe6..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/results_true.dat b/tests/regression_tests/filter_distribcell/case-4/results_true.dat deleted file mode 100644 index 43a837e98..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/results_true.dat +++ /dev/null @@ -1,17 +0,0 @@ -k-combined: -1.121246E-01 INF -tally 1: -2.265319E-02 -5.131668E-04 -2.026852E-02 -4.108129E-04 -2.051718E-02 -4.209546E-04 -3.015130E-02 -9.091008E-04 -2.356397E-02 -5.552605E-04 -2.558974E-02 -6.548347E-04 -2.012046E-02 -4.048329E-04 diff --git a/tests/regression_tests/filter_distribcell/case-4/settings.xml b/tests/regression_tests/filter_distribcell/case-4/settings.xml deleted file mode 100644 index f3f0779bc..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - eigenvalue - 1000 - 1 - 0 - - - -1 -1 -1 1 1 1 - - - diff --git a/tests/regression_tests/filter_distribcell/case-4/tallies.xml b/tests/regression_tests/filter_distribcell/case-4/tallies.xml deleted file mode 100644 index b923c030b..000000000 --- a/tests/regression_tests/filter_distribcell/case-4/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - distribcell - 101 - - - - 1 - total - - - diff --git a/tests/regression_tests/filter_distribcell/test.py b/tests/regression_tests/filter_distribcell/test.py deleted file mode 100644 index 028c6a779..000000000 --- a/tests/regression_tests/filter_distribcell/test.py +++ /dev/null @@ -1,73 +0,0 @@ -import glob -import os - -from tests.testing_harness import * - - -class DistribcellTestHarness(TestHarness): - def __init__(self): - super().__init__(None) - - def execute_test(self): - """Run OpenMC with the appropriate arguments and check the outputs.""" - base_dir = os.getcwd() - try: - dirs = ('case-1', '../case-2', '../case-3', '../case-4') - sps = ('statepoint.1.*', 'statepoint.1.*', 'statepoint.3.*', - 'statepoint.1.*') - tallies_out_present = (True, True, False, True) - hash_out = (False, False, True, False) - for i in range(len(dirs)): - os.chdir(dirs[i]) - self._sp_name = sps[i] - - self._run_openmc() - self._test_output_created(tallies_out_present[i]) - results = self._get_results(hash_out[i]) - self._write_results(results) - self._compare_results() - finally: - os.chdir(base_dir) - for i in range(len(dirs)): - os.chdir(dirs[i]) - self._cleanup() - - def update_results(self): - """Update the results_true using the current version of OpenMC.""" - base_dir = os.getcwd() - try: - dirs = ('case-1', '../case-2', '../case-3', '../case-4') - sps = ('statepoint.1.h5', 'statepoint.1.h5', 'statepoint.3.h5', - 'statepoint.1.h5') - tallies_out_present = (True, True, False, True) - hash_out = (False, False, True, False) - for i in range(len(dirs)): - os.chdir(dirs[i]) - self._sp_name = sps[i] - - self._run_openmc() - self._test_output_created(tallies_out_present[i]) - results = self._get_results(hash_out[i]) - self._write_results(results) - self._overwrite_results() - finally: - os.chdir(base_dir) - for i in range(len(dirs)): - os.chdir(dirs[i]) - self._cleanup() - - def _test_output_created(self, tallies_out_present): - """Make sure statepoint.* and tallies.out have been created.""" - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) - assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ - 'exist.' - assert statepoint[0].endswith('h5'), \ - 'Statepoint file is not a HDF5 file.' - if tallies_out_present: - assert os.path.exists(os.path.join(os.getcwd(), 'tallies.out')), \ - 'Tally output file does not exist.' - - -def test_filter_distribcell(): - harness = DistribcellTestHarness() - harness.main() diff --git a/tests/regression_tests/filter_energyfun/__init__.py b/tests/regression_tests/filter_energyfun/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat deleted file mode 100644 index 0f506f3f5..000000000 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 - 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 - - - Am241 - (n,gamma) - - - 1 - Am241 - (n,gamma) - - diff --git a/tests/regression_tests/filter_energyfun/results_true.dat b/tests/regression_tests/filter_energyfun/results_true.dat deleted file mode 100644 index a88cff496..000000000 --- a/tests/regression_tests/filter_energyfun/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ - energyfunction nuclide score mean std. dev. -0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.74e-01 3.55e-03 diff --git a/tests/regression_tests/filter_energyfun/test.py b/tests/regression_tests/filter_energyfun/test.py deleted file mode 100644 index f61f05d78..000000000 --- a/tests/regression_tests/filter_energyfun/test.py +++ /dev/null @@ -1,62 +0,0 @@ -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - m = openmc.Material() - m.set_density('g/cm3', 10.0) - m.add_nuclide('Am241', 1.0) - model.materials.append(m) - - s = openmc.Sphere(r=100.0, boundary_type='vacuum') - c = openmc.Cell(fill=m, region=-s) - model.geometry = openmc.Geometry([c]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - - # Define Am242m / Am242 branching ratio from ENDF/B-VII.1 data. - x = [1e-5, 3.69e-1, 1e3, 1e5, 6e5, 1e6, 2e6, 4e6, 3e7] - y = [0.1, 0.1, 0.1333, 0.158, 0.18467, 0.25618, 0.4297, 0.48, 0.48] - - # Make an EnergyFunctionFilter directly from the x and y lists. - filt1 = openmc.EnergyFunctionFilter(x, y) - - # Also make a filter with the .from_tabulated1d constructor. Make sure - # the filters are identical. - tab1d = openmc.data.Tabulated1D(x, y) - filt2 = openmc.EnergyFunctionFilter.from_tabulated1d(tab1d) - assert filt1 == filt2, 'Error with the .from_tabulated1d constructor' - - # Make tallies - tallies = [openmc.Tally(), openmc.Tally()] - for t in tallies: - t.scores = ['(n,gamma)'] - t.nuclides = ['Am241'] - tallies[1].filters = [filt1] - model.tallies.extend(tallies) - - return model - - -class FilterEnergyFunHarness(PyAPITestHarness): - def _get_results(self): - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Use tally arithmetic to compute the branching ratio. - br_tally = sp.tallies[2] / sp.tallies[1] - - # Output the tally in a Pandas DataFrame. - return br_tally.get_pandas_dataframe().to_string() + '\n' - - -def test_filter_energyfun(model): - harness = FilterEnergyFunHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/filter_mesh/__init__.py b/tests/regression_tests/filter_mesh/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/filter_mesh/inputs_true.dat b/tests/regression_tests/filter_mesh/inputs_true.dat deleted file mode 100644 index 37716c02e..000000000 --- a/tests/regression_tests/filter_mesh/inputs_true.dat +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 5 - -7.5 - 7.5 - - - 5 5 - -7.5 -7.5 - 7.5 7.5 - - - 5 5 5 - -7.5 -7.5 -7.5 - 7.5 7.5 7.5 - - - -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 - -7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5 - 1.0 1.223224374241637 1.4962778697388448 1.8302835609029084 2.2388474634702153 2.7386127875258306 3.3499379133114306 4.09772570775871 5.012437964687018 6.131336292779302 7.500000000000001 - - - 1 - - - 1 - - - 2 - - - 2 - - - 3 - - - 3 - - - 4 - - - 4 - - - 1 - total - - - 5 - current - - - 2 - total - - - 6 - current - - - 3 - total - - - 7 - current - - - 4 - total - - - 8 - current - - diff --git a/tests/regression_tests/filter_mesh/results_true.dat b/tests/regression_tests/filter_mesh/results_true.dat deleted file mode 100644 index 10ea99f64..000000000 --- a/tests/regression_tests/filter_mesh/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -c3560155c2f713e5e2ad84451ddcd40484942faf94e2829db77df9b648ea880b3fba35c2a80dd1502e1ba62843e19e746638b2fe4961bde4ded3ce98624a2447 \ No newline at end of file diff --git a/tests/regression_tests/filter_mesh/test.py b/tests/regression_tests/filter_mesh/test.py deleted file mode 100644 index c8aa871a8..000000000 --- a/tests/regression_tests/filter_mesh/test.py +++ /dev/null @@ -1,84 +0,0 @@ -import numpy as np - -import openmc -import pytest - -from tests.testing_harness import HashedPyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material() - fuel.set_density('g/cm3', 10.0) - fuel.add_nuclide('U235', 1.0) - zr = openmc.Material() - zr.set_density('g/cm3', 1.0) - zr.add_nuclide('Zr90', 1.0) - model.materials.extend([fuel, zr]) - - box1 = openmc.model.rectangular_prism(10.0, 10.0) - box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective') - top = openmc.ZPlane(z0=10.0, boundary_type='vacuum') - bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum') - cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top) - cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top) - model.geometry = openmc.Geometry([cell1, cell2]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - - # Create meshes - mesh_1d = openmc.RegularMesh() - mesh_1d.dimension = [5] - mesh_1d.lower_left = [-7.5] - mesh_1d.upper_right = [7.5] - - mesh_2d = openmc.RegularMesh() - mesh_2d.dimension = [5, 5] - mesh_2d.lower_left = [-7.5, -7.5] - mesh_2d.upper_right = [7.5, 7.5] - - mesh_3d = openmc.RegularMesh() - mesh_3d.dimension = [5, 5, 5] - mesh_3d.lower_left = [-7.5, -7.5, -7.5] - mesh_3d.upper_right = [7.5, 7.5, 7.5] - - recti_mesh = openmc.RectilinearMesh() - recti_mesh.x_grid = np.linspace(-7.5, 7.5, 18) - recti_mesh.y_grid = np.linspace(-7.5, 7.5, 18) - recti_mesh.z_grid = np.logspace(0, np.log10(7.5), 11) - - # Create filters - reg_filters = [ - openmc.MeshFilter(mesh_1d), - openmc.MeshFilter(mesh_2d), - openmc.MeshFilter(mesh_3d), - openmc.MeshFilter(recti_mesh) - ] - surf_filters = [ - openmc.MeshSurfaceFilter(mesh_1d), - openmc.MeshSurfaceFilter(mesh_2d), - openmc.MeshSurfaceFilter(mesh_3d), - openmc.MeshSurfaceFilter(recti_mesh) - ] - - # Create tallies - for f1, f2 in zip(reg_filters, surf_filters): - tally = openmc.Tally() - tally.filters = [f1] - tally.scores = ['total'] - model.tallies.append(tally) - tally = openmc.Tally() - tally.filters = [f2] - tally.scores = ['current'] - model.tallies.append(tally) - - return model - - -def test_filter_mesh(model): - harness = HashedPyAPITestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/fixed_source/__init__.py b/tests/regression_tests/fixed_source/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/fixed_source/inputs_true.dat b/tests/regression_tests/fixed_source/inputs_true.dat deleted file mode 100644 index f1aebb3b2..000000000 --- a/tests/regression_tests/fixed_source/inputs_true.dat +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - fixed source - 100 - 10 - - - 0.0 0.0 0.0 - - - 294 - - - - - flux - - diff --git a/tests/regression_tests/fixed_source/results_true.dat b/tests/regression_tests/fixed_source/results_true.dat deleted file mode 100644 index c911b4fd2..000000000 --- a/tests/regression_tests/fixed_source/results_true.dat +++ /dev/null @@ -1,6 +0,0 @@ -tally 1: -4.448476E+03 -1.984373E+06 -leakage: -9.790000E+00 -9.588300E+00 diff --git a/tests/regression_tests/fixed_source/test.py b/tests/regression_tests/fixed_source/test.py deleted file mode 100644 index 74908f87c..000000000 --- a/tests/regression_tests/fixed_source/test.py +++ /dev/null @@ -1,59 +0,0 @@ -import numpy as np - -import openmc -import openmc.stats - -from tests.testing_harness import PyAPITestHarness - - -class FixedSourceTestHarness(PyAPITestHarness): - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - outstr = '' - with openmc.StatePoint(self._sp_name) as sp: - # Write out tally data. - for i, tally_ind in enumerate(sp.tallies): - tally = sp.tallies[tally_ind] - results = np.zeros((tally.sum.size*2, )) - results[0::2] = tally.sum.ravel() - results[1::2] = tally.sum_sq.ravel() - results = ['{0:12.6E}'.format(x) for x in results] - - outstr += 'tally ' + str(i + 1) + ':\n' - outstr += '\n'.join(results) + '\n' - - gt = sp.global_tallies - outstr += 'leakage:\n' - outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum']) + '\n' - outstr += '{0:12.6E}'.format(gt[gt['name'] == b'leakage'][0]['sum_sq']) + '\n' - - return outstr - - -def test_fixed_source(): - mat = openmc.Material() - mat.add_nuclide('O16', 1.0) - mat.add_nuclide('U238', 0.0001) - mat.set_density('g/cc', 7.5) - - surf = openmc.Sphere(r=10.0, boundary_type='vacuum') - cell = openmc.Cell(fill=mat, region=-surf) - - model = openmc.model.Model() - model.geometry.root_universe = openmc.Universe(cells=[cell]) - model.materials.append(mat) - - model.settings.run_mode = 'fixed source' - model.settings.batches = 10 - model.settings.particles = 100 - model.settings.temperature = {'default': 294} - model.settings.source = openmc.Source(space=openmc.stats.Point(), - strength=10.0) - - tally = openmc.Tally() - tally.scores = ['flux'] - model.tallies.append(tally) - - harness = FixedSourceTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/infinite_cell/__init__.py b/tests/regression_tests/infinite_cell/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/infinite_cell/geometry.xml b/tests/regression_tests/infinite_cell/geometry.xml deleted file mode 100644 index 90bd2233b..000000000 --- a/tests/regression_tests/infinite_cell/geometry.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - 11 12 - 12 11 - - - - - - - diff --git a/tests/regression_tests/infinite_cell/materials.xml b/tests/regression_tests/infinite_cell/materials.xml deleted file mode 100644 index 6acd8df74..000000000 --- a/tests/regression_tests/infinite_cell/materials.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/infinite_cell/results_true.dat b/tests/regression_tests/infinite_cell/results_true.dat deleted file mode 100644 index 9e1a7a827..000000000 --- a/tests/regression_tests/infinite_cell/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.893459E-02 1.178315E-03 diff --git a/tests/regression_tests/infinite_cell/settings.xml b/tests/regression_tests/infinite_cell/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/infinite_cell/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/infinite_cell/test.py b/tests/regression_tests/infinite_cell/test.py deleted file mode 100644 index 59abec300..000000000 --- a/tests/regression_tests/infinite_cell/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_infinite_cell(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/iso_in_lab/__init__.py b/tests/regression_tests/iso_in_lab/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/iso_in_lab/inputs_true.dat b/tests/regression_tests/iso_in_lab/inputs_true.dat deleted file mode 100644 index 2a302ada6..000000000 --- a/tests/regression_tests/iso_in_lab/inputs_true.dat +++ /dev/null @@ -1,321 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - U234 U235 U238 Xe135 O16 - - - - - - - - - Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - - - - - H1 O16 B10 B11 - - - - - - - - - H1 O16 B10 B11 - - - - - - - - - - - - - - Fe54 Fe56 Fe57 Fe58 Ni58 Ni60 Mn55 Cr52 C0 Cu63 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - - - H1 O16 B10 B11 Fe54 Fe56 Fe57 Fe58 Ni58 Mn55 Cr52 - - - - - - - - - - - - - - H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - - - - - - - - - - H1 O16 B10 B11 Zr90 Zr91 Zr92 Zr94 Zr96 - - - - - eigenvalue - 100 - 10 - 5 - - - -160 -160 -183 160 160 183 - - - diff --git a/tests/regression_tests/iso_in_lab/results_true.dat b/tests/regression_tests/iso_in_lab/results_true.dat deleted file mode 100644 index 844bc2e8e..000000000 --- a/tests/regression_tests/iso_in_lab/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.672875E-01 3.577848E-02 diff --git a/tests/regression_tests/iso_in_lab/test.py b/tests/regression_tests/iso_in_lab/test.py deleted file mode 100644 index 0e8edc218..000000000 --- a/tests/regression_tests/iso_in_lab/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from tests.testing_harness import PyAPITestHarness - - -def test_iso_in_lab(): - # Force iso-in-lab scattering. - harness = PyAPITestHarness('statepoint.10.h5') - harness._model.materials.make_isotropic_in_lab() - harness.main() diff --git a/tests/regression_tests/lattice/__init__.py b/tests/regression_tests/lattice/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice/geometry.xml b/tests/regression_tests/lattice/geometry.xml deleted file mode 100644 index 809cd6fbb..000000000 --- a/tests/regression_tests/lattice/geometry.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29 29 - -0.889 -0.889 - 1.778 1.778 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice/materials.xml b/tests/regression_tests/lattice/materials.xml deleted file mode 100644 index 971f5c548..000000000 --- a/tests/regression_tests/lattice/materials.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice/results_true.dat b/tests/regression_tests/lattice/results_true.dat deleted file mode 100644 index 9def6fa33..000000000 --- a/tests/regression_tests/lattice/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.413559E-01 6.157521E-02 diff --git a/tests/regression_tests/lattice/settings.xml b/tests/regression_tests/lattice/settings.xml deleted file mode 100644 index ebe98a283..000000000 --- a/tests/regression_tests/lattice/settings.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 100 - - - - - 0. 0. 3.5560 - 21.336 21.336 94.9960 - - - - - diff --git a/tests/regression_tests/lattice/test.py b/tests/regression_tests/lattice/test.py deleted file mode 100644 index a32b9a629..000000000 --- a/tests/regression_tests/lattice/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_lattice(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/lattice_hex/__init__.py b/tests/regression_tests/lattice_hex/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_hex/geometry.xml b/tests/regression_tests/lattice_hex/geometry.xml deleted file mode 100644 index fa6a18ee1..000000000 --- a/tests/regression_tests/lattice_hex/geometry.xml +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 011 - 011 011 - 011 011 011 - 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 055 011 011 055 011 055 011 011 - 011 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 - 011 011 055 011 011 051 011 011 055 011 011 - 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 011 - 011 011 055 011 055 011 011 055 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 - 011 011 011 - 011 011 - 011 - - 011 - 011 011 - 011 011 011 - 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 055 011 011 055 011 055 011 011 - 011 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 - 011 011 055 011 011 051 011 011 055 011 011 - 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 011 - 011 011 055 011 055 011 011 055 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 - 011 011 011 - 011 011 - 011 - - 011 - 011 011 - 011 011 011 - 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 055 011 011 055 011 055 011 011 - 011 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 - 011 011 055 011 011 051 011 011 055 011 011 - 011 011 011 055 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 055 011 011 011 011 - 011 011 055 011 055 011 011 055 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 011 - 011 011 011 055 011 011 055 011 011 011 - 011 011 011 011 011 055 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 011 - 011 011 011 011 011 011 011 - 011 011 011 011 011 011 - 011 011 011 011 011 - 011 011 011 011 - 011 011 011 - 011 011 - 011 - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice_hex/materials.xml b/tests/regression_tests/lattice_hex/materials.xml deleted file mode 100644 index c7649fcf9..000000000 --- a/tests/regression_tests/lattice_hex/materials.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/lattice_hex/plots.xml b/tests/regression_tests/lattice_hex/plots.xml deleted file mode 100644 index 903d69aef..000000000 --- a/tests/regression_tests/lattice_hex/plots.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - xy_cell - 0 0 0 - 30 30 - 500 500 - - - - xy_material - 0 0 0 - 30 30 - 500 500 - - - - yz_cell - 0 0 0 - 50 400 - 500 4000 - - - - yz_material - 0 0 0 - 5 5 - 500 500 - - - diff --git a/tests/regression_tests/lattice_hex/results_true.dat b/tests/regression_tests/lattice_hex/results_true.dat deleted file mode 100644 index d83501bcf..000000000 --- a/tests/regression_tests/lattice_hex/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.562946E-01 1.530982E-02 diff --git a/tests/regression_tests/lattice_hex/settings.xml b/tests/regression_tests/lattice_hex/settings.xml deleted file mode 100644 index 0d87c3b86..000000000 --- a/tests/regression_tests/lattice_hex/settings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - eigenvalue - 10 - 5 - 500 - - - - -8.0 -8.0 -1.5 - 8.0 8.0 1.5 - - - diff --git a/tests/regression_tests/lattice_hex/test.py b/tests/regression_tests/lattice_hex/test.py deleted file mode 100644 index eb63f84df..000000000 --- a/tests/regression_tests/lattice_hex/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_lattice_hex(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/lattice_hex_coincident/__init__.py b/tests/regression_tests/lattice_hex_coincident/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_hex_coincident/inputs_true.dat b/tests/regression_tests/lattice_hex_coincident/inputs_true.dat deleted file mode 100644 index 0388a4f55..000000000 --- a/tests/regression_tests/lattice_hex_coincident/inputs_true.dat +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - 1.4 - 11 -
0.0 0.0
- - 10 -10 10 - 9 -10 10 - 10 -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 2 - - - -0.9899494936611666 -0.9899494936611666 0.0 0.9899494936611666 0.9899494936611666 10.0 - - - - false - - 22 - diff --git a/tests/regression_tests/lattice_hex_coincident/results_true.dat b/tests/regression_tests/lattice_hex_coincident/results_true.dat deleted file mode 100644 index 1f95edaf8..000000000 --- a/tests/regression_tests/lattice_hex_coincident/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.910374E+00 2.685991E-02 diff --git a/tests/regression_tests/lattice_hex_coincident/test.py b/tests/regression_tests/lattice_hex_coincident/test.py deleted file mode 100644 index 30bc470f2..000000000 --- a/tests/regression_tests/lattice_hex_coincident/test.py +++ /dev/null @@ -1,151 +0,0 @@ -from math import sqrt - -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class HexLatticeCoincidentTestHarness(PyAPITestHarness): - def _build_inputs(self): - materials = openmc.Materials() - - fuel_mat = openmc.Material() - fuel_mat.add_nuclide('U235', 4.9817E-03, 'ao') - materials.append(fuel_mat) - - matrix = openmc.Material() - matrix.set_density('atom/b-cm', 1.7742E-02) - matrix.add_element('C', 1.0, 'ao') - matrix.add_s_alpha_beta('c_Graphite') - materials.append(matrix) - - lead = openmc.Material(name="Lead") - lead.set_density('g/cm3', 10.32) - lead.add_nuclide('Pb204', 0.014, 'ao') - lead.add_nuclide('Pb206', 0.241, 'ao') - lead.add_nuclide('Pb207', 0.221, 'ao') - lead.add_nuclide('Pb208', 0.524, 'ao') - materials.append(lead) - - coolant = openmc.Material() - coolant.set_density('atom/b-cm', 5.4464E-04) - coolant.add_nuclide('He4', 1.0, 'ao') - materials.append(coolant) - - zirc = openmc.Material(name="Zirc4") - zirc.add_nuclide('Zr90', 2.217E-02, 'ao') - zirc.add_nuclide('Zr91', 4.781E-03, 'ao') - zirc.add_nuclide('Zr92', 7.228E-03, 'ao') - zirc.add_nuclide('Zr94', 7.169E-03, 'ao') - zirc.add_nuclide('Zr96', 1.131E-03, 'ao') - materials.append(zirc) - - materials.export_to_xml() - - ### Geometry ### - pin_rad = 0.7 # cm - assembly_pitch = 1.4 # cm - - cool_rad = 0.293 # cm - zirc_clad_thickness = 0.057 # cm - zirc_ir = cool_rad # cm - zirc_or = cool_rad + zirc_clad_thickness # cm - lead_thickness = 0.002 # cm - lead_ir = zirc_or # cm - lead_or = zirc_or + lead_thickness # cm - - cyl = openmc.ZCylinder(x0=0., y0=0., r=pin_rad) - fuel_btm = openmc.ZPlane(z0=0.0, boundary_type = 'reflective') - fuel_top = openmc.ZPlane(z0=10.0, boundary_type = 'reflective') - region = -cyl & +fuel_btm & -fuel_top - - container = openmc.Cell(region=region) - container.fill = fuel_mat - - fuel_outside = openmc.Cell() - fuel_outside.region = +cyl - fuel_outside.fill = matrix - - fuel_ch_univ = openmc.Universe(cells=[container, fuel_outside]) - - # Coolant Channel - cool_outer = openmc.ZCylinder(x0=0.0, y0=0.0, r=cool_rad) - zirc_outer = openmc.ZCylinder(x0=0.0, y0=0.0, r=zirc_or) - lead_outer = openmc.ZCylinder(x0=0.0, y0=0.0, r=lead_or) - - coolant_ch = openmc.Cell(name="coolant") - coolant_ch.region = -cool_outer & +fuel_btm & -fuel_top - coolant_ch.fill = coolant - - zirc_shell = openmc.Cell(name="zirconium_shell") - zirc_shell.region = +cool_outer & -zirc_outer & +fuel_btm & -fuel_top - zirc_shell.fill = zirc - - lead_shell = openmc.Cell(name="lead_shell") - lead_shell.region = +zirc_outer & -lead_outer & +fuel_btm & -fuel_top - lead_shell.fill = lead - - coolant_matrix = openmc.Cell(name="matrix coolant surround") - coolant_matrix.region = +lead_outer & +fuel_btm & -fuel_top - coolant_matrix.fill = matrix - - coolant_channel = [coolant_ch, zirc_shell, lead_shell, coolant_matrix] - - coolant_univ = openmc.Universe(name="coolant universe") - coolant_univ.add_cells(coolant_channel) - - half_width = assembly_pitch # cm - edge_length = (2./sqrt(3.0)) * half_width - - inf_mat = openmc.Cell() - inf_mat.fill = matrix - - inf_mat_univ = openmc.Universe(cells=[inf_mat,]) - - # a hex surface for the core to go inside of - hexprism = openmc.model.hexagonal_prism(edge_length=edge_length, - origin=(0.0, 0.0), - boundary_type = 'reflective', - orientation='x') - - pincell_only_lattice = openmc.HexLattice(name="regular fuel assembly") - pincell_only_lattice.center = (0., 0.) - pincell_only_lattice.pitch = (assembly_pitch,) - pincell_only_lattice.outer = inf_mat_univ - - # setup hex rings - ring0 = [fuel_ch_univ] - ring1 = [coolant_univ] * 6 - pincell_only_lattice.universes = [ring1, ring0] - - pincell_only_cell = openmc.Cell(name="container cell") - pincell_only_cell.region = hexprism & +fuel_btm & -fuel_top - pincell_only_cell.fill = pincell_only_lattice - - root_univ = openmc.Universe(name="root universe", cells=[pincell_only_cell,]) - - geom = openmc.Geometry(root_univ) - geom.export_to_xml() - - ### Settings ### - - settings = openmc.Settings() - settings.run_mode = 'eigenvalue' - - source = openmc.Source() - corner_dist = sqrt(2) * pin_rad - ll = [-corner_dist, -corner_dist, 0.0] - ur = [corner_dist, corner_dist, 10.0] - source.space = openmc.stats.Box(ll, ur) - source.strength = 1.0 - settings.source = source - settings.output = {'summary' : False} - settings.batches = 5 - settings.inactive = 2 - settings.particles = 1000 - settings.seed = 22 - settings.export_to_xml() - -def test_lattice_hex_coincident_surf(): - harness = HexLatticeCoincidentTestHarness('statepoint.5.h5') - harness.main() diff --git a/tests/regression_tests/lattice_hex_x/__init__.py b/tests/regression_tests/lattice_hex_x/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_hex_x/inputs_true.dat b/tests/regression_tests/lattice_hex_x/inputs_true.dat deleted file mode 100644 index b528a97b7..000000000 --- a/tests/regression_tests/lattice_hex_x/inputs_true.dat +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - 1.235 5.0 - 4 -
0.0 0.0 5.0
- - 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 1 3 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 3 1 1 1 1 3 1 1 1 3 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 -1 1 1 1 1 3 1 1 1 1 2 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 3 1 1 1 3 1 1 1 1 3 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 3 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 1 3 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 3 1 1 1 1 3 1 1 1 3 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 -1 1 1 1 1 3 1 1 1 1 2 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 3 1 1 1 3 1 1 1 1 3 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 3 1 1 1 1 3 1 1 1 1 1 - 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - -13.62546635287517 -13.62546635287517 0.0 13.62546635287517 13.62546635287517 10.0 - - - 22 - diff --git a/tests/regression_tests/lattice_hex_x/results_true.dat b/tests/regression_tests/lattice_hex_x/results_true.dat deleted file mode 100644 index a742aa0d5..000000000 --- a/tests/regression_tests/lattice_hex_x/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.355663E+00 2.896562E-02 diff --git a/tests/regression_tests/lattice_hex_x/test.py b/tests/regression_tests/lattice_hex_x/test.py deleted file mode 100644 index ecb27c9c2..000000000 --- a/tests/regression_tests/lattice_hex_x/test.py +++ /dev/null @@ -1,206 +0,0 @@ -from tests.testing_harness import PyAPITestHarness -import openmc -import numpy as np - - -class HexLatticeOXTestHarness(PyAPITestHarness): - - def _build_inputs(self): - materials = openmc.Materials() - - fuel_mat = openmc.Material(material_id=1, name="UO2") - fuel_mat.set_density('sum') - fuel_mat.add_nuclide('U235', 0.87370e-03) - fuel_mat.add_nuclide('U238', 1.87440e-02) - fuel_mat.add_nuclide('O16', 3.92350e-02) - materials.append(fuel_mat) - - coolant = openmc.Material(material_id=2, name="borated H2O") - coolant.set_density('sum') - coolant.add_nuclide('H1', 0.06694) - coolant.add_nuclide('O16', 0.03347) - coolant.add_nuclide('B10', 6.6262e-6) - coolant.add_nuclide('B11', 2.6839e-5) - materials.append(coolant) - - absorber = openmc.Material(material_id=3, name="pellet B4C") - absorber.set_density('sum') - absorber.add_nuclide('C0', 0.01966) - absorber.add_nuclide('B11', 4.7344e-6) - absorber.add_nuclide('B10', 1.9177e-5) - materials.append(absorber) - - zirc = openmc.Material(material_id=4, name="Zirc4") - zirc.set_density('sum') - zirc.add_element('Zr', 4.23e-2) - materials.append(zirc) - - materials.export_to_xml() - - # Geometry # - - pin_rad = 0.7 # cm - assembly_pitch = 1.235 # cm - hexagonal_pitch = 23.6 # cm - length = 10.0 # cm - - # Fuel pin surfaces - - cylfuelin = openmc.ZCylinder(surface_id=1, r=0.386) - cylfuelout = openmc.ZCylinder(surface_id=2, r=0.4582) - - # Fuel cells - - infcell = openmc.Cell(cell_id=1) - infcell.region = -cylfuelin - infcell.fill = fuel_mat - - clfcell = openmc.Cell(cell_id=2) - clfcell.region = -cylfuelout & +cylfuelin - clfcell.fill = zirc - - outfcell = openmc.Cell(cell_id=3) - outfcell.region = +cylfuelout - outfcell.fill = coolant - - # Fuel universe - - fuel_ch_univ = openmc.Universe(universe_id=1, name="Fuel channel", - cells=[infcell, clfcell, outfcell]) - - # Central tube surfaces - - cyltubein = openmc.ZCylinder(surface_id=3, r=0.45) - cyltubeout = openmc.ZCylinder(surface_id=4, r=0.5177) - - # Central tube cells - - inctcell = openmc.Cell(cell_id=4) - inctcell.region = -cyltubein - inctcell.fill = coolant - - clctcell = openmc.Cell(cell_id=5) - clctcell.region = -cyltubeout & +cyltubein - clctcell.fill = zirc - - outctcell = openmc.Cell(cell_id=6) - outctcell.region = +cyltubeout - outctcell.fill = coolant - - # Central tubel universe - - tube_ch_univ = openmc.Universe(universe_id=2, - name="Central tube channel", - cells=[inctcell, clctcell, outctcell]) - - # Absorber tube surfaces - - cylabsin = openmc.ZCylinder(surface_id=5, r=0.35) - cylabsout = openmc.ZCylinder(surface_id=6, r=0.41) - cylabsclin = openmc.ZCylinder(surface_id=7, r=0.545) - cylabsclout = openmc.ZCylinder(surface_id=8, r=0.6323) - - # Absorber tube cells - - inabscell = openmc.Cell(cell_id=7) - inabscell.region = -cylabsin - inabscell.fill = absorber - - clabscell = openmc.Cell(cell_id=8) - clabscell.region = -cylabsout & +cylabsin - clabscell.fill = zirc - - interabscell = openmc.Cell(cell_id=9) - interabscell.region = -cylabsclin & +cylabsout - interabscell.fill = coolant - - clatcell = openmc.Cell(cell_id=10) - clatcell.region = -cylabsclout & +cylabsclin - clatcell.fill = zirc - - outabscell = openmc.Cell(cell_id=11) - outabscell.region = +cylabsclout - outabscell.fill = coolant - - # Absorber tube universe - - abs_ch_univ = openmc.Universe(universe_id=3, - name="Central tube channel", - cells=[inabscell, clabscell, - interabscell, - clatcell, outabscell]) - # Assembly surfaces - - edge_length = (1./np.sqrt(3.0)) * hexagonal_pitch - fuel_bottom = openmc.ZPlane(surface_id=9, z0=0.0, - boundary_type='reflective') - fuel_top = openmc.ZPlane(surface_id=10, z0=length, - boundary_type='reflective') - - # a hex surface for the core to go inside of - - hexprism = openmc.model.hexagonal_prism(edge_length=edge_length, - origin=(0.0, 0.0), - boundary_type='reflective', - orientation='x') - region = hexprism & +fuel_bottom & -fuel_top - - inf_mat = openmc.Cell(cell_id=12) - inf_mat.fill = coolant - inf_mat_univ = openmc.Universe(universe_id=4, cells=[inf_mat]) - - # Fill lattice by channels - - nring = 11 - universes = [] - for ring in range(nring - 1, -1, -1): - arr = [] - arr.append(fuel_ch_univ) - for cell in range(ring * 6 - 1): - arr.append(fuel_ch_univ) - universes.append(arr) - universes[-1] = [tube_ch_univ] - channels = [(7, 2), (7, 5), (7, 8), (7, 11), (7, 14), (7, 17), (5, 0), - (4, 3), (5, 5), (4, 9), (5, 10), (4, 15), (5, 15), - (4, 21), (5, 20), (4, 27), (5, 25), (4, 33)] - for i, j in channels: - universes[i][j] = abs_ch_univ - lattice = openmc.HexLattice(name="regular fuel assembly") - lattice.orientation = "x" - lattice.center = (0., 0., length/2.0) - lattice.pitch = (assembly_pitch, length/2.0) - lattice.universes = 2*[universes] - lattice.outer = inf_mat_univ - - assembly_cell = openmc.Cell(cell_id=13, - name="container assembly cell") - assembly_cell.region = region - assembly_cell.fill = lattice - - root_univ = openmc.Universe(universe_id=5, name="root universe", - cells=[assembly_cell]) - - geom = openmc.Geometry(root_univ) - geom.export_to_xml() - - # Settings # - - settings = openmc.Settings() - settings.run_mode = 'eigenvalue' - - source = openmc.Source() - ll = [-edge_length, -edge_length, 0.0] - ur = [edge_length, edge_length, 10.0] - source.space = openmc.stats.Box(ll, ur) - source.strength = 1.0 - settings.source = source - settings.batches = 10 - settings.inactive = 5 - settings.particles = 1000 - settings.seed = 22 - settings.export_to_xml() - - -def test_lattice_hex_ox_surf(): - harness = HexLatticeOXTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/lattice_multiple/__init__.py b/tests/regression_tests/lattice_multiple/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_multiple/inputs_true.dat b/tests/regression_tests/lattice_multiple/inputs_true.dat deleted file mode 100644 index c92e841bc..000000000 --- a/tests/regression_tests/lattice_multiple/inputs_true.dat +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - 1.2 1.2 - 1 - 2 2 - -1.2 -1.2 - -2 1 -1 1 - - - 2.4 2.4 - 2 2 - -2.4 -2.4 - -4 4 -4 4 - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - diff --git a/tests/regression_tests/lattice_multiple/results_true.dat b/tests/regression_tests/lattice_multiple/results_true.dat deleted file mode 100644 index c1fa5321b..000000000 --- a/tests/regression_tests/lattice_multiple/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.831313E+00 6.958576E-04 diff --git a/tests/regression_tests/lattice_multiple/test.py b/tests/regression_tests/lattice_multiple/test.py deleted file mode 100644 index c287c0102..000000000 --- a/tests/regression_tests/lattice_multiple/test.py +++ /dev/null @@ -1,58 +0,0 @@ -import numpy as np -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - uo2 = openmc.Material(name='UO2') - uo2.set_density('g/cm3', 10.0) - uo2.add_nuclide('U235', 1.0) - uo2.add_nuclide('O16', 2.0) - water = openmc.Material(name='light water') - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.set_density('g/cm3', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - model.materials.extend([uo2, water]) - - cyl = openmc.ZCylinder(r=0.4) - big_cyl = openmc.ZCylinder(r=0.5) - pin = openmc.model.pin([cyl], [uo2, water]) - big_pin = openmc.model.pin([big_cyl], [uo2, water]) - - d = 1.2 - inner_lattice = openmc.RectLattice() - inner_lattice.lower_left = (-d, -d) - inner_lattice.pitch = (d, d) - inner_lattice.outer = pin - inner_lattice.universes = [ - [big_pin, pin], - [pin, pin], - ] - inner_cell = openmc.Cell(fill=inner_lattice) - inner_univ = openmc.Universe(cells=[inner_cell]) - - lattice = openmc.RectLattice() - lattice.lower_left = (-2*d, -2*d) - lattice.pitch = (2*d, 2*d) - lattice.universes = np.full((2, 2), inner_univ) - - box = openmc.model.rectangular_prism(4*d, 4*d, boundary_type='reflective') - main_cell = openmc.Cell(fill=lattice, region=box) - model.geometry = openmc.Geometry([main_cell]) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 1000 - - return model - - -def test_lattice_multiple(model): - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/lattice_rotated/__init__.py b/tests/regression_tests/lattice_rotated/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/lattice_rotated/inputs_true.dat b/tests/regression_tests/lattice_rotated/inputs_true.dat deleted file mode 100644 index 8ee34b4f3..000000000 --- a/tests/regression_tests/lattice_rotated/inputs_true.dat +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - 1.25 - 30 -
0.0 0.0
- - 2 - 1 1 -1 2 1 - 1 1 -1 2 1 - 1 1 -1 1 1 - 1 1 - 1 -
- - 1.25 1.25 - 30 - 4 4 - -2.5 -2.5 - -2 2 2 2 -1 1 1 1 -1 1 1 1 -1 1 1 1 - - - - - - -
- - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - 0.0 0.0 0.0 - - - diff --git a/tests/regression_tests/lattice_rotated/results_true.dat b/tests/regression_tests/lattice_rotated/results_true.dat deleted file mode 100644 index b92298cc2..000000000 --- a/tests/regression_tests/lattice_rotated/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -4.538090E-01 2.452457E-02 diff --git a/tests/regression_tests/lattice_rotated/test.py b/tests/regression_tests/lattice_rotated/test.py deleted file mode 100644 index 9cab92e1e..000000000 --- a/tests/regression_tests/lattice_rotated/test.py +++ /dev/null @@ -1,85 +0,0 @@ -import numpy as np -import openmc - -from tests.testing_harness import PyAPITestHarness - - -def rotated_lattice_model(): - model = openmc.model.Model() - - # Create some materials - fuel1 = openmc.Material() - fuel1.set_density('g/cm3', 10.0) - fuel1.add_nuclide('U235', 1.0) - fuel2 = openmc.Material() - fuel2.set_density('g/cm3', 10.0) - fuel2.add_nuclide('U238', 1.0) - water = openmc.Material() - water.set_density('g/cm3', 1.0) - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - model.materials.extend([fuel1, fuel2, water]) - - # Create universes for lattices - r_pin = openmc.ZCylinder(r=0.25) - fuel_cell = openmc.Cell(fill=fuel1, region=-r_pin) - water_cell = openmc.Cell(fill=water, region=+r_pin) - pin_universe = openmc.Universe(cells=(fuel_cell, water_cell)) - r_big_pin = openmc.ZCylinder(r=0.5) - fuel2_cell = openmc.Cell(fill=fuel2, region=-r_big_pin) - water2_cell = openmc.Cell(fill=water, region=+r_big_pin) - big_pin_universe = openmc.Universe(cells=(fuel2_cell, water2_cell)) - all_water_cell = openmc.Cell(fill=water) - outer_universe = openmc.Universe(30, cells=(all_water_cell,)) - - # Create hexagonal lattice - pitch = 1.25 - hexlat = openmc.HexLattice() - hexlat.center = (0., 0.) - hexlat.pitch = [pitch] - hexlat.outer = outer_universe - outer_ring = [big_pin_universe] + [pin_universe]*11 - middle_ring = [big_pin_universe] + [pin_universe]*5 - inner_ring = [big_pin_universe] - hexlat.universes = [outer_ring, middle_ring, inner_ring] - - # Create rectangular lattice - rectlat = openmc.RectLattice() - rectlat.center = (0., 0.) - rectlat.pitch = (pitch, pitch) - rectlat.lower_left = (-2*pitch, -2*pitch) - rectlat.outer = outer_universe - rectlat.universes = np.full((4, 4), pin_universe) - rectlat.universes[0] = big_pin_universe - - # Create cell filled with translated/rotated rectangular lattice on left - left_cyl = openmc.ZCylinder(x0=-4.0, r=4.0) - left_cell = openmc.Cell(fill=rectlat, region=-left_cyl) - left_cell.translation = (-4.0, 0.0, 0.0) - left_cell.rotation = (0.0, 0.0, 45.0) - - # Create cell filled with translated/rotated hexagonal lattice on right - right_cyl = openmc.ZCylinder(x0=4.0, r=4.0) - right_cell = openmc.Cell(fill=hexlat, region=-right_cyl) - right_cell.translation = (4.0, 0.0, 0.0) - right_cell.rotation = (0.0, 0.0, 30.0) - - # Finish up with the geometry - outer_cyl = openmc.ZCylinder(r=8.0, boundary_type='vacuum') - main_cell = openmc.Cell(fill=water, region=-outer_cyl & +left_cyl & +right_cyl) - model.geometry = openmc.Geometry([main_cell, left_cell, right_cell]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - model.settings.source = openmc.Source(space=openmc.stats.Point()) - model.settings.export_to_xml() - - return model - - -def test(): - model = rotated_lattice_model() - harness = PyAPITestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_basic/__init__.py b/tests/regression_tests/mg_basic/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_basic/inputs_true.dat b/tests/regression_tests/mg_basic/inputs_true.dat deleted file mode 100644 index 4f2fd3f0b..000000000 --- a/tests/regression_tests/mg_basic/inputs_true.dat +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - 2g.h5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 - - - - false - - multi-group - - false - - diff --git a/tests/regression_tests/mg_basic/results_true.dat b/tests/regression_tests/mg_basic/results_true.dat deleted file mode 100644 index dede97007..000000000 --- a/tests/regression_tests/mg_basic/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.005345E+00 1.109180E-02 diff --git a/tests/regression_tests/mg_basic/test.py b/tests/regression_tests/mg_basic/test.py deleted file mode 100644 index 7b456bb9d..000000000 --- a/tests/regression_tests/mg_basic/test.py +++ /dev/null @@ -1,97 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import PyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - - # Make the base, isotropic data - nu = [2.50, 2.50] - fiss = np.array([0.002817, 0.097]) - capture = [0.008708, 0.02518] - absorption = np.add(capture, fiss) - scatter = np.array( - [[[0.31980, 0.06694], [0.004555, -0.0003972]], - [[0.00000, 0.00000], [0.424100, 0.05439000]]]) - total = [0.33588, 0.54628] - chi = [1., 0.] - - mat_1 = openmc.XSdata('mat_1', groups) - mat_1.order = 1 - mat_1.set_nu_fission(np.multiply(nu, fiss)) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_1) - - # Make a version of mat-1 which has a tabular representation of the - # scattering vice Legendre with 33 points - mat_2 = mat_1.convert_scatter_format('tabular', 33) - mat_2.name = 'mat_2' - mg_cross_sections_file.add_xsdata(mat_2) - - # Make a version of mat-1 which has a histogram representation of the - # scattering vice Legendre with 33 bins - mat_3 = mat_1.convert_scatter_format('histogram', 33) - mat_3.name = 'mat_3' - mg_cross_sections_file.add_xsdata(mat_3) - - # Make a version which uses a fission matrix vice chi & nu-fission - mat_4 = openmc.XSdata('mat_4', groups) - mat_4.order = 1 - mat_4.set_nu_fission(np.outer(np.multiply(nu, fiss), chi)) - mat_4.set_absorption(absorption) - mat_4.set_scatter_matrix(scatter) - mat_4.set_total(total) - mg_cross_sections_file.add_xsdata(mat_4) - - # Make an angle-dependent version of mat_1 with 2 polar and 2 azim. angles - mat_5 = mat_1.convert_representation('angle', 2, 2) - mat_5.name = 'mat_5' - mg_cross_sections_file.add_xsdata(mat_5) - - # Make a copy of mat_1 for testing microscopic cross sections - mat_6 = openmc.XSdata('mat_6', groups) - mat_6.order = 1 - mat_6.set_nu_fission(np.multiply(nu, fiss)) - mat_6.set_absorption(absorption) - mat_6.set_scatter_matrix(scatter) - mat_6.set_total(total) - mat_6.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_6) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(PyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_basic(): - create_library() - mat_names = ['base leg', 'base tab', 'base hist', 'base matrix', - 'base ang', 'micro'] - model = slab_mg(num_regions=6, mat_names=mat_names) - # Modify the last material to be a microscopic combination of nuclides - model.materials[-1] = openmc.Material(name='micro', material_id=6) - model.materials[-1].set_density("sum") - model.materials[-1].add_nuclide("mat_1", 0.5) - model.materials[-1].add_nuclide("mat_6", 0.5) - - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_basic_delayed/__init__.py b/tests/regression_tests/mg_basic_delayed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_basic_delayed/inputs_true.dat b/tests/regression_tests/mg_basic_delayed/inputs_true.dat deleted file mode 100644 index 9fb7afe7e..000000000 --- a/tests/regression_tests/mg_basic_delayed/inputs_true.dat +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - 2g.h5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 154.90833333333333 1000.0 1000.0 - - - - false - - multi-group - - false - - diff --git a/tests/regression_tests/mg_basic_delayed/results_true.dat b/tests/regression_tests/mg_basic_delayed/results_true.dat deleted file mode 100644 index 85312b8e1..000000000 --- a/tests/regression_tests/mg_basic_delayed/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.003463E+00 2.173155E-02 diff --git a/tests/regression_tests/mg_basic_delayed/test.py b/tests/regression_tests/mg_basic_delayed/test.py deleted file mode 100644 index f0474a567..000000000 --- a/tests/regression_tests/mg_basic_delayed/test.py +++ /dev/null @@ -1,131 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import PyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - n_dg = 2 - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - mg_cross_sections_file.num_delayed_groups = n_dg - - beta = np.array([0.003, 0.003]) - one_m_beta = 1. - np.sum(beta) - nu = [2.50, 2.50] - fiss = np.array([0.002817, 0.097]) - capture = [0.008708, 0.02518] - absorption = np.add(capture, fiss) - scatter = np.array( - [[[0.31980, 0.06694], [0.004555, -0.0003972]], - [[0.00000, 0.00000], [0.424100, 0.05439000]]]) - total = [0.33588, 0.54628] - chi = [1., 0.] - - # Make the base data that uses chi & nu-fission vectors with a beta - mat_1 = openmc.XSdata('mat_1', groups) - mat_1.order = 1 - mat_1.num_delayed_groups = 2 - mat_1.set_beta(beta) - mat_1.set_nu_fission(np.multiply(nu, fiss)) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_1) - - # Make a version that uses prompt and delayed version of nufiss and chi - mat_2 = openmc.XSdata('mat_2', groups) - mat_2.order = 1 - mat_2.num_delayed_groups = 2 - mat_2.set_prompt_nu_fission(one_m_beta * np.multiply(nu, fiss)) - delay_nu_fiss = np.zeros((n_dg, groups.num_groups)) - for dg in range(n_dg): - for g in range(groups.num_groups): - delay_nu_fiss[dg, g] = beta[dg] * nu[g] * fiss[g] - mat_2.set_delayed_nu_fission(delay_nu_fiss) - mat_2.set_absorption(absorption) - mat_2.set_scatter_matrix(scatter) - mat_2.set_total(total) - mat_2.set_chi_prompt(chi) - mat_2.set_chi_delayed(np.stack([chi] * n_dg)) - mg_cross_sections_file.add_xsdata(mat_2) - - # Make a version that uses a nu-fission matrix with a beta - mat_3 = openmc.XSdata('mat_3', groups) - mat_3.order = 1 - mat_3.num_delayed_groups = 2 - mat_3.set_beta(beta) - mat_3.set_nu_fission(np.outer(np.multiply(nu, fiss), chi)) - mat_3.set_absorption(absorption) - mat_3.set_scatter_matrix(scatter) - mat_3.set_total(total) - mg_cross_sections_file.add_xsdata(mat_3) - - # Make a version that uses prompt and delayed version of the nufiss matrix - mat_4 = openmc.XSdata('mat_4', groups) - mat_4.order = 1 - mat_4.num_delayed_groups = 2 - mat_4.set_prompt_nu_fission(one_m_beta * - np.outer(np.multiply(nu, fiss), chi)) - delay_nu_fiss = np.zeros((n_dg, groups.num_groups, groups.num_groups)) - for dg in range(n_dg): - for g in range(groups.num_groups): - for go in range(groups.num_groups): - delay_nu_fiss[dg, g, go] = beta[dg] * nu[g] * fiss[g] * chi[go] - mat_4.set_delayed_nu_fission(delay_nu_fiss) - mat_4.set_absorption(absorption) - mat_4.set_scatter_matrix(scatter) - mat_4.set_total(total) - mg_cross_sections_file.add_xsdata(mat_4) - - # Make the base data that uses chi & nu-fiss vectors with a group-wise beta - mat_5 = openmc.XSdata('mat_5', groups) - mat_5.order = 1 - mat_5.num_delayed_groups = 2 - mat_5.set_beta(np.stack([beta] * groups.num_groups)) - mat_5.set_nu_fission(np.multiply(nu, fiss)) - mat_5.set_absorption(absorption) - mat_5.set_scatter_matrix(scatter) - mat_5.set_total(total) - mat_5.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_5) - - # Make a version that uses a nu-fission matrix with a group-wise beta - mat_6 = openmc.XSdata('mat_6', groups) - mat_6.order = 1 - mat_6.num_delayed_groups = 2 - mat_6.set_beta(np.stack([beta] * groups.num_groups)) - mat_6.set_nu_fission(np.outer(np.multiply(nu, fiss), chi)) - mat_6.set_absorption(absorption) - mat_6.set_scatter_matrix(scatter) - mat_6.set_total(total) - mg_cross_sections_file.add_xsdata(mat_6) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(PyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_basic_delayed(): - create_library() - model = slab_mg(num_regions=6, mat_names=['vec beta', 'vec no beta', - 'matrix beta', 'matrix no beta', - 'vec group beta', - 'matrix group beta']) - - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_convert/__init__.py b/tests/regression_tests/mg_convert/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_convert/inputs_true.dat b/tests/regression_tests/mg_convert/inputs_true.dat deleted file mode 100644 index e2c3a01fa..000000000 --- a/tests/regression_tests/mg_convert/inputs_true.dat +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - ./mgxs.h5 - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -5 -5 -5 5 5 5 - - - multi-group - diff --git a/tests/regression_tests/mg_convert/results_true.dat b/tests/regression_tests/mg_convert/results_true.dat deleted file mode 100644 index a52b929dc..000000000 --- a/tests/regression_tests/mg_convert/results_true.dat +++ /dev/null @@ -1,24 +0,0 @@ -k-combined: -9.930873E-01 2.221904E-03 -k-combined: -9.948148E-01 1.216270E-03 -k-combined: -9.930873E-01 2.221904E-03 -k-combined: -9.755034E-01 6.178296E-03 -k-combined: -9.738059E-01 4.529068E-03 -k-combined: -9.866847E-01 9.485912E-03 -k-combined: -9.755024E-01 6.179047E-03 -k-combined: -9.738061E-01 4.529462E-03 -k-combined: -9.866835E-01 9.485832E-03 -k-combined: -9.719024E-01 4.213166E-03 -k-combined: -9.930873E-01 2.221904E-03 -k-combined: -9.930873E-01 2.221904E-03 diff --git a/tests/regression_tests/mg_convert/test.py b/tests/regression_tests/mg_convert/test.py deleted file mode 100755 index 4cc6b656a..000000000 --- a/tests/regression_tests/mg_convert/test.py +++ /dev/null @@ -1,198 +0,0 @@ -import os -import hashlib - -import numpy as np -import openmc - -from tests.testing_harness import PyAPITestHarness -from tests.regression_tests import config - -# OpenMC simulation parameters -batches = 10 -inactive = 5 -particles = 100 - - -def build_mgxs_library(convert): - # Instantiate the energy group data - groups = openmc.mgxs.EnergyGroups(group_edges=[1e-5, 0.625, 20.0e6]) - - # Instantiate the 2-group (C5G7) cross section data - uo2_xsdata = openmc.XSdata('UO2', groups) - uo2_xsdata.order = 2 - uo2_xsdata.set_total([2., 2.]) - uo2_xsdata.set_absorption([1., 1.]) - scatter_matrix = np.array([[[0.75, 0.25], - [0.00, 1.00]], - [[0.75 / 3., 0.25 / 3.], - [0.00 / 3., 1.00 / 3.]], - [[0.75 / 4., 0.25 / 4.], - [0.00 / 4., 1.00 / 4.]]]) - scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) - uo2_xsdata.set_scatter_matrix(scatter_matrix) - uo2_xsdata.set_fission([0.5, 0.5]) - uo2_xsdata.set_nu_fission([1., 1.]) - uo2_xsdata.set_chi([1., 0.]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - mg_cross_sections_file.add_xsdatas([uo2_xsdata]) - - if convert is not None: - if isinstance(convert[0], list): - for conv in convert: - if conv[0] in ['legendre', 'tabular', 'histogram']: - mg_cross_sections_file = \ - mg_cross_sections_file.convert_scatter_format( - conv[0], conv[1]) - elif conv[0] in ['angle', 'isotropic']: - mg_cross_sections_file = \ - mg_cross_sections_file.convert_representation( - conv[0], conv[1], conv[1]) - elif convert[0] in ['legendre', 'tabular', 'histogram']: - mg_cross_sections_file = \ - mg_cross_sections_file.convert_scatter_format( - convert[0], convert[1]) - elif convert[0] in ['angle', 'isotropic']: - mg_cross_sections_file = \ - mg_cross_sections_file.convert_representation( - convert[0], convert[1], convert[1]) - - mg_cross_sections_file.export_to_hdf5() - - -class MGXSTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Instantiate some Macroscopic Data - uo2_data = openmc.Macroscopic('UO2') - - # Instantiate some Materials and register the appropriate objects - mat = openmc.Material(material_id=1, name='UO2 fuel') - mat.set_density('macro', 1.0) - mat.add_macroscopic(uo2_data) - - # Instantiate a Materials collection and export to XML - materials_file = openmc.Materials([mat]) - materials_file.cross_sections = "./mgxs.h5" - materials_file.export_to_xml() - - # Instantiate ZCylinder surfaces - left = openmc.XPlane(surface_id=4, x0=-5., name='left') - right = openmc.XPlane(surface_id=5, x0=5., name='right') - bottom = openmc.YPlane(surface_id=6, y0=-5., name='bottom') - top = openmc.YPlane(surface_id=7, y0=5., name='top') - - left.boundary_type = 'reflective' - right.boundary_type = 'vacuum' - top.boundary_type = 'reflective' - bottom.boundary_type = 'reflective' - - # Instantiate Cells - fuel = openmc.Cell(cell_id=1, name='cell 1') - - # Use surface half-spaces to define regions - fuel.region = +left & -right & +bottom & -top - - # Register Materials with Cells - fuel.fill = mat - - # Instantiate Universe - root = openmc.Universe(universe_id=0, name='root universe') - - # Register Cells with Universe - root.add_cells([fuel]) - - # Instantiate a Geometry, register the root Universe, and export to XML - geometry = openmc.Geometry(root) - geometry.export_to_xml() - - settings_file = openmc.Settings() - settings_file.energy_mode = "multi-group" - settings_file.batches = batches - settings_file.inactive = inactive - settings_file.particles = particles - - # Create an initial uniform spatial source distribution - bounds = [-5, -5, -5, 5, 5, 5] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) - settings_file.source = openmc.source.Source(space=uniform_dist) - - settings_file.export_to_xml() - - def _run_openmc(self): - # Run multiple conversions to compare results - cases = [['legendre', 2], ['legendre', 0], - ['tabular', 33], ['histogram', 32], - [['tabular', 33], ['legendre', 1]], - [['tabular', 33], ['tabular', 3]], - [['tabular', 33], ['histogram', 32]], - [['histogram', 32], ['legendre', 1]], - [['histogram', 32], ['tabular', 3]], - [['histogram', 32], ['histogram', 16]], - ['angle', 2], [['angle', 2], ['isotropic', None]]] - - outstr = '' - for case in cases: - build_mgxs_library(case) - - if config['mpi']: - mpi_args = [config['mpiexec'], '-n', config['mpi_np']] - openmc.run(openmc_exec=config['exe'], mpi_args=mpi_args) - - else: - openmc.run(openmc_exec=config['exe']) - - with openmc.StatePoint('statepoint.{}.h5'.format(batches)) as sp: - # Write out k-combined. - outstr += 'k-combined:\n' - form = '{:12.6E} {:12.6E}\n' - outstr += form.format(sp.k_combined.n, sp.k_combined.s) - - return outstr - - def _get_results(self, outstr, hash_output=False): - # Hash the results if necessary. - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - def _cleanup(self): - super()._cleanup() - f = os.path.join(os.getcwd(), 'mgxs.h5') - if os.path.exists(f): - os.remove(f) - - def execute_test(self): - """Build input XMLs, run OpenMC, and verify correct results.""" - try: - self._build_inputs() - inputs = self._get_inputs() - self._write_inputs(inputs) - self._compare_inputs() - outstr = self._run_openmc() - results = self._get_results(outstr) - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Update results_true.dat and inputs_true.dat""" - try: - self._build_inputs() - inputs = self._get_inputs() - self._write_inputs(inputs) - self._overwrite_inputs() - outstr = self._run_openmc() - results = self._get_results(outstr) - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - -def test_mg_convert(): - harness = MGXSTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/mg_legendre/__init__.py b/tests/regression_tests/mg_legendre/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_legendre/inputs_true.dat b/tests/regression_tests/mg_legendre/inputs_true.dat deleted file mode 100644 index ad3b434e6..000000000 --- a/tests/regression_tests/mg_legendre/inputs_true.dat +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - - false - - diff --git a/tests/regression_tests/mg_legendre/results_true.dat b/tests/regression_tests/mg_legendre/results_true.dat deleted file mode 100644 index 4a9d98237..000000000 --- a/tests/regression_tests/mg_legendre/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.934975E-01 2.679669E-02 diff --git a/tests/regression_tests/mg_legendre/test.py b/tests/regression_tests/mg_legendre/test.py deleted file mode 100644 index b5a05c706..000000000 --- a/tests/regression_tests/mg_legendre/test.py +++ /dev/null @@ -1,55 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import PyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - - # Make the base, isotropic data - nu = [2.50, 2.50] - fiss = np.array([0.002817, 0.097]) - capture = [0.008708, 0.02518] - absorption = np.add(capture, fiss) - scatter = np.array( - [[[0.31980, 0.06694], [0.004555, -0.0003972]], - [[0.00000, 0.00000], [0.424100, 0.05439000]]]) - total = [0.33588, 0.54628] - chi = [1., 0.] - - mat_1 = openmc.XSdata('mat_1', groups) - mat_1.order = 1 - mat_1.set_nu_fission(np.multiply(nu, fiss)) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_1) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(PyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_legendre(): - create_library() - model = slab_mg() - model.settings.tabular_legendre = {'enable': False} - - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_max_order/__init__.py b/tests/regression_tests/mg_max_order/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_max_order/inputs_true.dat b/tests/regression_tests/mg_max_order/inputs_true.dat deleted file mode 100644 index 2ac83852c..000000000 --- a/tests/regression_tests/mg_max_order/inputs_true.dat +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - 1 - - false - - diff --git a/tests/regression_tests/mg_max_order/results_true.dat b/tests/regression_tests/mg_max_order/results_true.dat deleted file mode 100644 index 4a9d98237..000000000 --- a/tests/regression_tests/mg_max_order/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.934975E-01 2.679669E-02 diff --git a/tests/regression_tests/mg_max_order/test.py b/tests/regression_tests/mg_max_order/test.py deleted file mode 100644 index 97d3f57d7..000000000 --- a/tests/regression_tests/mg_max_order/test.py +++ /dev/null @@ -1,55 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import PyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - - # Make the base, isotropic data - nu = [2.50, 2.50] - fiss = np.array([0.002817, 0.097]) - capture = [0.008708, 0.02518] - absorption = np.add(capture, fiss) - scatter = np.array( - [[[0.31980, 0.06694, 0.003], [0.004555, -0.0003972, 0.00002]], - [[0.00000, 0.00000, 0.000], [0.424100, 0.05439000, 0.0025]]]) - total = [0.33588, 0.54628] - chi = [1., 0.] - - mat_1 = openmc.XSdata('mat_1', groups) - mat_1.order = 2 - mat_1.set_nu_fission(np.multiply(nu, fiss)) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_1) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(PyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_max_order(): - create_library() - model = slab_mg() - model.settings.max_order = 1 - - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_survival_biasing/__init__.py b/tests/regression_tests/mg_survival_biasing/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_survival_biasing/inputs_true.dat b/tests/regression_tests/mg_survival_biasing/inputs_true.dat deleted file mode 100644 index 5ece3ce9f..000000000 --- a/tests/regression_tests/mg_survival_biasing/inputs_true.dat +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - true - - false - - diff --git a/tests/regression_tests/mg_survival_biasing/results_true.dat b/tests/regression_tests/mg_survival_biasing/results_true.dat deleted file mode 100644 index ebe98679f..000000000 --- a/tests/regression_tests/mg_survival_biasing/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -9.979905E-01 6.207495E-03 diff --git a/tests/regression_tests/mg_survival_biasing/test.py b/tests/regression_tests/mg_survival_biasing/test.py deleted file mode 100644 index 5d75611a9..000000000 --- a/tests/regression_tests/mg_survival_biasing/test.py +++ /dev/null @@ -1,55 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import PyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups) - - # Make the base, isotropic data - nu = [2.50, 2.50] - fiss = np.array([0.002817, 0.097]) - capture = [0.008708, 0.02518] - absorption = np.add(capture, fiss) - scatter = np.array( - [[[0.31980, 0.06694], [0.004555, -0.0003972]], - [[0.00000, 0.00000], [0.424100, 0.05439000]]]) - total = [0.33588, 0.54628] - chi = [1., 0.] - - mat_1 = openmc.XSdata('mat_1', groups) - mat_1.order = 1 - mat_1.set_nu_fission(np.multiply(nu, fiss)) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mg_cross_sections_file.add_xsdata(mat_1) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(PyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_survival_biasing(): - create_library() - model = slab_mg() - model.settings.survival_biasing = True - - harness = PyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mg_tallies/__init__.py b/tests/regression_tests/mg_tallies/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mg_tallies/inputs_true.dat b/tests/regression_tests/mg_tallies/inputs_true.dat deleted file mode 100644 index 562958722..000000000 --- a/tests/regression_tests/mg_tallies/inputs_true.dat +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - 2g.h5 - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - 0.0 -1000.0 -1000.0 929.45 1000.0 1000.0 - - - - false - - multi-group - - false - - - - - - 10 1 1 - 0.0 0.0 0.0 - 929.45 1000 1000 - - - 1 - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 5 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - analog - - - 5 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter - analog - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - collision - - - 6 1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 1 2 - scatter nu-scatter nu-fission - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux scatter nu-scatter - analog - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - collision - - - 6 3 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate flux - tracklength - - - 6 3 4 - scatter nu-scatter nu-fission - - - 5 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - analog - - - 5 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter - analog - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - collision - - - 6 1 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 1 2 - mat_1 - scatter nu-scatter nu-fission - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate scatter nu-scatter - analog - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - collision - - - 6 3 - mat_1 - total absorption fission nu-fission inverse-velocity prompt-nu-fission delayed-nu-fission kappa-fission events decay-rate - tracklength - - - 6 3 4 - mat_1 - scatter nu-scatter nu-fission - - diff --git a/tests/regression_tests/mg_tallies/results_true.dat b/tests/regression_tests/mg_tallies/results_true.dat deleted file mode 100644 index 50ec653e2..000000000 --- a/tests/regression_tests/mg_tallies/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -508cd056f2d9409a536e487512df34c683720ea45b9100316efb31c19927890c4cacd92f38817d74fcf491bbe4bdb78a0215a798d5a078e0575e3fd94cedf0bd \ No newline at end of file diff --git a/tests/regression_tests/mg_tallies/test.py b/tests/regression_tests/mg_tallies/test.py deleted file mode 100644 index e1c19e6b7..000000000 --- a/tests/regression_tests/mg_tallies/test.py +++ /dev/null @@ -1,148 +0,0 @@ -import os - -import numpy as np - -import openmc -from openmc.examples import slab_mg - -from tests.testing_harness import HashedPyAPITestHarness - - -def create_library(): - # Instantiate the energy group data and file object - groups = openmc.mgxs.EnergyGroups(group_edges=[0.0, 0.625, 20.0e6]) - - mg_cross_sections_file = openmc.MGXSLibrary(groups, 6) - - # Make the base, isotropic data - nu = np.array([2.50, 2.50]) - fiss = np.array([0.002817, 0.097]) - capture = np.array([0.008708, 0.02518]) - absorption = capture + fiss - scatter = np.array( - [[[0.31980, 0.06694], [0.004555, -0.0003972]], - [[0.00000, 0.00000], [0.424100, 0.05439000]]]) - total = np.array([0.33588, 0.54628]) - chi = np.array([1., 0.]) - decay_rate = np.array([0.013336, 0.032739, 0.12078, 0.30278, 0.84949, - 2.853]) - delayed_yield = np.array([0.00055487, 0.00286407, 0.00273429, 0.0061305, - 0.00251342, 0.00105286]) - inv_vel = 1.0 / np.array([1.4e9, 4.4e5]) - - - mat_1 = openmc.XSdata('mat_1', groups, num_delayed_groups=6) - mat_1.order = 1 - mat_1.set_fission(fiss) - mat_1.set_kappa_fission(fiss * 200e6) - mat_1.set_nu_fission(nu * fiss) - mat_1.set_beta(delayed_yield / 2.5) - mat_1.set_decay_rate(decay_rate) - mat_1.set_absorption(absorption) - mat_1.set_scatter_matrix(scatter) - mat_1.set_total(total) - mat_1.set_chi(chi) - mat_1.set_inverse_velocity(inv_vel) - mg_cross_sections_file.add_xsdata(mat_1) - - # Write the file - mg_cross_sections_file.export_to_hdf5('2g.h5') - - -class MGXSTestHarness(HashedPyAPITestHarness): - def _cleanup(self): - super()._cleanup() - f = '2g.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mg_tallies(): - create_library() - model = slab_mg() - - # Instantiate a tally mesh - mesh = openmc.RegularMesh(mesh_id=1) - mesh.dimension = [10, 1, 1] - mesh.lower_left = [0.0, 0.0, 0.0] - mesh.upper_right = [929.45, 1000, 1000] - - # Instantiate some tally filters - energy_filter = openmc.EnergyFilter([0.0, 20.0e6]) - energyout_filter = openmc.EnergyoutFilter([0.0, 20.0e6]) - energies = [0.0, 0.625, 20.0e6] - matching_energy_filter = openmc.EnergyFilter(energies) - matching_eout_filter = openmc.EnergyoutFilter(energies) - mesh_filter = openmc.MeshFilter(mesh) - - mat_filter = openmc.MaterialFilter(model.materials) - - nuclides = model.xs_data - - scores_with_nuclides = [ - 'total', 'absorption', 'fission', 'nu-fission', 'inverse-velocity', - 'prompt-nu-fission', 'delayed-nu-fission', 'kappa-fission', 'events', - 'decay-rate'] - scores_without_nuclides = scores_with_nuclides + ['flux'] - - for do_nuclides, scores in ((False, scores_without_nuclides), - (True, scores_with_nuclides)): - t = openmc.Tally() - t.filters = [mesh_filter] - t.estimator = 'analog' - t.scores = scores - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - t = openmc.Tally() - t.filters = [mesh_filter] - t.estimator = 'tracklength' - t.scores = scores - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - # Impose energy bins that dont match the MG structure and those - # that do - for match_energy_bins in [False, True]: - if match_energy_bins: - e_filter = matching_energy_filter - eout_filter = matching_eout_filter - else: - e_filter = energy_filter - eout_filter = energyout_filter - - t = openmc.Tally() - t.filters = [mat_filter, e_filter] - t.estimator = 'analog' - t.scores = scores + ['scatter', 'nu-scatter'] - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - t = openmc.Tally() - t.filters = [mat_filter, e_filter] - t.estimator = 'collision' - t.scores = scores - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - t = openmc.Tally() - t.filters = [mat_filter, e_filter] - t.estimator = 'tracklength' - t.scores = scores - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - t = openmc.Tally() - t.filters = [mat_filter, e_filter, eout_filter] - t.scores = ['scatter', 'nu-scatter', 'nu-fission'] - if do_nuclides: - t.nuclides = nuclides - model.tallies.append(t) - - harness = HashedPyAPITestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/__init__.py b/tests/regression_tests/mgxs_library_ce_to_mg/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat deleted file mode 100644 index bc5c4b2d4..000000000 --- a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 3 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - analog - - - 1 2 7 - total - nu-fission - analog - - - 1 2 - total - flux - analog - - - 1 2 7 11 - total - nu-scatter - analog - - - 1 2 7 - total - nu-scatter - analog - - - 1 2 7 - total - scatter - analog - - - 15 2 - total - flux - tracklength - - - 15 2 - total - total - tracklength - - - 15 2 - total - flux - tracklength - - - 15 2 - total - absorption - tracklength - - - 15 2 - total - flux - analog - - - 15 2 7 - total - nu-fission - analog - - - 15 2 - total - flux - analog - - - 15 2 7 11 - total - nu-scatter - analog - - - 15 2 7 - total - nu-scatter - analog - - - 15 2 7 - total - scatter - analog - - - 29 2 - total - flux - tracklength - - - 29 2 - total - total - tracklength - - - 29 2 - total - flux - tracklength - - - 29 2 - total - absorption - tracklength - - - 29 2 - total - flux - analog - - - 29 2 7 - total - nu-fission - analog - - - 29 2 - total - flux - analog - - - 29 2 7 11 - total - nu-scatter - analog - - - 29 2 7 - total - nu-scatter - analog - - - 29 2 7 - total - scatter - analog - - diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/results_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg/results_true.dat deleted file mode 100644 index 0fd5b4827..000000000 --- a/tests/regression_tests/mgxs_library_ce_to_mg/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.133362E+00 1.746523E-02 diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/test.py b/tests/regression_tests/mgxs_library_ce_to_mg/test.py deleted file mode 100644 index 72f052e68..000000000 --- a/tests/regression_tests/mgxs_library_ce_to_mg/test.py +++ /dev/null @@ -1,85 +0,0 @@ -import os - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness -from tests.regression_tests import config - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - self.mgxs_lib.mgxs_types = ['total', 'absorption', 'nu-fission matrix', - 'nu-scatter matrix', 'multiplicity matrix'] - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.correction = None - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Initialize a tallies file - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _run_openmc(self): - # Initial run - if config['mpi']: - mpi_args = [config['mpiexec'], '-n', config['mpi_np']] - openmc.run(openmc_exec=config['exe'], mpi_args=mpi_args) - else: - openmc.run(openmc_exec=config['exe']) - - # Build MG Inputs - # Get data needed to execute Library calculations. - sp = openmc.StatePoint(self._sp_name) - self.mgxs_lib.load_from_statepoint(sp) - self._model.mgxs_file, self._model.materials, \ - self._model.geometry = self.mgxs_lib.create_mg_mode() - - # Modify materials and settings so we can run in MG mode - self._model.materials.cross_sections = './mgxs.h5' - self._model.settings.energy_mode = 'multi-group' - - # Write modified input files - self._model.settings.export_to_xml() - self._model.geometry.export_to_xml() - self._model.materials.export_to_xml() - self._model.mgxs_file.export_to_hdf5() - # Dont need tallies.xml, so remove the file - if os.path.exists('tallies.xml'): - os.remove('tallies.xml') - - # Enforce closing statepoint and summary files so HDF5 - # does not throw an error during the next OpenMC execution - sp._f.close() - sp._summary._f.close() - - # Re-run MG mode. - if config['mpi']: - mpi_args = [config['mpiexec'], '-n', config['mpi_np']] - openmc.run(openmc_exec=config['exe'], mpi_args=mpi_args) - else: - openmc.run(openmc_exec=config['exe']) - - def _cleanup(self): - super()._cleanup() - f = 'mgxs.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mgxs_library_ce_to_mg(): - # Set the input set to use the pincell model - model = pwr_pin_cell() - - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_condense/__init__.py b/tests/regression_tests/mgxs_library_condense/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_condense/inputs_true.dat b/tests/regression_tests/mgxs_library_condense/inputs_true.dat deleted file mode 100644 index 5aedd383d..000000000 --- a/tests/regression_tests/mgxs_library_condense/inputs_true.dat +++ /dev/null @@ -1,1178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 2 3 4 5 6 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 52 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 52 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 52 - total - delayed-nu-fission - analog - - - 1 65 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 65 2 5 - total - delayed-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - nu-scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - nu-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - kappa-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 - total - flux - analog - - - 80 2 - total - nu-scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - nu-scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 - total - nu-fission - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 52 - total - nu-fission - analog - - - 80 5 - total - nu-fission - analog - - - 80 52 - total - prompt-nu-fission - analog - - - 80 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - inverse-velocity - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - prompt-nu-fission - tracklength - - - 80 2 - total - flux - analog - - - 80 2 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 52 - total - delayed-nu-fission - analog - - - 80 65 5 - total - delayed-nu-fission - analog - - - 80 2 - total - nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - decay-rate - tracklength - - - 80 2 - total - flux - analog - - - 80 65 2 5 - total - delayed-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - nu-scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - nu-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - kappa-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 - total - flux - analog - - - 159 2 - total - nu-scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - nu-scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 - total - nu-fission - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 52 - total - nu-fission - analog - - - 159 5 - total - nu-fission - analog - - - 159 52 - total - prompt-nu-fission - analog - - - 159 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - inverse-velocity - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - prompt-nu-fission - tracklength - - - 159 2 - total - flux - analog - - - 159 2 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 52 - total - delayed-nu-fission - analog - - - 159 65 5 - total - delayed-nu-fission - analog - - - 159 2 - total - nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - decay-rate - tracklength - - - 159 2 - total - flux - analog - - - 159 65 2 5 - total - delayed-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_condense/results_true.dat b/tests/regression_tests/mgxs_library_condense/results_true.dat deleted file mode 100644 index d4aa6b811..000000000 --- a/tests/regression_tests/mgxs_library_condense/results_true.dat +++ /dev/null @@ -1,273 +0,0 @@ - material group in nuclide mean std. dev. -0 1 1 total 0.453624 0.021053 - material group in nuclide mean std. dev. -0 1 1 total 0.4074 0.021863 - material group in nuclide mean std. dev. -0 1 1 total 0.4074 0.021863 - material group in nuclide mean std. dev. -0 1 1 total 0.064903 0.004313 - material group in nuclide mean std. dev. -0 1 1 total 0.028048 0.00458 - material group in nuclide mean std. dev. -0 1 1 total 0.036855 0.002622 - material group in nuclide mean std. dev. -0 1 1 total 0.090649 0.00641 - material group in nuclide mean std. dev. -0 1 1 total 7.137954e+06 507363.467231 - material group in nuclide mean std. dev. -0 1 1 total 0.388721 0.01783 - material group in nuclide mean std. dev. -0 1 1 total 0.389304 0.023076 - material group in group out legendre nuclide mean std. dev. -0 1 1 1 P0 total 0.389304 0.023146 -1 1 1 1 P1 total 0.046224 0.005907 -2 1 1 1 P2 total 0.017984 0.002883 -3 1 1 1 P3 total 0.006628 0.002457 - material group in group out legendre nuclide mean std. dev. -0 1 1 1 P0 total 0.389304 0.023146 -1 1 1 1 P1 total 0.046224 0.005907 -2 1 1 1 P2 total 0.017984 0.002883 -3 1 1 1 P3 total 0.006628 0.002457 - material group in group out nuclide mean std. dev. -0 1 1 1 total 1.0 0.066111 - material group in group out nuclide mean std. dev. -0 1 1 1 total 0.085835 0.005592 - material group in group out nuclide mean std. dev. -0 1 1 1 total 1.0 0.066111 - material group in group out legendre nuclide mean std. dev. -0 1 1 1 P0 total 0.388721 0.031279 -1 1 1 1 P1 total 0.046155 0.006407 -2 1 1 1 P2 total 0.017957 0.003039 -3 1 1 1 P3 total 0.006618 0.002480 - material group in group out legendre nuclide mean std. dev. -0 1 1 1 P0 total 0.388721 0.040482 -1 1 1 1 P1 total 0.046155 0.007097 -2 1 1 1 P2 total 0.017957 0.003262 -3 1 1 1 P3 total 0.006618 0.002518 - material group out nuclide mean std. dev. -0 1 1 total 1.0 0.046071 - material group out nuclide mean std. dev. -0 1 1 total 1.0 0.051471 - material group in nuclide mean std. dev. -0 1 1 total 4.996730e-07 3.650633e-08 - material group in nuclide mean std. dev. -0 1 1 total 0.090004 0.006367 - material group in group out nuclide mean std. dev. -0 1 1 1 total 0.084542 0.005716 - material delayedgroup group in nuclide mean std. dev. -0 1 1 1 total 0.000021 0.000001 -1 1 2 1 total 0.000110 0.000008 -2 1 3 1 total 0.000107 0.000007 -3 1 4 1 total 0.000249 0.000017 -4 1 5 1 total 0.000112 0.000007 -5 1 6 1 total 0.000046 0.000003 - material delayedgroup group out nuclide mean std. dev. -0 1 1 1 total 0.0 0.000000 -1 1 2 1 total 1.0 0.869128 -2 1 3 1 total 1.0 1.414214 -3 1 4 1 total 1.0 0.360359 -4 1 5 1 total 0.0 0.000000 -5 1 6 1 total 0.0 0.000000 - material delayedgroup group in nuclide mean std. dev. -0 1 1 1 total 0.000227 0.000020 -1 1 2 1 total 0.001214 0.000108 -2 1 3 1 total 0.001184 0.000104 -3 1 4 1 total 0.002752 0.000240 -4 1 5 1 total 0.001231 0.000105 -5 1 6 1 total 0.000512 0.000044 - material delayedgroup group in nuclide mean std. dev. -0 1 1 1 total 0.013355 0.001207 -1 1 2 1 total 0.032600 0.002866 -2 1 3 1 total 0.121083 0.010442 -3 1 4 1 total 0.305910 0.025627 -4 1 5 1 total 0.861934 0.068281 -5 1 6 1 total 2.895065 0.230223 - material delayedgroup group in group out nuclide mean std. dev. -0 1 1 1 1 total 0.000000 0.000000 -1 1 2 1 1 total 0.000384 0.000236 -2 1 3 1 1 total 0.000179 0.000180 -3 1 4 1 1 total 0.000730 0.000188 -4 1 5 1 1 total 0.000000 0.000000 -5 1 6 1 1 total 0.000000 0.000000 - material group in nuclide mean std. dev. -0 2 1 total 0.311594 0.013793 - material group in nuclide mean std. dev. -0 2 1 total 0.280977 0.015683 - material group in nuclide mean std. dev. -0 2 1 total 0.280977 0.015683 - material group in nuclide mean std. dev. -0 2 1 total 0.00221 0.000286 - material group in nuclide mean std. dev. -0 2 1 total 0.00221 0.000286 - material group in nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 2 1 total 0.309384 0.013551 - material group in nuclide mean std. dev. -0 2 1 total 0.307987 0.029308 - material group in group out legendre nuclide mean std. dev. -0 2 1 1 P0 total 0.307987 0.029308 -1 2 1 1 P1 total 0.030617 0.007464 -2 2 1 1 P2 total 0.018911 0.004323 -3 2 1 1 P3 total 0.006235 0.003338 - material group in group out legendre nuclide mean std. dev. -0 2 1 1 P0 total 0.307987 0.029308 -1 2 1 1 P1 total 0.030617 0.007464 -2 2 1 1 P2 total 0.018911 0.004323 -3 2 1 1 P3 total 0.006235 0.003338 - material group in group out nuclide mean std. dev. -0 2 1 1 total 1.0 0.095039 - material group in group out nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 - material group in group out nuclide mean std. dev. -0 2 1 1 total 1.0 0.095039 - material group in group out legendre nuclide mean std. dev. -0 2 1 1 P0 total 0.309384 0.032376 -1 2 1 1 P1 total 0.030756 0.007617 -2 2 1 1 P2 total 0.018997 0.004420 -3 2 1 1 P3 total 0.006263 0.003364 - material group in group out legendre nuclide mean std. dev. -0 2 1 1 P0 total 0.309384 0.043735 -1 2 1 1 P1 total 0.030756 0.008159 -2 2 1 1 P2 total 0.018997 0.004775 -3 2 1 1 P3 total 0.006263 0.003417 - material group out nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group out nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 2 1 total 5.454762e-07 4.949807e-08 - material group in nuclide mean std. dev. -0 2 1 total 0.0 0.0 - material group in group out nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -2 2 3 1 total 0.0 0.0 -3 2 4 1 total 0.0 0.0 -4 2 5 1 total 0.0 0.0 -5 2 6 1 total 0.0 0.0 - material delayedgroup group out nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -2 2 3 1 total 0.0 0.0 -3 2 4 1 total 0.0 0.0 -4 2 5 1 total 0.0 0.0 -5 2 6 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -2 2 3 1 total 0.0 0.0 -3 2 4 1 total 0.0 0.0 -4 2 5 1 total 0.0 0.0 -5 2 6 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 2 1 1 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -2 2 3 1 total 0.0 0.0 -3 2 4 1 total 0.0 0.0 -4 2 5 1 total 0.0 0.0 -5 2 6 1 total 0.0 0.0 - material delayedgroup group in group out nuclide mean std. dev. -0 2 1 1 1 total 0.0 0.0 -1 2 2 1 1 total 0.0 0.0 -2 2 3 1 1 total 0.0 0.0 -3 2 4 1 1 total 0.0 0.0 -4 2 5 1 1 total 0.0 0.0 -5 2 6 1 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 3 1 total 0.904999 0.043964 - material group in nuclide mean std. dev. -0 3 1 total 0.494581 0.046763 - material group in nuclide mean std. dev. -0 3 1 total 0.494581 0.046763 - material group in nuclide mean std. dev. -0 3 1 total 0.00606 0.000555 - material group in nuclide mean std. dev. -0 3 1 total 0.00606 0.000555 - material group in nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 3 1 total 0.898938 0.043493 - material group in nuclide mean std. dev. -0 3 1 total 0.903415 0.043959 - material group in group out legendre nuclide mean std. dev. -0 3 1 1 P0 total 0.903415 0.043586 -1 3 1 1 P1 total 0.410417 0.015877 -2 3 1 1 P2 total 0.143301 0.007187 -3 3 1 1 P3 total 0.008739 0.003571 - material group in group out legendre nuclide mean std. dev. -0 3 1 1 P0 total 0.903415 0.043586 -1 3 1 1 P1 total 0.410417 0.015877 -2 3 1 1 P2 total 0.143301 0.007187 -3 3 1 1 P3 total 0.008739 0.003571 - material group in group out nuclide mean std. dev. -0 3 1 1 total 1.0 0.056867 - material group in group out nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 - material group in group out nuclide mean std. dev. -0 3 1 1 total 1.0 0.056867 - material group in group out legendre nuclide mean std. dev. -0 3 1 1 P0 total 0.898938 0.067118 -1 3 1 1 P1 total 0.408384 0.028127 -2 3 1 1 P2 total 0.142591 0.010824 -3 3 1 1 P3 total 0.008696 0.003588 - material group in group out legendre nuclide mean std. dev. -0 3 1 1 P0 total 0.898938 0.084369 -1 3 1 1 P1 total 0.408384 0.036475 -2 3 1 1 P2 total 0.142591 0.013525 -3 3 1 1 P3 total 0.008696 0.003622 - material group out nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group out nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group in nuclide mean std. dev. -0 3 1 total 5.773007e-07 5.322133e-08 - material group in nuclide mean std. dev. -0 3 1 total 0.0 0.0 - material group in group out nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -2 3 3 1 total 0.0 0.0 -3 3 4 1 total 0.0 0.0 -4 3 5 1 total 0.0 0.0 -5 3 6 1 total 0.0 0.0 - material delayedgroup group out nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -2 3 3 1 total 0.0 0.0 -3 3 4 1 total 0.0 0.0 -4 3 5 1 total 0.0 0.0 -5 3 6 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -2 3 3 1 total 0.0 0.0 -3 3 4 1 total 0.0 0.0 -4 3 5 1 total 0.0 0.0 -5 3 6 1 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -0 3 1 1 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -2 3 3 1 total 0.0 0.0 -3 3 4 1 total 0.0 0.0 -4 3 5 1 total 0.0 0.0 -5 3 6 1 total 0.0 0.0 - material delayedgroup group in group out nuclide mean std. dev. -0 3 1 1 1 total 0.0 0.0 -1 3 2 1 1 total 0.0 0.0 -2 3 3 1 1 total 0.0 0.0 -3 3 4 1 1 total 0.0 0.0 -4 3 5 1 1 total 0.0 0.0 -5 3 6 1 1 total 0.0 0.0 diff --git a/tests/regression_tests/mgxs_library_condense/test.py b/tests/regression_tests/mgxs_library_condense/test.py deleted file mode 100644 index 167772e2f..000000000 --- a/tests/regression_tests/mgxs_library_condense/test.py +++ /dev/null @@ -1,67 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ - openmc.mgxs.MDGXS_TYPES - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.num_delayed_groups = 6 - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Build a condensed 1-group MGXS Library - one_group = openmc.mgxs.EnergyGroups([0., 20.e6]) - condense_lib = self.mgxs_lib.get_condensed_library(one_group) - - # Build a string from Pandas Dataframe for each 1-group MGXS - outstr = '' - for domain in condense_lib.domains: - for mgxs_type in condense_lib.mgxs_types: - mgxs = condense_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_condense(): - # Use the pincell model - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_correction/__init__.py b/tests/regression_tests/mgxs_library_correction/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_correction/inputs_true.dat b/tests/regression_tests/mgxs_library_correction/inputs_true.dat deleted file mode 100644 index 8c1cd4d16..000000000 --- a/tests/regression_tests/mgxs_library_correction/inputs_true.dat +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 0 - - - 2 - - - 3 - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 12 - total - scatter - analog - - - 1 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 12 - total - scatter - analog - - - 1 2 3 - total - nu-scatter - analog - - - 1 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 19 2 - total - flux - analog - - - 19 2 3 4 - total - scatter - analog - - - 19 2 - total - flux - analog - - - 19 2 3 4 - total - nu-scatter - analog - - - 19 2 - total - flux - tracklength - - - 19 2 - total - scatter - tracklength - - - 19 2 3 12 - total - scatter - analog - - - 19 3 4 - total - scatter - analog - - - 19 2 - total - flux - analog - - - 19 2 - total - flux - tracklength - - - 19 2 - total - scatter - tracklength - - - 19 2 3 12 - total - scatter - analog - - - 19 2 3 - total - nu-scatter - analog - - - 19 3 4 - total - nu-scatter - analog - - - 19 2 - total - flux - analog - - - 37 2 - total - flux - analog - - - 37 2 3 4 - total - scatter - analog - - - 37 2 - total - flux - analog - - - 37 2 3 4 - total - nu-scatter - analog - - - 37 2 - total - flux - tracklength - - - 37 2 - total - scatter - tracklength - - - 37 2 3 12 - total - scatter - analog - - - 37 3 4 - total - scatter - analog - - - 37 2 - total - flux - analog - - - 37 2 - total - flux - tracklength - - - 37 2 - total - scatter - tracklength - - - 37 2 3 12 - total - scatter - analog - - - 37 2 3 - total - nu-scatter - analog - - - 37 3 4 - total - nu-scatter - analog - - - 37 2 - total - flux - analog - - diff --git a/tests/regression_tests/mgxs_library_correction/results_true.dat b/tests/regression_tests/mgxs_library_correction/results_true.dat deleted file mode 100644 index cc28320e2..000000000 --- a/tests/regression_tests/mgxs_library_correction/results_true.dat +++ /dev/null @@ -1,60 +0,0 @@ - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.332466 0.026533 -2 1 1 2 total 0.000989 0.000482 -1 1 2 1 total 0.000925 0.000925 -0 1 2 2 total 0.396146 0.015707 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.332466 0.026533 -2 1 1 2 total 0.000989 0.000482 -1 1 2 1 total 0.000925 0.000925 -0 1 2 2 total 0.396146 0.015707 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.334690 0.037288 -2 1 1 2 total 0.000995 0.000489 -1 1 2 1 total 0.000887 0.000889 -0 1 2 2 total 0.379453 0.030118 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.334690 0.048073 -2 1 1 2 total 0.000995 0.000841 -1 1 2 1 total 0.000887 0.001538 -0 1 2 2 total 0.379453 0.034216 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.271891 0.032748 -2 2 1 2 total 0.000000 0.000000 -1 2 2 1 total 0.000000 0.000000 -0 2 2 2 total 0.307478 0.047512 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.271891 0.032748 -2 2 1 2 total 0.000000 0.000000 -1 2 2 1 total 0.000000 0.000000 -0 2 2 2 total 0.307478 0.047512 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.273933 0.038207 -2 2 1 2 total 0.000000 0.000000 -1 2 2 1 total 0.000000 0.000000 -0 2 2 2 total 0.306635 0.052777 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.273933 0.051116 -2 2 1 2 total 0.000000 0.000000 -1 2 2 1 total 0.000000 0.000000 -0 2 2 2 total 0.306635 0.067497 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.258652 0.022596 -2 3 1 2 total 0.031368 0.001728 -1 3 2 1 total 0.000443 0.000445 -0 3 2 2 total 1.482300 0.232582 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.258652 0.022596 -2 3 1 2 total 0.031368 0.001728 -1 3 2 1 total 0.000443 0.000445 -0 3 2 2 total 1.482300 0.232582 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.251610 0.041472 -2 3 1 2 total 0.031023 0.002232 -1 3 2 1 total 0.000440 0.000445 -0 3 2 2 total 1.467612 0.356408 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.251610 0.048135 -2 3 1 2 total 0.031023 0.003064 -1 3 2 1 total 0.000440 0.000765 -0 3 2 2 total 1.467612 0.449931 diff --git a/tests/regression_tests/mgxs_library_correction/test.py b/tests/regression_tests/mgxs_library_correction/test.py deleted file mode 100644 index 05eedfef8..000000000 --- a/tests/regression_tests/mgxs_library_correction/test.py +++ /dev/null @@ -1,63 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = ['scatter matrix', 'nu-scatter matrix', - 'consistent scatter matrix', - 'consistent nu-scatter matrix'] - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.correction = 'P0' - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Build a string from Pandas Dataframe for each MGXS - outstr = '' - for domain in self.mgxs_lib.domains: - for mgxs_type in self.mgxs_lib.mgxs_types: - mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_correction(): - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_distribcell/__init__.py b/tests/regression_tests/mgxs_library_distribcell/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat deleted file mode 100644 index f6748d150..000000000 --- a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -10.71 -10.71 -1 10.71 10.71 1 - - - - - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 1 - - - 3 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 2 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - analog - - - 1 65 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 65 2 5 - total - delayed-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_distribcell/results_true.dat b/tests/regression_tests/mgxs_library_distribcell/results_true.dat deleted file mode 100644 index 9f58621c1..000000000 --- a/tests/regression_tests/mgxs_library_distribcell/results_true.dat +++ /dev/null @@ -1,91 +0,0 @@ - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.457353 0.010474 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.410174 0.011573 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.410166 0.011577 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.066556 0.00251 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.028979 0.002712 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.037577 0.001487 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.092377 0.003628 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 7.276706e+06 287579.247699 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.390797 0.008717 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.387332 0.014241 - sum(distribcell) group in group out legendre nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.387009 0.014230 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047179 0.004923 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015713 0.003654 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005378 0.003137 - sum(distribcell) group in group out legendre nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.387332 0.014241 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047187 0.004933 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015727 0.003654 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005387 0.003141 - sum(distribcell) group in group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 1.000834 0.037242 - sum(distribcell) group in group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.094516 0.0059 - sum(distribcell) group in group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 1.0 0.037213 - sum(distribcell) group in group out legendre nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.390797 0.016955 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047641 0.005091 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015866 0.003708 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005430 0.003170 - sum(distribcell) group in group out legendre nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.391123 0.022356 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047680 0.005395 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015880 0.003758 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005435 0.003179 - sum(distribcell) group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 1.0 0.080455 - sum(distribcell) group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 1.0 0.080541 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 5.139437e-07 2.133314e-08 - sum(distribcell) group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.091725 0.003604 - sum(distribcell) group in group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.093985 0.005872 - sum(distribcell) delayedgroup group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.000021 8.253906e-07 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 2 1 total 0.000112 4.284000e-06 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 3 1 total 0.000109 4.105197e-06 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 4 1 total 0.000252 9.271419e-06 -4 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 5 1 total 0.000112 3.888624e-06 -5 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 6 1 total 0.000047 1.625563e-06 - sum(distribcell) delayedgroup group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.0 0.000000 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 2 1 total 1.0 1.414214 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 3 1 total 1.0 1.414214 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 4 1 total 0.0 0.000000 -4 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 5 1 total 0.0 0.000000 -5 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 6 1 total 1.0 1.414214 - sum(distribcell) delayedgroup group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.000227 0.000012 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 2 1 total 0.001209 0.000061 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 3 1 total 0.001177 0.000059 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 4 1 total 0.002727 0.000135 -4 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 5 1 total 0.001210 0.000058 -5 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 6 1 total 0.000504 0.000024 - sum(distribcell) delayedgroup group in nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.013353 0.000686 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 2 1 total 0.032613 0.001627 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 3 1 total 0.121054 0.005911 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 4 1 total 0.305627 0.014428 -4 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 5 1 total 0.860892 0.037879 -5 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 6 1 total 2.891521 0.127879 - sum(distribcell) delayedgroup group in group out nuclide mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 1 total 0.000000 0.000000 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 2 1 1 total 0.000175 0.000175 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 3 1 1 total 0.000178 0.000178 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 4 1 1 total 0.000000 0.000000 -4 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 5 1 1 total 0.000000 0.000000 -5 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 6 1 1 total 0.000178 0.000178 diff --git a/tests/regression_tests/mgxs_library_distribcell/test.py b/tests/regression_tests/mgxs_library_distribcell/test.py deleted file mode 100644 index 5290d313b..000000000 --- a/tests/regression_tests/mgxs_library_distribcell/test.py +++ /dev/null @@ -1,70 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_assembly - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a one-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 20.e6]) - - # Initialize MGXS Library for a few cross section types - # for one material-filled cell in the geometry - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ - openmc.mgxs.MDGXS_TYPES - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.num_delayed_groups = 6 - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'distribcell' - cells = self.mgxs_lib.geometry.get_all_material_cells().values() - self.mgxs_lib.domains = [c for c in cells if c.name == 'fuel'] - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - self._model.tallies.export_to_xml() - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Average the MGXS across distribcell subdomains - avg_lib = self.mgxs_lib.get_subdomain_avg_library() - - # Build a string from Pandas Dataframe for each 1-group MGXS - outstr = '' - for domain in avg_lib.domains: - for mgxs_type in avg_lib.mgxs_types: - mgxs = avg_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_distribcell(): - model = pwr_assembly() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_hdf5/__init__.py b/tests/regression_tests/mgxs_library_hdf5/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat deleted file mode 100644 index 5aedd383d..000000000 --- a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat +++ /dev/null @@ -1,1178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 2 3 4 5 6 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 52 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 52 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 52 - total - delayed-nu-fission - analog - - - 1 65 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 65 2 5 - total - delayed-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - nu-scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - nu-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - kappa-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 - total - flux - analog - - - 80 2 - total - nu-scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - nu-scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 - total - nu-fission - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 52 - total - nu-fission - analog - - - 80 5 - total - nu-fission - analog - - - 80 52 - total - prompt-nu-fission - analog - - - 80 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - inverse-velocity - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - prompt-nu-fission - tracklength - - - 80 2 - total - flux - analog - - - 80 2 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 52 - total - delayed-nu-fission - analog - - - 80 65 5 - total - delayed-nu-fission - analog - - - 80 2 - total - nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - decay-rate - tracklength - - - 80 2 - total - flux - analog - - - 80 65 2 5 - total - delayed-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - nu-scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - nu-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - kappa-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 - total - flux - analog - - - 159 2 - total - nu-scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - nu-scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 - total - nu-fission - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 52 - total - nu-fission - analog - - - 159 5 - total - nu-fission - analog - - - 159 52 - total - prompt-nu-fission - analog - - - 159 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - inverse-velocity - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - prompt-nu-fission - tracklength - - - 159 2 - total - flux - analog - - - 159 2 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 52 - total - delayed-nu-fission - analog - - - 159 65 5 - total - delayed-nu-fission - analog - - - 159 2 - total - nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - decay-rate - tracklength - - - 159 2 - total - flux - analog - - - 159 65 2 5 - total - delayed-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_hdf5/results_true.dat b/tests/regression_tests/mgxs_library_hdf5/results_true.dat deleted file mode 100644 index 7ef172574..000000000 --- a/tests/regression_tests/mgxs_library_hdf5/results_true.dat +++ /dev/null @@ -1,579 +0,0 @@ -domain=1 type=total -[4.14825464e-01 6.60169863e-01] -[2.27929104e-02 4.75189000e-02] -domain=1 type=transport -[3.63092031e-01 6.44850709e-01] -[2.38384842e-02 4.76746410e-02] -domain=1 type=nu-transport -[3.63092031e-01 6.44850709e-01] -[2.38384842e-02 4.76746410e-02] -domain=1 type=absorption -[2.74078431e-02 2.64510714e-01] -[2.69249666e-03 2.33670618e-02] -domain=1 type=capture -[1.98445482e-02 7.17193458e-02] -[2.64330389e-03 2.52078411e-02] -domain=1 type=fission -[7.56329484e-03 1.92791369e-01] -[5.08483893e-04 1.71059103e-02] -domain=1 type=nu-fission -[1.94317397e-02 4.69774728e-01] -[1.32297610e-03 4.16819717e-02] -domain=1 type=kappa-fission -[1.47456979e+06 3.72868925e+07] -[9.92353624e+04 3.30837549e+06] -domain=1 type=scatter -[3.87417621e-01 3.95659148e-01] -[2.06257342e-02 2.51250448e-02] -domain=1 type=nu-scatter -[3.85188361e-01 4.12389370e-01] -[2.69456191e-02 1.54252759e-02] -domain=1 type=scatter matrix -[[[3.84199430e-01 5.18702806e-02 2.00688439e-02 9.47771502e-03] - [9.88930322e-04 -2.07234582e-04 -1.03366173e-04 2.34290606e-04]] - - [[9.24639842e-04 -7.67704913e-04 4.93788836e-04 -1.71497217e-04] - [4.11464730e-01 1.64817268e-02 6.37149004e-03 -1.04991213e-02]]] -[[[2.70010116e-02 6.98254837e-03 2.84649498e-03 2.23351961e-03] - [4.82419410e-04 1.49010765e-04 1.84316299e-04 1.28173102e-04]] - - [[9.24883397e-04 7.67907131e-04 4.93918903e-04 1.71542390e-04] - [1.52449343e-02 4.50172764e-03 1.05507486e-02 1.04381870e-02]]] -domain=1 type=nu-scatter matrix -[[[3.84199430e-01 5.18702806e-02 2.00688439e-02 9.47771502e-03] - [9.88930322e-04 -2.07234582e-04 -1.03366173e-04 2.34290606e-04]] - - [[9.24639842e-04 -7.67704913e-04 4.93788836e-04 -1.71497217e-04] - [4.11464730e-01 1.64817268e-02 6.37149004e-03 -1.04991213e-02]]] -[[[2.70010116e-02 6.98254837e-03 2.84649498e-03 2.23351961e-03] - [4.82419410e-04 1.49010765e-04 1.84316299e-04 1.28173102e-04]] - - [[9.24883397e-04 7.67907131e-04 4.93918903e-04 1.71542390e-04] - [1.52449343e-02 4.50172764e-03 1.05507486e-02 1.04381870e-02]]] -domain=1 type=multiplicity matrix -[[1.00000000e+00 1.00000000e+00] - [1.00000000e+00 1.00000000e+00]] -[[7.85164550e-02 6.87184271e-01] - [1.41421356e+00 4.11303488e-02]] -domain=1 type=nu-fission matrix -[[2.01424221e-02 0.00000000e+00] - [4.54366342e-01 0.00000000e+00]] -[[3.14909051e-03 0.00000000e+00] - [2.74255160e-02 0.00000000e+00]] -domain=1 type=scatter probability matrix -[[9.97432606e-01 2.56739409e-03] - [2.24215247e-03 9.97757848e-01]] -[[7.82243018e-02 1.25560869e-03] - [2.24310192e-03 4.10531468e-02]] -domain=1 type=consistent scatter matrix -[[[3.86422967e-01 5.21704775e-02 2.01849914e-02 9.53256688e-03] - [9.94653712e-04 -2.08433942e-04 -1.03964400e-04 2.35646553e-04]] - - [[8.87128136e-04 -7.36559899e-04 4.73756321e-04 -1.64539748e-04] - [3.94772020e-01 1.58130798e-02 6.11300510e-03 -1.00731826e-02]]] -[[[3.66286904e-02 7.76748967e-03 3.13767805e-03 2.32683668e-03] - [4.89318749e-04 1.50458419e-04 1.85500930e-04 1.29783343e-04]] - - [[8.89289900e-04 7.38354757e-04 4.74910776e-04 1.64940700e-04] - [2.98710065e-02 4.44330993e-03 1.01307463e-02 1.00367467e-02]]] -domain=1 type=consistent nu-scatter matrix -[[[3.86422967e-01 5.21704775e-02 2.01849914e-02 9.53256688e-03] - [9.94653712e-04 -2.08433942e-04 -1.03964400e-04 2.35646553e-04]] - - [[8.87128136e-04 -7.36559899e-04 4.73756321e-04 -1.64539748e-04] - [3.94772020e-01 1.58130798e-02 6.11300510e-03 -1.00731826e-02]]] -[[[4.75627021e-02 8.78140568e-03 3.51522199e-03 2.44425169e-03] - [8.40606499e-04 2.07733706e-04 1.98782933e-04 2.07523215e-04]] - - [[1.53780011e-03 1.27679627e-03 8.21237084e-04 2.85222881e-04] - [3.39988353e-02 4.49065920e-03 1.01338659e-02 1.00452944e-02]]] -domain=1 type=chi -[1.00000000e+00 0.00000000e+00] -[4.60705491e-02 0.00000000e+00] -domain=1 type=chi-prompt -[1.00000000e+00 0.00000000e+00] -[5.14714842e-02 0.00000000e+00] -domain=1 type=inverse-velocity -[5.70932437e-08 2.85573948e-06] -[4.68793809e-09 2.44216369e-07] -domain=1 type=prompt-nu-fission -[1.92392209e-02 4.66718979e-01] -[1.30950644e-03 4.14108425e-02] -domain=1 type=prompt-nu-fission matrix -[[2.01424221e-02 0.00000000e+00] - [4.45819054e-01 0.00000000e+00]] -[[3.14909051e-03 0.00000000e+00] - [2.86750876e-02 0.00000000e+00]] -domain=1 type=delayed-nu-fission -[[4.31687649e-06 1.06974147e-04] - [2.69760050e-05 5.52167849e-04] - [2.84366794e-05 5.27147626e-04] - [7.42603126e-05 1.18190938e-03] - [4.14908415e-05 4.84567103e-04] - [1.70015984e-05 2.02983424e-04]] -[[2.89748551e-07 9.49155602e-06] - [1.85003750e-06 4.89925096e-05] - [1.97097929e-06 4.67725252e-05] - [5.22610328e-06 1.04867938e-04] - [2.99830754e-06 4.29944540e-05] - [1.22654681e-06 1.80102229e-05]] -domain=1 type=chi-delayed -[[0.00000000e+00 0.00000000e+00] - [1.00000000e+00 0.00000000e+00] - [1.00000000e+00 0.00000000e+00] - [1.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [8.69127748e-01 0.00000000e+00] - [1.41421356e+00 0.00000000e+00] - [3.60359016e-01 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=1 type=beta -[[2.22155945e-04 2.27713711e-04] - [1.38824446e-03 1.17538858e-03] - [1.46341397e-03 1.12212853e-03] - [3.82159878e-03 2.51590670e-03] - [2.13520982e-03 1.03148823e-03] - [8.74939592e-04 4.32086725e-04]] -[[1.80847601e-05 2.46946655e-05] - [1.14688936e-04 1.27466313e-04] - [1.21787671e-04 1.21690467e-04] - [3.21434951e-04 2.72840272e-04] - [1.82980530e-04 1.11860871e-04] - [7.48900063e-05 4.68581181e-05]] -domain=1 type=decay-rate -[[1.34450193e-02 1.33360001e-02] - [3.20638663e-02 3.27389978e-02] - [1.22136025e-01 1.20780007e-01] - [3.15269336e-01 3.02780066e-01] - [8.89232587e-01 8.49490287e-01] - [2.98940409e+00 2.85300088e+00]] -[[1.08439455e-03 1.44623725e-03] - [2.65795038e-03 3.55041661e-03] - [1.02955036e-02 1.30981202e-02] - [2.71748571e-02 3.28353145e-02] - [7.93682889e-02 9.21238900e-02] - [2.66253283e-01 3.09396760e-01]] -domain=1 type=delayed-nu-fission matrix -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [2.53814444e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [1.18579136e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [4.82335163e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [1.56094521e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [1.18610370e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [1.23402593e-03 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] -domain=2 type=total -[3.13737667e-01 3.00821380e-01] -[1.55819228e-02 2.80524816e-02] -domain=2 type=transport -[2.75508079e-01 3.12035015e-01] -[1.77418859e-02 3.23843473e-02] -domain=2 type=nu-transport -[2.75508079e-01 3.12035015e-01] -[1.77418859e-02 3.23843473e-02] -domain=2 type=absorption -[1.57499139e-03 5.40037825e-03] -[3.22547917e-04 6.18139027e-04] -domain=2 type=capture -[1.57499139e-03 5.40037825e-03] -[3.22547917e-04 6.18139027e-04] -domain=2 type=fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=nu-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=kappa-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=scatter -[3.12162675e-01 2.95421002e-01] -[1.53219435e-02 2.74455213e-02] -domain=2 type=nu-scatter -[3.10120713e-01 2.96264249e-01] -[3.37881037e-02 4.37922226e-02] -domain=2 type=scatter matrix -[[[3.10120713e-01 3.82295876e-02 2.07449405e-02 7.96429620e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [2.96264249e-01 -1.12136353e-02 8.83656566e-03 -3.27006707e-03]]] -[[[3.37881037e-02 8.48399649e-03 4.69561034e-03 3.73162234e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [4.37922226e-02 1.61803653e-02 1.15039636e-02 7.32884528e-03]]] -domain=2 type=nu-scatter matrix -[[[3.10120713e-01 3.82295876e-02 2.07449405e-02 7.96429620e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [2.96264249e-01 -1.12136353e-02 8.83656566e-03 -3.27006707e-03]]] -[[[3.37881037e-02 8.48399649e-03 4.69561034e-03 3.73162234e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [4.37922226e-02 1.61803653e-02 1.15039636e-02 7.32884528e-03]]] -domain=2 type=multiplicity matrix -[[1.00000000e+00 0.00000000e+00] - [0.00000000e+00 1.00000000e+00]] -[[1.08778697e-01 0.00000000e+00] - [0.00000000e+00 1.42427173e-01]] -domain=2 type=nu-fission matrix -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=scatter probability matrix -[[1.00000000e+00 0.00000000e+00] - [0.00000000e+00 1.00000000e+00]] -[[1.08778697e-01 0.00000000e+00] - [0.00000000e+00 1.42427173e-01]] -domain=2 type=consistent scatter matrix -[[[3.12162675e-01 3.84813069e-02 2.08815337e-02 8.01673640e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [2.95421002e-01 -1.11817183e-02 8.81141444e-03 -3.26075959e-03]]] -[[[3.72534020e-02 8.74305414e-03 4.83468236e-03 3.77642683e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [5.02358893e-02 1.61616720e-02 1.14951123e-02 7.31312479e-03]]] -domain=2 type=consistent nu-scatter matrix -[[[3.12162675e-01 3.84813069e-02 2.08815337e-02 8.01673640e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [2.95421002e-01 -1.11817183e-02 8.81141444e-03 -3.26075959e-03]]] -[[[5.04070429e-02 9.69345878e-03 5.34169556e-03 3.87580585e-03] - [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] - [6.55288678e-02 1.62399493e-02 1.15634161e-02 7.32785650e-03]]] -domain=2 type=chi -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=chi-prompt -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=inverse-velocity -[5.99597928e-08 2.98549016e-06] -[4.55308451e-09 3.41701982e-07] -domain=2 type=prompt-nu-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=2 type=prompt-nu-fission matrix -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=delayed-nu-fission -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=chi-delayed -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=beta -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=decay-rate -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=2 type=delayed-nu-fission matrix -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] -domain=3 type=total -[6.64572194e-01 2.05238389e+00] -[3.12147473e-02 2.24342890e-01] -domain=3 type=transport -[2.83322749e-01 1.49973953e+00] -[3.52061127e-02 2.30902118e-01] -domain=3 type=nu-transport -[2.83322749e-01 1.49973953e+00] -[3.52061127e-02 2.30902118e-01] -domain=3 type=absorption -[6.90399488e-04 3.16872537e-02] -[4.41475703e-05 3.74655812e-03] -domain=3 type=capture -[6.90399488e-04 3.16872537e-02] -[4.41475703e-05 3.74655812e-03] -domain=3 type=fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=nu-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=kappa-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=scatter -[6.63881795e-01 2.02069663e+00] -[3.11726794e-02 2.20604438e-01] -domain=3 type=nu-scatter -[6.71269157e-01 2.03538818e+00] -[2.61863693e-02 2.58060310e-01] -domain=3 type=scatter matrix -[[[6.39901439e-01 3.81167422e-01 1.52391887e-01 9.14802163e-03] - [3.13677176e-02 8.75772258e-03 -2.56790088e-03 -3.78480261e-03]] - - [[4.43343102e-04 3.99960385e-04 3.19562684e-04 2.13846954e-04] - [2.03494484e+00 5.09940476e-01 1.11174601e-01 2.49884339e-02]]] -[[[2.47091210e-02 1.62432637e-02 8.15627711e-03 3.88856186e-03] - [1.72811278e-03 9.25670435e-04 1.01398468e-03 8.17075512e-04]] - - [[4.44850361e-04 4.01320154e-04 3.20649120e-04 2.14573982e-04] - [2.57799870e-01 5.12359026e-02 1.30198161e-02 8.31235196e-03]]] -domain=3 type=nu-scatter matrix -[[[6.39901439e-01 3.81167422e-01 1.52391887e-01 9.14802163e-03] - [3.13677176e-02 8.75772258e-03 -2.56790088e-03 -3.78480261e-03]] - - [[4.43343102e-04 3.99960385e-04 3.19562684e-04 2.13846954e-04] - [2.03494484e+00 5.09940476e-01 1.11174601e-01 2.49884339e-02]]] -[[[2.47091210e-02 1.62432637e-02 8.15627711e-03 3.88856186e-03] - [1.72811278e-03 9.25670435e-04 1.01398468e-03 8.17075512e-04]] - - [[4.44850361e-04 4.01320154e-04 3.20649120e-04 2.14573982e-04] - [2.57799870e-01 5.12359026e-02 1.30198161e-02 8.31235196e-03]]] -domain=3 type=multiplicity matrix -[[1.00000000e+00 1.00000000e+00] - [1.00000000e+00 1.00000000e+00]] -[[3.86091908e-02 6.76673480e-02] - [1.41421356e+00 1.35929207e-01]] -domain=3 type=nu-fission matrix -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=scatter probability matrix -[[9.53271028e-01 4.67289720e-02] - [2.17817469e-04 9.99782183e-01]] -[[3.60184962e-02 2.54736726e-03] - [2.18820864e-04 1.35884974e-01]] -domain=3 type=consistent scatter matrix -[[[6.32859281e-01 3.76972649e-01 1.50714804e-01 9.04734705e-03] - [3.10225138e-02 8.66134326e-03 -2.53964096e-03 -3.74315061e-03]] - - [[4.40143026e-04 3.97073448e-04 3.17256062e-04 2.12303394e-04] - [2.02025649e+00 5.06259696e-01 1.10372136e-01 2.48080660e-02]]] -[[[3.81421848e-02 2.37145043e-02 1.06635009e-02 3.86848985e-03] - [2.23201039e-03 9.99377011e-04 1.00968851e-03 8.26439590e-04]] - - [[4.44773843e-04 4.01251123e-04 3.20593966e-04 2.14537073e-04] - [3.52193929e-01 7.91402819e-02 1.84875925e-02 8.77085752e-03]]] -domain=3 type=consistent nu-scatter matrix -[[[6.32859281e-01 3.76972649e-01 1.50714804e-01 9.04734705e-03] - [3.10225138e-02 8.66134326e-03 -2.53964096e-03 -3.74315061e-03]] - - [[4.40143026e-04 3.97073448e-04 3.17256062e-04 2.12303394e-04] - [2.02025649e+00 5.06259696e-01 1.10372136e-01 2.48080660e-02]]] -[[[4.52974133e-02 2.78247077e-02 1.21478698e-02 3.88422859e-03] - [3.06407542e-03 1.15855774e-03 1.02420876e-03 8.64382873e-04]] - - [[7.65033031e-04 6.90171798e-04 5.51437493e-04 3.69014387e-04] - [4.46600759e-01 1.04874946e-01 2.38091367e-02 9.39676938e-03]]] -domain=3 type=chi -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=chi-prompt -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=inverse-velocity -[6.02207835e-08 3.04495548e-06] -[3.78043705e-09 3.60007679e-07] -domain=3 type=prompt-nu-fission -[0.00000000e+00 0.00000000e+00] -[0.00000000e+00 0.00000000e+00] -domain=3 type=prompt-nu-fission matrix -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=delayed-nu-fission -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=chi-delayed -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=beta -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=decay-rate -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] -domain=3 type=delayed-nu-fission matrix -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] -[[[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]] - - [[0.00000000e+00 0.00000000e+00] - [0.00000000e+00 0.00000000e+00]]] diff --git a/tests/regression_tests/mgxs_library_hdf5/test.py b/tests/regression_tests/mgxs_library_hdf5/test.py deleted file mode 100644 index 9811ab215..000000000 --- a/tests/regression_tests/mgxs_library_hdf5/test.py +++ /dev/null @@ -1,83 +0,0 @@ -import os -import hashlib - -import numpy as np -import h5py -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ - openmc.mgxs.MDGXS_TYPES - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.num_delayed_groups = 6 - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Export the MGXS Library to an HDF5 file - self.mgxs_lib.build_hdf5_store(directory='.') - - # Open the MGXS HDF5 file - with h5py.File('mgxs.h5', 'r') as f: - - # Build a string from the datasets in the HDF5 file - outstr = '' - for domain in self.mgxs_lib.domains: - for mgxs_type in self.mgxs_lib.mgxs_types: - outstr += 'domain={0} type={1}\n'.format(domain.id, mgxs_type) - avg_key = 'material/{0}/{1}/average'.format(domain.id, mgxs_type) - std_key = 'material/{0}/{1}/std. dev.'.format(domain.id, mgxs_type) - outstr += '{}\n{}\n'.format(f[avg_key][...], f[std_key][...]) - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - def _cleanup(self): - super()._cleanup() - f = 'mgxs.h5' - if os.path.exists(f): - os.remove(f) - - -def test_mgxs_library_hdf5(): - try: - np.set_printoptions(formatter={'float_kind': '{:.8e}'.format}) - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() - finally: - np.set_printoptions(formatter=None) diff --git a/tests/regression_tests/mgxs_library_histogram/__init__.py b/tests/regression_tests/mgxs_library_histogram/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_histogram/inputs_true.dat b/tests/regression_tests/mgxs_library_histogram/inputs_true.dat deleted file mode 100644 index d1bd197a7..000000000 --- a/tests/regression_tests/mgxs_library_histogram/inputs_true.dat +++ /dev/null @@ -1,269 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - -1.0 -0.8181818181818181 -0.6363636363636364 -0.4545454545454546 -0.2727272727272727 -0.09090909090909083 0.09090909090909083 0.2727272727272727 0.4545454545454546 0.6363636363636365 0.8181818181818183 1.0 - - - 2 - - - 3 - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 3 4 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 4 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 3 4 - total - scatter - analog - - - 1 2 3 - total - nu-scatter - analog - - - 17 2 - total - flux - analog - - - 17 2 3 4 - total - scatter - analog - - - 17 2 - total - flux - analog - - - 17 2 3 4 - total - nu-scatter - analog - - - 17 2 - total - flux - tracklength - - - 17 2 - total - scatter - tracklength - - - 17 2 3 4 - total - scatter - analog - - - 17 2 - total - flux - tracklength - - - 17 2 - total - scatter - tracklength - - - 17 2 3 4 - total - scatter - analog - - - 17 2 3 - total - nu-scatter - analog - - - 33 2 - total - flux - analog - - - 33 2 3 4 - total - scatter - analog - - - 33 2 - total - flux - analog - - - 33 2 3 4 - total - nu-scatter - analog - - - 33 2 - total - flux - tracklength - - - 33 2 - total - scatter - tracklength - - - 33 2 3 4 - total - scatter - analog - - - 33 2 - total - flux - tracklength - - - 33 2 - total - scatter - tracklength - - - 33 2 3 4 - total - scatter - analog - - - 33 2 3 - total - nu-scatter - analog - - diff --git a/tests/regression_tests/mgxs_library_histogram/results_true.dat b/tests/regression_tests/mgxs_library_histogram/results_true.dat deleted file mode 100644 index 20625efd0..000000000 --- a/tests/regression_tests/mgxs_library_histogram/results_true.dat +++ /dev/null @@ -1,540 +0,0 @@ - material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025383 0.001933 -34 1 1 1 2 total 0.027855 0.001701 -35 1 1 1 3 total 0.031646 0.002913 -36 1 1 1 4 total 0.028185 0.001430 -37 1 1 1 5 total 0.030162 0.002739 -38 1 1 1 6 total 0.029009 0.002713 -39 1 1 1 7 total 0.030492 0.002907 -40 1 1 1 8 total 0.035272 0.003860 -41 1 1 1 9 total 0.043678 0.006074 -42 1 1 1 10 total 0.044502 0.003030 -43 1 1 1 11 total 0.058017 0.004319 -22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000165 0.000165 -24 1 1 2 3 total 0.000330 0.000202 -25 1 1 2 4 total 0.000165 0.000165 -26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000165 0.000165 -28 1 1 2 7 total 0.000000 0.000000 -29 1 1 2 8 total 0.000000 0.000000 -30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000165 0.000165 -32 1 1 2 11 total 0.000000 0.000000 -11 1 2 1 1 total 0.000925 0.000925 -12 1 2 1 2 total 0.000000 0.000000 -13 1 2 1 3 total 0.000000 0.000000 -14 1 2 1 4 total 0.000000 0.000000 -15 1 2 1 5 total 0.000000 0.000000 -16 1 2 1 6 total 0.000000 0.000000 -17 1 2 1 7 total 0.000000 0.000000 -18 1 2 1 8 total 0.000000 0.000000 -19 1 2 1 9 total 0.000000 0.000000 -20 1 2 1 10 total 0.000000 0.000000 -21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.037910 0.006498 -1 1 2 2 2 total 0.031438 0.002377 -2 1 2 2 3 total 0.036986 0.006429 -3 1 2 2 4 total 0.029588 0.005627 -4 1 2 2 5 total 0.036986 0.007359 -5 1 2 2 6 total 0.035136 0.004110 -6 1 2 2 7 total 0.037910 0.003188 -7 1 2 2 8 total 0.041609 0.004489 -8 1 2 2 9 total 0.040684 0.007710 -9 1 2 2 10 total 0.043458 0.004638 -10 1 2 2 11 total 0.039760 0.002920 - material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025383 0.001933 -34 1 1 1 2 total 0.027855 0.001701 -35 1 1 1 3 total 0.031646 0.002913 -36 1 1 1 4 total 0.028185 0.001430 -37 1 1 1 5 total 0.030162 0.002739 -38 1 1 1 6 total 0.029009 0.002713 -39 1 1 1 7 total 0.030492 0.002907 -40 1 1 1 8 total 0.035272 0.003860 -41 1 1 1 9 total 0.043678 0.006074 -42 1 1 1 10 total 0.044502 0.003030 -43 1 1 1 11 total 0.058017 0.004319 -22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000165 0.000165 -24 1 1 2 3 total 0.000330 0.000202 -25 1 1 2 4 total 0.000165 0.000165 -26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000165 0.000165 -28 1 1 2 7 total 0.000000 0.000000 -29 1 1 2 8 total 0.000000 0.000000 -30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000165 0.000165 -32 1 1 2 11 total 0.000000 0.000000 -11 1 2 1 1 total 0.000925 0.000925 -12 1 2 1 2 total 0.000000 0.000000 -13 1 2 1 3 total 0.000000 0.000000 -14 1 2 1 4 total 0.000000 0.000000 -15 1 2 1 5 total 0.000000 0.000000 -16 1 2 1 6 total 0.000000 0.000000 -17 1 2 1 7 total 0.000000 0.000000 -18 1 2 1 8 total 0.000000 0.000000 -19 1 2 1 9 total 0.000000 0.000000 -20 1 2 1 10 total 0.000000 0.000000 -21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.037910 0.006498 -1 1 2 2 2 total 0.031438 0.002377 -2 1 2 2 3 total 0.036986 0.006429 -3 1 2 2 4 total 0.029588 0.005627 -4 1 2 2 5 total 0.036986 0.007359 -5 1 2 2 6 total 0.035136 0.004110 -6 1 2 2 7 total 0.037910 0.003188 -7 1 2 2 8 total 0.041609 0.004489 -8 1 2 2 9 total 0.040684 0.007710 -9 1 2 2 10 total 0.043458 0.004638 -10 1 2 2 11 total 0.039760 0.002920 - material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025529 0.002197 -34 1 1 1 2 total 0.028016 0.002047 -35 1 1 1 3 total 0.031829 0.003196 -36 1 1 1 4 total 0.028348 0.001833 -37 1 1 1 5 total 0.030337 0.003012 -38 1 1 1 6 total 0.029177 0.002969 -39 1 1 1 7 total 0.030668 0.003172 -40 1 1 1 8 total 0.035476 0.004135 -41 1 1 1 9 total 0.043931 0.006358 -42 1 1 1 10 total 0.044759 0.003536 -43 1 1 1 11 total 0.058353 0.004934 -22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000166 0.000166 -24 1 1 2 3 total 0.000332 0.000204 -25 1 1 2 4 total 0.000166 0.000166 -26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000166 0.000166 -28 1 1 2 7 total 0.000000 0.000000 -29 1 1 2 8 total 0.000000 0.000000 -30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000166 0.000166 -32 1 1 2 11 total 0.000000 0.000000 -11 1 2 1 1 total 0.000887 0.000890 -12 1 2 1 2 total 0.000000 0.000000 -13 1 2 1 3 total 0.000000 0.000000 -14 1 2 1 4 total 0.000000 0.000000 -15 1 2 1 5 total 0.000000 0.000000 -16 1 2 1 6 total 0.000000 0.000000 -17 1 2 1 7 total 0.000000 0.000000 -18 1 2 1 8 total 0.000000 0.000000 -19 1 2 1 9 total 0.000000 0.000000 -20 1 2 1 10 total 0.000000 0.000000 -21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.036372 0.006773 -1 1 2 2 2 total 0.030162 0.003165 -2 1 2 2 3 total 0.035485 0.006687 -3 1 2 2 4 total 0.028388 0.005781 -4 1 2 2 5 total 0.035485 0.007518 -5 1 2 2 6 total 0.033711 0.004644 -6 1 2 2 7 total 0.036372 0.004045 -7 1 2 2 8 total 0.039921 0.005195 -8 1 2 2 9 total 0.039034 0.007923 -9 1 2 2 10 total 0.041695 0.005386 -10 1 2 2 11 total 0.038147 0.003944 - material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025529 0.002692 -34 1 1 1 2 total 0.028016 0.002666 -35 1 1 1 3 total 0.031829 0.003739 -36 1 1 1 4 total 0.028348 0.002519 -37 1 1 1 5 total 0.030337 0.003534 -38 1 1 1 6 total 0.029177 0.003461 -39 1 1 1 7 total 0.030668 0.003682 -40 1 1 1 8 total 0.035476 0.004666 -41 1 1 1 9 total 0.043931 0.006899 -42 1 1 1 10 total 0.044759 0.004466 -43 1 1 1 11 total 0.058353 0.006082 -22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000166 0.000196 -24 1 1 2 3 total 0.000332 0.000290 -25 1 1 2 4 total 0.000166 0.000196 -26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000166 0.000196 -28 1 1 2 7 total 0.000000 0.000000 -29 1 1 2 8 total 0.000000 0.000000 -30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000166 0.000196 -32 1 1 2 11 total 0.000000 0.000000 -11 1 2 1 1 total 0.000887 0.001538 -12 1 2 1 2 total 0.000000 0.000000 -13 1 2 1 3 total 0.000000 0.000000 -14 1 2 1 4 total 0.000000 0.000000 -15 1 2 1 5 total 0.000000 0.000000 -16 1 2 1 6 total 0.000000 0.000000 -17 1 2 1 7 total 0.000000 0.000000 -18 1 2 1 8 total 0.000000 0.000000 -19 1 2 1 9 total 0.000000 0.000000 -20 1 2 1 10 total 0.000000 0.000000 -21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.036372 0.007026 -1 1 2 2 2 total 0.030162 0.003524 -2 1 2 2 3 total 0.035485 0.006931 -3 1 2 2 4 total 0.028388 0.005962 -4 1 2 2 5 total 0.035485 0.007736 -5 1 2 2 6 total 0.033711 0.004957 -6 1 2 2 7 total 0.036372 0.004455 -7 1 2 2 8 total 0.039921 0.005585 -8 1 2 2 9 total 0.039034 0.008173 -9 1 2 2 10 total 0.041695 0.005796 -10 1 2 2 11 total 0.038147 0.004404 - material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026289 0.004089 -34 2 1 1 2 total 0.018269 0.002939 -35 2 1 1 3 total 0.025398 0.002153 -36 2 1 1 4 total 0.024061 0.005097 -37 2 1 1 5 total 0.022279 0.003375 -38 2 1 1 6 total 0.027626 0.004817 -39 2 1 1 7 total 0.025843 0.003039 -40 2 1 1 8 total 0.026735 0.006742 -41 2 1 1 9 total 0.027626 0.005213 -42 2 1 1 10 total 0.036537 0.005920 -43 2 1 1 11 total 0.049459 0.004153 -22 2 1 2 1 total 0.000000 0.000000 -23 2 1 2 2 total 0.000000 0.000000 -24 2 1 2 3 total 0.000000 0.000000 -25 2 1 2 4 total 0.000000 0.000000 -26 2 1 2 5 total 0.000000 0.000000 -27 2 1 2 6 total 0.000000 0.000000 -28 2 1 2 7 total 0.000000 0.000000 -29 2 1 2 8 total 0.000000 0.000000 -30 2 1 2 9 total 0.000000 0.000000 -31 2 1 2 10 total 0.000000 0.000000 -32 2 1 2 11 total 0.000000 0.000000 -11 2 2 1 1 total 0.000000 0.000000 -12 2 2 1 2 total 0.000000 0.000000 -13 2 2 1 3 total 0.000000 0.000000 -14 2 2 1 4 total 0.000000 0.000000 -15 2 2 1 5 total 0.000000 0.000000 -16 2 2 1 6 total 0.000000 0.000000 -17 2 2 1 7 total 0.000000 0.000000 -18 2 2 1 8 total 0.000000 0.000000 -19 2 2 1 9 total 0.000000 0.000000 -20 2 2 1 10 total 0.000000 0.000000 -21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024485 0.007210 -1 2 2 2 2 total 0.036727 0.005548 -2 2 2 2 3 total 0.041624 0.010918 -3 2 2 2 4 total 0.019588 0.008569 -4 2 2 2 5 total 0.022036 0.007526 -5 2 2 2 6 total 0.019588 0.011549 -6 2 2 2 7 total 0.022036 0.006454 -7 2 2 2 8 total 0.036727 0.010282 -8 2 2 2 9 total 0.022036 0.005164 -9 2 2 2 10 total 0.031830 0.011864 -10 2 2 2 11 total 0.019588 0.005336 - material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026289 0.004089 -34 2 1 1 2 total 0.018269 0.002939 -35 2 1 1 3 total 0.025398 0.002153 -36 2 1 1 4 total 0.024061 0.005097 -37 2 1 1 5 total 0.022279 0.003375 -38 2 1 1 6 total 0.027626 0.004817 -39 2 1 1 7 total 0.025843 0.003039 -40 2 1 1 8 total 0.026735 0.006742 -41 2 1 1 9 total 0.027626 0.005213 -42 2 1 1 10 total 0.036537 0.005920 -43 2 1 1 11 total 0.049459 0.004153 -22 2 1 2 1 total 0.000000 0.000000 -23 2 1 2 2 total 0.000000 0.000000 -24 2 1 2 3 total 0.000000 0.000000 -25 2 1 2 4 total 0.000000 0.000000 -26 2 1 2 5 total 0.000000 0.000000 -27 2 1 2 6 total 0.000000 0.000000 -28 2 1 2 7 total 0.000000 0.000000 -29 2 1 2 8 total 0.000000 0.000000 -30 2 1 2 9 total 0.000000 0.000000 -31 2 1 2 10 total 0.000000 0.000000 -32 2 1 2 11 total 0.000000 0.000000 -11 2 2 1 1 total 0.000000 0.000000 -12 2 2 1 2 total 0.000000 0.000000 -13 2 2 1 3 total 0.000000 0.000000 -14 2 2 1 4 total 0.000000 0.000000 -15 2 2 1 5 total 0.000000 0.000000 -16 2 2 1 6 total 0.000000 0.000000 -17 2 2 1 7 total 0.000000 0.000000 -18 2 2 1 8 total 0.000000 0.000000 -19 2 2 1 9 total 0.000000 0.000000 -20 2 2 1 10 total 0.000000 0.000000 -21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024485 0.007210 -1 2 2 2 2 total 0.036727 0.005548 -2 2 2 2 3 total 0.041624 0.010918 -3 2 2 2 4 total 0.019588 0.008569 -4 2 2 2 5 total 0.022036 0.007526 -5 2 2 2 6 total 0.019588 0.011549 -6 2 2 2 7 total 0.022036 0.006454 -7 2 2 2 8 total 0.036727 0.010282 -8 2 2 2 9 total 0.022036 0.005164 -9 2 2 2 10 total 0.031830 0.011864 -10 2 2 2 11 total 0.019588 0.005336 - material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026462 0.003961 -34 2 1 1 2 total 0.018389 0.002854 -35 2 1 1 3 total 0.025565 0.001877 -36 2 1 1 4 total 0.024220 0.005027 -37 2 1 1 5 total 0.022425 0.003262 -38 2 1 1 6 total 0.027808 0.004704 -39 2 1 1 7 total 0.026014 0.002854 -40 2 1 1 8 total 0.026911 0.006690 -41 2 1 1 9 total 0.027808 0.005114 -42 2 1 1 10 total 0.036778 0.005752 -43 2 1 1 11 total 0.049785 0.003610 -22 2 1 2 1 total 0.000000 0.000000 -23 2 1 2 2 total 0.000000 0.000000 -24 2 1 2 3 total 0.000000 0.000000 -25 2 1 2 4 total 0.000000 0.000000 -26 2 1 2 5 total 0.000000 0.000000 -27 2 1 2 6 total 0.000000 0.000000 -28 2 1 2 7 total 0.000000 0.000000 -29 2 1 2 8 total 0.000000 0.000000 -30 2 1 2 9 total 0.000000 0.000000 -31 2 1 2 10 total 0.000000 0.000000 -32 2 1 2 11 total 0.000000 0.000000 -11 2 2 1 1 total 0.000000 0.000000 -12 2 2 1 2 total 0.000000 0.000000 -13 2 2 1 3 total 0.000000 0.000000 -14 2 2 1 4 total 0.000000 0.000000 -15 2 2 1 5 total 0.000000 0.000000 -16 2 2 1 6 total 0.000000 0.000000 -17 2 2 1 7 total 0.000000 0.000000 -18 2 2 1 8 total 0.000000 0.000000 -19 2 2 1 9 total 0.000000 0.000000 -20 2 2 1 10 total 0.000000 0.000000 -21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024415 0.007393 -1 2 2 2 2 total 0.036622 0.006106 -2 2 2 2 3 total 0.041505 0.011274 -3 2 2 2 4 total 0.019532 0.008656 -4 2 2 2 5 total 0.021973 0.007663 -5 2 2 2 6 total 0.019532 0.011599 -6 2 2 2 7 total 0.021973 0.006620 -7 2 2 2 8 total 0.036622 0.010574 -8 2 2 2 9 total 0.021973 0.005378 -9 2 2 2 10 total 0.031739 0.012040 -10 2 2 2 11 total 0.019532 0.005496 - material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026462 0.004589 -34 2 1 1 2 total 0.018389 0.003277 -35 2 1 1 3 total 0.025565 0.002922 -36 2 1 1 4 total 0.024220 0.005456 -37 2 1 1 5 total 0.022425 0.003808 -38 2 1 1 6 total 0.027808 0.005297 -39 2 1 1 7 total 0.026014 0.003652 -40 2 1 1 8 total 0.026911 0.007093 -41 2 1 1 9 total 0.027808 0.005664 -42 2 1 1 10 total 0.036778 0.006592 -43 2 1 1 11 total 0.049785 0.005660 -22 2 1 2 1 total 0.000000 0.000000 -23 2 1 2 2 total 0.000000 0.000000 -24 2 1 2 3 total 0.000000 0.000000 -25 2 1 2 4 total 0.000000 0.000000 -26 2 1 2 5 total 0.000000 0.000000 -27 2 1 2 6 total 0.000000 0.000000 -28 2 1 2 7 total 0.000000 0.000000 -29 2 1 2 8 total 0.000000 0.000000 -30 2 1 2 9 total 0.000000 0.000000 -31 2 1 2 10 total 0.000000 0.000000 -32 2 1 2 11 total 0.000000 0.000000 -11 2 2 1 1 total 0.000000 0.000000 -12 2 2 1 2 total 0.000000 0.000000 -13 2 2 1 3 total 0.000000 0.000000 -14 2 2 1 4 total 0.000000 0.000000 -15 2 2 1 5 total 0.000000 0.000000 -16 2 2 1 6 total 0.000000 0.000000 -17 2 2 1 7 total 0.000000 0.000000 -18 2 2 1 8 total 0.000000 0.000000 -19 2 2 1 9 total 0.000000 0.000000 -20 2 2 1 10 total 0.000000 0.000000 -21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024415 0.008094 -1 2 2 2 2 total 0.036622 0.007855 -2 2 2 2 3 total 0.041505 0.012588 -3 2 2 2 4 total 0.019532 0.009048 -4 2 2 2 5 total 0.021973 0.008217 -5 2 2 2 6 total 0.019532 0.011894 -6 2 2 2 7 total 0.021973 0.007253 -7 2 2 2 8 total 0.036622 0.011671 -8 2 2 2 9 total 0.021973 0.006141 -9 2 2 2 10 total 0.031739 0.012779 -10 2 2 2 11 total 0.019532 0.006096 - material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.007001 0.000582 -34 3 1 1 2 total 0.007728 0.001008 -35 3 1 1 3 total 0.006819 0.001120 -36 3 1 1 4 total 0.006092 0.000787 -37 3 1 1 5 total 0.007183 0.000663 -38 3 1 1 6 total 0.011274 0.000704 -39 3 1 1 7 total 0.042642 0.002093 -40 3 1 1 8 total 0.074464 0.002664 -41 3 1 1 9 total 0.119015 0.006892 -42 3 1 1 10 total 0.153293 0.006049 -43 3 1 1 11 total 0.204390 0.010619 -22 3 1 2 1 total 0.000818 0.000302 -23 3 1 2 2 total 0.000818 0.000094 -24 3 1 2 3 total 0.001091 0.000234 -25 3 1 2 4 total 0.001091 0.000310 -26 3 1 2 5 total 0.002546 0.000607 -27 3 1 2 6 total 0.002364 0.000340 -28 3 1 2 7 total 0.004546 0.000835 -29 3 1 2 8 total 0.004819 0.000831 -30 3 1 2 9 total 0.006092 0.001113 -31 3 1 2 10 total 0.004546 0.000757 -32 3 1 2 11 total 0.002637 0.000371 -11 3 2 1 1 total 0.000000 0.000000 -12 3 2 1 2 total 0.000000 0.000000 -13 3 2 1 3 total 0.000000 0.000000 -14 3 2 1 4 total 0.000000 0.000000 -15 3 2 1 5 total 0.000000 0.000000 -16 3 2 1 6 total 0.000000 0.000000 -17 3 2 1 7 total 0.000000 0.000000 -18 3 2 1 8 total 0.000000 0.000000 -19 3 2 1 9 total 0.000000 0.000000 -20 3 2 1 10 total 0.000000 0.000000 -21 3 2 1 11 total 0.000443 0.000445 -0 3 2 2 1 total 0.088669 0.015373 -1 3 2 2 2 total 0.098422 0.016029 -2 3 2 2 3 total 0.126796 0.022922 -3 3 2 2 4 total 0.118373 0.018371 -4 3 2 2 5 total 0.131230 0.014538 -5 3 2 2 6 total 0.167584 0.027220 -6 3 2 2 7 total 0.180441 0.023605 -7 3 2 2 8 total 0.213691 0.028779 -8 3 2 2 9 total 0.236745 0.024777 -9 3 2 2 10 total 0.333394 0.041247 -10 3 2 2 11 total 0.339601 0.037814 - material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.007001 0.000582 -34 3 1 1 2 total 0.007728 0.001008 -35 3 1 1 3 total 0.006819 0.001120 -36 3 1 1 4 total 0.006092 0.000787 -37 3 1 1 5 total 0.007183 0.000663 -38 3 1 1 6 total 0.011274 0.000704 -39 3 1 1 7 total 0.042642 0.002093 -40 3 1 1 8 total 0.074464 0.002664 -41 3 1 1 9 total 0.119015 0.006892 -42 3 1 1 10 total 0.153293 0.006049 -43 3 1 1 11 total 0.204390 0.010619 -22 3 1 2 1 total 0.000818 0.000302 -23 3 1 2 2 total 0.000818 0.000094 -24 3 1 2 3 total 0.001091 0.000234 -25 3 1 2 4 total 0.001091 0.000310 -26 3 1 2 5 total 0.002546 0.000607 -27 3 1 2 6 total 0.002364 0.000340 -28 3 1 2 7 total 0.004546 0.000835 -29 3 1 2 8 total 0.004819 0.000831 -30 3 1 2 9 total 0.006092 0.001113 -31 3 1 2 10 total 0.004546 0.000757 -32 3 1 2 11 total 0.002637 0.000371 -11 3 2 1 1 total 0.000000 0.000000 -12 3 2 1 2 total 0.000000 0.000000 -13 3 2 1 3 total 0.000000 0.000000 -14 3 2 1 4 total 0.000000 0.000000 -15 3 2 1 5 total 0.000000 0.000000 -16 3 2 1 6 total 0.000000 0.000000 -17 3 2 1 7 total 0.000000 0.000000 -18 3 2 1 8 total 0.000000 0.000000 -19 3 2 1 9 total 0.000000 0.000000 -20 3 2 1 10 total 0.000000 0.000000 -21 3 2 1 11 total 0.000443 0.000445 -0 3 2 2 1 total 0.088669 0.015373 -1 3 2 2 2 total 0.098422 0.016029 -2 3 2 2 3 total 0.126796 0.022922 -3 3 2 2 4 total 0.118373 0.018371 -4 3 2 2 5 total 0.131230 0.014538 -5 3 2 2 6 total 0.167584 0.027220 -6 3 2 2 7 total 0.180441 0.023605 -7 3 2 2 8 total 0.213691 0.028779 -8 3 2 2 9 total 0.236745 0.024777 -9 3 2 2 10 total 0.333394 0.041247 -10 3 2 2 11 total 0.339601 0.037814 - material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.006924 0.000646 -34 3 1 1 2 total 0.007643 0.001048 -35 3 1 1 3 total 0.006744 0.001144 -36 3 1 1 4 total 0.006025 0.000819 -37 3 1 1 5 total 0.007104 0.000721 -38 3 1 1 6 total 0.011150 0.000841 -39 3 1 1 7 total 0.042173 0.002735 -40 3 1 1 8 total 0.073645 0.004084 -41 3 1 1 9 total 0.117706 0.008446 -42 3 1 1 10 total 0.151606 0.008778 -43 3 1 1 11 total 0.202141 0.013551 -22 3 1 2 1 total 0.000809 0.000301 -23 3 1 2 2 total 0.000809 0.000099 -24 3 1 2 3 total 0.001079 0.000236 -25 3 1 2 4 total 0.001079 0.000310 -26 3 1 2 5 total 0.002518 0.000610 -27 3 1 2 6 total 0.002338 0.000351 -28 3 1 2 7 total 0.004496 0.000848 -29 3 1 2 8 total 0.004766 0.000847 -30 3 1 2 9 total 0.006025 0.001130 -31 3 1 2 10 total 0.004496 0.000773 -32 3 1 2 11 total 0.002608 0.000383 -11 3 2 1 1 total 0.000000 0.000000 -12 3 2 1 2 total 0.000000 0.000000 -13 3 2 1 3 total 0.000000 0.000000 -14 3 2 1 4 total 0.000000 0.000000 -15 3 2 1 5 total 0.000000 0.000000 -16 3 2 1 6 total 0.000000 0.000000 -17 3 2 1 7 total 0.000000 0.000000 -18 3 2 1 8 total 0.000000 0.000000 -19 3 2 1 9 total 0.000000 0.000000 -20 3 2 1 10 total 0.000000 0.000000 -21 3 2 1 11 total 0.000440 0.000443 -0 3 2 2 1 total 0.088029 0.016753 -1 3 2 2 2 total 0.097712 0.017664 -2 3 2 2 3 total 0.125881 0.024808 -3 3 2 2 4 total 0.117518 0.020437 -4 3 2 2 5 total 0.130282 0.017687 -5 3 2 2 6 total 0.166374 0.030012 -6 3 2 2 7 total 0.179138 0.027327 -7 3 2 2 8 total 0.212149 0.033068 -8 3 2 2 9 total 0.235036 0.030744 -9 3 2 2 10 total 0.330988 0.048491 -10 3 2 2 11 total 0.337150 0.045927 - material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.006924 0.000686 -34 3 1 1 2 total 0.007643 0.001078 -35 3 1 1 3 total 0.006744 0.001166 -36 3 1 1 4 total 0.006025 0.000843 -37 3 1 1 5 total 0.007104 0.000759 -38 3 1 1 6 total 0.011150 0.000920 -39 3 1 1 7 total 0.042173 0.003073 -40 3 1 1 8 total 0.073645 0.004762 -41 3 1 1 9 total 0.117706 0.009309 -42 3 1 1 10 total 0.151606 0.010122 -43 3 1 1 11 total 0.202141 0.015127 -22 3 1 2 1 total 0.000809 0.000308 -23 3 1 2 2 total 0.000809 0.000118 -24 3 1 2 3 total 0.001079 0.000251 -25 3 1 2 4 total 0.001079 0.000321 -26 3 1 2 5 total 0.002518 0.000642 -27 3 1 2 6 total 0.002338 0.000397 -28 3 1 2 7 total 0.004496 0.000920 -29 3 1 2 8 total 0.004766 0.000928 -30 3 1 2 9 total 0.006025 0.001227 -31 3 1 2 10 total 0.004496 0.000852 -32 3 1 2 11 total 0.002608 0.000436 -11 3 2 1 1 total 0.000000 0.000000 -12 3 2 1 2 total 0.000000 0.000000 -13 3 2 1 3 total 0.000000 0.000000 -14 3 2 1 4 total 0.000000 0.000000 -15 3 2 1 5 total 0.000000 0.000000 -16 3 2 1 6 total 0.000000 0.000000 -17 3 2 1 7 total 0.000000 0.000000 -18 3 2 1 8 total 0.000000 0.000000 -19 3 2 1 9 total 0.000000 0.000000 -20 3 2 1 10 total 0.000000 0.000000 -21 3 2 1 11 total 0.000440 0.000764 -0 3 2 2 1 total 0.088029 0.018984 -1 3 2 2 2 total 0.097712 0.020255 -2 3 2 2 3 total 0.125881 0.027901 -3 3 2 2 4 total 0.117518 0.023659 -4 3 2 2 5 total 0.130282 0.022078 -5 3 2 2 6 total 0.166374 0.034431 -6 3 2 2 7 total 0.179138 0.032816 -7 3 2 2 8 total 0.212149 0.039453 -8 3 2 2 9 total 0.235036 0.038904 -9 3 2 2 10 total 0.330988 0.058979 -10 3 2 2 11 total 0.337150 0.057260 diff --git a/tests/regression_tests/mgxs_library_histogram/test.py b/tests/regression_tests/mgxs_library_histogram/test.py deleted file mode 100644 index b9905910a..000000000 --- a/tests/regression_tests/mgxs_library_histogram/test.py +++ /dev/null @@ -1,64 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = ['scatter matrix', 'nu-scatter matrix', - 'consistent scatter matrix', - 'consistent nu-scatter matrix'] - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.scatter_format = 'histogram' - self.mgxs_lib.histogram_bins = 11 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Build a string from Pandas Dataframe for each MGXS - outstr = '' - for domain in self.mgxs_lib.domains: - for mgxs_type in self.mgxs_lib.mgxs_types: - mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_histogram(): - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_mesh/__init__.py b/tests/regression_tests/mgxs_library_mesh/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat deleted file mode 100644 index f0f93d43c..000000000 --- a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat +++ /dev/null @@ -1,425 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 2 2 - -100.0 -100.0 - 100.0 100.0 - - - 1 - - - 0.0 20000000.0 - - - 0.0 20000000.0 - - - 1 - - - 3 - - - 1 2 3 4 5 6 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 2 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - analog - - - 1 65 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 65 2 5 - total - delayed-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_mesh/results_true.dat b/tests/regression_tests/mgxs_library_mesh/results_true.dat deleted file mode 100644 index f1ff29d6c..000000000 --- a/tests/regression_tests/mgxs_library_mesh/results_true.dat +++ /dev/null @@ -1,310 +0,0 @@ - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.105390 0.006421 -2 1 2 1 1 total 0.105466 0.003175 -1 2 1 1 1 total 0.106221 0.004040 -3 2 2 1 1 total 0.102641 0.002129 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.078603 0.006888 -2 1 2 1 1 total 0.075950 0.003755 -1 2 1 1 1 total 0.074519 0.004589 -3 2 2 1 1 total 0.072616 0.002838 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.078605 0.006892 -2 1 2 1 1 total 0.075989 0.003746 -1 2 1 1 1 total 0.074571 0.004600 -3 2 2 1 1 total 0.072586 0.002824 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.013600 0.000926 -2 1 2 1 1 total 0.013584 0.000551 -1 2 1 1 1 total 0.013692 0.000712 -3 2 2 1 1 total 0.013022 0.000430 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.001333 0.001105 -2 1 2 1 1 total 0.001339 0.000693 -1 2 1 1 1 total 0.001330 0.000885 -3 2 2 1 1 total 0.001260 0.000534 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.012266 0.000830 -2 1 2 1 1 total 0.012244 0.000486 -1 2 1 1 1 total 0.012361 0.000650 -3 2 2 1 1 total 0.011762 0.000376 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.032001 0.002161 -2 1 2 1 1 total 0.031882 0.001271 -1 2 1 1 1 total 0.032193 0.001701 -3 2 2 1 1 total 0.030726 0.001000 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 2.372379e+06 160440.303797 -2 1 2 1 1 total 2.368109e+06 93914.371991 -1 2 1 1 1 total 2.390701e+06 125743.883417 -3 2 2 1 1 total 2.274785e+06 72785.094827 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.091790 0.005503 -2 1 2 1 1 total 0.091883 0.002653 -1 2 1 1 1 total 0.092530 0.003354 -3 2 2 1 1 total 0.089619 0.001721 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.087817 0.005624 -2 1 2 1 1 total 0.090790 0.005246 -1 2 1 1 1 total 0.093736 0.005609 -3 2 2 1 1 total 0.092035 0.003633 - mesh 1 group in group out legendre nuclide mean std. dev. - x y z -0 1 1 1 1 1 P0 total 0.087684 0.005584 -1 1 1 1 1 1 P1 total 0.026787 0.002493 -2 1 1 1 1 1 P2 total 0.014937 0.001035 -3 1 1 1 1 1 P3 total 0.007893 0.001109 -8 1 2 1 1 1 P0 total 0.090687 0.005242 -9 1 2 1 1 1 P1 total 0.029516 0.002004 -10 1 2 1 1 1 P2 total 0.016952 0.001093 -11 1 2 1 1 1 P3 total 0.008019 0.001095 -4 2 1 1 1 1 P0 total 0.093670 0.005616 -5 2 1 1 1 1 P1 total 0.031703 0.002177 -6 2 1 1 1 1 P2 total 0.017922 0.001352 -7 2 1 1 1 1 P3 total 0.011171 0.001055 -12 2 2 1 1 1 P0 total 0.091808 0.003617 -13 2 2 1 1 1 P1 total 0.030025 0.001876 -14 2 2 1 1 1 P2 total 0.015181 0.002277 -15 2 2 1 1 1 P3 total 0.009550 0.001713 - mesh 1 group in group out legendre nuclide mean std. dev. - x y z -0 1 1 1 1 1 P0 total 0.087817 0.005624 -1 1 1 1 1 1 P1 total 0.026785 0.002504 -2 1 1 1 1 1 P2 total 0.014973 0.001041 -3 1 1 1 1 1 P3 total 0.007913 0.001144 -8 1 2 1 1 1 P0 total 0.090790 0.005246 -9 1 2 1 1 1 P1 total 0.029477 0.001987 -10 1 2 1 1 1 P2 total 0.016940 0.001094 -11 1 2 1 1 1 P3 total 0.008033 0.001104 -4 2 1 1 1 1 P0 total 0.093736 0.005609 -5 2 1 1 1 1 P1 total 0.031651 0.002201 -6 2 1 1 1 1 P2 total 0.017953 0.001364 -7 2 1 1 1 1 P3 total 0.011158 0.001044 -12 2 2 1 1 1 P0 total 0.092035 0.003633 -13 2 2 1 1 1 P1 total 0.030055 0.001856 -14 2 2 1 1 1 P2 total 0.015245 0.002274 -15 2 2 1 1 1 P3 total 0.009534 0.001700 - mesh 1 group in group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 1.001515 0.075311 -2 1 2 1 1 1 total 1.001135 0.061671 -1 2 1 1 1 1 total 1.000704 0.055977 -3 2 2 1 1 1 total 1.002471 0.042246 - mesh 1 group in group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.031246 0.001839 -2 1 2 1 1 1 total 0.032452 0.002365 -1 2 1 1 1 1 total 0.032568 0.002068 -3 2 2 1 1 1 total 0.031529 0.001639 - mesh 1 group in group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 1.0 0.074891 -2 1 2 1 1 1 total 1.0 0.061618 -1 2 1 1 1 1 total 1.0 0.056068 -3 2 2 1 1 1 total 1.0 0.042067 - mesh 1 group in group out legendre nuclide mean std. dev. - x y z -0 1 1 1 1 1 P0 total 0.091790 0.008806 -1 1 1 1 1 1 P1 total 0.028042 0.003295 -2 1 1 1 1 1 P2 total 0.015636 0.001560 -3 1 1 1 1 1 P3 total 0.008263 0.001304 -8 1 2 1 1 1 P0 total 0.091883 0.006252 -9 1 2 1 1 1 P1 total 0.029905 0.002297 -10 1 2 1 1 1 P2 total 0.017175 0.001268 -11 1 2 1 1 1 P3 total 0.008124 0.001147 -4 2 1 1 1 1 P0 total 0.092530 0.006177 -5 2 1 1 1 1 P1 total 0.031317 0.002339 -6 2 1 1 1 1 P2 total 0.017704 0.001433 -7 2 1 1 1 1 P3 total 0.011035 0.001092 -12 2 2 1 1 1 P0 total 0.089619 0.004144 -13 2 2 1 1 1 P1 total 0.029309 0.001964 -14 2 2 1 1 1 P2 total 0.014820 0.002251 -15 2 2 1 1 1 P3 total 0.009322 0.001687 - mesh 1 group in group out legendre nuclide mean std. dev. - x y z -0 1 1 1 1 1 P0 total 0.091929 0.011205 -1 1 1 1 1 1 P1 total 0.028084 0.003918 -2 1 1 1 1 1 P2 total 0.015660 0.001956 -3 1 1 1 1 1 P3 total 0.008276 0.001447 -8 1 2 1 1 1 P0 total 0.091987 0.008443 -9 1 2 1 1 1 P1 total 0.029939 0.002948 -10 1 2 1 1 1 P2 total 0.017195 0.001653 -11 1 2 1 1 1 P3 total 0.008134 0.001253 -4 2 1 1 1 1 P0 total 0.092595 0.008065 -5 2 1 1 1 1 P1 total 0.031339 0.002924 -6 2 1 1 1 1 P2 total 0.017716 0.001743 -7 2 1 1 1 1 P3 total 0.011042 0.001255 -12 2 2 1 1 1 P0 total 0.089840 0.005621 -13 2 2 1 1 1 P1 total 0.029381 0.002326 -14 2 2 1 1 1 P2 total 0.014856 0.002342 -15 2 2 1 1 1 P3 total 0.009345 0.001737 - mesh 1 group out nuclide mean std. dev. - x y z -0 1 1 1 1 total 1.0 0.066520 -2 1 2 1 1 total 1.0 0.087934 -1 2 1 1 1 total 1.0 0.063390 -3 2 2 1 1 total 1.0 0.063791 - mesh 1 group out nuclide mean std. dev. - x y z -0 1 1 1 1 total 1.0 0.068463 -2 1 2 1 1 total 1.0 0.091776 -1 2 1 1 1 total 1.0 0.064705 -3 2 2 1 1 total 1.0 0.063003 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 8.735713e-10 4.530341e-11 -2 1 2 1 1 total 8.821319e-10 3.206094e-11 -1 2 1 1 1 total 8.699208e-10 2.515246e-11 -3 2 2 1 1 total 8.738762e-10 1.734562e-11 - mesh 1 group in nuclide mean std. dev. - x y z -0 1 1 1 1 total 0.031799 0.002147 -2 1 2 1 1 total 0.031680 0.001263 -1 2 1 1 1 total 0.031989 0.001691 -3 2 2 1 1 total 0.030533 0.000994 - mesh 1 group in group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.031056 0.001862 -2 1 2 1 1 1 total 0.032188 0.002420 -1 2 1 1 1 1 total 0.032304 0.002073 -3 2 2 1 1 1 total 0.031336 0.001614 - mesh 1 delayedgroup group in nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.000007 4.734745e-07 -1 1 1 1 2 1 total 0.000036 2.443930e-06 -2 1 1 1 3 1 total 0.000035 2.333188e-06 -3 1 1 1 4 1 total 0.000078 5.231199e-06 -4 1 1 1 5 1 total 0.000032 2.144718e-06 -5 1 1 1 6 1 total 0.000013 8.984148e-07 -12 1 2 1 1 1 total 0.000007 2.770884e-07 -13 1 2 1 2 1 total 0.000036 1.430245e-06 -14 1 2 1 3 1 total 0.000035 1.365436e-06 -15 1 2 1 4 1 total 0.000078 3.061421e-06 -16 1 2 1 5 1 total 0.000032 1.255139e-06 -17 1 2 1 6 1 total 0.000013 5.257735e-07 -6 2 1 1 1 1 total 0.000007 3.731284e-07 -7 2 1 1 2 1 total 0.000037 1.925974e-06 -8 2 1 1 3 1 total 0.000035 1.838702e-06 -9 2 1 1 4 1 total 0.000079 4.122522e-06 -10 2 1 1 5 1 total 0.000032 1.690176e-06 -11 2 1 1 6 1 total 0.000014 7.080087e-07 -18 2 2 1 1 1 total 0.000007 2.050310e-07 -19 2 2 1 2 1 total 0.000035 1.058307e-06 -20 2 2 1 3 1 total 0.000033 1.010352e-06 -21 2 2 1 4 1 total 0.000075 2.265292e-06 -22 2 2 1 5 1 total 0.000031 9.287379e-07 -23 2 2 1 6 1 total 0.000013 3.890451e-07 - mesh 1 delayedgroup group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.0 0.000000 -1 1 1 1 2 1 total 1.0 1.414214 -2 1 1 1 3 1 total 1.0 0.868831 -3 1 1 1 4 1 total 1.0 1.414214 -4 1 1 1 5 1 total 1.0 1.414214 -5 1 1 1 6 1 total 0.0 0.000000 -12 1 2 1 1 1 total 0.0 0.000000 -13 1 2 1 2 1 total 1.0 0.866827 -14 1 2 1 3 1 total 0.0 0.000000 -15 1 2 1 4 1 total 1.0 0.455171 -16 1 2 1 5 1 total 1.0 0.868553 -17 1 2 1 6 1 total 0.0 0.000000 -6 2 1 1 1 1 total 0.0 0.000000 -7 2 1 1 2 1 total 1.0 1.414214 -8 2 1 1 3 1 total 1.0 1.414214 -9 2 1 1 4 1 total 1.0 0.674843 -10 2 1 1 5 1 total 1.0 1.414214 -11 2 1 1 6 1 total 1.0 0.866033 -18 2 2 1 1 1 total 1.0 1.414214 -19 2 2 1 2 1 total 1.0 1.414214 -20 2 2 1 3 1 total 1.0 1.414214 -21 2 2 1 4 1 total 1.0 0.579059 -22 2 2 1 5 1 total 0.0 0.000000 -23 2 2 1 6 1 total 1.0 1.414214 - mesh 1 delayedgroup group in nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.000221 0.000019 -1 1 1 1 2 1 total 0.001139 0.000096 -2 1 1 1 3 1 total 0.001087 0.000092 -3 1 1 1 4 1 total 0.002437 0.000206 -4 1 1 1 5 1 total 0.000999 0.000084 -5 1 1 1 6 1 total 0.000419 0.000035 -12 1 2 1 1 1 total 0.000222 0.000012 -13 1 2 1 2 1 total 0.001144 0.000060 -14 1 2 1 3 1 total 0.001092 0.000057 -15 1 2 1 4 1 total 0.002448 0.000129 -16 1 2 1 5 1 total 0.001004 0.000053 -17 1 2 1 6 1 total 0.000420 0.000022 -6 2 1 1 1 1 total 0.000221 0.000015 -7 2 1 1 2 1 total 0.001143 0.000078 -8 2 1 1 3 1 total 0.001091 0.000075 -9 2 1 1 4 1 total 0.002446 0.000167 -10 2 1 1 5 1 total 0.001003 0.000069 -11 2 1 1 6 1 total 0.000420 0.000029 -18 2 2 1 1 1 total 0.000220 0.000009 -19 2 2 1 2 1 total 0.001136 0.000047 -20 2 2 1 3 1 total 0.001084 0.000045 -21 2 2 1 4 1 total 0.002431 0.000100 -22 2 2 1 5 1 total 0.000997 0.000041 -23 2 2 1 6 1 total 0.000417 0.000017 - mesh 1 delayedgroup group in nuclide mean std. dev. - x y z -0 1 1 1 1 1 total 0.013336 0.001120 -1 1 1 1 2 1 total 0.032739 0.002751 -2 1 1 1 3 1 total 0.120780 0.010147 -3 1 1 1 4 1 total 0.302780 0.025438 -4 1 1 1 5 1 total 0.849490 0.071370 -5 1 1 1 6 1 total 2.853000 0.239696 -12 1 2 1 1 1 total 0.013336 0.000695 -13 1 2 1 2 1 total 0.032739 0.001707 -14 1 2 1 3 1 total 0.120780 0.006296 -15 1 2 1 4 1 total 0.302780 0.015784 -16 1 2 1 5 1 total 0.849490 0.044285 -17 1 2 1 6 1 total 2.853000 0.148730 -6 2 1 1 1 1 total 0.013336 0.000906 -7 2 1 1 2 1 total 0.032739 0.002224 -8 2 1 1 3 1 total 0.120780 0.008205 -9 2 1 1 4 1 total 0.302780 0.020570 -10 2 1 1 5 1 total 0.849490 0.057711 -11 2 1 1 6 1 total 2.853000 0.193821 -18 2 2 1 1 1 total 0.013336 0.000528 -19 2 2 1 2 1 total 0.032739 0.001296 -20 2 2 1 3 1 total 0.120780 0.004781 -21 2 2 1 4 1 total 0.302780 0.011986 -22 2 2 1 5 1 total 0.849490 0.033628 -23 2 2 1 6 1 total 2.853000 0.112940 - mesh 1 delayedgroup group in group out nuclide mean std. dev. - x y z -0 1 1 1 1 1 1 total 0.000000 0.000000 -1 1 1 1 2 1 1 total 0.000055 0.000055 -2 1 1 1 3 1 1 total 0.000055 0.000034 -3 1 1 1 4 1 1 total 0.000052 0.000052 -4 1 1 1 5 1 1 total 0.000029 0.000029 -5 1 1 1 6 1 1 total 0.000000 0.000000 -12 1 2 1 1 1 1 total 0.000000 0.000000 -13 1 2 1 2 1 1 total 0.000058 0.000036 -14 1 2 1 3 1 1 total 0.000000 0.000000 -15 1 2 1 4 1 1 total 0.000149 0.000048 -16 1 2 1 5 1 1 total 0.000057 0.000035 -17 1 2 1 6 1 1 total 0.000000 0.000000 -6 2 1 1 1 1 1 total 0.000000 0.000000 -7 2 1 1 2 1 1 total 0.000027 0.000027 -8 2 1 1 3 1 1 total 0.000026 0.000026 -9 2 1 1 4 1 1 total 0.000105 0.000051 -10 2 1 1 5 1 1 total 0.000054 0.000054 -11 2 1 1 6 1 1 total 0.000051 0.000031 -18 2 2 1 1 1 1 total 0.000028 0.000028 -19 2 2 1 2 1 1 total 0.000025 0.000025 -20 2 2 1 3 1 1 total 0.000032 0.000032 -21 2 2 1 4 1 1 total 0.000080 0.000033 -22 2 2 1 5 1 1 total 0.000000 0.000000 -23 2 2 1 6 1 1 total 0.000027 0.000027 diff --git a/tests/regression_tests/mgxs_library_mesh/test.py b/tests/regression_tests/mgxs_library_mesh/test.py deleted file mode 100644 index 3660d3eb7..000000000 --- a/tests/regression_tests/mgxs_library_mesh/test.py +++ /dev/null @@ -1,95 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material() - fuel.set_density('g/cm3', 10.0) - fuel.add_nuclide('U235', 1.0) - zr = openmc.Material() - zr.set_density('g/cm3', 1.0) - zr.add_nuclide('Zr90', 1.0) - model.materials.extend([fuel, zr]) - - box1 = openmc.model.rectangular_prism(10.0, 10.0) - box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective') - top = openmc.ZPlane(z0=10.0, boundary_type='vacuum') - bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum') - cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top) - cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top) - model.geometry = openmc.Geometry([cell1, cell2]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - - # Initialize a one-group structure - energy_groups = openmc.mgxs.EnergyGroups([0, 20.e6]) - - # Initialize MGXS Library for a few cross section types - # for one material-filled cell in the geometry - model.mgxs_lib = openmc.mgxs.Library(model.geometry) - model.mgxs_lib.by_nuclide = False - - # Test all MGXS types - model.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES - model.mgxs_lib.energy_groups = energy_groups - model.mgxs_lib.num_delayed_groups = 6 - model.mgxs_lib.correction = None # Avoid warning about P0 correction - model.mgxs_lib.legendre_order = 3 - model.mgxs_lib.domain_type = 'mesh' - - # Instantiate a tally mesh - mesh = openmc.RegularMesh(mesh_id=1) - mesh.dimension = [2, 2] - mesh.lower_left = [-100., -100.] - mesh.width = [100., 100.] - - model.mgxs_lib.domains = [mesh] - model.mgxs_lib.build_library() - - # Add tallies - model.mgxs_lib.add_to_tallies_file(model.tallies, merge=False) - - return model - - -class MGXSTestHarness(PyAPITestHarness): - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - mgxs_lib = self._model.mgxs_lib - mgxs_lib.load_from_statepoint(sp) - - # Build a string from Pandas Dataframe for each 1-group MGXS - outstr = '' - for domain in mgxs_lib.domains: - for mgxs_type in mgxs_lib.mgxs_types: - mgxs = mgxs_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_mesh(model): - harness = MGXSTestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_no_nuclides/__init__.py b/tests/regression_tests/mgxs_library_no_nuclides/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat deleted file mode 100644 index 5aedd383d..000000000 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ /dev/null @@ -1,1178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 1 2 3 4 5 6 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - total - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - absorption - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - total - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - total - nu-scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - total - nu-fission - analog - - - 1 2 5 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - scatter - tracklength - - - 1 2 5 28 - total - scatter - analog - - - 1 2 5 - total - nu-scatter - analog - - - 1 52 - total - nu-fission - analog - - - 1 5 - total - nu-fission - analog - - - 1 52 - total - prompt-nu-fission - analog - - - 1 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - total - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - total - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - total - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 52 - total - delayed-nu-fission - analog - - - 1 65 5 - total - delayed-nu-fission - analog - - - 1 2 - total - nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - delayed-nu-fission - tracklength - - - 1 65 2 - total - decay-rate - tracklength - - - 1 2 - total - flux - analog - - - 1 65 2 5 - total - delayed-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - total - tracklength - - - 80 2 - total - flux - analog - - - 80 5 6 - total - nu-scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - absorption - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - nu-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - kappa-fission - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 - total - flux - analog - - - 80 2 - total - nu-scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 28 - total - nu-scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - analog - - - 80 2 5 - total - nu-fission - analog - - - 80 2 5 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - scatter - tracklength - - - 80 2 5 28 - total - scatter - analog - - - 80 2 5 - total - nu-scatter - analog - - - 80 52 - total - nu-fission - analog - - - 80 5 - total - nu-fission - analog - - - 80 52 - total - prompt-nu-fission - analog - - - 80 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 2 - total - inverse-velocity - tracklength - - - 80 2 - total - flux - tracklength - - - 80 2 - total - prompt-nu-fission - tracklength - - - 80 2 - total - flux - analog - - - 80 2 5 - total - prompt-nu-fission - analog - - - 80 2 - total - flux - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 52 - total - delayed-nu-fission - analog - - - 80 65 5 - total - delayed-nu-fission - analog - - - 80 2 - total - nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - delayed-nu-fission - tracklength - - - 80 65 2 - total - decay-rate - tracklength - - - 80 2 - total - flux - analog - - - 80 65 2 5 - total - delayed-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - total - tracklength - - - 159 2 - total - flux - analog - - - 159 5 6 - total - nu-scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - absorption - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - nu-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - kappa-fission - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 - total - flux - analog - - - 159 2 - total - nu-scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 28 - total - nu-scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - analog - - - 159 2 5 - total - nu-fission - analog - - - 159 2 5 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - scatter - tracklength - - - 159 2 5 28 - total - scatter - analog - - - 159 2 5 - total - nu-scatter - analog - - - 159 52 - total - nu-fission - analog - - - 159 5 - total - nu-fission - analog - - - 159 52 - total - prompt-nu-fission - analog - - - 159 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 2 - total - inverse-velocity - tracklength - - - 159 2 - total - flux - tracklength - - - 159 2 - total - prompt-nu-fission - tracklength - - - 159 2 - total - flux - analog - - - 159 2 5 - total - prompt-nu-fission - analog - - - 159 2 - total - flux - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 52 - total - delayed-nu-fission - analog - - - 159 65 5 - total - delayed-nu-fission - analog - - - 159 2 - total - nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - delayed-nu-fission - tracklength - - - 159 65 2 - total - decay-rate - tracklength - - - 159 2 - total - flux - analog - - - 159 65 2 5 - total - delayed-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat deleted file mode 100644 index dc98a2263..000000000 --- a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat +++ /dev/null @@ -1,621 +0,0 @@ - material group in nuclide mean std. dev. -1 1 1 total 0.414825 0.022793 -0 1 2 total 0.660170 0.047519 - material group in nuclide mean std. dev. -1 1 1 total 0.363092 0.023838 -0 1 2 total 0.644851 0.047675 - material group in nuclide mean std. dev. -1 1 1 total 0.363092 0.023838 -0 1 2 total 0.644851 0.047675 - material group in nuclide mean std. dev. -1 1 1 total 0.027408 0.002692 -0 1 2 total 0.264511 0.023367 - material group in nuclide mean std. dev. -1 1 1 total 0.019845 0.002643 -0 1 2 total 0.071719 0.025208 - material group in nuclide mean std. dev. -1 1 1 total 0.007563 0.000508 -0 1 2 total 0.192791 0.017106 - material group in nuclide mean std. dev. -1 1 1 total 0.019432 0.001323 -0 1 2 total 0.469775 0.041682 - material group in nuclide mean std. dev. -1 1 1 total 1.474570e+06 9.923536e+04 -0 1 2 total 3.728689e+07 3.308375e+06 - material group in nuclide mean std. dev. -1 1 1 total 0.387418 0.020626 -0 1 2 total 0.395659 0.025125 - material group in nuclide mean std. dev. -1 1 1 total 0.385188 0.026946 -0 1 2 total 0.412389 0.015425 - material group in group out legendre nuclide mean std. dev. -12 1 1 1 P0 total 0.384199 0.027001 -13 1 1 1 P1 total 0.051870 0.006983 -14 1 1 1 P2 total 0.020069 0.002846 -15 1 1 1 P3 total 0.009478 0.002234 -8 1 1 2 P0 total 0.000989 0.000482 -9 1 1 2 P1 total -0.000207 0.000149 -10 1 1 2 P2 total -0.000103 0.000184 -11 1 1 2 P3 total 0.000234 0.000128 -4 1 2 1 P0 total 0.000925 0.000925 -5 1 2 1 P1 total -0.000768 0.000768 -6 1 2 1 P2 total 0.000494 0.000494 -7 1 2 1 P3 total -0.000171 0.000172 -0 1 2 2 P0 total 0.411465 0.015245 -1 1 2 2 P1 total 0.016482 0.004502 -2 1 2 2 P2 total 0.006371 0.010551 -3 1 2 2 P3 total -0.010499 0.010438 - material group in group out legendre nuclide mean std. dev. -12 1 1 1 P0 total 0.384199 0.027001 -13 1 1 1 P1 total 0.051870 0.006983 -14 1 1 1 P2 total 0.020069 0.002846 -15 1 1 1 P3 total 0.009478 0.002234 -8 1 1 2 P0 total 0.000989 0.000482 -9 1 1 2 P1 total -0.000207 0.000149 -10 1 1 2 P2 total -0.000103 0.000184 -11 1 1 2 P3 total 0.000234 0.000128 -4 1 2 1 P0 total 0.000925 0.000925 -5 1 2 1 P1 total -0.000768 0.000768 -6 1 2 1 P2 total 0.000494 0.000494 -7 1 2 1 P3 total -0.000171 0.000172 -0 1 2 2 P0 total 0.411465 0.015245 -1 1 2 2 P1 total 0.016482 0.004502 -2 1 2 2 P2 total 0.006371 0.010551 -3 1 2 2 P3 total -0.010499 0.010438 - material group in group out nuclide mean std. dev. -3 1 1 1 total 1.0 0.078516 -2 1 1 2 total 1.0 0.687184 -1 1 2 1 total 1.0 1.414214 -0 1 2 2 total 1.0 0.041130 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.020142 0.003149 -2 1 1 2 total 0.000000 0.000000 -1 1 2 1 total 0.454366 0.027426 -0 1 2 2 total 0.000000 0.000000 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.997433 0.078224 -2 1 1 2 total 0.002567 0.001256 -1 1 2 1 total 0.002242 0.002243 -0 1 2 2 total 0.997758 0.041053 - material group in group out legendre nuclide mean std. dev. -12 1 1 1 P0 total 0.386423 0.036629 -13 1 1 1 P1 total 0.052170 0.007767 -14 1 1 1 P2 total 0.020185 0.003138 -15 1 1 1 P3 total 0.009533 0.002327 -8 1 1 2 P0 total 0.000995 0.000489 -9 1 1 2 P1 total -0.000208 0.000150 -10 1 1 2 P2 total -0.000104 0.000186 -11 1 1 2 P3 total 0.000236 0.000130 -4 1 2 1 P0 total 0.000887 0.000889 -5 1 2 1 P1 total -0.000737 0.000738 -6 1 2 1 P2 total 0.000474 0.000475 -7 1 2 1 P3 total -0.000165 0.000165 -0 1 2 2 P0 total 0.394772 0.029871 -1 1 2 2 P1 total 0.015813 0.004443 -2 1 2 2 P2 total 0.006113 0.010131 -3 1 2 2 P3 total -0.010073 0.010037 - material group in group out legendre nuclide mean std. dev. -12 1 1 1 P0 total 0.386423 0.047563 -13 1 1 1 P1 total 0.052170 0.008781 -14 1 1 1 P2 total 0.020185 0.003515 -15 1 1 1 P3 total 0.009533 0.002444 -8 1 1 2 P0 total 0.000995 0.000841 -9 1 1 2 P1 total -0.000208 0.000208 -10 1 1 2 P2 total -0.000104 0.000199 -11 1 1 2 P3 total 0.000236 0.000208 -4 1 2 1 P0 total 0.000887 0.001538 -5 1 2 1 P1 total -0.000737 0.001277 -6 1 2 1 P2 total 0.000474 0.000821 -7 1 2 1 P3 total -0.000165 0.000285 -0 1 2 2 P0 total 0.394772 0.033999 -1 1 2 2 P1 total 0.015813 0.004491 -2 1 2 2 P2 total 0.006113 0.010134 -3 1 2 2 P3 total -0.010073 0.010045 - material group out nuclide mean std. dev. -1 1 1 total 1.0 0.046071 -0 1 2 total 0.0 0.000000 - material group out nuclide mean std. dev. -1 1 1 total 1.0 0.051471 -0 1 2 total 0.0 0.000000 - material group in nuclide mean std. dev. -1 1 1 total 5.709324e-08 4.687938e-09 -0 1 2 total 2.855739e-06 2.442164e-07 - material group in nuclide mean std. dev. -1 1 1 total 0.019239 0.001310 -0 1 2 total 0.466719 0.041411 - material group in group out nuclide mean std. dev. -3 1 1 1 total 0.020142 0.003149 -2 1 1 2 total 0.000000 0.000000 -1 1 2 1 total 0.445819 0.028675 -0 1 2 2 total 0.000000 0.000000 - material delayedgroup group in nuclide mean std. dev. -1 1 1 1 total 0.000004 2.897486e-07 -3 1 2 1 total 0.000027 1.850037e-06 -5 1 3 1 total 0.000028 1.970979e-06 -7 1 4 1 total 0.000074 5.226103e-06 -9 1 5 1 total 0.000041 2.998308e-06 -11 1 6 1 total 0.000017 1.226547e-06 -0 1 1 2 total 0.000107 9.491556e-06 -2 1 2 2 total 0.000552 4.899251e-05 -4 1 3 2 total 0.000527 4.677253e-05 -6 1 4 2 total 0.001182 1.048679e-04 -8 1 5 2 total 0.000485 4.299445e-05 -10 1 6 2 total 0.000203 1.801022e-05 - material delayedgroup group out nuclide mean std. dev. -1 1 1 1 total 0.0 0.000000 -3 1 2 1 total 1.0 0.869128 -5 1 3 1 total 1.0 1.414214 -7 1 4 1 total 1.0 0.360359 -9 1 5 1 total 0.0 0.000000 -11 1 6 1 total 0.0 0.000000 -0 1 1 2 total 0.0 0.000000 -2 1 2 2 total 0.0 0.000000 -4 1 3 2 total 0.0 0.000000 -6 1 4 2 total 0.0 0.000000 -8 1 5 2 total 0.0 0.000000 -10 1 6 2 total 0.0 0.000000 - material delayedgroup group in nuclide mean std. dev. -1 1 1 1 total 0.000222 0.000018 -3 1 2 1 total 0.001388 0.000115 -5 1 3 1 total 0.001463 0.000122 -7 1 4 1 total 0.003822 0.000321 -9 1 5 1 total 0.002135 0.000183 -11 1 6 1 total 0.000875 0.000075 -0 1 1 2 total 0.000228 0.000025 -2 1 2 2 total 0.001175 0.000127 -4 1 3 2 total 0.001122 0.000122 -6 1 4 2 total 0.002516 0.000273 -8 1 5 2 total 0.001031 0.000112 -10 1 6 2 total 0.000432 0.000047 - material delayedgroup group in nuclide mean std. dev. -1 1 1 1 total 0.013445 0.001084 -3 1 2 1 total 0.032064 0.002658 -5 1 3 1 total 0.122136 0.010296 -7 1 4 1 total 0.315269 0.027175 -9 1 5 1 total 0.889233 0.079368 -11 1 6 1 total 2.989404 0.266253 -0 1 1 2 total 0.013336 0.001446 -2 1 2 2 total 0.032739 0.003550 -4 1 3 2 total 0.120780 0.013098 -6 1 4 2 total 0.302780 0.032835 -8 1 5 2 total 0.849490 0.092124 -10 1 6 2 total 2.853001 0.309397 - material delayedgroup group in group out nuclide mean std. dev. -3 1 1 1 1 total 0.000000 0.000000 -7 1 2 1 1 total 0.000000 0.000000 -11 1 3 1 1 total 0.000000 0.000000 -15 1 4 1 1 total 0.000000 0.000000 -19 1 5 1 1 total 0.000000 0.000000 -23 1 6 1 1 total 0.000000 0.000000 -2 1 1 1 2 total 0.000000 0.000000 -6 1 2 1 2 total 0.000000 0.000000 -10 1 3 1 2 total 0.000000 0.000000 -14 1 4 1 2 total 0.000000 0.000000 -18 1 5 1 2 total 0.000000 0.000000 -22 1 6 1 2 total 0.000000 0.000000 -1 1 1 2 1 total 0.000000 0.000000 -5 1 2 2 1 total 0.002538 0.001561 -9 1 3 2 1 total 0.001186 0.001186 -13 1 4 2 1 total 0.004823 0.001234 -17 1 5 2 1 total 0.000000 0.000000 -21 1 6 2 1 total 0.000000 0.000000 -0 1 1 2 2 total 0.000000 0.000000 -4 1 2 2 2 total 0.000000 0.000000 -8 1 3 2 2 total 0.000000 0.000000 -12 1 4 2 2 total 0.000000 0.000000 -16 1 5 2 2 total 0.000000 0.000000 -20 1 6 2 2 total 0.000000 0.000000 - material group in nuclide mean std. dev. -1 2 1 total 0.313738 0.015582 -0 2 2 total 0.300821 0.028052 - material group in nuclide mean std. dev. -1 2 1 total 0.275508 0.017742 -0 2 2 total 0.312035 0.032384 - material group in nuclide mean std. dev. -1 2 1 total 0.275508 0.017742 -0 2 2 total 0.312035 0.032384 - material group in nuclide mean std. dev. -1 2 1 total 0.001575 0.000323 -0 2 2 total 0.005400 0.000618 - material group in nuclide mean std. dev. -1 2 1 total 0.001575 0.000323 -0 2 2 total 0.005400 0.000618 - material group in nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 2 1 total 0.312163 0.015322 -0 2 2 total 0.295421 0.027446 - material group in nuclide mean std. dev. -1 2 1 total 0.310121 0.033788 -0 2 2 total 0.296264 0.043792 - material group in group out legendre nuclide mean std. dev. -12 2 1 1 P0 total 0.310121 0.033788 -13 2 1 1 P1 total 0.038230 0.008484 -14 2 1 1 P2 total 0.020745 0.004696 -15 2 1 1 P3 total 0.007964 0.003732 -8 2 1 2 P0 total 0.000000 0.000000 -9 2 1 2 P1 total 0.000000 0.000000 -10 2 1 2 P2 total 0.000000 0.000000 -11 2 1 2 P3 total 0.000000 0.000000 -4 2 2 1 P0 total 0.000000 0.000000 -5 2 2 1 P1 total 0.000000 0.000000 -6 2 2 1 P2 total 0.000000 0.000000 -7 2 2 1 P3 total 0.000000 0.000000 -0 2 2 2 P0 total 0.296264 0.043792 -1 2 2 2 P1 total -0.011214 0.016180 -2 2 2 2 P2 total 0.008837 0.011504 -3 2 2 2 P3 total -0.003270 0.007329 - material group in group out legendre nuclide mean std. dev. -12 2 1 1 P0 total 0.310121 0.033788 -13 2 1 1 P1 total 0.038230 0.008484 -14 2 1 1 P2 total 0.020745 0.004696 -15 2 1 1 P3 total 0.007964 0.003732 -8 2 1 2 P0 total 0.000000 0.000000 -9 2 1 2 P1 total 0.000000 0.000000 -10 2 1 2 P2 total 0.000000 0.000000 -11 2 1 2 P3 total 0.000000 0.000000 -4 2 2 1 P0 total 0.000000 0.000000 -5 2 2 1 P1 total 0.000000 0.000000 -6 2 2 1 P2 total 0.000000 0.000000 -7 2 2 1 P3 total 0.000000 0.000000 -0 2 2 2 P0 total 0.296264 0.043792 -1 2 2 2 P1 total -0.011214 0.016180 -2 2 2 2 P2 total 0.008837 0.011504 -3 2 2 2 P3 total -0.003270 0.007329 - material group in group out nuclide mean std. dev. -3 2 1 1 total 1.0 0.108779 -2 2 1 2 total 0.0 0.000000 -1 2 2 1 total 0.0 0.000000 -0 2 2 2 total 1.0 0.142427 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.0 0.0 -2 2 1 2 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -0 2 2 2 total 0.0 0.0 - material group in group out nuclide mean std. dev. -3 2 1 1 total 1.0 0.108779 -2 2 1 2 total 0.0 0.000000 -1 2 2 1 total 0.0 0.000000 -0 2 2 2 total 1.0 0.142427 - material group in group out legendre nuclide mean std. dev. -12 2 1 1 P0 total 0.312163 0.037253 -13 2 1 1 P1 total 0.038481 0.008743 -14 2 1 1 P2 total 0.020882 0.004835 -15 2 1 1 P3 total 0.008017 0.003776 -8 2 1 2 P0 total 0.000000 0.000000 -9 2 1 2 P1 total 0.000000 0.000000 -10 2 1 2 P2 total 0.000000 0.000000 -11 2 1 2 P3 total 0.000000 0.000000 -4 2 2 1 P0 total 0.000000 0.000000 -5 2 2 1 P1 total 0.000000 0.000000 -6 2 2 1 P2 total 0.000000 0.000000 -7 2 2 1 P3 total 0.000000 0.000000 -0 2 2 2 P0 total 0.295421 0.050236 -1 2 2 2 P1 total -0.011182 0.016162 -2 2 2 2 P2 total 0.008811 0.011495 -3 2 2 2 P3 total -0.003261 0.007313 - material group in group out legendre nuclide mean std. dev. -12 2 1 1 P0 total 0.312163 0.050407 -13 2 1 1 P1 total 0.038481 0.009693 -14 2 1 1 P2 total 0.020882 0.005342 -15 2 1 1 P3 total 0.008017 0.003876 -8 2 1 2 P0 total 0.000000 0.000000 -9 2 1 2 P1 total 0.000000 0.000000 -10 2 1 2 P2 total 0.000000 0.000000 -11 2 1 2 P3 total 0.000000 0.000000 -4 2 2 1 P0 total 0.000000 0.000000 -5 2 2 1 P1 total 0.000000 0.000000 -6 2 2 1 P2 total 0.000000 0.000000 -7 2 2 1 P3 total 0.000000 0.000000 -0 2 2 2 P0 total 0.295421 0.065529 -1 2 2 2 P1 total -0.011182 0.016240 -2 2 2 2 P2 total 0.008811 0.011563 -3 2 2 2 P3 total -0.003261 0.007328 - material group out nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group out nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 2 1 total 5.995979e-08 4.553085e-09 -0 2 2 total 2.985490e-06 3.417020e-07 - material group in nuclide mean std. dev. -1 2 1 total 0.0 0.0 -0 2 2 total 0.0 0.0 - material group in group out nuclide mean std. dev. -3 2 1 1 total 0.0 0.0 -2 2 1 2 total 0.0 0.0 -1 2 2 1 total 0.0 0.0 -0 2 2 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 2 1 1 total 0.0 0.0 -3 2 2 1 total 0.0 0.0 -5 2 3 1 total 0.0 0.0 -7 2 4 1 total 0.0 0.0 -9 2 5 1 total 0.0 0.0 -11 2 6 1 total 0.0 0.0 -0 2 1 2 total 0.0 0.0 -2 2 2 2 total 0.0 0.0 -4 2 3 2 total 0.0 0.0 -6 2 4 2 total 0.0 0.0 -8 2 5 2 total 0.0 0.0 -10 2 6 2 total 0.0 0.0 - material delayedgroup group out nuclide mean std. dev. -1 2 1 1 total 0.0 0.0 -3 2 2 1 total 0.0 0.0 -5 2 3 1 total 0.0 0.0 -7 2 4 1 total 0.0 0.0 -9 2 5 1 total 0.0 0.0 -11 2 6 1 total 0.0 0.0 -0 2 1 2 total 0.0 0.0 -2 2 2 2 total 0.0 0.0 -4 2 3 2 total 0.0 0.0 -6 2 4 2 total 0.0 0.0 -8 2 5 2 total 0.0 0.0 -10 2 6 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 2 1 1 total 0.0 0.0 -3 2 2 1 total 0.0 0.0 -5 2 3 1 total 0.0 0.0 -7 2 4 1 total 0.0 0.0 -9 2 5 1 total 0.0 0.0 -11 2 6 1 total 0.0 0.0 -0 2 1 2 total 0.0 0.0 -2 2 2 2 total 0.0 0.0 -4 2 3 2 total 0.0 0.0 -6 2 4 2 total 0.0 0.0 -8 2 5 2 total 0.0 0.0 -10 2 6 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 2 1 1 total 0.0 0.0 -3 2 2 1 total 0.0 0.0 -5 2 3 1 total 0.0 0.0 -7 2 4 1 total 0.0 0.0 -9 2 5 1 total 0.0 0.0 -11 2 6 1 total 0.0 0.0 -0 2 1 2 total 0.0 0.0 -2 2 2 2 total 0.0 0.0 -4 2 3 2 total 0.0 0.0 -6 2 4 2 total 0.0 0.0 -8 2 5 2 total 0.0 0.0 -10 2 6 2 total 0.0 0.0 - material delayedgroup group in group out nuclide mean std. dev. -3 2 1 1 1 total 0.0 0.0 -7 2 2 1 1 total 0.0 0.0 -11 2 3 1 1 total 0.0 0.0 -15 2 4 1 1 total 0.0 0.0 -19 2 5 1 1 total 0.0 0.0 -23 2 6 1 1 total 0.0 0.0 -2 2 1 1 2 total 0.0 0.0 -6 2 2 1 2 total 0.0 0.0 -10 2 3 1 2 total 0.0 0.0 -14 2 4 1 2 total 0.0 0.0 -18 2 5 1 2 total 0.0 0.0 -22 2 6 1 2 total 0.0 0.0 -1 2 1 2 1 total 0.0 0.0 -5 2 2 2 1 total 0.0 0.0 -9 2 3 2 1 total 0.0 0.0 -13 2 4 2 1 total 0.0 0.0 -17 2 5 2 1 total 0.0 0.0 -21 2 6 2 1 total 0.0 0.0 -0 2 1 2 2 total 0.0 0.0 -4 2 2 2 2 total 0.0 0.0 -8 2 3 2 2 total 0.0 0.0 -12 2 4 2 2 total 0.0 0.0 -16 2 5 2 2 total 0.0 0.0 -20 2 6 2 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 3 1 total 0.664572 0.031215 -0 3 2 total 2.052384 0.224343 - material group in nuclide mean std. dev. -1 3 1 total 0.283323 0.035206 -0 3 2 total 1.499740 0.230902 - material group in nuclide mean std. dev. -1 3 1 total 0.283323 0.035206 -0 3 2 total 1.499740 0.230902 - material group in nuclide mean std. dev. -1 3 1 total 0.000690 0.000044 -0 3 2 total 0.031687 0.003747 - material group in nuclide mean std. dev. -1 3 1 total 0.000690 0.000044 -0 3 2 total 0.031687 0.003747 - material group in nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 3 1 total 0.663882 0.031173 -0 3 2 total 2.020697 0.220604 - material group in nuclide mean std. dev. -1 3 1 total 0.671269 0.026186 -0 3 2 total 2.035388 0.258060 - material group in group out legendre nuclide mean std. dev. -12 3 1 1 P0 total 0.639901 0.024709 -13 3 1 1 P1 total 0.381167 0.016243 -14 3 1 1 P2 total 0.152392 0.008156 -15 3 1 1 P3 total 0.009148 0.003889 -8 3 1 2 P0 total 0.031368 0.001728 -9 3 1 2 P1 total 0.008758 0.000926 -10 3 1 2 P2 total -0.002568 0.001014 -11 3 1 2 P3 total -0.003785 0.000817 -4 3 2 1 P0 total 0.000443 0.000445 -5 3 2 1 P1 total 0.000400 0.000401 -6 3 2 1 P2 total 0.000320 0.000321 -7 3 2 1 P3 total 0.000214 0.000215 -0 3 2 2 P0 total 2.034945 0.257800 -1 3 2 2 P1 total 0.509940 0.051236 -2 3 2 2 P2 total 0.111175 0.013020 -3 3 2 2 P3 total 0.024988 0.008312 - material group in group out legendre nuclide mean std. dev. -12 3 1 1 P0 total 0.639901 0.024709 -13 3 1 1 P1 total 0.381167 0.016243 -14 3 1 1 P2 total 0.152392 0.008156 -15 3 1 1 P3 total 0.009148 0.003889 -8 3 1 2 P0 total 0.031368 0.001728 -9 3 1 2 P1 total 0.008758 0.000926 -10 3 1 2 P2 total -0.002568 0.001014 -11 3 1 2 P3 total -0.003785 0.000817 -4 3 2 1 P0 total 0.000443 0.000445 -5 3 2 1 P1 total 0.000400 0.000401 -6 3 2 1 P2 total 0.000320 0.000321 -7 3 2 1 P3 total 0.000214 0.000215 -0 3 2 2 P0 total 2.034945 0.257800 -1 3 2 2 P1 total 0.509940 0.051236 -2 3 2 2 P2 total 0.111175 0.013020 -3 3 2 2 P3 total 0.024988 0.008312 - material group in group out nuclide mean std. dev. -3 3 1 1 total 1.0 0.038609 -2 3 1 2 total 1.0 0.067667 -1 3 2 1 total 1.0 1.414214 -0 3 2 2 total 1.0 0.135929 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.0 0.0 -2 3 1 2 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -0 3 2 2 total 0.0 0.0 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.953271 0.036018 -2 3 1 2 total 0.046729 0.002547 -1 3 2 1 total 0.000218 0.000219 -0 3 2 2 total 0.999782 0.135885 - material group in group out legendre nuclide mean std. dev. -12 3 1 1 P0 total 0.632859 0.038142 -13 3 1 1 P1 total 0.376973 0.023715 -14 3 1 1 P2 total 0.150715 0.010664 -15 3 1 1 P3 total 0.009047 0.003868 -8 3 1 2 P0 total 0.031023 0.002232 -9 3 1 2 P1 total 0.008661 0.000999 -10 3 1 2 P2 total -0.002540 0.001010 -11 3 1 2 P3 total -0.003743 0.000826 -4 3 2 1 P0 total 0.000440 0.000445 -5 3 2 1 P1 total 0.000397 0.000401 -6 3 2 1 P2 total 0.000317 0.000321 -7 3 2 1 P3 total 0.000212 0.000215 -0 3 2 2 P0 total 2.020256 0.352194 -1 3 2 2 P1 total 0.506260 0.079140 -2 3 2 2 P2 total 0.110372 0.018488 -3 3 2 2 P3 total 0.024808 0.008771 - material group in group out legendre nuclide mean std. dev. -12 3 1 1 P0 total 0.632859 0.045297 -13 3 1 1 P1 total 0.376973 0.027825 -14 3 1 1 P2 total 0.150715 0.012148 -15 3 1 1 P3 total 0.009047 0.003884 -8 3 1 2 P0 total 0.031023 0.003064 -9 3 1 2 P1 total 0.008661 0.001159 -10 3 1 2 P2 total -0.002540 0.001024 -11 3 1 2 P3 total -0.003743 0.000864 -4 3 2 1 P0 total 0.000440 0.000765 -5 3 2 1 P1 total 0.000397 0.000690 -6 3 2 1 P2 total 0.000317 0.000551 -7 3 2 1 P3 total 0.000212 0.000369 -0 3 2 2 P0 total 2.020256 0.446601 -1 3 2 2 P1 total 0.506260 0.104875 -2 3 2 2 P2 total 0.110372 0.023809 -3 3 2 2 P3 total 0.024808 0.009397 - material group out nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group out nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group in nuclide mean std. dev. -1 3 1 total 6.022078e-08 3.780437e-09 -0 3 2 total 3.044955e-06 3.600077e-07 - material group in nuclide mean std. dev. -1 3 1 total 0.0 0.0 -0 3 2 total 0.0 0.0 - material group in group out nuclide mean std. dev. -3 3 1 1 total 0.0 0.0 -2 3 1 2 total 0.0 0.0 -1 3 2 1 total 0.0 0.0 -0 3 2 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 3 1 1 total 0.0 0.0 -3 3 2 1 total 0.0 0.0 -5 3 3 1 total 0.0 0.0 -7 3 4 1 total 0.0 0.0 -9 3 5 1 total 0.0 0.0 -11 3 6 1 total 0.0 0.0 -0 3 1 2 total 0.0 0.0 -2 3 2 2 total 0.0 0.0 -4 3 3 2 total 0.0 0.0 -6 3 4 2 total 0.0 0.0 -8 3 5 2 total 0.0 0.0 -10 3 6 2 total 0.0 0.0 - material delayedgroup group out nuclide mean std. dev. -1 3 1 1 total 0.0 0.0 -3 3 2 1 total 0.0 0.0 -5 3 3 1 total 0.0 0.0 -7 3 4 1 total 0.0 0.0 -9 3 5 1 total 0.0 0.0 -11 3 6 1 total 0.0 0.0 -0 3 1 2 total 0.0 0.0 -2 3 2 2 total 0.0 0.0 -4 3 3 2 total 0.0 0.0 -6 3 4 2 total 0.0 0.0 -8 3 5 2 total 0.0 0.0 -10 3 6 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 3 1 1 total 0.0 0.0 -3 3 2 1 total 0.0 0.0 -5 3 3 1 total 0.0 0.0 -7 3 4 1 total 0.0 0.0 -9 3 5 1 total 0.0 0.0 -11 3 6 1 total 0.0 0.0 -0 3 1 2 total 0.0 0.0 -2 3 2 2 total 0.0 0.0 -4 3 3 2 total 0.0 0.0 -6 3 4 2 total 0.0 0.0 -8 3 5 2 total 0.0 0.0 -10 3 6 2 total 0.0 0.0 - material delayedgroup group in nuclide mean std. dev. -1 3 1 1 total 0.0 0.0 -3 3 2 1 total 0.0 0.0 -5 3 3 1 total 0.0 0.0 -7 3 4 1 total 0.0 0.0 -9 3 5 1 total 0.0 0.0 -11 3 6 1 total 0.0 0.0 -0 3 1 2 total 0.0 0.0 -2 3 2 2 total 0.0 0.0 -4 3 3 2 total 0.0 0.0 -6 3 4 2 total 0.0 0.0 -8 3 5 2 total 0.0 0.0 -10 3 6 2 total 0.0 0.0 - material delayedgroup group in group out nuclide mean std. dev. -3 3 1 1 1 total 0.0 0.0 -7 3 2 1 1 total 0.0 0.0 -11 3 3 1 1 total 0.0 0.0 -15 3 4 1 1 total 0.0 0.0 -19 3 5 1 1 total 0.0 0.0 -23 3 6 1 1 total 0.0 0.0 -2 3 1 1 2 total 0.0 0.0 -6 3 2 1 2 total 0.0 0.0 -10 3 3 1 2 total 0.0 0.0 -14 3 4 1 2 total 0.0 0.0 -18 3 5 1 2 total 0.0 0.0 -22 3 6 1 2 total 0.0 0.0 -1 3 1 2 1 total 0.0 0.0 -5 3 2 2 1 total 0.0 0.0 -9 3 3 2 1 total 0.0 0.0 -13 3 4 2 1 total 0.0 0.0 -17 3 5 2 1 total 0.0 0.0 -21 3 6 2 1 total 0.0 0.0 -0 3 1 2 2 total 0.0 0.0 -4 3 2 2 2 total 0.0 0.0 -8 3 3 2 2 total 0.0 0.0 -12 3 4 2 2 total 0.0 0.0 -16 3 5 2 2 total 0.0 0.0 -20 3 6 2 2 total 0.0 0.0 diff --git a/tests/regression_tests/mgxs_library_no_nuclides/test.py b/tests/regression_tests/mgxs_library_no_nuclides/test.py deleted file mode 100644 index 506ac238f..000000000 --- a/tests/regression_tests/mgxs_library_no_nuclides/test.py +++ /dev/null @@ -1,63 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - # Generate inputs using parent class routine - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = False - - # Test all MGXS types - self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ - openmc.mgxs.MDGXS_TYPES - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.num_delayed_groups = 6 - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Build a string from Pandas Dataframe for each MGXS - outstr = '' - for domain in self.mgxs_lib.domains: - for mgxs_type in self.mgxs_lib.mgxs_types: - mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_no_nuclides(): - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/mgxs_library_nuclides/__init__.py b/tests/regression_tests/mgxs_library_nuclides/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat deleted file mode 100644 index f859d5f3a..000000000 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ /dev/null @@ -1,995 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -0.63 -0.63 -1 0.63 0.63 1 - - - - - - - 1 - - - 0.0 0.625 20000000.0 - - - 0.0 0.625 20000000.0 - - - 1 - - - 3 - - - 0.0 20000000.0 - - - 2 - - - 3 - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - total - tracklength - - - 1 2 - total - flux - analog - - - 1 5 6 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - absorption - tracklength - - - 1 2 - U234 U235 U238 O16 - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - nu-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - kappa-fission - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 - total - flux - analog - - - 1 2 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 28 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-fission - analog - - - 1 2 5 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - scatter - tracklength - - - 1 2 5 28 - U234 U235 U238 O16 - scatter - analog - - - 1 2 5 - U234 U235 U238 O16 - nu-scatter - analog - - - 1 52 - U234 U235 U238 O16 - nu-fission - analog - - - 1 5 - U234 U235 U238 O16 - nu-fission - analog - - - 1 52 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - inverse-velocity - tracklength - - - 1 2 - total - flux - tracklength - - - 1 2 - U234 U235 U238 O16 - prompt-nu-fission - tracklength - - - 1 2 - total - flux - analog - - - 1 2 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 63 2 - total - flux - analog - - - 63 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 63 2 - total - flux - analog - - - 63 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - kappa-fission - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 63 2 - total - flux - analog - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 63 2 - total - flux - analog - - - 63 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 - total - flux - analog - - - 63 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 - total - flux - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 63 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 63 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 63 52 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 63 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 63 52 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 63 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - inverse-velocity - tracklength - - - 63 2 - total - flux - tracklength - - - 63 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - tracklength - - - 63 2 - total - flux - analog - - - 63 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - total - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - total - tracklength - - - 125 2 - total - flux - analog - - - 125 5 6 - H1 O16 B10 B11 - scatter - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - total - tracklength - - - 125 2 - total - flux - analog - - - 125 5 6 - H1 O16 B10 B11 - nu-scatter - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - absorption - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - absorption - tracklength - - - 125 2 - H1 O16 B10 B11 - fission - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - fission - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - nu-fission - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - kappa-fission - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - scatter - tracklength - - - 125 2 - total - flux - analog - - - 125 2 - H1 O16 B10 B11 - nu-scatter - analog - - - 125 2 - total - flux - analog - - - 125 2 5 28 - H1 O16 B10 B11 - scatter - analog - - - 125 2 - total - flux - analog - - - 125 2 5 28 - H1 O16 B10 B11 - nu-scatter - analog - - - 125 2 5 - H1 O16 B10 B11 - nu-scatter - analog - - - 125 2 5 - H1 O16 B10 B11 - scatter - analog - - - 125 2 - total - flux - analog - - - 125 2 5 - H1 O16 B10 B11 - nu-fission - analog - - - 125 2 5 - H1 O16 B10 B11 - scatter - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - scatter - tracklength - - - 125 2 5 28 - H1 O16 B10 B11 - scatter - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - scatter - tracklength - - - 125 2 5 28 - H1 O16 B10 B11 - scatter - analog - - - 125 2 5 - H1 O16 B10 B11 - nu-scatter - analog - - - 125 52 - H1 O16 B10 B11 - nu-fission - analog - - - 125 5 - H1 O16 B10 B11 - nu-fission - analog - - - 125 52 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 125 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - inverse-velocity - tracklength - - - 125 2 - total - flux - tracklength - - - 125 2 - H1 O16 B10 B11 - prompt-nu-fission - tracklength - - - 125 2 - total - flux - analog - - - 125 2 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - diff --git a/tests/regression_tests/mgxs_library_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_nuclides/results_true.dat deleted file mode 100644 index 27272239c..000000000 --- a/tests/regression_tests/mgxs_library_nuclides/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -185e6f1f7ba94b0cdfae5b2519865efec84055d341bd490b856f9786ef1c91a3cb007d6b22811ffa30d4665256aad8a2982548e6c96e8d8d9c5f569475e52cfe \ No newline at end of file diff --git a/tests/regression_tests/mgxs_library_nuclides/test.py b/tests/regression_tests/mgxs_library_nuclides/test.py deleted file mode 100644 index c64c27709..000000000 --- a/tests/regression_tests/mgxs_library_nuclides/test.py +++ /dev/null @@ -1,59 +0,0 @@ -import hashlib - -import openmc -import openmc.mgxs -from openmc.examples import pwr_pin_cell - -from tests.testing_harness import PyAPITestHarness - - -class MGXSTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Initialize a two-group structure - energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) - - # Initialize MGXS Library for a few cross section types - self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) - self.mgxs_lib.by_nuclide = True - # Test all MGXS types - self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES - self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.legendre_order = 3 - self.mgxs_lib.domain_type = 'material' - self.mgxs_lib.build_library() - - # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) - - def _get_results(self, hash_output=True): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the MGXS library from the statepoint - self.mgxs_lib.load_from_statepoint(sp) - - # Build a string from Pandas Dataframe for each MGXS - outstr = '' - for domain in self.mgxs_lib.domains: - for mgxs_type in self.mgxs_lib.mgxs_types: - mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) - df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_mgxs_library_nuclides(): - model = pwr_pin_cell() - harness = MGXSTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/multipole/__init__.py b/tests/regression_tests/multipole/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/multipole/inputs_true.dat b/tests/regression_tests/multipole/inputs_true.dat deleted file mode 100644 index 3bbcc2024..000000000 --- a/tests/regression_tests/multipole/inputs_true.dat +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - 2.0 2.0 - 1 - 2 2 - -2.0 -2.0 - -11 11 -11 11 - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - -1 -1 -1 1 1 1 - - - true - 1000 - - - - - U235 O16 total - total fission (n,gamma) elastic (n,p) - - diff --git a/tests/regression_tests/multipole/results_true.dat b/tests/regression_tests/multipole/results_true.dat deleted file mode 100644 index 890e47efd..000000000 --- a/tests/regression_tests/multipole/results_true.dat +++ /dev/null @@ -1,41 +0,0 @@ -k-combined: -1.342579E+00 1.221176E-02 -tally 1: -3.839794E+00 -2.951721E+00 -2.785273E+00 -1.554128E+00 -5.349716E-01 -5.732174E-02 -4.499834E-01 -4.055011E-02 -0.000000E+00 -0.000000E+00 -2.258507E+01 -1.020294E+02 -0.000000E+00 -0.000000E+00 -6.862242E-04 -9.421377E-08 -2.256396E+01 -1.018388E+02 -1.146136E-04 -3.296980E-09 -3.624627E+02 -2.628739E+04 -2.785273E+00 -1.554128E+00 -2.176478E+00 -9.480405E-01 -3.574110E+02 -2.555993E+04 -1.146136E-04 -3.296980E-09 -Cell - ID = 11 - Name = - Fill = Material 2 - Region = -1 - Rotation = None - Temperature = [500. 700. 0. 800.] - Translation = None diff --git a/tests/regression_tests/multipole/test.py b/tests/regression_tests/multipole/test.py deleted file mode 100644 index 4c4353c84..000000000 --- a/tests/regression_tests/multipole/test.py +++ /dev/null @@ -1,80 +0,0 @@ -import os - -import openmc -import openmc.model -import pytest - -from tests.testing_harness import TestHarness, PyAPITestHarness - - -def make_model(): - model = openmc.model.Model() - - # Materials - moderator = openmc.Material(material_id=1) - moderator.set_density('g/cc', 1.0) - moderator.add_nuclide('H1', 2.0) - moderator.add_nuclide('O16', 1.0) - moderator.add_s_alpha_beta('c_H_in_H2O') - - dense_fuel = openmc.Material(material_id=2) - dense_fuel.set_density('g/cc', 4.5) - dense_fuel.add_nuclide('U235', 1.0) - - model.materials += [moderator, dense_fuel] - - # Geometry - c1 = openmc.Cell(cell_id=1, fill=moderator) - mod_univ = openmc.Universe(universe_id=1, cells=(c1,)) - - r0 = openmc.ZCylinder(r=0.3) - c11 = openmc.Cell(cell_id=11, fill=dense_fuel, region=-r0) - c11.temperature = [500, 700, 0, 800] - c12 = openmc.Cell(cell_id=12, fill=moderator, region=+r0) - fuel_univ = openmc.Universe(universe_id=11, cells=(c11, c12)) - - lat = openmc.RectLattice(lattice_id=101) - lat.dimension = [2, 2] - lat.lower_left = [-2.0, -2.0] - lat.pitch = [2.0, 2.0] - lat.universes = [[fuel_univ]*2]*2 - lat.outer = mod_univ - - x0 = openmc.XPlane(x0=-3.0) - x1 = openmc.XPlane(x0=3.0) - y0 = openmc.YPlane(y0=-3.0) - y1 = openmc.YPlane(y0=3.0) - for s in [x0, x1, y0, y1]: - s.boundary_type = 'reflective' - c101 = openmc.Cell(cell_id=101, fill=lat, region=+x0 & -x1 & +y0 & -y1) - model.geometry.root_universe = openmc.Universe(universe_id=0, cells=(c101,)) - - # Settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-1, -1, -1], [1, 1, 1])) - model.settings.temperature = {'tolerance': 1000, 'multipole': True} - - # Tallies - tally = openmc.Tally() - tally.nuclides = ['U235', 'O16', 'total'] - tally.scores = ['total', 'fission', '(n,gamma)', 'elastic', '(n,p)'] - model.tallies.append(tally) - - return model - - -class MultipoleTestHarness(PyAPITestHarness): - def _get_results(self): - outstr = super()._get_results() - su = openmc.Summary('summary.h5') - outstr += str(su.geometry.get_all_cells()[11]) - return outstr - - -def test_multipole(): - model = make_model() - harness = MultipoleTestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/output/__init__.py b/tests/regression_tests/output/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/output/geometry.xml b/tests/regression_tests/output/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/output/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/output/materials.xml b/tests/regression_tests/output/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/output/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/output/results_true.dat b/tests/regression_tests/output/results_true.dat deleted file mode 100644 index 5cb3925a6..000000000 --- a/tests/regression_tests/output/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 diff --git a/tests/regression_tests/output/settings.xml b/tests/regression_tests/output/settings.xml deleted file mode 100644 index 22b6267a3..000000000 --- a/tests/regression_tests/output/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/output/test.py b/tests/regression_tests/output/test.py deleted file mode 100644 index d9568ba4b..000000000 --- a/tests/regression_tests/output/test.py +++ /dev/null @@ -1,28 +0,0 @@ -import os -import glob - -from tests.testing_harness import TestHarness - - -class OutputTestHarness(TestHarness): - def _test_output_created(self): - """Make sure output files have been created.""" - # Check for the statepoint. - TestHarness._test_output_created(self) - - # Check for the summary. - summary = glob.glob(os.path.join(os.getcwd(), 'summary.*')) - assert len(summary) == 1, 'Either multiple or no summary file exists.' - assert summary[0].endswith('h5'),\ - 'Summary file is not a HDF5 file.' - - def _cleanup(self): - TestHarness._cleanup(self) - f = 'summary.h5' - if os.path.exists(f): - os.remove(f) - - -def test_output(): - harness = OutputTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/particle_restart_eigval/__init__.py b/tests/regression_tests/particle_restart_eigval/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/particle_restart_eigval/geometry.xml b/tests/regression_tests/particle_restart_eigval/geometry.xml deleted file mode 100644 index c86e016c6..000000000 --- a/tests/regression_tests/particle_restart_eigval/geometry.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/particle_restart_eigval/materials.xml b/tests/regression_tests/particle_restart_eigval/materials.xml deleted file mode 100644 index 3aa37fca6..000000000 --- a/tests/regression_tests/particle_restart_eigval/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/particle_restart_eigval/results_true.dat b/tests/regression_tests/particle_restart_eigval/results_true.dat deleted file mode 100644 index d1f933582..000000000 --- a/tests/regression_tests/particle_restart_eigval/results_true.dat +++ /dev/null @@ -1,16 +0,0 @@ -current batch: -1.000000E+01 -current generation: -1.000000E+00 -particle id: -1.030000E+03 -run mode: -eigenvalue -particle weight: -1.000000E+00 -particle energy: -3.158576E+06 -particle xyz: -5.846531E+01 -3.717881E+01 -3.787515E+00 -particle uvw: -6.197114E-01 -2.450461E-01 -7.455939E-01 diff --git a/tests/regression_tests/particle_restart_eigval/settings.xml b/tests/regression_tests/particle_restart_eigval/settings.xml deleted file mode 100644 index 64b1a4dd4..000000000 --- a/tests/regression_tests/particle_restart_eigval/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - 1 - eigenvalue - 12 - 5 - 1200 - - - - -10 -10 -5 10 10 5 - - - - diff --git a/tests/regression_tests/particle_restart_eigval/test.py b/tests/regression_tests/particle_restart_eigval/test.py deleted file mode 100644 index a30eb9787..000000000 --- a/tests/regression_tests/particle_restart_eigval/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import ParticleRestartTestHarness - - -def test_particle_restart_eigval(): - harness = ParticleRestartTestHarness('particle_10_1030.h5') - harness.main() diff --git a/tests/regression_tests/particle_restart_fixed/__init__.py b/tests/regression_tests/particle_restart_fixed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/particle_restart_fixed/geometry.xml b/tests/regression_tests/particle_restart_fixed/geometry.xml deleted file mode 100644 index c86e016c6..000000000 --- a/tests/regression_tests/particle_restart_fixed/geometry.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/particle_restart_fixed/materials.xml b/tests/regression_tests/particle_restart_fixed/materials.xml deleted file mode 100644 index f3851d7ef..000000000 --- a/tests/regression_tests/particle_restart_fixed/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/particle_restart_fixed/results_true.dat b/tests/regression_tests/particle_restart_fixed/results_true.dat deleted file mode 100644 index c4ac94c4d..000000000 --- a/tests/regression_tests/particle_restart_fixed/results_true.dat +++ /dev/null @@ -1,16 +0,0 @@ -current batch: -7.000000E+00 -current generation: -1.000000E+00 -particle id: -1.440000E+02 -run mode: -fixed source -particle weight: -1.000000E+00 -particle energy: -5.749729E+06 -particle xyz: -8.754675E+00 2.551620E+00 4.394350E-01 -particle uvw: --5.971721E-01 -4.845709E-01 6.391999E-01 diff --git a/tests/regression_tests/particle_restart_fixed/settings.xml b/tests/regression_tests/particle_restart_fixed/settings.xml deleted file mode 100644 index 9c731fde8..000000000 --- a/tests/regression_tests/particle_restart_fixed/settings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - fixed source - 12 - 1000 - - - - -10 -10 -5 10 10 5 - - - - diff --git a/tests/regression_tests/particle_restart_fixed/test.py b/tests/regression_tests/particle_restart_fixed/test.py deleted file mode 100644 index 463568ecc..000000000 --- a/tests/regression_tests/particle_restart_fixed/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import ParticleRestartTestHarness - - -def test_particle_restart_fixed(): - harness = ParticleRestartTestHarness('particle_7_144.h5') - harness.main() diff --git a/tests/regression_tests/periodic/__init__.py b/tests/regression_tests/periodic/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/periodic/inputs_true.dat b/tests/regression_tests/periodic/inputs_true.dat deleted file mode 100644 index 6f613a160..000000000 --- a/tests/regression_tests/periodic/inputs_true.dat +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 4 - 0 - - - -5.0 -5.0 -5.0 5.0 5.0 5.0 - - - diff --git a/tests/regression_tests/periodic/results_true.dat b/tests/regression_tests/periodic/results_true.dat deleted file mode 100644 index 5a9820dd3..000000000 --- a/tests/regression_tests/periodic/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.040109E+00 6.527466E-02 diff --git a/tests/regression_tests/periodic/test.py b/tests/regression_tests/periodic/test.py deleted file mode 100644 index 879bd8480..000000000 --- a/tests/regression_tests/periodic/test.py +++ /dev/null @@ -1,56 +0,0 @@ -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class PeriodicTest(PyAPITestHarness): - def _build_inputs(self): - # Define materials - water = openmc.Material(1) - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - water.set_density('g/cc', 1.0) - - fuel = openmc.Material(2) - fuel.add_nuclide('U235', 1.0) - fuel.set_density('g/cc', 4.5) - - materials = openmc.Materials((water, fuel)) - materials.default_temperature = '294K' - materials.export_to_xml() - - # Define geometry - x_min = openmc.XPlane(surface_id=1, x0=-5., boundary_type='periodic') - x_max = openmc.XPlane(surface_id=2, x0=5., boundary_type='periodic') - x_max.periodic_surface = x_min - - y_min = openmc.YPlane(surface_id=3, y0=-5., boundary_type='periodic') - y_max = openmc.YPlane(surface_id=4, y0=5., boundary_type='periodic') - - z_min = openmc.ZPlane(surface_id=5, z0=-5., boundary_type='reflective') - z_max = openmc.ZPlane(surface_id=6, z0=5., boundary_type='reflective') - z_cyl = openmc.ZCylinder(surface_id=7, x0=-2.5, y0=2.5, r=2.0) - - outside_cyl = openmc.Cell(1, fill=water, region=( - +x_min & -x_max & +y_min & -y_max & +z_min & -z_max & +z_cyl)) - inside_cyl = openmc.Cell(2, fill=fuel, region=+z_min & -z_max & -z_cyl) - root_universe = openmc.Universe(0, cells=(outside_cyl, inside_cyl)) - - geometry = openmc.Geometry() - geometry.root_universe = root_universe - geometry.export_to_xml() - - # Define settings - settings = openmc.Settings() - settings.particles = 1000 - settings.batches = 4 - settings.inactive = 0 - settings.source = openmc.Source(space=openmc.stats.Box( - *outside_cyl.region.bounding_box)) - settings.export_to_xml() - - -def test_periodic(): - harness = PeriodicTest('statepoint.4.h5') - harness.main() diff --git a/tests/regression_tests/photon_production/__init__.py b/tests/regression_tests/photon_production/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/photon_production/inputs_true.dat b/tests/regression_tests/photon_production/inputs_true.dat deleted file mode 100644 index 1821bea92..000000000 --- a/tests/regression_tests/photon_production/inputs_true.dat +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - fixed source - 10000 - 1 - - - 0 0 0 - - - - 14000000.0 1.0 - - - ttb - true - - 1000.0 - - - - - - 9 - - - photon - - - 1 2 - current - - - 2 - Al27 total - total heating - tracklength - - - 2 - Al27 total - total heating - collision - - - 2 - Al27 total - total heating - analog - - diff --git a/tests/regression_tests/photon_production/results_true.dat b/tests/regression_tests/photon_production/results_true.dat deleted file mode 100644 index a7725576c..000000000 --- a/tests/regression_tests/photon_production/results_true.dat +++ /dev/null @@ -1,30 +0,0 @@ -tally 1: -9.403000E-01 -8.841641E-01 -tally 2: -1.819886E-01 -3.311985E-02 -1.960159E+05 -3.842224E+10 -8.281718E-01 -6.858685E-01 -1.960159E+05 -3.842224E+10 -tally 3: -1.799069E-01 -3.236650E-02 -1.945225E+05 -3.783901E+10 -8.242000E-01 -6.793056E-01 -1.945225E+05 -3.783901E+10 -tally 4: -2.308000E-01 -5.326864E-02 -1.988563E+05 -3.954384E+10 -8.242000E-01 -6.793056E-01 -1.988612E+05 -3.954578E+10 diff --git a/tests/regression_tests/photon_production/test.py b/tests/regression_tests/photon_production/test.py deleted file mode 100644 index 1f645ebb9..000000000 --- a/tests/regression_tests/photon_production/test.py +++ /dev/null @@ -1,90 +0,0 @@ -from math import pi - -import numpy as np -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class SourceTestHarness(PyAPITestHarness): - def _build_inputs(self): - mat = openmc.Material() - mat.set_density('g/cm3', 2.6989) - mat.add_nuclide('Al27', 1.0) - materials = openmc.Materials([mat]) - materials.export_to_xml() - - cyl = openmc.XCylinder(r=1.0, boundary_type='vacuum') - x_plane_left = openmc.XPlane(-1.0, 'vacuum') - x_plane_center = openmc.XPlane(1.0) - x_plane_right = openmc.XPlane(1.0e9, 'vacuum') - - inner_cyl_left = openmc.Cell() - inner_cyl_right = openmc.Cell() - outer_cyl = openmc.Cell() - - inner_cyl_left.region = -cyl & +x_plane_left & -x_plane_center - inner_cyl_right.region = -cyl & +x_plane_center & -x_plane_right - outer_cyl.region = ~(-cyl & +x_plane_left & -x_plane_right) - inner_cyl_right.fill = mat - geometry = openmc.Geometry([inner_cyl_left, inner_cyl_right, outer_cyl]) - geometry.export_to_xml() - - source = openmc.Source() - source.space = openmc.stats.Point((0, 0, 0)) - source.angle = openmc.stats.Monodirectional() - source.energy = openmc.stats.Discrete([14.0e6], [1.0]) - source.particle = 'neutron' - - settings = openmc.Settings() - settings.particles = 10000 - settings.run_mode = 'fixed source' - settings.batches = 1 - settings.photon_transport = True - settings.electron_treatment = 'ttb' - settings.cutoff = {'energy_photon' : 1000.0} - settings.source = source - settings.export_to_xml() - - surface_filter = openmc.SurfaceFilter(cyl) - particle_filter = openmc.ParticleFilter('photon') - current_tally = openmc.Tally() - current_tally.filters = [surface_filter, particle_filter] - current_tally.scores = ['current'] - tally_tracklength = openmc.Tally() - tally_tracklength.filters = [particle_filter] - tally_tracklength.scores = ['total', 'heating'] - tally_tracklength.nuclides = ['Al27', 'total'] - tally_tracklength.estimator = 'tracklength' - tally_collision = openmc.Tally() - tally_collision.filters = [particle_filter] - tally_collision.scores = ['total', 'heating'] - tally_collision.nuclides = ['Al27', 'total'] - tally_collision.estimator = 'collision' - tally_analog = openmc.Tally() - tally_analog.filters = [particle_filter] - tally_analog.scores = ['total', 'heating'] - tally_analog.nuclides = ['Al27', 'total'] - tally_analog.estimator = 'analog' - tallies = openmc.Tallies([current_tally, tally_tracklength, - tally_collision, tally_analog]) - tallies.export_to_xml() - - def _get_results(self): - with openmc.StatePoint(self._sp_name) as sp: - outstr = '' - for i, tally_ind in enumerate(sp.tallies): - tally = sp.tallies[tally_ind] - results = np.zeros((tally.sum.size * 2, )) - results[0::2] = tally.sum.ravel() - results[1::2] = tally.sum_sq.ravel() - results = ['{0:12.6E}'.format(x) for x in results] - - outstr += 'tally {}:\n'.format(i + 1) - outstr += '\n'.join(results) + '\n' - return outstr - - -def test_photon_production(): - harness = SourceTestHarness('statepoint.1.h5') - harness.main() diff --git a/tests/regression_tests/photon_source/__init__.py b/tests/regression_tests/photon_source/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/photon_source/inputs_true.dat b/tests/regression_tests/photon_source/inputs_true.dat deleted file mode 100644 index 89f4de0e0..000000000 --- a/tests/regression_tests/photon_source/inputs_true.dat +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - fixed source - 10000 - 1 - - - 0 0 0 - - - - 10000000.0 1.0 - - - ttb - true - - 1000.0 - - - - - - photon - - - 1 - flux - - diff --git a/tests/regression_tests/photon_source/results_true.dat b/tests/regression_tests/photon_source/results_true.dat deleted file mode 100644 index 1448ad6db..000000000 --- a/tests/regression_tests/photon_source/results_true.dat +++ /dev/null @@ -1,3 +0,0 @@ -tally 1: -sum = 2.275713E+02 -sum_sq = 5.178870E+04 diff --git a/tests/regression_tests/photon_source/test.py b/tests/regression_tests/photon_source/test.py deleted file mode 100644 index 94b028003..000000000 --- a/tests/regression_tests/photon_source/test.py +++ /dev/null @@ -1,61 +0,0 @@ -from math import pi - -import numpy as np -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class SourceTestHarness(PyAPITestHarness): - def _build_inputs(self): - mat = openmc.Material() - mat.set_density('g/cm3', 0.998207) - mat.add_element('H', 0.111894) - mat.add_element('O', 0.888106) - materials = openmc.Materials([mat]) - materials.export_to_xml() - - sphere = openmc.Sphere(r=1.0e9, boundary_type='reflective') - inside_sphere = openmc.Cell() - inside_sphere.region = -sphere - inside_sphere.fill = mat - geometry = openmc.Geometry([inside_sphere]) - geometry.export_to_xml() - - source = openmc.Source() - source.space = openmc.stats.Point((0, 0, 0)) - source.angle = openmc.stats.Isotropic() - source.energy = openmc.stats.Discrete([10.0e6], [1.0]) - source.particle = 'photon' - - settings = openmc.Settings() - settings.particles = 10000 - settings.batches = 1 - settings.photon_transport = True - settings.electron_treatment = 'ttb' - settings.cutoff = {'energy_photon' : 1000.0} - settings.run_mode = 'fixed source' - settings.source = source - settings.export_to_xml() - - particle_filter = openmc.ParticleFilter('photon') - tally = openmc.Tally() - tally.filters = [particle_filter] - tally.scores = ['flux'] - tallies = openmc.Tallies([tally]) - tallies.export_to_xml() - - def _get_results(self): - with openmc.StatePoint(self._sp_name) as sp: - outstr = '' - t = sp.get_tally() - outstr += 'tally {}:\n'.format(t.id) - outstr += 'sum = {:12.6E}\n'.format(t.sum[0, 0, 0]) - outstr += 'sum_sq = {:12.6E}\n'.format(t.sum_sq[0, 0, 0]) - - return outstr - - -def test_photon_source(): - harness = SourceTestHarness('statepoint.1.h5') - harness.main() diff --git a/tests/regression_tests/plot/__init__.py b/tests/regression_tests/plot/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/plot/geometry.xml b/tests/regression_tests/plot/geometry.xml deleted file mode 100644 index 83619d9f7..000000000 --- a/tests/regression_tests/plot/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot/materials.xml b/tests/regression_tests/plot/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot/plots.xml b/tests/regression_tests/plot/plots.xml deleted file mode 100644 index ce63da144..000000000 --- a/tests/regression_tests/plot/plots.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 0. 0. 0. - 25 25 - 200 200 - - - - - - 0. 0. 0. - 25 25 - 200 200 - - - - - - 0. 0. 0. - 25 25 - 200 200 - 0 0 0 - - - - 100 100 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot/results_true.dat b/tests/regression_tests/plot/results_true.dat deleted file mode 100644 index db6beb9cd..000000000 --- a/tests/regression_tests/plot/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -fd61f6a5de632f06a39e2a938480ba3dc314810655e684291e4b255bb8c142a16f10fec414c587ecd727fa559d3760d6e5b43f53fe86e90238a69d9c5698db8e \ No newline at end of file diff --git a/tests/regression_tests/plot/settings.xml b/tests/regression_tests/plot/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/plot/tallies.xml b/tests/regression_tests/plot/tallies.xml deleted file mode 100644 index b7e678ca0..000000000 --- a/tests/regression_tests/plot/tallies.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -10 10 - -10 10 - -10 0 5 7.5 8.75 10 - - - - mesh - 2 - - - - 1 - total - - - diff --git a/tests/regression_tests/plot/test.py b/tests/regression_tests/plot/test.py deleted file mode 100644 index bfaef019c..000000000 --- a/tests/regression_tests/plot/test.py +++ /dev/null @@ -1,61 +0,0 @@ -import glob -import hashlib -import os - -import h5py -import openmc - -from tests.testing_harness import TestHarness -from tests.regression_tests import config - - -class PlotTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC plotting tests.""" - def __init__(self, plot_names): - super().__init__(None) - self._plot_names = plot_names - - def _run_openmc(self): - openmc.plot_geometry(openmc_exec=config['exe']) - - def _test_output_created(self): - """Make sure *.ppm has been created.""" - for fname in self._plot_names: - assert os.path.exists(fname), 'Plot output file does not exist.' - - def _cleanup(self): - super()._cleanup() - for fname in self._plot_names: - if os.path.exists(fname): - os.remove(fname) - - def _get_results(self): - """Return a string hash of the plot files.""" - outstr = bytes() - - for fname in self._plot_names: - if fname.endswith('.ppm'): - # Add PPM output to results - with open(fname, 'rb') as fh: - outstr += fh.read() - elif fname.endswith('.h5'): - # Add voxel data to results - with h5py.File(fname, 'r') as fh: - outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() - - # Hash the information and return. - sha512 = hashlib.sha512() - sha512.update(outstr) - outstr = sha512.hexdigest() - - return outstr - - -def test_plot(): - harness = PlotTestHarness(('plot_1.ppm', 'plot_2.ppm', 'plot_3.ppm', - 'plot_4.h5')) - harness.main() diff --git a/tests/regression_tests/plot_overlaps/__init__.py b/tests/regression_tests/plot_overlaps/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/plot_overlaps/geometry.xml b/tests/regression_tests/plot_overlaps/geometry.xml deleted file mode 100644 index 7a9f1fb41..000000000 --- a/tests/regression_tests/plot_overlaps/geometry.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_overlaps/materials.xml b/tests/regression_tests/plot_overlaps/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot_overlaps/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_overlaps/plots.xml b/tests/regression_tests/plot_overlaps/plots.xml deleted file mode 100644 index 28064f58f..000000000 --- a/tests/regression_tests/plot_overlaps/plots.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - 0. 0. 0. - 25 25 - 200 200 - - - true - - - - 0. 0. 0. - 25 25 - 200 200 - - true - 255 211 0 - - - - 0. 0. 0. - 25 25 - 200 200 - 0 0 0 - - - - 100 100 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot_overlaps/results_true.dat b/tests/regression_tests/plot_overlaps/results_true.dat deleted file mode 100644 index a2afd4c35..000000000 --- a/tests/regression_tests/plot_overlaps/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -e67f7737b49af347a617bfdeebebc3288bd85050f33c9208403f3dfb4625a42f63f3396ecb2517ed9214c3e4e68c9038a8f9a7b3e27a414565c5580827dbb6e6 \ No newline at end of file diff --git a/tests/regression_tests/plot_overlaps/settings.xml b/tests/regression_tests/plot_overlaps/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot_overlaps/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/plot_overlaps/test.py b/tests/regression_tests/plot_overlaps/test.py deleted file mode 100644 index d8c0943cf..000000000 --- a/tests/regression_tests/plot_overlaps/test.py +++ /dev/null @@ -1,61 +0,0 @@ -import glob -import hashlib -import os - -import h5py -import openmc - -from tests.testing_harness import TestHarness -from tests.regression_tests import config - - -class PlotTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC plotting tests.""" - def __init__(self, plot_names): - super().__init__(None) - self._plot_names = plot_names - - def _run_openmc(self): - openmc.plot_geometry(openmc_exec=config['exe']) - - def _test_output_created(self): - """Make sure *.ppm has been created.""" - for fname in self._plot_names: - assert os.path.exists(fname), 'Plot output file does not exist.' - - def _cleanup(self): - super()._cleanup() - for fname in self._plot_names: - if os.path.exists(fname): - os.remove(fname) - - def _get_results(self): - """Return a string hash of the plot files.""" - outstr = bytes() - - for fname in self._plot_names: - if fname.endswith('.ppm'): - # Add PPM output to results - with open(fname, 'rb') as fh: - outstr += fh.read() - elif fname.endswith('.h5'): - # Add voxel data to results - with h5py.File(fname, 'r') as fh: - outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() - - # Hash the information and return. - sha512 = hashlib.sha512() - sha512.update(outstr) - outstr = sha512.hexdigest() - - return outstr - - -def test_plot_overlap(): - harness = PlotTestHarness(('plot_1.ppm', 'plot_2.ppm', 'plot_3.ppm', - 'plot_4.h5')) - harness.main() diff --git a/tests/regression_tests/plot_voxel/__init__.py b/tests/regression_tests/plot_voxel/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/plot_voxel/geometry.xml b/tests/regression_tests/plot_voxel/geometry.xml deleted file mode 100644 index 83619d9f7..000000000 --- a/tests/regression_tests/plot_voxel/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_voxel/materials.xml b/tests/regression_tests/plot_voxel/materials.xml deleted file mode 100644 index 90b354267..000000000 --- a/tests/regression_tests/plot_voxel/materials.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/plot_voxel/plots.xml b/tests/regression_tests/plot_voxel/plots.xml deleted file mode 100644 index 833329b42..000000000 --- a/tests/regression_tests/plot_voxel/plots.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 50 50 10 - 0. 0. 0. - 20 20 10 - - - diff --git a/tests/regression_tests/plot_voxel/results_true.dat b/tests/regression_tests/plot_voxel/results_true.dat deleted file mode 100644 index 52222000f..000000000 --- a/tests/regression_tests/plot_voxel/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -ff596b17d2cd33f964a952279b824292272ab73f57ded94812286e6bce12b5c54852d5ccd1dd137fa6312101568c06510cd89f822469d6c904a17f96259e4d03 \ No newline at end of file diff --git a/tests/regression_tests/plot_voxel/settings.xml b/tests/regression_tests/plot_voxel/settings.xml deleted file mode 100644 index adf256d2d..000000000 --- a/tests/regression_tests/plot_voxel/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - plot - - - 5 4 3 - -10 -10 -10 - 10 10 10 - - 1 - - diff --git a/tests/regression_tests/plot_voxel/test.py b/tests/regression_tests/plot_voxel/test.py deleted file mode 100644 index d2767e2f1..000000000 --- a/tests/regression_tests/plot_voxel/test.py +++ /dev/null @@ -1,62 +0,0 @@ -import glob -import hashlib -import os -from subprocess import check_call - -import h5py -import openmc -import pytest - -from tests.testing_harness import TestHarness -from tests.regression_tests import config - - -vtk = pytest.importorskip('vtk') -class PlotVoxelTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC voxel plot tests.""" - def __init__(self, plot_names): - super().__init__(None) - self._plot_names = plot_names - - def _run_openmc(self): - openmc.plot_geometry(openmc_exec=config['exe']) - - check_call(['../../../scripts/openmc-voxel-to-vtk'] + - glob.glob('plot_4.h5')) - - def _test_output_created(self): - """Make sure *.ppm has been created.""" - for fname in self._plot_names: - assert os.path.exists(fname), 'Plot output file does not exist.' - - def _cleanup(self): - super()._cleanup() - for fname in self._plot_names: - if os.path.exists(fname): - os.remove(fname) - - def _get_results(self): - """Return a string hash of the plot files.""" - outstr = bytes() - - for fname in self._plot_names: - if fname.endswith('.h5'): - # Add voxel data to results - with h5py.File(fname, 'r') as fh: - outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() - - # Hash the information and return. - sha512 = hashlib.sha512() - sha512.update(outstr) - outstr = sha512.hexdigest() - - return outstr - - -def test_plot_voxel(): - harness = PlotVoxelTestHarness(('plot_4.h5', 'plot.vti')) - harness.main() diff --git a/tests/regression_tests/ptables_off/__init__.py b/tests/regression_tests/ptables_off/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/ptables_off/geometry.xml b/tests/regression_tests/ptables_off/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/ptables_off/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/ptables_off/materials.xml b/tests/regression_tests/ptables_off/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/ptables_off/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/ptables_off/results_true.dat b/tests/regression_tests/ptables_off/results_true.dat deleted file mode 100644 index a21d1f997..000000000 --- a/tests/regression_tests/ptables_off/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.998034E-01 5.228002E-03 diff --git a/tests/regression_tests/ptables_off/settings.xml b/tests/regression_tests/ptables_off/settings.xml deleted file mode 100644 index 5ae20fd38..000000000 --- a/tests/regression_tests/ptables_off/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - false - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/ptables_off/test.py b/tests/regression_tests/ptables_off/test.py deleted file mode 100644 index cc316f8c3..000000000 --- a/tests/regression_tests/ptables_off/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_ptables_off(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/quadric_surfaces/__init__.py b/tests/regression_tests/quadric_surfaces/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/quadric_surfaces/geometry.xml b/tests/regression_tests/quadric_surfaces/geometry.xml deleted file mode 100644 index 98d647a4f..000000000 --- a/tests/regression_tests/quadric_surfaces/geometry.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/quadric_surfaces/materials.xml b/tests/regression_tests/quadric_surfaces/materials.xml deleted file mode 100644 index 460406296..000000000 --- a/tests/regression_tests/quadric_surfaces/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/quadric_surfaces/results_true.dat b/tests/regression_tests/quadric_surfaces/results_true.dat deleted file mode 100644 index 587d302ad..000000000 --- a/tests/regression_tests/quadric_surfaces/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.083927E+00 7.465752E-03 diff --git a/tests/regression_tests/quadric_surfaces/settings.xml b/tests/regression_tests/quadric_surfaces/settings.xml deleted file mode 100644 index b04ecac4b..000000000 --- a/tests/regression_tests/quadric_surfaces/settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - eigenvalue - 4 - 0 - 1000 - - - - - - diff --git a/tests/regression_tests/quadric_surfaces/test.py b/tests/regression_tests/quadric_surfaces/test.py deleted file mode 100755 index 94540da04..000000000 --- a/tests/regression_tests/quadric_surfaces/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_quadric_surfaces(): - harness = TestHarness('statepoint.4.h5') - harness.main() diff --git a/tests/regression_tests/reflective_plane/__init__.py b/tests/regression_tests/reflective_plane/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/reflective_plane/geometry.xml b/tests/regression_tests/reflective_plane/geometry.xml deleted file mode 100644 index 0dc5c29ab..000000000 --- a/tests/regression_tests/reflective_plane/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/reflective_plane/materials.xml b/tests/regression_tests/reflective_plane/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/reflective_plane/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/reflective_plane/results_true.dat b/tests/regression_tests/reflective_plane/results_true.dat deleted file mode 100644 index c4544c749..000000000 --- a/tests/regression_tests/reflective_plane/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.271202E+00 3.876145E-03 diff --git a/tests/regression_tests/reflective_plane/settings.xml b/tests/regression_tests/reflective_plane/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/reflective_plane/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/reflective_plane/test.py b/tests/regression_tests/reflective_plane/test.py deleted file mode 100644 index 906174f33..000000000 --- a/tests/regression_tests/reflective_plane/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_reflective_plane(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/resonance_scattering/__init__.py b/tests/regression_tests/resonance_scattering/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/resonance_scattering/inputs_true.dat b/tests/regression_tests/resonance_scattering/inputs_true.dat deleted file mode 100644 index 57a5e1a4b..000000000 --- a/tests/regression_tests/resonance_scattering/inputs_true.dat +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - -4 -4 -4 4 4 4 - - - - true - rvs - 1.0 - 210.0 - U238 U235 Pu239 - - diff --git a/tests/regression_tests/resonance_scattering/results_true.dat b/tests/regression_tests/resonance_scattering/results_true.dat deleted file mode 100644 index 153e8b025..000000000 --- a/tests/regression_tests/resonance_scattering/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.432684E+00 1.233834E-02 diff --git a/tests/regression_tests/resonance_scattering/test.py b/tests/regression_tests/resonance_scattering/test.py deleted file mode 100644 index 588ba7c97..000000000 --- a/tests/regression_tests/resonance_scattering/test.py +++ /dev/null @@ -1,47 +0,0 @@ -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class ResonanceScatteringTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Materials - mat = openmc.Material(material_id=1) - mat.set_density('g/cc', 1.0) - mat.add_nuclide('U238', 1.0) - mat.add_nuclide('U235', 0.02) - mat.add_nuclide('Pu239', 0.02) - mat.add_nuclide('H1', 20.0) - - mats_file = openmc.Materials([mat]) - mats_file.export_to_xml() - - # Geometry - dumb_surface = openmc.XPlane(100, 'reflective') - c1 = openmc.Cell(cell_id=1, fill=mat, region=-dumb_surface) - root_univ = openmc.Universe(universe_id=0, cells=[c1]) - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() - - # Resonance elastic scattering settings - res_scat_settings = { - 'enable': True, - 'energy_min': 1.0, - 'energy_max': 210.0, - 'method': 'rvs', - 'nuclides': ['U238', 'U235', 'Pu239'] - } - - settings = openmc.Settings() - settings.batches = 10 - settings.inactive = 5 - settings.particles = 1000 - settings.source = openmc.source.Source( - space=openmc.stats.Box([-4, -4, -4], [4, 4, 4])) - settings.resonance_scattering = res_scat_settings - settings.export_to_xml() - - -def test_resonance_scattering(): - harness = ResonanceScatteringTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/rotation/__init__.py b/tests/regression_tests/rotation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/rotation/geometry.xml b/tests/regression_tests/rotation/geometry.xml deleted file mode 100644 index f32461706..000000000 --- a/tests/regression_tests/rotation/geometry.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/rotation/materials.xml b/tests/regression_tests/rotation/materials.xml deleted file mode 100644 index 160c9c678..000000000 --- a/tests/regression_tests/rotation/materials.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/rotation/results_true.dat b/tests/regression_tests/rotation/results_true.dat deleted file mode 100644 index 7598a4a47..000000000 --- a/tests/regression_tests/rotation/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -4.240695E-01 8.013236E-03 diff --git a/tests/regression_tests/rotation/settings.xml b/tests/regression_tests/rotation/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/rotation/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/rotation/test.py b/tests/regression_tests/rotation/test.py deleted file mode 100644 index 31c3d8d65..000000000 --- a/tests/regression_tests/rotation/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_rotation(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/salphabeta/__init__.py b/tests/regression_tests/salphabeta/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/salphabeta/inputs_true.dat b/tests/regression_tests/salphabeta/inputs_true.dat deleted file mode 100644 index 29d8065cf..000000000 --- a/tests/regression_tests/salphabeta/inputs_true.dat +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 400 - 5 - 0 - - - -4 -4 -4 4 4 4 - - - diff --git a/tests/regression_tests/salphabeta/results_true.dat b/tests/regression_tests/salphabeta/results_true.dat deleted file mode 100644 index 708e6e726..000000000 --- a/tests/regression_tests/salphabeta/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -8.474822E-01 1.767966E-02 diff --git a/tests/regression_tests/salphabeta/test.py b/tests/regression_tests/salphabeta/test.py deleted file mode 100644 index f487723de..000000000 --- a/tests/regression_tests/salphabeta/test.py +++ /dev/null @@ -1,79 +0,0 @@ -import openmc -import openmc.model - -from tests.testing_harness import PyAPITestHarness - - -def make_model(): - model = openmc.model.Model() - - # Materials - m1 = openmc.Material() - m1.set_density('g/cc', 4.5) - m1.add_nuclide('U235', 1.0) - m1.add_nuclide('H1', 1.0) - m1.add_s_alpha_beta('c_H_in_H2O', fraction=0.5) - - m2 = openmc.Material() - m2.set_density('g/cc', 4.5) - m2.add_nuclide('U235', 1.0) - m2.add_nuclide('C0', 1.0) - m2.add_s_alpha_beta('c_Graphite') - - m3 = openmc.Material() - m3.set_density('g/cc', 4.5) - m3.add_nuclide('U235', 1.0) - m3.add_nuclide('Be9', 1.0) - m3.add_nuclide('O16', 1.0) - m3.add_s_alpha_beta('c_Be_in_BeO') - m3.add_s_alpha_beta('c_O_in_BeO') - - m4 = openmc.Material() - m4.set_density('g/cm3', 5.90168) - m4.add_nuclide('H1', 0.3) - m4.add_nuclide('Zr90', 0.15) - m4.add_nuclide('Zr91', 0.1) - m4.add_nuclide('Zr92', 0.1) - m4.add_nuclide('Zr94', 0.05) - m4.add_nuclide('Zr96', 0.05) - m4.add_nuclide('U235', 0.1) - m4.add_nuclide('U238', 0.15) - m4.add_s_alpha_beta('c_Zr_in_ZrH') - m4.add_s_alpha_beta('c_H_in_ZrH') - - model.materials += [m1, m2, m3, m4] - - # Geometry - x0 = openmc.XPlane(-10, 'vacuum') - x1 = openmc.XPlane(-5) - x2 = openmc.XPlane(0) - x3 = openmc.XPlane(5) - x4 = openmc.XPlane(10, 'vacuum') - - root_univ = openmc.Universe() - - surfs = (x0, x1, x2, x3, x4) - mats = (m1, m2, m3, m4) - cells = [] - for i in range(4): - cell = openmc.Cell() - cell.region = +surfs[i] & -surfs[i+1] - cell.fill = mats[i] - root_univ.add_cell(cell) - - model.geometry.root_universe = root_univ - - # Settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 400 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-4, -4, -4], [4, 4, 4])) - - return model - - -def test_salphabeta(): - model = make_model() - harness = PyAPITestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/score_current/__init__.py b/tests/regression_tests/score_current/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/score_current/inputs_true.dat b/tests/regression_tests/score_current/inputs_true.dat deleted file mode 100644 index 2b81f508f..000000000 --- a/tests/regression_tests/score_current/inputs_true.dat +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 3 3 3 - -10.0 -10.0 -10.0 - 10.0 10.0 10.0 - - - 1 - - - 0.0 0.253 20000000.0 - - - 1 - current - - - 1 2 - current - - diff --git a/tests/regression_tests/score_current/results_true.dat b/tests/regression_tests/score_current/results_true.dat deleted file mode 100644 index ddd73d6cc..000000000 --- a/tests/regression_tests/score_current/results_true.dat +++ /dev/null @@ -1,1948 +0,0 @@ -k-combined: -7.656044E-01 5.168921E-02 -tally 1: -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.386000E-03 -1.410000E-01 -4.007000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.160000E-01 -2.830000E-03 -1.530000E-01 -4.895000E-03 -1.450000E-01 -4.395000E-03 -0.000000E+00 -0.000000E+00 -6.500000E-02 -9.150000E-04 -1.340000E-01 -3.660000E-03 -1.410000E-01 -4.007000E-03 -1.080000E-01 -2.386000E-03 -1.640000E-01 -5.438000E-03 -1.230000E-01 -3.203000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.776000E-03 -2.610000E-01 -1.373100E-02 -1.910000E-01 -7.339000E-03 -0.000000E+00 -0.000000E+00 -1.000000E-01 -2.116000E-03 -1.990000E-01 -8.309000E-03 -1.230000E-01 -3.203000E-03 -1.640000E-01 -5.438000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.476000E-03 -1.540000E-01 -5.106000E-03 -1.660000E-01 -5.664000E-03 -0.000000E+00 -0.000000E+00 -7.000000E-02 -1.080000E-03 -1.370000E-01 -3.867000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.422000E-03 -2.650000E-01 -1.456300E-02 -1.530000E-01 -4.895000E-03 -1.160000E-01 -2.830000E-03 -1.600000E-01 -5.184000E-03 -1.060000E-01 -2.286000E-03 -1.870000E-01 -7.195000E-03 -0.000000E+00 -0.000000E+00 -1.090000E-01 -2.653000E-03 -2.320000E-01 -1.087200E-02 -2.650000E-01 -1.456300E-02 -1.620000E-01 -5.422000E-03 -2.500000E-01 -1.285000E-02 -1.530000E-01 -4.823000E-03 -2.610000E-01 -1.373100E-02 -1.640000E-01 -5.776000E-03 -2.530000E-01 -1.347100E-02 -1.700000E-01 -5.906000E-03 -2.300000E-01 -1.089400E-02 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.226000E-02 -5.120000E-01 -5.796600E-02 -1.530000E-01 -4.823000E-03 -2.500000E-01 -1.285000E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.540000E-01 -5.106000E-03 -1.100000E-01 -2.476000E-03 -1.600000E-01 -5.166000E-03 -1.350000E-01 -3.771000E-03 -1.830000E-01 -6.757000E-03 -0.000000E+00 -0.000000E+00 -9.100000E-02 -1.903000E-03 -1.940000E-01 -7.626000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.360000E-01 -3.862000E-03 -1.560000E-01 -4.970000E-03 -1.060000E-01 -2.286000E-03 -1.600000E-01 -5.184000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.922000E-03 -0.000000E+00 -0.000000E+00 -5.900000E-02 -7.270000E-04 -1.310000E-01 -3.483000E-03 -1.560000E-01 -4.970000E-03 -1.360000E-01 -3.862000E-03 -1.940000E-01 -8.162000E-03 -1.390000E-01 -3.905000E-03 -1.700000E-01 -5.906000E-03 -2.530000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.020000E-01 -8.326000E-03 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.510000E-03 -2.230000E-01 -1.009700E-02 -1.390000E-01 -3.905000E-03 -1.940000E-01 -8.162000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.350000E-01 -3.771000E-03 -1.600000E-01 -5.166000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.630000E-01 -5.451000E-03 -0.000000E+00 -0.000000E+00 -8.100000E-02 -1.385000E-03 -1.530000E-01 -4.723000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.380000E-01 -3.886000E-03 -2.270000E-01 -1.064700E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.625000E-03 -2.150000E-01 -9.531000E-03 -1.340000E-01 -3.660000E-03 -6.500000E-02 -9.150000E-04 -1.510000E-01 -4.573000E-03 -6.900000E-02 -9.890000E-04 -2.270000E-01 -1.064700E-02 -1.380000E-01 -3.886000E-03 -2.040000E-01 -8.552000E-03 -1.310000E-01 -3.655000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.390000E-01 -1.148900E-02 -5.090000E-01 -6.440300E-02 -1.990000E-01 -8.309000E-03 -1.000000E-01 -2.116000E-03 -2.040000E-01 -8.722000E-03 -8.700000E-02 -1.655000E-03 -1.310000E-01 -3.655000E-03 -2.040000E-01 -8.552000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.840000E-03 -2.210000E-01 -1.015500E-02 -1.370000E-01 -3.867000E-03 -7.000000E-02 -1.080000E-03 -1.510000E-01 -4.589000E-03 -5.600000E-02 -7.760000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.440000E-01 -1.198000E-02 -5.330000E-01 -6.307900E-02 -2.150000E-01 -9.531000E-03 -1.670000E-01 -5.625000E-03 -2.090000E-01 -8.891000E-03 -1.580000E-01 -5.042000E-03 -2.320000E-01 -1.087200E-02 -1.090000E-01 -2.653000E-03 -2.150000E-01 -9.421000E-03 -7.800000E-02 -1.474000E-03 -5.330000E-01 -6.307900E-02 -2.440000E-01 -1.198000E-02 -5.000000E-01 -5.426200E-02 -2.160000E-01 -9.816000E-03 -5.090000E-01 -6.440300E-02 -2.390000E-01 -1.148900E-02 -4.860000E-01 -5.139400E-02 -2.330000E-01 -1.110300E-02 -5.120000E-01 -5.796600E-02 -2.380000E-01 -1.226000E-02 -5.280000E-01 -6.237800E-02 -2.150000E-01 -1.004500E-02 -2.160000E-01 -9.816000E-03 -5.000000E-01 -5.426200E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.210000E-01 -1.015500E-02 -1.520000E-01 -4.840000E-03 -2.300000E-01 -1.067400E-02 -1.610000E-01 -5.391000E-03 -1.940000E-01 -7.626000E-03 -9.100000E-02 -1.903000E-03 -2.160000E-01 -9.358000E-03 -8.000000E-02 -1.440000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.420000E-01 -4.126000E-03 -2.210000E-01 -9.953000E-03 -1.580000E-01 -5.042000E-03 -2.090000E-01 -8.891000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.483000E-03 -5.900000E-02 -7.270000E-04 -1.310000E-01 -3.567000E-03 -6.000000E-02 -7.940000E-04 -2.210000E-01 -9.953000E-03 -1.420000E-01 -4.126000E-03 -2.360000E-01 -1.141600E-02 -1.770000E-01 -6.341000E-03 -2.330000E-01 -1.110300E-02 -4.860000E-01 -5.139400E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.230000E-01 -1.009700E-02 -1.100000E-01 -2.510000E-03 -2.040000E-01 -8.736000E-03 -1.100000E-01 -2.790000E-03 -1.770000E-01 -6.341000E-03 -2.360000E-01 -1.141600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.391000E-03 -2.300000E-01 -1.067400E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.723000E-03 -8.100000E-02 -1.385000E-03 -1.460000E-01 -4.382000E-03 -6.100000E-02 -8.190000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.140000E-01 -2.660000E-03 -1.620000E-01 -5.420000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-01 -3.474000E-03 -1.440000E-01 -4.322000E-03 -6.900000E-02 -9.890000E-04 -1.510000E-01 -4.573000E-03 -1.560000E-01 -4.912000E-03 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.420000E-03 -1.140000E-01 -2.660000E-03 -1.580000E-01 -5.102000E-03 -1.550000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.708000E-03 -2.300000E-01 -1.092600E-02 -8.700000E-02 -1.655000E-03 -2.040000E-01 -8.722000E-03 -2.060000E-01 -8.520000E-03 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.831000E-03 -1.580000E-01 -5.102000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.223000E-03 -1.680000E-01 -5.674000E-03 -5.600000E-02 -7.760000E-04 -1.510000E-01 -4.589000E-03 -1.660000E-01 -6.068000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.450000E-01 -4.371000E-03 -2.450000E-01 -1.248900E-02 -1.440000E-01 -4.322000E-03 -1.300000E-01 -3.474000E-03 -1.680000E-01 -5.918000E-03 -1.120000E-01 -2.590000E-03 -7.800000E-02 -1.474000E-03 -2.150000E-01 -9.421000E-03 -2.110000E-01 -9.163000E-03 -0.000000E+00 -0.000000E+00 -2.450000E-01 -1.248900E-02 -1.450000E-01 -4.371000E-03 -2.490000E-01 -1.251100E-02 -1.460000E-01 -4.574000E-03 -2.300000E-01 -1.092600E-02 -1.340000E-01 -3.708000E-03 -2.680000E-01 -1.517800E-02 -1.560000E-01 -5.476000E-03 -2.150000E-01 -1.004500E-02 -5.280000E-01 -6.237800E-02 -2.380000E-01 -1.203000E-02 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.574000E-03 -2.490000E-01 -1.251100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.674000E-03 -1.230000E-01 -3.223000E-03 -1.460000E-01 -4.356000E-03 -1.260000E-01 -3.252000E-03 -8.000000E-02 -1.440000E-03 -2.160000E-01 -9.358000E-03 -2.100000E-01 -9.014000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.190000E-01 -2.863000E-03 -1.520000E-01 -4.782000E-03 -1.120000E-01 -2.590000E-03 -1.680000E-01 -5.918000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-02 -7.940000E-04 -1.310000E-01 -3.567000E-03 -1.730000E-01 -6.389000E-03 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.782000E-03 -1.190000E-01 -2.863000E-03 -1.640000E-01 -5.422000E-03 -1.290000E-01 -3.499000E-03 -1.560000E-01 -5.476000E-03 -2.680000E-01 -1.517800E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.790000E-03 -2.040000E-01 -8.736000E-03 -1.930000E-01 -7.503000E-03 -0.000000E+00 -0.000000E+00 -1.290000E-01 -3.499000E-03 -1.640000E-01 -5.422000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.260000E-01 -3.252000E-03 -1.460000E-01 -4.356000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.100000E-02 -8.190000E-04 -1.460000E-01 -4.382000E-03 -1.560000E-01 -4.892000E-03 -0.000000E+00 -0.000000E+00 -tally 2: -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.386000E-03 -0.000000E+00 -0.000000E+00 -1.410000E-01 -4.007000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.160000E-01 -2.830000E-03 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.895000E-03 -0.000000E+00 -0.000000E+00 -1.450000E-01 -4.395000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.500000E-02 -9.150000E-04 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.660000E-03 -0.000000E+00 -0.000000E+00 -1.410000E-01 -4.007000E-03 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.386000E-03 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.438000E-03 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.203000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.776000E-03 -0.000000E+00 -0.000000E+00 -2.610000E-01 -1.373100E-02 -0.000000E+00 -0.000000E+00 -1.910000E-01 -7.339000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-01 -2.116000E-03 -0.000000E+00 -0.000000E+00 -1.990000E-01 -8.309000E-03 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.203000E-03 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.438000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.476000E-03 -0.000000E+00 -0.000000E+00 -1.540000E-01 -5.106000E-03 -0.000000E+00 -0.000000E+00 -1.660000E-01 -5.664000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-02 -1.080000E-03 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.867000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.422000E-03 -0.000000E+00 -0.000000E+00 -2.650000E-01 -1.456300E-02 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.895000E-03 -0.000000E+00 -0.000000E+00 -1.160000E-01 -2.830000E-03 -0.000000E+00 -0.000000E+00 -1.600000E-01 -5.184000E-03 -0.000000E+00 -0.000000E+00 -1.060000E-01 -2.286000E-03 -0.000000E+00 -0.000000E+00 -1.870000E-01 -7.195000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.090000E-01 -2.653000E-03 -0.000000E+00 -0.000000E+00 -2.320000E-01 -1.087200E-02 -0.000000E+00 -0.000000E+00 -2.650000E-01 -1.456300E-02 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.422000E-03 -0.000000E+00 -0.000000E+00 -2.500000E-01 -1.285000E-02 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.823000E-03 -0.000000E+00 -0.000000E+00 -2.610000E-01 -1.373100E-02 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.776000E-03 -0.000000E+00 -0.000000E+00 -2.530000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -1.700000E-01 -5.906000E-03 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.089400E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.226000E-02 -0.000000E+00 -0.000000E+00 -5.120000E-01 -5.796600E-02 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.823000E-03 -0.000000E+00 -0.000000E+00 -2.500000E-01 -1.285000E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.540000E-01 -5.106000E-03 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.476000E-03 -0.000000E+00 -0.000000E+00 -1.600000E-01 -5.166000E-03 -0.000000E+00 -0.000000E+00 -1.350000E-01 -3.771000E-03 -0.000000E+00 -0.000000E+00 -1.830000E-01 -6.757000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.100000E-02 -1.903000E-03 -0.000000E+00 -0.000000E+00 -1.940000E-01 -7.626000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.360000E-01 -3.862000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.970000E-03 -0.000000E+00 -0.000000E+00 -1.060000E-01 -2.286000E-03 -0.000000E+00 -0.000000E+00 -1.600000E-01 -5.184000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.922000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.900000E-02 -7.270000E-04 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.483000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.970000E-03 -0.000000E+00 -0.000000E+00 -1.360000E-01 -3.862000E-03 -0.000000E+00 -0.000000E+00 -1.940000E-01 -8.162000E-03 -0.000000E+00 -0.000000E+00 -1.390000E-01 -3.905000E-03 -0.000000E+00 -0.000000E+00 -1.700000E-01 -5.906000E-03 -0.000000E+00 -0.000000E+00 -2.530000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.020000E-01 -8.326000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.510000E-03 -0.000000E+00 -0.000000E+00 -2.230000E-01 -1.009700E-02 -0.000000E+00 -0.000000E+00 -1.390000E-01 -3.905000E-03 -0.000000E+00 -0.000000E+00 -1.940000E-01 -8.162000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.350000E-01 -3.771000E-03 -0.000000E+00 -0.000000E+00 -1.600000E-01 -5.166000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.630000E-01 -5.451000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.100000E-02 -1.385000E-03 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.723000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.380000E-01 -3.886000E-03 -0.000000E+00 -0.000000E+00 -2.270000E-01 -1.064700E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.625000E-03 -0.000000E+00 -0.000000E+00 -2.150000E-01 -9.531000E-03 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.660000E-03 -0.000000E+00 -0.000000E+00 -6.500000E-02 -9.150000E-04 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.573000E-03 -0.000000E+00 -0.000000E+00 -6.900000E-02 -9.890000E-04 -0.000000E+00 -0.000000E+00 -2.270000E-01 -1.064700E-02 -0.000000E+00 -0.000000E+00 -1.380000E-01 -3.886000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.552000E-03 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.655000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.390000E-01 -1.148900E-02 -0.000000E+00 -0.000000E+00 -5.090000E-01 -6.440300E-02 -0.000000E+00 -0.000000E+00 -1.990000E-01 -8.309000E-03 -0.000000E+00 -0.000000E+00 -1.000000E-01 -2.116000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.722000E-03 -0.000000E+00 -0.000000E+00 -8.700000E-02 -1.655000E-03 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.655000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.552000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.840000E-03 -0.000000E+00 -0.000000E+00 -2.210000E-01 -1.015500E-02 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.867000E-03 -0.000000E+00 -0.000000E+00 -7.000000E-02 -1.080000E-03 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.589000E-03 -0.000000E+00 -0.000000E+00 -5.600000E-02 -7.760000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.440000E-01 -1.198000E-02 -0.000000E+00 -0.000000E+00 -5.330000E-01 -6.307900E-02 -0.000000E+00 -0.000000E+00 -2.150000E-01 -9.531000E-03 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.625000E-03 -0.000000E+00 -0.000000E+00 -2.090000E-01 -8.891000E-03 -0.000000E+00 -0.000000E+00 -1.580000E-01 -5.042000E-03 -0.000000E+00 -0.000000E+00 -2.320000E-01 -1.087200E-02 -0.000000E+00 -0.000000E+00 -1.090000E-01 -2.653000E-03 -0.000000E+00 -0.000000E+00 -2.150000E-01 -9.421000E-03 -0.000000E+00 -0.000000E+00 -7.800000E-02 -1.474000E-03 -0.000000E+00 -0.000000E+00 -5.330000E-01 -6.307900E-02 -0.000000E+00 -0.000000E+00 -2.440000E-01 -1.198000E-02 -0.000000E+00 -0.000000E+00 -5.000000E-01 -5.426200E-02 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.816000E-03 -0.000000E+00 -0.000000E+00 -5.090000E-01 -6.440300E-02 -0.000000E+00 -0.000000E+00 -2.390000E-01 -1.148900E-02 -0.000000E+00 -0.000000E+00 -4.860000E-01 -5.139400E-02 -0.000000E+00 -0.000000E+00 -2.330000E-01 -1.110300E-02 -0.000000E+00 -0.000000E+00 -5.120000E-01 -5.796600E-02 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.226000E-02 -0.000000E+00 -0.000000E+00 -5.280000E-01 -6.237800E-02 -0.000000E+00 -0.000000E+00 -2.150000E-01 -1.004500E-02 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.816000E-03 -0.000000E+00 -0.000000E+00 -5.000000E-01 -5.426200E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.210000E-01 -1.015500E-02 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.840000E-03 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.067400E-02 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.391000E-03 -0.000000E+00 -0.000000E+00 -1.940000E-01 -7.626000E-03 -0.000000E+00 -0.000000E+00 -9.100000E-02 -1.903000E-03 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.358000E-03 -0.000000E+00 -0.000000E+00 -8.000000E-02 -1.440000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.420000E-01 -4.126000E-03 -0.000000E+00 -0.000000E+00 -2.210000E-01 -9.953000E-03 -0.000000E+00 -0.000000E+00 -1.580000E-01 -5.042000E-03 -0.000000E+00 -0.000000E+00 -2.090000E-01 -8.891000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.483000E-03 -0.000000E+00 -0.000000E+00 -5.900000E-02 -7.270000E-04 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.567000E-03 -0.000000E+00 -0.000000E+00 -6.000000E-02 -7.940000E-04 -0.000000E+00 -0.000000E+00 -2.210000E-01 -9.953000E-03 -0.000000E+00 -0.000000E+00 -1.420000E-01 -4.126000E-03 -0.000000E+00 -0.000000E+00 -2.360000E-01 -1.141600E-02 -0.000000E+00 -0.000000E+00 -1.770000E-01 -6.341000E-03 -0.000000E+00 -0.000000E+00 -2.330000E-01 -1.110300E-02 -0.000000E+00 -0.000000E+00 -4.860000E-01 -5.139400E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.230000E-01 -1.009700E-02 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.510000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.736000E-03 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.790000E-03 -0.000000E+00 -0.000000E+00 -1.770000E-01 -6.341000E-03 -0.000000E+00 -0.000000E+00 -2.360000E-01 -1.141600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.391000E-03 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.067400E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.723000E-03 -0.000000E+00 -0.000000E+00 -8.100000E-02 -1.385000E-03 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.382000E-03 -0.000000E+00 -0.000000E+00 -6.100000E-02 -8.190000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.140000E-01 -2.660000E-03 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.420000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-01 -3.474000E-03 -0.000000E+00 -0.000000E+00 -1.440000E-01 -4.322000E-03 -0.000000E+00 -0.000000E+00 -6.900000E-02 -9.890000E-04 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.573000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.912000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.420000E-03 -0.000000E+00 -0.000000E+00 -1.140000E-01 -2.660000E-03 -0.000000E+00 -0.000000E+00 -1.580000E-01 -5.102000E-03 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.708000E-03 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.092600E-02 -0.000000E+00 -0.000000E+00 -8.700000E-02 -1.655000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.722000E-03 -0.000000E+00 -0.000000E+00 -2.060000E-01 -8.520000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -1.580000E-01 -5.102000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.223000E-03 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.674000E-03 -0.000000E+00 -0.000000E+00 -5.600000E-02 -7.760000E-04 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.589000E-03 -0.000000E+00 -0.000000E+00 -1.660000E-01 -6.068000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.450000E-01 -4.371000E-03 -0.000000E+00 -0.000000E+00 -2.450000E-01 -1.248900E-02 -0.000000E+00 -0.000000E+00 -1.440000E-01 -4.322000E-03 -0.000000E+00 -0.000000E+00 -1.300000E-01 -3.474000E-03 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.918000E-03 -0.000000E+00 -0.000000E+00 -1.120000E-01 -2.590000E-03 -0.000000E+00 -0.000000E+00 -7.800000E-02 -1.474000E-03 -0.000000E+00 -0.000000E+00 -2.150000E-01 -9.421000E-03 -0.000000E+00 -0.000000E+00 -2.110000E-01 -9.163000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.450000E-01 -1.248900E-02 -0.000000E+00 -0.000000E+00 -1.450000E-01 -4.371000E-03 -0.000000E+00 -0.000000E+00 -2.490000E-01 -1.251100E-02 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.574000E-03 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.092600E-02 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.708000E-03 -0.000000E+00 -0.000000E+00 -2.680000E-01 -1.517800E-02 -0.000000E+00 -0.000000E+00 -1.560000E-01 -5.476000E-03 -0.000000E+00 -0.000000E+00 -2.150000E-01 -1.004500E-02 -0.000000E+00 -0.000000E+00 -5.280000E-01 -6.237800E-02 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.203000E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.574000E-03 -0.000000E+00 -0.000000E+00 -2.490000E-01 -1.251100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.674000E-03 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.223000E-03 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.356000E-03 -0.000000E+00 -0.000000E+00 -1.260000E-01 -3.252000E-03 -0.000000E+00 -0.000000E+00 -8.000000E-02 -1.440000E-03 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.358000E-03 -0.000000E+00 -0.000000E+00 -2.100000E-01 -9.014000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.190000E-01 -2.863000E-03 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.782000E-03 -0.000000E+00 -0.000000E+00 -1.120000E-01 -2.590000E-03 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.918000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-02 -7.940000E-04 -0.000000E+00 -0.000000E+00 -1.310000E-01 -3.567000E-03 -0.000000E+00 -0.000000E+00 -1.730000E-01 -6.389000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.520000E-01 -4.782000E-03 -0.000000E+00 -0.000000E+00 -1.190000E-01 -2.863000E-03 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.422000E-03 -0.000000E+00 -0.000000E+00 -1.290000E-01 -3.499000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -5.476000E-03 -0.000000E+00 -0.000000E+00 -2.680000E-01 -1.517800E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-01 -2.790000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.736000E-03 -0.000000E+00 -0.000000E+00 -1.930000E-01 -7.503000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.290000E-01 -3.499000E-03 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.422000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.260000E-01 -3.252000E-03 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.356000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.100000E-02 -8.190000E-04 -0.000000E+00 -0.000000E+00 -1.460000E-01 -4.382000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.892000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 diff --git a/tests/regression_tests/score_current/test.py b/tests/regression_tests/score_current/test.py deleted file mode 100644 index 1309584d2..000000000 --- a/tests/regression_tests/score_current/test.py +++ /dev/null @@ -1,53 +0,0 @@ -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material() - fuel.set_density('g/cm3', 10.0) - fuel.add_nuclide('U235', 1.0) - zr = openmc.Material() - zr.set_density('g/cm3', 1.0) - zr.add_nuclide('Zr90', 1.0) - model.materials.extend([fuel, zr]) - - box1 = openmc.model.rectangular_prism(10.0, 10.0) - box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective') - top = openmc.ZPlane(z0=10.0, boundary_type='vacuum') - bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum') - cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top) - cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top) - model.geometry = openmc.Geometry([cell1, cell2]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - - - mesh = openmc.Mesh() - mesh.lower_left = (-10.0, -10.0, -10.0) - mesh.upper_right = (10.0, 10.0, 10.0) - mesh.dimension = (3, 3, 3) - - mesh_surface_filter = openmc.MeshSurfaceFilter(mesh) - energy_filter = openmc.EnergyFilter([0.0, 0.253, 20.0e6]) - - tally1 = openmc.Tally() - tally1.filters = [mesh_surface_filter] - tally1.scores = ['current'] - tally2 = openmc.Tally() - tally2.filters = [mesh_surface_filter, energy_filter] - tally2.scores = ['current'] - model.tallies.extend([tally1, tally2]) - - return model - - -def test_score_current(model): - harness = PyAPITestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/seed/__init__.py b/tests/regression_tests/seed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/seed/geometry.xml b/tests/regression_tests/seed/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/seed/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/seed/materials.xml b/tests/regression_tests/seed/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/seed/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/seed/results_true.dat b/tests/regression_tests/seed/results_true.dat deleted file mode 100644 index cbc03aec2..000000000 --- a/tests/regression_tests/seed/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.131924E-01 7.639718E-03 diff --git a/tests/regression_tests/seed/settings.xml b/tests/regression_tests/seed/settings.xml deleted file mode 100644 index 11da44588..000000000 --- a/tests/regression_tests/seed/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - 239407351 - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/seed/test.py b/tests/regression_tests/seed/test.py deleted file mode 100644 index 8b2f031b3..000000000 --- a/tests/regression_tests/seed/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_seed(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/source/__init__.py b/tests/regression_tests/source/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/source/inputs_true.dat b/tests/regression_tests/source/inputs_true.dat deleted file mode 100644 index 7eeefbc00..000000000 --- a/tests/regression_tests/source/inputs_true.dat +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - - - -4.0 -1.0 3.0 0.2 0.3 0.5 - - - -2.0 0.0 2.0 0.2 0.3 0.2 - - - - - -1.0 0.0 1.0 0.5 0.25 0.25 - - - - - - - - -4.0 -4.0 -4.0 4.0 4.0 4.0 - - - - - - - 1.2 -2.3 0.781 - - - - 1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23 - - - diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat deleted file mode 100644 index 6fe76c8cd..000000000 --- a/tests/regression_tests/source/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.800827E-01 7.360163E-03 diff --git a/tests/regression_tests/source/test.py b/tests/regression_tests/source/test.py deleted file mode 100644 index cd468c5b8..000000000 --- a/tests/regression_tests/source/test.py +++ /dev/null @@ -1,63 +0,0 @@ -from math import pi - -import numpy as np -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class SourceTestHarness(PyAPITestHarness): - def _build_inputs(self): - mat1 = openmc.Material(material_id=1, temperature=294) - mat1.set_density('g/cm3', 4.5) - mat1.add_nuclide(openmc.Nuclide('U235'), 1.0) - materials = openmc.Materials([mat1]) - materials.export_to_xml() - - sphere = openmc.Sphere(surface_id=1, r=10.0, boundary_type='vacuum') - inside_sphere = openmc.Cell(cell_id=1) - inside_sphere.region = -sphere - inside_sphere.fill = mat1 - - root = openmc.Universe(universe_id=0) - root.add_cell(inside_sphere) - geometry = openmc.Geometry() - geometry.root_universe = root - geometry.export_to_xml() - - # Create an array of different sources - x_dist = openmc.stats.Uniform(-3., 3.) - y_dist = openmc.stats.Discrete([-4., -1., 3.], [0.2, 0.3, 0.5]) - z_dist = openmc.stats.Tabular([-2., 0., 2.], [0.2, 0.3, 0.2]) - spatial1 = openmc.stats.CartesianIndependent(x_dist, y_dist, z_dist) - spatial2 = openmc.stats.Box([-4., -4., -4.], [4., 4., 4.]) - spatial3 = openmc.stats.Point([1.2, -2.3, 0.781]) - - mu_dist = openmc.stats.Discrete([-1., 0., 1.], [0.5, 0.25, 0.25]) - phi_dist = openmc.stats.Uniform(0., 6.28318530718) - angle1 = openmc.stats.PolarAzimuthal(mu_dist, phi_dist) - angle2 = openmc.stats.Monodirectional(reference_uvw=[0., 1., 0.]) - angle3 = openmc.stats.Isotropic() - - E = np.logspace(0, 7) - p = np.sin(np.linspace(0., pi)) - p /= sum(np.diff(E)*p[:-1]) - energy1 = openmc.stats.Maxwell(1.2895e6) - energy2 = openmc.stats.Watt(0.988e6, 2.249e-6) - energy3 = openmc.stats.Tabular(E, p, interpolation='histogram') - - source1 = openmc.Source(spatial1, angle1, energy1, strength=0.5) - source2 = openmc.Source(spatial2, angle2, energy2, strength=0.3) - source3 = openmc.Source(spatial3, angle3, energy3, strength=0.2) - - settings = openmc.Settings() - settings.batches = 10 - settings.inactive = 5 - settings.particles = 1000 - settings.source = [source1, source2, source3] - settings.export_to_xml() - - -def test_source(): - harness = SourceTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/source_file/__init__.py b/tests/regression_tests/source_file/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/source_file/geometry.xml b/tests/regression_tests/source_file/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/source_file/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/source_file/materials.xml b/tests/regression_tests/source_file/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/source_file/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/source_file/results_true.dat b/tests/regression_tests/source_file/results_true.dat deleted file mode 100644 index 4ab7993d8..000000000 --- a/tests/regression_tests/source_file/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.939525E-01 6.311780E-03 diff --git a/tests/regression_tests/source_file/settings.xml b/tests/regression_tests/source_file/settings.xml deleted file mode 100644 index 4464d4369..000000000 --- a/tests/regression_tests/source_file/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - diff --git a/tests/regression_tests/source_file/test.py b/tests/regression_tests/source_file/test.py deleted file mode 100644 index b4d9c4a31..000000000 --- a/tests/regression_tests/source_file/test.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python - -import glob -import os - -from tests.testing_harness import * - - -settings1=""" - - - - - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - -""" - -settings2 = """ - - - 10 - 5 - 1000 - - - source.10.{0} - - -""" - - -class SourceFileTestHarness(TestHarness): - def execute_test(self): - """Run OpenMC with the appropriate arguments and check the outputs.""" - try: - self._run_openmc() - self._test_output_created() - self._run_openmc_restart() - results = self._get_results() - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Update the results_true using the current version of OpenMC.""" - try: - self._run_openmc() - self._test_output_created() - self._run_openmc_restart() - results = self._get_results() - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - def _test_output_created(self): - """Make sure statepoint and source files have been created.""" - statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name)) - assert len(statepoint) == 1, 'Either multiple or no statepoint files ' \ - 'exist.' - assert statepoint[0].endswith('h5'), \ - 'Statepoint file is not a HDF5 file.' - - source = glob.glob(os.path.join(os.getcwd(), 'source.10.*')) - assert len(source) == 1, 'Either multiple or no source files exist.' - assert source[0].endswith('h5'), \ - 'Source file is not a HDF5 file.' - - def _run_openmc_restart(self): - # Get the name of the source file. - source = glob.glob(os.path.join(os.getcwd(), 'source.10.*')) - - # Write the new settings.xml file. - with open('settings.xml','w') as fh: - fh.write(settings2.format(source[0].split('.')[-1])) - - # Run OpenMC. - self._run_openmc() - - def _cleanup(self): - TestHarness._cleanup(self) - output = glob.glob(os.path.join(os.getcwd(), 'source.*')) - for f in output: - if os.path.exists(f): - os.remove(f) - with open('settings.xml','w') as fh: - fh.write(settings1) - - -def test_source_file(): - harness = SourceFileTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/sourcepoint_batch/__init__.py b/tests/regression_tests/sourcepoint_batch/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/sourcepoint_batch/geometry.xml b/tests/regression_tests/sourcepoint_batch/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/sourcepoint_batch/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_batch/materials.xml b/tests/regression_tests/sourcepoint_batch/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/sourcepoint_batch/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_batch/results_true.dat b/tests/regression_tests/sourcepoint_batch/results_true.dat deleted file mode 100644 index a9843df53..000000000 --- a/tests/regression_tests/sourcepoint_batch/results_true.dat +++ /dev/null @@ -1,3 +0,0 @@ -k-combined: -2.976389E-01 3.770725E-03 -1.892327E+00 -3.385257E+00 6.702632E-01 diff --git a/tests/regression_tests/sourcepoint_batch/settings.xml b/tests/regression_tests/sourcepoint_batch/settings.xml deleted file mode 100644 index 13096d551..000000000 --- a/tests/regression_tests/sourcepoint_batch/settings.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/sourcepoint_batch/test.py b/tests/regression_tests/sourcepoint_batch/test.py deleted file mode 100644 index fdc5ecca1..000000000 --- a/tests/regression_tests/sourcepoint_batch/test.py +++ /dev/null @@ -1,31 +0,0 @@ -import glob - -from openmc import StatePoint - -from tests.testing_harness import TestHarness - - -class SourcepointTestHarness(TestHarness): - def _test_output_created(self): - """Make sure statepoint files have been created.""" - statepoint = glob.glob('statepoint.*.h5') - assert len(statepoint) == 5, 'Five statepoint files must exist.' - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Get the eigenvalue information. - outstr = TestHarness._get_results(self) - - # Read the statepoint file. - with StatePoint(self._sp_name) as sp: - # Add the source information. - xyz = sp.source[0]['r'] - outstr += ' '.join(['{0:12.6E}'.format(x) for x in xyz]) - outstr += "\n" - - return outstr - - -def test_sourcepoint_batch(): - harness = SourcepointTestHarness('statepoint.08.h5') - harness.main() diff --git a/tests/regression_tests/sourcepoint_latest/__init__.py b/tests/regression_tests/sourcepoint_latest/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/sourcepoint_latest/geometry.xml b/tests/regression_tests/sourcepoint_latest/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/sourcepoint_latest/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_latest/materials.xml b/tests/regression_tests/sourcepoint_latest/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/sourcepoint_latest/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_latest/results_true.dat b/tests/regression_tests/sourcepoint_latest/results_true.dat deleted file mode 100644 index 5cb3925a6..000000000 --- a/tests/regression_tests/sourcepoint_latest/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 diff --git a/tests/regression_tests/sourcepoint_latest/settings.xml b/tests/regression_tests/sourcepoint_latest/settings.xml deleted file mode 100644 index 58dfa671d..000000000 --- a/tests/regression_tests/sourcepoint_latest/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/sourcepoint_latest/test.py b/tests/regression_tests/sourcepoint_latest/test.py deleted file mode 100644 index d14b566ad..000000000 --- a/tests/regression_tests/sourcepoint_latest/test.py +++ /dev/null @@ -1,18 +0,0 @@ -import os -import sys - -from tests.testing_harness import TestHarness - - -class SourcepointTestHarness(TestHarness): - def _test_output_created(self): - """Make sure statepoint.* and source* have been created.""" - TestHarness._test_output_created(self) - source = glob.glob(os.path.join(os.getcwd(), 'source.*.h5')) - assert len(source) == 1, 'Either multiple or no source files ' \ - 'exist.' - - -def test_sourcepoint_latest(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/sourcepoint_restart/__init__.py b/tests/regression_tests/sourcepoint_restart/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/sourcepoint_restart/geometry.xml b/tests/regression_tests/sourcepoint_restart/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/sourcepoint_restart/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_restart/materials.xml b/tests/regression_tests/sourcepoint_restart/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/sourcepoint_restart/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/sourcepoint_restart/results_true.dat b/tests/regression_tests/sourcepoint_restart/results_true.dat deleted file mode 100644 index e210748bf..000000000 --- a/tests/regression_tests/sourcepoint_restart/results_true.dat +++ /dev/null @@ -1,972 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 -tally 1: -1.100000E-02 -3.700000E-05 -7.719234E-03 -2.632582E-05 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -8.816168E-04 -7.772482E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.100000E-02 -1.150000E-04 -1.071093E-02 -2.748612E-05 -0.000000E+00 -0.000000E+00 -8.954045E-04 -2.673851E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.130000E-04 -1.363637E-02 -4.345510E-05 -0.000000E+00 -0.000000E+00 -1.182717E-03 -5.268980E-07 -2.000000E-03 -2.000000E-06 -2.110880E-03 -1.737594E-06 -1.000000E-03 -1.000000E-06 -2.938723E-04 -8.636091E-08 -2.300000E-02 -1.330000E-04 -1.162826E-02 -3.490280E-05 -0.000000E+00 -0.000000E+00 -8.957100E-04 -4.402864E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -3.400000E-05 -5.414128E-03 -8.079333E-06 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.700000E-02 -7.100000E-05 -8.048522E-03 -1.583843E-05 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.700000E-02 -1.670000E-04 -1.100708E-02 -2.835295E-05 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -1.000000E-03 -1.000000E-06 -1.203064E-03 -7.240967E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -4.400000E-02 -4.320000E-04 -2.116869E-02 -9.629046E-05 -0.000000E+00 -0.000000E+00 -1.501009E-03 -6.405021E-07 -1.000000E-03 -1.000000E-06 -1.472277E-03 -9.506217E-07 -2.000000E-03 -2.000000E-06 -2.977039E-04 -8.862762E-08 -2.000000E-02 -1.080000E-04 -8.949667E-03 -1.935056E-05 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -2.121142E-03 -1.958355E-06 -1.000000E-03 -1.000000E-06 -2.938723E-04 -8.636091E-08 -1.000000E-02 -3.400000E-05 -4.754696E-03 -7.172309E-06 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -3.700000E-05 -5.365659E-03 -6.567979E-06 -0.000000E+00 -0.000000E+00 -6.056043E-04 -1.834316E-07 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -2.230000E-04 -1.486928E-02 -5.763901E-05 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.990000E-04 -1.189702E-02 -3.303340E-05 -0.000000E+00 -0.000000E+00 -9.033082E-04 -2.720592E-07 -3.000000E-03 -3.000000E-06 -1.484187E-03 -9.721092E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.500000E-02 -1.390000E-04 -1.043467E-02 -2.526768E-05 -0.000000E+00 -0.000000E+00 -5.912057E-04 -1.747704E-07 -1.000000E-03 -1.000000E-06 -8.813114E-04 -4.316251E-07 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.900000E-02 -1.030000E-04 -9.748672E-03 -2.956633E-05 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -4.135720E-03 -4.532611E-06 -0.000000E+00 -0.000000E+00 -5.874391E-04 -1.725424E-07 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.560000E-04 -1.249410E-02 -3.501589E-05 -0.000000E+00 -0.000000E+00 -6.159309E-04 -3.793709E-07 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.950000E-04 -1.461148E-02 -4.367385E-05 -0.000000E+00 -0.000000E+00 -5.912057E-04 -1.747704E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.700000E-05 -1.099391E-02 -2.847330E-05 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -0.000000E+00 -0.000000E+00 -2.655539E-03 -2.523801E-06 -3.000000E-03 -5.000000E-06 -2.976389E-04 -8.858890E-08 -6.000000E-03 -8.000000E-06 -2.683856E-03 -1.512640E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -2.976389E-04 -8.858890E-08 -1.200000E-02 -4.600000E-05 -5.941985E-03 -9.853870E-06 -0.000000E+00 -0.000000E+00 -1.186548E-03 -5.291647E-07 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.230000E-04 -1.015650E-02 -2.236950E-05 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -0.000000E+00 -0.000000E+00 -5.912707E-04 -1.748091E-07 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.250000E-04 -1.729188E-02 -6.078653E-05 -0.000000E+00 -0.000000E+00 -1.792523E-03 -8.900697E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.700000E-02 -7.100000E-05 -7.760000E-03 -1.634547E-05 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -8.807004E-04 -7.756332E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.900000E-02 -2.030000E-04 -1.108618E-02 -3.019577E-05 -0.000000E+00 -0.000000E+00 -1.174573E-03 -8.619941E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -5.500000E-05 -5.944486E-03 -1.042417E-05 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -1.190621E-03 -8.859277E-07 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.460000E-04 -9.232713E-03 -1.900222E-05 -0.000000E+00 -0.000000E+00 -1.186919E-03 -5.294603E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.600000E-02 -2.740000E-04 -1.462273E-02 -4.551798E-05 -0.000000E+00 -0.000000E+00 -6.056694E-04 -1.834703E-07 -0.000000E+00 -0.000000E+00 -8.807004E-04 -7.756332E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.200000E-02 -3.000000E-05 -7.754474E-03 -1.333333E-05 -0.000000E+00 -0.000000E+00 -2.938723E-04 -8.636091E-08 -0.000000E+00 -0.000000E+00 -1.484382E-03 -1.504223E-06 -3.000000E-03 -5.000000E-06 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.900000E-05 -1.066281E-02 -2.937590E-05 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -3.000000E-06 -1.484493E-03 -9.722886E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.650000E-04 -1.065253E-02 -3.447907E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.030000E-04 -1.342551E-02 -3.842917E-05 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -8.700000E-05 -8.693502E-03 -1.682273E-05 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.000000E-03 -1.600000E-05 -3.866943E-03 -3.257876E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.175489E-03 -1.381775E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -8.000000E-03 -2.000000E-05 -3.248622E-03 -4.063213E-06 -0.000000E+00 -0.000000E+00 -2.938723E-04 -8.636091E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.780000E-04 -1.283876E-02 -3.527487E-05 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-02 -3.880000E-04 -1.659048E-02 -7.200873E-05 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -8.891500E-04 -4.407165E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.200000E-02 -3.400000E-05 -5.074320E-03 -5.793165E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -8.000000E-06 -3.570375E-03 -5.251426E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -4.000000E-06 -1.494579E-03 -6.241235E-07 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -1.950000E-04 -1.250316E-02 -3.147175E-05 -0.000000E+00 -0.000000E+00 -5.953428E-04 -1.772165E-07 -1.000000E-03 -1.000000E-06 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.800000E-04 -1.162837E-02 -3.241150E-05 -0.000000E+00 -0.000000E+00 -5.874391E-04 -1.725424E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.900000E-05 -9.216754E-03 -2.272207E-05 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -6.159309E-04 -3.793709E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.000000E-05 -2.404012E-03 -1.641294E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.300000E-05 -6.572185E-03 -9.479065E-06 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -1.030000E-04 -7.760558E-03 -1.654841E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.800000E-02 -1.220000E-04 -7.815192E-03 -2.039362E-05 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -1.511030E-03 -1.198310E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -1.030000E-04 -7.130794E-03 -1.485134E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.816168E-04 -7.772482E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.970000E-04 -1.046961E-02 -2.353870E-05 -0.000000E+00 -0.000000E+00 -6.056694E-04 -1.834703E-07 -0.000000E+00 -0.000000E+00 -1.203064E-03 -7.240967E-07 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -1.600000E-02 -5.400000E-05 -6.546902E-03 -9.343143E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -9.135698E-04 -4.679598E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.600000E-05 -5.048984E-03 -5.880389E-06 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -5.952777E-04 -3.543556E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.000000E-02 -9.000000E-05 -9.248312E-03 -1.738407E-05 -0.000000E+00 -0.000000E+00 -8.991711E-04 -2.696131E-07 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -8.000000E-03 -1.800000E-05 -3.844641E-03 -4.075868E-06 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -0.000000E+00 -0.000000E+00 -9.238963E-04 -8.535844E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 2: -5.656886E-01 -6.401440E-02 -6.158975E-01 -7.588369E-02 -3.588479E+00 -2.575762E+00 -4.003040E+01 -3.205439E+02 diff --git a/tests/regression_tests/sourcepoint_restart/settings.xml b/tests/regression_tests/sourcepoint_restart/settings.xml deleted file mode 100644 index 1a7a21357..000000000 --- a/tests/regression_tests/sourcepoint_restart/settings.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/sourcepoint_restart/tallies.xml b/tests/regression_tests/sourcepoint_restart/tallies.xml deleted file mode 100644 index 60bf6b268..000000000 --- a/tests/regression_tests/sourcepoint_restart/tallies.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - regular - 5 3 4 - -10. -5. 0. - 10. 4. 9. - - - - mesh - 1 - - - - energy - 0.0 5.0e6 10.0e6 - - - - energyout - 0.0 5.0e6 10.0e6 - - - - cell - 1 - - - - 1 2 3 - scatter nu-fission - - - - 4 - fission absorption total flux - - - diff --git a/tests/regression_tests/sourcepoint_restart/test.py b/tests/regression_tests/sourcepoint_restart/test.py deleted file mode 100644 index 32f53ec23..000000000 --- a/tests/regression_tests/sourcepoint_restart/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_sourcepoint_restart(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/statepoint_batch/__init__.py b/tests/regression_tests/statepoint_batch/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/statepoint_batch/geometry.xml b/tests/regression_tests/statepoint_batch/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/statepoint_batch/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/statepoint_batch/materials.xml b/tests/regression_tests/statepoint_batch/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/statepoint_batch/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/statepoint_batch/results_true.dat b/tests/regression_tests/statepoint_batch/results_true.dat deleted file mode 100644 index ebd9a1a16..000000000 --- a/tests/regression_tests/statepoint_batch/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.003258E-01 3.388075E-03 diff --git a/tests/regression_tests/statepoint_batch/settings.xml b/tests/regression_tests/statepoint_batch/settings.xml deleted file mode 100644 index e2f8dad47..000000000 --- a/tests/regression_tests/statepoint_batch/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/statepoint_batch/test.py b/tests/regression_tests/statepoint_batch/test.py deleted file mode 100644 index 323b28fc6..000000000 --- a/tests/regression_tests/statepoint_batch/test.py +++ /dev/null @@ -1,18 +0,0 @@ -from tests.testing_harness import TestHarness - - -class StatepointTestHarness(TestHarness): - def __init__(self): - super().__init__(None) - - def _test_output_created(self): - """Make sure statepoint files have been created.""" - sps = ('statepoint.03.h5', 'statepoint.06.h5', 'statepoint.09.h5') - for sp in sps: - self._sp_name = sp - TestHarness._test_output_created(self) - - -def test_statepoint_batch(): - harness = StatepointTestHarness() - harness.main() diff --git a/tests/regression_tests/statepoint_restart/__init__.py b/tests/regression_tests/statepoint_restart/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/statepoint_restart/geometry.xml b/tests/regression_tests/statepoint_restart/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/statepoint_restart/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/statepoint_restart/materials.xml b/tests/regression_tests/statepoint_restart/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/statepoint_restart/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/statepoint_restart/results_true.dat b/tests/regression_tests/statepoint_restart/results_true.dat deleted file mode 100644 index c35ff46b8..000000000 --- a/tests/regression_tests/statepoint_restart/results_true.dat +++ /dev/null @@ -1,1452 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 -tally 1: -1.100000E-02 -3.700000E-05 -1.100000E-02 -3.700000E-05 -7.719234E-03 -2.632582E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.816168E-04 -7.772482E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.100000E-02 -1.150000E-04 -2.100000E-02 -1.150000E-04 -1.071093E-02 -2.748612E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.954045E-04 -2.673851E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.130000E-04 -3.100000E-02 -2.130000E-04 -1.363637E-02 -4.345510E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.182717E-03 -5.268980E-07 -2.000000E-03 -2.000000E-06 -3.000000E-03 -5.000000E-06 -2.110880E-03 -1.737594E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -2.938723E-04 -8.636091E-08 -2.300000E-02 -1.330000E-04 -2.300000E-02 -1.330000E-04 -1.162826E-02 -3.490280E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.957100E-04 -4.402864E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -3.400000E-05 -1.000000E-02 -3.400000E-05 -5.414128E-03 -8.079333E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.700000E-02 -7.100000E-05 -1.700000E-02 -7.100000E-05 -8.048522E-03 -1.583843E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.700000E-02 -1.670000E-04 -2.700000E-02 -1.670000E-04 -1.100708E-02 -2.835295E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -1.203064E-03 -7.240967E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -4.400000E-02 -4.320000E-04 -4.400000E-02 -4.320000E-04 -2.116869E-02 -9.629046E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.501009E-03 -6.405021E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -1.472277E-03 -9.506217E-07 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -2.977039E-04 -8.862762E-08 -2.000000E-02 -1.080000E-04 -2.000000E-02 -1.080000E-04 -8.949667E-03 -1.935056E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -2.121142E-03 -1.958355E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -2.938723E-04 -8.636091E-08 -1.000000E-02 -3.400000E-05 -1.000000E-02 -3.400000E-05 -4.754696E-03 -7.172309E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -3.700000E-05 -1.300000E-02 -3.700000E-05 -5.365659E-03 -6.567979E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.056043E-04 -1.834316E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -2.230000E-04 -2.900000E-02 -2.230000E-04 -1.486928E-02 -5.763901E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.990000E-04 -2.900000E-02 -1.990000E-04 -1.189702E-02 -3.303340E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.033082E-04 -2.720592E-07 -3.000000E-03 -3.000000E-06 -4.000000E-03 -6.000000E-06 -1.484187E-03 -9.721092E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.500000E-02 -1.390000E-04 -2.500000E-02 -1.390000E-04 -1.043467E-02 -2.526768E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.912057E-04 -1.747704E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -8.813114E-04 -4.316251E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.900000E-02 -1.030000E-04 -1.900000E-02 -1.030000E-04 -9.748672E-03 -2.956633E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -7.000000E-03 -1.500000E-05 -4.135720E-03 -4.532611E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.874391E-04 -1.725424E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.560000E-04 -2.600000E-02 -1.560000E-04 -1.249410E-02 -3.501589E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.159309E-04 -3.793709E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.950000E-04 -2.900000E-02 -1.950000E-04 -1.461148E-02 -4.367385E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.912057E-04 -1.747704E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.700000E-05 -1.900000E-02 -9.700000E-05 -1.099391E-02 -2.847330E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.655539E-03 -2.523801E-06 -3.000000E-03 -5.000000E-06 -3.000000E-03 -5.000000E-06 -2.976389E-04 -8.858890E-08 -6.000000E-03 -8.000000E-06 -6.000000E-03 -8.000000E-06 -2.683856E-03 -1.512640E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -2.976389E-04 -8.858890E-08 -1.200000E-02 -4.600000E-05 -1.200000E-02 -4.600000E-05 -5.941985E-03 -9.853870E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.186548E-03 -5.291647E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.230000E-04 -2.300000E-02 -1.230000E-04 -1.015650E-02 -2.236950E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.912707E-04 -1.748091E-07 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.250000E-04 -3.100000E-02 -2.250000E-04 -1.729188E-02 -6.078653E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.792523E-03 -8.900697E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.700000E-02 -7.100000E-05 -1.700000E-02 -7.100000E-05 -7.760000E-03 -1.634547E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -8.807004E-04 -7.756332E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.900000E-02 -2.030000E-04 -2.900000E-02 -2.030000E-04 -1.108618E-02 -3.019577E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.174573E-03 -8.619941E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -5.500000E-05 -1.500000E-02 -5.500000E-05 -5.944486E-03 -1.042417E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.190621E-03 -8.859277E-07 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.460000E-04 -2.600000E-02 -1.460000E-04 -9.232713E-03 -1.900222E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.186919E-03 -5.294603E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.600000E-02 -2.740000E-04 -3.600000E-02 -2.740000E-04 -1.462273E-02 -4.551798E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.056694E-04 -1.834703E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.807004E-04 -7.756332E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.200000E-02 -3.000000E-05 -1.200000E-02 -3.000000E-05 -7.754474E-03 -1.333333E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.938723E-04 -8.636091E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.484382E-03 -1.504223E-06 -3.000000E-03 -5.000000E-06 -3.000000E-03 -5.000000E-06 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.900000E-05 -1.900000E-02 -9.900000E-05 -1.066281E-02 -2.937590E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -3.000000E-06 -3.000000E-03 -3.000000E-06 -1.484493E-03 -9.722886E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.650000E-04 -2.300000E-02 -1.650000E-04 -1.065253E-02 -3.447907E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.030000E-04 -3.100000E-02 -2.030000E-04 -1.342551E-02 -3.842917E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.915762E-04 -1.749885E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -8.700000E-05 -1.900000E-02 -8.700000E-05 -8.693502E-03 -1.682273E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.000000E-03 -1.600000E-05 -8.000000E-03 -1.600000E-05 -3.866943E-03 -3.257876E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.175489E-03 -1.381775E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -8.000000E-03 -2.000000E-05 -8.000000E-03 -2.000000E-05 -3.248622E-03 -4.063213E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.938723E-04 -8.636091E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.780000E-04 -2.800000E-02 -1.780000E-04 -1.283876E-02 -3.527487E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-02 -3.880000E-04 -4.000000E-02 -3.880000E-04 -1.659048E-02 -7.200873E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -8.891500E-04 -4.407165E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.200000E-02 -3.400000E-05 -1.200000E-02 -3.400000E-05 -5.074320E-03 -5.793165E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -8.000000E-06 -4.000000E-03 -8.000000E-06 -3.570375E-03 -5.251426E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.000000E-03 -4.000000E-06 -4.000000E-03 -4.000000E-06 -1.494579E-03 -6.241235E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.976389E-04 -8.858890E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -1.950000E-04 -3.100000E-02 -1.950000E-04 -1.250316E-02 -3.147175E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.953428E-04 -1.772165E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.800000E-04 -2.600000E-02 -1.800000E-04 -1.162837E-02 -3.241150E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.874391E-04 -1.725424E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -9.900000E-05 -1.900000E-02 -9.900000E-05 -9.216754E-03 -2.272207E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.159309E-04 -3.793709E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.000000E-05 -6.000000E-03 -1.000000E-05 -2.404012E-03 -1.641294E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.300000E-05 -1.500000E-02 -6.300000E-05 -6.572185E-03 -9.479065E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -1.030000E-04 -1.900000E-02 -1.030000E-04 -7.760558E-03 -1.654841E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.800000E-02 -1.220000E-04 -1.800000E-02 -1.220000E-04 -7.815192E-03 -2.039362E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.935668E-04 -8.618147E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -1.511030E-03 -1.198310E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.900000E-02 -1.030000E-04 -1.900000E-02 -1.030000E-04 -7.130794E-03 -1.485134E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.816168E-04 -7.772482E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.970000E-04 -2.900000E-02 -1.970000E-04 -1.046961E-02 -2.353870E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.056694E-04 -1.834703E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.203064E-03 -7.240967E-07 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -0.000000E+00 -0.000000E+00 -1.600000E-02 -5.400000E-05 -1.600000E-02 -5.400000E-05 -6.546902E-03 -9.343143E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -9.135698E-04 -4.679598E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.600000E-05 -1.000000E-02 -2.600000E-05 -5.048984E-03 -5.880389E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.079654E-04 -9.484271E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.952777E-04 -3.543556E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.000000E-02 -9.000000E-05 -2.000000E-02 -9.000000E-05 -9.248312E-03 -1.738407E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.991711E-04 -2.696131E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.954078E-04 -3.545105E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -8.000000E-03 -1.800000E-05 -8.000000E-03 -1.800000E-05 -3.844641E-03 -4.075868E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.977039E-04 -8.862762E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.238963E-04 -8.535844E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -5.871336E-04 -3.447259E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -tally 2: -5.656886E-01 -6.401440E-02 -6.158975E-01 -7.588369E-02 -3.588479E+00 -2.575762E+00 -4.003040E+01 -3.205439E+02 diff --git a/tests/regression_tests/statepoint_restart/settings.xml b/tests/regression_tests/statepoint_restart/settings.xml deleted file mode 100644 index 88382f74b..000000000 --- a/tests/regression_tests/statepoint_restart/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/statepoint_restart/tallies.xml b/tests/regression_tests/statepoint_restart/tallies.xml deleted file mode 100644 index c7dff36f0..000000000 --- a/tests/regression_tests/statepoint_restart/tallies.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - regular - 5 3 4 - -10. -5. 0. - 10. 4. 9. - - - - mesh - 1 - - - - energy - 0.0 5.0e6 10.0e6 - - - - energyout - 0.0 5.0e6 10.0e6 - - - - cell - 1 - - - - 1 2 3 - scatter nu-scatter nu-fission - - - - 4 - fission absorption total flux - - - diff --git a/tests/regression_tests/statepoint_restart/test.py b/tests/regression_tests/statepoint_restart/test.py deleted file mode 100644 index 4575607f7..000000000 --- a/tests/regression_tests/statepoint_restart/test.py +++ /dev/null @@ -1,61 +0,0 @@ -import glob -import os - -import openmc - -from tests.testing_harness import TestHarness -from tests.regression_tests import config - - -class StatepointRestartTestHarness(TestHarness): - def __init__(self, final_sp, restart_sp): - super().__init__(final_sp) - self._restart_sp = restart_sp - - def execute_test(self): - """Run OpenMC with the appropriate arguments and check the outputs.""" - try: - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._compare_results() - - self._run_openmc_restart() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Update the results_true using the current version of OpenMC.""" - try: - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - def _run_openmc_restart(self): - # Get the name of the statepoint file. - statepoint = glob.glob(os.path.join(os.getcwd(), self._restart_sp)) - assert len(statepoint) == 1 - statepoint = statepoint[0] - - # Run OpenMC - if config['mpi']: - mpi_args = [config['mpiexec'], '-n', config['mpi_np']] - openmc.run(restart_file=statepoint, openmc_exec=config['exe'], - mpi_args=mpi_args) - else: - openmc.run(openmc_exec=config['exe'], restart_file=statepoint) - - -def test_statepoint_restart(): - harness = StatepointRestartTestHarness('statepoint.10.h5', - 'statepoint.07.h5') - harness.main() diff --git a/tests/regression_tests/statepoint_sourcesep/__init__.py b/tests/regression_tests/statepoint_sourcesep/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/statepoint_sourcesep/geometry.xml b/tests/regression_tests/statepoint_sourcesep/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/statepoint_sourcesep/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/statepoint_sourcesep/materials.xml b/tests/regression_tests/statepoint_sourcesep/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/statepoint_sourcesep/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/statepoint_sourcesep/results_true.dat b/tests/regression_tests/statepoint_sourcesep/results_true.dat deleted file mode 100644 index 5cb3925a6..000000000 --- a/tests/regression_tests/statepoint_sourcesep/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 diff --git a/tests/regression_tests/statepoint_sourcesep/settings.xml b/tests/regression_tests/statepoint_sourcesep/settings.xml deleted file mode 100644 index 86489bf33..000000000 --- a/tests/regression_tests/statepoint_sourcesep/settings.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/statepoint_sourcesep/test.py b/tests/regression_tests/statepoint_sourcesep/test.py deleted file mode 100644 index 3d63ca8ee..000000000 --- a/tests/regression_tests/statepoint_sourcesep/test.py +++ /dev/null @@ -1,25 +0,0 @@ -import glob -import os - -from tests.testing_harness import TestHarness - - -class SourcepointTestHarness(TestHarness): - def _test_output_created(self): - """Make sure statepoint.* and source* have been created.""" - TestHarness._test_output_created(self) - source = glob.glob('source.*.h5') - assert len(source) == 1, 'Either multiple or no source files ' \ - 'exist.' - - def _cleanup(self): - TestHarness._cleanup(self) - output = glob.glob('source.*.h5') - for f in output: - if os.path.exists(f): - os.remove(f) - - -def test_statepoint_sourcesep(): - harness = SourcepointTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/surface_tally/__init__.py b/tests/regression_tests/surface_tally/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/surface_tally/inputs_true.dat b/tests/regression_tests/surface_tally/inputs_true.dat deleted file mode 100644 index 96639a076..000000000 --- a/tests/regression_tests/surface_tally/inputs_true.dat +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 0 - - - -0.62992 -0.62992 -1 0.62992 0.62992 1 - - - - - - - 13 - - - 14 - - - 0.0 4000000.0 20000000.0 - - - 0.0 0.7853981633974483 3.141592653589793 - - - 0.0 0.7853981633974483 3.141592653589793 - - - 1 - - - 14 - - - 13 - - - 2 - - - 3 - - - 5 6 1 2 3 - current - - - 5 4 1 2 3 - current - - - 7 8 1 2 3 - current - - - 7 4 1 2 3 - current - - - 4 1 2 3 - current - - - 10 1 2 3 - current - - - 11 1 - current - - - 11 1 - current - - diff --git a/tests/regression_tests/surface_tally/results_true.dat b/tests/regression_tests/surface_tally/results_true.dat deleted file mode 100644 index 186ca9fb3..000000000 --- a/tests/regression_tests/surface_tally/results_true.dat +++ /dev/null @@ -1,53 +0,0 @@ -mean,std. dev. -2.1400000e-02,1.1850926e-03 -7.4700000e-02,2.5649345e-03 -1.6090000e-01,4.4433471e-03 -6.4810000e-01,8.6041979e-03 -2.0000000e-03,3.9440532e-04 -4.2000000e-03,8.2731158e-04 -1.1200000e-02,1.0934146e-03 -4.6400000e-02,2.2715633e-03 -2.1400000e-02,1.1850926e-03 -7.4700000e-02,2.5649345e-03 -1.6090000e-01,4.4433471e-03 -6.4810000e-01,8.6041979e-03 -2.0000000e-03,3.9440532e-04 -4.2000000e-03,8.2731158e-04 -1.1200000e-02,1.0934146e-03 -4.6400000e-02,2.2715633e-03 -5.5000000e-03,5.6273143e-04 -4.4300000e-02,1.8502252e-03 -4.5600000e-02,1.2220202e-03 -4.1780000e-01,6.4460151e-03 -0.0000000e+00,0.0000000e+00 -1.4000000e-03,3.3993463e-04 -0.0000000e+00,0.0000000e+00 -1.6600000e-02,1.0561986e-03 --5.5000000e-03,5.6273143e-04 --4.4300000e-02,1.8502252e-03 --4.5600000e-02,1.2220202e-03 --4.1780000e-01,6.4460151e-03 -0.0000000e+00,0.0000000e+00 --1.4000000e-03,3.3993463e-04 -0.0000000e+00,0.0000000e+00 --1.6600000e-02,1.0561986e-03 -1.5900000e-02,1.1200198e-03 -3.0400000e-02,3.2734623e-03 -1.1530000e-01,3.8327536e-03 -2.3030000e-01,7.2250336e-03 -2.0000000e-03,3.9440532e-04 -2.8000000e-03,7.8598841e-04 -1.1200000e-02,1.0934146e-03 -2.9800000e-02,2.5811281e-03 -0.0000000e+00,0.0000000e+00 --3.0000000e-02,1.3743685e-03 -0.0000000e+00,0.0000000e+00 --3.4810000e-01,5.9711343e-03 -0.0000000e+00,0.0000000e+00 --3.1000000e-03,6.9041051e-04 -0.0000000e+00,0.0000000e+00 --2.1900000e-02,2.4241837e-03 -0.0000000e+00,0.0000000e+00 -0.0000000e+00,0.0000000e+00 -0.0000000e+00,0.0000000e+00 -0.0000000e+00,0.0000000e+00 diff --git a/tests/regression_tests/surface_tally/test.py b/tests/regression_tests/surface_tally/test.py deleted file mode 100644 index 96199ec2a..000000000 --- a/tests/regression_tests/surface_tally/test.py +++ /dev/null @@ -1,179 +0,0 @@ -import numpy as np -import openmc -import pandas as pd - -from tests.testing_harness import PyAPITestHarness - - -class SurfaceTallyTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Instantiate some Materials and register the appropriate Nuclides - uo2 = openmc.Material(name='UO2 fuel at 2.4% wt enrichment') - uo2.set_density('g/cc', 10.0) - uo2.add_nuclide('U238', 1.0) - uo2.add_nuclide('U235', 0.02) - uo2.add_nuclide('O16', 2.0) - - borated_water = openmc.Material(name='Borated water') - borated_water.set_density('g/cm3', 1) - borated_water.add_nuclide('B10', 10e-5) - borated_water.add_nuclide('H1', 2.0) - borated_water.add_nuclide('O16', 1.0) - - # Instantiate a Materials collection and export to XML - materials_file = openmc.Materials([uo2, borated_water]) - materials_file.export_to_xml() - - # Instantiate ZCylinder surfaces - fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=1, - name='Fuel OR') - left = openmc.XPlane(surface_id=2, x0=-2, name='left') - right = openmc.XPlane(surface_id=3, x0=2, name='right') - bottom = openmc.YPlane(y0=-2, name='bottom') - top = openmc.YPlane(y0=2, name='top') - - left.boundary_type = 'vacuum' - right.boundary_type = 'reflective' - top.boundary_type = 'reflective' - bottom.boundary_type = 'reflective' - - # Instantiate Cells - fuel = openmc.Cell(name='fuel') - water = openmc.Cell(name='water') - - # Use surface half-spaces to define regions - fuel.region = -fuel_or - water.region = +fuel_or & -right & +bottom & -top - - # Register Materials with Cells - fuel.fill = uo2 - water.fill = borated_water - - # Instantiate pin cell Universe - pin_cell = openmc.Universe(name='pin cell') - pin_cell.add_cells([fuel, water]) - - # Instantiate root Cell and Universe - root_cell = openmc.Cell(name='root cell') - root_cell.region = +left & -right & +bottom & -top - root_cell.fill = pin_cell - root_univ = openmc.Universe(universe_id=0, name='root universe') - root_univ.add_cell(root_cell) - - # Instantiate a Geometry, register the root Universe - geometry = openmc.Geometry(root_univ) - geometry.export_to_xml() - - # Instantiate a Settings object, set all runtime parameters - settings_file = openmc.Settings() - settings_file.batches = 10 - settings_file.inactive = 0 - settings_file.particles = 1000 - #settings_file.output = {'tallies': True} - - # Create an initial uniform spatial source distribution - bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1] - uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:],\ - only_fissionable=True) - settings_file.source = openmc.source.Source(space=uniform_dist) - settings_file.export_to_xml() - - # Tallies file - tallies_file = openmc.Tallies() - - # Create partial current tallies from fuel to water - # Filters - two_groups = [0., 4e6, 20e6] - energy_filter = openmc.EnergyFilter(two_groups) - polar_filter = openmc.PolarFilter([0, np.pi / 4, np.pi]) - azimuthal_filter = openmc.AzimuthalFilter([0, np.pi / 4, np.pi]) - surface_filter = openmc.SurfaceFilter([1]) - cell_from_filter = openmc.CellFromFilter(fuel) - cell_filter = openmc.CellFilter(water) - - # Use Cell to cell filters for partial current - cell_to_cell_tally = openmc.Tally(name=str('fuel_to_water_1')) - cell_to_cell_tally.filters = [cell_from_filter, cell_filter, \ - energy_filter, polar_filter, azimuthal_filter] - cell_to_cell_tally.scores = ['current'] - tallies_file.append(cell_to_cell_tally) - - # Use a Cell from + surface filters for partial current - cell_to_cell_tally = openmc.Tally(name=str('fuel_to_water_2')) - cell_to_cell_tally.filters = [cell_from_filter, surface_filter, \ - energy_filter, polar_filter, azimuthal_filter] - cell_to_cell_tally.scores = ['current'] - tallies_file.append(cell_to_cell_tally) - - # Create partial current tallies from water to fuel - # Filters - cell_from_filter = openmc.CellFromFilter(water) - cell_filter = openmc.CellFilter(fuel) - - # Cell to cell filters for partial current - cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_1')) - cell_to_cell_tally.filters = [cell_from_filter, cell_filter, \ - energy_filter, polar_filter, azimuthal_filter] - cell_to_cell_tally.scores = ['current'] - tallies_file.append(cell_to_cell_tally) - - # Cell from + surface filters for partial current - cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_2')) - cell_to_cell_tally.filters = [cell_from_filter, surface_filter, \ - energy_filter, polar_filter, azimuthal_filter] - cell_to_cell_tally.scores = ['current'] - tallies_file.append(cell_to_cell_tally) - - # Create a net current tally on inner surface using a surface filter - surface_filter = openmc.SurfaceFilter([1]) - surf_tally1 = openmc.Tally(name='net_cylinder') - surf_tally1.filters = [surface_filter, energy_filter, polar_filter, \ - azimuthal_filter] - surf_tally1.scores = ['current'] - tallies_file.append(surf_tally1) - - # Create a net current tally on left surface using a surface filter - # This surface has a vacuum boundary condition, so leakage is tallied - surface_filter = openmc.SurfaceFilter([2]) - surf_tally2 = openmc.Tally(name='leakage_left') - surf_tally2.filters = [surface_filter, energy_filter, polar_filter, \ - azimuthal_filter] - surf_tally2.scores = ['current'] - tallies_file.append(surf_tally2) - - # Create a net current tally on right surface using a surface filter - # This surface has a reflective boundary condition, so the net current - # should be zero. - surface_filter = openmc.SurfaceFilter([3]) - surf_tally3 = openmc.Tally(name='net_right') - surf_tally3.filters = [surface_filter, energy_filter] - surf_tally3.scores = ['current'] - tallies_file.append(surf_tally3) - - surface_filter = openmc.SurfaceFilter([3]) - surf_tally3 = openmc.Tally(name='net_right') - surf_tally3.filters = [surface_filter, energy_filter] - surf_tally3.scores = ['current'] - tallies_file.append(surf_tally3) - - tallies_file.export_to_xml() - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Extract the tally data as a Pandas DataFrame. - df = pd.DataFrame() - for t in sp.tallies.values(): - df = df.append(t.get_pandas_dataframe(), ignore_index=True) - - # Extract the relevant data as a CSV string. - cols = ('mean', 'std. dev.') - return df.to_csv(None, columns=cols, index=False, float_format='%.7e') - return outstr - - -def test_surface_tally(): - harness = SurfaceTallyTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/survival_biasing/__init__.py b/tests/regression_tests/survival_biasing/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/survival_biasing/geometry.xml b/tests/regression_tests/survival_biasing/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/survival_biasing/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/survival_biasing/materials.xml b/tests/regression_tests/survival_biasing/materials.xml deleted file mode 100644 index f271ddee2..000000000 --- a/tests/regression_tests/survival_biasing/materials.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/survival_biasing/results_true.dat b/tests/regression_tests/survival_biasing/results_true.dat deleted file mode 100644 index c2dea8018..000000000 --- a/tests/regression_tests/survival_biasing/results_true.dat +++ /dev/null @@ -1,20 +0,0 @@ -k-combined: -9.686216E-01 1.511499E-02 -tally 1: -4.243782E+01 -3.604528E+02 -1.770205E+01 -6.273029E+01 -2.176094E+00 -9.477949E-01 -1.881775E+00 -7.087350E-01 -4.868971E+00 -4.744828E+00 -3.400887E-02 -2.314715E-04 -3.644408E+08 -2.658287E+16 -tally 2: -1.770205E+01 -6.273029E+01 diff --git a/tests/regression_tests/survival_biasing/settings.xml b/tests/regression_tests/survival_biasing/settings.xml deleted file mode 100644 index 6d5b66789..000000000 --- a/tests/regression_tests/survival_biasing/settings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - true - - - 0.50 - 1.2 - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/survival_biasing/tallies.xml b/tests/regression_tests/survival_biasing/tallies.xml deleted file mode 100644 index 8d939dfff..000000000 --- a/tests/regression_tests/survival_biasing/tallies.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - flux total absorption fission nu-fission delayed-nu-fission kappa-fission - - analog - - - - total - collision - - - diff --git a/tests/regression_tests/survival_biasing/test.py b/tests/regression_tests/survival_biasing/test.py deleted file mode 100644 index 39e6faed8..000000000 --- a/tests/regression_tests/survival_biasing/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_survival_biasing(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/tallies/__init__.py b/tests/regression_tests/tallies/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat deleted file mode 100644 index 9409ca4a7..000000000 --- a/tests/regression_tests/tallies/inputs_true.dat +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 400 - 5 - 0 - - - -160 -160 -183 160 160 183 - - - - - - - 2 2 - -182.07 -182.07 - 182.07 182.07 - - - -3.14159 -1.885 -0.6283 0.6283 1.885 3.14159 - - - 1 - - - 10 21 22 23 - - - 1 2 3 4 5 6 - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 1 2 3 4 - - - -1.0 -0.5 0.0 0.5 1.0 - - - 0.0 0.6283 1.2566 1.885 2.5132 3.14159 - - - 4 - - - 4 - - - 1 2 3 4 6 8 - - - 10 21 22 23 60 - - - 21 22 23 27 28 29 60 - - - 1 - flux - tracklength - - - 1 - flux - analog - - - 1 2 - flux - tracklength - - - 3 - total - - - 4 - U235 O16 total - delayed-nu-fission decay-rate - - - 5 - total - - - 6 - scatter - - - 5 6 - scatter nu-fission - - - 7 - total - - - 8 - scatter nu-scatter - - - 8 2 - scatter nu-scatter - - - 9 - flux - tracklength - - - 9 - flux - analog - - - 9 2 - flux - tracklength - - - 10 - scatter nu-scatter - - - 11 - scatter nu-scatter flux total - - - 11 - flux total - - - 11 - flux total - - - 12 - total - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - tracklength - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - tracklength - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - analog - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - analog - - - 13 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - collision - - - 13 - U235 O16 total - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate - collision - - - 14 - flux - tracklength - - - 14 - flux - analog - - - 14 - flux - collision - - - 13 - all - total - tracklength - - - 13 - all - total - collision - - - 2 - all - total - tracklength - - - 2 - U235 - total - tracklength - - - H1-production H2-production H3-production He3-production He4-production heating damage-energy - - diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat deleted file mode 100644 index de1a18eff..000000000 --- a/tests/regression_tests/tallies/results_true.dat +++ /dev/null @@ -1 +0,0 @@ -c37e0468f1684f7810429332721762884f3cdf0429d38caa99500bbde04ad84cf1e1639adc46b6db44b28b6f31028ed029f85920c8164d77463b6d89336043a8 \ No newline at end of file diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py deleted file mode 100644 index d4857b3ec..000000000 --- a/tests/regression_tests/tallies/test.py +++ /dev/null @@ -1,183 +0,0 @@ -from openmc.filter import * -from openmc.filter_expansion import * -from openmc import RegularMesh, Tally - -from tests.testing_harness import HashedPyAPITestHarness - - -def test_tallies(): - harness = HashedPyAPITestHarness('statepoint.5.h5') - model = harness._model - - # Set settings explicitly - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 400 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-160, -160, -183], [160, 160, 183])) - - azimuthal_bins = (-3.14159, -1.8850, -0.6283, 0.6283, 1.8850, 3.14159) - azimuthal_filter = AzimuthalFilter(azimuthal_bins) - azimuthal_tally1 = Tally() - azimuthal_tally1.filters = [azimuthal_filter] - azimuthal_tally1.scores = ['flux'] - azimuthal_tally1.estimator = 'tracklength' - - azimuthal_tally2 = Tally() - azimuthal_tally2.filters = [azimuthal_filter] - azimuthal_tally2.scores = ['flux'] - azimuthal_tally2.estimator = 'analog' - - mesh_2x2 = RegularMesh(mesh_id=1) - mesh_2x2.lower_left = [-182.07, -182.07] - mesh_2x2.upper_right = [182.07, 182.07] - mesh_2x2.dimension = [2, 2] - mesh_filter = MeshFilter(mesh_2x2) - azimuthal_tally3 = Tally() - azimuthal_tally3.filters = [azimuthal_filter, mesh_filter] - azimuthal_tally3.scores = ['flux'] - azimuthal_tally3.estimator = 'tracklength' - - cellborn_tally = Tally() - cellborn_tally.filters = [ - CellbornFilter((model.geometry.get_all_cells()[10], - model.geometry.get_all_cells()[21], - 22, 23))] # Test both Cell objects and ids - cellborn_tally.scores = ['total'] - - dg_tally = Tally() - dg_tally.filters = [DelayedGroupFilter((1, 2, 3, 4, 5, 6))] - dg_tally.scores = ['delayed-nu-fission', 'decay-rate'] - dg_tally.nuclides = ['U235', 'O16', 'total'] - - four_groups = (0.0, 0.253, 1.0e3, 1.0e6, 20.0e6) - energy_filter = EnergyFilter(four_groups) - energy_tally = Tally() - energy_tally.filters = [energy_filter] - energy_tally.scores = ['total'] - - energyout_filter = EnergyoutFilter(four_groups) - energyout_tally = Tally() - energyout_tally.filters = [energyout_filter] - energyout_tally.scores = ['scatter'] - - transfer_tally = Tally() - transfer_tally.filters = [energy_filter, energyout_filter] - transfer_tally.scores = ['scatter', 'nu-fission'] - - material_tally = Tally() - material_tally.filters = [ - MaterialFilter((model.geometry.get_materials_by_name('UOX fuel')[0], - model.geometry.get_materials_by_name('Zircaloy')[0], - 3, 4))] # Test both Material objects and ids - material_tally.scores = ['total'] - - mu_bins = (-1.0, -0.5, 0.0, 0.5, 1.0) - mu_filter = MuFilter(mu_bins) - mu_tally1 = Tally() - mu_tally1.filters = [mu_filter] - mu_tally1.scores = ['scatter', 'nu-scatter'] - - mu_tally2 = Tally() - mu_tally2.filters = [mu_filter, mesh_filter] - mu_tally2.scores = ['scatter', 'nu-scatter'] - - polar_bins = (0.0, 0.6283, 1.2566, 1.8850, 2.5132, 3.14159) - polar_filter = PolarFilter(polar_bins) - polar_tally1 = Tally() - polar_tally1.filters = [polar_filter] - polar_tally1.scores = ['flux'] - polar_tally1.estimator = 'tracklength' - - polar_tally2 = Tally() - polar_tally2.filters = [polar_filter] - polar_tally2.scores = ['flux'] - polar_tally2.estimator = 'analog' - - polar_tally3 = Tally() - polar_tally3.filters = [polar_filter, mesh_filter] - polar_tally3.scores = ['flux'] - polar_tally3.estimator = 'tracklength' - - legendre_filter = LegendreFilter(order=4) - legendre_tally = Tally() - legendre_tally.filters = [legendre_filter] - legendre_tally.scores = ['scatter', 'nu-scatter'] - legendre_tally.estimatir = 'analog' - - harmonics_filter = SphericalHarmonicsFilter(order=4) - harmonics_tally = Tally() - harmonics_tally.filters = [harmonics_filter] - harmonics_tally.scores = ['scatter', 'nu-scatter', 'flux', 'total'] - harmonics_tally.estimatir = 'analog' - - harmonics_tally2 = Tally() - harmonics_tally2.filters = [harmonics_filter] - harmonics_tally2.scores = ['flux', 'total'] - harmonics_tally2.estimatir = 'collision' - - harmonics_tally3 = Tally() - harmonics_tally3.filters = [harmonics_filter] - harmonics_tally3.scores = ['flux', 'total'] - harmonics_tally3.estimatir = 'tracklength' - - universe_tally = Tally() - universe_tally.filters = [ - UniverseFilter((model.geometry.get_all_universes()[1], - model.geometry.get_all_universes()[2], - 3, 4, 6, 8))] # Test both Universe objects and ids - universe_tally.scores = ['total'] - - cell_filter = CellFilter((model.geometry.get_all_cells()[10], - model.geometry.get_all_cells()[21], - 22, 23, 60)) # Test both Cell objects and ids - score_tallies = [Tally() for i in range(6)] - for t in score_tallies: - t.filters = [cell_filter] - t.scores = ['absorption', 'delayed-nu-fission', 'events', 'fission', - 'inverse-velocity', 'kappa-fission', '(n,2n)', '(n,n1)', - '(n,gamma)', 'nu-fission', 'scatter', 'elastic', - 'total', 'prompt-nu-fission', 'fission-q-prompt', - 'fission-q-recoverable', 'decay-rate'] - for t in score_tallies[0:2]: t.estimator = 'tracklength' - for t in score_tallies[2:4]: t.estimator = 'analog' - for t in score_tallies[4:6]: t.estimator = 'collision' - for t in score_tallies[1::2]: - t.nuclides = ['U235', 'O16', 'total'] - - cell_filter2 = CellFilter((21, 22, 23, 27, 28, 29, 60)) - flux_tallies = [Tally() for i in range(3)] - for t in flux_tallies: - t.filters = [cell_filter2] - t.scores = ['flux'] - flux_tallies[0].estimator = 'tracklength' - flux_tallies[1].estimator = 'analog' - flux_tallies[2].estimator = 'collision' - - all_nuclide_tallies = [Tally() for i in range(4)] - for t in all_nuclide_tallies: - t.filters = [cell_filter] - t.estimator = 'tracklength' - t.nuclides = ['all'] - t.scores = ['total'] - all_nuclide_tallies[1].estimator = 'collision' - all_nuclide_tallies[2].filters = [mesh_filter] - all_nuclide_tallies[3].filters = [mesh_filter] - all_nuclide_tallies[3].nuclides = ['U235'] - - fusion_tally = Tally() - fusion_tally.scores = ['H1-production', 'H2-production', 'H3-production', - 'He3-production', 'He4-production', 'heating', 'damage-energy'] - - model.tallies += [ - azimuthal_tally1, azimuthal_tally2, azimuthal_tally3, - cellborn_tally, dg_tally, energy_tally, energyout_tally, - transfer_tally, material_tally, mu_tally1, mu_tally2, - polar_tally1, polar_tally2, polar_tally3, legendre_tally, - harmonics_tally, harmonics_tally2, harmonics_tally3, universe_tally] - model.tallies += score_tallies - model.tallies += flux_tallies - model.tallies += all_nuclide_tallies - model.tallies.append(fusion_tally) - - harness.main() diff --git a/tests/regression_tests/tally_aggregation/__init__.py b/tests/regression_tests/tally_aggregation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tally_aggregation/inputs_true.dat b/tests/regression_tests/tally_aggregation/inputs_true.dat deleted file mode 100644 index 80356f711..000000000 --- a/tests/regression_tests/tally_aggregation/inputs_true.dat +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - 1.2 1.2 - 1 - 2 2 - -1.2 -1.2 - -1 1 -1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 10 - 5 - - - - - 0.0 0.253 1000.0 1000000.0 20000000.0 - - - 1 - - - 1 2 - U234 U235 U238 - nu-fission total - - diff --git a/tests/regression_tests/tally_aggregation/results_true.dat b/tests/regression_tests/tally_aggregation/results_true.dat deleted file mode 100644 index e48f93370..000000000 --- a/tests/regression_tests/tally_aggregation/results_true.dat +++ /dev/null @@ -1,97 +0,0 @@ -[[1.63731762e-05 5.08325999e-04] - [3.27547470e-01 1.77506218e-01] - [1.89164083e-02 7.22719366e-01]], [[1.64200315e-05 5.45231503e-04] - [3.24031537e-01 1.75537230e-01] - [1.87708717e-02 7.26768216e-01]], [[1.67487818e-05 5.03394672e-04] - [3.07780931e-01 1.67166322e-01] - [1.97449893e-02 7.06598738e-01]], [[1.63603106e-05 6.10423337e-04] - [3.32313666e-01 1.79982864e-01] - [1.90686364e-02 7.22662206e-01]][[4.65536263e-07 4.34762669e-05] - [9.14451087e-03 4.56766386e-03] - [7.87091351e-04 1.04610084e-02]], [[1.70217471e-07 3.74604055e-05] - [9.18903111e-03 4.56228307e-03] - [1.74179620e-04 9.17281345e-03]], [[2.49291594e-07 1.81470751e-05] - [8.34746285e-03 4.15219947e-03] - [3.57935129e-04 1.00438242e-02]], [[4.12850822e-07 3.98122204e-05] - [1.38191650e-02 6.82224745e-03] - [6.79096490e-04 9.85922061e-03]][[1.03849782e-06 8.14983256e-04] - [1.13114721e+00 5.60394847e-01] - [1.40550899e-06 5.11848857e-01]], [[1.99773314e-06 1.03955500e-03] - [1.42269343e-01 9.92372469e-02] - [3.30482612e-05 8.08235307e-01]], [[1.45630159e-05 2.22446467e-04] - [1.30357824e-02 2.93669452e-02] - [3.05346682e-04 1.10154874e+00]], [[4.83030533e-05 9.03907895e-05] - [5.22127114e-03 1.11935954e-02] - [7.61611053e-02 4.57115627e-01]][[1.87165262e-08 1.43906416e-05] - [2.05916324e-02 1.01675733e-02] - [2.50902573e-08 8.54377830e-03]], [[1.12098060e-07 7.06870145e-05] - [2.16279434e-03 1.42142705e-03] - [1.22851164e-05 1.41445724e-02]], [[2.08629342e-07 1.63602148e-06] - [1.08988258e-04 2.01647731e-04] - [7.14052741e-06 9.13467415e-03]], [[6.49497971e-07 1.17295883e-06] - [7.03193479e-05 1.45388818e-04] - [1.11307638e-03 5.92861613e-03]][[0.28708077 0.27231775]], [[0.283269 0.26846215]], [[0.26933717 0.25561967]], [[0.29146272 0.27665912]], [[0.03591854 0.2267151 ]], [[0.03618374 0.23663228]], [[0.03393119 0.22268261]], [[0.03627092 0.22248212]], [[0.00333501 0.28502144]], [[0.00339378 0.2823686 ]], [[0.0032646 0.27622413]], [[0.0033623 0.28752397]], [[0.02014593 0.11667962]], [[0.01997231 0.11538764]], [[0.02100971 0.11974205]], [[0.02030272 0.11659029]][[0.00908247 0.00614665]], [[0.00911888 0.00556208]], [[0.00831969 0.00596124]], [[0.01375328 0.00849244]], [[0.00106067 0.00719168]], [[0.00113262 0.00790992]], [[0.00067545 0.00732313]], [[0.00134675 0.00584628]], [[5.86657354e-05 4.85962742e-03]], [[3.78231391e-05 3.26052035e-03]], [[7.89746053e-05 5.03120906e-03]], [[2.86395600e-05 4.89110417e-03]], [[0.00078861 0.00414495]], [[0.00017413 0.00090648]], [[0.00035855 0.00190835]], [[0.00068051 0.0036777 ]][[2.07154706e-04] - [4.29264961e-01] - [1.29926403e-01]], [[2.04124023e-04] - [4.23635331e-01] - [1.27891698e-01]], [[1.94482255e-04] - [4.02735295e-01] - [1.22027057e-01]], [[2.10260769e-04] - [4.35906468e-01] - [1.32005105e-01]], [[0.00022426] - [0.06105851] - [0.20135086]], [[0.00026389] - [0.0612101 ] - [0.21134203]], [[0.00023084] - [0.05761498] - [0.19876799]], [[0.00032256] - [0.061623 ] - [0.19680747]], [[5.87610156e-05] - [1.06427230e-02] - [2.77654967e-01]], [[5.94899925e-05] - [1.06822132e-02] - [2.75020675e-01]], [[5.93176564e-05] - [1.03968293e-02] - [2.69032575e-01]], [[5.94408186e-05] - [1.06809621e-02] - [2.80145865e-01]], [[3.45195544e-05] - [4.08749343e-03] - [1.32703540e-01]], [[3.41476180e-05] - [4.04112643e-03] - [1.31284684e-01]], [[3.55075881e-05] - [4.20014745e-03] - [1.36516110e-01]], [[3.45190823e-05] - [4.08609920e-03] - [1.32772398e-01]][[6.53616088e-06] - [1.01396032e-02] - [4.17862796e-03]], [[6.14101518e-06] - [1.01647874e-02] - [3.28144648e-03]], [[6.21879601e-06] - [9.29002877e-03] - [4.29521996e-03]], [[9.37998012e-06] - [1.53282674e-02] - [5.13014723e-03]], [[4.29725320e-05] - [1.28419933e-03] - [7.15501363e-03]], [[3.69392134e-05] - [1.38678579e-03] - [7.86925329e-03]], [[1.70223774e-05] - [7.65771551e-04] - [7.31421975e-03]], [[3.86750728e-05] - [1.59354492e-03] - [5.78376198e-03]], [[4.00936601e-07] - [1.10265266e-04] - [4.85873047e-03]], [[1.02736776e-06] - [7.78918832e-05] - [3.25980910e-03]], [[8.71027724e-07] - [1.64820060e-04] - [5.02912867e-03]], [[8.63231446e-07] - [8.45518855e-05] - [4.89045708e-03]], [[9.39068799e-07] - [1.12928697e-04] - [4.21779516e-03]], [[1.94712273e-07] - [2.39886479e-05] - [9.22741200e-04]], [[4.30155635e-07] - [5.18679547e-05] - [1.94104652e-03]], [[8.32395987e-07] - [1.00319931e-04] - [3.73878581e-03]] \ No newline at end of file diff --git a/tests/regression_tests/tally_aggregation/test.py b/tests/regression_tests/tally_aggregation/test.py deleted file mode 100644 index 70a948be6..000000000 --- a/tests/regression_tests/tally_aggregation/test.py +++ /dev/null @@ -1,95 +0,0 @@ -import hashlib - -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material(name='UO2') - fuel.set_density('g/cm3', 10.29769) - fuel.add_nuclide("U234", 4.4843e-6) - fuel.add_nuclide("U235", 5.5815e-4) - fuel.add_nuclide("U238", 2.2408e-2) - fuel.add_nuclide("O16", 4.5829e-2) - water = openmc.Material(name='light water') - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.set_density('g/cm3', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - model.materials.extend([fuel, water]) - - cyl = openmc.ZCylinder(r=0.4) - pin = openmc.model.pin([cyl], [fuel, water]) - d = 1.2 - lattice = openmc.RectLattice() - lattice.lower_left = (-d, -d) - lattice.pitch = (d, d) - lattice.outer = pin - lattice.universes = [ - [pin, pin], - [pin, pin], - ] - box = openmc.model.rectangular_prism(2*d, 2*d, boundary_type='reflective') - main_cell = openmc.Cell(fill=lattice, region=box) - model.geometry = openmc.Geometry([main_cell]) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 1000 - - energy_filter = openmc.EnergyFilter([0.0, 0.253, 1.0e3, 1.0e6, 20.0e6]) - distrib_filter = openmc.DistribcellFilter(pin.cells[1]) - tally = openmc.Tally(name='distribcell tally') - tally.filters = [energy_filter, distrib_filter] - tally.scores = ['nu-fission', 'total'] - tally.nuclides = ['U234', 'U235', 'U238'] - model.tallies.append(tally) - - return model - - - -class TallyAggregationTestHarness(PyAPITestHarness): - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Extract the tally of interest - tally = sp.get_tally(name='distribcell tally') - - # Perform tally aggregations across filter bins, nuclides and scores - outstr = '' - - # Sum across all energy filter bins - tally_sum = tally.summation(filter_type=openmc.EnergyFilter) - outstr += ', '.join(map(str, tally_sum.mean)) - outstr += ', '.join(map(str, tally_sum.std_dev)) - - # Sum across all distribcell filter bins - tally_sum = tally.summation(filter_type=openmc.DistribcellFilter) - outstr += ', '.join(map(str, tally_sum.mean)) - outstr += ', '.join(map(str, tally_sum.std_dev)) - - # Sum across all nuclides - tally_sum = tally.summation(nuclides=['U234', 'U235', 'U238']) - outstr += ', '.join(map(str, tally_sum.mean)) - outstr += ', '.join(map(str, tally_sum.std_dev)) - - # Sum across all scores - tally_sum = tally.summation(scores=['nu-fission', 'total']) - outstr += ', '.join(map(str, tally_sum.mean)) - outstr += ', '.join(map(str, tally_sum.std_dev)) - - return outstr - - -def test_tally_aggregation(model): - harness = TallyAggregationTestHarness('statepoint.10.h5', model) - harness.main() diff --git a/tests/regression_tests/tally_arithmetic/__init__.py b/tests/regression_tests/tally_arithmetic/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tally_arithmetic/inputs_true.dat b/tests/regression_tests/tally_arithmetic/inputs_true.dat deleted file mode 100644 index fbbf94fa9..000000000 --- a/tests/regression_tests/tally_arithmetic/inputs_true.dat +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 1000 - 5 - 0 - - - - - 2 2 - -10.0 -10.0 - 10.0 10.0 - - - 1 2 - - - 0.0 10.0 20000000.0 - - - 1 - - - 2 1 - U234 U235 - nu-fission total - - - 1 3 - U238 U235 - total fission - - diff --git a/tests/regression_tests/tally_arithmetic/results_true.dat b/tests/regression_tests/tally_arithmetic/results_true.dat deleted file mode 100644 index c10e0fb38..000000000 --- a/tests/regression_tests/tally_arithmetic/results_true.dat +++ /dev/null @@ -1,49 +0,0 @@ -[2.87610e-07 1.60278e-13 2.54988e-04 1.42099e-10 2.33002e-07 1.83973e-07 - 2.06574e-04 1.63105e-04 7.77662e-03 4.33372e-09 4.02417e-03 2.24257e-09 - 6.30008e-03 4.97439e-03 3.26010e-03 2.57410e-03 2.52614e-07 1.57719e-13 - 2.23961e-04 1.39830e-10 2.43493e-07 1.93615e-07 2.15874e-04 1.71654e-04 - 6.83035e-03 4.26453e-09 3.53450e-03 2.20677e-09 6.58373e-03 5.23510e-03 - 3.40688e-03 2.70901e-03 2.72019e-07 1.63161e-13 2.41165e-04 1.44654e-10 - 2.44531e-07 1.94194e-07 2.16795e-04 1.72167e-04 7.35506e-03 4.41166e-09 - 3.80602e-03 2.28290e-09 6.61180e-03 5.25075e-03 3.42141e-03 2.71710e-03 - 2.41472e-07 1.50936e-13 2.14083e-04 1.33816e-10 2.24252e-07 1.77892e-07 - 1.98816e-04 1.57715e-04 6.52910e-03 4.08113e-09 3.37861e-03 2.11186e-09 - 6.06350e-03 4.80998e-03 3.13768e-03 2.48902e-03 2.48914e-03 4.48016e-05 - 1.13508e-02 2.04302e-04 1.19934e-04 2.60981e-05 5.46915e-04 1.19011e-04 - 2.77675e-02 4.99783e-04 4.93334e-02 8.87945e-04 1.33792e-03 2.91137e-04 - 2.37703e-03 5.17251e-04 2.49083e-03 4.43597e-05 1.13585e-02 2.02286e-04 - 1.21668e-04 2.66359e-05 5.54821e-04 1.21463e-04 2.77864e-02 4.94854e-04 - 4.93670e-02 8.79187e-04 1.35726e-03 2.97136e-04 2.41139e-03 5.27909e-04 - 2.28387e-03 4.25108e-05 1.04148e-02 1.93855e-04 1.16292e-04 2.67442e-05 - 5.30307e-04 1.21957e-04 2.54776e-02 4.74228e-04 4.52651e-02 8.42543e-04 - 1.29729e-03 2.98344e-04 2.30485e-03 5.30056e-04 2.25849e-03 4.37806e-05 - 1.02990e-02 1.99646e-04 1.16539e-04 2.71633e-05 5.31435e-04 1.23868e-04 - 2.51945e-02 4.88393e-04 4.47620e-02 8.67709e-04 1.30005e-03 3.03020e-04 - 2.30975e-03 5.38363e-04][2.87610e-07 1.60278e-13 2.54988e-04 1.42099e-10 2.33002e-07 1.83973e-07 - 2.06574e-04 1.63105e-04 7.77662e-03 4.33372e-09 4.02417e-03 2.24257e-09 - 6.30008e-03 4.97439e-03 3.26010e-03 2.57410e-03 2.52614e-07 1.57719e-13 - 2.23961e-04 1.39830e-10 2.43493e-07 1.93615e-07 2.15874e-04 1.71654e-04 - 6.83035e-03 4.26453e-09 3.53450e-03 2.20677e-09 6.58373e-03 5.23510e-03 - 3.40688e-03 2.70901e-03 2.72019e-07 1.63161e-13 2.41165e-04 1.44654e-10 - 2.44531e-07 1.94194e-07 2.16795e-04 1.72167e-04 7.35506e-03 4.41166e-09 - 3.80602e-03 2.28290e-09 6.61180e-03 5.25075e-03 3.42141e-03 2.71710e-03 - 2.41472e-07 1.50936e-13 2.14083e-04 1.33816e-10 2.24252e-07 1.77892e-07 - 1.98816e-04 1.57715e-04 6.52910e-03 4.08113e-09 3.37861e-03 2.11186e-09 - 6.06350e-03 4.80998e-03 3.13768e-03 2.48902e-03 2.48914e-03 4.48016e-05 - 1.13508e-02 2.04302e-04 1.19934e-04 2.60981e-05 5.46915e-04 1.19011e-04 - 2.77675e-02 4.99783e-04 4.93334e-02 8.87945e-04 1.33792e-03 2.91137e-04 - 2.37703e-03 5.17251e-04 2.49083e-03 4.43597e-05 1.13585e-02 2.02286e-04 - 1.21668e-04 2.66359e-05 5.54821e-04 1.21463e-04 2.77864e-02 4.94854e-04 - 4.93670e-02 8.79187e-04 1.35726e-03 2.97136e-04 2.41139e-03 5.27909e-04 - 2.28387e-03 4.25108e-05 1.04148e-02 1.93855e-04 1.16292e-04 2.67442e-05 - 5.30307e-04 1.21957e-04 2.54776e-02 4.74228e-04 4.52651e-02 8.42543e-04 - 1.29729e-03 2.98344e-04 2.30485e-03 5.30056e-04 2.25849e-03 4.37806e-05 - 1.02990e-02 1.99646e-04 1.16539e-04 2.71633e-05 5.31435e-04 1.23868e-04 - 2.51945e-02 4.88393e-04 4.47620e-02 8.67709e-04 1.30005e-03 3.03020e-04 - 2.30975e-03 5.38363e-04][0.0063 0.00497 0.00326 0.00257 0.00658 0.00524 0.00341 0.00271 0.00661 - 0.00525 0.00342 0.00272 0.00606 0.00481 0.00314 0.00249 0.00134 0.00029 - 0.00238 0.00052 0.00136 0.0003 0.00241 0.00053 0.0013 0.0003 0.0023 - 0.00053 0.0013 0.0003 0.00231 0.00054][0.00025 0.00021 0.00402 0.00326 0.00022 0.00022 0.00353 0.00341 0.00024 - 0.00022 0.00381 0.00342 0.00021 0.0002 0.00338 0.00314 0.01135 0.00055 - 0.04933 0.00238 0.01136 0.00055 0.04937 0.00241 0.01041 0.00053 0.04527 - 0.0023 0.0103 0.00053 0.04476 0.00231][0.00326 0.00341 0.00342 0.00314 0.00238 0.00241 0.0023 0.00231] \ No newline at end of file diff --git a/tests/regression_tests/tally_arithmetic/test.py b/tests/regression_tests/tally_arithmetic/test.py deleted file mode 100644 index 532160a17..000000000 --- a/tests/regression_tests/tally_arithmetic/test.py +++ /dev/null @@ -1,103 +0,0 @@ -import hashlib - -import numpy as np -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - - -@pytest.fixture -def model(): - model = openmc.model.Model() - - fuel = openmc.Material() - fuel.set_density('g/cm3', 10.0) - fuel.add_nuclide('U234', 1.0) - fuel.add_nuclide('U235', 4.0) - fuel.add_nuclide('U238', 95.0) - water = openmc.Material(name='light water') - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.set_density('g/cm3', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - model.materials.extend([fuel, water]) - - cyl1 = openmc.ZCylinder(r=5.0) - cyl2 = openmc.ZCylinder(r=10.0, boundary_type='vacuum') - cell1 = openmc.Cell(fill=fuel, region=-cyl1) - cell2 = openmc.Cell(fill=water, region=+cyl1 & -cyl2) - model.geometry = openmc.Geometry([cell1, cell2]) - - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 1000 - - mesh = openmc.RegularMesh() - mesh.dimension = (2, 2) - mesh.lower_left = (-10.0, -10.0) - mesh.upper_right = (10.0, 10.0) - energy_filter = openmc.EnergyFilter((0.0, 10.0, 20.0e6)) - material_filter = openmc.MaterialFilter((fuel, water)) - mesh_filter = openmc.MeshFilter(mesh) - - tally = openmc.Tally(name='tally 1') - tally.filters = [material_filter, energy_filter] - tally.scores = ['nu-fission', 'total'] - tally.nuclides = ['U234', 'U235'] - model.tallies.append(tally) - tally = openmc.Tally(name='tally 2') - tally.filters = [energy_filter, mesh_filter] - tally.scores = ['total', 'fission'] - tally.nuclides = ['U238', 'U235'] - model.tallies.append(tally) - - return model - - -class TallyArithmeticTestHarness(PyAPITestHarness): - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Load the tallies - tally_1 = sp.get_tally(name='tally 1') - tally_2 = sp.get_tally(name='tally 2') - - # Perform all the tally arithmetic operations and output results - output = [] - with np.printoptions(precision=5, threshold=np.inf): - mean = (tally_1 * tally_2).mean - output.append(str(mean[np.nonzero(mean)])) - - mean = tally_1.hybrid_product( - tally_2, '*', 'entrywise', 'tensor', 'tensor').mean - output.append(str(mean[np.nonzero(mean)])) - - mean = tally_1.hybrid_product( - tally_2, '*', 'entrywise', 'entrywise', 'tensor').mean - output.append(str(mean[np.nonzero(mean)])) - - mean = tally_1.hybrid_product( - tally_2, '*', 'entrywise', 'tensor', 'entrywise').mean - output.append(str(mean[np.nonzero(mean)])) - - mean = tally_1.hybrid_product( - tally_2, '*', 'entrywise', 'entrywise', 'entrywise').mean - output.append(str(mean[np.nonzero(mean)])) - - # Hash the results if necessary - outstr = ''.join(output) - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_tally_arithmetic(model): - harness = TallyArithmeticTestHarness('statepoint.5.h5', model) - harness.main() diff --git a/tests/regression_tests/tally_assumesep/__init__.py b/tests/regression_tests/tally_assumesep/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tally_assumesep/geometry.xml b/tests/regression_tests/tally_assumesep/geometry.xml deleted file mode 100644 index a028ad05d..000000000 --- a/tests/regression_tests/tally_assumesep/geometry.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/tally_assumesep/materials.xml b/tests/regression_tests/tally_assumesep/materials.xml deleted file mode 100644 index b27086e61..000000000 --- a/tests/regression_tests/tally_assumesep/materials.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/tally_assumesep/results_true.dat b/tests/regression_tests/tally_assumesep/results_true.dat deleted file mode 100644 index d9dc53f0a..000000000 --- a/tests/regression_tests/tally_assumesep/results_true.dat +++ /dev/null @@ -1,11 +0,0 @@ -k-combined: -6.161485E-01 2.229530E-02 -tally 1: -7.433231E+00 -1.122269E+01 -tally 2: -2.545046E-01 -1.340485E-02 -tally 3: -1.136947E+01 -2.646408E+01 diff --git a/tests/regression_tests/tally_assumesep/settings.xml b/tests/regression_tests/tally_assumesep/settings.xml deleted file mode 100644 index 64b69f394..000000000 --- a/tests/regression_tests/tally_assumesep/settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - eigenvalue - 10 - 5 - 100 - - - 0.0 0.0 0.0 - - - diff --git a/tests/regression_tests/tally_assumesep/tallies.xml b/tests/regression_tests/tally_assumesep/tallies.xml deleted file mode 100644 index f65e5dfec..000000000 --- a/tests/regression_tests/tally_assumesep/tallies.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - true - - - cell - 1 - - - - cell - 2 - - - - cell - 3 - - - - 1 - total - - - - 2 - total - - - - 3 - total - - - diff --git a/tests/regression_tests/tally_assumesep/test.py b/tests/regression_tests/tally_assumesep/test.py deleted file mode 100644 index 64595ced2..000000000 --- a/tests/regression_tests/tally_assumesep/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_tally_assumesep(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/tally_nuclides/__init__.py b/tests/regression_tests/tally_nuclides/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tally_nuclides/geometry.xml b/tests/regression_tests/tally_nuclides/geometry.xml deleted file mode 100644 index 7c3aefe88..000000000 --- a/tests/regression_tests/tally_nuclides/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/tally_nuclides/materials.xml b/tests/regression_tests/tally_nuclides/materials.xml deleted file mode 100644 index 1f89c7df6..000000000 --- a/tests/regression_tests/tally_nuclides/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/tally_nuclides/results_true.dat b/tests/regression_tests/tally_nuclides/results_true.dat deleted file mode 100644 index 6c05f21c1..000000000 --- a/tests/regression_tests/tally_nuclides/results_true.dat +++ /dev/null @@ -1,28 +0,0 @@ -k-combined: -9.752413E-01 4.425138E-02 -tally 1: -6.903182E+00 -9.661093E+00 -1.569337E+00 -4.971848E-01 -1.521894E+00 -4.673220E-01 -5.333845E+00 -5.778630E+00 -6.903182E+00 -9.661093E+00 -1.569337E+00 -4.971848E-01 -1.521894E+00 -4.673220E-01 -5.333845E+00 -5.778630E+00 -tally 2: -6.903182E+00 -9.661093E+00 -1.569337E+00 -4.971848E-01 -1.521894E+00 -4.673220E-01 -5.333845E+00 -5.778630E+00 diff --git a/tests/regression_tests/tally_nuclides/settings.xml b/tests/regression_tests/tally_nuclides/settings.xml deleted file mode 100644 index 32afc717a..000000000 --- a/tests/regression_tests/tally_nuclides/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - eigenvalue - 10 - 5 - 100 - - - - point - 0.0 0.0 0.0 - - - - diff --git a/tests/regression_tests/tally_nuclides/tallies.xml b/tests/regression_tests/tally_nuclides/tallies.xml deleted file mode 100644 index 3440dbf21..000000000 --- a/tests/regression_tests/tally_nuclides/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - all - total absorption fission scatter - - - - Pu239 - total absorption fission scatter - - - diff --git a/tests/regression_tests/tally_nuclides/test.py b/tests/regression_tests/tally_nuclides/test.py deleted file mode 100644 index ee1f4b600..000000000 --- a/tests/regression_tests/tally_nuclides/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_tally_nuclides(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/tally_slice_merge/__init__.py b/tests/regression_tests/tally_slice_merge/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/tally_slice_merge/inputs_true.dat b/tests/regression_tests/tally_slice_merge/inputs_true.dat deleted file mode 100644 index 6f421b1d9..000000000 --- a/tests/regression_tests/tally_slice_merge/inputs_true.dat +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 -1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - - - 1.26 1.26 - 17 17 - -10.71 -10.71 - -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3 -3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 -3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 -5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 -5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 -5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 -5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 - - - 21.42 21.42 - 21 21 - -224.91 -224.91 - -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 -7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 -7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 -7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 10 - 5 - - - -160 -160 -183 160 160 183 - - - - - - - - 2 2 - -50.0 -50.0 - 50.0 50.0 - - - 21 27 - - - 0.0 0.625 20000000.0 - - - 21 - - - 1 - - - 16 8 - U235 U238 - fission nu-fission - tracklength - - - 6 8 - U235 U238 - fission nu-fission - tracklength - - - 7 8 - U235 U238 - fission nu-fission - tracklength - - diff --git a/tests/regression_tests/tally_slice_merge/results_true.dat b/tests/regression_tests/tally_slice_merge/results_true.dat deleted file mode 100644 index 461c4faa8..000000000 --- a/tests/regression_tests/tally_slice_merge/results_true.dat +++ /dev/null @@ -1,67 +0,0 @@ - cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 2.21e-01 9.47e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 nu-fission 5.38e-01 2.31e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 fission 3.05e-07 1.36e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 nu-fission 7.60e-07 3.39e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 fission 3.97e-02 4.54e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 nu-fission 9.72e-02 1.10e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 fission 1.89e-02 1.11e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 nu-fission 5.31e-02 3.32e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 fission 6.24e-02 1.10e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 nu-fission 1.52e-01 2.67e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 fission 8.80e-08 1.49e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 nu-fission 2.19e-07 3.72e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 fission 1.08e-02 1.46e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 nu-fission 2.65e-02 3.55e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 fission 5.88e-03 9.74e-04 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 nu-fission 1.61e-02 2.59e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 2.21e-01 9.47e-03 -1 21 0.00e+00 6.25e-01 U235 nu-fission 5.38e-01 2.31e-02 -2 21 0.00e+00 6.25e-01 U238 fission 3.05e-07 1.36e-08 -3 21 0.00e+00 6.25e-01 U238 nu-fission 7.60e-07 3.39e-08 -4 21 6.25e-01 2.00e+07 U235 fission 3.97e-02 4.54e-03 -5 21 6.25e-01 2.00e+07 U235 nu-fission 9.72e-02 1.10e-02 -6 21 6.25e-01 2.00e+07 U238 fission 1.89e-02 1.11e-03 -7 21 6.25e-01 2.00e+07 U238 nu-fission 5.31e-02 3.32e-03 -8 27 0.00e+00 6.25e-01 U235 fission 6.24e-02 1.10e-02 -9 27 0.00e+00 6.25e-01 U235 nu-fission 1.52e-01 2.67e-02 -10 27 0.00e+00 6.25e-01 U238 fission 8.80e-08 1.49e-08 -11 27 0.00e+00 6.25e-01 U238 nu-fission 2.19e-07 3.72e-08 -12 27 6.25e-01 2.00e+07 U235 fission 1.08e-02 1.46e-03 -13 27 6.25e-01 2.00e+07 U235 nu-fission 2.65e-02 3.55e-03 -14 27 6.25e-01 2.00e+07 U238 fission 5.88e-03 9.74e-04 -15 27 6.25e-01 2.00e+07 U238 nu-fission 1.61e-02 2.59e-03 - sum(distribcell) energy low [eV] energy high [eV] nuclide score mean std. dev. -0 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 -1 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 -2 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 -3 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 -4 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 fission 0.00e+00 0.00e+00 -5 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 nu-fission 0.00e+00 0.00e+00 -6 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 -7 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 -8 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 -9 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 -10 (500, 5000, 50000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 -11 (500, 5000, 50000) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 -12 (500, 5000, 50000) 6.25e-01 2.00e+07 U235 fission 0.00e+00 0.00e+00 -13 (500, 5000, 50000) 6.25e-01 2.00e+07 U235 nu-fission 0.00e+00 0.00e+00 -14 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 -15 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 - sum(mesh) energy low [eV] energy high [eV] nuclide score mean std. dev. -0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 -1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 -2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 -3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 -4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 1.60e-04 1.60e-04 -5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 3.91e-04 3.91e-04 -6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 5.12e-05 5.12e-05 -7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.36e-04 1.36e-04 -8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 4.04e-02 6.60e-03 -9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 9.85e-02 1.61e-02 -10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 5.61e-08 9.18e-09 -11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 1.40e-07 2.29e-08 -12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 7.08e-03 1.43e-03 -13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 1.73e-02 3.48e-03 -14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 2.91e-03 3.36e-04 -15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 7.96e-03 9.27e-04 diff --git a/tests/regression_tests/tally_slice_merge/test.py b/tests/regression_tests/tally_slice_merge/test.py deleted file mode 100644 index 090e31448..000000000 --- a/tests/regression_tests/tally_slice_merge/test.py +++ /dev/null @@ -1,170 +0,0 @@ -import hashlib -import itertools - -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class TallySliceMergeTestHarness(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Define nuclides and scores to add to both tallies - self.nuclides = ['U235', 'U238'] - self.scores = ['fission', 'nu-fission'] - - # Define filters for energy and spatial domain - - low_energy = openmc.EnergyFilter([0., 0.625]) - high_energy = openmc.EnergyFilter([0.625, 20.e6]) - merged_energies = low_energy.merge(high_energy) - - cell_21 = openmc.CellFilter(21) - cell_27 = openmc.CellFilter(27) - distribcell_filter = openmc.DistribcellFilter(21) - - mesh = openmc.RegularMesh(name='mesh') - mesh.dimension = [2, 2] - mesh.lower_left = [-50., -50.] - mesh.upper_right = [+50., +50.] - mesh_filter = openmc.MeshFilter(mesh) - - self.cell_filters = [cell_21, cell_27] - self.energy_filters = [low_energy, high_energy] - - # Initialize cell tallies with filters, nuclides and scores - tallies = [] - for energy_filter in self.energy_filters: - for cell_filter in self.cell_filters: - for nuclide in self.nuclides: - for score in self.scores: - tally = openmc.Tally() - tally.estimator = 'tracklength' - tally.scores.append(score) - tally.nuclides.append(nuclide) - tally.filters.append(cell_filter) - tally.filters.append(energy_filter) - tallies.append(tally) - - # Merge all cell tallies together - while len(tallies) != 1: - halfway = len(tallies) // 2 - zip_split = zip(tallies[:halfway], tallies[halfway:]) - tallies = list(map(lambda xy: xy[0].merge(xy[1]), zip_split)) - - # Specify a name for the tally - tallies[0].name = 'cell tally' - - # Initialize a distribcell tally - distribcell_tally = openmc.Tally(name='distribcell tally') - distribcell_tally.estimator = 'tracklength' - distribcell_tally.filters = [distribcell_filter, merged_energies] - for score in self.scores: - distribcell_tally.scores.append(score) - for nuclide in self.nuclides: - distribcell_tally.nuclides.append(nuclide) - - mesh_tally = openmc.Tally(name='mesh tally') - mesh_tally.estimator = 'tracklength' - mesh_tally.filters = [mesh_filter, merged_energies] - mesh_tally.scores = self.scores - mesh_tally.nuclides = self.nuclides - - # Add tallies to a Tallies object - self._model.tallies = [tallies[0], distribcell_tally, mesh_tally] - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - - # Read the statepoint file. - sp = openmc.StatePoint(self._sp_name) - - # Extract the cell tally - tallies = [sp.get_tally(name='cell tally')] - - # Slice the tallies by cell filter bins - cell_filter_prod = itertools.product(tallies, self.cell_filters) - tallies = map(lambda tf: tf[0].get_slice(filters=[type(tf[1])], - filter_bins=[(tf[1].bins[0],)]), - cell_filter_prod) - - # Slice the tallies by energy filter bins - energy_filter_prod = itertools.product(tallies, self.energy_filters) - tallies = map(lambda tf: tf[0].get_slice(filters=[type(tf[1])], - filter_bins=[(tf[1].bins[0],)]), - energy_filter_prod) - - # Slice the tallies by nuclide - nuclide_prod = itertools.product(tallies, self.nuclides) - tallies = map(lambda tn: tn[0].get_slice(nuclides=[tn[1]]), nuclide_prod) - - # Slice the tallies by score - score_prod = itertools.product(tallies, self.scores) - tallies = map(lambda ts: ts[0].get_slice(scores=[ts[1]]), score_prod) - tallies = list(tallies) - - # Initialize an output string - outstr = '' - - # Append sliced Tally Pandas DataFrames to output string - for tally in tallies: - df = tally.get_pandas_dataframe() - outstr += df.to_string() - - # Merge all tallies together - while len(tallies) != 1: - halfway = int(len(tallies) / 2) - zip_split = zip(tallies[:halfway], tallies[halfway:]) - tallies = list(map(lambda xy: xy[0].merge(xy[1]), zip_split)) - - # Append merged Tally Pandas DataFrame to output string - df = tallies[0].get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Extract the distribcell tally - distribcell_tally = sp.get_tally(name='distribcell tally') - - # Sum up a few subdomains from the distribcell tally - sum1 = distribcell_tally.summation(filter_type=openmc.DistribcellFilter, - filter_bins=[0, 100, 2000, 30000]) - # Sum up a few subdomains from the distribcell tally - sum2 = distribcell_tally.summation(filter_type=openmc.DistribcellFilter, - filter_bins=[500, 5000, 50000]) - - # Merge the distribcell tally slices - merge_tally = sum1.merge(sum2) - - # Append merged Tally Pandas DataFrame to output string - df = merge_tally.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Extract the mesh tally - mesh_tally = sp.get_tally(name='mesh tally') - - # Sum up a few subdomains from the mesh tally - sum1 = mesh_tally.summation(filter_type=openmc.MeshFilter, - filter_bins=[(1, 1), (1, 2)]) - # Sum up a few subdomains from the mesh tally - sum2 = mesh_tally.summation(filter_type=openmc.MeshFilter, - filter_bins=[(2, 1), (2, 2)]) - - # Merge the mesh tally slices - merge_tally = sum1.merge(sum2) - - # Append merged Tally Pandas DataFrame to output string - df = merge_tally.get_pandas_dataframe() - outstr += df.to_string() + '\n' - - # Hash the results if necessary - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - -def test_tally_slice_merge(): - harness = TallySliceMergeTestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/trace/__init__.py b/tests/regression_tests/trace/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/trace/geometry.xml b/tests/regression_tests/trace/geometry.xml deleted file mode 100644 index bc56030e1..000000000 --- a/tests/regression_tests/trace/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/trace/materials.xml b/tests/regression_tests/trace/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/trace/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/trace/results_true.dat b/tests/regression_tests/trace/results_true.dat deleted file mode 100644 index 5cb3925a6..000000000 --- a/tests/regression_tests/trace/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 diff --git a/tests/regression_tests/trace/settings.xml b/tests/regression_tests/trace/settings.xml deleted file mode 100644 index ce614711b..000000000 --- a/tests/regression_tests/trace/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - 5 1 453 - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/trace/test.py b/tests/regression_tests/trace/test.py deleted file mode 100644 index 79dcaa106..000000000 --- a/tests/regression_tests/trace/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_trace(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/track_output/__init__.py b/tests/regression_tests/track_output/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/track_output/geometry.xml b/tests/regression_tests/track_output/geometry.xml deleted file mode 100644 index 5b16fe26c..000000000 --- a/tests/regression_tests/track_output/geometry.xml +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 3 2 2 2 2 2 2 2 1 2 2 2 - 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - - - - - - - - - - -12.2682 -12.2682 - 1.63576 1.63576 - - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 - - - - - - - - - - - - - - - - - - - -85.8774 -85.8774 - 24.5364 24.5364 - - 999 999 130 140 150 999 999 - 999 220 230 240 250 260 999 - 130 320 777 222 333 360 150 - 410 240 444 111 666 240 470 - 510 520 888 555 998 560 570 - 999 620 630 240 650 660 999 - 999 999 510 740 570 999 999 - - - - - - - - diff --git a/tests/regression_tests/track_output/materials.xml b/tests/regression_tests/track_output/materials.xml deleted file mode 100644 index 5dc9a6475..000000000 --- a/tests/regression_tests/track_output/materials.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat deleted file mode 100644 index 1d0ca8039..000000000 --- a/tests/regression_tests/track_output/results_true.dat +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/track_output/settings.xml b/tests/regression_tests/track_output/settings.xml deleted file mode 100644 index 299ee72c5..000000000 --- a/tests/regression_tests/track_output/settings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - eigenvalue - 2 - 0 - 100 - - - - - -1 -1 -1 1 1 1 - - - - - 1 1 1 - 1 1 2 - - - diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py deleted file mode 100644 index a5300a4ae..000000000 --- a/tests/regression_tests/track_output/test.py +++ /dev/null @@ -1,46 +0,0 @@ -import glob -import os -from subprocess import call -import shutil - -import pytest - -from tests.testing_harness import TestHarness - - -class TrackTestHarness(TestHarness): - def _test_output_created(self): - """Make sure statepoint.* and track* have been created.""" - TestHarness._test_output_created(self) - - outputs = glob.glob('track_1_1_*.h5') - assert len(outputs) == 2, 'Expected two track files.' - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Run the track-to-vtk conversion script. - call(['../../../scripts/openmc-track-to-vtk', '-o', 'poly'] + - glob.glob('track_1_1_*.h5')) - - # Make sure the vtk file was created then return it's contents. - assert os.path.isfile('poly.pvtp'), 'poly.pvtp file not found.' - - with open('poly.pvtp', 'r') as fin: - outstr = fin.read() - - return outstr - - def _cleanup(self): - TestHarness._cleanup(self) - output = glob.glob('track*') + glob.glob('poly*') - for f in output: - if os.path.exists(f): - os.remove(f) - - -def test_track_output(): - # If vtk python module is not available, we can't run track.py so skip this - # test. - vtk = pytest.importorskip('vtk') - harness = TrackTestHarness('statepoint.2.h5') - harness.main() diff --git a/tests/regression_tests/translation/__init__.py b/tests/regression_tests/translation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/translation/geometry.xml b/tests/regression_tests/translation/geometry.xml deleted file mode 100644 index 6c6343865..000000000 --- a/tests/regression_tests/translation/geometry.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/translation/materials.xml b/tests/regression_tests/translation/materials.xml deleted file mode 100644 index 160c9c678..000000000 --- a/tests/regression_tests/translation/materials.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tests/regression_tests/translation/results_true.dat b/tests/regression_tests/translation/results_true.dat deleted file mode 100644 index a50311034..000000000 --- a/tests/regression_tests/translation/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -4.101355E-01 1.577552E-02 diff --git a/tests/regression_tests/translation/settings.xml b/tests/regression_tests/translation/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/translation/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/translation/test.py b/tests/regression_tests/translation/test.py deleted file mode 100644 index 876db736b..000000000 --- a/tests/regression_tests/translation/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_translation(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/trigger_batch_interval/__init__.py b/tests/regression_tests/trigger_batch_interval/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/trigger_batch_interval/geometry.xml b/tests/regression_tests/trigger_batch_interval/geometry.xml deleted file mode 100644 index 7c3aefe88..000000000 --- a/tests/regression_tests/trigger_batch_interval/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/trigger_batch_interval/materials.xml b/tests/regression_tests/trigger_batch_interval/materials.xml deleted file mode 100644 index 1f89c7df6..000000000 --- a/tests/regression_tests/trigger_batch_interval/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/trigger_batch_interval/results_true.dat b/tests/regression_tests/trigger_batch_interval/results_true.dat deleted file mode 100644 index 18eee6d4d..000000000 --- a/tests/regression_tests/trigger_batch_interval/results_true.dat +++ /dev/null @@ -1,28 +0,0 @@ -k-combined: -9.722624E-01 1.010455E-02 -tally 1: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -tally 2: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 diff --git a/tests/regression_tests/trigger_batch_interval/settings.xml b/tests/regression_tests/trigger_batch_interval/settings.xml deleted file mode 100644 index ecba8d347..000000000 --- a/tests/regression_tests/trigger_batch_interval/settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - eigenvalue - 15 - 5 - 1000 - - std_dev - 0.004 - - - - true - 30 - 1 - - - - - point - 0.0 0.0 0.0 - - - - diff --git a/tests/regression_tests/trigger_batch_interval/tallies.xml b/tests/regression_tests/trigger_batch_interval/tallies.xml deleted file mode 100644 index 3440dbf21..000000000 --- a/tests/regression_tests/trigger_batch_interval/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - all - total absorption fission scatter - - - - Pu239 - total absorption fission scatter - - - diff --git a/tests/regression_tests/trigger_batch_interval/test.py b/tests/regression_tests/trigger_batch_interval/test.py deleted file mode 100644 index e16174502..000000000 --- a/tests/regression_tests/trigger_batch_interval/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_trigger_batch_interval(): - harness = TestHarness('statepoint.15.h5') - harness.main() diff --git a/tests/regression_tests/trigger_no_batch_interval/__init__.py b/tests/regression_tests/trigger_no_batch_interval/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/trigger_no_batch_interval/geometry.xml b/tests/regression_tests/trigger_no_batch_interval/geometry.xml deleted file mode 100644 index 7c3aefe88..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/trigger_no_batch_interval/materials.xml b/tests/regression_tests/trigger_no_batch_interval/materials.xml deleted file mode 100644 index 1f89c7df6..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/trigger_no_batch_interval/results_true.dat b/tests/regression_tests/trigger_no_batch_interval/results_true.dat deleted file mode 100644 index 18eee6d4d..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/results_true.dat +++ /dev/null @@ -1,28 +0,0 @@ -k-combined: -9.722624E-01 1.010455E-02 -tally 1: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -tally 2: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 diff --git a/tests/regression_tests/trigger_no_batch_interval/settings.xml b/tests/regression_tests/trigger_no_batch_interval/settings.xml deleted file mode 100644 index 9a4c94226..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/settings.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - eigenvalue - 15 - 5 - 1000 - - std_dev - 0.004 - - - - true - 30 - - - - - point - 0.0 0.0 0.0 - - - - diff --git a/tests/regression_tests/trigger_no_batch_interval/tallies.xml b/tests/regression_tests/trigger_no_batch_interval/tallies.xml deleted file mode 100644 index 3440dbf21..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - all - total absorption fission scatter - - - - Pu239 - total absorption fission scatter - - - diff --git a/tests/regression_tests/trigger_no_batch_interval/test.py b/tests/regression_tests/trigger_no_batch_interval/test.py deleted file mode 100644 index 4a40def5a..000000000 --- a/tests/regression_tests/trigger_no_batch_interval/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_trigger_no_batch_interval(): - harness = TestHarness('statepoint.15.h5') - harness.main() diff --git a/tests/regression_tests/trigger_no_status/__init__.py b/tests/regression_tests/trigger_no_status/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/trigger_no_status/geometry.xml b/tests/regression_tests/trigger_no_status/geometry.xml deleted file mode 100644 index 7c3aefe88..000000000 --- a/tests/regression_tests/trigger_no_status/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/trigger_no_status/materials.xml b/tests/regression_tests/trigger_no_status/materials.xml deleted file mode 100644 index 1f89c7df6..000000000 --- a/tests/regression_tests/trigger_no_status/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/trigger_no_status/results_true.dat b/tests/regression_tests/trigger_no_status/results_true.dat deleted file mode 100644 index bb71a4e53..000000000 --- a/tests/regression_tests/trigger_no_status/results_true.dat +++ /dev/null @@ -1,28 +0,0 @@ -k-combined: -9.733783E-01 1.678092E-02 -tally 1: -6.901811E+00 -9.536642E+00 -1.572258E+00 -4.947921E-01 -1.527087E+00 -4.667458E-01 -5.329552E+00 -5.686972E+00 -6.901811E+00 -9.536642E+00 -1.572258E+00 -4.947921E-01 -1.527087E+00 -4.667458E-01 -5.329552E+00 -5.686972E+00 -tally 2: -6.901811E+00 -9.536642E+00 -1.572258E+00 -4.947921E-01 -1.527087E+00 -4.667458E-01 -5.329552E+00 -5.686972E+00 diff --git a/tests/regression_tests/trigger_no_status/settings.xml b/tests/regression_tests/trigger_no_status/settings.xml deleted file mode 100644 index b85816240..000000000 --- a/tests/regression_tests/trigger_no_status/settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - eigenvalue - 10 - 5 - 1000 - - std_dev - 0.009 - - - false - 15 - 1 - - - - - - point - 0.0 0.0 0.0 - - - - diff --git a/tests/regression_tests/trigger_no_status/tallies.xml b/tests/regression_tests/trigger_no_status/tallies.xml deleted file mode 100644 index 3440dbf21..000000000 --- a/tests/regression_tests/trigger_no_status/tallies.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - all - total absorption fission scatter - - - - Pu239 - total absorption fission scatter - - - diff --git a/tests/regression_tests/trigger_no_status/test.py b/tests/regression_tests/trigger_no_status/test.py deleted file mode 100644 index 75ae9a8cc..000000000 --- a/tests/regression_tests/trigger_no_status/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_trigger_no_status(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/trigger_tallies/__init__.py b/tests/regression_tests/trigger_tallies/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/trigger_tallies/geometry.xml b/tests/regression_tests/trigger_tallies/geometry.xml deleted file mode 100644 index 7c3aefe88..000000000 --- a/tests/regression_tests/trigger_tallies/geometry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/regression_tests/trigger_tallies/materials.xml b/tests/regression_tests/trigger_tallies/materials.xml deleted file mode 100644 index 1f89c7df6..000000000 --- a/tests/regression_tests/trigger_tallies/materials.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/trigger_tallies/results_true.dat b/tests/regression_tests/trigger_tallies/results_true.dat deleted file mode 100644 index 18eee6d4d..000000000 --- a/tests/regression_tests/trigger_tallies/results_true.dat +++ /dev/null @@ -1,28 +0,0 @@ -k-combined: -9.722624E-01 1.010455E-02 -tally 1: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 -tally 2: -1.392936E+01 -1.941888E+01 -3.159556E+00 -9.989775E-01 -3.063616E+00 -9.391665E-01 -1.076980E+01 -1.160931E+01 diff --git a/tests/regression_tests/trigger_tallies/settings.xml b/tests/regression_tests/trigger_tallies/settings.xml deleted file mode 100644 index d8f814bf3..000000000 --- a/tests/regression_tests/trigger_tallies/settings.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - eigenvalue - 10 - 5 - 1000 - - std_dev - 0.001 - - - - true - 15 - 1 - - - - - point - 0.0 0.0 0.0 - - - - diff --git a/tests/regression_tests/trigger_tallies/tallies.xml b/tests/regression_tests/trigger_tallies/tallies.xml deleted file mode 100644 index 0d66e1538..000000000 --- a/tests/regression_tests/trigger_tallies/tallies.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - all - total absorption fission scatter - - - - Pu239 - total absorption fission scatter - - - - diff --git a/tests/regression_tests/trigger_tallies/test.py b/tests/regression_tests/trigger_tallies/test.py deleted file mode 100644 index f8493c0c6..000000000 --- a/tests/regression_tests/trigger_tallies/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_trigger_tallies(): - harness = TestHarness('statepoint.15.h5') - harness.main() diff --git a/tests/regression_tests/triso/__init__.py b/tests/regression_tests/triso/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/triso/inputs_true.dat b/tests/regression_tests/triso/inputs_true.dat deleted file mode 100644 index 2ea049465..000000000 --- a/tests/regression_tests/triso/inputs_true.dat +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0.3333333333333333 0.3333333333333333 0.3333333333333333 - 38 - 3 3 3 - -0.5 -0.5 -0.5 - -17 18 19 -14 15 16 -11 12 13 - -26 27 28 -23 24 25 -20 21 22 - -35 36 37 -32 33 34 -29 30 31 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eigenvalue - 100 - 4 - 0 - - - 0.0 0.0 0.0 - - - diff --git a/tests/regression_tests/triso/results_true.dat b/tests/regression_tests/triso/results_true.dat deleted file mode 100644 index c8e683234..000000000 --- a/tests/regression_tests/triso/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -1.701412E+00 3.180881E-02 diff --git a/tests/regression_tests/triso/test.py b/tests/regression_tests/triso/test.py deleted file mode 100644 index 7bef80ea8..000000000 --- a/tests/regression_tests/triso/test.py +++ /dev/null @@ -1,97 +0,0 @@ -import random -from math import sqrt - -import numpy as np -import openmc -import openmc.model - -from tests.testing_harness import PyAPITestHarness - - -class TRISOTestHarness(PyAPITestHarness): - def _build_inputs(self): - # Define TRISO matrials - fuel = openmc.Material() - fuel.set_density('g/cm3', 10.5) - fuel.add_nuclide('U235', 0.14154) - fuel.add_nuclide('U238', 0.85846) - fuel.add_nuclide('C0', 0.5) - fuel.add_nuclide('O16', 1.5) - - porous_carbon = openmc.Material() - porous_carbon.set_density('g/cm3', 1.0) - porous_carbon.add_nuclide('C0', 1.0) - porous_carbon.add_s_alpha_beta('c_Graphite') - - ipyc = openmc.Material() - ipyc.set_density('g/cm3', 1.90) - ipyc.add_nuclide('C0', 1.0) - ipyc.add_s_alpha_beta('c_Graphite') - - sic = openmc.Material() - sic.set_density('g/cm3', 3.20) - sic.add_nuclide('C0', 1.0) - sic.add_element('Si', 1.0) - - opyc = openmc.Material() - opyc.set_density('g/cm3', 1.87) - opyc.add_nuclide('C0', 1.0) - opyc.add_s_alpha_beta('c_Graphite') - - graphite = openmc.Material() - graphite.set_density('g/cm3', 1.1995) - graphite.add_nuclide('C0', 1.0) - graphite.add_s_alpha_beta('c_Graphite') - - # Create TRISO particles - spheres = [openmc.Sphere(r=r*1e-4) - for r in [212.5, 312.5, 347.5, 382.5]] - c1 = openmc.Cell(fill=fuel, region=-spheres[0]) - c2 = openmc.Cell(fill=porous_carbon, region=+spheres[0] & -spheres[1]) - c3 = openmc.Cell(fill=ipyc, region=+spheres[1] & -spheres[2]) - c4 = openmc.Cell(fill=sic, region=+spheres[2] & -spheres[3]) - c5 = openmc.Cell(fill=opyc, region=+spheres[3]) - inner_univ = openmc.Universe(cells=[c1, c2, c3, c4, c5]) - - # Define box to contain lattice and to pack TRISO particles in - min_x = openmc.XPlane(-0.5, 'reflective') - max_x = openmc.XPlane(0.5, 'reflective') - min_y = openmc.YPlane(-0.5, 'reflective') - max_y = openmc.YPlane(0.5, 'reflective') - min_z = openmc.ZPlane(-0.5, 'reflective') - max_z = openmc.ZPlane(0.5, 'reflective') - box_region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z - box = openmc.Cell(region=box_region) - - outer_radius = 422.5*1e-4 - centers = openmc.model.pack_spheres(radius=outer_radius, - region=box_region, num_spheres=100) - trisos = [openmc.model.TRISO(outer_radius, inner_univ, c) - for c in centers] - - # Create lattice - ll, ur = box.region.bounding_box - shape = (3, 3, 3) - pitch = (ur - ll) / shape - lattice = openmc.model.create_triso_lattice( - trisos, ll, pitch, shape, graphite) - box.fill = lattice - - root = openmc.Universe(0, cells=[box]) - geom = openmc.Geometry(root) - geom.export_to_xml() - - settings = openmc.Settings() - settings.batches = 4 - settings.inactive = 0 - settings.particles = 100 - settings.source = openmc.Source(space=openmc.stats.Point()) - settings.export_to_xml() - - mats = openmc.Materials([fuel, porous_carbon, ipyc, sic, opyc, graphite]) - mats.export_to_xml() - - -def test_triso(): - harness = TRISOTestHarness('statepoint.4.h5') - harness.main() diff --git a/tests/regression_tests/uniform_fs/__init__.py b/tests/regression_tests/uniform_fs/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/uniform_fs/geometry.xml b/tests/regression_tests/uniform_fs/geometry.xml deleted file mode 100644 index 90cf35461..000000000 --- a/tests/regression_tests/uniform_fs/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/uniform_fs/materials.xml b/tests/regression_tests/uniform_fs/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/uniform_fs/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/uniform_fs/results_true.dat b/tests/regression_tests/uniform_fs/results_true.dat deleted file mode 100644 index 050863cdf..000000000 --- a/tests/regression_tests/uniform_fs/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.634131E-01 6.507592E-03 diff --git a/tests/regression_tests/uniform_fs/settings.xml b/tests/regression_tests/uniform_fs/settings.xml deleted file mode 100644 index 3e6ef672f..000000000 --- a/tests/regression_tests/uniform_fs/settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - - - - 10 10 10 - -10. -10. -10. - 10. 10. 10. - - - diff --git a/tests/regression_tests/uniform_fs/test.py b/tests/regression_tests/uniform_fs/test.py deleted file mode 100644 index 64d997909..000000000 --- a/tests/regression_tests/uniform_fs/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_uniform_fs(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/universe/__init__.py b/tests/regression_tests/universe/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/universe/geometry.xml b/tests/regression_tests/universe/geometry.xml deleted file mode 100644 index 03f507bec..000000000 --- a/tests/regression_tests/universe/geometry.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/regression_tests/universe/materials.xml b/tests/regression_tests/universe/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/universe/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/universe/results_true.dat b/tests/regression_tests/universe/results_true.dat deleted file mode 100644 index 5cb3925a6..000000000 --- a/tests/regression_tests/universe/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.943619E-01 3.309646E-03 diff --git a/tests/regression_tests/universe/settings.xml b/tests/regression_tests/universe/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/universe/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/universe/test.py b/tests/regression_tests/universe/test.py deleted file mode 100644 index d5ed9645b..000000000 --- a/tests/regression_tests/universe/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_universe(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/regression_tests/void/__init__.py b/tests/regression_tests/void/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/void/inputs_true.dat b/tests/regression_tests/void/inputs_true.dat deleted file mode 100644 index 644952097..000000000 --- a/tests/regression_tests/void/inputs_true.dat +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fixed source - 1000 - 3 - - - 0.0 0.0 0.0 - - - - - - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 - - - 1 - total - - diff --git a/tests/regression_tests/void/results_true.dat b/tests/regression_tests/void/results_true.dat deleted file mode 100644 index ec87df3ba..000000000 --- a/tests/regression_tests/void/results_true.dat +++ /dev/null @@ -1,103 +0,0 @@ -tally 1: -8.636087E-01 -2.486134E-01 -0.000000E+00 -0.000000E+00 -2.848447E+00 -2.704761E+00 -0.000000E+00 -0.000000E+00 -3.944691E+00 -5.195294E+00 -0.000000E+00 -0.000000E+00 -4.822264E+00 -7.764351E+00 -0.000000E+00 -0.000000E+00 -5.295627E+00 -9.359046E+00 -0.000000E+00 -0.000000E+00 -5.331702E+00 -9.480054E+00 -0.000000E+00 -0.000000E+00 -5.598029E+00 -1.044833E+01 -0.000000E+00 -0.000000E+00 -5.803138E+00 -1.124136E+01 -0.000000E+00 -0.000000E+00 -5.768440E+00 -1.110547E+01 -0.000000E+00 -0.000000E+00 -5.554687E+00 -1.029492E+01 -0.000000E+00 -0.000000E+00 -5.503880E+00 -1.011832E+01 -0.000000E+00 -0.000000E+00 -5.059080E+00 -8.564408E+00 -0.000000E+00 -0.000000E+00 -4.718153E+00 -7.431929E+00 -0.000000E+00 -0.000000E+00 -4.575826E+00 -6.980348E+00 -0.000000E+00 -0.000000E+00 -4.283929E+00 -6.120164E+00 -0.000000E+00 -0.000000E+00 -3.997971E+00 -5.330979E+00 -0.000000E+00 -0.000000E+00 -3.735927E+00 -4.653022E+00 -0.000000E+00 -0.000000E+00 -3.302545E+00 -3.645387E+00 -0.000000E+00 -0.000000E+00 -3.082630E+00 -3.203343E+00 -0.000000E+00 -0.000000E+00 -2.775434E+00 -2.569844E+00 -0.000000E+00 -0.000000E+00 -2.518170E+00 -2.134420E+00 -0.000000E+00 -0.000000E+00 -2.233921E+00 -1.666795E+00 -0.000000E+00 -0.000000E+00 -1.829991E+00 -1.118883E+00 -0.000000E+00 -0.000000E+00 -1.420528E+00 -6.755061E-01 -0.000000E+00 -0.000000E+00 -9.856494E-01 -3.253539E-01 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 diff --git a/tests/regression_tests/void/test.py b/tests/regression_tests/void/test.py deleted file mode 100644 index af1e3887b..000000000 --- a/tests/regression_tests/void/test.py +++ /dev/null @@ -1,39 +0,0 @@ -import numpy as np -import openmc -import pytest - -from tests.testing_harness import PyAPITestHarness - -@pytest.fixture -def model(): - model = openmc.model.Model() - - zn = openmc.Material() - zn.set_density('g/cm3', 7.14) - zn.add_nuclide('Zn64', 1.0) - model.materials.append(zn) - - radii = np.linspace(1.0, 100.0) - surfs = [openmc.Sphere(r=r) for r in radii] - surfs[-1].boundary_type = 'vacuum' - cells = [openmc.Cell(fill=(zn if i % 2 == 0 else None), region=region) - for i, region in enumerate(openmc.model.subdivide(surfs))] - model.geometry = openmc.Geometry(cells) - - model.settings.run_mode = 'fixed source' - model.settings.batches = 3 - model.settings.particles = 1000 - model.settings.source = openmc.Source(space=openmc.stats.Point()) - - cell_filter = openmc.CellFilter(cells) - tally = openmc.Tally() - tally.filters = [cell_filter] - tally.scores = ['total'] - model.tallies.append(tally) - - return model - - -def test_void(model): - harness = PyAPITestHarness('statepoint.3.h5', model) - harness.main() diff --git a/tests/regression_tests/volume_calc/__init__.py b/tests/regression_tests/volume_calc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/volume_calc/inputs_true.dat b/tests/regression_tests/volume_calc/inputs_true.dat deleted file mode 100644 index 607921af2..000000000 --- a/tests/regression_tests/volume_calc/inputs_true.dat +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - volume - - cell - 1 2 3 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - material - 1 2 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - - universe - 0 - 100000 - -1.0 -1.0 -6.0 - 1.0 1.0 6.0 - - diff --git a/tests/regression_tests/volume_calc/results_true.dat b/tests/regression_tests/volume_calc/results_true.dat deleted file mode 100644 index 466139cd6..000000000 --- a/tests/regression_tests/volume_calc/results_true.dat +++ /dev/null @@ -1,30 +0,0 @@ -Volume calculation 0 -Domain 1: 31.47+/-0.07 cm^3 -Domain 2: 2.093+/-0.031 cm^3 -Domain 3: 2.049+/-0.031 cm^3 - Cell Nuclide Atoms -0 1 U235 (3.482+/-0.008)e+23 -1 1 Mo99 (3.482+/-0.008)e+22 -2 2 H1 (1.400+/-0.021)e+23 -3 2 O16 (7.00+/-0.10)e+22 -4 2 B10 (7.00+/-0.10)e+18 -5 3 H1 (1.370+/-0.021)e+23 -6 3 O16 (6.85+/-0.10)e+22 -7 3 B10 (6.85+/-0.10)e+18 -Volume calculation 1 -Domain 1: 4.14+/-0.04 cm^3 -Domain 2: 31.47+/-0.07 cm^3 - Material Nuclide Atoms -0 1 H1 (2.770+/-0.029)e+23 -1 1 O16 (1.385+/-0.014)e+23 -2 1 B10 (1.385+/-0.014)e+19 -3 2 U235 (3.482+/-0.008)e+23 -4 2 Mo99 (3.482+/-0.008)e+22 -Volume calculation 2 -Domain 0: 35.61+/-0.07 cm^3 - Universe Nuclide Atoms -0 0 H1 (2.770+/-0.029)e+23 -1 0 O16 (1.385+/-0.014)e+23 -2 0 B10 (1.385+/-0.014)e+19 -3 0 U235 (3.482+/-0.008)e+23 -4 0 Mo99 (3.482+/-0.008)e+22 diff --git a/tests/regression_tests/volume_calc/test.py b/tests/regression_tests/volume_calc/test.py deleted file mode 100644 index 8ea4ab04e..000000000 --- a/tests/regression_tests/volume_calc/test.py +++ /dev/null @@ -1,77 +0,0 @@ -import os -import glob -import sys - -import openmc - -from tests.testing_harness import PyAPITestHarness - - -class VolumeTest(PyAPITestHarness): - def _build_inputs(self): - # Define materials - water = openmc.Material(1) - water.add_nuclide('H1', 2.0) - water.add_nuclide('O16', 1.0) - water.add_nuclide('B10', 0.0001) - water.add_s_alpha_beta('c_H_in_H2O') - water.set_density('g/cc', 1.0) - - fuel = openmc.Material(2) - fuel.add_nuclide('U235', 1.0) - fuel.add_nuclide('Mo99', 0.1) - fuel.set_density('g/cc', 4.5) - - materials = openmc.Materials((water, fuel)) - materials.export_to_xml() - - cyl = openmc.ZCylinder(surface_id=1, r=1.0, boundary_type='vacuum') - top_sphere = openmc.Sphere(surface_id=2, z0=5., r=1., boundary_type='vacuum') - top_plane = openmc.ZPlane(surface_id=3, z0=5.) - bottom_sphere = openmc.Sphere(surface_id=4, z0=-5., r=1., boundary_type='vacuum') - bottom_plane = openmc.ZPlane(surface_id=5, z0=-5.) - - # Define geometry - inside_cyl = openmc.Cell(1, fill=fuel, region=-cyl & -top_plane & +bottom_plane) - top_hemisphere = openmc.Cell(2, fill=water, region=-top_sphere & +top_plane) - bottom_hemisphere = openmc.Cell(3, fill=water, region=-bottom_sphere & -top_plane) - root = openmc.Universe(0, cells=(inside_cyl, top_hemisphere, bottom_hemisphere)) - - geometry = openmc.Geometry(root) - geometry.export_to_xml() - - # Set up stochastic volume calculation - ll, ur = root.bounding_box - vol_calcs = [ - openmc.VolumeCalculation(list(root.cells.values()), 100000), - openmc.VolumeCalculation([water, fuel], 100000, ll, ur), - openmc.VolumeCalculation([root], 100000, ll, ur) - ] - - # Define settings - settings = openmc.Settings() - settings.run_mode = 'volume' - settings.volume_calculations = vol_calcs - settings.export_to_xml() - - def _get_results(self): - outstr = '' - for i, filename in enumerate(sorted(glob.glob('volume_*.h5'))): - outstr += 'Volume calculation {}\n'.format(i) - - # Read volume calculation results - volume_calc = openmc.VolumeCalculation.from_hdf5(filename) - - # Write cell volumes and total # of atoms for each nuclide - for uid, volume in sorted(volume_calc.volumes.items()): - outstr += 'Domain {}: {} cm^3\n'.format(uid, volume) - outstr += str(volume_calc.atoms_dataframe) + '\n' - - return outstr - - def _test_output_created(self): - pass - -def test_volume_calc(): - harness = VolumeTest('') - harness.main() diff --git a/tests/regression_tests/white_plane/__init__.py b/tests/regression_tests/white_plane/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/regression_tests/white_plane/geometry.xml b/tests/regression_tests/white_plane/geometry.xml deleted file mode 100644 index b8be4b59d..000000000 --- a/tests/regression_tests/white_plane/geometry.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/regression_tests/white_plane/materials.xml b/tests/regression_tests/white_plane/materials.xml deleted file mode 100644 index 2472a7471..000000000 --- a/tests/regression_tests/white_plane/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/white_plane/results_true.dat b/tests/regression_tests/white_plane/results_true.dat deleted file mode 100644 index b80361ced..000000000 --- a/tests/regression_tests/white_plane/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -2.268730E+00 4.470768E-03 diff --git a/tests/regression_tests/white_plane/settings.xml b/tests/regression_tests/white_plane/settings.xml deleted file mode 100644 index 70b4e802f..000000000 --- a/tests/regression_tests/white_plane/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/white_plane/test.py b/tests/regression_tests/white_plane/test.py deleted file mode 100644 index 223f4e5e6..000000000 --- a/tests/regression_tests/white_plane/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from tests.testing_harness import TestHarness - - -def test_white_plane(): - harness = TestHarness('statepoint.10.h5') - harness.main() diff --git a/tests/testing_harness.py b/tests/testing_harness.py deleted file mode 100644 index 0d3c4bec0..000000000 --- a/tests/testing_harness.py +++ /dev/null @@ -1,348 +0,0 @@ -from difflib import unified_diff -import filecmp -import glob -import hashlib -from optparse import OptionParser -import os -import shutil -import sys - -import numpy as np -import openmc -from openmc.examples import pwr_core - -from tests.regression_tests import config - - -class TestHarness(object): - """General class for running OpenMC regression tests.""" - - def __init__(self, statepoint_name): - self._sp_name = statepoint_name - - def main(self): - """Accept commandline arguments and either run or update tests.""" - if config['update']: - self.update_results() - else: - self.execute_test() - - def execute_test(self): - """Run OpenMC with the appropriate arguments and check the outputs.""" - try: - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Update the results_true using the current version of OpenMC.""" - try: - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - def _run_openmc(self): - if config['mpi']: - mpi_args = [config['mpiexec'], '-n', config['mpi_np']] - openmc.run(openmc_exec=config['exe'], mpi_args=mpi_args) - else: - openmc.run(openmc_exec=config['exe']) - - def _test_output_created(self): - """Make sure statepoint.* and tallies.out have been created.""" - statepoint = glob.glob(self._sp_name) - assert len(statepoint) == 1, 'Either multiple or no statepoint files' \ - ' exist.' - assert statepoint[0].endswith('h5'), \ - 'Statepoint file is not a HDF5 file.' - if os.path.exists('tallies.xml'): - assert os.path.exists('tallies.out'), \ - 'Tally output file does not exist.' - - def _get_results(self, hash_output=False): - """Digest info in the statepoint and return as a string.""" - # Read the statepoint file. - statepoint = glob.glob(self._sp_name)[0] - with openmc.StatePoint(statepoint) as sp: - outstr = '' - if sp.run_mode == 'eigenvalue': - # Write out k-combined. - outstr += 'k-combined:\n' - form = '{0:12.6E} {1:12.6E}\n' - outstr += form.format(sp.k_combined.n, sp.k_combined.s) - - # Write out tally data. - for i, tally_ind in enumerate(sp.tallies): - tally = sp.tallies[tally_ind] - results = np.zeros((tally.sum.size * 2, )) - results[0::2] = tally.sum.ravel() - results[1::2] = tally.sum_sq.ravel() - results = ['{0:12.6E}'.format(x) for x in results] - - outstr += 'tally {}:\n'.format(i + 1) - outstr += '\n'.join(results) + '\n' - - # Hash the results if necessary. - if hash_output: - sha512 = hashlib.sha512() - sha512.update(outstr.encode('utf-8')) - outstr = sha512.hexdigest() - - return outstr - - def _write_results(self, results_string): - """Write the results to an ASCII file.""" - with open('results_test.dat', 'w') as fh: - fh.write(results_string) - - def _overwrite_results(self): - """Overwrite the results_true with the results_test.""" - shutil.copyfile('results_test.dat', 'results_true.dat') - - def _compare_results(self): - """Make sure the current results agree with the _true standard.""" - compare = filecmp.cmp('results_test.dat', 'results_true.dat') - if not compare: - os.rename('results_test.dat', 'results_error.dat') - assert compare, 'Results do not agree.' - - def _cleanup(self): - """Delete statepoints, tally, and test files.""" - output = glob.glob('statepoint.*.h5') - output += ['tallies.out', 'results_test.dat', 'summary.h5'] - output += glob.glob('volume_*.h5') - for f in output: - if os.path.exists(f): - os.remove(f) - - -class HashedTestHarness(TestHarness): - """Specialized TestHarness that hashes the results.""" - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - return super()._get_results(True) - - -class CMFDTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC CMFD tests.""" - - def __init__(self, statepoint_name, cmfd_run): - super().__init__(statepoint_name) - self._create_cmfd_result_str(cmfd_run) - - def _create_cmfd_result_str(self, cmfd_run): - """Create CMFD result string from variables of CMFDRun instance""" - outstr = 'cmfd indices\n' - outstr += '\n'.join(['{:.6E}'.format(x) for x in cmfd_run.indices]) - outstr += '\nk cmfd\n' - outstr += '\n'.join(['{:.6E}'.format(x) for x in cmfd_run.k_cmfd]) - outstr += '\ncmfd entropy\n' - outstr += '\n'.join(['{:.6E}'.format(x) for x in cmfd_run.entropy]) - outstr += '\ncmfd balance\n' - outstr += '\n'.join(['{:.5E}'.format(x) for x in cmfd_run.balance]) - outstr += '\ncmfd dominance ratio\n' - outstr += '\n'.join(['{:.3E}'.format(x) for x in cmfd_run.dom]) - outstr += '\ncmfd openmc source comparison\n' - outstr += '\n'.join(['{:.6E}'.format(x) for x in cmfd_run.src_cmp]) - outstr += '\ncmfd source\n' - cmfdsrc = np.reshape(cmfd_run.cmfd_src, np.product(cmfd_run.indices), - order='F') - outstr += '\n'.join(['{:.6E}'.format(x) for x in cmfdsrc]) - outstr += '\n' - self._cmfdrun_results = outstr - - def execute_test(self): - """Don't call _run_openmc as OpenMC will be called through C API for - CMFD tests, and write CMFD results that were passsed as argument - - """ - try: - self._test_output_created() - results = self._get_results() - results += self._cmfdrun_results - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Don't call _run_openmc as OpenMC will be called through C API for - CMFD tests, and write CMFD results that were passsed as argument - - """ - try: - self._test_output_created() - results = self._get_results() - results += self._cmfdrun_results - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - def _cleanup(self): - """Delete output files for numpy matrices and flux vectors.""" - super()._cleanup() - output = ['loss.npz', 'loss.dat', 'prod.npz', 'prod.dat', - 'fluxvec.npy', 'fluxvec.dat'] - for f in output: - if os.path.exists(f): - os.remove(f) - - -class ParticleRestartTestHarness(TestHarness): - """Specialized TestHarness for running OpenMC particle restart tests.""" - - def _run_openmc(self): - # Set arguments - args = {'openmc_exec': config['exe']} - if config['mpi']: - args['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] - - # Initial run - openmc.run(**args) - - # Run particle restart - args.update({'restart_file': self._sp_name}) - openmc.run(**args) - - def _test_output_created(self): - """Make sure the restart file has been created.""" - particle = glob.glob(self._sp_name) - assert len(particle) == 1, 'Either multiple or no particle restart ' \ - 'files exist.' - assert particle[0].endswith('h5'), \ - 'Particle restart file is not a HDF5 file.' - - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - # Read the particle restart file. - particle = glob.glob(self._sp_name)[0] - p = openmc.Particle(particle) - - # Write out the properties. - outstr = '' - outstr += 'current batch:\n' - outstr += "{0:12.6E}\n".format(p.current_batch) - outstr += 'current generation:\n' - outstr += "{0:12.6E}\n".format(p.current_generation) - outstr += 'particle id:\n' - outstr += "{0:12.6E}\n".format(p.id) - outstr += 'run mode:\n' - outstr += "{0}\n".format(p.run_mode) - outstr += 'particle weight:\n' - outstr += "{0:12.6E}\n".format(p.weight) - outstr += 'particle energy:\n' - outstr += "{0:12.6E}\n".format(p.energy) - outstr += 'particle xyz:\n' - outstr += "{0:12.6E} {1:12.6E} {2:12.6E}\n".format(p.xyz[0], p.xyz[1], - p.xyz[2]) - outstr += 'particle uvw:\n' - outstr += "{0:12.6E} {1:12.6E} {2:12.6E}\n".format(p.uvw[0], p.uvw[1], - p.uvw[2]) - - return outstr - - -class PyAPITestHarness(TestHarness): - def __init__(self, statepoint_name, model=None): - super().__init__(statepoint_name) - if model is None: - self._model = pwr_core() - else: - self._model = model - self._model.plots = [] - - - def main(self): - """Accept commandline arguments and either run or update tests.""" - if config['build_inputs']: - self._build_inputs() - elif config['update']: - self.update_results() - else: - self.execute_test() - - def execute_test(self): - """Build input XMLs, run OpenMC, and verify correct results.""" - try: - self._build_inputs() - inputs = self._get_inputs() - self._write_inputs(inputs) - self._compare_inputs() - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._compare_results() - finally: - self._cleanup() - - def update_results(self): - """Update results_true.dat and inputs_true.dat""" - try: - self._build_inputs() - inputs = self._get_inputs() - self._write_inputs(inputs) - self._overwrite_inputs() - self._run_openmc() - self._test_output_created() - results = self._get_results() - self._write_results(results) - self._overwrite_results() - finally: - self._cleanup() - - def _build_inputs(self): - """Write input XML files.""" - self._model.export_to_xml() - - def _get_inputs(self): - """Return a hash digest of the input XML files.""" - xmls = ['geometry.xml', 'materials.xml', 'settings.xml', - 'tallies.xml', 'plots.xml'] - return ''.join([open(fname).read() for fname in xmls - if os.path.exists(fname)]) - - def _write_inputs(self, input_digest): - """Write the digest of the input XMLs to an ASCII file.""" - with open('inputs_test.dat', 'w') as fh: - fh.write(input_digest) - - def _overwrite_inputs(self): - """Overwrite inputs_true.dat with inputs_test.dat""" - shutil.copyfile('inputs_test.dat', 'inputs_true.dat') - - def _compare_inputs(self): - """Make sure the current inputs agree with the _true standard.""" - compare = filecmp.cmp('inputs_test.dat', 'inputs_true.dat') - if not compare: - os.rename('inputs_test.dat', 'inputs_error.dat') - for line in unified_diff(open('inputs_true.dat', 'r').readlines(), - open('inputs_error.dat', 'r').readlines(), - 'inputs_true.dat', 'inputs_error.dat'): - print(line, end='') - assert compare, 'Input files are broken.' - - def _cleanup(self): - """Delete XMLs, statepoints, tally, and test files.""" - super()._cleanup() - output = ['materials.xml', 'geometry.xml', 'settings.xml', - 'tallies.xml', 'plots.xml', 'inputs_test.dat'] - for f in output: - if os.path.exists(f): - os.remove(f) - - -class HashedPyAPITestHarness(PyAPITestHarness): - def _get_results(self): - """Digest info in the statepoint and return as a string.""" - return super()._get_results(True) diff --git a/tests/unit_tests/__init__.py b/tests/unit_tests/__init__.py deleted file mode 100644 index e97ab13e2..000000000 --- a/tests/unit_tests/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -import shutil - -import numpy as np -import pytest - - -# Check if NJOY is available -needs_njoy = pytest.mark.skipif(shutil.which('njoy') is None, - reason="NJOY not installed") - - -def assert_unbounded(obj): - """Assert that a region/cell is unbounded.""" - ll, ur = obj.bounding_box - assert ll == pytest.approx((-np.inf, -np.inf, -np.inf)) - assert ur == pytest.approx((np.inf, np.inf, np.inf)) diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py deleted file mode 100644 index 926535a9c..000000000 --- a/tests/unit_tests/conftest.py +++ /dev/null @@ -1,124 +0,0 @@ -import openmc -import pytest - -from tests.regression_tests import config - - -@pytest.fixture(scope='module') -def mpi_intracomm(): - if config['mpi']: - from mpi4py import MPI - return MPI.COMM_WORLD - else: - return None - - -@pytest.fixture(scope='module') -def uo2(): - m = openmc.Material(material_id=100, name='UO2') - m.add_nuclide('U235', 1.0) - m.add_nuclide('O16', 2.0) - m.set_density('g/cm3', 10.0) - m.depletable = True - return m - - -@pytest.fixture(scope='module') -def water(): - m = openmc.Material(name='light water') - m.add_nuclide('H1', 2.0) - m.add_nuclide('O16', 1.0) - m.set_density('g/cm3', 1.0) - m.add_s_alpha_beta('c_H_in_H2O') - return m - - -@pytest.fixture(scope='module') -def sphere_model(): - model = openmc.model.Model() - m = openmc.Material() - m.add_nuclide('U235', 1.0) - m.set_density('g/cm3', 1.0) - model.materials.append(m) - - sph = openmc.Sphere(boundary_type='vacuum') - c = openmc.Cell(fill=m, region=-sph) - model.geometry.root_universe = openmc.Universe(cells=[c]) - - model.settings.particles = 100 - model.settings.batches = 10 - model.settings.run_mode = 'fixed source' - model.settings.source = openmc.Source(space=openmc.stats.Point()) - return model - - -@pytest.fixture -def cell_with_lattice(): - m_inside = [openmc.Material(), openmc.Material(), None, openmc.Material()] - m_outside = openmc.Material() - - cyl = openmc.ZCylinder(r=1.0) - inside_cyl = openmc.Cell(fill=m_inside, region=-cyl) - outside_cyl = openmc.Cell(fill=m_outside, region=+cyl) - univ = openmc.Universe(cells=[inside_cyl, outside_cyl]) - - lattice = openmc.RectLattice(name='My Lattice') - lattice.lower_left = (-4.0, -4.0) - lattice.pitch = (4.0, 4.0) - lattice.universes = [[univ, univ], [univ, univ]] - main_cell = openmc.Cell(fill=lattice) - - return ([inside_cyl, outside_cyl, main_cell], - [m_inside[0], m_inside[1], m_inside[3], m_outside], - univ, lattice) - -@pytest.fixture -def mixed_lattice_model(uo2, water): - cyl = openmc.ZCylinder(r=0.4) - c1 = openmc.Cell(fill=uo2, region=-cyl) - c1.temperature = 600.0 - c2 = openmc.Cell(fill=water, region=+cyl) - pin = openmc.Universe(cells=[c1, c2]) - - empty = openmc.Cell() - empty_univ = openmc.Universe(cells=[empty]) - - hex_lattice = openmc.HexLattice() - hex_lattice.center = (0.0, 0.0) - hex_lattice.pitch = (1.2, 10.0) - outer_ring = [pin]*6 - inner_ring = [empty_univ] - axial_level = [outer_ring, inner_ring] - hex_lattice.universes = [axial_level]*3 - hex_lattice.outer = empty_univ - - cell_hex = openmc.Cell(fill=hex_lattice) - u = openmc.Universe(cells=[cell_hex]) - rotated_cell_hex = openmc.Cell(fill=u) - rotated_cell_hex.rotation = (0., 0., 30.) - ur = openmc.Universe(cells=[rotated_cell_hex]) - - d = 6.0 - rect_lattice = openmc.RectLattice() - rect_lattice.lower_left = (-d, -d) - rect_lattice.pitch = (d, d) - rect_lattice.outer = empty_univ - rect_lattice.universes = [ - [ur, empty_univ], - [empty_univ, u] - ] - - xmin = openmc.XPlane(-d, 'periodic') - xmax = openmc.XPlane(d, 'periodic') - xmin.periodic_surface = xmax - ymin = openmc.YPlane(-d, 'periodic') - ymax = openmc.YPlane(d, 'periodic') - main_cell = openmc.Cell(fill=rect_lattice, - region=+xmin & -xmax & +ymin & -ymax) - - # Create geometry and use unique material in each fuel cell - geometry = openmc.Geometry([main_cell]) - geometry.determine_paths() - c1.fill = [water.clone() for i in range(c1.num_instances)] - - return openmc.model.Model(geometry) diff --git a/tests/unit_tests/dagmc/__init__.py b/tests/unit_tests/dagmc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/unit_tests/dagmc/dagmc.h5m b/tests/unit_tests/dagmc/dagmc.h5m deleted file mode 120000 index 0c5ab5da8..000000000 --- a/tests/unit_tests/dagmc/dagmc.h5m +++ /dev/null @@ -1 +0,0 @@ -../../regression_tests/dagmc/legacy/dagmc.h5m \ No newline at end of file diff --git a/tests/unit_tests/dagmc/test.py b/tests/unit_tests/dagmc/test.py deleted file mode 100644 index f7b2844f6..000000000 --- a/tests/unit_tests/dagmc/test.py +++ /dev/null @@ -1,74 +0,0 @@ -import shutil - -import numpy as np -import pytest - -import openmc -import openmc.lib - -from tests import cdtemp - -pytestmark = pytest.mark.skipif( - not openmc.lib._dagmc_enabled(), - reason="DAGMC CAD geometry is not enabled.") - - -@pytest.fixture(scope="module", autouse=True) -def dagmc_model(request): - - model = openmc.model.Model() - - # settings - model.settings.batches = 5 - model.settings.inactive = 0 - model.settings.particles = 100 - model.settings.temperature = {'tolerance': 50.0} - model.settings.verbosity = 1 - source_box = openmc.stats.Box([ -4, -4, -4 ], - [ 4, 4, 4 ]) - source = openmc.Source(space=source_box) - model.settings.source = source - - model.settings.dagmc = True - - # tally - tally = openmc.Tally() - tally.scores = ['total'] - tally.filters = [openmc.CellFilter(1)] - model.tallies = [tally] - - # materials - u235 = openmc.Material(name="fuel") - u235.add_nuclide('U235', 1.0, 'ao') - u235.set_density('g/cc', 11) - u235.id = 40 - u235.temperature = 320 - - water = openmc.Material(name="water") - water.add_nuclide('H1', 2.0, 'ao') - water.add_nuclide('O16', 1.0, 'ao') - water.set_density('g/cc', 1.0) - water.add_s_alpha_beta('c_H_in_H2O') - water.id = 41 - - mats = openmc.Materials([u235, water]) - model.materials = mats - - # location of dagmc file in test directory - dagmc_file = request.fspath.dirpath() + "/dagmc.h5m" - # move to a temporary directory - with cdtemp(): - shutil.copyfile(dagmc_file, "./dagmc.h5m") - model.export_to_xml() - openmc.lib.init() - yield - - openmc.lib.finalize() - - -@pytest.mark.parametrize("cell_id,exp_temp", ((1, 320.0), # assigned by material - (2, 300.0), # assigned in dagmc file - (3, 293.6))) # assigned by default -def test_dagmc_temperatures(cell_id, exp_temp): - cell = openmc.lib.cells[cell_id] - assert np.isclose(cell.get_temperature(), exp_temp) diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py deleted file mode 100644 index d01d94a32..000000000 --- a/tests/unit_tests/test_cell.py +++ /dev/null @@ -1,168 +0,0 @@ -import xml.etree. ElementTree as ET - -import numpy as np -import openmc -import pytest - -from tests.unit_tests import assert_unbounded - - -def test_contains(): - # Cell with specified region - s = openmc.XPlane() - c = openmc.Cell(region=+s) - assert (1.0, 0.0, 0.0) in c - assert (-1.0, 0.0, 0.0) not in c - - # Cell with no region - c = openmc.Cell() - assert (10.0, -4., 2.0) in c - - -def test_repr(cell_with_lattice): - cells, mats, univ, lattice = cell_with_lattice - repr(cells[0]) # cell with distributed materials - repr(cells[1]) # cell with material - repr(cells[2]) # cell with lattice - - # Empty cell - c = openmc.Cell() - repr(c) - - -def test_bounding_box(): - zcyl = openmc.ZCylinder() - c = openmc.Cell(region=-zcyl) - ll, ur = c.bounding_box - assert ll == pytest.approx((-1., -1., -np.inf)) - assert ur == pytest.approx((1., 1., np.inf)) - - # Cell with no region specified - c = openmc.Cell() - assert_unbounded(c) - - -def test_clone(): - m = openmc.Material() - cyl = openmc.ZCylinder() - c = openmc.Cell(fill=m, region=-cyl) - c.temperature = 650. - - c2 = c.clone() - assert c2.id != c.id - assert c2.fill != c.fill - assert c2.region != c.region - assert c2.temperature == c.temperature - - -def test_temperature(cell_with_lattice): - # Make sure temperature propagates through universes - m = openmc.Material() - s = openmc.XPlane() - c1 = openmc.Cell(fill=m, region=+s) - c2 = openmc.Cell(fill=m, region=-s) - u1 = openmc.Universe(cells=[c1, c2]) - c = openmc.Cell(fill=u1) - - c.temperature = 400.0 - assert c1.temperature == 400.0 - assert c2.temperature == 400.0 - with pytest.raises(ValueError): - c.temperature = -100. - - # distributed temperature - cells, _, _, _ = cell_with_lattice - c = cells[0] - c.temperature = (300., 600., 900.) - - -def test_rotation(): - u = openmc.Universe() - c = openmc.Cell(fill=u) - c.rotation = (180.0, 0.0, 0.0) - assert np.allclose(c.rotation_matrix, [ - [1., 0., 0.], - [0., -1., 0.], - [0., 0., -1.] - ]) - - c.rotation = (0.0, 90.0, 0.0) - assert np.allclose(c.rotation_matrix, [ - [0., 0., -1.], - [0., 1., 0.], - [1., 0., 0.] - ]) - - -def test_get_nuclides(uo2): - c = openmc.Cell(fill=uo2) - nucs = c.get_nuclides() - assert nucs == ['U235', 'O16'] - - -def test_nuclide_densities(uo2): - c = openmc.Cell(fill=uo2) - expected_nucs = ['U235', 'O16'] - expected_density = [1.0, 2.0] - tuples = list(c.get_nuclide_densities().values()) - for nuc, density, t in zip(expected_nucs, expected_density, tuples): - assert nuc == t[0] - assert density == t[1] - - # Empty cell - c = openmc.Cell() - assert not c.get_nuclide_densities() - - -def test_get_all_universes(cell_with_lattice): - # Cell with nested universes - c1 = openmc.Cell() - u1 = openmc.Universe(cells=[c1]) - c2 = openmc.Cell(fill=u1) - u2 = openmc.Universe(cells=[c2]) - c3 = openmc.Cell(fill=u2) - univs = set(c3.get_all_universes().values()) - assert not (univs ^ {u1, u2}) - - # Cell with lattice - cells, mats, univ, lattice = cell_with_lattice - univs = set(cells[-1].get_all_universes().values()) - assert not (univs ^ {univ}) - - -def test_get_all_materials(cell_with_lattice): - # Normal cell - m = openmc.Material() - c = openmc.Cell(fill=m) - test_mats = set(c.get_all_materials().values()) - assert not(test_mats ^ {m}) - - # Cell filled with distributed materials - cells, mats, univ, lattice = cell_with_lattice - c = cells[0] - test_mats = set(c.get_all_materials().values()) - assert not (test_mats ^ set(m for m in c.fill if m is not None)) - - # Cell filled with universe - c = cells[-1] - test_mats = set(c.get_all_materials().values()) - assert not (test_mats ^ set(mats)) - - -def test_to_xml_element(cell_with_lattice): - cells, mats, univ, lattice = cell_with_lattice - - c = cells[-1] - root = ET.Element('geometry') - elem = c.create_xml_subelement(root) - assert elem.tag == 'cell' - assert elem.get('id') == str(c.id) - assert elem.get('region') is None - surf_elem = root.find('surface') - assert surf_elem.get('id') == str(cells[0].region.surface.id) - - c = cells[0] - c.temperature = 900.0 - elem = c.create_xml_subelement(root) - assert elem.get('region') == str(c.region) - assert elem.get('temperature') == str(c.temperature) diff --git a/tests/unit_tests/test_complex_cell_bb.py b/tests/unit_tests/test_complex_cell_bb.py deleted file mode 100644 index 8db20f05c..000000000 --- a/tests/unit_tests/test_complex_cell_bb.py +++ /dev/null @@ -1,98 +0,0 @@ -import numpy as np -import openmc.lib -import pytest - -@pytest.fixture(autouse=True) -def complex_cell(run_in_tmpdir, mpi_intracomm): - - openmc.reset_auto_ids() - - model = openmc.model.Model() - - u235 = openmc.Material() - u235.set_density('g/cc', 4.5) - u235.add_nuclide("U235", 1.0) - - u238 = openmc.Material() - u238.set_density('g/cc', 4.5) - u238.add_nuclide("U238", 1.0) - - zr90 = openmc.Material() - zr90.set_density('g/cc', 2.0) - zr90.add_nuclide("Zr90", 1.0) - - n14 = openmc.Material() - n14.set_density('g/cc', 0.1) - n14.add_nuclide("N14", 1.0) - - model.materials = (u235, u238, zr90, n14) - - s1 = openmc.XPlane(-10.0, 'vacuum') - s2 = openmc.XPlane(-7.0) - s3 = openmc.XPlane(-4.0) - s4 = openmc.XPlane(4.0) - s5 = openmc.XPlane(7.0) - s6 = openmc.XPlane(10.0, 'vacuum') - s7 = openmc.XPlane(0.0) - - s11 = openmc.YPlane(-10.0, 'vacuum') - s12 = openmc.YPlane(-7.0) - s13 = openmc.YPlane(-4.0) - s14 = openmc.YPlane(4.0) - s15 = openmc.YPlane(7.0) - s16 = openmc.YPlane(10.0, 'vacuum') - s17 = openmc.YPlane(0.0) - - c1 = openmc.Cell(fill=u235) - c1.region = ~(-s3 | +s4 | ~(+s13 & -s14)) - - c2 = openmc.Cell(fill=u238) - c2.region = ~(+s3 & -s4 & +s13 & -s14) & +s2 & -s5 & +s12 & -s15 - - c3 = openmc.Cell(fill=zr90) - c3.region = ((+s1 & -s7 & +s17 & -s16) | (+s7 & -s6 & +s11 & -s17)) \ - & (-s2 | +s5 | -s12 | +s15) - - c4 = openmc.Cell(fill=n14) - c4.region = ((+s1 & -s7 & +s11 & -s17) | (+s7 & -s6 & +s17 & -s16)) & \ - ~(+s2 & -s5 & +s12 & -s15) - - c5 = openmc.Cell(fill=n14) - c5.region = ~(+s1 & -s6 & +s11 & -s16) - - model.geometry.root_universe = openmc.Universe() - model.geometry.root_universe.add_cells([c1, c2, c3, c4, c5]) - - model.settings.batches = 10 - model.settings.inactive = 5 - model.settings.particles = 100 - model.settings.source = openmc.Source(space=openmc.stats.Box( - [-10., -10., -1.], [10., 10., 1.])) - - model.settings.verbosity = 1 - - model.export_to_xml() - - openmc.lib.finalize() - openmc.lib.init(intracomm=mpi_intracomm) - - yield - - openmc.lib.finalize() - - -expected_results = ( (1, (( -4., -4., -np.inf), - ( 4., 4., np.inf))), - (2, (( -7., -7., -np.inf), - ( 7., 7., np.inf))), - (3, ((-10., -10., -np.inf), - ( 10., 10., np.inf))), - (4, ((-10., -10., -np.inf), - ( 10., 10., np.inf))), - (5, ((-np.inf, -np.inf, -np.inf), - ( np.inf, np.inf, np.inf))) ) -@pytest.mark.parametrize("cell_id,expected_box", expected_results) -def test_cell_box(cell_id, expected_box): - cell_box = openmc.lib.cells[cell_id].bounding_box - assert tuple(cell_box[0]) == expected_box[0] - assert tuple(cell_box[1]) == expected_box[1] diff --git a/tests/unit_tests/test_data_decay.py b/tests/unit_tests/test_data_decay.py deleted file mode 100644 index 0cc793990..000000000 --- a/tests/unit_tests/test_data_decay.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python - -from collections.abc import Mapping -import os -from math import log - -import numpy as np -import pytest -from uncertainties import ufloat -import openmc.data - - -def ufloat_close(a, b): - assert a.nominal_value == pytest.approx(b.nominal_value) - assert a.std_dev == pytest.approx(b.std_dev) - - -@pytest.fixture(scope='module') -def nb90(): - """Nb90 decay data.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'decay', 'dec-041_Nb_090.endf') - return openmc.data.Decay.from_endf(filename) - - -@pytest.fixture(scope='module') -def u235_yields(): - """U235 fission product yield data.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'nfy', 'nfy-092_U_235.endf') - return openmc.data.FissionProductYields.from_endf(filename) - - -def test_nb90_halflife(nb90): - ufloat_close(nb90.half_life, ufloat(52560.0, 180.0)) - ufloat_close(nb90.decay_constant, log(2.)/nb90.half_life) - - -def test_nb90_nuclide(nb90): - assert nb90.nuclide['atomic_number'] == 41 - assert nb90.nuclide['mass_number'] == 90 - assert nb90.nuclide['isomeric_state'] == 0 - assert nb90.nuclide['parity'] == 1.0 - assert nb90.nuclide['spin'] == 8.0 - assert not nb90.nuclide['stable'] - assert nb90.nuclide['mass'] == pytest.approx(89.13888) - - -def test_nb90_modes(nb90): - assert len(nb90.modes) == 2 - ec = nb90.modes[0] - assert ec.modes == ['ec/beta+'] - assert ec.parent == 'Nb90' - assert ec.daughter == 'Zr90' - assert 'Nb90 -> Zr90' in str(ec) - ufloat_close(ec.branching_ratio, ufloat(0.0147633, 0.0003386195)) - ufloat_close(ec.energy, ufloat(6111000., 4000.)) - - # Make sure branching ratios sum to 1 - total = sum(m.branching_ratio for m in nb90.modes) - assert total.nominal_value == pytest.approx(1.0) - - -def test_nb90_spectra(nb90): - assert sorted(nb90.spectra.keys()) == ['e-', 'ec/beta+', 'gamma', 'xray'] - - -def test_fpy(u235_yields): - assert u235_yields.nuclide['atomic_number'] == 92 - assert u235_yields.nuclide['mass_number'] == 235 - assert u235_yields.nuclide['isomeric_state'] == 0 - assert u235_yields.nuclide['name'] == 'U235' - assert u235_yields.energies == pytest.approx([0.0253, 500.e3, 1.4e7]) - - assert len(u235_yields.cumulative) == 3 - thermal = u235_yields.cumulative[0] - ufloat_close(thermal['I135'], ufloat(0.0628187, 0.000879461)) - - assert len(u235_yields.independent) == 3 - thermal = u235_yields.independent[0] - ufloat_close(thermal['I135'], ufloat(0.0292737, 0.000819663)) diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py deleted file mode 100644 index 2585e9315..000000000 --- a/tests/unit_tests/test_data_misc.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python - -from collections.abc import Mapping -import os -from pathlib import Path - -import numpy as np -import pytest -import openmc.data - - -def test_data_library(tmpdir): - lib = openmc.data.DataLibrary.from_xml() - for f in lib.libraries: - assert sorted(f.keys()) == ['materials', 'path', 'type'] - - f = lib.get_by_material('U235') - assert f['type'] == 'neutron' - assert 'U235' in f['materials'] - - f = lib.get_by_material('c_H_in_H2O') - assert f['type'] == 'thermal' - assert 'c_H_in_H2O' in f['materials'] - - filename = str(tmpdir.join('test.xml')) - lib.export_to_xml(filename) - assert os.path.exists(filename) - - new_lib = openmc.data.DataLibrary() - directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) - new_lib.register_file(os.path.join(directory, 'H1.h5')) - assert new_lib.libraries[-1]['type'] == 'neutron' - new_lib.register_file(os.path.join(directory, 'c_Zr_in_ZrH.h5')) - assert new_lib.libraries[-1]['type'] == 'thermal' - - -def test_depletion_chain_data_library(run_in_tmpdir): - dep_lib = openmc.data.DataLibrary.from_xml() - prev_len = len(dep_lib.libraries) - chain_path = Path(__file__).parents[1] / "chain_simple.xml" - dep_lib.register_file(chain_path) - assert len(dep_lib.libraries) == prev_len + 1 - # Inspect - dep_dict = dep_lib.libraries[-1] - assert dep_dict['materials'] == [] - assert dep_dict['type'] == 'depletion_chain' - assert dep_dict['path'] == str(chain_path) - - out_path = "cross_section_chain.xml" - dep_lib.export_to_xml(out_path) - - dep_import = openmc.data.DataLibrary.from_xml(out_path) - for lib in reversed(dep_import.libraries): - if lib['type'] == 'depletion_chain': - break - else: - raise IndexError("depletion_chain not found in exported DataLibrary") - assert os.path.exists(lib['path']) - - -def test_linearize(): - """Test linearization of a continuous function.""" - x, y = openmc.data.linearize([-1., 1.], lambda x: 1 - x*x) - f = openmc.data.Tabulated1D(x, y) - assert f(-0.5) == pytest.approx(1 - 0.5*0.5, 0.001) - assert f(0.32) == pytest.approx(1 - 0.32*0.32, 0.001) - - -def test_thin(): - """Test thinning of a tabulated function.""" - x = np.linspace(0., 2*np.pi, 1000) - y = np.sin(x) - x_thin, y_thin = openmc.data.thin(x, y) - f = openmc.data.Tabulated1D(x_thin, y_thin) - assert f(1.0) == pytest.approx(np.sin(1.0), 0.001) - - -def test_atomic_mass(): - assert openmc.data.atomic_mass('H1') == 1.00782503224 - assert openmc.data.atomic_mass('U235') == 235.04392819 - with pytest.raises(KeyError): - openmc.data.atomic_mass('U100') - - -def test_atomic_weight(): - assert openmc.data.atomic_weight('C') == 12.011115164864455 - with pytest.raises(ValueError): - openmc.data.atomic_weight('Qt') - - -def test_water_density(): - dens = openmc.data.water_density - # These test values are from IAPWS R7-97(2012). They are actually specific - # volumes so they need to be inverted. They also need to be divided by 1000 - # to convert from [kg / m^3] to [g / cm^3]. - assert dens(300.0, 3.0) == pytest.approx(1e-3/0.100215168e-2, 1e-6) - assert dens(300.0, 80.0) == pytest.approx(1e-3/0.971180894e-3, 1e-6) - assert dens(500.0, 3.0) == pytest.approx(1e-3/0.120241800e-2, 1e-6) - - -def test_gnd_name(): - assert openmc.data.gnd_name(1, 1) == 'H1' - assert openmc.data.gnd_name(40, 90) == ('Zr90') - assert openmc.data.gnd_name(95, 242, 0) == ('Am242') - assert openmc.data.gnd_name(95, 242, 1) == ('Am242_m1') - assert openmc.data.gnd_name(95, 242, 10) == ('Am242_m10') - - -def test_zam(): - assert openmc.data.zam('H1') == (1, 1, 0) - assert openmc.data.zam('Zr90') == (40, 90, 0) - assert openmc.data.zam('Am242') == (95, 242, 0) - assert openmc.data.zam('Am242_m1') == (95, 242, 1) - assert openmc.data.zam('Am242_m10') == (95, 242, 10) - with pytest.raises(ValueError): - openmc.data.zam('garbage') diff --git a/tests/unit_tests/test_data_multipole.py b/tests/unit_tests/test_data_multipole.py deleted file mode 100644 index 02147bf0e..000000000 --- a/tests/unit_tests/test_data_multipole.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import pathlib - -import numpy as np -import pytest -import openmc.data - - -@pytest.fixture(scope='module') -def u235(): - directory = pathlib.Path(os.environ['OPENMC_CROSS_SECTIONS']).parent - u235 = directory / 'wmp' / '092235.h5' - return openmc.data.WindowedMultipole.from_hdf5(u235) - - -@pytest.fixture(scope='module') -def b10(): - directory = pathlib.Path(os.environ['OPENMC_CROSS_SECTIONS']).parent - b10 = directory / 'wmp' / '005010.h5' - return openmc.data.WindowedMultipole.from_hdf5(b10) - - -def test_evaluate(u235): - """Test the cross section evaluation of a library.""" - energies = [1e-3, 1.0, 10.0, 50.] - scattering, absorption, fission = u235(energies, 0.0) - assert (scattering[1], absorption[1], fission[1]) == \ - pytest.approx((13.09, 77.56, 67.36), rel=1e-3) - scattering, absorption, fission = u235(energies, 300.0) - assert (scattering[2], absorption[2], fission[2]) == \ - pytest.approx((11.24, 21.26, 15.50), rel=1e-3) - - -def test_evaluate_none_poles(b10): - """Test a library with no poles, i.e., purely polynomials.""" - energies = [1e-3, 1.0, 10.0, 1e3, 1e5] - scattering, absorption, fission = b10(energies, 0.0) - assert (scattering[0], absorption[0], fission[0]) == \ - pytest.approx((2.201, 19330., 0.), rel=1e-3) - scattering, absorption, fission = b10(energies, 300.0) - assert (scattering[-1], absorption[-1], fission[-1]) == \ - pytest.approx((2.878, 1.982, 0.), rel=1e-3) - - -def test_export_to_hdf5(tmpdir, u235): - filename = str(tmpdir.join('092235.h5')) - u235.export_to_hdf5(filename) - assert os.path.exists(filename) diff --git a/tests/unit_tests/test_data_neutron.py b/tests/unit_tests/test_data_neutron.py deleted file mode 100644 index ac6164e5b..000000000 --- a/tests/unit_tests/test_data_neutron.py +++ /dev/null @@ -1,519 +0,0 @@ -from collections.abc import Mapping, Callable -import os - -import numpy as np -import pandas as pd -import pytest -import openmc.data - -from . import needs_njoy - -_TEMPERATURES = [300., 600., 900.] - - -@pytest.fixture(scope='module') -def pu239(): - """Pu239 HDF5 data.""" - directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) - filename = os.path.join(directory, 'Pu239.h5') - return openmc.data.IncidentNeutron.from_hdf5(filename) - - -@pytest.fixture(scope='module') -def xe135(): - """Xe135 ENDF data (contains SLBW resonance range)""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-054_Xe_135.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def sm150(): - """Sm150 ENDF data (contains MLBW resonance range)""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-062_Sm_150.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def gd154(): - """Gd154 ENDF data (contains Reich Moore resonance range and reosnance - covariance with LCOMP=1).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-064_Gd_154.endf') - return openmc.data.IncidentNeutron.from_endf(filename, covariance=True) - - -@pytest.fixture(scope='module') -def cl35(): - """Cl35 ENDF data (contains RML resonance range)""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-017_Cl_035.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def am241(): - """Am241 ENDF data (contains Madland-Nix fission energy distribution).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-095_Am_241.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def u233(): - """U233 ENDF data (contains Watt fission energy distribution).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-092_U_233.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def u236(): - """U236 ENDF data (contains Watt fission energy distribution).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-092_U_236.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def na22(): - """Na22 ENDF data (contains evaporation spectrum).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-011_Na_022.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def na23(): - """Na23 ENDF data (contains MLBW resonance covariance with LCOMP=0).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-011_Na_023.endf') - return openmc.data.IncidentNeutron.from_endf(filename, covariance=True) - - -@pytest.fixture(scope='module') -def be9(): - """Be9 ENDF data (contains laboratory angle-energy distribution).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-004_Be_009.endf') - return openmc.data.IncidentNeutron.from_endf(filename) - - -@pytest.fixture(scope='module') -def h2(): - endf_data = os.environ['OPENMC_ENDF_DATA'] - endf_file = os.path.join(endf_data, 'neutrons', 'n-001_H_002.endf') - return openmc.data.IncidentNeutron.from_njoy( - endf_file, temperatures=_TEMPERATURES) - - -@pytest.fixture(scope='module') -def am244(): - endf_data = os.environ['OPENMC_ENDF_DATA'] - endf_file = os.path.join(endf_data, 'neutrons', 'n-095_Am_244.endf') - return openmc.data.IncidentNeutron.from_njoy(endf_file) - - -@pytest.fixture(scope='module') -def ti50(): - """Ti50 ENDF data (contains Multi-level Breit-Wigner resonance range and - resonance covariance with LCOMP=1).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-022_Ti_050.endf') - return openmc.data.IncidentNeutron.from_endf(filename, covariance=True) - - -@pytest.fixture(scope='module') -def cf252(): - """Cf252 ENDF data (contains RM resonance covariance with LCOMP=0).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-098_Cf_252.endf') - return openmc.data.IncidentNeutron.from_endf(filename, covariance=True) - - -@pytest.fixture(scope='module') -def th232(): - """Th232 ENDF data (contains RM resonance covariance with LCOMP=2).""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-090_Th_232.endf') - return openmc.data.IncidentNeutron.from_endf(filename, covariance=True) - - -def test_attributes(pu239): - assert pu239.name == 'Pu239' - assert pu239.mass_number == 239 - assert pu239.metastable == 0 - assert pu239.atomic_symbol == 'Pu' - assert pu239.atomic_weight_ratio == pytest.approx(236.9986) - - -def test_fission_energy(pu239): - fer = pu239.fission_energy - assert isinstance(fer, openmc.data.FissionEnergyRelease) - components = ['betas', 'delayed_neutrons', 'delayed_photons', 'fragments', - 'neutrinos', 'prompt_neutrons', 'prompt_photons', 'recoverable', - 'total', 'q_prompt', 'q_recoverable', 'q_total'] - for c in components: - assert isinstance(getattr(fer, c), Callable) - - -def test_energy_grid(pu239): - assert isinstance(pu239.energy, Mapping) - for temp, grid in pu239.energy.items(): - assert temp.endswith('K') - assert np.all(np.diff(grid) >= 0.0) - - -def test_reactions(pu239): - assert 2 in pu239.reactions - assert isinstance(pu239.reactions[2], openmc.data.Reaction) - with pytest.raises(KeyError): - pu239.reactions[14] - - -def test_elastic(pu239): - elastic = pu239.reactions[2] - assert elastic.center_of_mass - assert elastic.q_value == 0.0 - assert elastic.mt == 2 - assert '0K' in elastic.xs - assert '294K' in elastic.xs - assert len(elastic.products) == 1 - p = elastic.products[0] - assert isinstance(p, openmc.data.Product) - assert p.particle == 'neutron' - assert p.emission_mode == 'prompt' - assert len(p.distribution) == 1 - d = p.distribution[0] - assert isinstance(d, openmc.data.UncorrelatedAngleEnergy) - assert isinstance(d.angle, openmc.data.AngleDistribution) - assert d.energy is None - assert p.yield_(0.0) == 1.0 - - -def test_fission(pu239): - fission = pu239.reactions[18] - assert not fission.center_of_mass - assert fission.q_value == pytest.approx(198902000.0) - assert fission.mt == 18 - assert '294K' in fission.xs - assert len(fission.products) == 8 - prompt = fission.products[0] - assert prompt.particle == 'neutron' - assert prompt.yield_(1.0e-5) == pytest.approx(2.874262) - delayed = [p for p in fission.products if p.emission_mode == 'delayed'] - assert len(delayed) == 6 - assert all(d.particle == 'neutron' for d in delayed) - assert sum(d.decay_rate for d in delayed) == pytest.approx(4.037212) - assert sum(d.yield_(1.0) for d in delayed) == pytest.approx(0.00645) - photon = fission.products[-1] - assert photon.particle == 'photon' - - -@needs_njoy -def test_derived_products(am244): - fission = am244.reactions[18] - total_neutron = fission.derived_products[0] - assert total_neutron.emission_mode == 'total' - assert total_neutron.yield_(6e6) == pytest.approx(4.2558) - - -def test_kerma(run_in_tmpdir, am244, h2): - # Make sure kerma w/ local photon is >= regular kerma - for nuc in (am244, h2): - assert 301 in nuc - assert 901 in nuc - for T in nuc.temperatures: - k, k_local = nuc[301].xs[T], nuc[901].xs[T] - assert np.all(k.x == k_local.x) - assert np.all(k_local.y >= k.y) - - # Make sure 301/901 get exported/imported correctly - h2.export_to_hdf5("H2.h5") - read_in = openmc.data.IncidentNeutron.from_hdf5("H2.h5") - assert 301 in read_in - assert 901 in read_in - assert np.all(read_in[901].xs['300K'].y == h2[901].xs['300K'].y) - - -def test_urr(pu239): - for T, ptable in pu239.urr.items(): - assert T.endswith('K') - assert isinstance(ptable, openmc.data.ProbabilityTables) - ptable = pu239.urr['294K'] - assert ptable.absorption_flag == -1 - assert ptable.energy[0] == pytest.approx(2500.001) - assert ptable.energy[-1] == pytest.approx(29999.99) - assert ptable.inelastic_flag == 51 - assert ptable.interpolation == 2 - assert not ptable.multiply_smooth - assert ptable.table.shape == (70, 6, 20) - assert ptable.table.shape[0] == ptable.energy.size - - -@needs_njoy -def test_get_reaction_components(h2): - assert h2.get_reaction_components(1) == [2, 16, 102] - assert h2.get_reaction_components(101) == [102] - assert h2.get_reaction_components(16) == [16] - assert h2.get_reaction_components(51) == [] - - -def test_export_to_hdf5(tmpdir, pu239, gd154): - filename = str(tmpdir.join('pu239.h5')) - pu239.export_to_hdf5(filename) - assert os.path.exists(filename) - with pytest.raises(NotImplementedError): - gd154.export_to_hdf5('gd154.h5') - - -def test_slbw(xe135): - res = xe135.resonances - assert isinstance(res, openmc.data.Resonances) - assert len(res.ranges) == 2 - resolved = res.resolved - assert isinstance(resolved, openmc.data.SingleLevelBreitWigner) - assert resolved.energy_min == pytest.approx(1e-5) - assert resolved.energy_max == pytest.approx(190.) - assert resolved.target_spin == pytest.approx(1.5) - assert isinstance(resolved.parameters, pd.DataFrame) - s = resolved.parameters.iloc[0] - assert s['energy'] == pytest.approx(0.084) - - xs = resolved.reconstruct([10., 30., 100.]) - assert sorted(xs.keys()) == [2, 18, 102] - assert np.all(xs[18] == 0.0) - - -def test_mlbw(sm150): - resolved = sm150.resonances.resolved - assert isinstance(resolved, openmc.data.MultiLevelBreitWigner) - assert resolved.energy_min == pytest.approx(1e-5) - assert resolved.energy_max == pytest.approx(1570.) - assert resolved.target_spin == 0.0 - - xs = resolved.reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - assert np.all(xs[18] == 0.0) - - -def test_reichmoore(gd154): - res = gd154.resonances - assert isinstance(res, openmc.data.Resonances) - assert len(res.ranges) == 2 - resolved, unresolved = res.ranges - assert resolved is res.resolved - assert unresolved is res.unresolved - assert isinstance(resolved, openmc.data.ReichMoore) - assert isinstance(unresolved, openmc.data.Unresolved) - assert resolved.energy_min == pytest.approx(1e-5) - assert resolved.energy_max == pytest.approx(2760.) - assert resolved.target_spin == 0.0 - assert resolved.channel_radius[0](1.0) == pytest.approx(0.74) - assert isinstance(resolved.parameters, pd.DataFrame) - assert (resolved.parameters['L'] == 0).all() - assert (resolved.parameters['J'] <= 0.5).all() - assert (resolved.parameters['fissionWidthA'] == 0.0).all() - - elastic = gd154.reactions[2].xs['0K'] - assert isinstance(elastic, openmc.data.ResonancesWithBackground) - assert elastic(0.0253) == pytest.approx(5.7228949796394524) - - -def test_rml(cl35): - resolved = cl35.resonances.resolved - assert isinstance(resolved, openmc.data.RMatrixLimited) - assert resolved.energy_min == pytest.approx(1e-5) - assert resolved.energy_max == pytest.approx(1.2e6) - assert resolved.target_spin == 0.0 - for group in resolved.spin_groups: - assert isinstance(group, openmc.data.SpinGroup) - - -def test_mlbw_cov_lcomp0(cf252): - # Testing on first range only - cov = cf252.resonance_covariance.ranges[0] - res = cf252.resonances.ranges[0] - assert cov.parameters['energy'][0] == pytest.approx(-3.5) - assert res.parameters['energy'][0] == cov.parameters['energy'][0] - assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance) - assert cov.energy_min == pytest.approx(1e-5) - assert cov.energy_max == pytest.approx(1000.) - assert cov.covariance[0,0] == pytest.approx(1.225e-05) - - subset = cov.subset('energy', [0, 100]) - assert not subset.parameters.empty - assert (subset.file2res.parameters['energy'] < 100).all() - samples = cov.sample(1) - xs = samples[0].reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - - -def test_mlbw_cov_lcomp1(ti50): - # Testing on first range only - cov = ti50.resonance_covariance.ranges[0] - res = ti50.resonances.ranges[0] - assert cov.parameters['energy'][0] == pytest.approx(-21020.) - assert res.parameters['energy'][0] == cov.parameters['energy'][0] - assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance) - assert cov.energy_min == pytest.approx(1e-5) - assert cov.energy_max == pytest.approx(587000.) - assert cov.covariance[0,0] == pytest.approx(1.410177e5) - - subset = cov.subset('L', [1, 1]) - assert not subset.parameters.empty - assert (subset.file2res.parameters['L'] == 1).all() - samples = cov.sample(1) - xs = samples[0].reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - - -def test_mlbw_cov_lcomp2(na23): - # Testing on first range only - cov = na23.resonance_covariance.ranges[0] - res = na23.resonances.ranges[0] - assert cov.parameters['energy'][0] == pytest.approx(2810.) - assert res.parameters['energy'][0] == cov.parameters['energy'][0] - assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance) - assert cov.energy_min == pytest.approx(600) - assert cov.energy_max == pytest.approx(500000.) - assert cov.covariance[0,0] == pytest.approx(16.1064163584) - - subset = cov.subset('L', [1, 1]) - assert not subset.parameters.empty - assert (subset.file2res.parameters['L'] == 1).all() - samples = cov.sample(1) - xs = samples[0].reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - - -def test_rmcov_lcomp1(gd154): - # Testing on first range only - cov = gd154.resonance_covariance.ranges[0] - res = gd154.resonances.ranges[0] - assert cov.parameters['energy'][0] == pytest.approx(-2.200001) - assert res.parameters['energy'][0] == cov.parameters['energy'][0] - assert isinstance(cov, openmc.data.resonance_covariance.ReichMooreCovariance) - assert cov.energy_min == pytest.approx(1e-5) - assert cov.energy_max == pytest.approx(2760.) - assert cov.covariance[0,0] == pytest.approx(0.8895997) - - subset = cov.subset('energy', [0, 100]) - assert not subset.parameters.empty - assert (subset.file2res.parameters['energy'] < 100).all() - samples = cov.sample(1) - xs = samples[0].reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - - -def test_rmcov_lcomp2(th232): - # Testing on first range only - cov = th232.resonance_covariance.ranges[0] - res = th232.resonances.ranges[0] - assert cov.parameters['energy'][0] == pytest.approx(-2000) - assert res.parameters['energy'][0] == cov.parameters['energy'][0] - assert isinstance(cov, openmc.data.resonance_covariance.ReichMooreCovariance) - assert cov.energy_min == pytest.approx(1e-5) - assert cov.energy_max == pytest.approx(4000.) - assert cov.covariance[0,0] == pytest.approx(246.6043092496) - - subset = cov.subset('energy', [0, 100]) - assert not subset.parameters.empty - assert (subset.file2res.parameters['energy'] < 100).all() - samples = cov.sample(1) - xs = samples[0].reconstruct([10., 100., 1000.]) - assert sorted(xs.keys()) == [2, 18, 102] - - -def test_madland_nix(am241): - fission = am241.reactions[18] - prompt_neutron = fission.products[0] - dist = prompt_neutron.distribution[0].energy - assert isinstance(dist, openmc.data.MadlandNix) - assert dist.efl == pytest.approx(1029979.0) - assert dist.efh == pytest.approx(546729.7) - assert isinstance(dist.tm, Callable) - - -def test_watt(u233): - fission = u233.reactions[18] - prompt_neutron = fission.products[0] - dist = prompt_neutron.distribution[0].energy - assert isinstance(dist, openmc.data.WattEnergy) - - -def test_maxwell(u236): - fission = u236.reactions[18] - prompt_neutron = fission.products[0] - dist = prompt_neutron.distribution[0].energy - assert isinstance(dist, openmc.data.MaxwellEnergy) - - -def test_evaporation(na22): - n2n = na22.reactions[16] - dist = n2n.products[0].distribution[0].energy - assert isinstance(dist, openmc.data.Evaporation) - - -def test_laboratory(be9): - n2n = be9.reactions[16] - dist = n2n.products[0].distribution[0] - assert isinstance(dist, openmc.data.LaboratoryAngleEnergy) - assert list(dist.breakpoints) == [18] - assert list(dist.interpolation) == [2] - assert dist.energy[0] == pytest.approx(1748830.) - assert dist.energy[-1] == pytest.approx(20.e6) - assert len(dist.energy) == len(dist.energy_out) == len(dist.mu) - for eout, mu in zip(dist.energy_out, dist.mu): - assert len(eout) == len(mu) - assert np.all((-1. <= mu.x) & (mu.x <= 1.)) - - -@needs_njoy -def test_correlated(tmpdir): - endf_data = os.environ['OPENMC_ENDF_DATA'] - endf_file = os.path.join(endf_data, 'neutrons', 'n-014_Si_030.endf') - si30 = openmc.data.IncidentNeutron.from_njoy(endf_file, heatr=False) - - # Convert to HDF5 and read back - filename = str(tmpdir.join('si30.h5')) - si30.export_to_hdf5(filename) - si30_copy = openmc.data.IncidentNeutron.from_hdf5(filename) - - -@needs_njoy -def test_nbody(tmpdir, h2): - # Convert to HDF5 and read back - filename = str(tmpdir.join('h2.h5')) - h2.export_to_hdf5(filename) - h2_copy = openmc.data.IncidentNeutron.from_hdf5(filename) - - # Compare distributions - nbody1 = h2[16].products[0].distribution[0] - nbody2 = h2_copy[16].products[0].distribution[0] - assert nbody1.total_mass == nbody2.total_mass - assert nbody1.n_particles == nbody2.n_particles - assert nbody1.q_value == nbody2.q_value - - -@needs_njoy -def test_ace_convert(run_in_tmpdir): - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'neutrons', 'n-001_H_001.endf') - ace_ascii = 'ace_ascii' - ace_binary = 'ace_binary' - openmc.data.njoy.make_ace(filename, acer=ace_ascii) - - # Convert to binary - openmc.data.ace.ascii_to_binary(ace_ascii, ace_binary) - - # Make sure conversion worked - lib_ascii = openmc.data.ace.Library(ace_ascii) - lib_binary = openmc.data.ace.Library(ace_binary) - for tab_a, tab_b in zip(lib_ascii.tables, lib_binary.tables): - assert tab_a.name == tab_b.name - assert tab_a.atomic_weight_ratio == pytest.approx(tab_b.atomic_weight_ratio) - assert tab_a.temperature == pytest.approx(tab_b.temperature) - assert np.all(tab_a.nxs == tab_b.nxs) - assert np.all(tab_a.jxs == tab_b.jxs) diff --git a/tests/unit_tests/test_data_photon.py b/tests/unit_tests/test_data_photon.py deleted file mode 100644 index c767d19e6..000000000 --- a/tests/unit_tests/test_data_photon.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python - -from collections.abc import Mapping, Callable -import os - -import numpy as np -import pandas as pd -import pytest -import openmc.data - - -@pytest.fixture(scope='module') -def elements_endf(): - """Dictionary of element ENDF data indexed by atomic symbol.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - elements = {'H': 1, 'O': 8, 'Al': 13, 'Cu': 29, 'Ag': 47, 'U': 92, 'Pu': 94} - data = {} - for symbol, Z in elements.items(): - p_file = 'photoat-{:03}_{}_000.endf'.format(Z, symbol) - p_path = os.path.join(endf_data, 'photoat', p_file) - a_file = 'atom-{:03}_{}_000.endf'.format(Z, symbol) - a_path = os.path.join(endf_data, 'atomic_relax', a_file) - data[symbol] = openmc.data.IncidentPhoton.from_endf(p_path, a_path) - return data - - -@pytest.fixture() -def element(request, elements_endf): - """Element ENDF data""" - return elements_endf[request.param] - - -@pytest.mark.parametrize( - 'element, atomic_number', [ - ('Al', 13), - ('Cu', 29), - ('Pu', 94) - ], - indirect=['element'] -) -def test_attributes(element, atomic_number): - assert element.atomic_number == atomic_number - - -@pytest.mark.parametrize( - 'element, subshell, binding_energy, num_electrons', [ - ('H', 'K', 13.61, 1.0), - ('O', 'L3', 14.15, 2.67), - ('U', 'P2', 34.09, 2.0) - ], - indirect=['element'] -) -def test_atomic_relaxation(element, subshell, binding_energy, num_electrons): - atom_relax = element.atomic_relaxation - assert isinstance(atom_relax, openmc.data.photon.AtomicRelaxation) - assert subshell in atom_relax.subshells - assert atom_relax.binding_energy[subshell] == binding_energy - assert atom_relax.num_electrons[subshell] == num_electrons - - -@pytest.mark.parametrize('element', ['Al', 'Cu', 'Pu'], indirect=True) -def test_transitions(element): - transitions = element.atomic_relaxation.transitions - assert transitions - assert isinstance(transitions, Mapping) - for matrix in transitions.values(): - assert isinstance(matrix, pd.core.frame.DataFrame) - assert len(matrix.columns) == 4 - assert sum(matrix['probability']) == pytest.approx(1.0) - - -@pytest.mark.parametrize( - 'element, I, i_shell, ionization_energy, num_electrons', [ - ('H', 19.2, 0, 13.6, 1), - ('O', 95.0, 2, 13.62, 4), - ('U', 890.0, 25, 6.033, -3) - ], - indirect=['element'] -) -def test_bremsstrahlung(element, I, i_shell, ionization_energy, num_electrons): - brems = element.bremsstrahlung - assert isinstance(brems, Mapping) - assert brems['I'] == I - assert brems['num_electrons'][i_shell] == num_electrons - assert brems['ionization_energy'][i_shell] == ionization_energy - assert np.all(np.diff(brems['electron_energy']) > 0.0) - assert np.all(np.diff(brems['photon_energy']) > 0.0) - assert brems['photon_energy'][0] == 0.0 - assert brems['photon_energy'][-1] == 1.0 - assert brems['dcs'].shape == (200, 30) - - -@pytest.mark.parametrize( - 'element, n_shell', [ - ('H', 1), - ('O', 3), - ('Al', 5) - ], - indirect=['element'] -) -def test_compton_profiles(element, n_shell): - profile = element.compton_profiles - assert profile - assert isinstance(profile, Mapping) - assert all(isinstance(x, Callable) for x in profile['J']) - assert all(len(x) == n_shell for x in profile.values()) - - -@pytest.mark.parametrize( - 'element, reaction', [ - ('Cu', 541), - ('Ag', 502), - ('Pu', 504) - ], - indirect=['element'] -) -def test_reactions(element, reaction): - reactions = element.reactions - assert all(isinstance(x, openmc.data.PhotonReaction) for x in reactions.values()) - assert reaction in reactions - with pytest.raises(KeyError): - reactions[18] - - -@pytest.mark.parametrize('element', ['Pu'], indirect=True) -def test_export_to_hdf5(tmpdir, element): - filename = str(tmpdir.join('tmp.h5')) - element.export_to_hdf5(filename) - assert os.path.exists(filename) - # Read in data from hdf5 - element2 = openmc.data.IncidentPhoton.from_hdf5(filename) - # Check for some cross section and datasets of element and element2 - energy = np.logspace(np.log10(1.0), np.log10(1.0e10), num=100) - for mt in (502, 504, 515, 517, 522, 541, 570): - xs = element[mt].xs(energy) - xs2 = element2[mt].xs(energy) - assert np.allclose(xs, xs2) - assert element[502].scattering_factor == element2[502].scattering_factor - assert element.atomic_relaxation.transitions['O3'].equals( - element2.atomic_relaxation.transitions['O3']) - assert (element.compton_profiles['binding_energy'] == - element2.compton_profiles['binding_energy']).all() - assert (element.bremsstrahlung['electron_energy'] == - element2.bremsstrahlung['electron_energy']).all() - # Export to hdf5 again - element2.export_to_hdf5(filename, 'w') diff --git a/tests/unit_tests/test_data_thermal.py b/tests/unit_tests/test_data_thermal.py deleted file mode 100644 index dc4d24628..000000000 --- a/tests/unit_tests/test_data_thermal.py +++ /dev/null @@ -1,264 +0,0 @@ -from collections.abc import Callable -from math import exp -import os -import random - -import numpy as np -import pytest -import openmc.data - -from . import needs_njoy - - -@pytest.fixture(scope='module') -def h2o(): - """H in H2O thermal scattering data.""" - directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) - filename = os.path.join(directory, 'c_H_in_H2O.h5') - return openmc.data.ThermalScattering.from_hdf5(filename) - - -@pytest.fixture(scope='module') -def graphite(): - """Graphite thermal scattering data.""" - directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS']) - filename = os.path.join(directory, 'c_Graphite.h5') - return openmc.data.ThermalScattering.from_hdf5(filename) - - -@pytest.fixture(scope='module') -def h2o_njoy(): - """H in H2O generated using NJOY.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - path_h1 = os.path.join(endf_data, 'neutrons', 'n-001_H_001.endf') - path_h2o = os.path.join(endf_data, 'thermal_scatt', 'tsl-HinH2O.endf') - return openmc.data.ThermalScattering.from_njoy( - path_h1, path_h2o, temperatures=[293.6, 500.0]) - - -@pytest.fixture(scope='module') -def hzrh(): - """H in ZrH thermal scattering data.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'thermal_scatt', 'tsl-HinZrH.endf') - return openmc.data.ThermalScattering.from_endf(filename) - - -@pytest.fixture(scope='module') -def hzrh_njoy(): - """H in ZrH generated using NJOY.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - path_h1 = os.path.join(endf_data, 'neutrons', 'n-001_H_001.endf') - path_hzrh = os.path.join(endf_data, 'thermal_scatt', 'tsl-HinZrH.endf') - with_endf_data = openmc.data.ThermalScattering.from_njoy( - path_h1, path_hzrh, temperatures=[296.0], iwt=0 - ) - without_endf_data = openmc.data.ThermalScattering.from_njoy( - path_h1, path_hzrh, temperatures=[296.0], use_endf_data=False, iwt=1 - ) - return with_endf_data, without_endf_data - - -@pytest.fixture(scope='module') -def sio2(): - """SiO2 thermal scattering data.""" - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'thermal_scatt', 'tsl-SiO2.endf') - return openmc.data.ThermalScattering.from_endf(filename) - - -def test_h2o_attributes(h2o): - assert h2o.name == 'c_H_in_H2O' - assert h2o.nuclides == ['H1'] - assert h2o.temperatures == ['294K'] - assert h2o.atomic_weight_ratio == pytest.approx(0.999167) - assert h2o.energy_max == pytest.approx(4.46) - assert isinstance(repr(h2o), str) - - -def test_h2o_xs(h2o): - assert not h2o.elastic - for temperature, func in h2o.inelastic.xs.items(): - assert temperature.endswith('K') - assert isinstance(func, Callable) - - -def test_graphite_attributes(graphite): - assert graphite.name == 'c_Graphite' - assert graphite.nuclides == ['C0', 'C12', 'C13'] - assert graphite.temperatures == ['296K'] - assert graphite.atomic_weight_ratio == pytest.approx(11.898) - assert graphite.energy_max == pytest.approx(4.46) - - -def test_graphite_xs(graphite): - for temperature, func in graphite.elastic.xs.items(): - assert temperature.endswith('K') - assert isinstance(func, openmc.data.CoherentElastic) - for temperature, func in graphite.inelastic.xs.items(): - assert temperature.endswith('K') - assert isinstance(func, Callable) - elastic = graphite.elastic.xs['296K'] - assert elastic([1e-3, 1.0]) == pytest.approx([0.0, 0.62586153]) - -@needs_njoy -def test_graphite_njoy(): - endf_data = os.environ['OPENMC_ENDF_DATA'] - path_c0 = os.path.join(endf_data, 'neutrons', 'n-006_C_000.endf') - path_gr = os.path.join(endf_data, 'thermal_scatt', 'tsl-graphite.endf') - graphite = openmc.data.ThermalScattering.from_njoy( - path_c0, path_gr, temperatures=[296.0]) - assert graphite.nuclides == ['C0', 'C12', 'C13'] - assert graphite.atomic_weight_ratio == pytest.approx(11.898) - assert graphite.energy_max == pytest.approx(2.02) - assert graphite.temperatures == ['296K'] - - -@needs_njoy -def test_export_to_hdf5(tmpdir, h2o_njoy, hzrh_njoy, graphite): - filename = str(tmpdir.join('water.h5')) - h2o_njoy.export_to_hdf5(filename) - assert os.path.exists(filename) - - # Graphite covers export of coherent elastic data - filename = str(tmpdir.join('graphite.h5')) - graphite.export_to_hdf5(filename) - assert os.path.exists(filename) - - # H in ZrH covers export of incoherent elastic data, and incoherent - # inelastic angle-energy distributions - filename = str(tmpdir.join('hzrh.h5')) - hzrh_njoy[0].export_to_hdf5(filename) - assert os.path.exists(filename) - hzrh_njoy[1].export_to_hdf5(filename, 'w') - assert os.path.exists(filename) - - -@needs_njoy -def test_continuous_dist(h2o_njoy): - for temperature, dist in h2o_njoy.inelastic.distribution.items(): - assert temperature.endswith('K') - assert isinstance(dist, openmc.data.IncoherentInelasticAE) - - -def test_h2o_endf(): - endf_data = os.environ['OPENMC_ENDF_DATA'] - filename = os.path.join(endf_data, 'thermal_scatt', 'tsl-HinH2O.endf') - h2o = openmc.data.ThermalScattering.from_endf(filename) - assert not h2o.elastic - assert h2o.atomic_weight_ratio == pytest.approx(0.99917) - assert h2o.energy_max == pytest.approx(3.99993) - assert h2o.temperatures == ['294K', '350K', '400K', '450K', '500K', '550K', - '600K', '650K', '800K'] - - -def test_hzrh_attributes(hzrh): - assert hzrh.atomic_weight_ratio == pytest.approx(0.99917) - assert hzrh.energy_max == pytest.approx(1.9734) - assert hzrh.temperatures == ['296K', '400K', '500K', '600K', '700K', '800K', - '1000K', '1200K'] - - -def test_hzrh_elastic(hzrh): - rx = hzrh.elastic - for temperature, func in rx.xs.items(): - assert temperature.endswith('K') - assert isinstance(func, openmc.data.IncoherentElastic) - - xs = rx.xs['296K'] - sig_b, W = xs.bound_xs, xs.debye_waller - assert sig_b == pytest.approx(81.98006) - assert W == pytest.approx(8.486993) - for i in range(10): - E = random.uniform(0.0, hzrh.energy_max) - assert xs(E) == pytest.approx(sig_b/2 * ((1 - exp(-4*E*W))/(2*E*W))) - - for temperature, dist in rx.distribution.items(): - assert temperature.endswith('K') - assert dist.debye_waller > 0.0 - - -@needs_njoy -def test_hzrh_njoy(hzrh_njoy): - endf, ace = hzrh_njoy - - # First check version using ENDF incoherent elastic data - assert endf.atomic_weight_ratio == pytest.approx(0.999167) - assert endf.energy_max == pytest.approx(1.855) - assert endf.temperatures == ['296K'] - - # Now check version using ACE incoherent elastic data (discretized) - assert ace.atomic_weight_ratio == endf.atomic_weight_ratio - assert ace.energy_max == endf.energy_max - - # Cross sections should be about the same (within 1%) - E = np.linspace(1e-5, endf.energy_max) - xs1 = endf.elastic.xs['296K'](E) - xs2 = ace.elastic.xs['296K'](E) - assert xs1 == pytest.approx(xs2, rel=0.01) - - # Check discrete incoherent elastic distribution - d = ace.elastic.distribution['296K'] - assert np.all((-1.0 <= d.mu_out) & (d.mu_out <= 1.0)) - - # Check discrete incoherent inelastic distribution - d = endf.inelastic.distribution['296K'] - assert d.skewed - assert np.all((-1.0 <= d.mu_out) & (d.mu_out <= 1.0)) - assert np.all((0.0 <= d.energy_out) & (d.energy_out < 3*endf.energy_max)) - - -def test_sio2_attributes(sio2): - assert sio2.atomic_weight_ratio == pytest.approx(27.84423) - assert sio2.energy_max == pytest.approx(2.46675) - assert sio2.temperatures == ['294K', '350K', '400K', '500K', '800K', - '1000K', '1200K'] - - -def test_sio2_elastic(sio2): - rx = sio2.elastic - for temperature, func in rx.xs.items(): - assert temperature.endswith('K') - assert isinstance(func, openmc.data.CoherentElastic) - xs = rx.xs['294K'] - assert len(xs) == 317 - assert xs.bragg_edges[0] == pytest.approx(0.000711634) - assert xs.factors[0] == pytest.approx(2.6958e-14) - - # Below first bragg edge, cross section should be zero - E = xs.bragg_edges[0] / 2.0 - assert xs(E) == 0.0 - - # Between bragg edges, cross section is P/E where P is the factor - E = (xs.bragg_edges[0] + xs.bragg_edges[1]) / 2.0 - P = xs.factors[0] - assert xs(E) == pytest.approx(P / E) - - # Check the last Bragg edge - E = 1.1 * xs.bragg_edges[-1] - P = xs.factors[-1] - assert xs(E) == pytest.approx(P / E) - - for temperature, dist in rx.distribution.items(): - assert temperature.endswith('K') - assert dist.coherent_xs is rx.xs[temperature] - - -def test_get_thermal_name(): - f = openmc.data.get_thermal_name - # Names which are recognized - assert f('lwtr') == 'c_H_in_H2O' - assert f('hh2o') == 'c_H_in_H2O' - - with pytest.warns(UserWarning, match='is not recognized'): - # Names which can be guessed - assert f('lw00') == 'c_H_in_H2O' - assert f('graphite') == 'c_Graphite' - assert f('D_in_D2O') == 'c_D_in_D2O' - - # Not in values, but very close - assert f('hluci') == 'c_H_in_C5O2H8' - assert f('ortho_d') == 'c_ortho_D' - - # Names that don't remotely match anything - assert f('boogie_monster') == 'c_boogie_monster' diff --git a/tests/unit_tests/test_deplete_atom_number.py b/tests/unit_tests/test_deplete_atom_number.py deleted file mode 100644 index 4cc9207ca..000000000 --- a/tests/unit_tests/test_deplete_atom_number.py +++ /dev/null @@ -1,147 +0,0 @@ -""" Tests for the AtomNumber class """ - -import numpy as np -from openmc.deplete import atom_number - - -def test_indexing(): - """Tests the __getitem__ and __setitem__ routines simultaneously.""" - - local_mats = ["10000", "10001"] - nuclides = ["U238", "U235", "U234"] - volume = {"10000" : 0.38, "10001" : 0.21} - - number = atom_number.AtomNumber(local_mats, nuclides, volume, 2) - - number["10000", "U238"] = 1.0 - number["10001", "U238"] = 2.0 - number["10000", "U235"] = 3.0 - number["10001", "U235"] = 4.0 - - # String indexing - assert number["10000", "U238"] == 1.0 - assert number["10001", "U238"] == 2.0 - assert number["10000", "U235"] == 3.0 - assert number["10001", "U235"] == 4.0 - - # Int indexing - assert number[0, 0] == 1.0 - assert number[1, 0] == 2.0 - assert number[0, 1] == 3.0 - assert number[1, 1] == 4.0 - - number[0, 0] = 5.0 - - assert number[0, 0] == 5.0 - assert number["10000", "U238"] == 5.0 - - -def test_properties(): - """Test properties. """ - local_mats = ["10000", "10001"] - nuclides = ["U238", "U235", "Gd157"] - volume = {"10000" : 0.38, "10001" : 0.21} - - number = atom_number.AtomNumber(local_mats, nuclides, volume, 2) - - assert list(number.materials) == ["10000", "10001"] - assert number.n_nuc == 3 - assert list(number.nuclides) == ["U238", "U235", "Gd157"] - assert number.burnable_nuclides == ["U238", "U235"] - - -def test_density_indexing(): - """Tests the get and set_atom_density routines simultaneously.""" - - local_mats = ["10000", "10001", "10002"] - nuclides = ["U238", "U235", "U234"] - volume = {"10000" : 0.38, "10001" : 0.21} - - number = atom_number.AtomNumber(local_mats, nuclides, volume, 2) - - number.set_atom_density("10000", "U238", 1.0) - number.set_atom_density("10001", "U238", 2.0) - number.set_atom_density("10002", "U238", 3.0) - number.set_atom_density("10000", "U235", 4.0) - number.set_atom_density("10001", "U235", 5.0) - number.set_atom_density("10002", "U235", 6.0) - number.set_atom_density("10000", "U234", 7.0) - number.set_atom_density("10001", "U234", 8.0) - number.set_atom_density("10002", "U234", 9.0) - - # String indexing - assert number.get_atom_density("10000", "U238") == 1.0 - assert number.get_atom_density("10001", "U238") == 2.0 - assert number.get_atom_density("10002", "U238") == 3.0 - assert number.get_atom_density("10000", "U235") == 4.0 - assert number.get_atom_density("10001", "U235") == 5.0 - assert number.get_atom_density("10002", "U235") == 6.0 - assert number.get_atom_density("10000", "U234") == 7.0 - assert number.get_atom_density("10001", "U234") == 8.0 - assert number.get_atom_density("10002", "U234") == 9.0 - - # Int indexing - assert number.get_atom_density(0, 0) == 1.0 - assert number.get_atom_density(1, 0) == 2.0 - assert number.get_atom_density(2, 0) == 3.0 - assert number.get_atom_density(0, 1) == 4.0 - assert number.get_atom_density(1, 1) == 5.0 - assert number.get_atom_density(2, 1) == 6.0 - assert number.get_atom_density(0, 2) == 7.0 - assert number.get_atom_density(1, 2) == 8.0 - assert number.get_atom_density(2, 2) == 9.0 - - - number.set_atom_density(0, 0, 5.0) - assert number.get_atom_density(0, 0) == 5.0 - - # Verify volume is used correctly - assert number[0, 0] == 5.0 * 0.38 - assert number[1, 0] == 2.0 * 0.21 - assert number[2, 0] == 3.0 * 1.0 - assert number[0, 1] == 4.0 * 0.38 - assert number[1, 1] == 5.0 * 0.21 - assert number[2, 1] == 6.0 * 1.0 - assert number[0, 2] == 7.0 * 0.38 - assert number[1, 2] == 8.0 * 0.21 - assert number[2, 2] == 9.0 * 1.0 - - -def test_get_mat_slice(): - """Tests getting slices.""" - - local_mats = ["10000", "10001", "10002"] - nuclides = ["U238", "U235", "U234"] - volume = {"10000" : 0.38, "10001" : 0.21} - - number = atom_number.AtomNumber(local_mats, nuclides, volume, 2) - - number.number = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) - - sl = number.get_mat_slice(0) - - np.testing.assert_array_equal(sl, np.array([1.0, 2.0])) - - sl = number.get_mat_slice("10000") - - np.testing.assert_array_equal(sl, np.array([1.0, 2.0])) - - -def test_set_mat_slice(): - """Tests getting slices.""" - - local_mats = ["10000", "10001", "10002"] - nuclides = ["U238", "U235", "U234"] - volume = {"10000" : 0.38, "10001" : 0.21} - - number = atom_number.AtomNumber(local_mats, nuclides, volume, 2) - - number.set_mat_slice(0, [1.0, 2.0]) - - assert number[0, 0] == 1.0 - assert number[0, 1] == 2.0 - - number.set_mat_slice("10000", [3.0, 4.0]) - - assert number[0, 0] == 3.0 - assert number[0, 1] == 4.0 diff --git a/tests/unit_tests/test_deplete_chain.py b/tests/unit_tests/test_deplete_chain.py deleted file mode 100644 index 08c60d3ed..000000000 --- a/tests/unit_tests/test_deplete_chain.py +++ /dev/null @@ -1,459 +0,0 @@ -"""Tests for openmc.deplete.Chain class.""" - -from collections.abc import Mapping -import os -from pathlib import Path -from itertools import product - -import numpy as np -from openmc.data import zam, ATOMIC_SYMBOL -from openmc.deplete import comm, Chain, reaction_rates, nuclide, cram -import pytest - -from tests import cdtemp - -_TEST_CHAIN = """\ - - - - - - - - - - - - - - - - 0.0253 - - A B - 0.0292737 0.002566345 - - - - -""" - - -@pytest.fixture(scope='module') -def simple_chain(): - with cdtemp(): - with open('chain_test.xml', 'w') as fh: - fh.write(_TEST_CHAIN) - yield Chain.from_xml('chain_test.xml') - - -def test_init(): - """Test depletion chain initialization.""" - chain = Chain() - - assert isinstance(chain.nuclides, list) - assert isinstance(chain.nuclide_dict, Mapping) - - -def test_len(): - """Test depletion chain length.""" - chain = Chain() - chain.nuclides = ["NucA", "NucB", "NucC"] - - assert len(chain) == 3 - - -def test_from_endf(): - """Test depletion chain building from ENDF files""" - endf_data = Path(os.environ['OPENMC_ENDF_DATA']) - decay_data = (endf_data / 'decay').glob('*.endf') - fpy_data = (endf_data / 'nfy').glob('*.endf') - neutron_data = (endf_data / 'neutrons').glob('*.endf') - chain = Chain.from_endf(decay_data, fpy_data, neutron_data) - - assert len(chain) == len(chain.nuclides) == len(chain.nuclide_dict) == 3820 - for nuc in chain.nuclides: - assert nuc == chain[nuc.name] - - -def test_from_xml(simple_chain): - """Read chain_test.xml and ensure all values are correct.""" - # Unfortunately, this routine touches a lot of the code, but most of - # the components external to depletion_chain.py are simple storage - # types. - - chain = simple_chain - - # Basic checks - assert len(chain) == 3 - - # A tests - nuc = chain["A"] - - assert nuc.name == "A" - assert nuc.half_life == 2.36520E+04 - assert nuc.n_decay_modes == 2 - modes = nuc.decay_modes - assert [m.target for m in modes] == ["B", "C"] - assert [m.type for m in modes] == ["beta1", "beta2"] - assert [m.branching_ratio for m in modes] == [0.6, 0.4] - assert nuc.n_reaction_paths == 1 - assert [r.target for r in nuc.reactions] == ["C"] - assert [r.type for r in nuc.reactions] == ["(n,gamma)"] - assert [r.branching_ratio for r in nuc.reactions] == [1.0] - - # B tests - nuc = chain["B"] - - assert nuc.name == "B" - assert nuc.half_life == 3.29040E+04 - assert nuc.n_decay_modes == 1 - modes = nuc.decay_modes - assert [m.target for m in modes] == ["A"] - assert [m.type for m in modes] == ["beta"] - assert [m.branching_ratio for m in modes] == [1.0] - assert nuc.n_reaction_paths == 1 - assert [r.target for r in nuc.reactions] == ["C"] - assert [r.type for r in nuc.reactions] == ["(n,gamma)"] - assert [r.branching_ratio for r in nuc.reactions] == [1.0] - - # C tests - nuc = chain["C"] - - assert nuc.name == "C" - assert nuc.n_decay_modes == 0 - assert nuc.n_reaction_paths == 3 - assert [r.target for r in nuc.reactions] == [None, "A", "B"] - assert [r.type for r in nuc.reactions] == ["fission", "(n,gamma)", "(n,gamma)"] - assert [r.branching_ratio for r in nuc.reactions] == [1.0, 0.7, 0.3] - - # Yield tests - assert nuc.yield_energies == (0.0253,) - assert list(nuc.yield_data) == [0.0253] - assert nuc.yield_data[0.0253].products == ("A", "B") - assert (nuc.yield_data[0.0253].yields == [0.0292737, 0.002566345]).all() - - -def test_export_to_xml(run_in_tmpdir): - """Test writing a depletion chain to XML.""" - - # Prevent different MPI ranks from conflicting - filename = 'test{}.xml'.format(comm.rank) - - A = nuclide.Nuclide("A") - A.half_life = 2.36520e4 - A.decay_modes = [ - nuclide.DecayTuple("beta1", "B", 0.6), - nuclide.DecayTuple("beta2", "C", 0.4) - ] - A.reactions = [nuclide.ReactionTuple("(n,gamma)", "C", 0.0, 1.0)] - - B = nuclide.Nuclide("B") - B.half_life = 3.29040e4 - B.decay_modes = [nuclide.DecayTuple("beta", "A", 1.0)] - B.reactions = [nuclide.ReactionTuple("(n,gamma)", "C", 0.0, 1.0)] - - C = nuclide.Nuclide("C") - C.reactions = [ - nuclide.ReactionTuple("fission", None, 2.0e8, 1.0), - nuclide.ReactionTuple("(n,gamma)", "A", 0.0, 0.7), - nuclide.ReactionTuple("(n,gamma)", "B", 0.0, 0.3) - ] - C.yield_data = nuclide.FissionYieldDistribution({ - 0.0253: {"A": 0.0292737, "B": 0.002566345}}) - - chain = Chain() - chain.nuclides = [A, B, C] - chain.export_to_xml(filename) - - chain_xml = open(filename, 'r').read() - assert _TEST_CHAIN == chain_xml - - -def test_form_matrix(simple_chain): - """ Using chain_test, and a dummy reaction rate, compute the matrix. """ - # Relies on test_from_xml passing. - - chain = simple_chain - - mats = ["10000", "10001"] - nuclides = ["A", "B", "C"] - - react = reaction_rates.ReactionRates(mats, nuclides, chain.reactions) - - react.set("10000", "C", "fission", 1.0) - react.set("10000", "A", "(n,gamma)", 2.0) - react.set("10000", "B", "(n,gamma)", 3.0) - react.set("10000", "C", "(n,gamma)", 4.0) - - mat = chain.form_matrix(react[0, :, :]) - # Loss A, decay, (n, gamma) - mat00 = -np.log(2) / 2.36520E+04 - 2 - # A -> B, decay, 0.6 branching ratio - mat10 = np.log(2) / 2.36520E+04 * 0.6 - # A -> C, decay, 0.4 branching ratio + (n,gamma) - mat20 = np.log(2) / 2.36520E+04 * 0.4 + 2 - - # B -> A, decay, 1.0 branching ratio - mat01 = np.log(2)/3.29040E+04 - # Loss B, decay, (n, gamma) - mat11 = -np.log(2)/3.29040E+04 - 3 - # B -> C, (n, gamma) - mat21 = 3 - - # C -> A fission, (n, gamma) - mat02 = 0.0292737 * 1.0 + 4.0 * 0.7 - # C -> B fission, (n, gamma) - mat12 = 0.002566345 * 1.0 + 4.0 * 0.3 - # Loss C, fission, (n, gamma) - mat22 = -1.0 - 4.0 - - assert mat[0, 0] == mat00 - assert mat[1, 0] == mat10 - assert mat[2, 0] == mat20 - assert mat[0, 1] == mat01 - assert mat[1, 1] == mat11 - assert mat[2, 1] == mat21 - assert mat[0, 2] == mat02 - assert mat[1, 2] == mat12 - assert mat[2, 2] == mat22 - - # Pass equivalent fission yields directly - # Ensure identical matrix is formed - f_yields = {"C": {"A": 0.0292737, "B": 0.002566345}} - new_mat = chain.form_matrix(react[0], f_yields) - for r, c in product(range(3), range(3)): - assert new_mat[r, c] == mat[r, c] - - -def test_getitem(): - """ Test nuc_by_ind converter function. """ - chain = Chain() - chain.nuclides = ["NucA", "NucB", "NucC"] - chain.nuclide_dict = {nuc: chain.nuclides.index(nuc) - for nuc in chain.nuclides} - - assert "NucA" == chain["NucA"] - assert "NucB" == chain["NucB"] - assert "NucC" == chain["NucC"] - - -def test_set_fiss_q(): - """Make sure new fission q values can be set on the chain""" - new_q = {"U235": 2.0E8, "U238": 2.0E8, "U234": 5.0E7} - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - mod_chain = Chain.from_xml(chain_file, new_q) - for name, q in new_q.items(): - chain_nuc = mod_chain[name] - for rx in chain_nuc.reactions: - if rx.type == 'fission': - assert rx.Q == q - - -def test_get_set_chain_br(simple_chain): - """Test minor modifications to capture branch ratios""" - expected = {"C": {"A": 0.7, "B": 0.3}} - assert simple_chain.get_branch_ratios() == expected - - # safely modify - new_chain = Chain.from_xml("chain_test.xml") - new_br = {"C": {"A": 0.5, "B": 0.5}, "A": {"C": 0.99, "B": 0.01}} - new_chain.set_branch_ratios(new_br) - assert new_chain.get_branch_ratios() == new_br - - # write, re-read - new_chain.export_to_xml("chain_mod.xml") - assert Chain.from_xml("chain_mod.xml").get_branch_ratios() == new_br - - # Test non-strict [warn, not error] setting - bad_br = {"B": {"X": 0.6, "A": 0.4}, "X": {"A": 0.5, "C": 0.5}} - bad_br.update(new_br) - new_chain.set_branch_ratios(bad_br, strict=False) - assert new_chain.get_branch_ratios() == new_br - - # Ensure capture reactions are removed - rem_br = {"A": {"C": 1.0}} - new_chain.set_branch_ratios(rem_br) - # A is not in returned dict because there is no branch - assert "A" not in new_chain.get_branch_ratios() - - -def test_capture_branch_infer_ground(): - """Ensure the ground state is infered if not given""" - # Make up a metastable capture transition: - infer_br = {"Xe135": {"Xe136_m1": 0.5}} - set_br = {"Xe135": {"Xe136": 0.5, "Xe136_m1": 0.5}} - - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - chain = Chain.from_xml(chain_file) - - # Create nuclide to be added into the chain - xe136m = nuclide.Nuclide("Xe136_m1") - - chain.nuclides.append(xe136m) - chain.nuclide_dict[xe136m.name] = len(chain.nuclides) - 1 - - chain.set_branch_ratios(infer_br, "(n,gamma)") - - assert chain.get_branch_ratios("(n,gamma)") == set_br - - -def test_capture_branch_no_rxn(): - """Ensure capture reactions that don't exist aren't created""" - u4br = {"U234": {"U235": 0.5, "U235_m1": 0.5}} - - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - chain = Chain.from_xml(chain_file) - - u5m = nuclide.Nuclide("U235_m1") - - chain.nuclides.append(u5m) - chain.nuclide_dict[u5m.name] = len(chain.nuclides) - 1 - - with pytest.raises(AttributeError, match="U234"): - chain.set_branch_ratios(u4br) - - -def test_capture_branch_failures(simple_chain): - """Test failure modes for setting capture branch ratios""" - - # Parent isotope not present - br = {"X": {"A": 0.6, "B": 0.7}} - with pytest.raises(KeyError, match="X"): - simple_chain.set_branch_ratios(br) - - # Product isotope not present - br = {"C": {"X": 0.4, "A": 0.2, "B": 0.4}} - with pytest.raises(KeyError, match="X"): - simple_chain.set_branch_ratios(br) - - # Sum of ratios > 1.0 - br = {"C": {"A": 1.0, "B": 1.0}} - with pytest.raises(ValueError, match=r"Sum of \(n,gamma\).*for C"): - simple_chain.set_branch_ratios(br, "(n,gamma)") - - -def test_set_alpha_branches(): - """Test setting of alpha reaction branching ratios""" - # Build a mock chain - chain = Chain() - - parent = nuclide.Nuclide() - parent.name = "A" - - he4 = nuclide.Nuclide() - he4.name = "He4" - - ground_tgt = nuclide.Nuclide() - ground_tgt.name = "B" - - meta_tgt = nuclide.Nuclide() - meta_tgt.name = "B_m1" - - for ix, nuc in enumerate((parent, ground_tgt, meta_tgt, he4)): - chain.nuclides.append(nuc) - chain.nuclide_dict[nuc.name] = ix - - # add reactions to parent - parent.reactions.append(nuclide.ReactionTuple( - "(n,a)", ground_tgt.name, 1.0, 0.6)) - parent.reactions.append(nuclide.ReactionTuple( - "(n,a)", meta_tgt.name, 1.0, 0.4)) - parent.reactions.append(nuclide.ReactionTuple( - "(n,a)", he4.name, 1.0, 1.0)) - - expected_ref = {"A": {"B": 0.6, "B_m1": 0.4}} - - assert chain.get_branch_ratios("(n,a)") == expected_ref - - # alter and check again - - altered = {"A": {"B": 0.5, "B_m1": 0.5}} - - chain.set_branch_ratios(altered, "(n,a)") - assert chain.get_branch_ratios("(n,a)") == altered - - # make sure that alpha particle still produced - for r in parent.reactions: - if r.target == he4.name: - break - else: - raise ValueError("Helium has been removed and should not have been") - - -def test_simple_fission_yields(simple_chain): - """Check the default fission yields that can be used to form the matrix - """ - fission_yields = simple_chain.get_default_fission_yields() - assert fission_yields == {"C": {"A": 0.0292737, "B": 0.002566345}} - - -def test_fission_yield_attribute(simple_chain): - """Test the fission_yields property""" - thermal_yields = simple_chain.get_default_fission_yields() - # generate default with property - assert simple_chain.fission_yields[0] == thermal_yields - empty_chain = Chain() - empty_chain.fission_yields = thermal_yields - assert empty_chain.fission_yields[0] == thermal_yields - empty_chain.fission_yields = [thermal_yields] * 2 - assert empty_chain.fission_yields[0] == thermal_yields - assert empty_chain.fission_yields[1] == thermal_yields - - # test failure with deplete function - # number fission yields != number of materials - dummy_conc = [[1, 2]] * (len(empty_chain.fission_yields) + 1) - with pytest.raises( - ValueError, match="fission yield.*not equal.*compositions"): - cram.deplete(empty_chain, dummy_conc, None, 0.5) - -def test_validate(simple_chain): - """Test the validate method""" - - # current chain is invalid - # fission yields do not sum to 2.0 - with pytest.raises(ValueError, match="Nuclide C.*fission yields"): - simple_chain.validate(strict=True, tolerance=0.0) - - with pytest.warns(UserWarning) as record: - assert not simple_chain.validate(strict=False, quiet=False, tolerance=0.0) - assert not simple_chain.validate(strict=False, quiet=True, tolerance=0.0) - assert len(record) == 1 - assert "Nuclide C" in record[0].message.args[0] - - # Fix fission yields but keep to restore later - old_yields = simple_chain["C"].yield_data - simple_chain["C"].yield_data = {0.0253: {"A": 1.4, "B": 0.6}} - - assert simple_chain.validate(strict=True, tolerance=0.0) - with pytest.warns(None) as record: - assert simple_chain.validate(strict=False, quiet=False, tolerance=0.0) - assert len(record) == 0 - - # Mess up "earlier" nuclide's reactions - decay_mode = simple_chain["A"].decay_modes.pop() - - with pytest.raises(ValueError, match="Nuclide A.*decay mode"): - simple_chain.validate(strict=True, tolerance=0.0) - - # restore old fission yields - simple_chain["C"].yield_data = old_yields - - with pytest.warns(UserWarning) as record: - assert not simple_chain.validate(strict=False, quiet=False, tolerance=0.0) - assert len(record) == 2 - assert "Nuclide A" in record[0].message.args[0] - assert "Nuclide C" in record[1].message.args[0] - - # restore decay modes - simple_chain["A"].decay_modes.append(decay_mode) - - -def test_validate_inputs(): - c = Chain() - - with pytest.raises(TypeError, match="tolerance"): - c.validate(tolerance=None) - - with pytest.raises(ValueError, match="tolerance"): - c.validate(tolerance=-1) diff --git a/tests/unit_tests/test_deplete_cram.py b/tests/unit_tests/test_deplete_cram.py deleted file mode 100644 index 8987fbd7a..000000000 --- a/tests/unit_tests/test_deplete_cram.py +++ /dev/null @@ -1,37 +0,0 @@ -""" Tests for cram.py - -Compares a few Mathematica matrix exponentials to CRAM16/CRAM48. -""" - -from pytest import approx -import numpy as np -import scipy.sparse as sp -from openmc.deplete.cram import CRAM16, CRAM48 - - -def test_CRAM16(): - """Test 16-term CRAM.""" - x = np.array([1.0, 1.0]) - mat = sp.csr_matrix([[-1.0, 0.0], [-2.0, -3.0]]) - dt = 0.1 - - z = CRAM16(mat, x, dt) - - # Solution from mathematica - z0 = np.array((0.904837418035960, 0.576799023327476)) - - assert z == approx(z0) - - -def test_CRAM48(): - """Test 48-term CRAM.""" - x = np.array([1.0, 1.0]) - mat = sp.csr_matrix([[-1.0, 0.0], [-2.0, -3.0]]) - dt = 0.1 - - z = CRAM48(mat, x, dt) - - # Solution from mathematica - z0 = np.array((0.904837418035960, 0.576799023327476)) - - assert z == approx(z0) diff --git a/tests/unit_tests/test_deplete_fission_yields.py b/tests/unit_tests/test_deplete_fission_yields.py deleted file mode 100644 index 854c530f9..000000000 --- a/tests/unit_tests/test_deplete_fission_yields.py +++ /dev/null @@ -1,293 +0,0 @@ -"""Test the FissionYieldHelpers""" - -import os -from collections import namedtuple -from unittest.mock import Mock -import bisect - -import pytest -import numpy as np -import openmc -from openmc import lib -from openmc.deplete.nuclide import Nuclide, FissionYieldDistribution -from openmc.deplete.helpers import ( - FissionYieldCutoffHelper, ConstantFissionYieldHelper, - AveragedFissionYieldHelper) - - -@pytest.fixture(scope="module") -def materials(tmpdir_factory): - """Use C API to construct realistic materials for testing tallies""" - tmpdir = tmpdir_factory.mktemp("lib") - orig = tmpdir.chdir() - # Create proxy problem to please openmc - mfuel = openmc.Material(name="test_fuel") - mfuel.volume = 1.0 - for nuclide in ["U235", "U238", "Xe135", "Pu239"]: - mfuel.add_nuclide(nuclide, 1.0) - openmc.Materials([mfuel]).export_to_xml() - # Geometry - box = openmc.rectangular_prism(1.0, 1.0, boundary_type="reflective") - cell = openmc.Cell(fill=mfuel, region=box) - root = openmc.Universe(cells=[cell]) - openmc.Geometry(root).export_to_xml() - # settings - settings = openmc.Settings() - settings.particles = 100 - settings.inactive = 0 - settings.batches = 10 - settings.verbosity = 1 - settings.export_to_xml() - - try: - with lib.run_in_memory(): - yield [lib.Material(), lib.Material()] - finally: - # Convert to strings as os.remove in py 3.5 doesn't support Paths - for file_path in ("settings.xml", "geometry.xml", "materials.xml", - "summary.h5"): - os.remove(str(tmpdir / file_path)) - orig.chdir() - os.rmdir(str(tmpdir)) - - -def proxy_tally_data(tally, fill=None): - """Construct an empty matrix built from a C tally - - The shape of tally.results will be - ``(n_bins, n_nuc * n_scores, 3)`` - """ - n_nucs = max(len(tally.nuclides), 1) - n_scores = max(len(tally.scores), 1) - n_bins = 1 - for tfilter in tally.filters: - if not hasattr(tfilter, "bins"): - continue - this_bins = len(tfilter.bins) - if isinstance(tfilter, lib.EnergyFilter): - this_bins -= 1 - n_bins *= max(this_bins, 1) - data = np.empty((n_bins, n_nucs * n_scores, 3)) - if fill is not None: - data.fill(fill) - return data - - -@pytest.fixture(scope="module") -def nuclide_bundle(): - u5yield_dict = { - 0.0253: {"Xe135": 7.85e-4, "Gd155": 4.08e-12, "Sm149": 1.71e-12}, - 5.0e5: {"Xe135": 7.85e-4, "Sm149": 1.71e-12}, - 1.40e7: {"Xe135": 4.54e-3, "Gd155": 5.83e-8}} - u235 = Nuclide("U235") - u235.yield_data = FissionYieldDistribution(u5yield_dict) - - u8yield_dict = {5.00e5: {"Xe135": 1.12e-3, "Gd155": 1.32e-12}} - u238 = Nuclide("U238") - u238.yield_data = FissionYieldDistribution(u8yield_dict) - - xe135 = Nuclide("Xe135") - - pu239 = Nuclide("Pu239") - pu239.yield_data = FissionYieldDistribution({ - 5.0e5: {"Xe135": 6.14e-3, "Sm149": 9.429e-10, "Gd155": 5.24e-9}, - 2e6: {"Xe135": 6.15e-3, "Sm149": 9.42e-10, "Gd155": 5.29e-9}}) - - NuclideBundle = namedtuple("NuclideBundle", "u235 u238 xe135 pu239") - return NuclideBundle(u235, u238, xe135, pu239) - - -@pytest.mark.parametrize( - "input_energy, yield_energy", - ((0.0253, 0.0253), (0.01, 0.0253), (4e5, 5e5))) -def test_constant_helper(nuclide_bundle, input_energy, yield_energy): - helper = ConstantFissionYieldHelper(nuclide_bundle, energy=input_energy) - assert helper.energy == input_energy - assert helper.constant_yields == { - "U235": nuclide_bundle.u235.yield_data[yield_energy], - "U238": nuclide_bundle.u238.yield_data[5.00e5], - "Pu239": nuclide_bundle.pu239.yield_data[5e5]} - assert helper.constant_yields == helper.weighted_yields(1) - - -def test_cutoff_construction(nuclide_bundle): - u235 = nuclide_bundle.u235 - u238 = nuclide_bundle.u238 - pu239 = nuclide_bundle.pu239 - - # defaults - helper = FissionYieldCutoffHelper(nuclide_bundle, 1) - assert helper.constant_yields == { - "U238": u238.yield_data[5.0e5], - "Pu239": pu239.yield_data[5e5]} - assert helper.thermal_yields == {"U235": u235.yield_data[0.0253]} - assert helper.fast_yields == {"U235": u235.yield_data[5e5]} - - # use 14 MeV yields - helper = FissionYieldCutoffHelper(nuclide_bundle, 1, fast_energy=14e6) - assert helper.constant_yields == { - "U238": u238.yield_data[5.0e5], - "Pu239": pu239.yield_data[5e5]} - assert helper.thermal_yields == {"U235": u235.yield_data[0.0253]} - assert helper.fast_yields == {"U235": u235.yield_data[14e6]} - - # specify missing thermal yields -> use 0.0253 - helper = FissionYieldCutoffHelper(nuclide_bundle, 1, thermal_energy=1) - assert helper.thermal_yields == {"U235": u235.yield_data[0.0253]} - assert helper.fast_yields == {"U235": u235.yield_data[5e5]} - - # request missing fast yields -> use epithermal - helper = FissionYieldCutoffHelper(nuclide_bundle, 1, fast_energy=1e4) - assert helper.thermal_yields == {"U235": u235.yield_data[0.0253]} - assert helper.fast_yields == {"U235": u235.yield_data[5e5]} - - # higher cutoff energy -> obtain fast and "faster" yields - helper = FissionYieldCutoffHelper(nuclide_bundle, 1, cutoff=1e6, - thermal_energy=5e5, fast_energy=14e6) - assert helper.constant_yields == {"U238": u238.yield_data[5e5]} - assert helper.thermal_yields == { - "U235": u235.yield_data[5e5], "Pu239": pu239.yield_data[5e5]} - assert helper.fast_yields == { - "U235": u235.yield_data[14e6], "Pu239": pu239.yield_data[2e6]} - - # test super low and super high cutoff energies - helper = FissionYieldCutoffHelper( - nuclide_bundle, 1, thermal_energy=0.001, cutoff=0.002) - assert helper.fast_yields == {} - assert helper.thermal_yields == {} - assert helper.constant_yields == { - "U235": u235.yield_data[0.0253], "U238": u238.yield_data[5e5], - "Pu239": pu239.yield_data[5e5]} - - helper = FissionYieldCutoffHelper( - nuclide_bundle, 1, cutoff=15e6, fast_energy=17e6) - assert helper.thermal_yields == {} - assert helper.fast_yields == {} - assert helper.constant_yields == { - "U235": u235.yield_data[14e6], "U238": u238.yield_data[5e5], - "Pu239": pu239.yield_data[2e6]} - - -@pytest.mark.parametrize("key", ("cutoff", "thermal_energy", "fast_energy")) -def test_cutoff_failure(key): - with pytest.raises(TypeError, match=key): - FissionYieldCutoffHelper(None, None, **{key: None}) - with pytest.raises(ValueError, match=key): - FissionYieldCutoffHelper(None, None, **{key: -1}) - - -# emulate some split between fast and thermal U235 fissions -@pytest.mark.parametrize("therm_frac", (0.5, 0.2, 0.8)) -def test_cutoff_helper(materials, nuclide_bundle, therm_frac): - helper = FissionYieldCutoffHelper(nuclide_bundle, len(materials), - cutoff=1e6, fast_energy=14e6) - helper.generate_tallies(materials, [0]) - - non_zero_nucs = [n.name for n in nuclide_bundle] - tally_nucs = helper.update_tally_nuclides(non_zero_nucs) - assert tally_nucs == ["Pu239", "U235"] - - # Check tallies - fission_tally = helper._fission_rate_tally - assert fission_tally is not None - filters = fission_tally.filters - assert len(filters) == 2 - assert isinstance(filters[0], lib.MaterialFilter) - assert len(filters[0].bins) == len(materials) - assert isinstance(filters[1], lib.EnergyFilter) - # lower, cutoff, and upper energy - assert len(filters[1].bins) == 3 - - # Emulate building tallies - # material x energy, tallied_nuclides, 3 - tally_data = proxy_tally_data(fission_tally) - helper._fission_rate_tally = Mock() - helper_flux = 1e6 - tally_data[0, :, 1] = therm_frac * helper_flux - tally_data[1, :, 1] = (1 - therm_frac) * helper_flux - helper._fission_rate_tally.results = tally_data - - helper.unpack() - # expected results of shape (n_mats, 2, n_tnucs) - expected_results = np.empty((1, 2, len(tally_nucs))) - expected_results[:, 0] = therm_frac - expected_results[:, 1] = 1 - therm_frac - assert helper.results == pytest.approx(expected_results) - - actual_yields = helper.weighted_yields(0) - assert actual_yields["U238"] == nuclide_bundle.u238.yield_data[5e5] - for nuc in tally_nucs: - assert actual_yields[nuc] == ( - helper.thermal_yields[nuc] * therm_frac - + helper.fast_yields[nuc] * (1 - therm_frac)) - - -@pytest.mark.parametrize("avg_energy", (0.01, 6e5, 15e6)) -def test_averaged_helper(materials, nuclide_bundle, avg_energy): - helper = AveragedFissionYieldHelper(nuclide_bundle) - helper.generate_tallies(materials, [0]) - tallied_nucs = helper.update_tally_nuclides( - [n.name for n in nuclide_bundle]) - assert tallied_nucs == ["Pu239", "U235"] - - # check generated tallies - fission_tally = helper._fission_rate_tally - assert fission_tally is not None - fission_filters = fission_tally.filters - assert len(fission_filters) == 2 - assert isinstance(fission_filters[0], lib.MaterialFilter) - assert len(fission_filters[0].bins) == len(materials) - assert isinstance(fission_filters[1], lib.EnergyFilter) - assert len(fission_filters[1].bins) == 2 - assert fission_tally.scores == ["fission"] - assert fission_tally.nuclides == list(tallied_nucs) - - weighted_tally = helper._weighted_tally - assert weighted_tally is not None - weighted_filters = weighted_tally.filters - assert len(weighted_filters) == 2 - assert isinstance(weighted_filters[0], lib.MaterialFilter) - assert len(weighted_filters[0].bins) == len(materials) - assert isinstance(weighted_filters[1], lib.EnergyFunctionFilter) - assert len(weighted_filters[1].energy) == 2 - assert len(weighted_filters[1].y) == 2 - assert weighted_tally.scores == ["fission"] - assert weighted_tally.nuclides == list(tallied_nucs) - - helper_flux = 1e16 - fission_results = proxy_tally_data(fission_tally, helper_flux) - weighted_results = proxy_tally_data( - weighted_tally, helper_flux * avg_energy) - - helper._fission_rate_tally = Mock() - helper._weighted_tally = Mock() - helper._fission_rate_tally.results = fission_results - helper._weighted_tally.results = weighted_results - - helper.unpack() - expected_results = np.ones((1, len(tallied_nucs))) * avg_energy - assert helper.results == pytest.approx(expected_results) - - actual_yields = helper.weighted_yields(0) - # constant U238 => no interpolation - assert actual_yields["U238"] == nuclide_bundle.u238.yield_data[5e5] - # construct expected yields - exp_u235_yields = interp_average_yields(nuclide_bundle.u235, avg_energy) - assert actual_yields["U235"] == exp_u235_yields - exp_pu239_yields = interp_average_yields(nuclide_bundle.pu239, avg_energy) - assert actual_yields["Pu239"] == exp_pu239_yields - - -def interp_average_yields(nuc, avg_energy): - """Construct a set of yields by interpolation between neighbors""" - energies = nuc.yield_energies - yields = nuc.yield_data - if avg_energy < energies[0]: - return yields[energies[0]] - if avg_energy > energies[-1]: - return yields[energies[-1]] - thermal_ix = bisect.bisect_left(energies, avg_energy) - thermal_E, fast_E = energies[thermal_ix - 1:thermal_ix + 1] - assert thermal_E < avg_energy < fast_E - split = (avg_energy - thermal_E)/(fast_E - thermal_E) - return yields[thermal_E]*(1 - split) + yields[fast_E]*split diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py deleted file mode 100644 index 47c9690ae..000000000 --- a/tests/unit_tests/test_deplete_integrator.py +++ /dev/null @@ -1,161 +0,0 @@ -"""Tests for saving results - -It is worth noting that openmc.deplete.integrate is extremely complex, to the -point I am unsure if it can be reasonably unit-tested. For the time being, it -will be left unimplemented and testing will be done via regression. - -""" - -import copy -from unittest.mock import MagicMock - -import numpy as np -from uncertainties import ufloat -import pytest - -from openmc.deplete import ( - ReactionRates, Results, ResultsList, comm, OperatorResult, - PredictorIntegrator, SICELIIntegrator) - -from tests import dummy_operator - - -def test_results_save(run_in_tmpdir): - """Test data save module""" - - stages = 3 - - np.random.seed(comm.rank) - - # Mock geometry - op = MagicMock() - - # Avoid DummyOperator thinking it's doing a restart calculation - op.prev_res = None - - vol_dict = {} - full_burn_list = [] - - for i in range(comm.size): - vol_dict[str(2*i)] = 1.2 - vol_dict[str(2*i + 1)] = 1.2 - full_burn_list.append(str(2*i)) - full_burn_list.append(str(2*i + 1)) - - burn_list = full_burn_list[2*comm.rank: 2*comm.rank + 2] - nuc_list = ["na", "nb"] - - op.get_results_info.return_value = ( - vol_dict, nuc_list, burn_list, full_burn_list) - - # Construct x - x1 = [] - x2 = [] - - for i in range(stages): - x1.append([np.random.rand(2), np.random.rand(2)]) - x2.append([np.random.rand(2), np.random.rand(2)]) - - # Construct r - r1 = ReactionRates(burn_list, ["na", "nb"], ["ra", "rb"]) - r1[:] = np.random.rand(2, 2, 2) - - rate1 = [] - rate2 = [] - - for i in range(stages): - rate1.append(copy.deepcopy(r1)) - r1[:] = np.random.rand(2, 2, 2) - rate2.append(copy.deepcopy(r1)) - r1[:] = np.random.rand(2, 2, 2) - - # Create global terms - # Col 0: eig, Col 1: uncertainty - eigvl1 = np.random.rand(stages, 2) - eigvl2 = np.random.rand(stages, 2) - - eigvl1 = comm.bcast(eigvl1, root=0) - eigvl2 = comm.bcast(eigvl2, root=0) - - t1 = [0.0, 1.0] - t2 = [1.0, 2.0] - - op_result1 = [OperatorResult(ufloat(*k), rates) - for k, rates in zip(eigvl1, rate1)] - op_result2 = [OperatorResult(ufloat(*k), rates) - for k, rates in zip(eigvl2, rate2)] - Results.save(op, x1, op_result1, t1, 0, 0) - Results.save(op, x2, op_result2, t2, 0, 1) - - # Load the files - res = ResultsList.from_hdf5("depletion_results.h5") - - for i in range(stages): - for mat_i, mat in enumerate(burn_list): - for nuc_i, nuc in enumerate(nuc_list): - assert res[0][i, mat, nuc] == x1[i][mat_i][nuc_i] - assert res[1][i, mat, nuc] == x2[i][mat_i][nuc_i] - np.testing.assert_array_equal(res[0].rates[i], rate1[i]) - np.testing.assert_array_equal(res[1].rates[i], rate2[i]) - - np.testing.assert_array_equal(res[0].k, eigvl1) - np.testing.assert_array_equal(res[0].time, t1) - - np.testing.assert_array_equal(res[1].k, eigvl2) - np.testing.assert_array_equal(res[1].time, t2) - - -@pytest.mark.parametrize("timesteps", (1, [1])) -def test_bad_integrator_inputs(timesteps): - """Test failure modes for Integrator inputs""" - - op = MagicMock() - op.prev_res = None - op.chain = None - op.heavy_metal = 1.0 - - # No power nor power density given - with pytest.raises(ValueError, match="Either power or power density"): - PredictorIntegrator(op, timesteps) - - # Length of power != length time - with pytest.raises(ValueError, match="number of powers"): - PredictorIntegrator(op, timesteps, power=[1, 2]) - - # Length of power density != length time - with pytest.raises(ValueError, match="number of powers"): - PredictorIntegrator(op, timesteps, power_density=[1, 2]) - - # SI integrator with bad steps - with pytest.raises(TypeError, match="n_steps"): - SICELIIntegrator(op, timesteps, [1], n_steps=2.5) - - with pytest.raises(ValueError, match="n_steps"): - SICELIIntegrator(op, timesteps, [1], n_steps=0) - - -@pytest.mark.parametrize("scheme", dummy_operator.SCHEMES) -def test_integrator(run_in_tmpdir, scheme): - """Test the integrators against their expected values""" - - bundle = dummy_operator.SCHEMES[scheme] - operator = dummy_operator.DummyOperator() - bundle.solver(operator, [0.75, 0.75], 1.0).integrate() - - # get expected results - - res = ResultsList.from_hdf5( - operator.output_dir / "depletion_results.h5") - - t1, y1 = res.get_atoms("1", "1") - t2, y2 = res.get_atoms("1", "2") - - assert (t1 == [0.0, 0.75, 1.5]).all() - assert y1 == pytest.approx(bundle.atoms_1) - assert (t2 == [0.0, 0.75, 1.5]).all() - assert y2 == pytest.approx(bundle.atoms_2) - - # test structure of depletion time dataset - dep_time = res.get_depletion_time() - assert dep_time.shape == (2, ) - assert all(dep_time > 0) diff --git a/tests/unit_tests/test_deplete_nuclide.py b/tests/unit_tests/test_deplete_nuclide.py deleted file mode 100644 index 7d68b3a3d..000000000 --- a/tests/unit_tests/test_deplete_nuclide.py +++ /dev/null @@ -1,260 +0,0 @@ -"""Tests for the openmc.deplete.Nuclide class.""" - -import xml.etree.ElementTree as ET - -import numpy -import pytest -from openmc.deplete import nuclide - - -def test_n_decay_modes(): - """ Test the decay mode count parameter. """ - - nuc = nuclide.Nuclide() - - nuc.decay_modes = [ - nuclide.DecayTuple("beta1", "a", 0.5), - nuclide.DecayTuple("beta2", "b", 0.3), - nuclide.DecayTuple("beta3", "c", 0.2) - ] - - assert nuc.n_decay_modes == 3 - - -def test_n_reaction_paths(): - """ Test the reaction path count parameter. """ - - nuc = nuclide.Nuclide() - - nuc.reactions = [ - nuclide.ReactionTuple("(n,2n)", "a", 0.0, 1.0), - nuclide.ReactionTuple("(n,3n)", "b", 0.0, 1.0), - nuclide.ReactionTuple("(n,4n)", "c", 0.0, 1.0) - ] - - assert nuc.n_reaction_paths == 3 - - -def test_from_xml(): - """Test reading nuclide data from an XML element.""" - - data = """ - - - - - - - - - - 0.0253 - - Te134 Zr100 Xe138 - 0.062155 0.0497641 0.0481413 - - - - """ - - element = ET.fromstring(data) - u235 = nuclide.Nuclide.from_xml(element) - - assert u235.decay_modes == [ - nuclide.DecayTuple('sf', 'U235', 7.2e-11), - nuclide.DecayTuple('alpha', 'Th231', 1 - 7.2e-11) - ] - assert u235.reactions == [ - nuclide.ReactionTuple('(n,2n)', 'U234', -5297781.0, 1.0), - nuclide.ReactionTuple('(n,3n)', 'U233', -12142300.0, 1.0), - nuclide.ReactionTuple('(n,4n)', 'U232', -17885600.0, 1.0), - nuclide.ReactionTuple('(n,gamma)', 'U236', 6545200.0, 1.0), - nuclide.ReactionTuple('fission', None, 193405400.0, 1.0), - ] - expected_yield_data = nuclide.FissionYieldDistribution({ - 0.0253: {"Xe138": 0.0481413, "Zr100": 0.0497641, "Te134": 0.062155}}) - assert u235.yield_data == expected_yield_data - # test accessing the yield energies through the FissionYieldDistribution - assert u235.yield_energies == (0.0253,) - assert u235.yield_energies is u235.yield_data.energies - with pytest.raises(AttributeError): # not settable - u235.yield_energies = [0.0253, 5e5] - - -def test_to_xml_element(): - """Test writing nuclide data to an XML element.""" - - C = nuclide.Nuclide("C") - C.half_life = 0.123 - C.decay_modes = [ - nuclide.DecayTuple('beta-', 'B', 0.99), - nuclide.DecayTuple('alpha', 'D', 0.01) - ] - C.reactions = [ - nuclide.ReactionTuple('fission', None, 2.0e8, 1.0), - nuclide.ReactionTuple('(n,gamma)', 'A', 0.0, 1.0) - ] - C.yield_data = nuclide.FissionYieldDistribution( - {0.0253: {"A": 0.0292737, "B": 0.002566345}}) - element = C.to_xml_element() - - assert element.get("half_life") == "0.123" - - decay_elems = element.findall("decay") - assert len(decay_elems) == 2 - assert decay_elems[0].get("type") == "beta-" - assert decay_elems[0].get("target") == "B" - assert decay_elems[0].get("branching_ratio") == "0.99" - assert decay_elems[1].get("type") == "alpha" - assert decay_elems[1].get("target") == "D" - assert decay_elems[1].get("branching_ratio") == "0.01" - - rx_elems = element.findall("reaction") - assert len(rx_elems) == 2 - assert rx_elems[0].get("type") == "fission" - assert float(rx_elems[0].get("Q")) == 2.0e8 - assert rx_elems[1].get("type") == "(n,gamma)" - assert rx_elems[1].get("target") == "A" - assert float(rx_elems[1].get("Q")) == 0.0 - - assert element.find('neutron_fission_yields') is not None - - -def test_fission_yield_distribution(): - """Test an energy-dependent yield distribution""" - yield_dict = { - 0.0253: {"Xe135": 7.85e-4, "Gd155": 4.08e-12, "Sm149": 1.71e-12}, - 1.40e7: {"Xe135": 4.54e-3, "Gd155": 5.83e-8, "Sm149": 2.69e-8}, - 5.00e5: {"Xe135": 1.12e-3, "Gd155": 1.32e-12}, # drop Sm149 - } - yield_dist = nuclide.FissionYieldDistribution(yield_dict) - assert len(yield_dist) == len(yield_dict) - assert yield_dist.energies == tuple(sorted(yield_dict.keys())) - for exp_ene, exp_dist in yield_dict.items(): - act_dist = yield_dict[exp_ene] - for exp_prod, exp_yield in exp_dist.items(): - assert act_dist[exp_prod] == exp_yield - exp_yield = numpy.array([ - [4.08e-12, 1.71e-12, 7.85e-4], - [1.32e-12, 0.0, 1.12e-3], - [5.83e-8, 2.69e-8, 4.54e-3]]) - assert numpy.array_equal(yield_dist.yield_matrix, exp_yield) - - # Test the operations / special methods for fission yield - orig_yields = yield_dist[0.0253] - assert len(orig_yields) == len(yield_dict[0.0253]) - for key, value in yield_dict[0.0253].items(): - assert key in orig_yields - assert orig_yields[key] == value - # __getitem__ return yields as a view into yield matrix - assert orig_yields.yields.base is yield_dist.yield_matrix - - # Fission yield feature uses scaled and incremented - mod_yields = orig_yields * 2 - assert numpy.array_equal(orig_yields.yields * 2, mod_yields.yields) - mod_yields += orig_yields - assert numpy.array_equal(orig_yields.yields * 3, mod_yields.yields) - - # Failure modes for adding, multiplying yields - similar = numpy.empty_like(orig_yields.yields) - with pytest.raises(TypeError): - orig_yields + similar - with pytest.raises(TypeError): - similar + orig_yields - with pytest.raises(TypeError): - orig_yields += similar - with pytest.raises(TypeError): - orig_yields * similar - with pytest.raises(TypeError): - similar * orig_yields - with pytest.raises(TypeError): - orig_yields *= similar - - -def test_validate(): - - nuc = nuclide.Nuclide() - nuc.name = "Test" - - # decay modes: type, target, branching_ratio - - nuc.decay_modes = [ - nuclide.DecayTuple("type 0", "0", 0.5), - nuclide.DecayTuple("type 1", "1", 0.5), - ] - - # reactions: type, target, Q, branching_ratio - nuc.reactions = [ - nuclide.ReactionTuple("0", "0", 1000, 0.3), - nuclide.ReactionTuple("0", "1", 1000, 0.3), - nuclide.ReactionTuple("1", "2", 1000, 1.0), - nuclide.ReactionTuple("0", "3", 1000, 0.4), - ] - - # fission yields - - nuc.yield_data = { - 0.0253: {"0": 1.5, "1": 0.5}, - 1e6: {"0": 1.5, "1": 0.5}, - } - - # nuclide is good and should have no warnings raise - with pytest.warns(None) as record: - assert nuc.validate(strict=True, quiet=False, tolerance=0.0) - assert len(record) == 0 - - # invalidate decay modes - decay = nuc.decay_modes.pop() - with pytest.raises(ValueError, match="decay mode"): - nuc.validate(strict=True, quiet=False, tolerance=0.0) - - with pytest.warns(UserWarning) as record: - assert not nuc.validate(strict=False, quiet=False, tolerance=0.0) - assert not nuc.validate(strict=False, quiet=True, tolerance=0.0) - assert len(record) == 1 - assert "decay mode" in record[0].message.args[0] - - # restore decay modes, invalidate reactions - nuc.decay_modes.append(decay) - reaction = nuc.reactions.pop() - - with pytest.raises(ValueError, match="0 reaction"): - nuc.validate(strict=True, quiet=False, tolerance=0.0) - - with pytest.warns(UserWarning) as record: - assert not nuc.validate(strict=False, quiet=False, tolerance=0.0) - assert not nuc.validate(strict=False, quiet=True, tolerance=0.0) - assert len(record) == 1 - assert "0 reaction" in record[0].message.args[0] - - # restore reactions, invalidate fission yields - nuc.reactions.append(reaction) - nuc.yield_data[1e6].yields *= 2 - - with pytest.raises(ValueError, match=r"fission yields.*1\.0*e"): - nuc.validate(strict=True, quiet=False, tolerance=0.0) - - with pytest.warns(UserWarning) as record: - assert not nuc.validate(strict=False, quiet=False, tolerance=0.0) - assert not nuc.validate(strict=False, quiet=True, tolerance=0.0) - assert len(record) == 1 - assert "1.0" in record[0].message.args[0] - - # invalidate everything, check that error is raised at decay modes - - decay = nuc.decay_modes.pop() - reaction = nuc.reactions.pop() - - with pytest.raises(ValueError, match="decay mode"): - nuc.validate(strict=True, quiet=False, tolerance=0.0) - - # check for warnings - # should be one warning for decay modes, reactions, fission yields - - with pytest.warns(UserWarning) as record: - assert not nuc.validate(strict=False, quiet=False, tolerance=0.0) - assert not nuc.validate(strict=False, quiet=True, tolerance=0.0) - assert len(record) == 3 - assert "decay mode" in record[0].message.args[0] - assert "0 reaction" in record[1].message.args[0] - assert "1.0" in record[2].message.args[0] diff --git a/tests/unit_tests/test_deplete_operator.py b/tests/unit_tests/test_deplete_operator.py deleted file mode 100644 index 3574d293d..000000000 --- a/tests/unit_tests/test_deplete_operator.py +++ /dev/null @@ -1,89 +0,0 @@ -"""Basic unit tests for openmc.deplete.Operator instantiation - -Modifies and resets environment variable OPENMC_CROSS_SECTIONS -to a custom file with new depletion_chain node -""" - -from os import environ -from unittest import mock -from pathlib import Path - -import pytest -from openmc.deplete.abc import TransportOperator -from openmc.deplete.chain import Chain - -BARE_XS_FILE = "bare_cross_sections.xml" -CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" - - -@pytest.fixture() -def bare_xs(run_in_tmpdir): - """Create a very basic cross_sections file, return simple Chain. - - """ - - bare_xs_contents = """ - - - -""".format(CHAIN_PATH) - - with open(BARE_XS_FILE, "w") as out: - out.write(bare_xs_contents) - - yield - - -class BareDepleteOperator(TransportOperator): - """Very basic class for testing the initialization.""" - - @staticmethod - def __call__(*args, **kwargs): - pass - - @staticmethod - def initial_condition(): - pass - - @staticmethod - def get_results_info(): - pass - - @staticmethod - def write_bos_data(): - pass - - -@mock.patch.dict(environ, {"OPENMC_CROSS_SECTIONS": BARE_XS_FILE}) -def test_operator_init(bare_xs): - """The test will set and unset environment variable OPENMC_CROSS_SECTIONS - to point towards a temporary dummy file. This file will be removed - at the end of the test, and only contains a - depletion_chain node.""" - # force operator to read from OPENMC_CROSS_SECTIONS - bare_op = BareDepleteOperator(chain_file=None) - act_chain = bare_op.chain - ref_chain = Chain.from_xml(CHAIN_PATH) - assert len(act_chain) == len(ref_chain) - for name in ref_chain.nuclide_dict: - # compare openmc.deplete.Nuclide objects - ref_nuc = ref_chain[name] - act_nuc = act_chain[name] - for prop in [ - 'name', 'half_life', 'decay_energy', 'reactions', - 'decay_modes', 'yield_data', 'yield_energies', - ]: - assert getattr(act_nuc, prop) == getattr(ref_nuc, prop), prop - - -def test_operator_fiss_q(): - """Make sure fission q values can be set""" - new_q = {"U235": 2.0E8, "U238": 2.0E8, "U234": 5.0E7} - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - operator = BareDepleteOperator(chain_file=chain_file, fission_q=new_q) - mod_chain = operator.chain - for name, q in new_q.items(): - chain_nuc = mod_chain[name] - for rx in chain_nuc.reactions: - if rx.type == 'fission': - assert rx.Q == q diff --git a/tests/unit_tests/test_deplete_reaction.py b/tests/unit_tests/test_deplete_reaction.py deleted file mode 100644 index 18639a27a..000000000 --- a/tests/unit_tests/test_deplete_reaction.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Tests for the openmc.deplete.ReactionRates class.""" - -import numpy as np -from openmc.deplete import ReactionRates - - -def test_get_set(): - """Tests the get/set methods.""" - - local_mats = ["10000", "10001"] - nuclides = ["U238", "U235"] - reactions = ["fission", "(n,gamma)"] - - rates = ReactionRates(local_mats, nuclides, reactions) - assert rates.shape == (2, 2, 2) - assert np.all(rates == 0.0) - - rates.set("10000", "U238", "fission", 1.0) - rates.set("10001", "U238", "fission", 2.0) - rates.set("10000", "U235", "fission", 3.0) - rates.set("10001", "U235", "fission", 4.0) - rates.set("10000", "U238", "(n,gamma)", 5.0) - rates.set("10001", "U238", "(n,gamma)", 6.0) - rates.set("10000", "U235", "(n,gamma)", 7.0) - rates.set("10001", "U235", "(n,gamma)", 8.0) - - # String indexing - assert rates.get("10000", "U238", "fission") == 1.0 - assert rates.get("10001", "U238", "fission") == 2.0 - assert rates.get("10000", "U235", "fission") == 3.0 - assert rates.get("10001", "U235", "fission") == 4.0 - assert rates.get("10000", "U238", "(n,gamma)") == 5.0 - assert rates.get("10001", "U238", "(n,gamma)") == 6.0 - assert rates.get("10000", "U235", "(n,gamma)") == 7.0 - assert rates.get("10001", "U235", "(n,gamma)") == 8.0 - - # Int indexing - assert rates[0, 0, 0] == 1.0 - assert rates[1, 0, 0] == 2.0 - assert rates[0, 1, 0] == 3.0 - assert rates[1, 1, 0] == 4.0 - assert rates[0, 0, 1] == 5.0 - assert rates[1, 0, 1] == 6.0 - assert rates[0, 1, 1] == 7.0 - assert rates[1, 1, 1] == 8.0 - - rates[0, 0, 0] = 5.0 - - assert rates[0, 0, 0] == 5.0 - assert rates.get("10000", "U238", "fission") == 5.0 - - -def test_properties(): - """Test number of materials property.""" - local_mats = ["10000", "10001"] - nuclides = ["U238", "U235", "Gd157"] - reactions = ["fission", "(n,gamma)", "(n,2n)", "(n,3n)"] - - rates = ReactionRates(local_mats, nuclides, reactions) - - assert rates.n_mat == 2 - assert rates.n_nuc == 3 - assert rates.n_react == 4 diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py deleted file mode 100644 index 82ef05ac7..000000000 --- a/tests/unit_tests/test_deplete_restart.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Regression tests for openmc.deplete restart capability. - -These tests run in two steps, a first run then a restart run, a simple test -problem described in dummy_geometry.py. -""" - -import pytest - -import openmc.deplete - -from tests import dummy_operator - - -def test_restart_predictor_cecm(run_in_tmpdir): - """Test to ensure that schemes with different stages are not compatible""" - - op = dummy_operator.DummyOperator() - output_dir = "test_restart_predictor_cecm" - op.output_dir = output_dir - - # Perform simulation using the predictor algorithm - dt = [0.75] - power = 1.0 - openmc.deplete.PredictorIntegrator(op, dt, power).integrate() - - # Load the files - prev_res = openmc.deplete.ResultsList.from_hdf5( - op.output_dir / "depletion_results.h5") - - # Re-create depletion operator and load previous results - op = dummy_operator.DummyOperator(prev_res) - op.output_dir = output_dir - - # check ValueError is raised, indicating previous and current stages - with pytest.raises(ValueError, match="incompatible.* 1.*2"): - openmc.deplete.CECMIntegrator(op, dt, power) - - -def test_restart_cecm_predictor(run_in_tmpdir): - """Integral regression test of integrator algorithm using CE/CM for the - first run then predictor for the restart run.""" - - op = dummy_operator.DummyOperator() - output_dir = "test_restart_cecm_predictor" - op.output_dir = output_dir - - # Perform simulation using the MCNPX/MCNP6 algorithm - dt = [0.75] - power = 1.0 - cecm = openmc.deplete.CECMIntegrator(op, dt, power) - cecm.integrate() - - # Load the files - prev_res = openmc.deplete.ResultsList.from_hdf5( - op.output_dir / "depletion_results.h5") - - # Re-create depletion operator and load previous results - op = dummy_operator.DummyOperator(prev_res) - op.output_dir = output_dir - - # check ValueError is raised, indicating previous and current stages - with pytest.raises(ValueError, match="incompatible.* 2.*1"): - openmc.deplete.PredictorIntegrator(op, dt, power) - - -@pytest.mark.parametrize("scheme", dummy_operator.SCHEMES) -def test_restart(run_in_tmpdir, scheme): - # set up the problem - - bundle = dummy_operator.SCHEMES[scheme] - - operator = dummy_operator.DummyOperator() - - # take first step - bundle.solver(operator, [0.75], 1.0).integrate() - - # restart - prev_res = openmc.deplete.ResultsList.from_hdf5( - operator.output_dir / "depletion_results.h5") - operator = dummy_operator.DummyOperator(prev_res) - - # take second step - bundle.solver(operator, [0.75], 1.0).integrate() - - # compare results - - results = openmc.deplete.ResultsList.from_hdf5( - operator.output_dir / "depletion_results.h5") - - _t, y1 = results.get_atoms("1", "1") - _t, y2 = results.get_atoms("1", "2") - - assert y1 == pytest.approx(bundle.atoms_1) - assert y2 == pytest.approx(bundle.atoms_2) diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py deleted file mode 100644 index c3ceda5d5..000000000 --- a/tests/unit_tests/test_deplete_resultslist.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Tests the ResultsList class""" - -from pathlib import Path - -import numpy as np -import pytest -import openmc.deplete - - -@pytest.fixture -def res(): - """Load the reference results""" - filename = (Path(__file__).parents[1] / 'regression_tests' / 'deplete' - / 'test_reference.h5') - return openmc.deplete.ResultsList.from_hdf5(filename) - - -def test_get_atoms(res): - """Tests evaluating single nuclide concentration.""" - t, n = res.get_atoms("1", "Xe135") - - t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - n_ref = [6.67473282e+08, 3.76986925e+14, 3.68587383e+14, 3.91338675e+14] - - np.testing.assert_allclose(t, t_ref) - np.testing.assert_allclose(n, n_ref) - - -def test_get_reaction_rate(res): - """Tests evaluating reaction rate.""" - t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)") - - t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - n_ref = [6.67473282e+08, 3.76986925e+14, 3.68587383e+14, 3.91338675e+14] - xs_ref = [3.32282266e-05, 2.76207120e-05, 4.10986677e-05, 3.72453665e-05] - - np.testing.assert_allclose(t, t_ref) - np.testing.assert_allclose(r, np.array(n_ref) * xs_ref) - - -def test_get_eigenvalue(res): - """Tests evaluating eigenvalue.""" - t, k = res.get_eigenvalue() - - t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - k_ref = [1.16984322, 1.19097427, 1.03012572, 1.20045627] - u_ref = [0.0375587, 0.0347639, 0.07216021, 0.02839642] - - np.testing.assert_allclose(t, t_ref) - np.testing.assert_allclose(k[:, 0], k_ref) - np.testing.assert_allclose(k[:, 1], u_ref) diff --git a/tests/unit_tests/test_element_wo.py b/tests/unit_tests/test_element_wo.py deleted file mode 100644 index 2431f9e0e..000000000 --- a/tests/unit_tests/test_element_wo.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python - -import os -import sys - -import pytest - -from openmc import Material -from openmc.data import NATURAL_ABUNDANCE, atomic_mass - - -def test_element_wo(): - # This test doesn't require an OpenMC run. We just need to make sure the - # element.expand() method expands elements with the proper nuclide - # compositions. - - h_am = (NATURAL_ABUNDANCE['H1'] * atomic_mass('H1') + - NATURAL_ABUNDANCE['H2'] * atomic_mass('H2')) - o_am = (NATURAL_ABUNDANCE['O17'] * atomic_mass('O17') + - (NATURAL_ABUNDANCE['O16'] + NATURAL_ABUNDANCE['O18']) - * atomic_mass('O16')) - water_am = 2 * h_am + o_am - - water = Material() - water.add_element('O', o_am / water_am, 'wo') - water.add_element('H', 2 * h_am / water_am, 'wo') - densities = water.get_nuclide_densities() - - for nuc in densities.keys(): - assert nuc in ('H1', 'H2', 'O16', 'O17') - - if nuc in ('H1', 'H2'): - val = 2 * NATURAL_ABUNDANCE[nuc] * atomic_mass(nuc) / water_am - assert densities[nuc][1] == pytest.approx(val) - if nuc == 'O16': - val = (NATURAL_ABUNDANCE[nuc] + NATURAL_ABUNDANCE['O18']) \ - * atomic_mass(nuc) / water_am - assert densities[nuc][1] == pytest.approx(val) - if nuc == 'O17': - val = NATURAL_ABUNDANCE[nuc] * atomic_mass(nuc) / water_am - assert densities[nuc][1] == pytest.approx(val) diff --git a/tests/unit_tests/test_endf.py b/tests/unit_tests/test_endf.py deleted file mode 100644 index 11a8db443..000000000 --- a/tests/unit_tests/test_endf.py +++ /dev/null @@ -1,29 +0,0 @@ -from openmc.data import endf -from pytest import approx - - -def test_float_endf(): - assert endf.float_endf('+3.2146') == approx(3.2146) - assert endf.float_endf('.12345') == approx(0.12345) - assert endf.float_endf('6.022+23') == approx(6.022e23) - assert endf.float_endf('6.022-23') == approx(6.022e-23) - assert endf.float_endf(' +1.01+ 2') == approx(101.0) - assert endf.float_endf(' -1.01- 2') == approx(-0.0101) - assert endf.float_endf('+ 2 . 3+ 1') == approx(23.0) - assert endf.float_endf('-7 .8 -1') == approx(-0.78) - assert endf.float_endf('3.14e0') == approx(3.14) - assert endf.float_endf('3.14E0') == approx(3.14) - assert endf.float_endf('3.14e-1') == approx(0.314) - assert endf.float_endf('3.14d0') == approx(3.14) - assert endf.float_endf('3.14D0') == approx(3.14) - assert endf.float_endf('3.14d-1') == approx(0.314) - assert endf.float_endf('1+2') == approx(100.0) - assert endf.float_endf('-1+2') == approx(-100.0) - assert endf.float_endf('1.+2') == approx(100.0) - assert endf.float_endf('-1.+2') == approx(-100.0) - assert endf.float_endf(' ') == 0.0 - - -def test_int_endf(): - assert endf.int_endf(' ') == 0 - assert endf.int_endf('+4032') == 4032 diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py deleted file mode 100644 index 676ee452e..000000000 --- a/tests/unit_tests/test_filters.py +++ /dev/null @@ -1,165 +0,0 @@ -from math import sqrt, pi - -import openmc -from pytest import fixture, approx - - -@fixture(scope='module') -def box_model(): - model = openmc.model.Model() - m = openmc.Material() - m.add_nuclide('U235', 1.0) - m.set_density('g/cm3', 1.0) - - box = openmc.model.rectangular_prism(10., 10., boundary_type='vacuum') - c = openmc.Cell(fill=m, region=box) - model.geometry.root_universe = openmc.Universe(cells=[c]) - - model.settings.particles = 100 - model.settings.batches = 10 - model.settings.inactive = 0 - model.settings.source = openmc.Source(space=openmc.stats.Point()) - return model - - -def test_legendre(): - n = 5 - f = openmc.LegendreFilter(n) - assert f.order == n - assert f.bins[0] == 'P0' - assert f.bins[-1] == 'P5' - assert len(f.bins) == n + 1 - - # Make sure __repr__ works - repr(f) - - # to_xml_element() - elem = f.to_xml_element() - assert elem.tag == 'filter' - assert elem.attrib['type'] == 'legendre' - assert elem.find('order').text == str(n) - - -def test_spatial_legendre(): - n = 5 - axis = 'x' - f = openmc.SpatialLegendreFilter(n, axis, -10., 10.) - assert f.order == n - assert f.axis == axis - assert f.minimum == -10. - assert f.maximum == 10. - assert f.bins[0] == 'P0' - assert f.bins[-1] == 'P5' - assert len(f.bins) == n + 1 - - # Make sure __repr__ works - repr(f) - - # to_xml_element() - elem = f.to_xml_element() - assert elem.tag == 'filter' - assert elem.attrib['type'] == 'spatiallegendre' - assert elem.find('order').text == str(n) - assert elem.find('axis').text == str(axis) - - -def test_spherical_harmonics(): - n = 3 - f = openmc.SphericalHarmonicsFilter(n) - f.cosine = 'particle' - assert f.order == n - assert f.bins[0] == 'Y0,0' - assert f.bins[-1] == 'Y{0},{0}'.format(n, n) - assert len(f.bins) == (n + 1)**2 - - # Make sure __repr__ works - repr(f) - - # to_xml_element() - elem = f.to_xml_element() - assert elem.tag == 'filter' - assert elem.attrib['type'] == 'sphericalharmonics' - assert elem.attrib['cosine'] == f.cosine - assert elem.find('order').text == str(n) - - -def test_zernike(): - n = 4 - f = openmc.ZernikeFilter(n, 0., 0., 1.) - assert f.order == n - assert f.bins[0] == 'Z0,0' - assert f.bins[-1] == 'Z{0},{0}'.format(n) - assert len(f.bins) == (n + 1)*(n + 2)//2 - - # Make sure __repr__ works - repr(f) - - # to_xml_element() - elem = f.to_xml_element() - assert elem.tag == 'filter' - assert elem.attrib['type'] == 'zernike' - assert elem.find('order').text == str(n) - -def test_zernike_radial(): - n = 4 - f = openmc.ZernikeRadialFilter(n, 0., 0., 1.) - assert f.order == n - assert f.bins[0] == 'Z0,0' - assert f.bins[-1] == 'Z{},0'.format(n) - assert len(f.bins) == n//2 + 1 - - # Make sure __repr__ works - repr(f) - - # to_xml_element() - elem = f.to_xml_element() - assert elem.tag == 'filter' - assert elem.attrib['type'] == 'zernikeradial' - assert elem.find('order').text == str(n) - - -def test_first_moment(run_in_tmpdir, box_model): - plain_tally = openmc.Tally() - plain_tally.scores = ['flux', 'scatter'] - - # Create tallies with expansion filters - leg_tally = openmc.Tally() - leg_tally.filters = [openmc.LegendreFilter(3)] - leg_tally.scores = ['scatter'] - leg_sptl_tally = openmc.Tally() - leg_sptl_tally.filters = [openmc.SpatialLegendreFilter(3, 'x', -5., 5.)] - leg_sptl_tally.scores = ['scatter'] - sph_scat_filter = openmc.SphericalHarmonicsFilter(5) - sph_scat_filter.cosine = 'scatter' - sph_scat_tally = openmc.Tally() - sph_scat_tally.filters = [sph_scat_filter] - sph_scat_tally.scores = ['scatter'] - sph_flux_filter = openmc.SphericalHarmonicsFilter(5) - sph_flux_filter.cosine = 'particle' - sph_flux_tally = openmc.Tally() - sph_flux_tally.filters = [sph_flux_filter] - sph_flux_tally.scores = ['flux'] - zernike_tally = openmc.Tally() - zernike_tally.filters = [openmc.ZernikeFilter(3, r=10.)] - zernike_tally.scores = ['scatter'] - - # Add tallies to model and ensure they all use the same estimator - box_model.tallies = [plain_tally, leg_tally, leg_sptl_tally, - sph_scat_tally, sph_flux_tally, zernike_tally] - for t in box_model.tallies: - t.estimator = 'analog' - - box_model.run() - - # Check that first moment matches the score from the plain tally - with openmc.StatePoint('statepoint.10.h5') as sp: - # Get scores from tally without expansion filters - flux, scatter = sp.tallies[plain_tally.id].mean.ravel() - - # Check that first moment matches - first_score = lambda t: sp.tallies[t.id].mean.ravel()[0] - assert first_score(leg_tally) == scatter - assert first_score(leg_sptl_tally) == scatter - assert first_score(sph_scat_tally) == scatter - assert first_score(sph_flux_tally) == approx(flux) - assert first_score(zernike_tally) == approx(scatter) diff --git a/tests/unit_tests/test_geometry.py b/tests/unit_tests/test_geometry.py deleted file mode 100644 index 69211f72e..000000000 --- a/tests/unit_tests/test_geometry.py +++ /dev/null @@ -1,282 +0,0 @@ -import xml.etree.ElementTree as ET - -import numpy as np -import openmc -import pytest - - -def test_volume(run_in_tmpdir, uo2): - """Test adding volume information from a volume calculation.""" - # Create model with nested spheres - model = openmc.model.Model() - model.materials.append(uo2) - inner = openmc.Sphere(r=1.) - outer = openmc.Sphere(r=2., boundary_type='vacuum') - c1 = openmc.Cell(fill=uo2, region=-inner) - c2 = openmc.Cell(region=+inner & -outer) - u = openmc.Universe(cells=[c1, c2]) - model.geometry.root_universe = u - model.settings.particles = 100 - model.settings.batches = 10 - model.settings.run_mode = 'fixed source' - model.settings.source = openmc.Source(space=openmc.stats.Point()) - - ll, ur = model.geometry.bounding_box - assert ll == pytest.approx((-outer.r, -outer.r, -outer.r)) - assert ur == pytest.approx((outer.r, outer.r, outer.r)) - model.settings.volume_calculations - - for domain in (c1, uo2, u): - # Run stochastic volume calculation - volume_calc = openmc.VolumeCalculation( - domains=[domain], samples=1000, lower_left=ll, upper_right=ur) - model.settings.volume_calculations = [volume_calc] - model.export_to_xml() - openmc.calculate_volumes() - - # Load results and add volume information - volume_calc.load_results('volume_1.h5') - model.geometry.add_volume_information(volume_calc) - - # get_nuclide_densities relies on volume information - nucs = set(domain.get_nuclide_densities()) - assert not nucs ^ {'U235', 'O16'} - - -def test_export_xml(run_in_tmpdir, uo2): - s1 = openmc.Sphere(r=1.) - s2 = openmc.Sphere(r=2., boundary_type='reflective') - c1 = openmc.Cell(fill=uo2, region=-s1) - c2 = openmc.Cell(fill=uo2, region=+s1 & -s2) - geom = openmc.Geometry([c1, c2]) - geom.export_to_xml() - - doc = ET.parse('geometry.xml') - root = doc.getroot() - assert root.tag == 'geometry' - cells = root.findall('cell') - assert [int(c.get('id')) for c in cells] == [c1.id, c2.id] - surfs = root.findall('surface') - assert [int(s.get('id')) for s in surfs] == [s1.id, s2.id] - - -def test_find(uo2): - xp = openmc.XPlane() - c1 = openmc.Cell(fill=uo2, region=+xp) - c2 = openmc.Cell(region=-xp) - u1 = openmc.Universe(cells=(c1, c2)) - - cyl = openmc.ZCylinder() - c3 = openmc.Cell(fill=u1, region=-cyl) - c4 = openmc.Cell(region=+cyl) - geom = openmc.Geometry((c3, c4)) - - seq = geom.find((0.5, 0., 0.)) - assert seq[-1] == c1 - seq = geom.find((-0.5, 0., 0.)) - assert seq[-1] == c2 - seq = geom.find((-1.5, 0., 0.)) - assert seq[-1] == c4 - - -def test_get_all_cells(): - cells = [openmc.Cell() for i in range(5)] - cells2 = [openmc.Cell() for i in range(3)] - cells[0].fill = openmc.Universe(cells=cells2) - geom = openmc.Geometry(cells) - - all_cells = set(geom.get_all_cells().values()) - assert not all_cells ^ set(cells + cells2) - - -def test_get_all_materials(): - m1 = openmc.Material() - m2 = openmc.Material() - c1 = openmc.Cell(fill=m1) - u1 = openmc.Universe(cells=[c1]) - - s = openmc.Sphere() - c2 = openmc.Cell(fill=u1, region=-s) - c3 = openmc.Cell(fill=m2, region=+s) - geom = openmc.Geometry([c2, c3]) - - all_mats = set(geom.get_all_materials().values()) - assert not all_mats ^ {m1, m2} - - -def test_get_all_material_cells(): - m1 = openmc.Material() - m2 = openmc.Material() - c1 = openmc.Cell(fill=m1) - u1 = openmc.Universe(cells=[c1]) - - s = openmc.Sphere() - c2 = openmc.Cell(fill=u1, region=-s) - c3 = openmc.Cell(fill=m2, region=+s) - geom = openmc.Geometry([c2, c3]) - - all_cells = set(geom.get_all_material_cells().values()) - assert not all_cells ^ {c1, c3} - - -def test_get_all_material_universes(): - m1 = openmc.Material() - m2 = openmc.Material() - c1 = openmc.Cell(fill=m1) - u1 = openmc.Universe(cells=[c1]) - - s = openmc.Sphere() - c2 = openmc.Cell(fill=u1, region=-s) - c3 = openmc.Cell(fill=m2, region=+s) - geom = openmc.Geometry([c2, c3]) - - all_univs = set(geom.get_all_material_universes().values()) - assert not all_univs ^ {u1, geom.root_universe} - - -def test_get_all_lattices(cell_with_lattice): - cells, mats, univ, lattice = cell_with_lattice - geom = openmc.Geometry([cells[-1]]) - - lats = list(geom.get_all_lattices().values()) - assert lats == [lattice] - - -def test_get_all_surfaces(uo2): - planes = [openmc.ZPlane(z0=z) for z in np.linspace(-100., 100.)] - slabs = [] - for region in openmc.model.subdivide(planes): - slabs.append(openmc.Cell(fill=uo2, region=region)) - geom = openmc.Geometry(slabs) - - surfs = set(geom.get_all_surfaces().values()) - assert not surfs ^ set(planes) - - -def test_get_by_name(): - m1 = openmc.Material(name='zircaloy') - m1.add_element('Zr', 1.0) - m2 = openmc.Material(name='Zirconium') - m2.add_element('Zr', 1.0) - - c1 = openmc.Cell(fill=m1, name='cell1') - u1 = openmc.Universe(name='Zircaloy universe', cells=[c1]) - - cyl = openmc.ZCylinder() - c2 = openmc.Cell(fill=u1, region=-cyl, name='cell2') - c3 = openmc.Cell(fill=m2, region=+cyl, name='Cell3') - root = openmc.Universe(name='root Universe', cells=[c2, c3]) - geom = openmc.Geometry(root) - - mats = set(geom.get_materials_by_name('zirc')) - assert not mats ^ {m1, m2} - mats = set(geom.get_materials_by_name('zirc', True)) - assert not mats ^ {m1} - mats = set(geom.get_materials_by_name('zirconium', False, True)) - assert not mats ^ {m2} - mats = geom.get_materials_by_name('zirconium', True, True) - assert not mats - - cells = set(geom.get_cells_by_name('cell')) - assert not cells ^ {c1, c2, c3} - cells = set(geom.get_cells_by_name('cell', True)) - assert not cells ^ {c1, c2} - cells = set(geom.get_cells_by_name('cell3', False, True)) - assert not cells ^ {c3} - cells = geom.get_cells_by_name('cell3', True, True) - assert not cells - - cells = set(geom.get_cells_by_fill_name('Zircaloy')) - assert not cells ^ {c1, c2} - cells = set(geom.get_cells_by_fill_name('Zircaloy', True)) - assert not cells ^ {c2} - cells = set(geom.get_cells_by_fill_name('Zircaloy', False, True)) - assert not cells ^ {c1} - cells = geom.get_cells_by_fill_name('Zircaloy', True, True) - assert not cells - - univs = set(geom.get_universes_by_name('universe')) - assert not univs ^ {u1, root} - univs = set(geom.get_universes_by_name('universe', True)) - assert not univs ^ {u1} - univs = set(geom.get_universes_by_name('universe', True, True)) - assert not univs - - -def test_hex_prism(): - hex_prism = openmc.model.hexagonal_prism(edge_length=5.0, - origin=(0.0, 0.0), - orientation='y') - # clear checks - assert (0.0, 0.0, 0.0) in hex_prism - assert (10.0, 10.0, 10.0) not in hex_prism - # edge checks - assert (0.0, 5.01, 0.0) not in hex_prism - assert (0.0, 4.99, 0.0) in hex_prism - - rounded_hex_prism = openmc.model.hexagonal_prism(edge_length=5.0, - origin=(0.0, 0.0), - orientation='y', - corner_radius=1.0) - - # clear checks - assert (0.0, 0.0, 0.0) in rounded_hex_prism - assert (10.0, 10.0, 10.0) not in rounded_hex_prism - # edge checks - assert (0.0, 5.01, 0.0) not in rounded_hex_prism - assert (0.0, 4.99, 0.0) not in rounded_hex_prism - - -def test_get_lattice_by_name(cell_with_lattice): - cells, _, _, lattice = cell_with_lattice - geom = openmc.Geometry([cells[-1]]) - - f = geom.get_lattices_by_name - assert f('lattice') == [lattice] - assert f('lattice', True) == [] - assert f('Lattice', True) == [lattice] - assert f('my lattice', False, True) == [lattice] - assert f('my lattice', True, True) == [] - - -def test_clone(): - c1 = openmc.Cell() - c2 = openmc.Cell() - root = openmc.Universe(cells=[c1, c2]) - geom = openmc.Geometry(root) - - clone = geom.clone() - root_clone = clone.root_universe - - assert root.id != root_clone.id - assert not (set(root.cells) & set(root_clone.cells)) - - -def test_determine_paths(cell_with_lattice): - cells, mats, univ, lattice = cell_with_lattice - u = openmc.Universe(cells=[cells[-1]]) - geom = openmc.Geometry(u) - - geom.determine_paths() - assert len(cells[0].paths) == 4 - assert len(cells[1].paths) == 4 - assert len(cells[2].paths) == 1 - assert len(mats[0].paths) == 1 - assert len(mats[-1].paths) == 4 - - # Test get_instances - for i in range(4): - assert geom.get_instances(cells[0].paths[i]) == i - assert geom.get_instances(mats[-1].paths[i]) == i - - -def test_from_xml(run_in_tmpdir, mixed_lattice_model): - # Export model - mixed_lattice_model.export_to_xml() - - # Import geometry - geom = openmc.Geometry.from_xml() - assert isinstance(geom, openmc.Geometry) - ll, ur = geom.bounding_box - assert ll == pytest.approx((-6.0, -6.0, -np.inf)) - assert ur == pytest.approx((6.0, 6.0, np.inf)) diff --git a/tests/unit_tests/test_lattice.py b/tests/unit_tests/test_lattice.py deleted file mode 100644 index c4a351776..000000000 --- a/tests/unit_tests/test_lattice.py +++ /dev/null @@ -1,353 +0,0 @@ -from math import sqrt -import xml.etree.ElementTree as ET - -import openmc -import pytest - - -@pytest.fixture(scope='module') -def pincell1(uo2, water): - cyl = openmc.ZCylinder(r=0.35) - fuel = openmc.Cell(fill=uo2, region=-cyl) - moderator = openmc.Cell(fill=water, region=+cyl) - - univ = openmc.Universe(cells=[fuel, moderator]) - univ.fuel = fuel - univ.moderator = moderator - return univ - - -@pytest.fixture(scope='module') -def pincell2(uo2, water): - cyl = openmc.ZCylinder(r=0.4) - fuel = openmc.Cell(fill=uo2, region=-cyl) - moderator = openmc.Cell(fill=water, region=+cyl) - - univ = openmc.Universe(cells=[fuel, moderator]) - univ.fuel = fuel - univ.moderator = moderator - return univ - - -@pytest.fixture(scope='module') -def zr(): - zr = openmc.Material() - zr.add_element('Zr', 1.0) - zr.set_density('g/cm3', 1.0) - return zr - - -@pytest.fixture(scope='module') -def rlat2(pincell1, pincell2, uo2, water, zr): - """2D Rectangular lattice for testing.""" - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - n = 3 - u1, u2 = pincell1, pincell2 - lattice = openmc.RectLattice() - lattice.lower_left = (-pitch*n/2, -pitch*n/2) - lattice.pitch = (pitch, pitch) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [u1, u2, u1], - [u2, u1, u2], - [u2, u1, u1] - ] - - # Add extra attributes for comparison purpose - lattice.cells = [u1.fuel, u1.moderator, u2.fuel, u2.moderator, all_zr] - lattice.mats = [uo2, water, zr] - lattice.univs = [u1, u2, lattice.outer] - return lattice - - -@pytest.fixture(scope='module') -def rlat3(pincell1, pincell2, uo2, water, zr): - """3D Rectangular lattice for testing.""" - - # Create another universe for top layer - hydrogen = openmc.Material() - hydrogen.add_element('H', 1.0) - hydrogen.set_density('g/cm3', 0.09) - h_cell = openmc.Cell(fill=hydrogen) - u3 = openmc.Universe(cells=[h_cell]) - - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - n = 3 - u1, u2 = pincell1, pincell2 - lattice = openmc.RectLattice() - lattice.lower_left = (-pitch*n/2, -pitch*n/2, -10.0) - lattice.pitch = (pitch, pitch, 10.0) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [[u1, u2, u1], - [u2, u1, u2], - [u2, u1, u1]], - [[u3, u1, u2], - [u1, u3, u2], - [u2, u1, u1]] - ] - - # Add extra attributes for comparison purpose - lattice.cells = [u1.fuel, u1.moderator, u2.fuel, u2.moderator, - h_cell, all_zr] - lattice.mats = [uo2, water, zr, hydrogen] - lattice.univs = [u1, u2, u3, lattice.outer] - return lattice - - -@pytest.fixture(scope='module') -def hlat2(pincell1, pincell2, uo2, water, zr): - """2D Hexagonal lattice for testing.""" - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - u1, u2 = pincell1, pincell2 - lattice = openmc.HexLattice() - lattice.center = (0., 0.) - lattice.pitch = (pitch,) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [u2, u1, u1, u1, u1, u1, u1, u1, u1, u1, u1, u1], - [u2, u1, u1, u1, u1, u1], - [u2] - ] - - # Add extra attributes for comparison purpose - lattice.cells = [u1.fuel, u1.moderator, u2.fuel, u2.moderator, all_zr] - lattice.mats = [uo2, water, zr] - lattice.univs = [u1, u2, lattice.outer] - return lattice - - -@pytest.fixture(scope='module') -def hlat3(pincell1, pincell2, uo2, water, zr): - """3D Hexagonal lattice for testing.""" - - # Create another universe for top layer - hydrogen = openmc.Material() - hydrogen.add_element('H', 1.0) - hydrogen.set_density('g/cm3', 0.09) - h_cell = openmc.Cell(fill=hydrogen) - u3 = openmc.Universe(cells=[h_cell]) - - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - u1, u2 = pincell1, pincell2 - lattice = openmc.HexLattice() - lattice.center = (0., 0., 0.) - lattice.pitch = (pitch, 10.0) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [[u2, u1, u1, u1, u1, u1, u1, u1, u1, u1, u1, u1], - [u2, u1, u1, u1, u1, u1], - [u2]], - [[u1, u1, u1, u1, u1, u1, u3, u1, u1, u1, u1, u1], - [u1, u1, u1, u3, u1, u1], - [u3]] - ] - - # Add extra attributes for comparison purpose - lattice.cells = [u1.fuel, u1.moderator, u2.fuel, u2.moderator, - h_cell, all_zr] - lattice.mats = [uo2, water, zr, hydrogen] - lattice.univs = [u1, u2, u3, lattice.outer] - return lattice - - -def test_get_nuclides(rlat2, rlat3, hlat2, hlat3): - for lat in (rlat2, hlat2): - nucs = rlat2.get_nuclides() - assert sorted(nucs) == ['H1', 'O16', 'U235', - 'Zr90', 'Zr91', 'Zr92', 'Zr94', 'Zr96'] - for lat in (rlat3, hlat3): - nucs = rlat3.get_nuclides() - assert sorted(nucs) == ['H1', 'H2', 'O16', 'U235', - 'Zr90', 'Zr91', 'Zr92', 'Zr94', 'Zr96'] - - -def test_get_all_cells(rlat2, rlat3, hlat2, hlat3): - for lat in (rlat2, rlat3, hlat2, hlat3): - cells = set(lat.get_all_cells().values()) - assert not cells ^ set(lat.cells) - - -def test_get_all_materials(rlat2, rlat3, hlat2, hlat3): - for lat in (rlat2, rlat3, hlat2, hlat3): - mats = set(lat.get_all_materials().values()) - assert not mats ^ set(lat.mats) - - -def test_get_all_universes(rlat2, rlat3, hlat2, hlat3): - for lat in (rlat2, rlat3, hlat2, hlat3): - univs = set(lat.get_all_universes().values()) - assert not univs ^ set(lat.univs) - - -def test_get_universe(rlat2, rlat3, hlat2, hlat3): - u1, u2, outer = rlat2.univs - assert rlat2.get_universe((0, 0)) == u2 - assert rlat2.get_universe((1, 0)) == u1 - assert rlat2.get_universe((0, 1)) == u2 - - u1, u2, u3, outer = rlat3.univs - assert rlat3.get_universe((0, 0, 0)) == u2 - assert rlat3.get_universe((2, 2, 0)) == u1 - assert rlat3.get_universe((0, 2, 1)) == u3 - assert rlat3.get_universe((2, 1, 1)) == u2 - - u1, u2, outer = hlat2.univs - assert hlat2.get_universe((0, 0)) == u2 - assert hlat2.get_universe((0, 2)) == u2 - assert hlat2.get_universe((1, 0)) == u1 - assert hlat2.get_universe((-2, 2)) == u1 - - hlat2.orientation = 'x' - assert hlat2.get_universe((2, 0)) == u2 - assert hlat2.get_universe((1, 0)) == u2 - assert hlat2.get_universe((1, 1)) == u1 - assert hlat2.get_universe((-1, 1)) == u1 - hlat2.orientation = 'y' - - u1, u2, u3, outer = hlat3.univs - assert hlat3.get_universe((0, 0, 0)) == u2 - assert hlat3.get_universe((0, 0, 1)) == u3 - assert hlat3.get_universe((0, 2, 0)) == u2 - assert hlat3.get_universe((0, 2, 1)) == u1 - assert hlat3.get_universe((0, -2, 0)) == u1 - assert hlat3.get_universe((0, -2, 1)) == u3 - - -def test_find(rlat2, rlat3, hlat2, hlat3): - pitch = rlat2.pitch[0] - seq = rlat2.find((0., 0., 0.)) - assert seq[-1] == rlat2.cells[0] - seq = rlat2.find((pitch, 0., 0.)) - assert seq[-1] == rlat2.cells[2] - seq = rlat2.find((0., -pitch, 0.)) - assert seq[-1] == rlat2.cells[0] - seq = rlat2.find((pitch*100, 0., 0.)) - assert seq[-1] == rlat2.cells[-1] - seq = rlat3.find((-pitch, pitch, 5.0)) - assert seq[-1] == rlat3.cells[-2] - - pitch = hlat2.pitch[0] - seq = hlat2.find((0., 0., 0.)) - assert seq[-1] == hlat2.cells[2] - seq = hlat2.find((0.5, 0., 0.)) - assert seq[-1] == hlat2.cells[3] - seq = hlat2.find((sqrt(3)*pitch, 0., 0.)) - assert seq[-1] == hlat2.cells[0] - seq = hlat2.find((0., pitch, 0.)) - assert seq[-1] == hlat2.cells[2] - - # bottom of 3D lattice - seq = hlat3.find((0., 0., -5.)) - assert seq[-1] == hlat3.cells[2] - seq = hlat3.find((0., pitch, -5.)) - assert seq[-1] == hlat3.cells[2] - seq = hlat3.find((0., -pitch, -5.)) - assert seq[-1] == hlat3.cells[0] - seq = hlat3.find((sqrt(3)*pitch, 0., -5.)) - assert seq[-1] == hlat3.cells[0] - - # top of 3D lattice - seq = hlat3.find((0., 0., 5.)) - assert seq[-1] == hlat3.cells[-2] - seq = hlat3.find((0., pitch, 5.)) - assert seq[-1] == hlat3.cells[0] - seq = hlat3.find((0., -pitch, 5.)) - assert seq[-1] == hlat3.cells[-2] - seq = hlat3.find((sqrt(3)*pitch, 0., 5.)) - assert seq[-1] == hlat3.cells[0] - - -def test_clone(rlat2, hlat2, hlat3): - rlat_clone = rlat2.clone() - assert rlat_clone.id != rlat2.id - assert rlat_clone.lower_left == rlat2.lower_left - assert rlat_clone.pitch == rlat2.pitch - - hlat_clone = hlat2.clone() - assert hlat_clone.id != hlat2.id - assert hlat_clone.center == hlat2.center - assert hlat_clone.pitch == hlat2.pitch - - hlat_clone = hlat3.clone() - assert hlat_clone.id != hlat3.id - assert hlat_clone.center == hlat3.center - assert hlat_clone.pitch == hlat3.pitch - - -def test_repr(rlat2, rlat3, hlat2, hlat3): - repr(rlat2) - repr(rlat3) - repr(hlat2) - repr(hlat3) - - -def test_indices_rect(rlat2, rlat3): - # (y, x) indices - assert rlat2.indices == [(0, 0), (0, 1), (0, 2), - (1, 0), (1, 1), (1, 2), - (2, 0), (2, 1), (2, 2)] - # (z, y, x) indices - assert rlat3.indices == [ - (0, 0, 0), (0, 0, 1), (0, 0, 2), - (0, 1, 0), (0, 1, 1), (0, 1, 2), - (0, 2, 0), (0, 2, 1), (0, 2, 2), - (1, 0, 0), (1, 0, 1), (1, 0, 2), - (1, 1, 0), (1, 1, 1), (1, 1, 2), - (1, 2, 0), (1, 2, 1), (1, 2, 2) - ] - - -def test_indices_hex(hlat2, hlat3): - # (r, i) indices - assert hlat2.indices == ( - [(0, i) for i in range(12)] + - [(1, i) for i in range(6)] + - [(2, 0)] - ) - - # (z, r, i) indices - assert hlat3.indices == ( - [(0, 0, i) for i in range(12)] + - [(0, 1, i) for i in range(6)] + - [(0, 2, 0)] + - [(1, 0, i) for i in range(12)] + - [(1, 1, i) for i in range(6)] + - [(1, 2, 0)] - ) - - -def test_xml_rect(rlat2, rlat3): - for lat in (rlat2, rlat3): - geom = ET.Element('geometry') - lat.create_xml_subelement(geom) - elem = geom.find('lattice') - assert elem.tag == 'lattice' - assert elem.get('id') == str(lat.id) - assert len(elem.find('pitch').text.split()) == lat.ndim - assert len(elem.find('lower_left').text.split()) == lat.ndim - assert len(elem.find('universes').text.split()) == len(lat.indices) - - -def test_xml_hex(hlat2, hlat3): - for lat in (hlat2, hlat3): - geom = ET.Element('geometry') - lat.create_xml_subelement(geom) - elem = geom.find('hex_lattice') - assert elem.tag == 'hex_lattice' - assert elem.get('id') == str(lat.id) - assert len(elem.find('center').text.split()) == lat.ndim - assert len(elem.find('pitch').text.split()) == lat.ndim - 1 - assert len(elem.find('universes').text.split()) == len(lat.indices) - - -def test_show_indices(): - for i in range(1, 11): - lines = openmc.HexLattice.show_indices(i).split('\n') - assert len(lines) == 4*i - 3 - lines_x = openmc.HexLattice.show_indices(i, 'x').split('\n') - assert len(lines) == 4*i - 3 diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py deleted file mode 100644 index ad198f255..000000000 --- a/tests/unit_tests/test_lib.py +++ /dev/null @@ -1,521 +0,0 @@ -from collections.abc import Mapping -import os - -import numpy as np -import pytest -import openmc -import openmc.exceptions as exc -import openmc.lib - -from tests import cdtemp - - -@pytest.fixture(scope='module') -def pincell_model(): - """Set up a model to test with and delete files when done""" - openmc.reset_auto_ids() - pincell = openmc.examples.pwr_pin_cell() - pincell.settings.verbosity = 1 - - # Add a tally - filter1 = openmc.MaterialFilter(pincell.materials) - filter2 = openmc.EnergyFilter([0.0, 1.0, 1.0e3, 20.0e6]) - mat_tally = openmc.Tally() - mat_tally.filters = [filter1, filter2] - mat_tally.nuclides = ['U235', 'U238'] - mat_tally.scores = ['total', 'elastic', '(n,gamma)'] - pincell.tallies.append(mat_tally) - - # Add an expansion tally - zernike_tally = openmc.Tally() - filter3 = openmc.ZernikeFilter(5, r=.63) - cells = pincell.geometry.root_universe.cells - filter4 = openmc.CellFilter(list(cells.values())) - zernike_tally.filters = [filter3, filter4] - zernike_tally.scores = ['fission'] - pincell.tallies.append(zernike_tally) - - # Add an energy function tally - energyfunc_tally = openmc.Tally() - energyfunc_filter = openmc.EnergyFunctionFilter( - [0.0, 20e6], [0.0, 20e6]) - energyfunc_tally.scores = ['fission'] - energyfunc_tally.filters = [energyfunc_filter] - pincell.tallies.append(energyfunc_tally) - - # Write XML files in tmpdir - with cdtemp(): - pincell.export_to_xml() - yield - - -@pytest.fixture(scope='module') -def lib_init(pincell_model, mpi_intracomm): - openmc.lib.init(intracomm=mpi_intracomm) - yield - openmc.lib.finalize() - - -@pytest.fixture(scope='module') -def lib_simulation_init(lib_init): - openmc.lib.simulation_init() - yield - - -@pytest.fixture(scope='module') -def lib_run(lib_simulation_init): - openmc.lib.run() - - -def test_cell_mapping(lib_init): - cells = openmc.lib.cells - assert isinstance(cells, Mapping) - assert len(cells) == 3 - for cell_id, cell in cells.items(): - assert isinstance(cell, openmc.lib.Cell) - assert cell_id == cell.id - - -def test_cell(lib_init): - cell = openmc.lib.cells[1] - assert isinstance(cell.fill, openmc.lib.Material) - cell.fill = openmc.lib.materials[1] - assert str(cell) == 'Cell[0]' - assert cell.name == "Fuel" - cell.name = "Not fuel" - assert cell.name == "Not fuel" - -def test_cell_temperature(lib_init): - cell = openmc.lib.cells[1] - cell.set_temperature(100.0, 0) - assert cell.get_temperature(0) == 100.0 - cell.set_temperature(200) - assert cell.get_temperature() == 200.0 - - -def test_new_cell(lib_init): - with pytest.raises(exc.AllocationError): - openmc.lib.Cell(1) - new_cell = openmc.lib.Cell() - new_cell_with_id = openmc.lib.Cell(10) - assert len(openmc.lib.cells) == 5 - - -def test_material_mapping(lib_init): - mats = openmc.lib.materials - assert isinstance(mats, Mapping) - assert len(mats) == 3 - for mat_id, mat in mats.items(): - assert isinstance(mat, openmc.lib.Material) - assert mat_id == mat.id - - -def test_material(lib_init): - m = openmc.lib.materials[3] - assert m.nuclides == ['H1', 'O16', 'B10', 'B11'] - - old_dens = m.densities - test_dens = [1.0e-1, 2.0e-1, 2.5e-1, 1.0e-3] - m.set_densities(m.nuclides, test_dens) - assert m.densities == pytest.approx(test_dens) - - assert m.volume is None - m.volume = 10.0 - assert m.volume == 10.0 - - with pytest.raises(exc.OpenMCError): - m.set_density(1.0, 'goblins') - - rho = 2.25e-2 - m.set_density(rho) - assert sum(m.densities) == pytest.approx(rho) - - m.set_density(0.1, 'g/cm3') - assert m.density == pytest.approx(0.1) - assert m.name == "Hot borated water" - m.name = "Not hot borated water" - assert m.name == "Not hot borated water" - -def test_material_add_nuclide(lib_init): - m = openmc.lib.materials[3] - m.add_nuclide('Xe135', 1e-12) - assert m.nuclides[-1] == 'Xe135' - assert m.densities[-1] == 1e-12 - - -def test_new_material(lib_init): - with pytest.raises(exc.AllocationError): - openmc.lib.Material(1) - new_mat = openmc.lib.Material() - new_mat_with_id = openmc.lib.Material(10) - assert len(openmc.lib.materials) == 5 - - -def test_nuclide_mapping(lib_init): - nucs = openmc.lib.nuclides - assert isinstance(nucs, Mapping) - assert len(nucs) == 13 - for name, nuc in nucs.items(): - assert isinstance(nuc, openmc.lib.Nuclide) - assert name == nuc.name - - -def test_settings(lib_init): - settings = openmc.lib.settings - assert settings.batches == 10 - settings.batches = 10 - assert settings.inactive == 5 - assert settings.generations_per_batch == 1 - assert settings.particles == 100 - assert settings.seed == 1 - settings.seed = 11 - - assert settings.run_mode == 'eigenvalue' - settings.run_mode = 'volume' - settings.run_mode = 'eigenvalue' - - -def test_tally_mapping(lib_init): - tallies = openmc.lib.tallies - assert isinstance(tallies, Mapping) - assert len(tallies) == 3 - for tally_id, tally in tallies.items(): - assert isinstance(tally, openmc.lib.Tally) - assert tally_id == tally.id - - -def test_energy_function_filter(lib_init): - """Test special __new__ and __init__ for EnergyFunctionFilter""" - efunc = openmc.lib.EnergyFunctionFilter([0.0, 1.0], [0.0, 2.0]) - assert len(efunc.energy) == 2 - assert (efunc.energy == [0.0, 1.0]).all() - assert len(efunc.y) == 2 - assert (efunc.y == [0.0, 2.0]).all() - - -def test_tally(lib_init): - t = openmc.lib.tallies[1] - assert t.type == 'volume' - assert len(t.filters) == 2 - assert isinstance(t.filters[0], openmc.lib.MaterialFilter) - assert isinstance(t.filters[1], openmc.lib.EnergyFilter) - - # Create new filter and replace existing - with pytest.raises(exc.AllocationError): - openmc.lib.MaterialFilter(uid=1) - mats = openmc.lib.materials - f = openmc.lib.MaterialFilter([mats[2], mats[1]]) - assert f.bins[0] == mats[2] - assert f.bins[1] == mats[1] - t.filters = [f] - assert t.filters == [f] - - assert t.nuclides == ['U235', 'U238'] - with pytest.raises(exc.DataError): - t.nuclides = ['Zr2'] - t.nuclides = ['U234', 'Zr90'] - assert t.nuclides == ['U234', 'Zr90'] - - assert t.scores == ['total', '(n,elastic)', '(n,gamma)'] - new_scores = ['scatter', 'fission', 'nu-fission', '(n,2n)'] - t.scores = new_scores - assert t.scores == new_scores - - t2 = openmc.lib.tallies[2] - assert len(t2.filters) == 2 - assert isinstance(t2.filters[0], openmc.lib.ZernikeFilter) - assert isinstance(t2.filters[1], openmc.lib.CellFilter) - assert len(t2.filters[1].bins) == 3 - assert t2.filters[0].order == 5 - - t3 = openmc.lib.tallies[3] - assert len(t3.filters) == 1 - t3_f = t3.filters[0] - assert isinstance(t3_f, openmc.lib.EnergyFunctionFilter) - assert len(t3_f.energy) == 2 - assert len(t3_f.y) == 2 - t3_f.set_data([0.0, 1.0, 2.0], [0.0, 1.0, 4.0]) - assert len(t3_f.energy) == 3 - assert len(t3_f.y) == 3 - - -def test_new_tally(lib_init): - with pytest.raises(exc.AllocationError): - openmc.lib.Material(1) - new_tally = openmc.lib.Tally() - new_tally.scores = ['flux'] - new_tally_with_id = openmc.lib.Tally(10) - new_tally_with_id.scores = ['flux'] - assert len(openmc.lib.tallies) == 5 - - -def test_tally_activate(lib_simulation_init): - t = openmc.lib.tallies[1] - assert not t.active - t.active = True - assert t.active - - -def test_tally_writable(lib_simulation_init): - t = openmc.lib.tallies[1] - assert t.writable - t.writable = False - assert not t.writable - # Revert tally to writable state for lib_run fixtures - t.writable = True - - -def test_tally_results(lib_run): - t = openmc.lib.tallies[1] - assert t.num_realizations == 10 # t was made active in test_tally_active - assert np.all(t.mean >= 0) - nonzero = (t.mean > 0.0) - assert np.all(t.std_dev[nonzero] >= 0) - assert np.all(t.ci_width()[nonzero] >= 1.95*t.std_dev[nonzero]) - - t2 = openmc.lib.tallies[2] - n = 5 - assert t2.mean.size == (n + 1) * (n + 2) // 2 * 3 # Number of Zernike coeffs * 3 cells - - -def test_global_tallies(lib_run): - assert openmc.lib.num_realizations() == 5 - gt = openmc.lib.global_tallies() - for mean, std_dev in gt: - assert mean >= 0 - - -def test_statepoint(lib_run): - openmc.lib.statepoint_write('test_sp.h5') - assert os.path.exists('test_sp.h5') - - -def test_source_bank(lib_run): - source = openmc.lib.source_bank() - assert np.all(source['E'] > 0.0) - assert np.all(source['wgt'] == 1.0) - assert np.allclose(np.linalg.norm(source['u'], axis=1), 1.0) - - -def test_by_batch(lib_run): - openmc.lib.hard_reset() - - # Running next batch before simulation is initialized should raise an - # exception - with pytest.raises(exc.AllocationError): - openmc.lib.next_batch() - - openmc.lib.simulation_init() - try: - for _ in openmc.lib.iter_batches(): - # Make sure we can get k-effective during inactive/active batches - mean, std_dev = openmc.lib.keff() - assert 0.0 < mean < 2.5 - assert std_dev > 0.0 - assert openmc.lib.num_realizations() == 5 - - for i in range(3): - openmc.lib.next_batch() - assert openmc.lib.num_realizations() == 8 - - finally: - openmc.lib.simulation_finalize() - - -def test_reset(lib_run): - # Init and run 10 batches. - openmc.lib.hard_reset() - openmc.lib.simulation_init() - try: - for i in range(10): - openmc.lib.next_batch() - - # Make sure there are 5 realizations for the 5 active batches. - assert openmc.lib.num_realizations() == 5 - assert openmc.lib.tallies[2].num_realizations == 5 - _, keff_sd1 = openmc.lib.keff() - tally_sd1 = openmc.lib.tallies[2].std_dev[0] - - # Reset and run 3 more batches. Check the number of realizations. - openmc.lib.reset() - for i in range(3): - openmc.lib.next_batch() - assert openmc.lib.num_realizations() == 3 - assert openmc.lib.tallies[2].num_realizations == 3 - - # Check the tally std devs to make sure results were cleared. - _, keff_sd2 = openmc.lib.keff() - tally_sd2 = openmc.lib.tallies[2].std_dev[0] - assert keff_sd2 > keff_sd1 - assert tally_sd2 > tally_sd1 - - finally: - openmc.lib.simulation_finalize() - - -def test_reproduce_keff(lib_init): - # Get k-effective after run - openmc.lib.hard_reset() - openmc.lib.run() - keff0 = openmc.lib.keff() - - # Reset, run again, and get k-effective again. they should match - openmc.lib.hard_reset() - openmc.lib.run() - keff1 = openmc.lib.keff() - assert keff0 == pytest.approx(keff1) - - -def test_find_cell(lib_init): - cell, instance = openmc.lib.find_cell((0., 0., 0.)) - assert cell is openmc.lib.cells[1] - cell, instance = openmc.lib.find_cell((0.4, 0., 0.)) - assert cell is openmc.lib.cells[2] - with pytest.raises(exc.GeometryError): - openmc.lib.find_cell((100., 100., 100.)) - - -def test_find_material(lib_init): - mat = openmc.lib.find_material((0., 0., 0.)) - assert mat is openmc.lib.materials[1] - mat = openmc.lib.find_material((0.4, 0., 0.)) - assert mat is openmc.lib.materials[2] - - -def test_mesh(lib_init): - mesh = openmc.lib.RegularMesh() - mesh.dimension = (2, 3, 4) - assert mesh.dimension == (2, 3, 4) - with pytest.raises(exc.AllocationError): - mesh2 = openmc.lib.RegularMesh(mesh.id) - - # Make sure each combination of parameters works - ll = (0., 0., 0.) - ur = (10., 10., 10.) - width = (1., 1., 1.) - mesh.set_parameters(lower_left=ll, upper_right=ur) - assert mesh.lower_left == pytest.approx(ll) - assert mesh.upper_right == pytest.approx(ur) - mesh.set_parameters(lower_left=ll, width=width) - assert mesh.lower_left == pytest.approx(ll) - assert mesh.width == pytest.approx(width) - mesh.set_parameters(upper_right=ur, width=width) - assert mesh.upper_right == pytest.approx(ur) - assert mesh.width == pytest.approx(width) - - meshes = openmc.lib.meshes - assert isinstance(meshes, Mapping) - assert len(meshes) == 1 - for mesh_id, mesh in meshes.items(): - assert isinstance(mesh, openmc.lib.RegularMesh) - assert mesh_id == mesh.id - - mf = openmc.lib.MeshFilter(mesh) - assert mf.mesh == mesh - - msf = openmc.lib.MeshSurfaceFilter(mesh) - assert msf.mesh == mesh - - -def test_restart(lib_init, mpi_intracomm): - # Finalize and re-init to make internal state consistent with XML. - openmc.lib.hard_reset() - openmc.lib.finalize() - openmc.lib.init(intracomm=mpi_intracomm) - openmc.lib.simulation_init() - - # Run for 7 batches then write a statepoint. - for i in range(7): - openmc.lib.next_batch() - openmc.lib.statepoint_write('restart_test.h5', True) - - # Run 3 more batches and copy the keff. - for i in range(3): - openmc.lib.next_batch() - keff0 = openmc.lib.keff() - - # Restart the simulation from the statepoint and the 3 remaining active batches. - openmc.lib.simulation_finalize() - openmc.lib.hard_reset() - openmc.lib.finalize() - openmc.lib.init(args=('-r', 'restart_test.h5')) - openmc.lib.simulation_init() - for i in range(3): - openmc.lib.next_batch() - keff1 = openmc.lib.keff() - openmc.lib.simulation_finalize() - - # Compare the keff values. - assert keff0 == pytest.approx(keff1) - - -def test_load_nuclide(lib_init): - # load multiple nuclides - openmc.lib.load_nuclide('H3') - assert 'H3' in openmc.lib.nuclides - openmc.lib.load_nuclide('Pu239') - assert 'Pu239' in openmc.lib.nuclides - # load non-existent nuclide - with pytest.raises(exc.DataError): - openmc.lib.load_nuclide('Pu3') - - -def test_id_map(lib_init): - expected_ids = np.array([[(3, 3), (2, 2), (3, 3)], - [(2, 2), (1, 1), (2, 2)], - [(3, 3), (2, 2), (3, 3)]], dtype='int32') - - # create a plot object - s = openmc.lib.plot._PlotBase() - s.width = 1.26 - s.height = 1.26 - s.v_res = 3 - s.h_res = 3 - s.origin = (0.0, 0.0, 0.0) - s.basis = 'xy' - s.level = -1 - - ids = openmc.lib.plot.id_map(s) - assert np.array_equal(expected_ids, ids) - -def test_property_map(lib_init): - expected_properties = np.array( - [[(293.6, 0.740582), (293.6, 6.55), (293.6, 0.740582)], - [ (293.6, 6.55), (293.6, 10.29769), (293.6, 6.55)], - [(293.6, 0.740582), (293.6, 6.55), (293.6, 0.740582)]], dtype='float') - - # create a plot object - s = openmc.lib.plot._PlotBase() - s.width = 1.26 - s.height = 1.26 - s.v_res = 3 - s.h_res = 3 - s.origin = (0.0, 0.0, 0.0) - s.basis = 'xy' - s.level = -1 - - properties = openmc.lib.plot.property_map(s) - assert np.allclose(expected_properties, properties, atol=1e-04) - - -def test_position(lib_init): - - pos = openmc.lib.plot._Position(1.0, 2.0, 3.0) - - assert tuple(pos) == (1.0, 2.0, 3.0) - - pos[0] = 1.3 - pos[1] = 2.3 - pos[2] = 3.3 - - assert tuple(pos) == (1.3, 2.3, 3.3) - - -def test_global_bounding_box(lib_init): - expected_llc = (-0.63, -0.63, -np.inf) - expected_urc = (0.63, 0.63, np.inf) - - llc, urc = openmc.lib.global_bounding_box() - - assert tuple(llc) == expected_llc - assert tuple(urc) == expected_urc diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py deleted file mode 100644 index 62fff7cdf..000000000 --- a/tests/unit_tests/test_material.py +++ /dev/null @@ -1,220 +0,0 @@ -import openmc -import openmc.model -import openmc.stats -import openmc.examples -import pytest - - -def test_attributes(uo2): - assert uo2.name == 'UO2' - assert uo2.id == 100 - assert uo2.depletable - - -def test_nuclides(uo2): - """Test adding/removing nuclides.""" - m = openmc.Material() - m.add_nuclide('U235', 1.0) - with pytest.raises(TypeError): - m.add_nuclide('H1', '1.0') - with pytest.raises(TypeError): - m.add_nuclide(1.0, 'H1') - with pytest.raises(ValueError): - m.add_nuclide('H1', 1.0, 'oa') - m.remove_nuclide('U235') - - -def test_elements(): - """Test adding elements.""" - m = openmc.Material() - m.add_element('Zr', 1.0) - m.add_element('U', 1.0, enrichment=4.5) - with pytest.raises(ValueError): - m.add_element('U', 1.0, enrichment=100.0) - with pytest.raises(ValueError): - m.add_element('Pu', 1.0, enrichment=3.0) - - -def test_density(): - m = openmc.Material() - for unit in ['g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3']: - m.set_density(unit, 1.0) - with pytest.raises(ValueError): - m.set_density('g/litre', 1.0) - - -def test_salphabeta(): - m = openmc.Material() - m.add_s_alpha_beta('c_H_in_H2O', 0.5) - - -def test_repr(): - m = openmc.Material() - m.add_nuclide('Zr90', 1.0) - m.add_nuclide('H2', 0.5) - m.add_s_alpha_beta('c_D_in_D2O') - m.set_density('sum') - m.temperature = 600.0 - repr(m) - - -def test_macroscopic(run_in_tmpdir): - m = openmc.Material(name='UO2') - m.add_macroscopic('UO2') - with pytest.raises(ValueError): - m.add_nuclide('H1', 1.0) - with pytest.raises(ValueError): - m.add_element('O', 1.0) - with pytest.raises(ValueError): - m.add_macroscopic('Other') - - m2 = openmc.Material() - m2.add_nuclide('He4', 1.0) - with pytest.raises(ValueError): - m2.add_macroscopic('UO2') - - # Make sure we can remove/add macroscopic - m.remove_macroscopic('UO2') - m.add_macroscopic('UO2') - repr(m) - - # Make sure we can export a material with macroscopic data - mats = openmc.Materials([m]) - mats.export_to_xml() - - -def test_paths(): - model = openmc.examples.pwr_assembly() - model.geometry.determine_paths() - fuel = model.materials[0] - assert fuel.num_instances == 264 - assert len(fuel.paths) == 264 - - -def test_isotropic(): - m1 = openmc.Material() - m1.add_nuclide('U235', 1.0) - m1.add_nuclide('O16', 2.0) - m1.isotropic = ['O16'] - assert m1.isotropic == ['O16'] - - m2 = openmc.Material() - m2.add_nuclide('H1', 1.0) - mats = openmc.Materials([m1, m2]) - mats.make_isotropic_in_lab() - assert m1.isotropic == ['U235', 'O16'] - assert m2.isotropic == ['H1'] - - -def test_get_nuclide_densities(uo2): - nucs = uo2.get_nuclide_densities() - for nuc, density, density_type in nucs.values(): - assert nuc in ('U235', 'O16') - assert density > 0 - assert density_type in ('ao', 'wo') - - -def test_get_nuclide_atom_densities(uo2): - nucs = uo2.get_nuclide_atom_densities() - for nuc, density in nucs.values(): - assert nuc in ('U235', 'O16') - assert density > 0 - - -def test_mass(): - m = openmc.Material() - m.add_nuclide('Zr90', 1.0, 'wo') - m.add_nuclide('U235', 1.0, 'wo') - m.set_density('g/cm3', 2.0) - m.volume = 10.0 - - assert m.get_mass_density('Zr90') == pytest.approx(1.0) - assert m.get_mass_density('U235') == pytest.approx(1.0) - assert m.get_mass_density() == pytest.approx(2.0) - - assert m.get_mass('Zr90') == pytest.approx(10.0) - assert m.get_mass('U235') == pytest.approx(10.0) - assert m.get_mass() == pytest.approx(20.0) - assert m.fissionable_mass == pytest.approx(10.0) - - -def test_materials(run_in_tmpdir): - m1 = openmc.Material() - m1.add_nuclide('U235', 1.0, 'wo') - m1.add_nuclide('O16', 2.0, 'wo') - m1.set_density('g/cm3', 10.0) - m1.depletable = True - m1.temperature = 900.0 - - m2 = openmc.Material() - m2.add_nuclide('H1', 2.0) - m2.add_nuclide('O16', 1.0) - m2.add_s_alpha_beta('c_H_in_H2O') - m2.set_density('kg/m3', 1000.0) - - mats = openmc.Materials([m1, m2]) - mats.cross_sections = '/some/fake/cross_sections.xml' - mats.export_to_xml() - - -def test_borated_water(): - # Test against reference values from the BEAVRS benchmark. - m = openmc.model.borated_water(975, 566.5, 15.51, material_id=50) - assert m.density == pytest.approx(0.7405, 1e-3) - assert m.temperature == pytest.approx(566.5) - assert m._sab[0][0] == 'c_H_in_H2O' - ref_dens = {'B10':8.0023e-06, 'B11':3.2210e-05, 'H1':4.9458e-02, - 'O16':2.4672e-02} - nuc_dens = m.get_nuclide_atom_densities() - for nuclide in ref_dens: - assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) - assert m.id == 50 - - # Test the Celsius conversion. - m = openmc.model.borated_water(975, 293.35, 15.51, 'C') - assert m.density == pytest.approx(0.7405, 1e-3) - - # Test Fahrenheit and psi conversions. - m = openmc.model.borated_water(975, 560.0, 2250.0, 'F', 'psi') - assert m.density == pytest.approx(0.7405, 1e-3) - - # Test the density override - m = openmc.model.borated_water(975, 566.5, 15.51, density=0.9) - assert m.density == pytest.approx(0.9, 1e-3) - - -def test_from_xml(run_in_tmpdir): - # Create a materials.xml file - m1 = openmc.Material(1, 'water') - m1.add_nuclide('H1', 1.0) - m1.add_nuclide('O16', 2.0) - m1.add_s_alpha_beta('c_H_in_H2O') - m1.temperature = 300 - m1.volume = 100 - m1.set_density('g/cm3', 0.9) - m1.isotropic = ['H1'] - m2 = openmc.Material(2, 'zirc') - m2.add_nuclide('Zr90', 1.0, 'wo') - m2.set_density('kg/m3', 10.0) - m3 = openmc.Material(3) - m3.add_nuclide('N14', 0.02) - - mats = openmc.Materials([m1, m2, m3]) - mats.cross_sections = 'fake_path.xml' - mats.export_to_xml() - - # Regenerate materials from XML - mats = openmc.Materials.from_xml() - assert len(mats) == 3 - m1 = mats[0] - assert m1.id == 1 - assert m1.name == 'water' - assert m1.nuclides == [('H1', 1.0, 'ao'), ('O16', 2.0, 'ao')] - assert m1.isotropic == ['H1'] - assert m1.temperature == 300 - assert m1.volume == 100 - m2 = mats[1] - assert m2.nuclides == [('Zr90', 1.0, 'wo')] - assert m2.density == 10.0 - assert m2.density_units == 'kg/m3' - assert mats[2].density_units == 'sum' diff --git a/tests/unit_tests/test_math.py b/tests/unit_tests/test_math.py deleted file mode 100644 index 7c0218fbd..000000000 --- a/tests/unit_tests/test_math.py +++ /dev/null @@ -1,246 +0,0 @@ -import numpy as np -import scipy as sp - -import openmc -import openmc.lib - -import pytest - -def test_t_percentile(): - # Permutations include 1 DoF, 2 DoF, and > 2 DoF - # We will test 5 p-values at 3-DoF values - test_ps = [0.02, 0.4, 0.5, 0.6, 0.98] - test_dfs = [1, 2, 5] - - # The reference solutions come from Scipy - ref_ts = [[sp.stats.t.ppf(p, df) for p in test_ps] for df in test_dfs] - - test_ts = [[openmc.lib.math.t_percentile(p, df) for p in test_ps] - for df in test_dfs] - - # The 5 DoF approximation in openmc.lib.math.t_percentile is off by up to - # 8e-3 from the scipy solution, so test that one separately with looser - # tolerance - assert np.allclose(ref_ts[:-1], test_ts[:-1]) - assert np.allclose(ref_ts[-1], test_ts[-1], atol=1e-2) - - -def test_calc_pn(): - max_order = 10 - test_xs = np.linspace(-1., 1., num=5, endpoint=True) - - # Reference solutions from scipy - ref_vals = np.array([sp.special.eval_legendre(n, test_xs) - for n in range(0, max_order + 1)]) - - test_vals = [] - for x in test_xs: - test_vals.append(openmc.lib.math.calc_pn(max_order, x).tolist()) - - test_vals = np.swapaxes(np.array(test_vals), 0, 1) - - assert np.allclose(ref_vals, test_vals) - - -def test_evaluate_legendre(): - max_order = 10 - # Coefficients are set to 1, but will incorporate the (2l+1)/2 norm factor - # for the reference solution - test_coeffs = [0.5 * (2. * l + 1.) for l in range(max_order + 1)] - test_xs = np.linspace(-1., 1., num=5, endpoint=True) - - ref_vals = np.polynomial.legendre.legval(test_xs, test_coeffs) - - # Set the coefficients back to 1s for the test values since - # evaluate legendre incorporates the (2l+1)/2 term on its own - test_coeffs = [1. for l in range(max_order + 1)] - - test_vals = np.array([openmc.lib.math.evaluate_legendre(test_coeffs, x) - for x in test_xs]) - - assert np.allclose(ref_vals, test_vals) - - -def test_calc_rn(): - max_order = 10 - test_ns = np.array([i for i in range(0, max_order + 1)]) - azi = 0.1 # Longitude - pol = 0.2 # Latitude - test_uvw = np.array([np.sin(pol) * np.cos(azi), - np.sin(pol) * np.sin(azi), - np.cos(pol)]) - - # Reference solutions from the equations - ref_vals = [] - - def coeff(n, m): - return np.sqrt((2. * n + 1) * sp.special.factorial(n - m) / - (sp.special.factorial(n + m))) - - def pnm_bar(n, m, mu): - val = coeff(n, m) - if m != 0: - val *= np.sqrt(2.) - val *= sp.special.lpmv([m], [n], [mu]) - return val[0] - - ref_vals = [] - for n in test_ns: - for m in range(-n, n + 1): - if m < 0: - ylm = pnm_bar(n, np.abs(m), np.cos(pol)) * \ - np.sin(np.abs(m) * azi) - else: - ylm = pnm_bar(n, m, np.cos(pol)) * np.cos(m * azi) - - # Un-normalize for comparison - ylm /= np.sqrt(2. * n + 1.) - ref_vals.append(ylm) - - test_vals = [] - test_vals = openmc.lib.math.calc_rn(max_order, test_uvw) - - assert np.allclose(ref_vals, test_vals) - - -def test_calc_zn(): - n = 10 - rho = 0.5 - phi = 0.5 - - # Reference solution from running the C++ implementation - ref_vals = np.array([ - 1.00000000e+00, 2.39712769e-01, 4.38791281e-01, - 2.10367746e-01, -5.00000000e-01, 1.35075576e-01, - 1.24686873e-01, -2.99640962e-01, -5.48489101e-01, - 8.84215021e-03, 5.68310892e-02, -4.20735492e-01, - -1.25000000e-01, -2.70151153e-01, -2.60091773e-02, - 1.87022545e-02, -3.42888902e-01, 1.49820481e-01, - 2.74244551e-01, -2.43159131e-02, -2.50357380e-02, - 2.20500013e-03, -1.98908812e-01, 4.07587508e-01, - 4.37500000e-01, 2.61708929e-01, 9.10321205e-02, - -1.54686328e-02, -2.74049397e-03, -7.94845816e-02, - 4.75368705e-01, 7.11647284e-02, 1.30266162e-01, - 3.37106977e-02, 1.06401886e-01, -7.31606787e-03, - -2.95625975e-03, -1.10250006e-02, 3.55194307e-01, - -1.44627826e-01, -2.89062500e-01, -9.28644588e-02, - -1.62557358e-01, 7.73431638e-02, -2.55329539e-03, - -1.90923851e-03, 1.57578403e-02, 1.72995854e-01, - -3.66267690e-01, -1.81657333e-01, -3.32521518e-01, - -2.59738162e-02, -2.31580576e-01, 4.20673902e-02, - -4.11710546e-04, -9.36449487e-04, 1.92156884e-02, - 2.82515641e-02, -3.90713738e-01, -1.69280296e-01, - -8.98437500e-02, -1.08693628e-01, 1.78813094e-01, - -1.98191857e-01, 1.65964201e-02, 2.77013853e-04]) - - test_vals = openmc.lib.math.calc_zn(n, rho, phi) - - assert np.allclose(ref_vals, test_vals) - - -def test_calc_zn_rad(): - n = 10 - rho = 0.5 - - # Reference solution from running the C++ implementation - ref_vals = np.array([ - 1.00000000e+00, -5.00000000e-01, -1.25000000e-01, - 4.37500000e-01, -2.89062500e-01,-8.98437500e-02]) - - test_vals = openmc.lib.math.calc_zn_rad(n, rho) - - assert np.allclose(ref_vals, test_vals) - - -def test_rotate_angle(): - uvw0 = np.array([1., 0., 0.]) - phi = 0. - mu = 0. - - # reference: mu of 0 pulls the vector the bottom, so: - ref_uvw = np.array([0., 0., -1.]) - - test_uvw = openmc.lib.math.rotate_angle(uvw0, mu, phi) - - assert np.array_equal(ref_uvw, test_uvw) - - # Repeat for mu = 1 (no change) - mu = 1. - ref_uvw = np.array([1., 0., 0.]) - - test_uvw = openmc.lib.math.rotate_angle(uvw0, mu, phi) - - assert np.array_equal(ref_uvw, test_uvw) - - # Now to test phi is None - mu = 0.9 - settings = openmc.lib.settings - settings.seed = 1 - - # When seed = 1, phi will be sampled as 1.9116495709698769 - # The resultant reference is from hand-calculations given the above - ref_uvw = [0.9, 0.410813051297112, 0.1457142302040] - test_uvw = openmc.lib.math.rotate_angle(uvw0, mu) - - assert np.allclose(ref_uvw, test_uvw) - - -def test_maxwell_spectrum(): - settings = openmc.lib.settings - settings.seed = 1 - T = 0.5 - ref_val = 0.6129982175261098 - test_val = openmc.lib.math.maxwell_spectrum(T) - - assert ref_val == test_val - - -def test_watt_spectrum(): - settings = openmc.lib.settings - settings.seed = 1 - a = 0.5 - b = 0.75 - ref_val = 0.6247242713640233 - test_val = openmc.lib.math.watt_spectrum(a, b) - - assert ref_val == test_val - - -def test_normal_dist(): - settings = openmc.lib.settings - settings.seed = 1 - a = 14.08 - b = 0.0 - ref_val = 14.08 - test_val = openmc.lib.math.normal_variate(a, b) - - assert ref_val == pytest.approx(test_val) - - settings.seed = 1 - a = 14.08 - b = 1.0 - ref_val = 16.436645416691427 - test_val = openmc.lib.math.normal_variate(a, b) - - assert ref_val == pytest.approx(test_val) - - -def test_broaden_wmp_polynomials(): - # Two branches of the code to worry about, beta > 6 and otherwise - # beta = sqrtE * dopp - # First lets do beta > 6 - test_E = 0.5 - test_dopp = 100. # approximately U235 at room temperature - n = 6 - - ref_val = [2., 1.41421356, 1.0001, 0.70731891, 0.50030001, 0.353907] - test_val = openmc.lib.math.broaden_wmp_polynomials(test_E, test_dopp, n) - - assert np.allclose(ref_val, test_val) - - # now beta < 6 - test_dopp = 5. - ref_val = [1.99999885, 1.41421356, 1.04, 0.79195959, 0.6224, 0.50346003] - test_val = openmc.lib.math.broaden_wmp_polynomials(test_E, test_dopp, n) - - assert np.allclose(ref_val, test_val) diff --git a/tests/unit_tests/test_mesh_from_lattice.py b/tests/unit_tests/test_mesh_from_lattice.py deleted file mode 100644 index 0a01387cd..000000000 --- a/tests/unit_tests/test_mesh_from_lattice.py +++ /dev/null @@ -1,116 +0,0 @@ -import numpy as np -import openmc -import pytest - - -@pytest.fixture(scope='module') -def pincell1(uo2, water): - cyl = openmc.ZCylinder(r=0.35) - fuel = openmc.Cell(fill=uo2, region=-cyl) - moderator = openmc.Cell(fill=water, region=+cyl) - - univ = openmc.Universe(cells=[fuel, moderator]) - univ.fuel = fuel - univ.moderator = moderator - return univ - - -@pytest.fixture(scope='module') -def pincell2(uo2, water): - cyl = openmc.ZCylinder(r=0.4) - fuel = openmc.Cell(fill=uo2, region=-cyl) - moderator = openmc.Cell(fill=water, region=+cyl) - - univ = openmc.Universe(cells=[fuel, moderator]) - univ.fuel = fuel - univ.moderator = moderator - return univ - - -@pytest.fixture(scope='module') -def zr(): - zr = openmc.Material() - zr.add_element('Zr', 1.0) - zr.set_density('g/cm3', 1.0) - return zr - - -@pytest.fixture(scope='module') -def rlat2(pincell1, pincell2, uo2, water, zr): - """2D Rectangular lattice for testing.""" - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - n = 3 - u1, u2 = pincell1, pincell2 - lattice = openmc.RectLattice() - lattice.lower_left = (-pitch*n/2, -pitch*n/2) - lattice.pitch = (pitch, pitch) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [u1, u2, u1], - [u2, u1, u2], - [u2, u1, u1] - ] - - return lattice - - -@pytest.fixture(scope='module') -def rlat3(pincell1, pincell2, uo2, water, zr): - """3D Rectangular lattice for testing.""" - - # Create another universe for top layer - hydrogen = openmc.Material() - hydrogen.add_element('H', 1.0) - hydrogen.set_density('g/cm3', 0.09) - h_cell = openmc.Cell(fill=hydrogen) - u3 = openmc.Universe(cells=[h_cell]) - - all_zr = openmc.Cell(fill=zr) - pitch = 1.2 - n = 3 - u1, u2 = pincell1, pincell2 - lattice = openmc.RectLattice() - lattice.lower_left = (-pitch*n/2, -pitch*n/2, -10.0) - lattice.pitch = (pitch, pitch, 10.0) - lattice.outer = openmc.Universe(cells=[all_zr]) - lattice.universes = [ - [[u1, u2, u1], - [u2, u1, u2], - [u2, u1, u1]], - [[u3, u1, u2], - [u1, u3, u2], - [u2, u1, u1]] - ] - - return lattice - - -def test_mesh2d(rlat2): - shape = np.array(rlat2.shape) - width = shape*rlat2.pitch - - mesh1 = openmc.RegularMesh.from_rect_lattice(rlat2) - assert np.array_equal(mesh1.dimension, (3, 3)) - assert np.array_equal(mesh1.lower_left, rlat2.lower_left) - assert np.array_equal(mesh1.upper_right, rlat2.lower_left + width) - - mesh2 = openmc.RegularMesh.from_rect_lattice(rlat2, division=3) - assert np.array_equal(mesh2.dimension, (9, 9)) - assert np.array_equal(mesh2.lower_left, rlat2.lower_left) - assert np.array_equal(mesh2.upper_right, rlat2.lower_left + width) - - -def test_mesh3d(rlat3): - shape = np.array(rlat3.shape) - width = shape*rlat3.pitch - - mesh1 = openmc.RegularMesh.from_rect_lattice(rlat3) - assert np.array_equal(mesh1.dimension, (3, 3, 2)) - assert np.array_equal(mesh1.lower_left, rlat3.lower_left) - assert np.array_equal(mesh1.upper_right, rlat3.lower_left + width) - - mesh2 = openmc.RegularMesh.from_rect_lattice(rlat3, division=3) - assert np.array_equal(mesh2.dimension, (9, 9, 6)) - assert np.array_equal(mesh2.lower_left, rlat3.lower_left) - assert np.array_equal(mesh2.upper_right, rlat3.lower_left + width) diff --git a/tests/unit_tests/test_model_triso.py b/tests/unit_tests/test_model_triso.py deleted file mode 100644 index c1f8c039e..000000000 --- a/tests/unit_tests/test_model_triso.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python - -from math import pi - -import numpy as np -from numpy.linalg import norm -import openmc -import openmc.model -import pytest -import scipy.spatial - - -_RADIUS = 0.1 -_PACKING_FRACTION = 0.35 -_PARAMS = [ - {'shape': 'rectangular_prism', 'volume': 1**3}, - {'shape': 'x_cylinder', 'volume': 1*pi*1**2}, - {'shape': 'y_cylinder', 'volume': 1*pi*1**2}, - {'shape': 'z_cylinder', 'volume': 1*pi*1**2}, - {'shape': 'sphere', 'volume': 4/3*pi*1**3}, - {'shape': 'spherical_shell', 'volume': 4/3*pi*(1**3 - 0.5**3)} -] - - -@pytest.fixture(scope='module', params=_PARAMS) -def container(request): - return request.param - - -@pytest.fixture(scope='module') -def centers(request, container): - return request.getfixturevalue('centers_' + container['shape']) - - -@pytest.fixture(scope='module') -def centers_rectangular_prism(): - min_x = openmc.XPlane(0) - max_x = openmc.XPlane(1) - min_y = openmc.YPlane(0) - max_y = openmc.YPlane(1) - min_z = openmc.ZPlane(0) - max_z = openmc.ZPlane(1) - region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def centers_x_cylinder(): - cylinder = openmc.XCylinder(r=1, y0=1, z0=2) - min_x = openmc.XPlane(0) - max_x = openmc.XPlane(1) - region = +min_x & -max_x & -cylinder - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def centers_y_cylinder(): - cylinder = openmc.YCylinder(r=1, x0=1, z0=2) - min_y = openmc.YPlane(0) - max_y = openmc.YPlane(1) - region = +min_y & -max_y & -cylinder - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def centers_z_cylinder(): - cylinder = openmc.ZCylinder(r=1, x0=1, y0=2) - min_z = openmc.ZPlane(0) - max_z = openmc.ZPlane(1) - region = +min_z & -max_z & -cylinder - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def centers_sphere(): - sphere = openmc.Sphere(r=1, x0=1, y0=2, z0=3) - region = -sphere - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def centers_spherical_shell(): - sphere = openmc.Sphere(r=1, x0=1, y0=2, z0=3) - inner_sphere = openmc.Sphere(r=0.5, x0=1, y0=2, z0=3) - region = -sphere & +inner_sphere - return openmc.model.pack_spheres(radius=_RADIUS, region=region, - pf=_PACKING_FRACTION, initial_pf=0.2) - - -@pytest.fixture(scope='module') -def triso_universe(): - sphere = openmc.Sphere(r=_RADIUS) - cell = openmc.Cell(region=-sphere) - univ = openmc.Universe(cells=[cell]) - return univ - - -def test_overlap(centers): - """Check that none of the spheres in the packed configuration overlap.""" - # Create KD tree for quick nearest neighbor search - tree = scipy.spatial.cKDTree(centers) - - # Find distance to nearest neighbor for all spheres - d = tree.query(centers, k=2)[0] - - # Get the smallest distance between any two spheres - d_min = min(d[:, 1]) - assert d_min > 2*_RADIUS or d_min == pytest.approx(2*_RADIUS) - - -def test_contained_rectangular_prism(centers_rectangular_prism): - """Make sure all spheres are entirely contained within the domain.""" - d_max = np.amax(centers_rectangular_prism) + _RADIUS - d_min = np.amin(centers_rectangular_prism) - _RADIUS - assert d_max < 1 or d_max == pytest.approx(1) - assert d_min > 0 or d_min == pytest.approx(0) - - -def test_contained_x_cylinder(centers_x_cylinder): - """Make sure all spheres are entirely contained within the domain.""" - d = np.linalg.norm(centers_x_cylinder[:,[1,2]] - [1, 2], axis=1) - r_max = max(d) + _RADIUS - x_max = max(centers_x_cylinder[:,0]) + _RADIUS - x_min = min(centers_x_cylinder[:,0]) - _RADIUS - assert r_max < 1 or r_max == pytest.approx(1) - assert x_max < 1 or x_max == pytest.approx(1) - assert x_min > 0 or x_min == pytest.approx(0) - - -def test_contained_y_cylinder(centers_y_cylinder): - """Make sure all spheres are entirely contained within the domain.""" - d = np.linalg.norm(centers_y_cylinder[:,[0,2]] - [1, 2], axis=1) - r_max = max(d) + _RADIUS - y_max = max(centers_y_cylinder[:,1]) + _RADIUS - y_min = min(centers_y_cylinder[:,1]) - _RADIUS - assert r_max < 1 or r_max == pytest.approx(1) - assert y_max < 1 or y_max == pytest.approx(1) - assert y_min > 0 or y_min == pytest.approx(0) - - -def test_contained_z_cylinder(centers_z_cylinder): - """Make sure all spheres are entirely contained within the domain.""" - d = np.linalg.norm(centers_z_cylinder[:,[0,1]] - [1, 2], axis=1) - r_max = max(d) + _RADIUS - z_max = max(centers_z_cylinder[:,2]) + _RADIUS - z_min = min(centers_z_cylinder[:,2]) - _RADIUS - assert r_max < 1 or r_max == pytest.approx(1) - assert z_max < 1 or z_max == pytest.approx(1) - assert z_min > 0 or z_min == pytest.approx(0) - - -def test_contained_sphere(centers_sphere): - """Make sure all spheres are entirely contained within the domain.""" - d = np.linalg.norm(centers_sphere - [1, 2, 3], axis=1) - r_max = max(d) + _RADIUS - assert r_max < 1 or r_max == pytest.approx(1) - - -def test_contained_spherical_shell(centers_spherical_shell): - """Make sure all spheres are entirely contained within the domain.""" - d = np.linalg.norm(centers_spherical_shell - [1, 2, 3], axis=1) - r_max = max(d) + _RADIUS - r_min = min(d) - _RADIUS - assert r_max < 1 or r_max == pytest.approx(1) - assert r_min > 0.5 or r_min == pytest.approx(0.5) - - -def test_packing_fraction(container, centers): - """Check that the actual PF is close to the requested PF.""" - pf = len(centers) * 4/3 * pi *_RADIUS**3 / container['volume'] - assert pf == pytest.approx(_PACKING_FRACTION, rel=1e-2) - - -def test_num_spheres(): - """Check that the function returns the correct number of spheres""" - centers = openmc.model.pack_spheres( - radius=_RADIUS, region=-openmc.Sphere(r=1), num_spheres=50 - ) - assert len(centers) == 50 - - -def test_triso_lattice(triso_universe, centers_rectangular_prism): - trisos = [openmc.model.TRISO(_RADIUS, triso_universe, c) - for c in centers_rectangular_prism] - - lower_left = np.array((0, 0, 0)) - upper_right = np.array((1, 1, 1)) - shape = (3, 3, 3) - pitch = (upper_right - lower_left)/shape - background = openmc.Material() - - lattice = openmc.model.create_triso_lattice( - trisos, lower_left, pitch, shape, background - ) - - -def test_container_input(triso_universe): - # Invalid container shape - with pytest.raises(ValueError): - centers = openmc.model.pack_spheres( - radius=_RADIUS, region=+openmc.Sphere(r=1), num_spheres=100 - ) - - -def test_packing_fraction_input(): - # Provide neither packing fraction nor number of spheres - with pytest.raises(ValueError): - centers = openmc.model.pack_spheres( - radius=_RADIUS, region=-openmc.Sphere(r=1) - ) - - # Specify a packing fraction that is too high for CRP - with pytest.raises(ValueError): - centers = openmc.model.pack_spheres( - radius=_RADIUS, region=-openmc.Sphere(r=1), pf=1 - ) - - # Specify a packing fraction that is too high for RSP - with pytest.raises(ValueError): - centers = openmc.model.pack_spheres( - radius=_RADIUS, region=-openmc.Sphere(r=1), pf=0.5, initial_pf=0.4 - ) diff --git a/tests/unit_tests/test_pin.py b/tests/unit_tests/test_pin.py deleted file mode 100644 index c2a5bc9c0..000000000 --- a/tests/unit_tests/test_pin.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -Tests for constructing Pin universes -""" - -import numpy as np -import pytest - -import openmc -from openmc.model import pin - - -def get_pin_radii(pin_univ): - """Return a sorted list of all radii from pin""" - rads = set() - - for cell in pin_univ.get_all_cells().values(): - surfs = cell.region.get_surfaces().values() - rads.update(set(s.r for s in surfs)) - - return list(sorted(rads)) - - -@pytest.fixture -def pin_mats(): - fuel = openmc.Material(name="UO2") - fuel.volume = 100 - clad = openmc.Material(name="zirc") - clad.volume = 100 - water = openmc.Material(name="water") - return fuel, clad, water - - -@pytest.fixture -def good_radii(): - return (0.4, 0.42) - - -def test_failure(pin_mats, good_radii): - """Check for various failure modes""" - good_surfaces = [openmc.ZCylinder(r=r) for r in good_radii] - # Bad material type - with pytest.raises(TypeError): - pin(good_surfaces, [mat.name for mat in pin_mats]) - - # Incorrect lengths - with pytest.raises(ValueError, match="length"): - pin(good_surfaces[:len(pin_mats) - 2], pin_mats) - - # Non-positive radii - rad = [openmc.ZCylinder(r=-0.1)] + good_surfaces[1:] - with pytest.raises(ValueError, match="index 0"): - pin(rad, pin_mats) - - # Non-increasing radii - surfs = tuple(reversed(good_surfaces)) - with pytest.raises(ValueError, match="index 1"): - pin(surfs, pin_mats) - - # Bad orientation - surfs = [openmc.XCylinder(r=good_surfaces[0].r)] + good_surfaces[1:] - with pytest.raises(TypeError, match="surfaces"): - pin(surfs, pin_mats) - - # Passing cells argument - with pytest.raises(SyntaxError, match="Cells"): - pin(surfs, pin_mats, cells=[]) - - -def test_pins_of_universes(pin_mats, good_radii): - """Build a pin with a Universe in one ring""" - u1 = openmc.Universe(cells=[openmc.Cell(fill=pin_mats[1])]) - new_items = pin_mats[:1] + (u1, ) + pin_mats[2:] - new_pin = pin( - [openmc.ZCylinder(r=r) for r in good_radii], new_items, - subdivisions={0: 2}, divide_vols=True) - assert len(new_pin.cells) == len(pin_mats) + 1 - - -@pytest.mark.parametrize( - "surf_type", [openmc.ZCylinder, openmc.XCylinder, openmc.YCylinder]) -def test_subdivide(pin_mats, good_radii, surf_type): - """Test the subdivision with various orientations""" - surfs = [surf_type(r=r) for r in good_radii] - fresh = pin(surfs, pin_mats, name="fresh pin") - assert len(fresh.cells) == len(pin_mats) - assert fresh.name == "fresh pin" - - # subdivide inner region - N = 5 - div0 = pin(surfs, pin_mats, {0: N}) - assert len(div0.cells) == len(pin_mats) + N - 1 - - # Check volume of fuel material - for mid, mat in div0.get_all_materials().items(): - if mat.name == "UO2": - assert mat.volume == pytest.approx(100 / N) - - # check volumes of new rings - radii = get_pin_radii(div0) - bounds = [0] + radii[:N] - sqrs = np.square(bounds) - assert np.all(sqrs[1:] - sqrs[:-1] == pytest.approx(good_radii[0] ** 2 / N)) - - # subdivide non-inner most region - new_pin = pin(surfs, pin_mats, {1: N}) - assert len(new_pin.cells) == len(pin_mats) + N - 1 - - # Check volume of clad material - for mid, mat in div0.get_all_materials().items(): - if mat.name == "zirc": - assert mat.volume == pytest.approx(100 / N) - - # check volumes of new rings - radii = get_pin_radii(new_pin) - sqrs = np.square(radii[:N + 1]) - assert np.all(sqrs[1:] - sqrs[:-1] == pytest.approx( - (good_radii[1] ** 2 - good_radii[0] ** 2) / N)) diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py deleted file mode 100644 index f2d3e1014..000000000 --- a/tests/unit_tests/test_plots.py +++ /dev/null @@ -1,94 +0,0 @@ -import openmc -import openmc.examples -import pytest - - -@pytest.fixture(scope='module') -def myplot(): - plot = openmc.Plot(name='myplot') - plot.width = (100., 100.) - plot.origin = (2., 3., -10.) - plot.pixels = (500, 500) - plot.filename = 'myplot' - plot.type = 'slice' - plot.basis = 'yz' - plot.background = (0, 0, 0) - plot.background = 'black' - - plot.color_by = 'material' - m1, m2 = openmc.Material(), openmc.Material() - plot.colors = {m1: (0, 255, 0), m2: (0, 0, 255)} - plot.colors = {m1: 'green', m2: 'blue'} - - plot.mask_components = [openmc.Material()] - plot.mask_background = (255, 255, 255) - plot.mask_background = 'white' - - plot.overlap_color = (255, 211, 0) - plot.overlap_color = 'yellow' - plot.show_overlaps = True - - plot.level = 1 - plot.meshlines = { - 'type': 'tally', - 'id': 1, - 'linewidth': 2, - 'color': (40, 30, 20) - } - return plot - - -def test_attributes(myplot): - assert myplot.name == 'myplot' - - -def test_repr(myplot): - r = repr(myplot) - assert isinstance(r, str) - - -def test_from_geometry(): - width = 25. - s = openmc.Sphere(r=width/2, boundary_type='vacuum') - c = openmc.Cell(region=-s) - univ = openmc.Universe(cells=[c]) - geom = openmc.Geometry(univ) - - for basis in ('xy', 'yz', 'xz'): - plot = openmc.Plot.from_geometry(geom, basis) - assert plot.origin == pytest.approx((0., 0., 0.)) - assert plot.width == pytest.approx((width, width)) - - -def test_highlight_domains(): - plot = openmc.Plot() - plot.color_by = 'material' - plots = openmc.Plots([plot]) - - model = openmc.examples.pwr_pin_cell() - mats = {m for m in model.materials if 'UO2' in m.name} - plots.highlight_domains(model.geometry, mats) - - -def test_to_xml_element(myplot): - elem = myplot.to_xml_element() - assert 'id' in elem.attrib - assert 'color_by' in elem.attrib - assert 'type' in elem.attrib - assert elem.find('origin') is not None - assert elem.find('width') is not None - assert elem.find('pixels') is not None - assert elem.find('background').text == '0 0 0' - - -def test_plots(run_in_tmpdir): - p1 = openmc.Plot(name='plot1') - p2 = openmc.Plot(name='plot2') - plots = openmc.Plots([p1, p2]) - assert len(plots) == 2 - - p3 = openmc.Plot(name='plot3') - plots.append(p3) - assert len(plots) == 3 - - plots.export_to_xml() diff --git a/tests/unit_tests/test_polynomials.py b/tests/unit_tests/test_polynomials.py deleted file mode 100644 index f6ac2711f..000000000 --- a/tests/unit_tests/test_polynomials.py +++ /dev/null @@ -1,44 +0,0 @@ -import numpy as np - -import openmc - - -def test_zernike_radial(): - coeff = np.asarray([1.3, -3.0, 9e-1, -6e-1, 0.11]) - zn_rad = openmc.ZernikeRadial(coeff) - assert zn_rad.order == 8 - assert zn_rad.radius == 1 - - coeff = np.asarray([1.3, -3.0, 9e-1, -6e-1, 0.11, 0.222]) - zn_rad = openmc.ZernikeRadial(coeff, 0.392) - assert zn_rad.order == 10 - assert zn_rad.radius == 0.392 - norm_vec = (2 * np.arange(6) + 1) / (np.pi * 0.392 ** 2) - norm_coeff = norm_vec * coeff - - rho = 0.5 - # Reference solution from running the Fortran implementation - raw_zn = np.array([ - 1.00000000e+00, -5.00000000e-01, -1.25000000e-01, - 4.37500000e-01, -2.89062500e-01, -8.98437500e-02]) - - ref_vals = np.sum(norm_coeff * raw_zn) - - test_vals = zn_rad(rho) - - assert ref_vals == test_vals - - rho = [0.2, 0.5] - # Reference solution from running the Fortran implementation - raw_zn1 = np.array([ - 1.00000000e+00, -9.20000000e-01, 7.69600000e-01, - -5.66720000e-01, 3.35219200e-01, -1.01747000e-01]) - raw_zn2 = np.array([ - 1.00000000e+00, -5.00000000e-01, -1.25000000e-01, - 4.37500000e-01, -2.89062500e-01, -8.98437500e-02]) - - ref_vals = [np.sum(norm_coeff * raw_zn1), np.sum(norm_coeff * raw_zn2)] - - test_vals = zn_rad(rho) - - assert np.allclose(ref_vals, test_vals) diff --git a/tests/unit_tests/test_region.py b/tests/unit_tests/test_region.py deleted file mode 100644 index f9656ebb4..000000000 --- a/tests/unit_tests/test_region.py +++ /dev/null @@ -1,180 +0,0 @@ -import numpy as np -import pytest -import openmc - -from tests.unit_tests import assert_unbounded - - -@pytest.fixture -def reset(): - openmc.reset_auto_ids() - - -def test_union(reset): - s1 = openmc.XPlane(x0=5, surface_id=1) - s2 = openmc.XPlane(x0=-5, surface_id=2) - region = +s1 | -s2 - assert isinstance(region, openmc.Union) - - # Check bounding box - assert_unbounded(region) - - # __contains__ - assert (6, 0, 0) in region - assert (-6, 0, 0) in region - assert (0, 0, 0) not in region - - # string representation - assert str(region) == '(1 | -2)' - - # Combining region with intersection - s3 = openmc.YPlane(surface_id=3) - reg2 = region & +s3 - assert (6, 1, 0) in reg2 - assert (6, -1, 0) not in reg2 - assert str(reg2) == '((1 | -2) 3)' - - # translate method - regt = region.translate((2.0, 0.0, 0.0)) - assert (-4, 0, 0) in regt - assert (6, 0, 0) not in regt - assert (8, 0, 0) in regt - - -def test_intersection(reset): - s1 = openmc.XPlane(x0=5, surface_id=1) - s2 = openmc.XPlane(x0=-5, surface_id=2) - region = -s1 & +s2 - assert isinstance(region, openmc.Intersection) - - # Check bounding box - ll, ur = region.bounding_box - assert ll == pytest.approx((-5, -np.inf, -np.inf)) - assert ur == pytest.approx((5, np.inf, np.inf)) - - # __contains__ - assert (6, 0, 0) not in region - assert (-6, 0, 0) not in region - assert (0, 0, 0) in region - - # string representation - assert str(region) == '(-1 2)' - - # Combining region with union - s3 = openmc.YPlane(surface_id=3) - reg2 = region | +s3 - assert (-6, 2, 0) in reg2 - assert (-6, -2, 0) not in reg2 - assert str(reg2) == '((-1 2) | 3)' - - # translate method - regt = region.translate((2.0, 0.0, 0.0)) - assert (-4, 0, 0) not in regt - assert (6, 0, 0) in regt - assert (8, 0, 0) not in regt - - -def test_complement(reset): - zcyl = openmc.ZCylinder(r=1., surface_id=1) - z0 = openmc.ZPlane(-5., surface_id=2) - z1 = openmc.ZPlane(5., surface_id=3) - outside = +zcyl | -z0 | +z1 - inside = ~outside - outside_equiv = ~(-zcyl & +z0 & -z1) - inside_equiv = ~outside_equiv - - # Check bounding box - for region in (inside, inside_equiv): - ll, ur = region.bounding_box - assert ll == pytest.approx((-1., -1., -5.)) - assert ur == pytest.approx((1., 1., 5.)) - assert_unbounded(outside) - assert_unbounded(outside_equiv) - - # string represention - assert str(inside) == '~(1 | -2 | 3)' - - # evaluate method - assert (0, 0, 0) in inside - assert (0, 0, 0) not in outside - assert (0, 0, 6) not in inside - assert (0, 0, 6) in outside - - # translate method - inside_t = inside.translate((1.0, 1.0, 1.0)) - ll, ur = inside_t.bounding_box - assert ll == pytest.approx((0., 0., -4.)) - assert ur == pytest.approx((2., 2., 6.)) - - -def test_get_surfaces(): - s1 = openmc.XPlane() - s2 = openmc.YPlane() - s3 = openmc.ZPlane() - region = (+s1 & -s2) | +s3 - - # Make sure get_surfaces() returns all surfaces - surfs = set(region.get_surfaces().values()) - assert not (surfs ^ {s1, s2, s3}) - - inverse = ~region - surfs = set(inverse.get_surfaces().values()) - assert not (surfs ^ {s1, s2, s3}) - - -def test_extend_clone(): - s1 = openmc.XPlane() - s2 = openmc.YPlane() - s3 = openmc.ZPlane() - s4 = openmc.ZCylinder() - - # extend intersection - r1 = +s1 & -s2 - r1 &= +s3 & -s4 - assert r1[:] == [+s1, -s2, +s3, -s4] - - # extend union - r2 = +s1 | -s2 - r2 |= +s3 | -s4 - assert r2[:] == [+s1, -s2, +s3, -s4] - - # clone methods - r3 = r1.clone() - assert len(r3) == len(r1) - r4 = r2.clone() - assert len(r4) == len(r2) - - r5 = ~r1 - r6 = r5.clone() - - -def test_from_expression(reset): - # Create surface dictionary - s1 = openmc.ZCylinder(surface_id=1) - s2 = openmc.ZPlane(-10., surface_id=2) - s3 = openmc.ZPlane(10., surface_id=3) - surfs = {1: s1, 2: s2, 3: s3} - - r = openmc.Region.from_expression('-1 2 -3', surfs) - assert isinstance(r, openmc.Intersection) - assert r[:] == [-s1, +s2, -s3] - - r = openmc.Region.from_expression('+1 | -2 | +3', surfs) - assert isinstance(r, openmc.Union) - assert r[:] == [+s1, -s2, +s3] - - r = openmc.Region.from_expression('~(-1)', surfs) - assert r == +s1 - - # Since & has higher precendence than |, the resulting region should be an - # instance of Union - r = openmc.Region.from_expression('1 -2 | 3', surfs) - assert isinstance(r, openmc.Union) - assert isinstance(r[0], openmc.Intersection) - assert r[0][:] == [+s1, -s2] - - # ...but not if we use parentheses - r = openmc.Region.from_expression('1 (-2 | 3)', surfs) - assert isinstance(r, openmc.Intersection) - assert isinstance(r[1], openmc.Union) - assert r[1][:] == [-s2, +s3] diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py deleted file mode 100644 index 9c33f6a2d..000000000 --- a/tests/unit_tests/test_settings.py +++ /dev/null @@ -1,106 +0,0 @@ -import openmc -import openmc.stats - - -def test_export_to_xml(run_in_tmpdir): - s = openmc.Settings() - s.run_mode = 'fixed source' - s.batches = 1000 - s.generations_per_batch = 10 - s.inactive = 100 - s.particles = 1000000 - s.keff_trigger = {'type': 'std_dev', 'threshold': 0.001} - s.energy_mode = 'continuous-energy' - s.max_order = 5 - s.source = openmc.Source(space=openmc.stats.Point()) - s.output = {'summary': True, 'tallies': False, 'path': 'here'} - s.verbosity = 7 - s.sourcepoint = {'batches': [50, 150, 500, 1000], 'separate': True, - 'write': True, 'overwrite': True} - s.statepoint = {'batches': [50, 150, 500, 1000]} - s.confidence_intervals = True - s.ptables = True - s.seed = 17 - s.survival_biasing = True - s.cutoff = {'weight': 0.25, 'weight_avg': 0.5, 'energy_neutron': 1.0e-5, - 'energy_photon': 1000.0, 'energy_electron': 1.0e-5, - 'energy_positron': 1.0e-5} - mesh = openmc.RegularMesh() - mesh.lower_left = (-10., -10., -10.) - mesh.upper_right = (10., 10., 10.) - mesh.dimension = (5, 5, 5) - s.entropy_mesh = mesh - s.trigger_active = True - s.trigger_max_batches = 10000 - s.trigger_batch_interval = 50 - s.no_reduce = False - s.tabular_legendre = {'enable': True, 'num_points': 50} - s.temperature = {'default': 293.6, 'method': 'interpolation', - 'multipole': True, 'range': (200., 1000.)} - s.trace = (10, 1, 20) - s.track = [1, 1, 1, 2, 1, 1] - s.ufs_mesh = mesh - s.resonance_scattering = {'enable': True, 'method': 'rvs', - 'energy_min': 1.0, 'energy_max': 1000.0, - 'nuclides': ['U235', 'U238', 'Pu239']} - s.volume_calculations = openmc.VolumeCalculation( - domains=[openmc.Cell()], samples=1000, lower_left=(-10., -10., -10.), - upper_right = (10., 10., 10.)) - s.create_fission_neutrons = True - s.log_grid_bins = 2000 - s.photon_transport = False - s.electron_treatment = 'led' - s.dagmc = False - - # Make sure exporting XML works - s.export_to_xml() - - # Generate settings from XML - s = openmc.Settings.from_xml() - assert s.run_mode == 'fixed source' - assert s.batches == 1000 - assert s.generations_per_batch == 10 - assert s.inactive == 100 - assert s.particles == 1000000 - assert s.keff_trigger == {'type': 'std_dev', 'threshold': 0.001} - assert s.energy_mode == 'continuous-energy' - assert s.max_order == 5 - assert isinstance(s.source[0], openmc.Source) - assert isinstance(s.source[0].space, openmc.stats.Point) - assert s.output == {'summary': True, 'tallies': False, 'path': 'here'} - assert s.verbosity == 7 - assert s.sourcepoint == {'batches': [50, 150, 500, 1000], 'separate': True, - 'write': True, 'overwrite': True} - assert s.statepoint == {'batches': [50, 150, 500, 1000]} - assert s.confidence_intervals - assert s.ptables - assert s.seed == 17 - assert s.survival_biasing - assert s.cutoff == {'weight': 0.25, 'weight_avg': 0.5, - 'energy_neutron': 1.0e-5, 'energy_photon': 1000.0, - 'energy_electron': 1.0e-5, 'energy_positron': 1.0e-5} - assert isinstance(s.entropy_mesh, openmc.RegularMesh) - assert s.entropy_mesh.lower_left == [-10., -10., -10.] - assert s.entropy_mesh.upper_right == [10., 10., 10.] - assert s.entropy_mesh.dimension == [5, 5, 5] - assert s.trigger_active - assert s.trigger_max_batches == 10000 - assert s.trigger_batch_interval == 50 - assert not s.no_reduce - assert s.tabular_legendre == {'enable': True, 'num_points': 50} - assert s.temperature == {'default': 293.6, 'method': 'interpolation', - 'multipole': True, 'range': [200., 1000.]} - assert s.trace == [10, 1, 20] - assert s.track == [1, 1, 1, 2, 1, 1] - assert isinstance(s.ufs_mesh, openmc.RegularMesh) - assert s.ufs_mesh.lower_left == [-10., -10., -10.] - assert s.ufs_mesh.upper_right == [10., 10., 10.] - assert s.ufs_mesh.dimension == [5, 5, 5] - assert s.resonance_scattering == {'enable': True, 'method': 'rvs', - 'energy_min': 1.0, 'energy_max': 1000.0, - 'nuclides': ['U235', 'U238', 'Pu239']} - assert s.create_fission_neutrons - assert s.log_grid_bins == 2000 - assert not s.photon_transport - assert s.electron_treatment == 'led' - assert not s.dagmc diff --git a/tests/unit_tests/test_source.py b/tests/unit_tests/test_source.py deleted file mode 100644 index 1c70e159d..000000000 --- a/tests/unit_tests/test_source.py +++ /dev/null @@ -1,36 +0,0 @@ -import openmc -import openmc.stats - - -def test_source(): - space = openmc.stats.Point() - energy = openmc.stats.Discrete([1.0e6], [1.0]) - angle = openmc.stats.Isotropic() - - src = openmc.Source(space=space, angle=angle, energy=energy) - assert src.space == space - assert src.angle == angle - assert src.energy == energy - - elem = src.to_xml_element() - assert 'strength' in elem.attrib - assert elem.find('space') is not None - assert elem.find('angle') is not None - assert elem.find('energy') is not None - - src = openmc.Source.from_xml_element(elem) - assert isinstance(src.angle, openmc.stats.Isotropic) - assert src.space.xyz == [0.0, 0.0, 0.0] - assert src.energy.x == [1.0e6] - assert src.energy.p == [1.0] - assert src.strength == 1.0 - - -def test_source_file(): - filename = 'source.h5' - src = openmc.Source(filename=filename) - assert src.file == filename - - elem = src.to_xml_element() - assert 'strength' in elem.attrib - assert 'file' in elem.attrib diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py deleted file mode 100644 index e15958478..000000000 --- a/tests/unit_tests/test_stats.py +++ /dev/null @@ -1,243 +0,0 @@ -from math import pi - -import numpy as np -import pytest -import openmc -import openmc.stats - - -def test_discrete(): - x = [0.0, 1.0, 10.0] - p = [0.3, 0.2, 0.5] - d = openmc.stats.Discrete(x, p) - elem = d.to_xml_element('distribution') - - d = openmc.stats.Discrete.from_xml_element(elem) - assert d.x == x - assert d.p == p - assert len(d) == len(x) - - d = openmc.stats.Univariate.from_xml_element(elem) - assert isinstance(d, openmc.stats.Discrete) - - # Single point - d2 = openmc.stats.Discrete(1e6, 1.0) - assert d2.x == [1e6] - assert d2.p == [1.0] - assert len(d2) == 1 - - -def test_uniform(): - a, b = 10.0, 20.0 - d = openmc.stats.Uniform(a, b) - elem = d.to_xml_element('distribution') - - d = openmc.stats.Uniform.from_xml_element(elem) - assert d.a == a - assert d.b == b - assert len(d) == 2 - - t = d.to_tabular() - assert t.x == [a, b] - assert t.p == [1/(b-a), 1/(b-a)] - assert t.interpolation == 'histogram' - - -def test_maxwell(): - theta = 1.2895e6 - d = openmc.stats.Maxwell(theta) - elem = d.to_xml_element('distribution') - - d = openmc.stats.Maxwell.from_xml_element(elem) - assert d.theta == theta - assert len(d) == 1 - - -def test_watt(): - a, b = 0.965e6, 2.29e-6 - d = openmc.stats.Watt(a, b) - elem = d.to_xml_element('distribution') - - d = openmc.stats.Watt.from_xml_element(elem) - assert d.a == a - assert d.b == b - assert len(d) == 2 - - -def test_tabular(): - x = [0.0, 5.0, 7.0] - p = [0.1, 0.2, 0.05] - d = openmc.stats.Tabular(x, p, 'linear-linear') - elem = d.to_xml_element('distribution') - - d = openmc.stats.Tabular.from_xml_element(elem) - assert d.x == x - assert d.p == p - assert d.interpolation == 'linear-linear' - assert len(d) == len(x) - - -def test_legendre(): - # Pu239 elastic scattering at 100 keV - coeffs = [1.000e+0, 1.536e-1, 1.772e-2, 5.945e-4, 3.497e-5, 1.881e-5] - d = openmc.stats.Legendre(coeffs) - assert d.coefficients == pytest.approx(coeffs) - assert len(d) == len(coeffs) - - # Integrating distribution should yield one - mu = np.linspace(-1., 1., 1000) - assert np.trapz(d(mu), mu) == pytest.approx(1.0, rel=1e-4) - - with pytest.raises(NotImplementedError): - d.to_xml_element('distribution') - - -def test_mixture(): - d1 = openmc.stats.Uniform(0, 5) - d2 = openmc.stats.Uniform(3, 7) - p = [0.5, 0.5] - mix = openmc.stats.Mixture(p, [d1, d2]) - assert mix.probability == p - assert mix.distribution == [d1, d2] - assert len(mix) == 4 - - with pytest.raises(NotImplementedError): - mix.to_xml_element('distribution') - - -def test_polar_azimuthal(): - # default polar-azimuthal should be uniform in mu and phi - d = openmc.stats.PolarAzimuthal() - assert isinstance(d.mu, openmc.stats.Uniform) - assert d.mu.a == -1. - assert d.mu.b == 1. - assert isinstance(d.phi, openmc.stats.Uniform) - assert d.phi.a == 0. - assert d.phi.b == 2*pi - - mu = openmc.stats.Discrete(1., 1.) - phi = openmc.stats.Discrete(0., 1.) - d = openmc.stats.PolarAzimuthal(mu, phi) - assert d.mu == mu - assert d.phi == phi - - elem = d.to_xml_element() - assert elem.tag == 'angle' - assert elem.attrib['type'] == 'mu-phi' - assert elem.find('mu') is not None - assert elem.find('phi') is not None - - d = openmc.stats.PolarAzimuthal.from_xml_element(elem) - assert d.mu.x == [1.] - assert d.mu.p == [1.] - assert d.phi.x == [0.] - assert d.phi.p == [1.] - - d = openmc.stats.UnitSphere.from_xml_element(elem) - assert isinstance(d, openmc.stats.PolarAzimuthal) - - -def test_isotropic(): - d = openmc.stats.Isotropic() - elem = d.to_xml_element() - assert elem.tag == 'angle' - assert elem.attrib['type'] == 'isotropic' - - d = openmc.stats.Isotropic.from_xml_element(elem) - assert isinstance(d, openmc.stats.Isotropic) - - -def test_monodirectional(): - d = openmc.stats.Monodirectional((1., 0., 0.)) - elem = d.to_xml_element() - assert elem.tag == 'angle' - assert elem.attrib['type'] == 'monodirectional' - - d = openmc.stats.Monodirectional.from_xml_element(elem) - assert d.reference_uvw == pytest.approx((1., 0., 0.)) - - -def test_cartesian(): - x = openmc.stats.Uniform(-10., 10.) - y = openmc.stats.Uniform(-10., 10.) - z = openmc.stats.Uniform(0., 20.) - d = openmc.stats.CartesianIndependent(x, y, z) - - elem = d.to_xml_element() - assert elem.tag == 'space' - assert elem.attrib['type'] == 'cartesian' - assert elem.find('x') is not None - assert elem.find('y') is not None - - d = openmc.stats.CartesianIndependent.from_xml_element(elem) - assert d.x == x - assert d.y == y - assert d.z == z - - d = openmc.stats.Spatial.from_xml_element(elem) - assert isinstance(d, openmc.stats.CartesianIndependent) - - -def test_box(): - lower_left = (-10., -10., -10.) - upper_right = (10., 10., 10.) - d = openmc.stats.Box(lower_left, upper_right) - - elem = d.to_xml_element() - assert elem.tag == 'space' - assert elem.attrib['type'] == 'box' - assert elem.find('parameters') is not None - - d = openmc.stats.Box.from_xml_element(elem) - assert d.lower_left == pytest.approx(lower_left) - assert d.upper_right == pytest.approx(upper_right) - assert not d.only_fissionable - - # only fissionable parameter - d2 = openmc.stats.Box(lower_left, upper_right, True) - assert d2.only_fissionable - elem = d2.to_xml_element() - assert elem.attrib['type'] == 'fission' - d = openmc.stats.Spatial.from_xml_element(elem) - assert isinstance(d, openmc.stats.Box) - - -def test_point(): - p = (-4., 2., 10.) - d = openmc.stats.Point(p) - - elem = d.to_xml_element() - assert elem.tag == 'space' - assert elem.attrib['type'] == 'point' - assert elem.find('parameters') is not None - - d = openmc.stats.Point.from_xml_element(elem) - assert d.xyz == pytest.approx(p) - -def test_normal(): - mean = 10.0 - std_dev = 2.0 - d = openmc.stats.Normal(mean,std_dev) - - elem = d.to_xml_element('distribution') - assert elem.attrib['type'] == 'normal' - - d = openmc.stats.Normal.from_xml_element(elem) - assert d.mean_value == pytest.approx(mean) - assert d.std_dev == pytest.approx(std_dev) - assert len(d) == 2 - -def test_muir(): - mean = 10.0 - mass = 5.0 - temp = 20000. - d = openmc.stats.Muir(mean,mass,temp) - - elem = d.to_xml_element('energy') - assert elem.attrib['type'] == 'muir' - - d = openmc.stats.Muir.from_xml_element(elem) - assert d.e0 == pytest.approx(mean) - assert d.m_rat == pytest.approx(mass) - assert d.kt == pytest.approx(temp) - assert len(d) == 3 diff --git a/tests/unit_tests/test_surface.py b/tests/unit_tests/test_surface.py deleted file mode 100644 index 703010a05..000000000 --- a/tests/unit_tests/test_surface.py +++ /dev/null @@ -1,392 +0,0 @@ -from functools import partial -from random import uniform, seed - -import numpy as np -import openmc -import pytest - - -def assert_infinite_bb(s): - ll, ur = (-s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - ll, ur = (+s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - - -def test_plane(): - s = openmc.Plane(a=1, b=2, c=-1, d=3, name='my plane') - assert s.a == 1 - assert s.b == 2 - assert s.c == -1 - assert s.d == 3 - assert s.boundary_type == 'transmission' - assert s.name == 'my plane' - assert s.type == 'plane' - - # Generic planes don't have well-defined bounding boxes - assert_infinite_bb(s) - - # evaluate method - x, y, z = (4, 3, 6) - assert s.evaluate((x, y, z)) == pytest.approx(s.a*x + s.b*y + s.c*z - s.d) - - # translate method - st = s.translate((1.0, 0.0, 0.0)) - assert (st.a, st.b, st.c, st.d) == (s.a, s.b, s.c, 4) - - # Make sure repr works - repr(s) - - -def test_plane_from_points(): - # Generate the plane x - y = 1 given three points - p1 = (0, -1, 0) - p2 = (1, 0, 0) - p3 = (1, 0, 1) - s = openmc.Plane.from_points(p1, p2, p3) - - # Confirm correct coefficients - assert s.a == 1.0 - assert s.b == -1.0 - assert s.c == 0.0 - assert s.d == 1.0 - - -def test_xplane(): - s = openmc.XPlane(3., 'reflective') - assert s.x0 == 3. - assert s.boundary_type == 'reflective' - - # Check bounding box - ll, ur = (+s).bounding_box - assert ll == pytest.approx((3., -np.inf, -np.inf)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ur == pytest.approx((3., np.inf, np.inf)) - assert np.all(np.isinf(ll)) - - # __contains__ on associated half-spaces - assert (5, 0, 0) in +s - assert (5, 0, 0) not in -s - assert (-2, 1, 10) in -s - assert (-2, 1, 10) not in +s - - # evaluate method - assert s.evaluate((5., 0., 0.)) == pytest.approx(2.) - - # translate method - st = s.translate((1.0, 0.0, 0.0)) - assert st.x0 == s.x0 + 1 - - # Make sure repr works - repr(s) - - -def test_yplane(): - s = openmc.YPlane(y0=3.) - assert s.y0 == 3. - - # Check bounding box - ll, ur = (+s).bounding_box - assert ll == pytest.approx((-np.inf, 3., -np.inf)) - assert np.all(np.isinf(ur)) - ll, ur = s.bounding_box('-') - assert ur == pytest.approx((np.inf, 3., np.inf)) - assert np.all(np.isinf(ll)) - - # __contains__ on associated half-spaces - assert (0, 5, 0) in +s - assert (0, 5, 0) not in -s - assert (-2, 1, 10) in -s - assert (-2, 1, 10) not in +s - - # evaluate method - assert s.evaluate((0., 0., 0.)) == pytest.approx(-3.) - - # translate method - st = s.translate((0.0, 1.0, 0.0)) - assert st.y0 == s.y0 + 1 - - -def test_zplane(): - s = openmc.ZPlane(z0=3.) - assert s.z0 == 3. - - # Check bounding box - ll, ur = (+s).bounding_box - assert ll == pytest.approx((-np.inf, -np.inf, 3.)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ur == pytest.approx((np.inf, np.inf, 3.)) - assert np.all(np.isinf(ll)) - - # __contains__ on associated half-spaces - assert (0, 0, 5) in +s - assert (0, 0, 5) not in -s - assert (-2, 1, -10) in -s - assert (-2, 1, -10) not in +s - - # evaluate method - assert s.evaluate((0., 0., 10.)) == pytest.approx(7.) - - # translate method - st = s.translate((0.0, 0.0, 1.0)) - assert st.z0 == s.z0 + 1 - - # Make sure repr works - repr(s) - - -def test_xcylinder(): - y, z, r = 3, 5, 2 - s = openmc.XCylinder(y0=y, z0=z, r=r) - assert s.y0 == y - assert s.z0 == z - assert s.r == r - - # Check bounding box - ll, ur = (+s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ll == pytest.approx((-np.inf, y-r, z-r)) - assert ur == pytest.approx((np.inf, y+r, z+r)) - - # evaluate method - assert s.evaluate((0, y, z)) == pytest.approx(-r**2) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - assert st.y0 == s.y0 + 1 - assert st.z0 == s.z0 + 1 - assert st.r == s.r - - # Make sure repr works - repr(s) - - -def test_periodic(): - x = openmc.XPlane(boundary_type='periodic') - y = openmc.YPlane(boundary_type='periodic') - x.periodic_surface = y - assert y.periodic_surface == x - with pytest.raises(TypeError): - x.periodic_surface = openmc.Sphere() - - -def test_ycylinder(): - x, z, r = 3, 5, 2 - s = openmc.YCylinder(x0=x, z0=z, r=r) - assert s.x0 == x - assert s.z0 == z - assert s.r == r - - # Check bounding box - ll, ur = (+s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ll == pytest.approx((x-r, -np.inf, z-r)) - assert ur == pytest.approx((x+r, np.inf, z+r)) - - # evaluate method - assert s.evaluate((x, 0, z)) == pytest.approx(-r**2) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - assert st.x0 == s.x0 + 1 - assert st.z0 == s.z0 + 1 - assert st.r == s.r - - -def test_zcylinder(): - x, y, r = 3, 5, 2 - s = openmc.ZCylinder(x0=x, y0=y, r=r) - assert s.x0 == x - assert s.y0 == y - assert s.r == r - - # Check bounding box - ll, ur = (+s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ll == pytest.approx((x-r, y-r, -np.inf)) - assert ur == pytest.approx((x+r, y+r, np.inf)) - - # evaluate method - assert s.evaluate((x, y, 0)) == pytest.approx(-r**2) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - assert st.x0 == s.x0 + 1 - assert st.y0 == s.y0 + 1 - assert st.r == s.r - - # Make sure repr works - repr(s) - - -def test_sphere(): - x, y, z, r = -3, 5, 6, 2 - s = openmc.Sphere(x0=x, y0=y, z0=z, r=r) - assert s.x0 == x - assert s.y0 == y - assert s.z0 == z - assert s.r == r - - # Check bounding box - ll, ur = (+s).bounding_box - assert np.all(np.isinf(ll)) - assert np.all(np.isinf(ur)) - ll, ur = (-s).bounding_box - assert ll == pytest.approx((x-r, y-r, z-r)) - assert ur == pytest.approx((x+r, y+r, z+r)) - - # evaluate method - assert s.evaluate((x, y, z)) == pytest.approx(-r**2) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - assert st.x0 == s.x0 + 1 - assert st.y0 == s.y0 + 1 - assert st.z0 == s.z0 + 1 - assert st.r == s.r - - # Make sure repr works - repr(s) - - -def cone_common(apex, r2, cls): - x, y, z = apex - s = cls(x0=x, y0=y, z0=z, r2=r2) - assert s.x0 == x - assert s.y0 == y - assert s.z0 == z - assert s.r2 == r2 - - # Check bounding box - assert_infinite_bb(s) - - # evaluate method -- should be zero at apex - assert s.evaluate((x, y, z)) == pytest.approx(0.0) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - assert st.x0 == s.x0 + 1 - assert st.y0 == s.y0 + 1 - assert st.z0 == s.z0 + 1 - assert st.r2 == s.r2 - - # Make sure repr works - repr(s) - - -def test_xcone(): - apex = (10, 0, 0) - r2 = 4 - cone_common(apex, r2, openmc.XCone) - - -def test_ycone(): - apex = (10, 0, 0) - r2 = 4 - cone_common(apex, r2, openmc.YCone) - - -def test_zcone(): - apex = (10, 0, 0) - r2 = 4 - cone_common(apex, r2, openmc.ZCone) - - -def test_quadric(): - # Make a sphere from a quadric - r = 10.0 - coeffs = {'a': 1, 'b': 1, 'c': 1, 'k': -r**2} - s = openmc.Quadric(**coeffs) - assert s.a == coeffs['a'] - assert s.b == coeffs['b'] - assert s.c == coeffs['c'] - assert s.k == coeffs['k'] - - # All other coeffs should be zero - for coeff in ('d', 'e', 'f', 'g', 'h', 'j'): - assert getattr(s, coeff) == 0.0 - - # Check bounding box - assert_infinite_bb(s) - - # evaluate method - assert s.evaluate((0., 0., 0.)) == pytest.approx(coeffs['k']) - assert s.evaluate((1., 1., 1.)) == pytest.approx(3 + coeffs['k']) - - # translate method - st = s.translate((1.0, 1.0, 1.0)) - for coeff in 'abcdef': - assert getattr(s, coeff) == getattr(st, coeff) - assert (st.g, st.h, st.j) == (-2, -2, -2) - assert st.k == s.k + 3 - - -def test_cylinder_from_points(): - seed(1) # Make random numbers reproducible - for _ in range(100): - # Generate cylinder in random direction - xi = partial(uniform, -10.0, 10.0) - p1 = np.array([xi(), xi(), xi()]) - p2 = np.array([xi(), xi(), xi()]) - r = uniform(1.0, 100.0) - s = openmc.model.cylinder_from_points(p1, p2, r) - - # Points p1 and p2 need to be inside cylinder - assert p1 in -s - assert p2 in -s - - # Points further along the line should be inside cylinder as well - t = uniform(-100.0, 100.0) - p = p1 + t*(p2 - p1) - assert p in -s - - # Check that points outside cylinder are in positive half-space and - # inside are in negative half-space. We do this by constructing a plane - # that includes the cylinder's axis, finding the normal to the plane, - # and using it to find a point slightly more/less than one radius away - # from the axis. - plane = openmc.Plane.from_points(p1, p2, (0., 0., 0.)) - n = np.array([plane.a, plane.b, plane.c]) - n /= np.linalg.norm(n) - assert p1 + 1.1*r*n in +s - assert p2 + 1.1*r*n in +s - assert p1 + 0.9*r*n in -s - assert p2 + 0.9*r*n in -s - - -def test_cylinder_from_points_axis(): - # Create axis-aligned cylinders and confirm the coefficients are as expected - - # (x - 3)^2 + (y - 4)^2 = 2^2 - # x^2 + y^2 - 6x - 8y + 21 = 0 - s = openmc.model.cylinder_from_points((3., 4., 0.), (3., 4., 1.), 2.) - assert (s.a, s.b, s.c) == pytest.approx((1., 1., 0.)) - assert (s.d, s.e, s.f) == pytest.approx((0., 0., 0.)) - assert (s.g, s.h, s.j) == pytest.approx((-6., -8., 0.)) - assert s.k == pytest.approx(21.) - - # (y + 7)^2 + (z - 1)^2 = 3^2 - # y^2 + z^2 + 14y - 2z + 41 = 0 - s = openmc.model.cylinder_from_points((0., -7, 1.), (1., -7., 1.), 3.) - assert (s.a, s.b, s.c) == pytest.approx((0., 1., 1.)) - assert (s.d, s.e, s.f) == pytest.approx((0., 0., 0.)) - assert (s.g, s.h, s.j) == pytest.approx((0., 14., -2.)) - assert s.k == 41. - - # (x - 2)^2 + (z - 5)^2 = 4^2 - # x^2 + z^2 - 4x - 10z + 13 = 0 - s = openmc.model.cylinder_from_points((2., 0., 5.), (2., 1., 5.), 4.) - assert (s.a, s.b, s.c) == pytest.approx((1., 0., 1.)) - assert (s.d, s.e, s.f) == pytest.approx((0., 0., 0.)) - assert (s.g, s.h, s.j) == pytest.approx((-4., 0., -10.)) - assert s.k == pytest.approx(13.) diff --git a/tests/unit_tests/test_transfer_volumes.py b/tests/unit_tests/test_transfer_volumes.py deleted file mode 100644 index 2e735c911..000000000 --- a/tests/unit_tests/test_transfer_volumes.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Regression tests for openmc.deplete.Results.transfer_volumes method. - - -""" - -from pytest import approx -import openmc -from openmc.deplete import PredictorIntegrator, ResultsList - -from tests import dummy_operator - - -def test_transfer_volumes(run_in_tmpdir): - """Unit test of volume transfer in restart calculations.""" - - op = dummy_operator.DummyOperator() - op.output_dir = "test_transfer_volumes" - - # Perform simulation using the predictor algorithm - dt = [0.75] - power = 1.0 - PredictorIntegrator(op, dt, power).integrate() - - # Load the files - res = openmc.deplete.ResultsList.from_hdf5(op.output_dir / "depletion_results.h5") - - # Create a dictionary of volumes to transfer - res[0].volume['1'] = 1.5 - res[0].volume['2'] = 2.5 - - # Create dummy geometry - mat1 = openmc.Material(material_id=1) - mat1.depletable = True - mat2 = openmc.Material(material_id=2) - - cell = openmc.Cell() - cell.fill = [mat1, mat2] - root = openmc.Universe() - root.add_cell(cell) - geometry = openmc.Geometry(root) - - # Transfer volumes - res[0].transfer_volumes(geometry) - - assert mat1.volume == 1.5 - assert mat2.volume is None diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py deleted file mode 100644 index 674fc5c18..000000000 --- a/tests/unit_tests/test_universe.py +++ /dev/null @@ -1,112 +0,0 @@ -import xml.etree.ElementTree as ET - -import numpy as np -import openmc -import pytest - -from tests.unit_tests import assert_unbounded - - -def test_basic(): - c1 = openmc.Cell() - c2 = openmc.Cell() - c3 = openmc.Cell() - u = openmc.Universe(name='cool', cells=(c1, c2, c3)) - assert u.name == 'cool' - - cells = set(u.cells.values()) - assert not (cells ^ {c1, c2, c3}) - - # Test __repr__ - repr(u) - - with pytest.raises(TypeError): - u.add_cell(openmc.Material()) - with pytest.raises(TypeError): - u.add_cells(c1) - - u.remove_cell(c3) - cells = set(u.cells.values()) - assert not (cells ^ {c1, c2}) - - u.clear_cells() - assert not set(u.cells) - - -def test_bounding_box(): - cyl1 = openmc.ZCylinder(r=1.0) - cyl2 = openmc.ZCylinder(r=2.0) - c1 = openmc.Cell(region=-cyl1) - c2 = openmc.Cell(region=+cyl1 & -cyl2) - - u = openmc.Universe(cells=[c1, c2]) - ll, ur = u.bounding_box - assert ll == pytest.approx((-2., -2., -np.inf)) - assert ur == pytest.approx((2., 2., np.inf)) - - u = openmc.Universe() - assert_unbounded(u) - - -def test_plot(run_in_tmpdir, sphere_model): - m = sphere_model.materials[0] - univ = sphere_model.geometry.root_universe - - colors = {m: 'limegreen'} - for basis in ('xy', 'yz', 'xz'): - univ.plot( - basis=basis, - pixels=(10, 10), - color_by='material', - colors=colors, - ) - - -def test_get_nuclides(uo2): - c = openmc.Cell(fill=uo2) - univ = openmc.Universe(cells=[c]) - nucs = univ.get_nuclides() - assert nucs == ['U235', 'O16'] - - -def test_cells(): - cells = [openmc.Cell() for i in range(5)] - cells2 = [openmc.Cell() for i in range(3)] - cells[0].fill = openmc.Universe(cells=cells2) - u = openmc.Universe(cells=cells) - assert not (set(u.cells.values()) ^ set(cells)) - - all_cells = set(u.get_all_cells().values()) - assert not (all_cells ^ set(cells + cells2)) - - -def test_get_all_materials(cell_with_lattice): - cells, mats, univ, lattice = cell_with_lattice - test_mats = set(univ.get_all_materials().values()) - assert not (test_mats ^ set(mats)) - - -def test_get_all_universes(): - c1 = openmc.Cell() - u1 = openmc.Universe(cells=[c1]) - c2 = openmc.Cell() - u2 = openmc.Universe(cells=[c2]) - c3 = openmc.Cell(fill=u1) - c4 = openmc.Cell(fill=u2) - u3 = openmc.Universe(cells=[c3, c4]) - - univs = set(u3.get_all_universes().values()) - assert not (univs ^ {u1, u2}) - - -def test_create_xml(cell_with_lattice): - cells = [openmc.Cell() for i in range(5)] - u = openmc.Universe(cells=cells) - - geom = ET.Element('geom') - u.create_xml_subelement(geom) - cell_elems = geom.findall('cell') - assert len(cell_elems) == len(cells) - assert all(c.get('universe') == str(u.id) for c in cell_elems) - assert not (set(c.get('id') for c in cell_elems) ^ - set(str(c.id) for c in cells)) diff --git a/tools/ci/download-xs.sh b/tools/ci/download-xs.sh deleted file mode 100755 index 07ade9c70..000000000 --- a/tools/ci/download-xs.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -ex - -# Download HDF5 data -if [[ ! -e $HOME/nndc_hdf5/cross_sections.xml ]]; then - wget -q -O - https://anl.box.com/shared/static/teaup95cqv8s9nn56hfn7ku8mmelr95p.xz | tar -C $HOME -xJ -fi - -# Download ENDF/B-VII.1 distribution -ENDF=$HOME/endf-b-vii.1/ -if [[ ! -d $ENDF/neutrons || ! -d $ENDF/photoat || ! -d $ENDF/atomic_relax ]]; then - wget -q -O - https://anl.box.com/shared/static/4kd2gxnf4gtk4w1c8eua5fsua22kvgjb.xz | tar -C $HOME -xJ -fi diff --git a/tools/ci/travis-before-script.sh b/tools/ci/travis-before-script.sh deleted file mode 100755 index 61f0bc087..000000000 --- a/tools/ci/travis-before-script.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -set -ex - -# Download NNDC HDF5 data, ENDF/B-VII.1 distribution, multipole library -source tools/ci/download-xs.sh diff --git a/tools/ci/travis-install-dagmc.sh b/tools/ci/travis-install-dagmc.sh deleted file mode 100755 index 1797e9dba..000000000 --- a/tools/ci/travis-install-dagmc.sh +++ /dev/null @@ -1,38 +0,0 @@ - -#!/bin/bash -set -ex - -# MOAB Variables -MOAB_BRANCH='Version5.1.0' -MOAB_REPO='https://bitbucket.org/fathomteam/moab/' -MOAB_INSTALL_DIR=$HOME/MOAB/ - -# DAGMC Variables -DAGMC_BRANCH='develop' -DAGMC_REPO='https://github.com/svalinn/dagmc' -DAGMC_INSTALL_DIR=$HOME/DAGMC/ - -CURRENT_DIR=$(pwd) - -# MOAB Install -cd $HOME -mkdir MOAB && cd MOAB -git clone -b $MOAB_BRANCH $MOAB_REPO -mkdir build && cd build -cmake ../moab -DENABLE_HDF5=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=$MOAB_INSTALL_DIR -make -j && make -j install -cmake ../moab -DBUILD_SHARED_LIBS=OFF -make -j install -rm -rf $HOME/MOAB/moab -export LD_LIBRARY_PATH=$MOAB_INSTALL_DIR/lib:$LD_LIBRARY_PATH - -# DAGMC Install -mkdir DAGMC && cd DAGMC -git clone -b $DAGMC_BRANCH $DAGMC_REPO -mkdir build && cd build -cmake ../dagmc -DBUILD_TALLY=ON -DCMAKE_INSTALL_PREFIX=$DAGMC_INSTALL_DIR -DMOAB_DIR=$MOAB_INSTALL_DIR -make -j install -rm -rf $HOME/DAGMC/dagmc -export LD_LIBRARY_PATH=$DAGMC_INSTALL_DIR/lib:$LD_LIBRARY_PATH - -cd $CURRENT_DIR diff --git a/tools/ci/travis-install-njoy.sh b/tools/ci/travis-install-njoy.sh deleted file mode 100755 index 8255ffea8..000000000 --- a/tools/ci/travis-install-njoy.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -ex -cd $HOME -git clone https://github.com/njoy/NJOY2016 -cd NJOY2016 -mkdir build && cd build -cmake -Dstatic=on .. && make 2>/dev/null && sudo make install diff --git a/tools/ci/travis-install.py b/tools/ci/travis-install.py deleted file mode 100644 index 9a9b06dae..000000000 --- a/tools/ci/travis-install.py +++ /dev/null @@ -1,73 +0,0 @@ -import os -import shutil -import subprocess - -def which(program): - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - fpath, fname = os.path.split(program) - if fpath: - if is_exe(program): - return program - else: - for path in os.environ["PATH"].split(os.pathsep): - path = path.strip('"') - exe_file = os.path.join(path, program) - if is_exe(exe_file): - return exe_file - return None - - -def install(omp=False, mpi=False, phdf5=False, dagmc=False): - # Create build directory and change to it - shutil.rmtree('build', ignore_errors=True) - os.mkdir('build') - os.chdir('build') - - # Build in debug mode by default - cmake_cmd = ['cmake', '-Ddebug=on'] - - # Turn off OpenMP if specified - if not omp: - cmake_cmd.append('-Dopenmp=off') - - # Use MPI wrappers when building in parallel - if mpi: - os.environ['CXX'] = 'mpicxx' - - # Tell CMake to prefer parallel HDF5 if specified - if phdf5: - if not mpi: - raise ValueError('Parallel HDF5 must be used in ' - 'conjunction with MPI.') - cmake_cmd.append('-DHDF5_PREFER_PARALLEL=ON') - else: - cmake_cmd.append('-DHDF5_PREFER_PARALLEL=OFF') - - if dagmc: - cmake_cmd.append('-Ddagmc=ON') - - # Build in coverage mode for coverage testing - cmake_cmd.append('-Dcoverage=on') - - # Build and install - cmake_cmd.append('..') - print(' '.join(cmake_cmd)) - subprocess.check_call(cmake_cmd) - subprocess.check_call(['make', '-j4']) - subprocess.check_call(['sudo', 'make', 'install']) - -def main(): - # Convert Travis matrix environment variables into arguments for install() - omp = (os.environ.get('OMP') == 'y') - mpi = (os.environ.get('MPI') == 'y') - phdf5 = (os.environ.get('PHDF5') == 'y') - - dagmc = (os.environ.get('DAGMC') == 'y') - - # Build and install - install(omp, mpi, phdf5, dagmc) - -if __name__ == '__main__': - main() diff --git a/tools/ci/travis-install.sh b/tools/ci/travis-install.sh deleted file mode 100755 index 4e32f31cc..000000000 --- a/tools/ci/travis-install.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -set -ex - -# Install NJOY 2016 -./tools/ci/travis-install-njoy.sh - -# Install DAGMC if needed -if [[ $DAGMC = 'y' ]]; then - ./tools/ci/travis-install-dagmc.sh -fi - -# Upgrade pip, pytest, numpy before doing anything else -pip install --upgrade pip -pip install --upgrade pytest -pip install --upgrade numpy - -# Install mpi4py for MPI configurations -if [[ $MPI == 'y' ]]; then - pip install --no-binary=mpi4py mpi4py -fi - -# Build and install OpenMC executable -python tools/ci/travis-install.py - -# Install Python API in editable mode -pip install -e .[test,vtk] - -# For coverage testing of the C++ source files -pip install cpp-coveralls - -# For coverage testing of the Python source files -pip install coveralls diff --git a/tools/ci/travis-script.sh b/tools/ci/travis-script.sh deleted file mode 100755 index 9ee1c1323..000000000 --- a/tools/ci/travis-script.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex - -# Run regression and unit tests -if [[ $MPI == 'y' ]]; then - pytest --cov=openmc -v --mpi tests -else - pytest --cov=openmc -v tests -fi diff --git a/vendor/faddeeva/Faddeeva.cc b/vendor/faddeeva/Faddeeva.cc deleted file mode 100644 index 80e42228c..000000000 --- a/vendor/faddeeva/Faddeeva.cc +++ /dev/null @@ -1,2516 +0,0 @@ -// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; -*- - -/* Copyright (c) 2012 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 the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* (Note that this file can be compiled with either C++, in which - case it uses C++ std::complex, or C, in which case it - uses C99 double complex.) */ - -/* Available at: http://ab-initio.mit.edu/Faddeeva - - Computes various error functions (erf, erfc, erfi, erfcx), - including the Dawson integral, in the complex plane, based - on algorithms for the computation of the Faddeeva function - w(z) = exp(-z^2) * erfc(-i*z). - Given w(z), the error functions are mostly straightforward - to compute, except for certain regions where we have to - switch to Taylor expansions to avoid cancellation errors - [e.g. near the origin for erf(z)]. - - To compute the Faddeeva function, we use a combination of two - algorithms: - - For sufficiently large |z|, we use a continued-fraction expansion - for w(z) similar to those described in: - - Walter Gautschi, "Efficient computation of the complex error - function," SIAM J. Numer. Anal. 7(1), pp. 187-198 (1970) - - G. P. M. Poppe and C. M. J. Wijers, "More efficient computation - of the complex error function," ACM Trans. Math. Soft. 16(1), - pp. 38-46 (1990). - - Unlike those papers, however, we switch to a completely different - algorithm for smaller |z|: - - Mofreh R. Zaghloul and Ahmed N. Ali, "Algorithm 916: Computing the - Faddeyeva and Voigt Functions," ACM Trans. Math. Soft. 38(2), 15 - (2011). - - (I initially used this algorithm for all z, but it turned out to be - significantly slower than the continued-fraction expansion for - larger |z|. On the other hand, it is competitive for smaller |z|, - and is significantly more accurate than the Poppe & Wijers code - in some regions, e.g. in the vicinity of z=1+1i.) - - Note that this is an INDEPENDENT RE-IMPLEMENTATION of these algorithms, - based on the description in the papers ONLY. In particular, I did - not refer to the authors' Fortran or Matlab implementations, respectively, - (which are under restrictive ACM copyright terms and therefore unusable - in free/open-source software). - - Steven G. Johnson, Massachusetts Institute of Technology - http://math.mit.edu/~stevenj - October 2012. - - -- Note that Algorithm 916 assumes that the erfc(x) function, - or rather the scaled function erfcx(x) = exp(x*x)*erfc(x), - is supplied for REAL arguments x. I originally used an - erfcx routine derived from DERFC in SLATEC, but I have - since replaced it with a much faster routine written by - me which uses a combination of continued-fraction expansions - and a lookup table of Chebyshev polynomials. For speed, - I implemented a similar algorithm for Im[w(x)] of real x, - since this comes up frequently in the other error functions. - - A small test program is included the end, which checks - the w(z) etc. results against several known values. To compile - the test function, compile with -DTEST_FADDEEVA (that is, - #define TEST_FADDEEVA). - - If HAVE_CONFIG_H is #defined (e.g. by compiling with -DHAVE_CONFIG_H), - then we #include "config.h", which is assumed to be a GNU autoconf-style - header defining HAVE_* macros to indicate the presence of features. In - particular, if HAVE_ISNAN and HAVE_ISINF are #defined, we use those - functions in math.h instead of defining our own, and if HAVE_ERF and/or - HAVE_ERFC are defined we use those functions from for erf and - erfc of real arguments, respectively, instead of defining our own. - - REVISION HISTORY: - 4 October 2012: Initial public release (SGJ) - 5 October 2012: Revised (SGJ) to fix spelling error, - start summation for large x at round(x/a) (> 1) - rather than ceil(x/a) as in the original - paper, which should slightly improve performance - (and, apparently, slightly improves accuracy) - 19 October 2012: Revised (SGJ) to fix bugs for large x, large -y, - and 15 1e154. - Set relerr argument to min(relerr,0.1). - 27 October 2012: Enhance accuracy in Re[w(z)] taken by itself, - by switching to Alg. 916 in a region near - the real-z axis where continued fractions - have poor relative accuracy in Re[w(z)]. Thanks - to M. Zaghloul for the tip. - 29 October 2012: Replace SLATEC-derived erfcx routine with - completely rewritten code by me, using a very - different algorithm which is much faster. - 30 October 2012: Implemented special-case code for real z - (where real part is exp(-x^2) and imag part is - Dawson integral), using algorithm similar to erfx. - Export ImFaddeeva_w function to make Dawson's - integral directly accessible. - 3 November 2012: Provide implementations of erf, erfc, erfcx, - and Dawson functions in Faddeeva:: namespace, - in addition to Faddeeva::w. Provide header - file Faddeeva.hh. - 4 November 2012: Slightly faster erf for real arguments. - Updated MATLAB and Octave plugins. - 27 November 2012: Support compilation with either C++ or - plain C (using C99 complex numbers). - For real x, use standard-library erf(x) - and erfc(x) if available (for C99 or C++11). - #include "config.h" if HAVE_CONFIG_H is #defined. - 15 December 2012: Portability fixes (copysign, Inf/NaN creation), - use CMPLX/__builtin_complex if available in C, - slight accuracy improvements to erf and dawson - functions near the origin. Use gnulib functions - if GNULIB_NAMESPACE is defined. - 18 December 2012: Slight tweaks (remove recomputation of x*x in Dawson) -*/ - -///////////////////////////////////////////////////////////////////////// -/* If this file is compiled as a part of a larger project, - support using an autoconf-style config.h header file - (with various "HAVE_*" #defines to indicate features) - if HAVE_CONFIG_H is #defined (in GNU autotools style). */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -///////////////////////////////////////////////////////////////////////// -// macros to allow us to use either C++ or C (with C99 features) - -#ifdef __cplusplus - -# include "Faddeeva.hh" - -# include -# include -# include -using namespace std; - -// use std::numeric_limits, since 1./0. and 0./0. fail with some compilers (MS) -# define Inf numeric_limits::infinity() -# define NaN numeric_limits::quiet_NaN() - -typedef complex cmplx; - -// Use C-like complex syntax, since the C syntax is more restrictive -# define cexp(z) exp(z) -# define creal(z) real(z) -# define cimag(z) imag(z) -# define cpolar(r,t) polar(r,t) - -# define C(a,b) cmplx(a,b) - -# define FADDEEVA(name) Faddeeva::name -# define FADDEEVA_RE(name) Faddeeva::name - -// isnan/isinf were introduced in C++11 -# if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF)) -static inline bool my_isnan(double x) { return x != x; } -# define isnan my_isnan -static inline bool my_isinf(double x) { return 1/x == 0.; } -# define isinf my_isinf -# elif (__cplusplus >= 201103L) -// g++ gets confused between the C and C++ isnan/isinf functions -# define isnan std::isnan -# define isinf std::isinf -# endif - -// copysign was introduced in C++11 (and is also in POSIX and C99) -# if defined(_WIN32) || defined(__WIN32__) -# define copysign _copysign // of course MS had to be different -# elif defined(GNULIB_NAMESPACE) // we are using using gnulib -# define copysign GNULIB_NAMESPACE::copysign -# elif (__cplusplus < 201103L) && !defined(HAVE_COPYSIGN) && !defined(__linux__) && !(defined(__APPLE__) && defined(__MACH__)) && !defined(_AIX) -static inline double my_copysign(double x, double y) { return y<0 ? -x : x; } -# define copysign my_copysign -# endif - -// If we are using the gnulib (e.g. in the GNU Octave sources), -// gnulib generates a link warning if we use ::floor instead of gnulib::floor. -// This warning is completely innocuous because the only difference between -// gnulib::floor and the system ::floor (and only on ancient OSF systems) -// has to do with floor(-0), which doesn't occur in the usage below, but -// the Octave developers prefer that we silence the warning. -# ifdef GNULIB_NAMESPACE -# define floor GNULIB_NAMESPACE::floor -# endif - -#else // !__cplusplus, i.e. pure C (requires C99 features) - -# include "Faddeeva.h" - -# define _GNU_SOURCE // enable GNU libc NAN extension if possible - -# include -# include - -typedef double complex cmplx; - -# define FADDEEVA(name) Faddeeva_ ## name -# define FADDEEVA_RE(name) Faddeeva_ ## name ## _re - -/* Constructing complex numbers like 0+i*NaN is problematic in C99 - without the C11 CMPLX macro, because 0.+I*NAN may give NaN+i*NAN if - I is a complex (rather than imaginary) constant. For some reason, - however, it works fine in (pre-4.7) gcc if I define Inf and NaN as - 1/0 and 0/0 (and only if I compile with optimization -O1 or more), - but not if I use the INFINITY or NAN macros. */ - -/* __builtin_complex was introduced in gcc 4.7, but the C11 CMPLX macro - may not be defined unless we are using a recent (2012) version of - glibc and compile with -std=c11... note that icc lies about being - gcc and probably doesn't have this builtin(?), so exclude icc explicitly */ -# if !defined(CMPLX) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !(defined(__ICC) || defined(__INTEL_COMPILER)) -# define CMPLX(a,b) __builtin_complex((double) (a), (double) (b)) -# endif - -# ifdef CMPLX // C11 -# define C(a,b) CMPLX(a,b) -# define Inf INFINITY // C99 infinity -# ifdef NAN // GNU libc extension -# define NaN NAN -# else -# define NaN (0./0.) // NaN -# endif -# else -# define C(a,b) ((a) + I*(b)) -# define Inf (1./0.) -# define NaN (0./0.) -# endif - -static inline cmplx cpolar(double r, double t) -{ - if (r == 0.0 && !isnan(t)) - return 0.0; - else - return C(r * cos(t), r * sin(t)); -} - -#endif // !__cplusplus, i.e. pure C (requires C99 features) - -///////////////////////////////////////////////////////////////////////// -// Auxiliary routines to compute other special functions based on w(z) - -// compute erfcx(z) = exp(z^2) erfz(z) -cmplx FADDEEVA(erfcx)(cmplx z, double relerr) -{ - return FADDEEVA(w)(C(-cimag(z), creal(z)), relerr); -} - -// compute the error function erf(x) -double FADDEEVA_RE(erf)(double x) -{ -#if !defined(__cplusplus) - return erf(x); // C99 supplies erf in math.h -#elif (__cplusplus >= 201103L) || defined(HAVE_ERF) - return ::erf(x); // C++11 supplies std::erf in cmath -#else - double mx2 = -x*x; - if (mx2 < -750) // underflow - return (x >= 0 ? 1.0 : -1.0); - - if (x >= 0) { - if (x < 8e-2) goto taylor; - return 1.0 - exp(mx2) * FADDEEVA_RE(erfcx)(x); - } - else { // x < 0 - if (x > -8e-2) goto taylor; - return exp(mx2) * FADDEEVA_RE(erfcx)(-x) - 1.0; - } - - // Use Taylor series for small |x|, to avoid cancellation inaccuracy - // erf(x) = 2/sqrt(pi) * x * (1 - x^2/3 + x^4/10 - x^6/42 + x^8/216 + ...) - taylor: - return x * (1.1283791670955125739 - + mx2 * (0.37612638903183752464 - + mx2 * (0.11283791670955125739 - + mx2 * (0.026866170645131251760 - + mx2 * 0.0052239776254421878422)))); -#endif -} - -// compute the error function erf(z) -cmplx FADDEEVA(erf)(cmplx z, double relerr) -{ - double x = creal(z), y = cimag(z); - - if (y == 0) - return C(FADDEEVA_RE(erf)(x), - y); // preserve sign of 0 - if (x == 0) // handle separately for speed & handling of y = Inf or NaN - return C(x, // preserve sign of 0 - /* handle y -> Inf limit manually, since - exp(y^2) -> Inf but Im[w(y)] -> 0, so - IEEE will give us a NaN when it should be Inf */ - y*y > 720 ? (y > 0 ? Inf : -Inf) - : exp(y*y) * FADDEEVA(w_im)(y)); - - double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow - double mIm_z2 = -2*x*y; // Im(-z^2) - if (mRe_z2 < -750) // underflow - return (x >= 0 ? 1.0 : -1.0); - - /* Handle positive and negative x via different formulas, - using the mirror symmetries of w, to avoid overflow/underflow - problems from multiplying exponentially large and small quantities. */ - if (x >= 0) { - if (x < 8e-2) { - if (fabs(y) < 1e-2) - goto taylor; - else if (fabs(mIm_z2) < 5e-3 && x < 5e-3) - goto taylor_erfi; - } - /* don't use complex exp function, since that will produce spurious NaN - values when multiplying w in an overflow situation. */ - return 1.0 - exp(mRe_z2) * - (C(cos(mIm_z2), sin(mIm_z2)) - * FADDEEVA(w)(C(-y,x), relerr)); - } - else { // x < 0 - if (x > -8e-2) { // duplicate from above to avoid fabs(x) call - if (fabs(y) < 1e-2) - goto taylor; - else if (fabs(mIm_z2) < 5e-3 && x > -5e-3) - goto taylor_erfi; - } - else if (isnan(x)) - return C(NaN, y == 0 ? 0 : NaN); - /* don't use complex exp function, since that will produce spurious NaN - values when multiplying w in an overflow situation. */ - return exp(mRe_z2) * - (C(cos(mIm_z2), sin(mIm_z2)) - * FADDEEVA(w)(C(y,-x), relerr)) - 1.0; - } - - // Use Taylor series for small |z|, to avoid cancellation inaccuracy - // erf(z) = 2/sqrt(pi) * z * (1 - z^2/3 + z^4/10 - z^6/42 + z^8/216 + ...) - taylor: - { - cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2 - return z * (1.1283791670955125739 - + mz2 * (0.37612638903183752464 - + mz2 * (0.11283791670955125739 - + mz2 * (0.026866170645131251760 - + mz2 * 0.0052239776254421878422)))); - } - - /* for small |x| and small |xy|, - use Taylor series to avoid cancellation inaccuracy: - erf(x+iy) = erf(iy) - + 2*exp(y^2)/sqrt(pi) * - [ x * (1 - x^2 * (1+2y^2)/3 + x^4 * (3+12y^2+4y^4)/30 + ... - - i * x^2 * y * (1 - x^2 * (3+2y^2)/6 + ...) ] - where: - erf(iy) = exp(y^2) * Im[w(y)] - */ - taylor_erfi: - { - double x2 = x*x, y2 = y*y; - double expy2 = exp(y2); - return C - (expy2 * x * (1.1283791670955125739 - - x2 * (0.37612638903183752464 - + 0.75225277806367504925*y2) - + x2*x2 * (0.11283791670955125739 - + y2 * (0.45135166683820502956 - + 0.15045055561273500986*y2))), - expy2 * (FADDEEVA(w_im)(y) - - x2*y * (1.1283791670955125739 - - x2 * (0.56418958354775628695 - + 0.37612638903183752464*y2)))); - } -} - -// erfi(z) = -i erf(iz) -cmplx FADDEEVA(erfi)(cmplx z, double relerr) -{ - cmplx e = FADDEEVA(erf)(C(-cimag(z),creal(z)), relerr); - return C(cimag(e), -creal(e)); -} - -// erfi(x) = -i erf(ix) -double FADDEEVA_RE(erfi)(double x) -{ - return x*x > 720 ? (x > 0 ? Inf : -Inf) - : exp(x*x) * FADDEEVA(w_im)(x); -} - -// erfc(x) = 1 - erf(x) -double FADDEEVA_RE(erfc)(double x) -{ -#if !defined(__cplusplus) - return erfc(x); // C99 supplies erfc in math.h -#elif (__cplusplus >= 201103L) || defined(HAVE_ERFC) - return ::erfc(x); // C++11 supplies std::erfc in cmath -#else - if (x*x > 750) // underflow - return (x >= 0 ? 0.0 : 2.0); - return x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) - : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x); -#endif -} - -// erfc(z) = 1 - erf(z) -cmplx FADDEEVA(erfc)(cmplx z, double relerr) -{ - double x = creal(z), y = cimag(z); - - if (x == 0.) - return C(1, - /* handle y -> Inf limit manually, since - exp(y^2) -> Inf but Im[w(y)] -> 0, so - IEEE will give us a NaN when it should be Inf */ - y*y > 720 ? (y > 0 ? -Inf : Inf) - : -exp(y*y) * FADDEEVA(w_im)(y)); - if (y == 0.) { - if (x*x > 750) // underflow - return C(x >= 0 ? 0.0 : 2.0, - -y); // preserve sign of 0 - return C(x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) - : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x), - -y); // preserve sign of zero - } - - double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow - double mIm_z2 = -2*x*y; // Im(-z^2) - if (mRe_z2 < -750) // underflow - return (x >= 0 ? 0.0 : 2.0); - - if (x >= 0) - return cexp(C(mRe_z2, mIm_z2)) - * FADDEEVA(w)(C(-y,x), relerr); - else - return 2.0 - cexp(C(mRe_z2, mIm_z2)) - * FADDEEVA(w)(C(y,-x), relerr); -} - -// compute Dawson(x) = sqrt(pi)/2 * exp(-x^2) * erfi(x) -double FADDEEVA_RE(Dawson)(double x) -{ - const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2 - return spi2 * FADDEEVA(w_im)(x); -} - -// compute Dawson(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z) -cmplx FADDEEVA(Dawson)(cmplx z, double relerr) -{ - const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2 - double x = creal(z), y = cimag(z); - - // handle axes separately for speed & proper handling of x or y = Inf or NaN - if (y == 0) - return C(spi2 * FADDEEVA(w_im)(x), - -y); // preserve sign of 0 - if (x == 0) { - double y2 = y*y; - if (y2 < 2.5e-5) { // Taylor expansion - return C(x, // preserve sign of 0 - y * (1. - + y2 * (0.6666666666666666666666666666666666666667 - + y2 * 0.26666666666666666666666666666666666667))); - } - return C(x, // preserve sign of 0 - spi2 * (y >= 0 - ? exp(y2) - FADDEEVA_RE(erfcx)(y) - : FADDEEVA_RE(erfcx)(-y) - exp(y2))); - } - - double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow - double mIm_z2 = -2*x*y; // Im(-z^2) - cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2 - - /* Handle positive and negative x via different formulas, - using the mirror symmetries of w, to avoid overflow/underflow - problems from multiplying exponentially large and small quantities. */ - if (y >= 0) { - if (y < 5e-3) { - if (fabs(x) < 5e-3) - goto taylor; - else if (fabs(mIm_z2) < 5e-3) - goto taylor_realaxis; - } - cmplx res = cexp(mz2) - FADDEEVA(w)(z, relerr); - return spi2 * C(-cimag(res), creal(res)); - } - else { // y < 0 - if (y > -5e-3) { // duplicate from above to avoid fabs(x) call - if (fabs(x) < 5e-3) - goto taylor; - else if (fabs(mIm_z2) < 5e-3) - goto taylor_realaxis; - } - else if (isnan(y)) - return C(x == 0 ? 0 : NaN, NaN); - cmplx res = FADDEEVA(w)(-z, relerr) - cexp(mz2); - return spi2 * C(-cimag(res), creal(res)); - } - - // Use Taylor series for small |z|, to avoid cancellation inaccuracy - // dawson(z) = z - 2/3 z^3 + 4/15 z^5 + ... - taylor: - return z * (1. - + mz2 * (0.6666666666666666666666666666666666666667 - + mz2 * 0.2666666666666666666666666666666666666667)); - - /* for small |y| and small |xy|, - use Taylor series to avoid cancellation inaccuracy: - dawson(x + iy) - = D + y^2 (D + x - 2Dx^2) - + y^4 (D/2 + 5x/6 - 2Dx^2 - x^3/3 + 2Dx^4/3) - + iy [ (1-2Dx) + 2/3 y^2 (1 - 3Dx - x^2 + 2Dx^3) - + y^4/15 (4 - 15Dx - 9x^2 + 20Dx^3 + 2x^4 - 4Dx^5) ] + ... - where D = dawson(x) - - However, for large |x|, 2Dx -> 1 which gives cancellation problems in - this series (many of the leading terms cancel). So, for large |x|, - we need to substitute a continued-fraction expansion for D. - - dawson(x) = 0.5 / (x-0.5/(x-1/(x-1.5/(x-2/(x-2.5/(x...)))))) - - The 6 terms shown here seems to be the minimum needed to be - accurate as soon as the simpler Taylor expansion above starts - breaking down. Using this 6-term expansion, factoring out the - denominator, and simplifying with Maple, we obtain: - - Re dawson(x + iy) * (-15 + 90x^2 - 60x^4 + 8x^6) / x - = 33 - 28x^2 + 4x^4 + y^2 (18 - 4x^2) + 4 y^4 - Im dawson(x + iy) * (-15 + 90x^2 - 60x^4 + 8x^6) / y - = -15 + 24x^2 - 4x^4 + 2/3 y^2 (6x^2 - 15) - 4 y^4 - - Finally, for |x| > 5e7, we can use a simpler 1-term continued-fraction - expansion for the real part, and a 2-term expansion for the imaginary - part. (This avoids overflow problems for huge |x|.) This yields: - - Re dawson(x + iy) = [1 + y^2 (1 + y^2/2 - (xy)^2/3)] / (2x) - Im dawson(x + iy) = y [ -1 - 2/3 y^2 + y^4/15 (2x^2 - 4) ] / (2x^2 - 1) - - */ - taylor_realaxis: - { - double x2 = x*x; - if (x2 > 1600) { // |x| > 40 - double y2 = y*y; - if (x2 > 25e14) {// |x| > 5e7 - double xy2 = (x*y)*(x*y); - return C((0.5 + y2 * (0.5 + 0.25*y2 - - 0.16666666666666666667*xy2)) / x, - y * (-1 + y2 * (-0.66666666666666666667 - + 0.13333333333333333333*xy2 - - 0.26666666666666666667*y2)) - / (2*x2 - 1)); - } - return (1. / (-15 + x2*(90 + x2*(-60 + 8*x2)))) * - C(x * (33 + x2 * (-28 + 4*x2) - + y2 * (18 - 4*x2 + 4*y2)), - y * (-15 + x2 * (24 - 4*x2) - + y2 * (4*x2 - 10 - 4*y2))); - } - else { - double D = spi2 * FADDEEVA(w_im)(x); - double y2 = y*y; - return C - (D + y2 * (D + x - 2*D*x2) - + y2*y2 * (D * (0.5 - x2 * (2 - 0.66666666666666666667*x2)) - + x * (0.83333333333333333333 - - 0.33333333333333333333 * x2)), - y * (1 - 2*D*x - + y2 * 0.66666666666666666667 * (1 - x2 - D*x * (3 - 2*x2)) - + y2*y2 * (0.26666666666666666667 - - x2 * (0.6 - 0.13333333333333333333 * x2) - - D*x * (1 - x2 * (1.3333333333333333333 - - 0.26666666666666666667 * x2))))); - } - } -} - -///////////////////////////////////////////////////////////////////////// - -// return sinc(x) = sin(x)/x, given both x and sin(x) -// [since we only use this in cases where sin(x) has already been computed] -static inline double sinc(double x, double sinx) { - return fabs(x) < 1e-4 ? 1 - (0.1666666666666666666667)*x*x : sinx / x; -} - -// sinh(x) via Taylor series, accurate to machine precision for |x| < 1e-2 -static inline double sinh_taylor(double x) { - return x * (1 + (x*x) * (0.1666666666666666666667 - + 0.00833333333333333333333 * (x*x))); -} - -static inline double sqr(double x) { return x*x; } - -// precomputed table of expa2n2[n-1] = exp(-a2*n*n) -// for double-precision a2 = 0.26865... in FADDEEVA(w), below. -static const double expa2n2[] = { - 7.64405281671221563e-01, - 3.41424527166548425e-01, - 8.91072646929412548e-02, - 1.35887299055460086e-02, - 1.21085455253437481e-03, - 6.30452613933449404e-05, - 1.91805156577114683e-06, - 3.40969447714832381e-08, - 3.54175089099469393e-10, - 2.14965079583260682e-12, - 7.62368911833724354e-15, - 1.57982797110681093e-17, - 1.91294189103582677e-20, - 1.35344656764205340e-23, - 5.59535712428588720e-27, - 1.35164257972401769e-30, - 1.90784582843501167e-34, - 1.57351920291442930e-38, - 7.58312432328032845e-43, - 2.13536275438697082e-47, - 3.51352063787195769e-52, - 3.37800830266396920e-57, - 1.89769439468301000e-62, - 6.22929926072668851e-68, - 1.19481172006938722e-73, - 1.33908181133005953e-79, - 8.76924303483223939e-86, - 3.35555576166254986e-92, - 7.50264110688173024e-99, - 9.80192200745410268e-106, - 7.48265412822268959e-113, - 3.33770122566809425e-120, - 8.69934598159861140e-128, - 1.32486951484088852e-135, - 1.17898144201315253e-143, - 6.13039120236180012e-152, - 1.86258785950822098e-160, - 3.30668408201432783e-169, - 3.43017280887946235e-178, - 2.07915397775808219e-187, - 7.36384545323984966e-197, - 1.52394760394085741e-206, - 1.84281935046532100e-216, - 1.30209553802992923e-226, - 5.37588903521080531e-237, - 1.29689584599763145e-247, - 1.82813078022866562e-258, - 1.50576355348684241e-269, - 7.24692320799294194e-281, - 2.03797051314726829e-292, - 3.34880215927873807e-304, - 0.0 // underflow (also prevents reads past array end, below) -}; - -///////////////////////////////////////////////////////////////////////// - -cmplx FADDEEVA(w)(cmplx z, double relerr) -{ - if (creal(z) == 0.0) - return C(FADDEEVA_RE(erfcx)(cimag(z)), - creal(z)); // give correct sign of 0 in cimag(w) - else if (cimag(z) == 0) - return C(exp(-sqr(creal(z))), - FADDEEVA(w_im)(creal(z))); - - double a, a2, c; - if (relerr <= DBL_EPSILON) { - relerr = DBL_EPSILON; - a = 0.518321480430085929872; // pi / sqrt(-log(eps*0.5)) - c = 0.329973702884629072537; // (2/pi) * a; - a2 = 0.268657157075235951582; // a^2 - } - else { - const double pi = 3.14159265358979323846264338327950288419716939937510582; - if (relerr > 0.1) relerr = 0.1; // not sensible to compute < 1 digit - a = pi / sqrt(-log(relerr*0.5)); - c = (2/pi)*a; - a2 = a*a; - } - const double x = fabs(creal(z)); - const double y = cimag(z), ya = fabs(y); - - cmplx ret = 0.; // return value - - double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0; - -#define USE_CONTINUED_FRACTION 1 // 1 to use continued fraction for large |z| - -#if USE_CONTINUED_FRACTION - if (ya > 7 || (x > 6 // continued fraction is faster - /* As pointed out by M. Zaghloul, the continued - fraction seems to give a large relative error in - Re w(z) for |x| ~ 6 and small |y|, so use - algorithm 816 in this region: */ - && (ya > 0.1 || (x > 8 && ya > 1e-10) || x > 28))) { - - /* Poppe & Wijers suggest using a number of terms - nu = 3 + 1442 / (26*rho + 77) - where rho = sqrt((x/x0)^2 + (y/y0)^2) where x0=6.3, y0=4.4. - (They only use this expansion for rho >= 1, but rho a little less - than 1 seems okay too.) - Instead, I did my own fit to a slightly different function - that avoids the hypotenuse calculation, using NLopt to minimize - the sum of the squares of the errors in nu with the constraint - that the estimated nu be >= minimum nu to attain machine precision. - I also separate the regions where nu == 2 and nu == 1. */ - const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) - double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 - if (x + ya > 4000) { // nu <= 2 - if (x + ya > 1e7) { // nu == 1, w(z) = i/sqrt(pi) / z - // scale to avoid overflow - if (x > ya) { - double yax = ya / xs; - double denom = ispi / (xs + yax*ya); - ret = C(denom*yax, denom); - } - else if (isinf(ya)) - return ((isnan(x) || y < 0) - ? C(NaN,NaN) : C(0,0)); - else { - double xya = xs / ya; - double denom = ispi / (xya*xs + ya); - ret = C(denom, denom*xya); - } - } - else { // nu == 2, w(z) = i/sqrt(pi) * z / (z*z - 0.5) - double dr = xs*xs - ya*ya - 0.5, di = 2*xs*ya; - double denom = ispi / (dr*dr + di*di); - ret = C(denom * (xs*di-ya*dr), denom * (xs*dr+ya*di)); - } - } - else { // compute nu(z) estimate and do general continued fraction - const double c0=3.9, c1=11.398, c2=0.08254, c3=0.1421, c4=0.2023; // fit - double nu = floor(c0 + c1 / (c2*x + c3*ya + c4)); - double wr = xs, wi = ya; - for (nu = 0.5 * (nu - 1); nu > 0.4; nu -= 0.5) { - // w <- z - nu/w: - double denom = nu / (wr*wr + wi*wi); - wr = xs - wr * denom; - wi = ya + wi * denom; - } - { // w(z) = i/sqrt(pi) / w: - double denom = ispi / (wr*wr + wi*wi); - ret = C(denom*wi, denom*wr); - } - } - if (y < 0) { - // use w(z) = 2.0*exp(-z*z) - w(-z), - // but be careful of overflow in exp(-z*z) - // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) - return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret; - } - else - return ret; - } -#else // !USE_CONTINUED_FRACTION - if (x + ya > 1e7) { // w(z) = i/sqrt(pi) / z, to machine precision - const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) - double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 - // scale to avoid overflow - if (x > ya) { - double yax = ya / xs; - double denom = ispi / (xs + yax*ya); - ret = C(denom*yax, denom); - } - else { - double xya = xs / ya; - double denom = ispi / (xya*xs + ya); - ret = C(denom, denom*xya); - } - if (y < 0) { - // use w(z) = 2.0*exp(-z*z) - w(-z), - // but be careful of overflow in exp(-z*z) - // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) - return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret; - } - else - return ret; - } -#endif // !USE_CONTINUED_FRACTION - - /* Note: The test that seems to be suggested in the paper is x < - sqrt(-log(DBL_MIN)), about 26.6, since otherwise exp(-x^2) - underflows to zero and sum1,sum2,sum4 are zero. However, long - before this occurs, the sum1,sum2,sum4 contributions are - negligible in double precision; I find that this happens for x > - about 6, for all y. On the other hand, I find that the case - where we compute all of the sums is faster (at least with the - precomputed expa2n2 table) until about x=10. Furthermore, if we - try to compute all of the sums for x > 20, I find that we - sometimes run into numerical problems because underflow/overflow - problems start to appear in the various coefficients of the sums, - below. Therefore, we use x < 10 here. */ - else if (x < 10) { - double prod2ax = 1, prodm2ax = 1; - double expx2; - - if (isnan(y)) - return C(y,y); - - /* Somewhat ugly copy-and-paste duplication here, but I see significant - speedups from using the special-case code with the precomputed - exponential, and the x < 5e-4 special case is needed for accuracy. */ - - if (relerr == DBL_EPSILON) { // use precomputed exp(-a2*(n*n)) table - if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 - const double x2 = x*x; - expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor - // compute exp(2*a*x) and exp(-2*a*x) via Taylor, to double precision - const double ax2 = 1.036642960860171859744*x; // 2*a*x - const double exp2ax = - 1 + ax2 * (1 + ax2 * (0.5 + 0.166666666666666666667*ax2)); - const double expm2ax = - 1 - ax2 * (1 - ax2 * (0.5 - 0.166666666666666666667*ax2)); - for (int n = 1; 1; ++n) { - const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); - prod2ax *= exp2ax; - prodm2ax *= expm2ax; - sum1 += coef; - sum2 += coef * prodm2ax; - sum3 += coef * prod2ax; - - // really = sum5 - sum4 - sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); - - // test convergence via sum3 - if (coef * prod2ax < relerr * sum3) break; - } - } - else { // x > 5e-4, compute sum4 and sum5 separately - expx2 = exp(-x*x); - const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; - for (int n = 1; 1; ++n) { - const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); - prod2ax *= exp2ax; - prodm2ax *= expm2ax; - sum1 += coef; - sum2 += coef * prodm2ax; - sum4 += (coef * prodm2ax) * (a*n); - sum3 += coef * prod2ax; - sum5 += (coef * prod2ax) * (a*n); - // test convergence via sum5, since this sum has the slowest decay - if ((coef * prod2ax) * (a*n) < relerr * sum5) break; - } - } - } - else { // relerr != DBL_EPSILON, compute exp(-a2*(n*n)) on the fly - const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; - if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 - const double x2 = x*x; - expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor - for (int n = 1; 1; ++n) { - const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); - prod2ax *= exp2ax; - prodm2ax *= expm2ax; - sum1 += coef; - sum2 += coef * prodm2ax; - sum3 += coef * prod2ax; - - // really = sum5 - sum4 - sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); - - // test convergence via sum3 - if (coef * prod2ax < relerr * sum3) break; - } - } - else { // x > 5e-4, compute sum4 and sum5 separately - expx2 = exp(-x*x); - for (int n = 1; 1; ++n) { - const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); - prod2ax *= exp2ax; - prodm2ax *= expm2ax; - sum1 += coef; - sum2 += coef * prodm2ax; - sum4 += (coef * prodm2ax) * (a*n); - sum3 += coef * prod2ax; - sum5 += (coef * prod2ax) * (a*n); - // test convergence via sum5, since this sum has the slowest decay - if ((coef * prod2ax) * (a*n) < relerr * sum5) break; - } - } - } - const double expx2erfcxy = // avoid spurious overflow for large negative y - y > -6 // for y < -6, erfcx(y) = 2*exp(y*y) to double precision - ? expx2*FADDEEVA_RE(erfcx)(y) : 2*exp(y*y-x*x); - if (y > 5) { // imaginary terms cancel - const double sinxy = sin(x*y); - ret = (expx2erfcxy - c*y*sum1) * cos(2*x*y) - + (c*x*expx2) * sinxy * sinc(x*y, sinxy); - } - else { - double xs = creal(z); - const double sinxy = sin(xs*y); - const double sin2xy = sin(2*xs*y), cos2xy = cos(2*xs*y); - const double coef1 = expx2erfcxy - c*y*sum1; - const double coef2 = c*xs*expx2; - ret = C(coef1 * cos2xy + coef2 * sinxy * sinc(xs*y, sinxy), - coef2 * sinc(2*xs*y, sin2xy) - coef1 * sin2xy); - } - } - else { // x large: only sum3 & sum5 contribute (see above note) - if (isnan(x)) - return C(x,x); - if (isnan(y)) - return C(y,y); - -#if USE_CONTINUED_FRACTION - ret = exp(-x*x); // |y| < 1e-10, so we only need exp(-x*x) term -#else - if (y < 0) { - /* erfcx(y) ~ 2*exp(y*y) + (< 1) if y < 0, so - erfcx(y)*exp(-x*x) ~ 2*exp(y*y-x*x) term may not be negligible - if y*y - x*x > -36 or so. So, compute this term just in case. - We also need the -exp(-x*x) term to compute Re[w] accurately - in the case where y is very small. */ - ret = cpolar(2*exp(y*y-x*x) - exp(-x*x), -2*creal(z)*y); - } - else - ret = exp(-x*x); // not negligible in real part if y very small -#endif - // (round instead of ceil as in original paper; note that x/a > 1 here) - double n0 = floor(x/a + 0.5); // sum in both directions, starting at n0 - double dx = a*n0 - x; - sum3 = exp(-dx*dx) / (a2*(n0*n0) + y*y); - sum5 = a*n0 * sum3; - double exp1 = exp(4*a*dx), exp1dn = 1; - int dn; - for (dn = 1; n0 - dn > 0; ++dn) { // loop over n0-dn and n0+dn terms - double np = n0 + dn, nm = n0 - dn; - double tp = exp(-sqr(a*dn+dx)); - double tm = tp * (exp1dn *= exp1); // trick to get tm from tp - tp /= (a2*(np*np) + y*y); - tm /= (a2*(nm*nm) + y*y); - sum3 += tp + tm; - sum5 += a * (np * tp + nm * tm); - if (a * (np * tp + nm * tm) < relerr * sum5) goto finish; - } - while (1) { // loop over n0+dn terms only (since n0-dn <= 0) - double np = n0 + dn++; - double tp = exp(-sqr(a*dn+dx)) / (a2*(np*np) + y*y); - sum3 += tp; - sum5 += a * np * tp; - if (a * np * tp < relerr * sum5) goto finish; - } - } - finish: - return ret + C((0.5*c)*y*(sum2+sum3), - (0.5*c)*copysign(sum5-sum4, creal(z))); -} - -///////////////////////////////////////////////////////////////////////// - -/* erfcx(x) = exp(x^2) erfc(x) function, for real x, written by - Steven G. Johnson, October 2012. - - This function combines a few different ideas. - - First, for x > 50, it uses a continued-fraction expansion (same as - for the Faddeeva function, but with algebraic simplifications for z=i*x). - - Second, for 0 <= x <= 50, it uses Chebyshev polynomial approximations, - but with two twists: - - a) It maps x to y = 4 / (4+x) in [0,1]. This simple transformation, - inspired by a similar transformation in the octave-forge/specfun - erfcx by Soren Hauberg, results in much faster Chebyshev convergence - than other simple transformations I have examined. - - b) Instead of using a single Chebyshev polynomial for the entire - [0,1] y interval, we break the interval up into 100 equal - subintervals, with a switch/lookup table, and use much lower - degree Chebyshev polynomials in each subinterval. This greatly - improves performance in my tests. - - For x < 0, we use the relationship erfcx(-x) = 2 exp(x^2) - erfc(x), - with the usual checks for overflow etcetera. - - Performance-wise, it seems to be substantially faster than either - the SLATEC DERFC function [or an erfcx function derived therefrom] - or Cody's CALERF function (from netlib.org/specfun), while - retaining near machine precision in accuracy. */ - -/* Given y100=100*y, where y = 4/(4+x) for x >= 0, compute erfc(x). - - Uses a look-up table of 100 different Chebyshev polynomials - for y intervals [0,0.01], [0.01,0.02], ...., [0.99,1], generated - with the help of Maple and a little shell script. This allows - the Chebyshev polynomials to be of significantly lower degree (about 1/4) - compared to fitting the whole [0,1] interval with a single polynomial. */ -static double erfcx_y100(double y100) -{ - switch ((int) y100) { -case 0: { -double t = 2*y100 - 1; -return 0.70878032454106438663e-3 + (0.71234091047026302958e-3 + (0.35779077297597742384e-5 + (0.17403143962587937815e-7 + (0.81710660047307788845e-10 + (0.36885022360434957634e-12 + 0.15917038551111111111e-14 * t) * t) * t) * t) * t) * t; -} -case 1: { -double t = 2*y100 - 3; -return 0.21479143208285144230e-2 + (0.72686402367379996033e-3 + (0.36843175430938995552e-5 + (0.18071841272149201685e-7 + (0.85496449296040325555e-10 + (0.38852037518534291510e-12 + 0.16868473576888888889e-14 * t) * t) * t) * t) * t) * t; -} -case 2: { -double t = 2*y100 - 5; -return 0.36165255935630175090e-2 + (0.74182092323555510862e-3 + (0.37948319957528242260e-5 + (0.18771627021793087350e-7 + (0.89484715122415089123e-10 + (0.40935858517772440862e-12 + 0.17872061464888888889e-14 * t) * t) * t) * t) * t) * t; -} -case 3: { -double t = 2*y100 - 7; -return 0.51154983860031979264e-2 + (0.75722840734791660540e-3 + (0.39096425726735703941e-5 + (0.19504168704300468210e-7 + (0.93687503063178993915e-10 + (0.43143925959079664747e-12 + 0.18939926435555555556e-14 * t) * t) * t) * t) * t) * t; -} -case 4: { -double t = 2*y100 - 9; -return 0.66457513172673049824e-2 + (0.77310406054447454920e-3 + (0.40289510589399439385e-5 + (0.20271233238288381092e-7 + (0.98117631321709100264e-10 + (0.45484207406017752971e-12 + 0.20076352213333333333e-14 * t) * t) * t) * t) * t) * t; -} -case 5: { -double t = 2*y100 - 11; -return 0.82082389970241207883e-2 + (0.78946629611881710721e-3 + (0.41529701552622656574e-5 + (0.21074693344544655714e-7 + (0.10278874108587317989e-9 + (0.47965201390613339638e-12 + 0.21285907413333333333e-14 * t) * t) * t) * t) * t) * t; -} -case 6: { -double t = 2*y100 - 13; -return 0.98039537275352193165e-2 + (0.80633440108342840956e-3 + (0.42819241329736982942e-5 + (0.21916534346907168612e-7 + (0.10771535136565470914e-9 + (0.50595972623692822410e-12 + 0.22573462684444444444e-14 * t) * t) * t) * t) * t) * t; -} -case 7: { -double t = 2*y100 - 15; -return 0.11433927298290302370e-1 + (0.82372858383196561209e-3 + (0.44160495311765438816e-5 + (0.22798861426211986056e-7 + (0.11291291745879239736e-9 + (0.53386189365816880454e-12 + 0.23944209546666666667e-14 * t) * t) * t) * t) * t) * t; -} -case 8: { -double t = 2*y100 - 17; -return 0.13099232878814653979e-1 + (0.84167002467906968214e-3 + (0.45555958988457506002e-5 + (0.23723907357214175198e-7 + (0.11839789326602695603e-9 + (0.56346163067550237877e-12 + 0.25403679644444444444e-14 * t) * t) * t) * t) * t) * t; -} -case 9: { -double t = 2*y100 - 19; -return 0.14800987015587535621e-1 + (0.86018092946345943214e-3 + (0.47008265848816866105e-5 + (0.24694040760197315333e-7 + (0.12418779768752299093e-9 + (0.59486890370320261949e-12 + 0.26957764568888888889e-14 * t) * t) * t) * t) * t) * t; -} -case 10: { -double t = 2*y100 - 21; -return 0.16540351739394069380e-1 + (0.87928458641241463952e-3 + (0.48520195793001753903e-5 + (0.25711774900881709176e-7 + (0.13030128534230822419e-9 + (0.62820097586874779402e-12 + 0.28612737351111111111e-14 * t) * t) * t) * t) * t) * t; -} -case 11: { -double t = 2*y100 - 23; -return 0.18318536789842392647e-1 + (0.89900542647891721692e-3 + (0.50094684089553365810e-5 + (0.26779777074218070482e-7 + (0.13675822186304615566e-9 + (0.66358287745352705725e-12 + 0.30375273884444444444e-14 * t) * t) * t) * t) * t) * t; -} -case 12: { -double t = 2*y100 - 25; -return 0.20136801964214276775e-1 + (0.91936908737673676012e-3 + (0.51734830914104276820e-5 + (0.27900878609710432673e-7 + (0.14357976402809042257e-9 + (0.70114790311043728387e-12 + 0.32252476000000000000e-14 * t) * t) * t) * t) * t) * t; -} -case 13: { -double t = 2*y100 - 27; -return 0.21996459598282740954e-1 + (0.94040248155366777784e-3 + (0.53443911508041164739e-5 + (0.29078085538049374673e-7 + (0.15078844500329731137e-9 + (0.74103813647499204269e-12 + 0.34251892320000000000e-14 * t) * t) * t) * t) * t) * t; -} -case 14: { -double t = 2*y100 - 29; -return 0.23898877187226319502e-1 + (0.96213386835900177540e-3 + (0.55225386998049012752e-5 + (0.30314589961047687059e-7 + (0.15840826497296335264e-9 + (0.78340500472414454395e-12 + 0.36381553564444444445e-14 * t) * t) * t) * t) * t) * t; -} -case 15: { -double t = 2*y100 - 31; -return 0.25845480155298518485e-1 + (0.98459293067820123389e-3 + (0.57082915920051843672e-5 + (0.31613782169164830118e-7 + (0.16646478745529630813e-9 + (0.82840985928785407942e-12 + 0.38649975768888888890e-14 * t) * t) * t) * t) * t) * t; -} -case 16: { -double t = 2*y100 - 33; -return 0.27837754783474696598e-1 + (0.10078108563256892757e-2 + (0.59020366493792212221e-5 + (0.32979263553246520417e-7 + (0.17498524159268458073e-9 + (0.87622459124842525110e-12 + 0.41066206488888888890e-14 * t) * t) * t) * t) * t) * t; -} -case 17: { -double t = 2*y100 - 35; -return 0.29877251304899307550e-1 + (0.10318204245057349310e-2 + (0.61041829697162055093e-5 + (0.34414860359542720579e-7 + (0.18399863072934089607e-9 + (0.92703227366365046533e-12 + 0.43639844053333333334e-14 * t) * t) * t) * t) * t) * t; -} -case 18: { -double t = 2*y100 - 37; -return 0.31965587178596443475e-1 + (0.10566560976716574401e-2 + (0.63151633192414586770e-5 + (0.35924638339521924242e-7 + (0.19353584758781174038e-9 + (0.98102783859889264382e-12 + 0.46381060817777777779e-14 * t) * t) * t) * t) * t) * t; -} -case 19: { -double t = 2*y100 - 39; -return 0.34104450552588334840e-1 + (0.10823541191350532574e-2 + (0.65354356159553934436e-5 + (0.37512918348533521149e-7 + (0.20362979635817883229e-9 + (0.10384187833037282363e-11 + 0.49300625262222222221e-14 * t) * t) * t) * t) * t) * t; -} -case 20: { -double t = 2*y100 - 41; -return 0.36295603928292425716e-1 + (0.11089526167995268200e-2 + (0.67654845095518363577e-5 + (0.39184292949913591646e-7 + (0.21431552202133775150e-9 + (0.10994259106646731797e-11 + 0.52409949102222222221e-14 * t) * t) * t) * t) * t) * t; -} -case 21: { -double t = 2*y100 - 43; -return 0.38540888038840509795e-1 + (0.11364917134175420009e-2 + (0.70058230641246312003e-5 + (0.40943644083718586939e-7 + (0.22563034723692881631e-9 + (0.11642841011361992885e-11 + 0.55721092871111111110e-14 * t) * t) * t) * t) * t) * t; -} -case 22: { -double t = 2*y100 - 45; -return 0.40842225954785960651e-1 + (0.11650136437945673891e-2 + (0.72569945502343006619e-5 + (0.42796161861855042273e-7 + (0.23761401711005024162e-9 + (0.12332431172381557035e-11 + 0.59246802364444444445e-14 * t) * t) * t) * t) * t) * t; -} -case 23: { -double t = 2*y100 - 47; -return 0.43201627431540222422e-1 + (0.11945628793917272199e-2 + (0.75195743532849206263e-5 + (0.44747364553960993492e-7 + (0.25030885216472953674e-9 + (0.13065684400300476484e-11 + 0.63000532853333333334e-14 * t) * t) * t) * t) * t) * t; -} -case 24: { -double t = 2*y100 - 49; -return 0.45621193513810471438e-1 + (0.12251862608067529503e-2 + (0.77941720055551920319e-5 + (0.46803119830954460212e-7 + (0.26375990983978426273e-9 + (0.13845421370977119765e-11 + 0.66996477404444444445e-14 * t) * t) * t) * t) * t) * t; -} -case 25: { -double t = 2*y100 - 51; -return 0.48103121413299865517e-1 + (0.12569331386432195113e-2 + (0.80814333496367673980e-5 + (0.48969667335682018324e-7 + (0.27801515481905748484e-9 + (0.14674637611609884208e-11 + 0.71249589351111111110e-14 * t) * t) * t) * t) * t) * t; -} -case 26: { -double t = 2*y100 - 53; -return 0.50649709676983338501e-1 + (0.12898555233099055810e-2 + (0.83820428414568799654e-5 + (0.51253642652551838659e-7 + (0.29312563849675507232e-9 + (0.15556512782814827846e-11 + 0.75775607822222222221e-14 * t) * t) * t) * t) * t) * t; -} -case 27: { -double t = 2*y100 - 55; -return 0.53263363664388864181e-1 + (0.13240082443256975769e-2 + (0.86967260015007658418e-5 + (0.53662102750396795566e-7 + (0.30914568786634796807e-9 + (0.16494420240828493176e-11 + 0.80591079644444444445e-14 * t) * t) * t) * t) * t) * t; -} -case 28: { -double t = 2*y100 - 57; -return 0.55946601353500013794e-1 + (0.13594491197408190706e-2 + (0.90262520233016380987e-5 + (0.56202552975056695376e-7 + (0.32613310410503135996e-9 + (0.17491936862246367398e-11 + 0.85713381688888888890e-14 * t) * t) * t) * t) * t) * t; -} -case 29: { -double t = 2*y100 - 59; -return 0.58702059496154081813e-1 + (0.13962391363223647892e-2 + (0.93714365487312784270e-5 + (0.58882975670265286526e-7 + (0.34414937110591753387e-9 + (0.18552853109751857859e-11 + 0.91160736711111111110e-14 * t) * t) * t) * t) * t) * t; -} -case 30: { -double t = 2*y100 - 61; -return 0.61532500145144778048e-1 + (0.14344426411912015247e-2 + (0.97331446201016809696e-5 + (0.61711860507347175097e-7 + (0.36325987418295300221e-9 + (0.19681183310134518232e-11 + 0.96952238400000000000e-14 * t) * t) * t) * t) * t) * t; -} -case 31: { -double t = 2*y100 - 63; -return 0.64440817576653297993e-1 + (0.14741275456383131151e-2 + (0.10112293819576437838e-4 + (0.64698236605933246196e-7 + (0.38353412915303665586e-9 + (0.20881176114385120186e-11 + 0.10310784480000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 32: { -double t = 2*y100 - 65; -return 0.67430045633130393282e-1 + (0.15153655418916540370e-2 + (0.10509857606888328667e-4 + (0.67851706529363332855e-7 + (0.40504602194811140006e-9 + (0.22157325110542534469e-11 + 0.10964842115555555556e-13 * t) * t) * t) * t) * t) * t; -} -case 33: { -double t = 2*y100 - 67; -return 0.70503365513338850709e-1 + (0.15582323336495709827e-2 + (0.10926868866865231089e-4 + (0.71182482239613507542e-7 + (0.42787405890153386710e-9 + (0.23514379522274416437e-11 + 0.11659571751111111111e-13 * t) * t) * t) * t) * t) * t; -} -case 34: { -double t = 2*y100 - 69; -return 0.73664114037944596353e-1 + (0.16028078812438820413e-2 + (0.11364423678778207991e-4 + (0.74701423097423182009e-7 + (0.45210162777476488324e-9 + (0.24957355004088569134e-11 + 0.12397238257777777778e-13 * t) * t) * t) * t) * t) * t; -} -case 35: { -double t = 2*y100 - 71; -return 0.76915792420819562379e-1 + (0.16491766623447889354e-2 + (0.11823685320041302169e-4 + (0.78420075993781544386e-7 + (0.47781726956916478925e-9 + (0.26491544403815724749e-11 + 0.13180196462222222222e-13 * t) * t) * t) * t) * t) * t; -} -case 36: { -double t = 2*y100 - 73; -return 0.80262075578094612819e-1 + (0.16974279491709504117e-2 + (0.12305888517309891674e-4 + (0.82350717698979042290e-7 + (0.50511496109857113929e-9 + (0.28122528497626897696e-11 + 0.14010889635555555556e-13 * t) * t) * t) * t) * t) * t; -} -case 37: { -double t = 2*y100 - 75; -return 0.83706822008980357446e-1 + (0.17476561032212656962e-2 + (0.12812343958540763368e-4 + (0.86506399515036435592e-7 + (0.53409440823869467453e-9 + (0.29856186620887555043e-11 + 0.14891851591111111111e-13 * t) * t) * t) * t) * t) * t; -} -case 38: { -double t = 2*y100 - 77; -return 0.87254084284461718231e-1 + (0.17999608886001962327e-2 + (0.13344443080089492218e-4 + (0.90900994316429008631e-7 + (0.56486134972616465316e-9 + (0.31698707080033956934e-11 + 0.15825697795555555556e-13 * t) * t) * t) * t) * t) * t; -} -case 39: { -double t = 2*y100 - 79; -return 0.90908120182172748487e-1 + (0.18544478050657699758e-2 + (0.13903663143426120077e-4 + (0.95549246062549906177e-7 + (0.59752787125242054315e-9 + (0.33656597366099099413e-11 + 0.16815130613333333333e-13 * t) * t) * t) * t) * t) * t; -} -case 40: { -double t = 2*y100 - 81; -return 0.94673404508075481121e-1 + (0.19112284419887303347e-2 + (0.14491572616545004930e-4 + (0.10046682186333613697e-6 + (0.63221272959791000515e-9 + (0.35736693975589130818e-11 + 0.17862931591111111111e-13 * t) * t) * t) * t) * t) * t; -} -case 41: { -double t = 2*y100 - 83; -return 0.98554641648004456555e-1 + (0.19704208544725622126e-2 + (0.15109836875625443935e-4 + (0.10567036667675984067e-6 + (0.66904168640019354565e-9 + (0.37946171850824333014e-11 + 0.18971959040000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 42: { -double t = 2*y100 - 85; -return 0.10255677889470089531e0 + (0.20321499629472857418e-2 + (0.15760224242962179564e-4 + (0.11117756071353507391e-6 + (0.70814785110097658502e-9 + (0.40292553276632563925e-11 + 0.20145143075555555556e-13 * t) * t) * t) * t) * t) * t; -} -case 43: { -double t = 2*y100 - 87; -return 0.10668502059865093318e0 + (0.20965479776148731610e-2 + (0.16444612377624983565e-4 + (0.11700717962026152749e-6 + (0.74967203250938418991e-9 + (0.42783716186085922176e-11 + 0.21385479360000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 44: { -double t = 2*y100 - 89; -return 0.11094484319386444474e0 + (0.21637548491908170841e-2 + (0.17164995035719657111e-4 + (0.12317915750735938089e-6 + (0.79376309831499633734e-9 + (0.45427901763106353914e-11 + 0.22696025653333333333e-13 * t) * t) * t) * t) * t) * t; -} -case 45: { -double t = 2*y100 - 91; -return 0.11534201115268804714e0 + (0.22339187474546420375e-2 + (0.17923489217504226813e-4 + (0.12971465288245997681e-6 + (0.84057834180389073587e-9 + (0.48233721206418027227e-11 + 0.24079890062222222222e-13 * t) * t) * t) * t) * t) * t; -} -case 46: { -double t = 2*y100 - 93; -return 0.11988259392684094740e0 + (0.23071965691918689601e-2 + (0.18722342718958935446e-4 + (0.13663611754337957520e-6 + (0.89028385488493287005e-9 + (0.51210161569225846701e-11 + 0.25540227111111111111e-13 * t) * t) * t) * t) * t) * t; -} -case 47: { -double t = 2*y100 - 95; -return 0.12457298393509812907e0 + (0.23837544771809575380e-2 + (0.19563942105711612475e-4 + (0.14396736847739470782e-6 + (0.94305490646459247016e-9 + (0.54366590583134218096e-11 + 0.27080225920000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 48: { -double t = 2*y100 - 97; -return 0.12941991566142438816e0 + (0.24637684719508859484e-2 + (0.20450821127475879816e-4 + (0.15173366280523906622e-6 + (0.99907632506389027739e-9 + (0.57712760311351625221e-11 + 0.28703099555555555556e-13 * t) * t) * t) * t) * t) * t; -} -case 49: { -double t = 2*y100 - 99; -return 0.13443048593088696613e0 + (0.25474249981080823877e-2 + (0.21385669591362915223e-4 + (0.15996177579900443030e-6 + (0.10585428844575134013e-8 + (0.61258809536787882989e-11 + 0.30412080142222222222e-13 * t) * t) * t) * t) * t) * t; -} -case 50: { -double t = 2*y100 - 101; -return 0.13961217543434561353e0 + (0.26349215871051761416e-2 + (0.22371342712572567744e-4 + (0.16868008199296822247e-6 + (0.11216596910444996246e-8 + (0.65015264753090890662e-11 + 0.32210394506666666666e-13 * t) * t) * t) * t) * t) * t; -} -case 51: { -double t = 2*y100 - 103; -return 0.14497287157673800690e0 + (0.27264675383982439814e-2 + (0.23410870961050950197e-4 + (0.17791863939526376477e-6 + (0.11886425714330958106e-8 + (0.68993039665054288034e-11 + 0.34101266222222222221e-13 * t) * t) * t) * t) * t) * t; -} -case 52: { -double t = 2*y100 - 105; -return 0.15052089272774618151e0 + (0.28222846410136238008e-2 + (0.24507470422713397006e-4 + (0.18770927679626136909e-6 + (0.12597184587583370712e-8 + (0.73203433049229821618e-11 + 0.36087889048888888890e-13 * t) * t) * t) * t) * t) * t; -} -case 53: { -double t = 2*y100 - 107; -return 0.15626501395774612325e0 + (0.29226079376196624949e-2 + (0.25664553693768450545e-4 + (0.19808568415654461964e-6 + (0.13351257759815557897e-8 + (0.77658124891046760667e-11 + 0.38173420035555555555e-13 * t) * t) * t) * t) * t) * t; -} -case 54: { -double t = 2*y100 - 109; -return 0.16221449434620737567e0 + (0.30276865332726475672e-2 + (0.26885741326534564336e-4 + (0.20908350604346384143e-6 + (0.14151148144240728728e-8 + (0.82369170665974313027e-11 + 0.40360957457777777779e-13 * t) * t) * t) * t) * t) * t; -} -case 55: { -double t = 2*y100 - 111; -return 0.16837910595412130659e0 + (0.31377844510793082301e-2 + (0.28174873844911175026e-4 + (0.22074043807045782387e-6 + (0.14999481055996090039e-8 + (0.87348993661930809254e-11 + 0.42653528977777777779e-13 * t) * t) * t) * t) * t) * t; -} -case 56: { -double t = 2*y100 - 113; -return 0.17476916455659369953e0 + (0.32531815370903068316e-2 + (0.29536024347344364074e-4 + (0.23309632627767074202e-6 + (0.15899007843582444846e-8 + (0.92610375235427359475e-11 + 0.45054073102222222221e-13 * t) * t) * t) * t) * t) * t; -} -case 57: { -double t = 2*y100 - 115; -return 0.18139556223643701364e0 + (0.33741744168096996041e-2 + (0.30973511714709500836e-4 + (0.24619326937592290996e-6 + (0.16852609412267750744e-8 + (0.98166442942854895573e-11 + 0.47565418097777777779e-13 * t) * t) * t) * t) * t) * t; -} -case 58: { -double t = 2*y100 - 117; -return 0.18826980194443664549e0 + (0.35010775057740317997e-2 + (0.32491914440014267480e-4 + (0.26007572375886319028e-6 + (0.17863299617388376116e-8 + (0.10403065638343878679e-10 + 0.50190265831111111110e-13 * t) * t) * t) * t) * t) * t; -} -case 59: { -double t = 2*y100 - 119; -return 0.19540403413693967350e0 + (0.36342240767211326315e-2 + (0.34096085096200907289e-4 + (0.27479061117017637474e-6 + (0.18934228504790032826e-8 + (0.11021679075323598664e-10 + 0.52931171733333333334e-13 * t) * t) * t) * t) * t) * t; -} -case 60: { -double t = 2*y100 - 121; -return 0.20281109560651886959e0 + (0.37739673859323597060e-2 + (0.35791165457592409054e-4 + (0.29038742889416172404e-6 + (0.20068685374849001770e-8 + (0.11673891799578381999e-10 + 0.55790523093333333334e-13 * t) * t) * t) * t) * t) * t; -} -case 61: { -double t = 2*y100 - 123; -return 0.21050455062669334978e0 + (0.39206818613925652425e-2 + (0.37582602289680101704e-4 + (0.30691836231886877385e-6 + (0.21270101645763677824e-8 + (0.12361138551062899455e-10 + 0.58770520160000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 62: { -double t = 2*y100 - 125; -return 0.21849873453703332479e0 + (0.40747643554689586041e-2 + (0.39476163820986711501e-4 + (0.32443839970139918836e-6 + (0.22542053491518680200e-8 + (0.13084879235290858490e-10 + 0.61873153262222222221e-13 * t) * t) * t) * t) * t) * t; -} -case 63: { -double t = 2*y100 - 127; -return 0.22680879990043229327e0 + (0.42366354648628516935e-2 + (0.41477956909656896779e-4 + (0.34300544894502810002e-6 + (0.23888264229264067658e-8 + (0.13846596292818514601e-10 + 0.65100183751111111110e-13 * t) * t) * t) * t) * t) * t; -} -case 64: { -double t = 2*y100 - 129; -return 0.23545076536988703937e0 + (0.44067409206365170888e-2 + (0.43594444916224700881e-4 + (0.36268045617760415178e-6 + (0.25312606430853202748e-8 + (0.14647791812837903061e-10 + 0.68453122631111111110e-13 * t) * t) * t) * t) * t) * t; -} -case 65: { -double t = 2*y100 - 131; -return 0.24444156740777432838e0 + (0.45855530511605787178e-2 + (0.45832466292683085475e-4 + (0.38352752590033030472e-6 + (0.26819103733055603460e-8 + (0.15489984390884756993e-10 + 0.71933206364444444445e-13 * t) * t) * t) * t) * t) * t; -} -case 66: { -double t = 2*y100 - 133; -return 0.25379911500634264643e0 + (0.47735723208650032167e-2 + (0.48199253896534185372e-4 + (0.40561404245564732314e-6 + (0.28411932320871165585e-8 + (0.16374705736458320149e-10 + 0.75541379822222222221e-13 * t) * t) * t) * t) * t) * t; -} -case 67: { -double t = 2*y100 - 135; -return 0.26354234756393613032e0 + (0.49713289477083781266e-2 + (0.50702455036930367504e-4 + (0.42901079254268185722e-6 + (0.30095422058900481753e-8 + (0.17303497025347342498e-10 + 0.79278273368888888890e-13 * t) * t) * t) * t) * t) * t; -} -case 68: { -double t = 2*y100 - 137; -return 0.27369129607732343398e0 + (0.51793846023052643767e-2 + (0.53350152258326602629e-4 + (0.45379208848865015485e-6 + (0.31874057245814381257e-8 + (0.18277905010245111046e-10 + 0.83144182364444444445e-13 * t) * t) * t) * t) * t) * t; -} -case 69: { -double t = 2*y100 - 139; -return 0.28426714781640316172e0 + (0.53983341916695141966e-2 + (0.56150884865255810638e-4 + (0.48003589196494734238e-6 + (0.33752476967570796349e-8 + (0.19299477888083469086e-10 + 0.87139049137777777779e-13 * t) * t) * t) * t) * t) * t; -} -case 70: { -double t = 2*y100 - 141; -return 0.29529231465348519920e0 + (0.56288077305420795663e-2 + (0.59113671189913307427e-4 + (0.50782393781744840482e-6 + (0.35735475025851713168e-8 + (0.20369760937017070382e-10 + 0.91262442613333333334e-13 * t) * t) * t) * t) * t) * t; -} -case 71: { -double t = 2*y100 - 143; -return 0.30679050522528838613e0 + (0.58714723032745403331e-2 + (0.62248031602197686791e-4 + (0.53724185766200945789e-6 + (0.37827999418960232678e-8 + (0.21490291930444538307e-10 + 0.95513539182222222221e-13 * t) * t) * t) * t) * t) * t; -} -case 72: { -double t = 2*y100 - 145; -return 0.31878680111173319425e0 + (0.61270341192339103514e-2 + (0.65564012259707640976e-4 + (0.56837930287837738996e-6 + (0.40035151353392378882e-8 + (0.22662596341239294792e-10 + 0.99891109760000000000e-13 * t) * t) * t) * t) * t) * t; -} -case 73: { -double t = 2*y100 - 147; -return 0.33130773722152622027e0 + (0.63962406646798080903e-2 + (0.69072209592942396666e-4 + (0.60133006661885941812e-6 + (0.42362183765883466691e-8 + (0.23888182347073698382e-10 + 0.10439349811555555556e-12 * t) * t) * t) * t) * t) * t; -} -case 74: { -double t = 2*y100 - 149; -return 0.34438138658041336523e0 + (0.66798829540414007258e-2 + (0.72783795518603561144e-4 + (0.63619220443228800680e-6 + (0.44814499336514453364e-8 + (0.25168535651285475274e-10 + 0.10901861383111111111e-12 * t) * t) * t) * t) * t) * t; -} -case 75: { -double t = 2*y100 - 151; -return 0.35803744972380175583e0 + (0.69787978834882685031e-2 + (0.76710543371454822497e-4 + (0.67306815308917386747e-6 + (0.47397647975845228205e-8 + (0.26505114141143050509e-10 + 0.11376390933333333333e-12 * t) * t) * t) * t) * t) * t; -} -case 76: { -double t = 2*y100 - 153; -return 0.37230734890119724188e0 + (0.72938706896461381003e-2 + (0.80864854542670714092e-4 + (0.71206484718062688779e-6 + (0.50117323769745883805e-8 + (0.27899342394100074165e-10 + 0.11862637614222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 77: { -double t = 2*y100 - 155; -return 0.38722432730555448223e0 + (0.76260375162549802745e-2 + (0.85259785810004603848e-4 + (0.75329383305171327677e-6 + (0.52979361368388119355e-8 + (0.29352606054164086709e-10 + 0.12360253370666666667e-12 * t) * t) * t) * t) * t) * t; -} -case 78: { -double t = 2*y100 - 157; -return 0.40282355354616940667e0 + (0.79762880915029728079e-2 + (0.89909077342438246452e-4 + (0.79687137961956194579e-6 + (0.55989731807360403195e-8 + (0.30866246101464869050e-10 + 0.12868841946666666667e-12 * t) * t) * t) * t) * t) * t; -} -case 79: { -double t = 2*y100 - 159; -return 0.41914223158913787649e0 + (0.83456685186950463538e-2 + (0.94827181359250161335e-4 + (0.84291858561783141014e-6 + (0.59154537751083485684e-8 + (0.32441553034347469291e-10 + 0.13387957943111111111e-12 * t) * t) * t) * t) * t) * t; -} -case 80: { -double t = 2*y100 - 161; -return 0.43621971639463786896e0 + (0.87352841828289495773e-2 + (0.10002929142066799966e-3 + (0.89156148280219880024e-6 + (0.62480008150788597147e-8 + (0.34079760983458878910e-10 + 0.13917107176888888889e-12 * t) * t) * t) * t) * t) * t; -} -case 81: { -double t = 2*y100 - 163; -return 0.45409763548534330981e0 + (0.91463027755548240654e-2 + (0.10553137232446167258e-3 + (0.94293113464638623798e-6 + (0.65972492312219959885e-8 + (0.35782041795476563662e-10 + 0.14455745872000000000e-12 * t) * t) * t) * t) * t) * t; -} -case 82: { -double t = 2*y100 - 165; -return 0.47282001668512331468e0 + (0.95799574408860463394e-2 + (0.11135019058000067469e-3 + (0.99716373005509038080e-6 + (0.69638453369956970347e-8 + (0.37549499088161345850e-10 + 0.15003280712888888889e-12 * t) * t) * t) * t) * t) * t; -} -case 83: { -double t = 2*y100 - 167; -return 0.49243342227179841649e0 + (0.10037550043909497071e-1 + (0.11750334542845234952e-3 + (0.10544006716188967172e-5 + (0.73484461168242224872e-8 + (0.39383162326435752965e-10 + 0.15559069118222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 84: { -double t = 2*y100 - 169; -return 0.51298708979209258326e0 + (0.10520454564612427224e-1 + (0.12400930037494996655e-3 + (0.11147886579371265246e-5 + (0.77517184550568711454e-8 + (0.41283980931872622611e-10 + 0.16122419680000000000e-12 * t) * t) * t) * t) * t) * t; -} -case 85: { -double t = 2*y100 - 171; -return 0.53453307979101369843e0 + (0.11030120618800726938e-1 + (0.13088741519572269581e-3 + (0.11784797595374515432e-5 + (0.81743383063044825400e-8 + (0.43252818449517081051e-10 + 0.16692592640000000000e-12 * t) * t) * t) * t) * t) * t; -} -case 86: { -double t = 2*y100 - 173; -return 0.55712643071169299478e0 + (0.11568077107929735233e-1 + (0.13815797838036651289e-3 + (0.12456314879260904558e-5 + (0.86169898078969313597e-8 + (0.45290446811539652525e-10 + 0.17268801084444444444e-12 * t) * t) * t) * t) * t) * t; -} -case 87: { -double t = 2*y100 - 175; -return 0.58082532122519320968e0 + (0.12135935999503877077e-1 + (0.14584223996665838559e-3 + (0.13164068573095710742e-5 + (0.90803643355106020163e-8 + (0.47397540713124619155e-10 + 0.17850211608888888889e-12 * t) * t) * t) * t) * t) * t; -} -case 88: { -double t = 2*y100 - 177; -return 0.60569124025293375554e0 + (0.12735396239525550361e-1 + (0.15396244472258863344e-3 + (0.13909744385382818253e-5 + (0.95651595032306228245e-8 + (0.49574672127669041550e-10 + 0.18435945564444444444e-12 * t) * t) * t) * t) * t) * t; -} -case 89: { -double t = 2*y100 - 179; -return 0.63178916494715716894e0 + (0.13368247798287030927e-1 + (0.16254186562762076141e-3 + (0.14695084048334056083e-5 + (0.10072078109604152350e-7 + (0.51822304995680707483e-10 + 0.19025081422222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 90: { -double t = 2*y100 - 181; -return 0.65918774689725319200e0 + (0.14036375850601992063e-1 + (0.17160483760259706354e-3 + (0.15521885688723188371e-5 + (0.10601827031535280590e-7 + (0.54140790105837520499e-10 + 0.19616655146666666667e-12 * t) * t) * t) * t) * t) * t; -} -case 91: { -double t = 2*y100 - 183; -return 0.68795950683174433822e0 + (0.14741765091365869084e-1 + (0.18117679143520433835e-3 + (0.16392004108230585213e-5 + (0.11155116068018043001e-7 + (0.56530360194925690374e-10 + 0.20209663662222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 92: { -double t = 2*y100 - 185; -return 0.71818103808729967036e0 + (0.15486504187117112279e-1 + (0.19128428784550923217e-3 + (0.17307350969359975848e-5 + (0.11732656736113607751e-7 + (0.58991125287563833603e-10 + 0.20803065333333333333e-12 * t) * t) * t) * t) * t) * t; -} -case 93: { -double t = 2*y100 - 187; -return 0.74993321911726254661e0 + (0.16272790364044783382e-1 + (0.20195505163377912645e-3 + (0.18269894883203346953e-5 + (0.12335161021630225535e-7 + (0.61523068312169087227e-10 + 0.21395783431111111111e-12 * t) * t) * t) * t) * t) * t; -} -case 94: { -double t = 2*y100 - 189; -return 0.78330143531283492729e0 + (0.17102934132652429240e-1 + (0.21321800585063327041e-3 + (0.19281661395543913713e-5 + (0.12963340087354341574e-7 + (0.64126040998066348872e-10 + 0.21986708942222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 95: { -double t = 2*y100 - 191; -return 0.81837581041023811832e0 + (0.17979364149044223802e-1 + (0.22510330592753129006e-3 + (0.20344732868018175389e-5 + (0.13617902941839949718e-7 + (0.66799760083972474642e-10 + 0.22574701262222222222e-12 * t) * t) * t) * t) * t) * t; -} -case 96: { -double t = 2*y100 - 193; -return 0.85525144775685126237e0 + (0.18904632212547561026e-1 + (0.23764237370371255638e-3 + (0.21461248251306387979e-5 + (0.14299555071870523786e-7 + (0.69543803864694171934e-10 + 0.23158593688888888889e-12 * t) * t) * t) * t) * t) * t; -} -case 97: { -double t = 2*y100 - 195; -return 0.89402868170849933734e0 + (0.19881418399127202569e-1 + (0.25086793128395995798e-3 + (0.22633402747585233180e-5 + (0.15008997042116532283e-7 + (0.72357609075043941261e-10 + 0.23737194737777777778e-12 * t) * t) * t) * t) * t) * t; -} -case 98: { -double t = 2*y100 - 197; -return 0.93481333942870796363e0 + (0.20912536329780368893e-1 + (0.26481403465998477969e-3 + (0.23863447359754921676e-5 + (0.15746923065472184451e-7 + (0.75240468141720143653e-10 + 0.24309291271111111111e-12 * t) * t) * t) * t) * t) * t; -} -case 99: { -double t = 2*y100 - 199; -return 0.97771701335885035464e0 + (0.22000938572830479551e-1 + (0.27951610702682383001e-3 + (0.25153688325245314530e-5 + (0.16514019547822821453e-7 + (0.78191526829368231251e-10 + 0.24873652355555555556e-12 * t) * t) * t) * t) * t) * t; -} - } - // we only get here if y = 1, i.e. |x| < 4*eps, in which case - // erfcx is within 1e-15 of 1.. - return 1.0; -} - -double FADDEEVA_RE(erfcx)(double x) -{ - if (x >= 0) { - if (x > 50) { // continued-fraction expansion is faster - const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) - if (x > 5e7) // 1-term expansion, important to avoid overflow - return ispi / x; - /* 5-term expansion (rely on compiler for CSE), simplified from: - ispi / (x+0.5/(x+1/(x+1.5/(x+2/x)))) */ - return ispi*((x*x) * (x*x+4.5) + 2) / (x * ((x*x) * (x*x+5) + 3.75)); - } - return erfcx_y100(400/(4+x)); - } - else - return x < -26.7 ? HUGE_VAL : (x < -6.1 ? 2*exp(x*x) - : 2*exp(x*x) - erfcx_y100(400/(4-x))); -} - -///////////////////////////////////////////////////////////////////////// -/* Compute a scaled Dawson integral - FADDEEVA(w_im)(x) = 2*Dawson(x)/sqrt(pi) - equivalent to the imaginary part w(x) for real x. - - Uses methods similar to the erfcx calculation above: continued fractions - for large |x|, a lookup table of Chebyshev polynomials for smaller |x|, - and finally a Taylor expansion for |x|<0.01. - - Steven G. Johnson, October 2012. */ - -/* Given y100=100*y, where y = 1/(1+x) for x >= 0, compute w_im(x). - - Uses a look-up table of 100 different Chebyshev polynomials - for y intervals [0,0.01], [0.01,0.02], ...., [0.99,1], generated - with the help of Maple and a little shell script. This allows - the Chebyshev polynomials to be of significantly lower degree (about 1/30) - compared to fitting the whole [0,1] interval with a single polynomial. */ -static double w_im_y100(double y100, double x) { - switch ((int) y100) { - case 0: { - double t = 2*y100 - 1; - return 0.28351593328822191546e-2 + (0.28494783221378400759e-2 + (0.14427470563276734183e-4 + (0.10939723080231588129e-6 + (0.92474307943275042045e-9 + (0.89128907666450075245e-11 + 0.92974121935111111110e-13 * t) * t) * t) * t) * t) * t; - } - case 1: { - double t = 2*y100 - 3; - return 0.85927161243940350562e-2 + (0.29085312941641339862e-2 + (0.15106783707725582090e-4 + (0.11716709978531327367e-6 + (0.10197387816021040024e-8 + (0.10122678863073360769e-10 + 0.10917479678400000000e-12 * t) * t) * t) * t) * t) * t; - } - case 2: { - double t = 2*y100 - 5; - return 0.14471159831187703054e-1 + (0.29703978970263836210e-2 + (0.15835096760173030976e-4 + (0.12574803383199211596e-6 + (0.11278672159518415848e-8 + (0.11547462300333495797e-10 + 0.12894535335111111111e-12 * t) * t) * t) * t) * t) * t; - } - case 3: { - double t = 2*y100 - 7; - return 0.20476320420324610618e-1 + (0.30352843012898665856e-2 + (0.16617609387003727409e-4 + (0.13525429711163116103e-6 + (0.12515095552507169013e-8 + (0.13235687543603382345e-10 + 0.15326595042666666667e-12 * t) * t) * t) * t) * t) * t; - } - case 4: { - double t = 2*y100 - 9; - return 0.26614461952489004566e-1 + (0.31034189276234947088e-2 + (0.17460268109986214274e-4 + (0.14582130824485709573e-6 + (0.13935959083809746345e-8 + (0.15249438072998932900e-10 + 0.18344741882133333333e-12 * t) * t) * t) * t) * t) * t; - } - case 5: { - double t = 2*y100 - 11; - return 0.32892330248093586215e-1 + (0.31750557067975068584e-2 + (0.18369907582308672632e-4 + (0.15761063702089457882e-6 + (0.15577638230480894382e-8 + (0.17663868462699097951e-10 + (0.22126732680711111111e-12 + 0.30273474177737853668e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 6: { - double t = 2*y100 - 13; - return 0.39317207681134336024e-1 + (0.32504779701937539333e-2 + (0.19354426046513400534e-4 + (0.17081646971321290539e-6 + (0.17485733959327106250e-8 + (0.20593687304921961410e-10 + (0.26917401949155555556e-12 + 0.38562123837725712270e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 7: { - double t = 2*y100 - 15; - return 0.45896976511367738235e-1 + (0.33300031273110976165e-2 + (0.20423005398039037313e-4 + (0.18567412470376467303e-6 + (0.19718038363586588213e-8 + (0.24175006536781219807e-10 + (0.33059982791466666666e-12 + 0.49756574284439426165e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 8: { - double t = 2*y100 - 17; - return 0.52640192524848962855e-1 + (0.34139883358846720806e-2 + (0.21586390240603337337e-4 + (0.20247136501568904646e-6 + (0.22348696948197102935e-8 + (0.28597516301950162548e-10 + (0.41045502119111111110e-12 + 0.65151614515238361946e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 9: { - double t = 2*y100 - 19; - return 0.59556171228656770456e-1 + (0.35028374386648914444e-2 + (0.22857246150998562824e-4 + (0.22156372146525190679e-6 + (0.25474171590893813583e-8 + (0.34122390890697400584e-10 + (0.51593189879111111110e-12 + 0.86775076853908006938e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 10: { - double t = 2*y100 - 21; - return 0.66655089485108212551e-1 + (0.35970095381271285568e-2 + (0.24250626164318672928e-4 + (0.24339561521785040536e-6 + (0.29221990406518411415e-8 + (0.41117013527967776467e-10 + (0.65786450716444444445e-12 + 0.11791885745450623331e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 11: { - double t = 2*y100 - 23; - return 0.73948106345519174661e-1 + (0.36970297216569341748e-2 + (0.25784588137312868792e-4 + (0.26853012002366752770e-6 + (0.33763958861206729592e-8 + (0.50111549981376976397e-10 + (0.85313857496888888890e-12 + 0.16417079927706899860e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 12: { - double t = 2*y100 - 25; - return 0.81447508065002963203e-1 + (0.38035026606492705117e-2 + (0.27481027572231851896e-4 + (0.29769200731832331364e-6 + (0.39336816287457655076e-8 + (0.61895471132038157624e-10 + (0.11292303213511111111e-11 + 0.23558532213703884304e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 13: { - double t = 2*y100 - 27; - return 0.89166884027582716628e-1 + (0.39171301322438946014e-2 + (0.29366827260422311668e-4 + (0.33183204390350724895e-6 + (0.46276006281647330524e-8 + (0.77692631378169813324e-10 + (0.15335153258844444444e-11 + 0.35183103415916026911e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 14: { - double t = 2*y100 - 29; - return 0.97121342888032322019e-1 + (0.40387340353207909514e-2 + (0.31475490395950776930e-4 + (0.37222714227125135042e-6 + (0.55074373178613809996e-8 + (0.99509175283990337944e-10 + (0.21552645758222222222e-11 + 0.55728651431872687605e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 15: { - double t = 2*y100 - 31; - return 0.10532778218603311137e0 + (0.41692873614065380607e-2 + (0.33849549774889456984e-4 + (0.42064596193692630143e-6 + (0.66494579697622432987e-8 + (0.13094103581931802337e-9 + (0.31896187409777777778e-11 + 0.97271974184476560742e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 16: { - double t = 2*y100 - 33; - return 0.11380523107427108222e0 + (0.43099572287871821013e-2 + (0.36544324341565929930e-4 + (0.47965044028581857764e-6 + (0.81819034238463698796e-8 + (0.17934133239549647357e-9 + (0.50956666166186293627e-11 + (0.18850487318190638010e-12 + 0.79697813173519853340e-14 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 17: { - double t = 2*y100 - 35; - return 0.12257529703447467345e0 + (0.44621675710026986366e-2 + (0.39634304721292440285e-4 + (0.55321553769873381819e-6 + (0.10343619428848520870e-7 + (0.26033830170470368088e-9 + (0.87743837749108025357e-11 + (0.34427092430230063401e-12 + 0.10205506615709843189e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 18: { - double t = 2*y100 - 37; - return 0.13166276955656699478e0 + (0.46276970481783001803e-2 + (0.43225026380496399310e-4 + (0.64799164020016902656e-6 + (0.13580082794704641782e-7 + (0.39839800853954313927e-9 + (0.14431142411840000000e-10 + 0.42193457308830027541e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 19: { - double t = 2*y100 - 39; - return 0.14109647869803356475e0 + (0.48088424418545347758e-2 + (0.47474504753352150205e-4 + (0.77509866468724360352e-6 + (0.18536851570794291724e-7 + (0.60146623257887570439e-9 + (0.18533978397305276318e-10 + (0.41033845938901048380e-13 - 0.46160680279304825485e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 20: { - double t = 2*y100 - 41; - return 0.15091057940548936603e0 + (0.50086864672004685703e-2 + (0.52622482832192230762e-4 + (0.95034664722040355212e-6 + (0.25614261331144718769e-7 + (0.80183196716888606252e-9 + (0.12282524750534352272e-10 + (-0.10531774117332273617e-11 - 0.86157181395039646412e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 21: { - double t = 2*y100 - 43; - return 0.16114648116017010770e0 + (0.52314661581655369795e-2 + (0.59005534545908331315e-4 + (0.11885518333915387760e-5 + (0.33975801443239949256e-7 + (0.82111547144080388610e-9 + (-0.12357674017312854138e-10 + (-0.24355112256914479176e-11 - 0.75155506863572930844e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 22: { - double t = 2*y100 - 45; - return 0.17185551279680451144e0 + (0.54829002967599420860e-2 + (0.67013226658738082118e-4 + (0.14897400671425088807e-5 + (0.40690283917126153701e-7 + (0.44060872913473778318e-9 + (-0.52641873433280000000e-10 - 0.30940587864543343124e-11 * t) * t) * t) * t) * t) * t) * t; - } - case 23: { - double t = 2*y100 - 47; - return 0.18310194559815257381e0 + (0.57701559375966953174e-2 + (0.76948789401735193483e-4 + (0.18227569842290822512e-5 + (0.41092208344387212276e-7 + (-0.44009499965694442143e-9 + (-0.92195414685628803451e-10 + (-0.22657389705721753299e-11 + 0.10004784908106839254e-12 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 24: { - double t = 2*y100 - 49; - return 0.19496527191546630345e0 + (0.61010853144364724856e-2 + (0.88812881056342004864e-4 + (0.21180686746360261031e-5 + (0.30652145555130049203e-7 + (-0.16841328574105890409e-8 + (-0.11008129460612823934e-9 + (-0.12180794204544515779e-12 + 0.15703325634590334097e-12 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 25: { - double t = 2*y100 - 51; - return 0.20754006813966575720e0 + (0.64825787724922073908e-2 + (0.10209599627522311893e-3 + (0.22785233392557600468e-5 + (0.73495224449907568402e-8 + (-0.29442705974150112783e-8 + (-0.94082603434315016546e-10 + (0.23609990400179321267e-11 + 0.14141908654269023788e-12 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 26: { - double t = 2*y100 - 53; - return 0.22093185554845172146e0 + (0.69182878150187964499e-2 + (0.11568723331156335712e-3 + (0.22060577946323627739e-5 + (-0.26929730679360840096e-7 + (-0.38176506152362058013e-8 + (-0.47399503861054459243e-10 + (0.40953700187172127264e-11 + 0.69157730376118511127e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 27: { - double t = 2*y100 - 55; - return 0.23524827304057813918e0 + (0.74063350762008734520e-2 + (0.12796333874615790348e-3 + (0.18327267316171054273e-5 + (-0.66742910737957100098e-7 + (-0.40204740975496797870e-8 + (0.14515984139495745330e-10 + (0.44921608954536047975e-11 - 0.18583341338983776219e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 28: { - double t = 2*y100 - 57; - return 0.25058626331812744775e0 + (0.79377285151602061328e-2 + (0.13704268650417478346e-3 + (0.11427511739544695861e-5 + (-0.10485442447768377485e-6 + (-0.34850364756499369763e-8 + (0.72656453829502179208e-10 + (0.36195460197779299406e-11 - 0.84882136022200714710e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 29: { - double t = 2*y100 - 59; - return 0.26701724900280689785e0 + (0.84959936119625864274e-2 + (0.14112359443938883232e-3 + (0.17800427288596909634e-6 + (-0.13443492107643109071e-6 + (-0.23512456315677680293e-8 + (0.11245846264695936769e-9 + (0.19850501334649565404e-11 - 0.11284666134635050832e-12 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 30: { - double t = 2*y100 - 61; - return 0.28457293586253654144e0 + (0.90581563892650431899e-2 + (0.13880520331140646738e-3 + (-0.97262302362522896157e-6 + (-0.15077100040254187366e-6 + (-0.88574317464577116689e-9 + (0.12760311125637474581e-9 + (0.20155151018282695055e-12 - 0.10514169375181734921e-12 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 31: { - double t = 2*y100 - 63; - return 0.30323425595617385705e0 + (0.95968346790597422934e-2 + (0.12931067776725883939e-3 + (-0.21938741702795543986e-5 + (-0.15202888584907373963e-6 + (0.61788350541116331411e-9 + (0.11957835742791248256e-9 + (-0.12598179834007710908e-11 - 0.75151817129574614194e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 32: { - double t = 2*y100 - 65; - return 0.32292521181517384379e0 + (0.10082957727001199408e-1 + (0.11257589426154962226e-3 + (-0.33670890319327881129e-5 + (-0.13910529040004008158e-6 + (0.19170714373047512945e-8 + (0.94840222377720494290e-10 + (-0.21650018351795353201e-11 - 0.37875211678024922689e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 33: { - double t = 2*y100 - 67; - return 0.34351233557911753862e0 + (0.10488575435572745309e-1 + (0.89209444197248726614e-4 + (-0.43893459576483345364e-5 + (-0.11488595830450424419e-6 + (0.28599494117122464806e-8 + (0.61537542799857777779e-10 - 0.24935749227658002212e-11 * t) * t) * t) * t) * t) * t) * t; - } - case 34: { - double t = 2*y100 - 69; - return 0.36480946642143669093e0 + (0.10789304203431861366e-1 + (0.60357993745283076834e-4 + (-0.51855862174130669389e-5 + (-0.83291664087289801313e-7 + (0.33898011178582671546e-8 + (0.27082948188277716482e-10 + (-0.23603379397408694974e-11 + 0.19328087692252869842e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 35: { - double t = 2*y100 - 71; - return 0.38658679935694939199e0 + (0.10966119158288804999e-1 + (0.27521612041849561426e-4 + (-0.57132774537670953638e-5 + (-0.48404772799207914899e-7 + (0.35268354132474570493e-8 + (-0.32383477652514618094e-11 + (-0.19334202915190442501e-11 + 0.32333189861286460270e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 36: { - double t = 2*y100 - 73; - return 0.40858275583808707870e0 + (0.11006378016848466550e-1 + (-0.76396376685213286033e-5 + (-0.59609835484245791439e-5 + (-0.13834610033859313213e-7 + (0.33406952974861448790e-8 + (-0.26474915974296612559e-10 + (-0.13750229270354351983e-11 + 0.36169366979417390637e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 37: { - double t = 2*y100 - 75; - return 0.43051714914006682977e0 + (0.10904106549500816155e-1 + (-0.43477527256787216909e-4 + (-0.59429739547798343948e-5 + (0.17639200194091885949e-7 + (0.29235991689639918688e-8 + (-0.41718791216277812879e-10 + (-0.81023337739508049606e-12 + 0.33618915934461994428e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 38: { - double t = 2*y100 - 77; - return 0.45210428135559607406e0 + (0.10659670756384400554e-1 + (-0.78488639913256978087e-4 + (-0.56919860886214735936e-5 + (0.44181850467477733407e-7 + (0.23694306174312688151e-8 + (-0.49492621596685443247e-10 + (-0.31827275712126287222e-12 + 0.27494438742721623654e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 39: { - double t = 2*y100 - 79; - return 0.47306491195005224077e0 + (0.10279006119745977570e-1 + (-0.11140268171830478306e-3 + (-0.52518035247451432069e-5 + (0.64846898158889479518e-7 + (0.17603624837787337662e-8 + (-0.51129481592926104316e-10 + (0.62674584974141049511e-13 + 0.20055478560829935356e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 40: { - double t = 2*y100 - 81; - return 0.49313638965719857647e0 + (0.97725799114772017662e-2 + (-0.14122854267291533334e-3 + (-0.46707252568834951907e-5 + (0.79421347979319449524e-7 + (0.11603027184324708643e-8 + (-0.48269605844397175946e-10 + (0.32477251431748571219e-12 + 0.12831052634143527985e-13 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 41: { - double t = 2*y100 - 83; - return 0.51208057433416004042e0 + (0.91542422354009224951e-2 + (-0.16726530230228647275e-3 + (-0.39964621752527649409e-5 + (0.88232252903213171454e-7 + (0.61343113364949928501e-9 + (-0.42516755603130443051e-10 + (0.47910437172240209262e-12 + 0.66784341874437478953e-14 * t) * t) * t) * t) * t) * t) * t) * t; - } - case 42: { - double t = 2*y100 - 85; - return 0.52968945458607484524e0 + (0.84400880445116786088e-2 + (-0.18908729783854258774e-3 + (-0.32725905467782951931e-5 + (0.91956190588652090659e-7 + (0.14593989152420122909e-9 + (-0.35239490687644444445e-10 + 0.54613829888448694898e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 43: { - double t = 2*y100 - 87; - return 0.54578857454330070965e0 + (0.76474155195880295311e-2 + (-0.20651230590808213884e-3 + (-0.25364339140543131706e-5 + (0.91455367999510681979e-7 + (-0.23061359005297528898e-9 + (-0.27512928625244444444e-10 + 0.54895806008493285579e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 44: { - double t = 2*y100 - 89; - return 0.56023851910298493910e0 + (0.67938321739997196804e-2 + (-0.21956066613331411760e-3 + (-0.18181127670443266395e-5 + (0.87650335075416845987e-7 + (-0.51548062050366615977e-9 + (-0.20068462174044444444e-10 + 0.50912654909758187264e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 45: { - double t = 2*y100 - 91; - return 0.57293478057455721150e0 + (0.58965321010394044087e-2 + (-0.22841145229276575597e-3 + (-0.11404605562013443659e-5 + (0.81430290992322326296e-7 + (-0.71512447242755357629e-9 + (-0.13372664928000000000e-10 + 0.44461498336689298148e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 46: { - double t = 2*y100 - 93; - return 0.58380635448407827360e0 + (0.49717469530842831182e-2 + (-0.23336001540009645365e-3 + (-0.51952064448608850822e-6 + (0.73596577815411080511e-7 + (-0.84020916763091566035e-9 + (-0.76700972702222222221e-11 + 0.36914462807972467044e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 47: { - double t = 2*y100 - 95; - return 0.59281340237769489597e0 + (0.40343592069379730568e-2 + (-0.23477963738658326185e-3 + (0.34615944987790224234e-7 + (0.64832803248395814574e-7 + (-0.90329163587627007971e-9 + (-0.30421940400000000000e-11 + 0.29237386653743536669e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 48: { - double t = 2*y100 - 97; - return 0.59994428743114271918e0 + (0.30976579788271744329e-2 + (-0.23308875765700082835e-3 + (0.51681681023846925160e-6 + (0.55694594264948268169e-7 + (-0.91719117313243464652e-9 + (0.53982743680000000000e-12 + 0.22050829296187771142e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 49: { - double t = 2*y100 - 99; - return 0.60521224471819875444e0 + (0.21732138012345456060e-2 + (-0.22872428969625997456e-3 + (0.92588959922653404233e-6 + (0.46612665806531930684e-7 + (-0.89393722514414153351e-9 + (0.31718550353777777778e-11 + 0.15705458816080549117e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 50: { - double t = 2*y100 - 101; - return 0.60865189969791123620e0 + (0.12708480848877451719e-2 + (-0.22212090111534847166e-3 + (0.12636236031532793467e-5 + (0.37904037100232937574e-7 + (-0.84417089968101223519e-9 + (0.49843180828444444445e-11 + 0.10355439441049048273e-12 * t) * t) * t) * t) * t) * t) * t; - } - case 51: { - double t = 2*y100 - 103; - return 0.61031580103499200191e0 + (0.39867436055861038223e-3 + (-0.21369573439579869291e-3 + (0.15339402129026183670e-5 + (0.29787479206646594442e-7 + (-0.77687792914228632974e-9 + (0.61192452741333333334e-11 + 0.60216691829459295780e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 52: { - double t = 2*y100 - 105; - return 0.61027109047879835868e0 + (-0.43680904508059878254e-3 + (-0.20383783788303894442e-3 + (0.17421743090883439959e-5 + (0.22400425572175715576e-7 + (-0.69934719320045128997e-9 + (0.67152759655111111110e-11 + 0.26419960042578359995e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 53: { - double t = 2*y100 - 107; - return 0.60859639489217430521e0 + (-0.12305921390962936873e-2 + (-0.19290150253894682629e-3 + (0.18944904654478310128e-5 + (0.15815530398618149110e-7 + (-0.61726850580964876070e-9 + 0.68987888999111111110e-11 * t) * t) * t) * t) * t) * t; - } - case 54: { - double t = 2*y100 - 109; - return 0.60537899426486075181e0 + (-0.19790062241395705751e-2 + (-0.18120271393047062253e-3 + (0.19974264162313241405e-5 + (0.10055795094298172492e-7 + (-0.53491997919318263593e-9 + (0.67794550295111111110e-11 - 0.17059208095741511603e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 55: { - double t = 2*y100 - 111; - return 0.60071229457904110537e0 + (-0.26795676776166354354e-2 + (-0.16901799553627508781e-3 + (0.20575498324332621581e-5 + (0.51077165074461745053e-8 + (-0.45536079828057221858e-9 + (0.64488005516444444445e-11 - 0.29311677573152766338e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 56: { - double t = 2*y100 - 113; - return 0.59469361520112714738e0 + (-0.33308208190600993470e-2 + (-0.15658501295912405679e-3 + (0.20812116912895417272e-5 + (0.93227468760614182021e-9 + (-0.38066673740116080415e-9 + (0.59806790359111111110e-11 - 0.36887077278950440597e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 57: { - double t = 2*y100 - 115; - return 0.58742228631775388268e0 + (-0.39321858196059227251e-2 + (-0.14410441141450122535e-3 + (0.20743790018404020716e-5 + (-0.25261903811221913762e-8 + (-0.31212416519526924318e-9 + (0.54328422462222222221e-11 - 0.40864152484979815972e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 58: { - double t = 2*y100 - 117; - return 0.57899804200033018447e0 + (-0.44838157005618913447e-2 + (-0.13174245966501437965e-3 + (0.20425306888294362674e-5 + (-0.53330296023875447782e-8 + (-0.25041289435539821014e-9 + (0.48490437205333333334e-11 - 0.42162206939169045177e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 59: { - double t = 2*y100 - 119; - return 0.56951968796931245974e0 + (-0.49864649488074868952e-2 + (-0.11963416583477567125e-3 + (0.19906021780991036425e-5 + (-0.75580140299436494248e-8 + (-0.19576060961919820491e-9 + (0.42613011928888888890e-11 - 0.41539443304115604377e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 60: { - double t = 2*y100 - 121; - return 0.55908401930063918964e0 + (-0.54413711036826877753e-2 + (-0.10788661102511914628e-3 + (0.19229663322982839331e-5 + (-0.92714731195118129616e-8 + (-0.14807038677197394186e-9 + (0.36920870298666666666e-11 - 0.39603726688419162617e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 61: { - double t = 2*y100 - 123; - return 0.54778496152925675315e0 + (-0.58501497933213396670e-2 + (-0.96582314317855227421e-4 + (0.18434405235069270228e-5 + (-0.10541580254317078711e-7 + (-0.10702303407788943498e-9 + (0.31563175582222222222e-11 - 0.36829748079110481422e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 62: { - double t = 2*y100 - 125; - return 0.53571290831682823999e0 + (-0.62147030670760791791e-2 + (-0.85782497917111760790e-4 + (0.17553116363443470478e-5 + (-0.11432547349815541084e-7 + (-0.72157091369041330520e-10 + (0.26630811607111111111e-11 - 0.33578660425893164084e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 63: { - double t = 2*y100 - 127; - return 0.52295422962048434978e0 + (-0.65371404367776320720e-2 + (-0.75530164941473343780e-4 + (0.16613725797181276790e-5 + (-0.12003521296598910761e-7 + (-0.42929753689181106171e-10 + (0.22170894940444444444e-11 - 0.30117697501065110505e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 64: { - double t = 2*y100 - 129; - return 0.50959092577577886140e0 + (-0.68197117603118591766e-2 + (-0.65852936198953623307e-4 + (0.15639654113906716939e-5 + (-0.12308007991056524902e-7 + (-0.18761997536910939570e-10 + (0.18198628922666666667e-11 - 0.26638355362285200932e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 65: { - double t = 2*y100 - 131; - return 0.49570040481823167970e0 + (-0.70647509397614398066e-2 + (-0.56765617728962588218e-4 + (0.14650274449141448497e-5 + (-0.12393681471984051132e-7 + (0.92904351801168955424e-12 + (0.14706755960177777778e-11 - 0.23272455351266325318e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 66: { - double t = 2*y100 - 133; - return 0.48135536250935238066e0 + (-0.72746293327402359783e-2 + (-0.48272489495730030780e-4 + (0.13661377309113939689e-5 + (-0.12302464447599382189e-7 + (0.16707760028737074907e-10 + (0.11672928324444444444e-11 - 0.20105801424709924499e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 67: { - double t = 2*y100 - 135; - return 0.46662374675511439448e0 + (-0.74517177649528487002e-2 + (-0.40369318744279128718e-4 + (0.12685621118898535407e-5 + (-0.12070791463315156250e-7 + (0.29105507892605823871e-10 + (0.90653314645333333334e-12 - 0.17189503312102982646e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 68: { - double t = 2*y100 - 137; - return 0.45156879030168268778e0 + (-0.75983560650033817497e-2 + (-0.33045110380705139759e-4 + (0.11732956732035040896e-5 + (-0.11729986947158201869e-7 + (0.38611905704166441308e-10 + (0.68468768305777777779e-12 - 0.14549134330396754575e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 69: { - double t = 2*y100 - 139; - return 0.43624909769330896904e0 + (-0.77168291040309554679e-2 + (-0.26283612321339907756e-4 + (0.10811018836893550820e-5 + (-0.11306707563739851552e-7 + (0.45670446788529607380e-10 + (0.49782492549333333334e-12 - 0.12191983967561779442e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 70: { - double t = 2*y100 - 141; - return 0.42071877443548481181e0 + (-0.78093484015052730097e-2 + (-0.20064596897224934705e-4 + (0.99254806680671890766e-6 + (-0.10823412088884741451e-7 + (0.50677203326904716247e-10 + (0.34200547594666666666e-12 - 0.10112698698356194618e-13 * t) * t) * t) * t) * t) * t) * t; - } - case 71: { - double t = 2*y100 - 143; - return 0.40502758809710844280e0 + (-0.78780384460872937555e-2 + (-0.14364940764532853112e-4 + (0.90803709228265217384e-6 + (-0.10298832847014466907e-7 + (0.53981671221969478551e-10 + (0.21342751381333333333e-12 - 0.82975901848387729274e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 72: { - double t = 2*y100 - 145; - return 0.38922115269731446690e0 + (-0.79249269708242064120e-2 + (-0.91595258799106970453e-5 + (0.82783535102217576495e-6 + (-0.97484311059617744437e-8 + (0.55889029041660225629e-10 + (0.10851981336888888889e-12 - 0.67278553237853459757e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 73: { - double t = 2*y100 - 147; - return 0.37334112915460307335e0 + (-0.79519385109223148791e-2 + (-0.44219833548840469752e-5 + (0.75209719038240314732e-6 + (-0.91848251458553190451e-8 + (0.56663266668051433844e-10 + (0.23995894257777777778e-13 - 0.53819475285389344313e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 74: { - double t = 2*y100 - 149; - return 0.35742543583374223085e0 + (-0.79608906571527956177e-2 + (-0.12530071050975781198e-6 + (0.68088605744900552505e-6 + (-0.86181844090844164075e-8 + (0.56530784203816176153e-10 + (-0.43120012248888888890e-13 - 0.42372603392496813810e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 75: { - double t = 2*y100 - 151; - return 0.34150846431979618536e0 + (-0.79534924968773806029e-2 + (0.37576885610891515813e-5 + (0.61419263633090524326e-6 + (-0.80565865409945960125e-8 + (0.55684175248749269411e-10 + (-0.95486860764444444445e-13 - 0.32712946432984510595e-14 * t) * t) * t) * t) * t) * t) * t; - } - case 76: { - double t = 2*y100 - 153; - return 0.32562129649136346824e0 + (-0.79313448067948884309e-2 + (0.72539159933545300034e-5 + (0.55195028297415503083e-6 + (-0.75063365335570475258e-8 + (0.54281686749699595941e-10 - 0.13545424295111111111e-12 * t) * t) * t) * t) * t) * t; - } - case 77: { - double t = 2*y100 - 155; - return 0.30979191977078391864e0 + (-0.78959416264207333695e-2 + (0.10389774377677210794e-4 + (0.49404804463196316464e-6 + (-0.69722488229411164685e-8 + (0.52469254655951393842e-10 - 0.16507860650666666667e-12 * t) * t) * t) * t) * t) * t; - } - case 78: { - double t = 2*y100 - 157; - return 0.29404543811214459904e0 + (-0.78486728990364155356e-2 + (0.13190885683106990459e-4 + (0.44034158861387909694e-6 + (-0.64578942561562616481e-8 + (0.50354306498006928984e-10 - 0.18614473550222222222e-12 * t) * t) * t) * t) * t) * t; - } - case 79: { - double t = 2*y100 - 159; - return 0.27840427686253660515e0 + (-0.77908279176252742013e-2 + (0.15681928798708548349e-4 + (0.39066226205099807573e-6 + (-0.59658144820660420814e-8 + (0.48030086420373141763e-10 - 0.20018995173333333333e-12 * t) * t) * t) * t) * t) * t; - } - case 80: { - double t = 2*y100 - 161; - return 0.26288838011163800908e0 + (-0.77235993576119469018e-2 + (0.17886516796198660969e-4 + (0.34482457073472497720e-6 + (-0.54977066551955420066e-8 + (0.45572749379147269213e-10 - 0.20852924954666666667e-12 * t) * t) * t) * t) * t) * t; - } - case 81: { - double t = 2*y100 - 163; - return 0.24751539954181029717e0 + (-0.76480877165290370975e-2 + (0.19827114835033977049e-4 + (0.30263228619976332110e-6 + (-0.50545814570120129947e-8 + (0.43043879374212005966e-10 - 0.21228012028444444444e-12 * t) * t) * t) * t) * t) * t; - } - case 82: { - double t = 2*y100 - 165; - return 0.23230087411688914593e0 + (-0.75653060136384041587e-2 + (0.21524991113020016415e-4 + (0.26388338542539382413e-6 + (-0.46368974069671446622e-8 + (0.40492715758206515307e-10 - 0.21238627815111111111e-12 * t) * t) * t) * t) * t) * t; - } - case 83: { - double t = 2*y100 - 167; - return 0.21725840021297341931e0 + (-0.74761846305979730439e-2 + (0.23000194404129495243e-4 + (0.22837400135642906796e-6 + (-0.42446743058417541277e-8 + (0.37958104071765923728e-10 - 0.20963978568888888889e-12 * t) * t) * t) * t) * t) * t; - } - case 84: { - double t = 2*y100 - 169; - return 0.20239979200788191491e0 + (-0.73815761980493466516e-2 + (0.24271552727631854013e-4 + (0.19590154043390012843e-6 + (-0.38775884642456551753e-8 + (0.35470192372162901168e-10 - 0.20470131678222222222e-12 * t) * t) * t) * t) * t) * t; - } - case 85: { - double t = 2*y100 - 171; - return 0.18773523211558098962e0 + (-0.72822604530339834448e-2 + (0.25356688567841293697e-4 + (0.16626710297744290016e-6 + (-0.35350521468015310830e-8 + (0.33051896213898864306e-10 - 0.19811844544000000000e-12 * t) * t) * t) * t) * t) * t; - } - case 86: { - double t = 2*y100 - 173; - return 0.17327341258479649442e0 + (-0.71789490089142761950e-2 + (0.26272046822383820476e-4 + (0.13927732375657362345e-6 + (-0.32162794266956859603e-8 + (0.30720156036105652035e-10 - 0.19034196304000000000e-12 * t) * t) * t) * t) * t) * t; - } - case 87: { - double t = 2*y100 - 175; - return 0.15902166648328672043e0 + (-0.70722899934245504034e-2 + (0.27032932310132226025e-4 + (0.11474573347816568279e-6 + (-0.29203404091754665063e-8 + (0.28487010262547971859e-10 - 0.18174029063111111111e-12 * t) * t) * t) * t) * t) * t; - } - case 88: { - double t = 2*y100 - 177; - return 0.14498609036610283865e0 + (-0.69628725220045029273e-2 + (0.27653554229160596221e-4 + (0.92493727167393036470e-7 + (-0.26462055548683583849e-8 + (0.26360506250989943739e-10 - 0.17261211260444444444e-12 * t) * t) * t) * t) * t) * t; - } - case 89: { - double t = 2*y100 - 179; - return 0.13117165798208050667e0 + (-0.68512309830281084723e-2 + (0.28147075431133863774e-4 + (0.72351212437979583441e-7 + (-0.23927816200314358570e-8 + (0.24345469651209833155e-10 - 0.16319736960000000000e-12 * t) * t) * t) * t) * t) * t; - } - case 90: { - double t = 2*y100 - 181; - return 0.11758232561160626306e0 + (-0.67378491192463392927e-2 + (0.28525664781722907847e-4 + (0.54156999310046790024e-7 + (-0.21589405340123827823e-8 + (0.22444150951727334619e-10 - 0.15368675584000000000e-12 * t) * t) * t) * t) * t) * t; - } - case 91: { - double t = 2*y100 - 183; - return 0.10422112945361673560e0 + (-0.66231638959845581564e-2 + (0.28800551216363918088e-4 + (0.37758983397952149613e-7 + (-0.19435423557038933431e-8 + (0.20656766125421362458e-10 - 0.14422990012444444444e-12 * t) * t) * t) * t) * t) * t; - } - case 92: { - double t = 2*y100 - 185; - return 0.91090275493541084785e-1 + (-0.65075691516115160062e-2 + (0.28982078385527224867e-4 + (0.23014165807643012781e-7 + (-0.17454532910249875958e-8 + (0.18981946442680092373e-10 - 0.13494234691555555556e-12 * t) * t) * t) * t) * t) * t; - } - case 93: { - double t = 2*y100 - 187; - return 0.78191222288771379358e-1 + (-0.63914190297303976434e-2 + (0.29079759021299682675e-4 + (0.97885458059415717014e-8 + (-0.15635596116134296819e-8 + (0.17417110744051331974e-10 - 0.12591151763555555556e-12 * t) * t) * t) * t) * t) * t; - } - case 94: { - double t = 2*y100 - 189; - return 0.65524757106147402224e-1 + (-0.62750311956082444159e-2 + (0.29102328354323449795e-4 + (-0.20430838882727954582e-8 + (-0.13967781903855367270e-8 + (0.15958771833747057569e-10 - 0.11720175765333333333e-12 * t) * t) * t) * t) * t) * t; - } - case 95: { - double t = 2*y100 - 191; - return 0.53091065838453612773e-1 + (-0.61586898417077043662e-2 + (0.29057796072960100710e-4 + (-0.12597414620517987536e-7 + (-0.12440642607426861943e-8 + (0.14602787128447932137e-10 - 0.10885859114666666667e-12 * t) * t) * t) * t) * t) * t; - } - case 96: { - double t = 2*y100 - 193; - return 0.40889797115352738582e-1 + (-0.60426484889413678200e-2 + (0.28953496450191694606e-4 + (-0.21982952021823718400e-7 + (-0.11044169117553026211e-8 + (0.13344562332430552171e-10 - 0.10091231402844444444e-12 * t) * t) * t) * t) * t) * t; - } - case 97: case 98: - case 99: case 100: { // use Taylor expansion for small x (|x| <= 0.0309...) - // (2/sqrt(pi)) * (x - 2/3 x^3 + 4/15 x^5 - 8/105 x^7 + 16/945 x^9) - double x2 = x*x; - return x * (1.1283791670955125739 - - x2 * (0.75225277806367504925 - - x2 * (0.30090111122547001970 - - x2 * (0.085971746064420005629 - - x2 * 0.016931216931216931217)))); - } - } - /* Since 0 <= y100 < 101, this is only reached if x is NaN, - in which case we should return NaN. */ - return NaN; -} - -double FADDEEVA(w_im)(double x) -{ - if (x >= 0) { - if (x > 45) { // continued-fraction expansion is faster - const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) - if (x > 5e7) // 1-term expansion, important to avoid overflow - return ispi / x; - /* 5-term expansion (rely on compiler for CSE), simplified from: - ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ - return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); - } - return w_im_y100(100/(1+x), x); - } - else { // = -FADDEEVA(w_im)(-x) - if (x < -45) { // continued-fraction expansion is faster - const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) - if (x < -5e7) // 1-term expansion, important to avoid overflow - return ispi / x; - /* 5-term expansion (rely on compiler for CSE), simplified from: - ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ - return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); - } - return -w_im_y100(100/(1-x), -x); - } -} - -///////////////////////////////////////////////////////////////////////// - -// Compile with -DTEST_FADDEEVA to compile a little test program -#ifdef TEST_FADDEEVA - -#ifdef __cplusplus -# include -#else -# include -#endif - -// compute relative error |b-a|/|a|, handling case of NaN and Inf, -static double relerr(double a, double b) { - if (isnan(a) || isnan(b) || isinf(a) || isinf(b)) { - if ((isnan(a) && !isnan(b)) || (!isnan(a) && isnan(b)) || - (isinf(a) && !isinf(b)) || (!isinf(a) && isinf(b)) || - (isinf(a) && isinf(b) && a*b < 0)) - return Inf; // "infinite" error - return 0; // matching infinity/nan results counted as zero error - } - if (a == 0) - return b == 0 ? 0 : Inf; - else - return fabs((b-a) / a); -} - -int main(void) { - double errmax_all = 0; - { - printf("############# w(z) tests #############\n"); -#define NTST 57 // define instead of const for C compatibility - cmplx z[NTST] = { - C(624.2,-0.26123), - C(-0.4,3.), - C(0.6,2.), - C(-1.,1.), - C(-1.,-9.), - C(-1.,9.), - C(-0.0000000234545,1.1234), - C(-3.,5.1), - C(-53,30.1), - C(0.0,0.12345), - C(11,1), - C(-22,-2), - C(9,-28), - C(21,-33), - C(1e5,1e5), - C(1e14,1e14), - C(-3001,-1000), - C(1e160,-1e159), - C(-6.01,0.01), - C(-0.7,-0.7), - C(2.611780000000000e+01, 4.540909610972489e+03), - C(0.8e7,0.3e7), - C(-20,-19.8081), - C(1e-16,-1.1e-16), - C(2.3e-8,1.3e-8), - C(6.3,-1e-13), - C(6.3,1e-20), - C(1e-20,6.3), - C(1e-20,16.3), - C(9,1e-300), - C(6.01,0.11), - C(8.01,1.01e-10), - C(28.01,1e-300), - C(10.01,1e-200), - C(10.01,-1e-200), - C(10.01,0.99e-10), - C(10.01,-0.99e-10), - C(1e-20,7.01), - C(-1,7.01), - C(5.99,7.01), - C(1,0), - C(55,0), - C(-0.1,0), - C(1e-20,0), - C(0,5e-14), - C(0,51), - C(Inf,0), - C(-Inf,0), - C(0,Inf), - C(0,-Inf), - C(Inf,Inf), - C(Inf,-Inf), - C(NaN,NaN), - C(NaN,0), - C(0,NaN), - C(NaN,Inf), - C(Inf,NaN) - }; - cmplx w[NTST] = { /* w(z), computed with WolframAlpha - ... note that WolframAlpha is problematic - some of the above inputs, so I had to - use the continued-fraction expansion - in WolframAlpha in some cases, or switch - to Maple */ - C(-3.78270245518980507452677445620103199303131110e-7, - 0.000903861276433172057331093754199933411710053155), - C(0.1764906227004816847297495349730234591778719532788, - -0.02146550539468457616788719893991501311573031095617), - C(0.2410250715772692146133539023007113781272362309451, - 0.06087579663428089745895459735240964093522265589350), - C(0.30474420525691259245713884106959496013413834051768, - -0.20821893820283162728743734725471561394145872072738), - C(7.317131068972378096865595229600561710140617977e34, - 8.321873499714402777186848353320412813066170427e34), - C(0.0615698507236323685519612934241429530190806818395, - -0.00676005783716575013073036218018565206070072304635), - C(0.3960793007699874918961319170187598400134746631, - -5.593152259116644920546186222529802777409274656e-9), - C(0.08217199226739447943295069917990417630675021771804, - -0.04701291087643609891018366143118110965272615832184), - C(0.00457246000350281640952328010227885008541748668738, - -0.00804900791411691821818731763401840373998654987934), - C(0.8746342859608052666092782112565360755791467973338452, - 0.), - C(0.00468190164965444174367477874864366058339647648741, - 0.0510735563901306197993676329845149741675029197050), - C(-0.0023193175200187620902125853834909543869428763219, - -0.025460054739731556004902057663500272721780776336), - C(9.11463368405637174660562096516414499772662584e304, - 3.97101807145263333769664875189354358563218932e305), - C(-4.4927207857715598976165541011143706155432296e281, - -2.8019591213423077494444700357168707775769028e281), - C(2.820947917809305132678577516325951485807107151e-6, - 2.820947917668257736791638444590253942253354058e-6), - C(2.82094791773878143474039725787438662716372268e-15, - 2.82094791773878143474039725773333923127678361e-15), - C(-0.0000563851289696244350147899376081488003110150498, - -0.000169211755126812174631861529808288295454992688), - C(-5.586035480670854326218608431294778077663867e-162, - 5.586035480670854326218608431294778077663867e-161), - C(0.00016318325137140451888255634399123461580248456, - -0.095232456573009287370728788146686162555021209999), - C(0.69504753678406939989115375989939096800793577783885, - -1.8916411171103639136680830887017670616339912024317), - C(0.0001242418269653279656612334210746733213167234822, - 7.145975826320186888508563111992099992116786763e-7), - C(2.318587329648353318615800865959225429377529825e-8, - 6.182899545728857485721417893323317843200933380e-8), - C(-0.0133426877243506022053521927604277115767311800303, - -0.0148087097143220769493341484176979826888871576145), - C(1.00000000000000012412170838050638522857747934, - 1.12837916709551279389615890312156495593616433e-16), - C(0.9999999853310704677583504063775310832036830015, - 2.595272024519678881897196435157270184030360773e-8), - C(-1.4731421795638279504242963027196663601154624e-15, - 0.090727659684127365236479098488823462473074709), - C(5.79246077884410284575834156425396800754409308e-18, - 0.0907276596841273652364790985059772809093822374), - C(0.0884658993528521953466533278764830881245144368, - 1.37088352495749125283269718778582613192166760e-22), - C(0.0345480845419190424370085249304184266813447878, - 2.11161102895179044968099038990446187626075258e-23), - C(6.63967719958073440070225527042829242391918213e-36, - 0.0630820900592582863713653132559743161572639353), - C(0.00179435233208702644891092397579091030658500743634, - 0.0951983814805270647939647438459699953990788064762), - C(9.09760377102097999924241322094863528771095448e-13, - 0.0709979210725138550986782242355007611074966717), - C(7.2049510279742166460047102593255688682910274423e-304, - 0.0201552956479526953866611812593266285000876784321), - C(3.04543604652250734193622967873276113872279682e-44, - 0.0566481651760675042930042117726713294607499165), - C(3.04543604652250734193622967873276113872279682e-44, - 0.0566481651760675042930042117726713294607499165), - C(0.5659928732065273429286988428080855057102069081e-12, - 0.056648165176067504292998527162143030538756683302), - C(-0.56599287320652734292869884280802459698927645e-12, - 0.0566481651760675042929985271621430305387566833029), - C(0.0796884251721652215687859778119964009569455462, - 1.11474461817561675017794941973556302717225126e-22), - C(0.07817195821247357458545539935996687005781943386550, - -0.01093913670103576690766705513142246633056714279654), - C(0.04670032980990449912809326141164730850466208439937, - 0.03944038961933534137558064191650437353429669886545), - C(0.36787944117144232159552377016146086744581113103176, - 0.60715770584139372911503823580074492116122092866515), - C(0, - 0.010259688805536830986089913987516716056946786526145), - C(0.99004983374916805357390597718003655777207908125383, - -0.11208866436449538036721343053869621153527769495574), - C(0.99999999999999999999999999999999999999990000, - 1.12837916709551257389615890312154517168802603e-20), - C(0.999999999999943581041645226871305192054749891144158, - 0), - C(0.0110604154853277201542582159216317923453996211744250, - 0), - C(0,0), - C(0,0), - C(0,0), - C(Inf,0), - C(0,0), - C(NaN,NaN), - C(NaN,NaN), - C(NaN,NaN), - C(NaN,0), - C(NaN,NaN), - C(NaN,NaN) - }; - double errmax = 0; - for (int i = 0; i < NTST; ++i) { - cmplx fw = FADDEEVA(w)(z[i],0.); - double re_err = relerr(creal(w[i]), creal(fw)); - double im_err = relerr(cimag(w[i]), cimag(fw)); - printf("w(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", - creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), - re_err, im_err); - if (re_err > errmax) errmax = re_err; - if (im_err > errmax) errmax = im_err; - } - if (errmax > 1e-13) { - printf("FAILURE -- relative error %g too large!\n", errmax); - return 1; - } - printf("SUCCESS (max relative error = %g)\n", errmax); - if (errmax > errmax_all) errmax_all = errmax; - } - { -#undef NTST -#define NTST 41 // define instead of const for C compatibility - cmplx z[NTST] = { - C(1,2), - C(-1,2), - C(1,-2), - C(-1,-2), - C(9,-28), - C(21,-33), - C(1e3,1e3), - C(-3001,-1000), - C(1e160,-1e159), - C(5.1e-3, 1e-8), - C(-4.9e-3, 4.95e-3), - C(4.9e-3, 0.5), - C(4.9e-4, -0.5e1), - C(-4.9e-5, -0.5e2), - C(5.1e-3, 0.5), - C(5.1e-4, -0.5e1), - C(-5.1e-5, -0.5e2), - C(1e-6,2e-6), - C(0,2e-6), - C(0,2), - C(0,20), - C(0,200), - C(Inf,0), - C(-Inf,0), - C(0,Inf), - C(0,-Inf), - C(Inf,Inf), - C(Inf,-Inf), - C(NaN,NaN), - C(NaN,0), - C(0,NaN), - C(NaN,Inf), - C(Inf,NaN), - C(1e-3,NaN), - C(7e-2,7e-2), - C(7e-2,-7e-4), - C(-9e-2,7e-4), - C(-9e-2,9e-2), - C(-7e-4,9e-2), - C(7e-2,0.9e-2), - C(7e-2,1.1e-2) - }; - cmplx w[NTST] = { // erf(z[i]), evaluated with Maple - C(-0.5366435657785650339917955593141927494421, - -5.049143703447034669543036958614140565553), - C(0.5366435657785650339917955593141927494421, - -5.049143703447034669543036958614140565553), - C(-0.5366435657785650339917955593141927494421, - 5.049143703447034669543036958614140565553), - C(0.5366435657785650339917955593141927494421, - 5.049143703447034669543036958614140565553), - C(0.3359473673830576996788000505817956637777e304, - -0.1999896139679880888755589794455069208455e304), - C(0.3584459971462946066523939204836760283645e278, - 0.3818954885257184373734213077678011282505e280), - C(0.9996020422657148639102150147542224526887, - 0.00002801044116908227889681753993542916894856), - C(-1, 0), - C(1, 0), - C(0.005754683859034800134412990541076554934877, - 0.1128349818335058741511924929801267822634e-7), - C(-0.005529149142341821193633460286828381876955, - 0.005585388387864706679609092447916333443570), - C(0.007099365669981359632319829148438283865814, - 0.6149347012854211635026981277569074001219), - C(0.3981176338702323417718189922039863062440e8, - -0.8298176341665249121085423917575122140650e10), - C(-Inf, - -Inf), - C(0.007389128308257135427153919483147229573895, - 0.6149332524601658796226417164791221815139), - C(0.4143671923267934479245651547534414976991e8, - -0.8298168216818314211557046346850921446950e10), - C(-Inf, - -Inf), - C(0.1128379167099649964175513742247082845155e-5, - 0.2256758334191777400570377193451519478895e-5), - C(0, - 0.2256758334194034158904576117253481476197e-5), - C(0, - 18.56480241457555259870429191324101719886), - C(0, - 0.1474797539628786202447733153131835124599e173), - C(0, - Inf), - C(1,0), - C(-1,0), - C(0,Inf), - C(0,-Inf), - C(NaN,NaN), - C(NaN,NaN), - C(NaN,NaN), - C(NaN,0), - C(0,NaN), - C(NaN,NaN), - C(NaN,NaN), - C(NaN,NaN), - C(0.07924380404615782687930591956705225541145, - 0.07872776218046681145537914954027729115247), - C(0.07885775828512276968931773651224684454495, - -0.0007860046704118224342390725280161272277506), - C(-0.1012806432747198859687963080684978759881, - 0.0007834934747022035607566216654982820299469), - C(-0.1020998418798097910247132140051062512527, - 0.1010030778892310851309082083238896270340), - C(-0.0007962891763147907785684591823889484764272, - 0.1018289385936278171741809237435404896152), - C(0.07886408666470478681566329888615410479530, - 0.01010604288780868961492224347707949372245), - C(0.07886723099940260286824654364807981336591, - 0.01235199327873258197931147306290916629654) - }; -#define TST(f,isc) \ - printf("############# " #f "(z) tests #############\n"); \ - double errmax = 0; \ - for (int i = 0; i < NTST; ++i) { \ - cmplx fw = FADDEEVA(f)(z[i],0.); \ - double re_err = relerr(creal(w[i]), creal(fw)); \ - double im_err = relerr(cimag(w[i]), cimag(fw)); \ - printf(#f "(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", \ - creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), \ - re_err, im_err); \ - if (re_err > errmax) errmax = re_err; \ - if (im_err > errmax) errmax = im_err; \ - } \ - if (errmax > 1e-13) { \ - printf("FAILURE -- relative error %g too large!\n", errmax); \ - return 1; \ - } \ - printf("Checking " #f "(x) special case...\n"); \ - for (int i = 0; i < 10000; ++i) { \ - double x = pow(10., -300. + i * 600. / (10000 - 1)); \ - double re_err = relerr(FADDEEVA_RE(f)(x), \ - creal(FADDEEVA(f)(C(x,x*isc),0.))); \ - if (re_err > errmax) errmax = re_err; \ - re_err = relerr(FADDEEVA_RE(f)(-x), \ - creal(FADDEEVA(f)(C(-x,x*isc),0.))); \ - if (re_err > errmax) errmax = re_err; \ - } \ - { \ - double re_err = relerr(FADDEEVA_RE(f)(Inf), \ - creal(FADDEEVA(f)(C(Inf,0.),0.))); \ - if (re_err > errmax) errmax = re_err; \ - re_err = relerr(FADDEEVA_RE(f)(-Inf), \ - creal(FADDEEVA(f)(C(-Inf,0.),0.))); \ - if (re_err > errmax) errmax = re_err; \ - re_err = relerr(FADDEEVA_RE(f)(NaN), \ - creal(FADDEEVA(f)(C(NaN,0.),0.))); \ - if (re_err > errmax) errmax = re_err; \ - } \ - if (errmax > 1e-13) { \ - printf("FAILURE -- relative error %g too large!\n", errmax); \ - return 1; \ - } \ - printf("SUCCESS (max relative error = %g)\n", errmax); \ - if (errmax > errmax_all) errmax_all = errmax - - TST(erf, 1e-20); - } - { - // since erfi just calls through to erf, just one test should - // be sufficient to make sure I didn't screw up the signs or something -#undef NTST -#define NTST 1 // define instead of const for C compatibility - cmplx z[NTST] = { C(1.234,0.5678) }; - cmplx w[NTST] = { // erfi(z[i]), computed with Maple - C(1.081032284405373149432716643834106923212, - 1.926775520840916645838949402886591180834) - }; - TST(erfi, 0); - } - { - // since erfcx just calls through to w, just one test should - // be sufficient to make sure I didn't screw up the signs or something -#undef NTST -#define NTST 1 // define instead of const for C compatibility - cmplx z[NTST] = { C(1.234,0.5678) }; - cmplx w[NTST] = { // erfcx(z[i]), computed with Maple - C(0.3382187479799972294747793561190487832579, - -0.1116077470811648467464927471872945833154) - }; - TST(erfcx, 0); - } - { -#undef NTST -#define NTST 30 // define instead of const for C compatibility - cmplx z[NTST] = { - C(1,2), - C(-1,2), - C(1,-2), - C(-1,-2), - C(9,-28), - C(21,-33), - C(1e3,1e3), - C(-3001,-1000), - C(1e160,-1e159), - C(5.1e-3, 1e-8), - C(0,2e-6), - C(0,2), - C(0,20), - C(0,200), - C(2e-6,0), - C(2,0), - C(20,0), - C(200,0), - C(Inf,0), - C(-Inf,0), - C(0,Inf), - C(0,-Inf), - C(Inf,Inf), - C(Inf,-Inf), - C(NaN,NaN), - C(NaN,0), - C(0,NaN), - C(NaN,Inf), - C(Inf,NaN), - C(88,0) - }; - cmplx w[NTST] = { // erfc(z[i]), evaluated with Maple - C(1.536643565778565033991795559314192749442, - 5.049143703447034669543036958614140565553), - C(0.4633564342214349660082044406858072505579, - 5.049143703447034669543036958614140565553), - C(1.536643565778565033991795559314192749442, - -5.049143703447034669543036958614140565553), - C(0.4633564342214349660082044406858072505579, - -5.049143703447034669543036958614140565553), - C(-0.3359473673830576996788000505817956637777e304, - 0.1999896139679880888755589794455069208455e304), - C(-0.3584459971462946066523939204836760283645e278, - -0.3818954885257184373734213077678011282505e280), - C(0.0003979577342851360897849852457775473112748, - -0.00002801044116908227889681753993542916894856), - C(2, 0), - C(0, 0), - C(0.9942453161409651998655870094589234450651, - -0.1128349818335058741511924929801267822634e-7), - C(1, - -0.2256758334194034158904576117253481476197e-5), - C(1, - -18.56480241457555259870429191324101719886), - C(1, - -0.1474797539628786202447733153131835124599e173), - C(1, -Inf), - C(0.9999977432416658119838633199332831406314, - 0), - C(0.004677734981047265837930743632747071389108, - 0), - C(0.5395865611607900928934999167905345604088e-175, - 0), - C(0, 0), - C(0, 0), - C(2, 0), - C(1, -Inf), - C(1, Inf), - C(NaN, NaN), - C(NaN, NaN), - C(NaN, NaN), - C(NaN, 0), - C(1, NaN), - C(NaN, NaN), - C(NaN, NaN), - C(0,0) - }; - TST(erfc, 1e-20); - } - { -#undef NTST -#define NTST 48 // define instead of const for C compatibility - cmplx z[NTST] = { - C(2,1), - C(-2,1), - C(2,-1), - C(-2,-1), - C(-28,9), - C(33,-21), - C(1e3,1e3), - C(-1000,-3001), - C(1e-8, 5.1e-3), - C(4.95e-3, -4.9e-3), - C(5.1e-3, 5.1e-3), - C(0.5, 4.9e-3), - C(-0.5e1, 4.9e-4), - C(-0.5e2, -4.9e-5), - C(0.5e3, 4.9e-6), - C(0.5, 5.1e-3), - C(-0.5e1, 5.1e-4), - C(-0.5e2, -5.1e-5), - C(1e-6,2e-6), - C(2e-6,0), - C(2,0), - C(20,0), - C(200,0), - C(0,4.9e-3), - C(0,-5.1e-3), - C(0,2e-6), - C(0,-2), - C(0,20), - C(0,-200), - C(Inf,0), - C(-Inf,0), - C(0,Inf), - C(0,-Inf), - C(Inf,Inf), - C(Inf,-Inf), - C(NaN,NaN), - C(NaN,0), - C(0,NaN), - C(NaN,Inf), - C(Inf,NaN), - C(39, 6.4e-5), - C(41, 6.09e-5), - C(4.9e7, 5e-11), - C(5.1e7, 4.8e-11), - C(1e9, 2.4e-12), - C(1e11, 2.4e-14), - C(1e13, 2.4e-16), - C(1e300, 2.4e-303) - }; - cmplx w[NTST] = { // dawson(z[i]), evaluated with Maple - C(0.1635394094345355614904345232875688576839, - -0.1531245755371229803585918112683241066853), - C(-0.1635394094345355614904345232875688576839, - -0.1531245755371229803585918112683241066853), - C(0.1635394094345355614904345232875688576839, - 0.1531245755371229803585918112683241066853), - C(-0.1635394094345355614904345232875688576839, - 0.1531245755371229803585918112683241066853), - C(-0.01619082256681596362895875232699626384420, - -0.005210224203359059109181555401330902819419), - C(0.01078377080978103125464543240346760257008, - 0.006866888783433775382193630944275682670599), - C(-0.5808616819196736225612296471081337245459, - 0.6688593905505562263387760667171706325749), - C(Inf, - -Inf), - C(0.1000052020902036118082966385855563526705e-7, - 0.005100088434920073153418834680320146441685), - C(0.004950156837581592745389973960217444687524, - -0.004899838305155226382584756154100963570500), - C(0.005100176864319675957314822982399286703798, - 0.005099823128319785355949825238269336481254), - C(0.4244534840871830045021143490355372016428, - 0.002820278933186814021399602648373095266538), - C(-0.1021340733271046543881236523269967674156, - -0.00001045696456072005761498961861088944159916), - C(-0.01000200120119206748855061636187197886859, - 0.9805885888237419500266621041508714123763e-8), - C(0.001000002000012000023960527532953151819595, - -0.9800058800588007290937355024646722133204e-11), - C(0.4244549085628511778373438768121222815752, - 0.002935393851311701428647152230552122898291), - C(-0.1021340732357117208743299813648493928105, - -0.00001088377943049851799938998805451564893540), - C(-0.01000200120119126652710792390331206563616, - 0.1020612612857282306892368985525393707486e-7), - C(0.1000000000007333333333344266666666664457e-5, - 0.2000000000001333333333323199999999978819e-5), - C(0.1999999999994666666666675199999999990248e-5, - 0), - C(0.3013403889237919660346644392864226952119, - 0), - C(0.02503136792640367194699495234782353186858, - 0), - C(0.002500031251171948248596912483183760683918, - 0), - C(0,0.004900078433419939164774792850907128053308), - C(0,-0.005100088434920074173454208832365950009419), - C(0,0.2000000000005333333333341866666666676419e-5), - C(0,-48.16001211429122974789822893525016528191), - C(0,0.4627407029504443513654142715903005954668e174), - C(0,-Inf), - C(0,0), - C(-0,0), - C(0, Inf), - C(0, -Inf), - C(NaN, NaN), - C(NaN, NaN), - C(NaN, NaN), - C(NaN, 0), - C(0, NaN), - C(NaN, NaN), - C(NaN, NaN), - C(0.01282473148489433743567240624939698290584, - -0.2105957276516618621447832572909153498104e-7), - C(0.01219875253423634378984109995893708152885, - -0.1813040560401824664088425926165834355953e-7), - C(0.1020408163265306334945473399689037886997e-7, - -0.1041232819658476285651490827866174985330e-25), - C(0.9803921568627452865036825956835185367356e-8, - -0.9227220299884665067601095648451913375754e-26), - C(0.5000000000000000002500000000000000003750e-9, - -0.1200000000000000001800000188712838420241e-29), - C(5.00000000000000000000025000000000000000000003e-12, - -1.20000000000000000000018000000000000000000004e-36), - C(5.00000000000000000000000002500000000000000000e-14, - -1.20000000000000000000000001800000000000000000e-42), - C(5e-301, 0) - }; - TST(Dawson, 1e-20); - } - printf("#####################################\n"); - printf("SUCCESS (max relative error = %g)\n", errmax_all); -} - -#endif diff --git a/vendor/faddeeva/Faddeeva.hh b/vendor/faddeeva/Faddeeva.hh deleted file mode 100644 index c4a2e9717..000000000 --- a/vendor/faddeeva/Faddeeva.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2012 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 the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* Available at: http://ab-initio.mit.edu/Faddeeva - - Header file for Faddeeva.cc; see that file for more information. */ - -#ifndef FADDEEVA_HH -#define FADDEEVA_HH 1 - -#include - -namespace Faddeeva { - -// compute w(z) = exp(-z^2) erfc(-iz) [ Faddeeva / scaled complex error func ] -extern std::complex w(std::complex z,double relerr=0); -extern double w_im(double x); // special-case code for Im[w(x)] of real x - -// Various functions that we can compute with the help of w(z) - -// compute erfcx(z) = exp(z^2) erfc(z) -extern std::complex erfcx(std::complex z, double relerr=0); -extern double erfcx(double x); // special case for real x - -// compute erf(z), the error function of complex arguments -extern std::complex erf(std::complex z, double relerr=0); -extern double erf(double x); // special case for real x - -// compute erfi(z) = -i erf(iz), the imaginary error function -extern std::complex erfi(std::complex z, double relerr=0); -extern double erfi(double x); // special case for real x - -// compute erfc(z) = 1 - erf(z), the complementary error function -extern std::complex erfc(std::complex z, double relerr=0); -extern double erfc(double x); // special case for real x - -// compute Dawson(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z) -extern std::complex Dawson(std::complex z, double relerr=0); -extern double Dawson(double x); // special case for real x - -} // namespace Faddeeva - -#endif // FADDEEVA_HH diff --git a/vendor/gsl/include/gsl/gsl b/vendor/gsl/include/gsl/gsl deleted file mode 100644 index be3f2ccdb..000000000 --- a/vendor/gsl/include/gsl/gsl +++ /dev/null @@ -1,27 +0,0 @@ -// -// gsl-lite is based on GSL: Guidelines Support Library. -// For more information see https://github.com/martinmoene/gsl-lite -// -// Copyright (c) 2015 Martin Moene -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// mimic MS include hierarchy - -#pragma once - -#ifndef GSL_GSL_H_INCLUDED -#define GSL_GSL_H_INCLUDED - -#include "gsl-lite.hpp" - -#endif // GSL_GSL_H_INCLUDED diff --git a/vendor/gsl/include/gsl/gsl-lite.hpp b/vendor/gsl/include/gsl/gsl-lite.hpp deleted file mode 100644 index 825087cab..000000000 --- a/vendor/gsl/include/gsl/gsl-lite.hpp +++ /dev/null @@ -1,2857 +0,0 @@ -// -// gsl-lite is based on GSL: Guidelines Support Library. -// For more information see https://github.com/martinmoene/gsl-lite -// -// Copyright (c) 2015-2018 Martin Moene -// Copyright (c) 2015-2018 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#pragma once - -#ifndef GSL_GSL_LITE_HPP_INCLUDED -#define GSL_GSL_LITE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define gsl_lite_MAJOR 0 -#define gsl_lite_MINOR 34 -#define gsl_lite_PATCH 0 - -#define gsl_lite_VERSION gsl_STRINGIFY(gsl_lite_MAJOR) "." gsl_STRINGIFY(gsl_lite_MINOR) "." gsl_STRINGIFY(gsl_lite_PATCH) - -// gsl-lite backward compatibility: - -#ifdef gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR -# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR -# pragma message ("gsl_CONFIG_ALLOWS_SPAN_CONTAINER_CTOR is deprecated since gsl-lite 0.7.0; replace with gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR, or consider span(with_container, cont).") -#endif - -// M-GSL compatibility: - -#if defined( GSL_THROW_ON_CONTRACT_VIOLATION ) -# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS 1 -#endif - -#if defined( GSL_TERMINATE_ON_CONTRACT_VIOLATION ) -# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS 0 -#endif - -#if defined( GSL_UNENFORCED_ON_CONTRACT_VIOLATION ) -# define gsl_CONFIG_CONTRACT_LEVEL_OFF 1 -#endif - -// Configuration: Features - -#ifndef gsl_FEATURE_WITH_CONTAINER_TO_STD -# define gsl_FEATURE_WITH_CONTAINER_TO_STD 99 -#endif - -#ifndef gsl_FEATURE_MAKE_SPAN_TO_STD -# define gsl_FEATURE_MAKE_SPAN_TO_STD 99 -#endif - -#ifndef gsl_FEATURE_BYTE_SPAN_TO_STD -# define gsl_FEATURE_BYTE_SPAN_TO_STD 99 -#endif - -#ifndef gsl_FEATURE_IMPLICIT_MACRO -# define gsl_FEATURE_IMPLICIT_MACRO 1 -#endif - -#ifndef gsl_FEATURE_OWNER_MACRO -# define gsl_FEATURE_OWNER_MACRO 1 -#endif - -#ifndef gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD -# define gsl_FEATURE_EXPERIMENTAL_RETURN_GUARD 0 -#endif - -// Configuration: Other - -#ifndef gsl_CONFIG_DEPRECATE_TO_LEVEL -# define gsl_CONFIG_DEPRECATE_TO_LEVEL 0 -#endif - -#ifndef gsl_CONFIG_SPAN_INDEX_TYPE -# define gsl_CONFIG_SPAN_INDEX_TYPE size_t -#endif - -#ifndef gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR -# define gsl_CONFIG_NOT_NULL_EXPLICIT_CTOR 0 -#endif - -#ifndef gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF -# define gsl_CONFIG_NOT_NULL_GET_BY_CONST_REF 0 -#endif - -#ifndef gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS -# define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS 0 -#endif - -#ifndef gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON -# define gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON 1 -#endif - -#ifndef gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR -# define gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR 0 -#endif - -#if defined( gsl_CONFIG_CONTRACT_LEVEL_ON ) -# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x11 -#elif defined( gsl_CONFIG_CONTRACT_LEVEL_OFF ) -# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x00 -#elif defined( gsl_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY ) -# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x01 -#elif defined( gsl_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY ) -# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x10 -#else -# define gsl_CONFIG_CONTRACT_LEVEL_MASK 0x11 -#endif - -#if !defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \ - !defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) -# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 -#elif defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \ - !defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) -# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 1 -#elif !defined( gsl_CONFIG_CONTRACT_VIOLATION_THROWS ) && \ - defined( gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES ) -# define gsl_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 -#else -# error only one of gsl_CONFIG_CONTRACT_VIOLATION_THROWS and gsl_CONFIG_CONTRACT_VIOLATION_TERMINATES may be defined. -#endif - -// C++ language version detection (C++20 is speculative): -// Note: VC14.0/1900 (VS2015) lacks too much from C++14. - -#ifndef gsl_CPLUSPLUS -# if defined(_MSVC_LANG ) && !defined(__clang__) -# define gsl_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) -# else -# define gsl_CPLUSPLUS __cplusplus -# endif -#endif - -#define gsl_CPP98_OR_GREATER ( gsl_CPLUSPLUS >= 199711L ) -#define gsl_CPP11_OR_GREATER ( gsl_CPLUSPLUS >= 201103L ) -#define gsl_CPP14_OR_GREATER ( gsl_CPLUSPLUS >= 201402L ) -#define gsl_CPP17_OR_GREATER ( gsl_CPLUSPLUS >= 201703L ) -#define gsl_CPP20_OR_GREATER ( gsl_CPLUSPLUS >= 202000L ) - -// C++ language version (represent 98 as 3): - -#define gsl_CPLUSPLUS_V ( gsl_CPLUSPLUS / 100 - (gsl_CPLUSPLUS > 200000 ? 2000 : 1994) ) - -// half-open range [lo..hi): -#define gsl_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) - -// Compiler versions: -// -// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0) -// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002) -// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003) -// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) -// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) -// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) -// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) -// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) -// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) -// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017) - -#if defined(_MSC_VER ) && !defined(__clang__) -# define gsl_COMPILER_MSVC_VER (_MSC_VER ) -# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) -#else -# define gsl_COMPILER_MSVC_VER 0 -# define gsl_COMPILER_MSVC_VERSION 0 -#endif - -#define gsl_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) - -#if defined(__clang__) -# define gsl_COMPILER_CLANG_VERSION gsl_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ ) -#else -# define gsl_COMPILER_CLANG_VERSION 0 -#endif - -#if defined(__GNUC__) && !defined(__clang__) -# define gsl_COMPILER_GNUC_VERSION gsl_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ ) -#else -# define gsl_COMPILER_GNUC_VERSION 0 -#endif - -// Method enabling (C++98, VC120 (VS2013) cannot use __VA_ARGS__) - -#define gsl_REQUIRES_0(VA) \ - template< bool B = (VA), typename std::enable_if::type = 0 > - -#define gsl_REQUIRES_T(VA) \ - , typename = typename std::enable_if< (VA), gsl::detail::enabler >::type - -#define gsl_REQUIRES_R(R, VA) \ - typename std::enable_if::type - -#define gsl_REQUIRES_A(VA) \ - , typename std::enable_if::type = nullptr - -// Compiler non-strict aliasing: - -#if defined(__clang__) || defined(__GNUC__) -# define gsl_may_alias __attribute__((__may_alias__)) -#else -# define gsl_may_alias -#endif - -// Presence of gsl, language and library features: - -#define gsl_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= gsl_CPLUSPLUS_V ) - -#define gsl_DEPRECATE_TO_LEVEL( level ) ( level <= gsl_CONFIG_DEPRECATE_TO_LEVEL ) -#define gsl_FEATURE_TO_STD( feature ) ( gsl_IN_STD( gsl_FEATURE( feature##_TO_STD ) ) ) -#define gsl_FEATURE( feature ) ( gsl_FEATURE_##feature ) -#define gsl_CONFIG( feature ) ( gsl_CONFIG_##feature ) -#define gsl_HAVE( feature ) ( gsl_HAVE_##feature ) - -// Presence of wide character support: - -#ifdef __DJGPP__ -# define gsl_HAVE_WCHAR 0 -#else -# define gsl_HAVE_WCHAR 1 -#endif - -// Presence of language & library features: - -#ifdef _HAS_CPP0X -# define gsl_HAS_CPP0X _HAS_CPP0X -#else -# define gsl_HAS_CPP0X 0 -#endif - -#define gsl_CPP11_100 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1600) -#define gsl_CPP11_110 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1700) -#define gsl_CPP11_120 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800) -#define gsl_CPP11_140 (gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900) - -#define gsl_CPP14_000 (gsl_CPP14_OR_GREATER) -#define gsl_CPP14_120 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1800) -#define gsl_CPP14_140 (gsl_CPP14_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900) - -#define gsl_CPP17_000 (gsl_CPP17_OR_GREATER) -#define gsl_CPP17_140 (gsl_CPP17_OR_GREATER || gsl_COMPILER_MSVC_VER >= 1900) - -#define gsl_CPP11_140_CPP0X_90 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1500 && gsl_HAS_CPP0X)) -#define gsl_CPP11_140_CPP0X_100 (gsl_CPP11_140 || (gsl_COMPILER_MSVC_VER >= 1600 && gsl_HAS_CPP0X)) - -// Presence of C++11 language features: - -#define gsl_HAVE_AUTO gsl_CPP11_100 -#define gsl_HAVE_NULLPTR gsl_CPP11_100 -#define gsl_HAVE_RVALUE_REFERENCE gsl_CPP11_100 - -#define gsl_HAVE_ENUM_CLASS gsl_CPP11_110 - -#define gsl_HAVE_ALIAS_TEMPLATE gsl_CPP11_120 -#define gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG gsl_CPP11_120 -#define gsl_HAVE_EXPLICIT gsl_CPP11_120 -#define gsl_HAVE_INITIALIZER_LIST gsl_CPP11_120 - -#define gsl_HAVE_CONSTEXPR_11 gsl_CPP11_140 -#define gsl_HAVE_IS_DEFAULT gsl_CPP11_140 -#define gsl_HAVE_IS_DELETE gsl_CPP11_140 -#define gsl_HAVE_NOEXCEPT gsl_CPP11_140 - -#if gsl_CPP11_OR_GREATER -// see above -#endif - -// Presence of C++14 language features: - -#define gsl_HAVE_CONSTEXPR_14 gsl_CPP14_000 -#define gsl_HAVE_DECLTYPE_AUTO gsl_CPP14_140 - -// Presence of C++17 language features: -// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7 - -#define gsl_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE gsl_CPP17_000 -#define gsl_HAVE_DEDUCTION_GUIDES (gsl_CPP17_000 && ! gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 1, 999 ) ) - -// Presence of C++ library features: - -#define gsl_HAVE_ADDRESSOF gsl_CPP17_000 -#define gsl_HAVE_ARRAY gsl_CPP11_110 -#define gsl_HAVE_TYPE_TRAITS gsl_CPP11_110 -#define gsl_HAVE_TR1_TYPE_TRAITS gsl_CPP11_110 - -#define gsl_HAVE_CONTAINER_DATA_METHOD gsl_CPP11_140_CPP0X_90 -#define gsl_HAVE_STD_DATA gsl_CPP17_000 - -#define gsl_HAVE_SIZED_TYPES gsl_CPP11_140 - -#define gsl_HAVE_MAKE_SHARED gsl_CPP11_140_CPP0X_100 -#define gsl_HAVE_SHARED_PTR gsl_CPP11_140_CPP0X_100 -#define gsl_HAVE_UNIQUE_PTR gsl_CPP11_140_CPP0X_100 - -#define gsl_HAVE_MAKE_UNIQUE gsl_CPP14_120 - -#define gsl_HAVE_UNCAUGHT_EXCEPTIONS gsl_CPP17_140 - -#define gsl_HAVE_ADD_CONST gsl_HAVE_TYPE_TRAITS -#define gsl_HAVE_INTEGRAL_CONSTANT gsl_HAVE_TYPE_TRAITS -#define gsl_HAVE_REMOVE_CONST gsl_HAVE_TYPE_TRAITS -#define gsl_HAVE_REMOVE_REFERENCE gsl_HAVE_TYPE_TRAITS - -#define gsl_HAVE_TR1_ADD_CONST gsl_HAVE_TR1_TYPE_TRAITS -#define gsl_HAVE_TR1_INTEGRAL_CONSTANT gsl_HAVE_TR1_TYPE_TRAITS -#define gsl_HAVE_TR1_REMOVE_CONST gsl_HAVE_TR1_TYPE_TRAITS -#define gsl_HAVE_TR1_REMOVE_REFERENCE gsl_HAVE_TR1_TYPE_TRAITS - -// C++ feature usage: - -#if gsl_HAVE( ADDRESSOF ) -# define gsl_ADDRESSOF(x) std::addressof(x) -#else -# define gsl_ADDRESSOF(x) (&x) -#endif - -#if gsl_HAVE( CONSTEXPR_11 ) -# define gsl_constexpr constexpr -#else -# define gsl_constexpr /*constexpr*/ -#endif - -#if gsl_HAVE( CONSTEXPR_14 ) -# define gsl_constexpr14 constexpr -#else -# define gsl_constexpr14 /*constexpr*/ -#endif - -#if gsl_HAVE( EXPLICIT ) -# define gsl_explicit explicit -#else -# define gsl_explicit /*explicit*/ -#endif - -#if gsl_FEATURE( IMPLICIT_MACRO ) -# define implicit /*implicit*/ -#endif - -#if gsl_HAVE( IS_DELETE ) -# define gsl_is_delete = delete -#else -# define gsl_is_delete -#endif - -#if gsl_HAVE( IS_DELETE ) -# define gsl_is_delete_access public -#else -# define gsl_is_delete_access private -#endif - -#if !gsl_HAVE( NOEXCEPT ) || gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) -# define gsl_noexcept /*noexcept*/ -#else -# define gsl_noexcept noexcept -#endif - -#if gsl_HAVE( NULLPTR ) -# define gsl_nullptr nullptr -#else -# define gsl_nullptr NULL -#endif - -#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) ) - -// Other features: - -#define gsl_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR \ - ( gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG && gsl_HAVE_CONTAINER_DATA_METHOD ) - -// Note: !defined(__NVCC__) doesn't work with nvcc here: -#define gsl_HAVE_UNCONSTRAINED_SPAN_CONTAINER_CTOR \ - ( gsl_CONFIG_ALLOWS_UNCONSTRAINED_SPAN_CONTAINER_CTOR && (__NVCC__== 0) ) - -// GSL API (e.g. for CUDA platform): - -#ifndef gsl_api -# ifdef __CUDACC__ -# define gsl_api __host__ __device__ -# else -# define gsl_api /*gsl_api*/ -# endif -#endif - -// Additional includes: - -#if gsl_HAVE( ARRAY ) -# include -#endif - -#if gsl_HAVE( TYPE_TRAITS ) -# include -#elif gsl_HAVE( TR1_TYPE_TRAITS ) -# include -#endif - -#if gsl_HAVE( SIZED_TYPES ) -# include -#endif - -// MSVC warning suppression macros: - -#if gsl_COMPILER_MSVC_VERSION >= 140 -# define gsl_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] -# define gsl_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) ) -# define gsl_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) -# define gsl_RESTORE_MSVC_WARNINGS() __pragma(warning(pop )) -#else -# define gsl_SUPPRESS_MSGSL_WARNING(expr) -# define gsl_SUPPRESS_MSVC_WARNING(code, descr) -# define gsl_DISABLE_MSVC_WARNINGS(codes) -# define gsl_RESTORE_MSVC_WARNINGS() -#endif - -// Suppress the following MSVC GSL warnings: -// - C26410: gsl::r.32: the parameter 'ptr' is a reference to const unique pointer, use const T* or const T& instead -// - C26415: gsl::r.30: smart pointer parameter 'ptr' is used only to access contained pointer. Use T* or T& instead -// - C26418: gsl::r.36: shared pointer parameter 'ptr' is not copied or moved. Use T* or T& instead -// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; -// use brace initialization, gsl::narrow_cast or gsl::narow -// - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept' -// - C26440, gsl::f.6 : function 'function' can be declared 'noexcept' -// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same -// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead -// - C26482, gsl::b.2 : only index into arrays using constant expressions -// - C26490: gsl::t.1 : don't use reinterpret_cast - -gsl_DISABLE_MSVC_WARNINGS( 26410 26415 26418 26472 26439 26440 26473 26481 26482 26490 ) - -namespace gsl { - -// forward declare span<>: - -template< class T > -class span; - -// C++11 emulation: - -namespace std11 { - -#if gsl_HAVE( ADD_CONST ) - -using std::add_const; - -#elif gsl_HAVE( TR1_ADD_CONST ) - -using std::tr1::add_const; - -#else - -template< class T > struct add_const { typedef const T type; }; - -#endif // gsl_HAVE( ADD_CONST ) - -#if gsl_HAVE( REMOVE_CONST ) - -using std::remove_cv; -using std::remove_const; -using std::remove_volatile; - -#elif gsl_HAVE( TR1_REMOVE_CONST ) - -using std::tr1::remove_cv; -using std::tr1::remove_const; -using std::tr1::remove_volatile; - -#else - -template< class T > struct remove_const { typedef T type; }; -template< class T > struct remove_const { typedef T type; }; - -template< class T > struct remove_volatile { typedef T type; }; -template< class T > struct remove_volatile { typedef T type; }; - -template< class T > -struct remove_cv -{ - typedef typename remove_volatile::type>::type type; -}; - -#endif // gsl_HAVE( REMOVE_CONST ) - -#if gsl_HAVE( INTEGRAL_CONSTANT ) - -using std::integral_constant; -using std::true_type; -using std::false_type; - -#elif gsl_HAVE( TR1_INTEGRAL_CONSTANT ) - -using std::tr1::integral_constant; -using std::tr1::true_type; -using std::tr1::false_type; - -#else - -template< int v > struct integral_constant { enum { value = v }; }; -typedef integral_constant< true > true_type; -typedef integral_constant< false > false_type; - -#endif - -} // namespace std11 - -namespace detail { - -/// for nsel_REQUIRES_T - -/*enum*/ class enabler{}; - -#if gsl_HAVE( TYPE_TRAITS ) - -template< class Q > -struct is_span_oracle : std11::false_type{}; - -template< class T> -struct is_span_oracle< span > : std11::true_type{}; - -template< class Q > -struct is_span : is_span_oracle< typename std11::remove_cv::type >{}; - -template< class Q > -struct is_std_array_oracle : std11::false_type{}; - -#if gsl_HAVE( ARRAY ) - -template< class T, std::size_t Extent > -struct is_std_array_oracle< std::array > : std11::true_type{}; - -#endif - -template< class Q > -struct is_std_array : is_std_array_oracle< typename std11::remove_cv::type >{}; - -template< class Q > -struct is_array : std11::false_type {}; - -template< class T > -struct is_array : std11::true_type {}; - -template< class T, std::size_t N > -struct is_array : std11::true_type {}; - -#endif // gsl_HAVE( TYPE_TRAITS ) - -} // namespace detail - -// -// GSL.util: utilities -// - -// index type for all container indexes/subscripts/sizes -typedef gsl_CONFIG_SPAN_INDEX_TYPE index; // p0122r3 uses std::ptrdiff_t - -// -// GSL.owner: ownership pointers -// -#if gsl_HAVE( SHARED_PTR ) - using std::unique_ptr; - using std::shared_ptr; - using std::make_shared; -# if gsl_HAVE( MAKE_UNIQUE ) - using std::make_unique; -# endif -#endif - -#if gsl_HAVE( ALIAS_TEMPLATE ) -# if gsl_HAVE( TYPE_TRAITS ) - template< class T - gsl_REQUIRES_T( std::is_pointer::value ) - > - using owner = T; -# else - template< class T > using owner = T; -# endif -#else - template< class T > struct owner { typedef T type; }; -#endif - -#define gsl_HAVE_OWNER_TEMPLATE gsl_HAVE_ALIAS_TEMPLATE - -#if gsl_FEATURE( OWNER_MACRO ) -# if gsl_HAVE( OWNER_TEMPLATE ) -# define Owner(t) ::gsl::owner -# else -# define Owner(t) ::gsl::owner::type -# endif -#endif - -// -// GSL.assert: assertions -// - -#define gsl_ELIDE_CONTRACT_EXPECTS ( 0 == ( gsl_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) ) -#define gsl_ELIDE_CONTRACT_ENSURES ( 0 == ( gsl_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) ) - -#if gsl_ELIDE_CONTRACT_EXPECTS -# define Expects( x ) /* Expects elided */ -#elif gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) -# define Expects( x ) ::gsl::fail_fast_assert( (x), "GSL: Precondition failure at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ); -#else -# define Expects( x ) ::gsl::fail_fast_assert( (x) ) -#endif - -#if gsl_ELIDE_CONTRACT_EXPECTS -# define gsl_EXPECTS_UNUSED_PARAM( x ) /* Make param unnamed if Expects elided */ -#else -# define gsl_EXPECTS_UNUSED_PARAM( x ) x -#endif - -#if gsl_ELIDE_CONTRACT_ENSURES -# define Ensures( x ) /* Ensures elided */ -#elif gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) -# define Ensures( x ) ::gsl::fail_fast_assert( (x), "GSL: Postcondition failure at " __FILE__ ":" gsl_STRINGIFY(__LINE__) ); -#else -# define Ensures( x ) ::gsl::fail_fast_assert( (x) ) -#endif - -#define gsl_STRINGIFY( x ) gsl_STRINGIFY_( x ) -#define gsl_STRINGIFY_( x ) #x - -struct fail_fast : public std::logic_error -{ - gsl_api explicit fail_fast( char const * const message ) - : std::logic_error( message ) {} -}; - -// workaround for gcc 5 throw/terminate constexpr bug: - -#if gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 430, 600 ) && gsl_HAVE( CONSTEXPR_14 ) - -# if gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - -gsl_api inline gsl_constexpr14 auto fail_fast_assert( bool cond, char const * const message ) -> void -{ - !cond ? throw fail_fast( message ) : 0; -} - -# else - -gsl_api inline gsl_constexpr14 auto fail_fast_assert( bool cond ) -> void -{ - struct F { static gsl_constexpr14 void f(){}; }; - - !cond ? std::terminate() : F::f(); -} - -# endif - -#else // workaround - -# if gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - -gsl_api inline gsl_constexpr14 void fail_fast_assert( bool cond, char const * const message ) -{ - if ( !cond ) - throw fail_fast( message ); -} - -# else - -gsl_api inline gsl_constexpr14 void fail_fast_assert( bool cond ) gsl_noexcept -{ - if ( !cond ) - std::terminate(); -} - -# endif -#endif // workaround - -// -// GSL.util: utilities -// - -#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) - -// Add uncaught_exceptions for pre-2017 MSVC, GCC and Clang -// Return unsigned char to save stack space, uncaught_exceptions can only increase by 1 in a scope - -namespace detail { - -inline unsigned char to_uchar( unsigned x ) gsl_noexcept -{ - return static_cast( x ); -} - -} // namespace detail - -namespace std11 { - -#if gsl_HAVE( UNCAUGHT_EXCEPTIONS ) - -inline unsigned char uncaught_exceptions() gsl_noexcept -{ - return detail::to_uchar( std::uncaught_exceptions() ); -} - -#elif gsl_COMPILER_MSVC_VERSION - -extern "C" char * __cdecl _getptd(); -inline unsigned char uncaught_exceptions() gsl_noexcept -{ - return detail::to_uchar( *reinterpret_cast(_getptd() + (sizeof(void*) == 8 ? 0x100 : 0x90) ) ); -} - -#elif gsl_COMPILER_CLANG_VERSION || gsl_COMPILER_GNUC_VERSION - -extern "C" char * __cxa_get_globals(); -inline unsigned char uncaught_exceptions() gsl_noexcept -{ - return detail::to_uchar( *reinterpret_cast(__cxa_get_globals() + sizeof(void*) ) ); -} -#endif -} // namespace std11 -#endif - -#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 110 - -template< class F > -class final_action -{ -public: - gsl_api explicit final_action( F action ) gsl_noexcept - : action_( std::move( action ) ) - , invoke_( true ) - {} - - gsl_api final_action( final_action && other ) gsl_noexcept - : action_( std::move( other.action_ ) ) - , invoke_( other.invoke_ ) - { - other.invoke_ = false; - } - - gsl_api virtual ~final_action() gsl_noexcept - { - if ( invoke_ ) - action_(); - } - -gsl_is_delete_access: - gsl_api final_action( final_action const & ) gsl_is_delete; - gsl_api final_action & operator=( final_action const & ) gsl_is_delete; - gsl_api final_action & operator=( final_action && ) gsl_is_delete; - -protected: - gsl_api void dismiss() gsl_noexcept - { - invoke_ = false; - } - -private: - F action_; - bool invoke_; -}; - -template< class F > -gsl_api inline final_action finally( F const & action ) gsl_noexcept -{ - return final_action( action ); -} - -template< class F > -gsl_api inline final_action finally( F && action ) gsl_noexcept -{ - return final_action( std::forward( action ) ); -} - -#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) - -template< class F > -class final_action_return : public final_action -{ -public: - gsl_api explicit final_action_return( F && action ) gsl_noexcept - : final_action( std::move( action ) ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api final_action_return( final_action_return && other ) gsl_noexcept - : final_action( std::move( other ) ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api ~final_action_return() override - { - if ( std11::uncaught_exceptions() != exception_count ) - this->dismiss(); - } - -gsl_is_delete_access: - gsl_api final_action_return( final_action_return const & ) gsl_is_delete; - gsl_api final_action_return & operator=( final_action_return const & ) gsl_is_delete; - -private: - unsigned char exception_count; -}; - -template< class F > -gsl_api inline final_action_return on_return( F const & action ) gsl_noexcept -{ - return final_action_return( action ); -} - -template< class F > -gsl_api inline final_action_return on_return( F && action ) gsl_noexcept -{ - return final_action_return( std::forward( action ) ); -} - -template< class F > -class final_action_error : public final_action -{ -public: - gsl_api explicit final_action_error( F && action ) gsl_noexcept - : final_action( std::move( action ) ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api final_action_error( final_action_error && other ) gsl_noexcept - : final_action( std::move( other ) ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api ~final_action_error() override - { - if ( std11::uncaught_exceptions() == exception_count ) - this->dismiss(); - } - -gsl_is_delete_access: - gsl_api final_action_error( final_action_error const & ) gsl_is_delete; - gsl_api final_action_error & operator=( final_action_error const & ) gsl_is_delete; - -private: - unsigned char exception_count; -}; - -template< class F > -gsl_api inline final_action_error on_error( F const & action ) gsl_noexcept -{ - return final_action_error( action ); -} - -template< class F > -gsl_api inline final_action_error on_error( F && action ) gsl_noexcept -{ - return final_action_error( std::forward( action ) ); -} - -#endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) - -#else // gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 110 - -class final_action -{ -public: - typedef void (*Action)(); - - gsl_api final_action( Action action ) - : action_( action ) - , invoke_( true ) - {} - - gsl_api final_action( final_action const & other ) - : action_( other.action_ ) - , invoke_( other.invoke_ ) - { - other.invoke_ = false; - } - - gsl_api virtual ~final_action() - { - if ( invoke_ ) - action_(); - } - -protected: - gsl_api void dismiss() - { - invoke_ = false; - } - -private: - gsl_api final_action & operator=( final_action const & ); - -private: - Action action_; - mutable bool invoke_; -}; - -template< class F > -gsl_api inline final_action finally( F const & f ) -{ - return final_action(( f )); -} - -#if gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) - -class final_action_return : public final_action -{ -public: - gsl_api explicit final_action_return( Action action ) - : final_action( action ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api ~final_action_return() - { - if ( std11::uncaught_exceptions() != exception_count ) - this->dismiss(); - } - -private: - gsl_api final_action_return & operator=( final_action_return const & ); - -private: - unsigned char exception_count; -}; - -template< class F > -gsl_api inline final_action_return on_return( F const & action ) -{ - return final_action_return( action ); -} - -class final_action_error : public final_action -{ -public: - gsl_api explicit final_action_error( Action action ) - : final_action( action ) - , exception_count( std11::uncaught_exceptions() ) - {} - - gsl_api ~final_action_error() - { - if ( std11::uncaught_exceptions() == exception_count ) - this->dismiss(); - } - -private: - gsl_api final_action_error & operator=( final_action_error const & ); - -private: - unsigned char exception_count; -}; - -template< class F > -gsl_api inline final_action_error on_error( F const & action ) -{ - return final_action_error( action ); -} - -#endif // gsl_FEATURE( EXPERIMENTAL_RETURN_GUARD ) - -#endif // gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION == 110 - -#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 120 - -template< class T, class U > -gsl_api inline gsl_constexpr T narrow_cast( U && u ) gsl_noexcept -{ - return static_cast( std::forward( u ) ); -} - -#else - -template< class T, class U > -gsl_api inline T narrow_cast( U u ) gsl_noexcept -{ - return static_cast( u ); -} - -#endif // gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 120 - -struct narrowing_error : public std::exception {}; - -#if gsl_HAVE( TYPE_TRAITS ) - -namespace detail -{ - template< class T, class U > - struct is_same_signedness : public std::integral_constant::value == std::is_signed::value> - {}; -} -#endif - -template< class T, class U > -gsl_api inline T narrow( U u ) -{ - T t = narrow_cast( u ); - - if ( static_cast( t ) != u ) - { -#if gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - throw narrowing_error(); -#else - std::terminate(); -#endif - } - -#if gsl_HAVE( TYPE_TRAITS ) -# if gsl_COMPILER_MSVC_VERSION - // Suppress MSVC level 4 warning C4127 (conditional expression is constant) - if ( 0, ! detail::is_same_signedness::value && ( ( t < T() ) != ( u < U() ) ) ) -# else - if ( ! detail::is_same_signedness::value && ( ( t < T() ) != ( u < U() ) ) ) -# endif -#else - // Don't assume T() works: - if ( ( t < 0 ) != ( u < 0 ) ) -#endif - { -#if gsl_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - throw narrowing_error(); -#else - std::terminate(); -#endif - } - return t; -} - -// -// at() - Bounds-checked way of accessing static arrays, std::array, std::vector. -// - -template< class T, size_t N > -gsl_api inline gsl_constexpr14 T & at( T(&arr)[N], size_t index ) -{ - Expects( index < N ); - return arr[index]; -} - -#if gsl_HAVE( ARRAY ) - -template< class T, size_t N > -gsl_api inline gsl_constexpr14 T & at( std::array & arr, size_t index ) -{ - Expects( index < N ); - return arr[index]; -} -#endif - -template< class Container > -gsl_api inline gsl_constexpr14 typename Container::value_type & at( Container & cont, size_t index ) -{ - Expects( index < cont.size() ); - return cont[index]; -} - -#if gsl_HAVE( INITIALIZER_LIST ) - -template< class T > -gsl_api inline const gsl_constexpr14 T & at( std::initializer_list cont, size_t index ) -{ - Expects( index < cont.size() ); - return *( cont.begin() + index ); -} -#endif - -template< class T > -gsl_api inline gsl_constexpr T & at( span s, size_t index ) -{ - return s.at( index ); -} - -// -// GSL.views: views -// - -// -// not_null<> - Wrap any indirection and enforce non-null. -// -template< class T > -class not_null -{ -#if gsl_CONFIG( NOT_NULL_EXPLICIT_CTOR ) -# define gsl_not_null_explicit explicit -#else -# define gsl_not_null_explicit /*explicit*/ -#endif - -#if gsl_CONFIG( NOT_NULL_GET_BY_CONST_REF ) - typedef T const & get_result_t; -#else - typedef T get_result_t; -#endif - -public: -#if gsl_HAVE( TYPE_TRAITS ) - static_assert( std::is_assignable::value, "T cannot be assigned nullptr." ); -#endif - - template< class U -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_constructible::value )) -#endif - > - gsl_api gsl_constexpr14 gsl_not_null_explicit -#if gsl_HAVE( RVALUE_REFERENCE ) - not_null( U && u ) - : ptr_( std::forward( u ) ) -#else - not_null( U const & u ) - : ptr_( u ) -#endif - { - Expects( ptr_ != gsl_nullptr ); - } -#undef gsl_not_null_explicit - -#if gsl_HAVE( IS_DEFAULT ) - gsl_api ~not_null() = default; - gsl_api gsl_constexpr not_null( not_null && other ) = default; - gsl_api gsl_constexpr not_null( not_null const & other ) = default; - gsl_api not_null & operator=( not_null && other ) = default; - gsl_api not_null & operator=( not_null const & other ) = default; -#else - gsl_api ~not_null() {}; - gsl_api gsl_constexpr not_null( not_null const & other ) : ptr_ ( other.ptr_ ) {} - gsl_api not_null & operator=( not_null const & other ) { ptr_ = other.ptr_; return *this; } -# if gsl_HAVE( RVALUE_REFERENCE ) - gsl_api gsl_constexpr not_null( not_null && other ) : ptr_( std::move( other.get() ) ) {} - gsl_api not_null & operator=( not_null && other ) { ptr_ = std::move( other.get() ); return *this; } -# endif -#endif - - template< class U -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::value )) -#endif - > - gsl_api gsl_constexpr not_null( not_null const & other ) - : ptr_( other.get() ) - {} - - gsl_api gsl_constexpr14 get_result_t get() const - { - // Without cheating and changing ptr_ from the outside, this check is superfluous: - Ensures( ptr_ != gsl_nullptr ); - return ptr_; - } - - gsl_api gsl_constexpr operator get_result_t () const { return get(); } - gsl_api gsl_constexpr get_result_t operator->() const { return get(); } - -#if gsl_HAVE( DECLTYPE_AUTO ) - gsl_api gsl_constexpr decltype(auto) operator*() const { return *get(); } -#endif - -gsl_is_delete_access: - // prevent compilation when initialized with a nullptr or literal 0: -#if gsl_HAVE( NULLPTR ) - gsl_api not_null( std::nullptr_t ) gsl_is_delete; - gsl_api not_null & operator=( std::nullptr_t ) gsl_is_delete; -#else - gsl_api not_null( int ) gsl_is_delete; - gsl_api not_null & operator=( int ) gsl_is_delete; -#endif - - // unwanted operators...pointers only point to single objects! - gsl_api not_null & operator++() gsl_is_delete; - gsl_api not_null & operator--() gsl_is_delete; - gsl_api not_null operator++( int ) gsl_is_delete; - gsl_api not_null operator--( int ) gsl_is_delete; - gsl_api not_null & operator+ ( size_t ) gsl_is_delete; - gsl_api not_null & operator+=( size_t ) gsl_is_delete; - gsl_api not_null & operator- ( size_t ) gsl_is_delete; - gsl_api not_null & operator-=( size_t ) gsl_is_delete; - gsl_api not_null & operator+=( std::ptrdiff_t ) gsl_is_delete; - gsl_api not_null & operator-=( std::ptrdiff_t ) gsl_is_delete; - gsl_api void operator[]( std::ptrdiff_t ) const gsl_is_delete; - -private: - T ptr_; -}; - -// not_null with implicit constructor, allowing copy-initialization: - -template< class T > -class not_null_ic : public not_null -{ -public: - template< class U -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_constructible::value )) -#endif - > - gsl_api gsl_constexpr14 -#if gsl_HAVE( RVALUE_REFERENCE ) - not_null_ic( U && u ) - : not_null( std::forward( u ) ) -#else - not_null_ic( U const & u ) - : not_null( u ) -#endif - {} -}; - -// more not_null unwanted operators - -template< class T, class U > -std::ptrdiff_t operator-( not_null const &, not_null const & ) gsl_is_delete; - -template< class T > -not_null operator-( not_null const &, std::ptrdiff_t ) gsl_is_delete; - -template< class T > -not_null operator+( not_null const &, std::ptrdiff_t ) gsl_is_delete; - -template< class T > -not_null operator+( std::ptrdiff_t, not_null const & ) gsl_is_delete; - -// not_null comparisons - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator==( not_null const & l, not_null const & r ) -{ - return l.get() == r.get(); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator< ( not_null const & l, not_null const & r ) -{ - return l.get() < r.get(); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator!=( not_null const & l, not_null const & r ) -{ - return !( l == r ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator<=( not_null const & l, not_null const & r ) -{ - return !( r < l ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator> ( not_null const & l, not_null const & r ) -{ - return ( r < l ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator>=( not_null const & l, not_null const & r ) -{ - return !( l < r ); -} - -// -// Byte-specific type. -// -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - enum class gsl_may_alias byte : unsigned char {}; -#else - struct gsl_may_alias byte { typedef unsigned char type; type v; }; -#endif - -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) -# define gsl_ENABLE_IF_INTEGRAL_T(T) \ - gsl_REQUIRES_T(( std::is_integral::value )) -#else -# define gsl_ENABLE_IF_INTEGRAL_T(T) -#endif - -template< class T > -gsl_api inline gsl_constexpr byte to_byte( T v ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return static_cast( v ); -#elif gsl_HAVE( CONSTEXPR_11 ) - return { static_cast( v ) }; -#else - byte b = { static_cast( v ) }; return b; -#endif -} - -template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) > -gsl_api inline gsl_constexpr IntegerType to_integer( byte b ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return static_cast::type>( b ); -#else - return b.v; -#endif -} - -gsl_api inline gsl_constexpr unsigned char to_uchar( byte b ) gsl_noexcept -{ - return to_integer( b ); -} - -gsl_api inline gsl_constexpr unsigned char to_uchar( int i ) gsl_noexcept -{ - return static_cast( i ); -} - -#if ! gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - -gsl_api inline gsl_constexpr bool operator==( byte l, byte r ) gsl_noexcept -{ - return l.v == r.v; -} - -gsl_api inline gsl_constexpr bool operator!=( byte l, byte r ) gsl_noexcept -{ - return !( l == r ); -} - -gsl_api inline gsl_constexpr bool operator< ( byte l, byte r ) gsl_noexcept -{ - return l.v < r.v; -} - -gsl_api inline gsl_constexpr bool operator<=( byte l, byte r ) gsl_noexcept -{ - return !( r < l ); -} - -gsl_api inline gsl_constexpr bool operator> ( byte l, byte r ) gsl_noexcept -{ - return ( r < l ); -} - -gsl_api inline gsl_constexpr bool operator>=( byte l, byte r ) gsl_noexcept -{ - return !( l < r ); -} -#endif - -template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) > -gsl_api inline gsl_constexpr14 byte & operator<<=( byte & b, IntegerType shift ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return b = to_byte( to_uchar( b ) << shift ); -#else - b.v = to_uchar( b.v << shift ); return b; -#endif -} - -template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) > -gsl_api inline gsl_constexpr byte operator<<( byte b, IntegerType shift ) gsl_noexcept -{ - return to_byte( to_uchar( b ) << shift ); -} - -template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) > -gsl_api inline gsl_constexpr14 byte & operator>>=( byte & b, IntegerType shift ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return b = to_byte( to_uchar( b ) >> shift ); -#else - b.v = to_uchar( b.v >> shift ); return b; -#endif -} - -template< class IntegerType gsl_ENABLE_IF_INTEGRAL_T( IntegerType ) > -gsl_api inline gsl_constexpr byte operator>>( byte b, IntegerType shift ) gsl_noexcept -{ - return to_byte( to_uchar( b ) >> shift ); -} - -gsl_api inline gsl_constexpr14 byte & operator|=( byte & l, byte r ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return l = to_byte( to_uchar( l ) | to_uchar( r ) ); -#else - l.v = to_uchar( l ) | to_uchar( r ); return l; -#endif -} - -gsl_api inline gsl_constexpr byte operator|( byte l, byte r ) gsl_noexcept -{ - return to_byte( to_uchar( l ) | to_uchar( r ) ); -} - -gsl_api inline gsl_constexpr14 byte & operator&=( byte & l, byte r ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return l = to_byte( to_uchar( l ) & to_uchar( r ) ); -#else - l.v = to_uchar( l ) & to_uchar( r ); return l; -#endif -} - -gsl_api inline gsl_constexpr byte operator&( byte l, byte r ) gsl_noexcept -{ - return to_byte( to_uchar( l ) & to_uchar( r ) ); -} - -gsl_api inline gsl_constexpr14 byte & operator^=( byte & l, byte r ) gsl_noexcept -{ -#if gsl_HAVE( ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE ) - return l = to_byte( to_uchar( l ) ^ to_uchar (r ) ); -#else - l.v = to_uchar( l ) ^ to_uchar (r ); return l; -#endif -} - -gsl_api inline gsl_constexpr byte operator^( byte l, byte r ) gsl_noexcept -{ - return to_byte( to_uchar( l ) ^ to_uchar( r ) ); -} - -gsl_api inline gsl_constexpr byte operator~( byte b ) gsl_noexcept -{ - return to_byte( ~to_uchar( b ) ); -} - -#if gsl_FEATURE_TO_STD( WITH_CONTAINER ) - -// Tag to select span constructor taking a container (prevent ms-gsl warning C26426): - -struct with_container_t { gsl_constexpr with_container_t() gsl_noexcept {} }; -const gsl_constexpr with_container_t with_container; - -#endif - -#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - -namespace detail { - -// Can construct from containers that: - -template< class Container, class ElementType - gsl_REQUIRES_T(( - ! detail::is_span< Container >::value - && ! detail::is_array< Container >::value - && ! detail::is_std_array< Container >::value - && std::is_convertible().data())>::type(*)[], ElementType(*)[] >::value - )) -#if gsl_HAVE( STD_DATA ) - // data(cont) and size(cont) well-formed: - , class = decltype( std::data( std::declval() ) ) - , class = decltype( std::size( std::declval() ) ) -#endif -> -struct can_construct_span_from : std11::true_type{}; - -} // namespace detail - -#endif - -// -// span<> - A 1D view of contiguous T's, replace (*,len). -// -template< class T > -class span -{ - template< class U > friend class span; - -public: - typedef index index_type; - - typedef T element_type; - typedef typename std11::remove_cv< T >::type value_type; - - typedef T & reference; - typedef T * pointer; - typedef T const * const_pointer; - typedef T const & const_reference; - - typedef pointer iterator; - typedef const_pointer const_iterator; - - typedef std::reverse_iterator< iterator > reverse_iterator; - typedef std::reverse_iterator< const_iterator > const_reverse_iterator; - - typedef typename std::iterator_traits< iterator >::difference_type difference_type; - - // 26.7.3.2 Constructors, copy, and assignment [span.cons] - - gsl_api gsl_constexpr14 span() gsl_noexcept - : first_( gsl_nullptr ) - , last_ ( gsl_nullptr ) - { - Expects( size() == 0 ); - } - -#if ! gsl_DEPRECATE_TO_LEVEL( 5 ) - -#if gsl_HAVE( NULLPTR ) - gsl_api gsl_constexpr14 span( std::nullptr_t, index_type gsl_EXPECTS_UNUSED_PARAM( size_in ) ) - : first_( nullptr ) - , last_ ( nullptr ) - { - Expects( size_in == 0 ); - } -#endif - -#if gsl_HAVE( IS_DELETE ) - gsl_api gsl_constexpr span( reference data_in ) - : span( &data_in, 1 ) - {} - - gsl_api gsl_constexpr span( element_type && ) = delete; -#endif - -#endif // deprecate - - gsl_api gsl_constexpr14 span( pointer data_in, index_type size_in ) - : first_( data_in ) - , last_ ( data_in + size_in ) - { - Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) ); - } - - gsl_api gsl_constexpr14 span( pointer first_in, pointer last_in ) - : first_( first_in ) - , last_ ( last_in ) - { - Expects( first_in <= last_in ); - } - -#if ! gsl_DEPRECATE_TO_LEVEL( 5 ) - - template< class U > - gsl_api gsl_constexpr14 span( U * & data_in, index_type size_in ) - : first_( data_in ) - , last_ ( data_in + size_in ) - { - Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) ); - } - - template< class U > - gsl_api gsl_constexpr14 span( U * const & data_in, index_type size_in ) - : first_( data_in ) - , last_ ( data_in + size_in ) - { - Expects( size_in == 0 || ( size_in > 0 && data_in != gsl_nullptr ) ); - } - -#endif // deprecate - -#if ! gsl_DEPRECATE_TO_LEVEL( 5 ) - template< class U, size_t N > - gsl_api gsl_constexpr span( U (&arr)[N] ) gsl_noexcept - : first_( gsl_ADDRESSOF( arr[0] ) ) - , last_ ( gsl_ADDRESSOF( arr[0] ) + N ) - {} -#else - template< size_t N -# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::value )) -# endif - > - gsl_api gsl_constexpr span( element_type (&arr)[N] ) gsl_noexcept - : first_( gsl_ADDRESSOF( arr[0] ) ) - , last_ ( gsl_ADDRESSOF( arr[0] ) + N ) - {} -#endif // deprecate - -#if gsl_HAVE( ARRAY ) -#if ! gsl_DEPRECATE_TO_LEVEL( 5 ) - - template< class U, size_t N > - gsl_api gsl_constexpr span( std::array< U, N > & arr ) - : first_( arr.data() ) - , last_ ( arr.data() + N ) - {} - - template< class U, size_t N > - gsl_api gsl_constexpr span( std::array< U, N > const & arr ) - : first_( arr.data() ) - , last_ ( arr.data() + N ) - {} - -#else - - template< size_t N -# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::value )) -# endif - > - gsl_api gsl_constexpr span( std::array< value_type, N > & arr ) - : first_( arr.data() ) - , last_ ( arr.data() + N ) - {} - - template< size_t N -# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::value )) -# endif - > - gsl_api gsl_constexpr span( std::array< value_type, N > const & arr ) - : first_( arr.data() ) - , last_ ( arr.data() + N ) - {} - -#endif // deprecate -#endif // gsl_HAVE( ARRAY ) - -#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - template< class Container - gsl_REQUIRES_T(( detail::can_construct_span_from< Container, element_type >::value )) - > - gsl_api gsl_constexpr span( Container & cont ) - : first_( cont.data() ) - , last_ ( cont.data() + cont.size() ) - {} - - template< class Container - gsl_REQUIRES_T(( - std::is_const< element_type >::value - && detail::can_construct_span_from< Container, element_type >::value - )) - > - gsl_api gsl_constexpr span( Container const & cont ) - : first_( cont.data() ) - , last_ ( cont.data() + cont.size() ) - {} - -#elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR ) - - template< class Container > - gsl_api gsl_constexpr span( Container & cont ) - : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) ) - , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() ) - {} - - template< class Container > - gsl_api gsl_constexpr span( Container const & cont ) - : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) ) - , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() ) - {} - -#endif - -#if gsl_FEATURE_TO_STD( WITH_CONTAINER ) - - template< class Container > - gsl_api gsl_constexpr span( with_container_t, Container & cont ) - : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) ) - , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() ) - {} - - template< class Container > - gsl_api gsl_constexpr span( with_container_t, Container const & cont ) - : first_( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) ) - , last_ ( cont.size() == 0 ? gsl_nullptr : gsl_ADDRESSOF( cont[0] ) + cont.size() ) - {} - -#endif - -#if ! gsl_DEPRECATE_TO_LEVEL( 4 ) - // constructor taking shared_ptr deprecated since 0.29.0 - -#if gsl_HAVE( SHARED_PTR ) - gsl_api gsl_constexpr span( shared_ptr const & ptr ) - : first_( ptr.get() ) - , last_ ( ptr.get() ? ptr.get() + 1 : gsl_nullptr ) - {} -#endif - - // constructors taking unique_ptr deprecated since 0.29.0 - -#if gsl_HAVE( UNIQUE_PTR ) -# if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - template< class ArrayElementType = typename std::add_pointer::type > -# else - template< class ArrayElementType > -# endif - gsl_api gsl_constexpr span( unique_ptr const & ptr, index_type count ) - : first_( ptr.get() ) - , last_ ( ptr.get() + count ) - {} - - gsl_api gsl_constexpr span( unique_ptr const & ptr ) - : first_( ptr.get() ) - , last_ ( ptr.get() ? ptr.get() + 1 : gsl_nullptr ) - {} -#endif - -#endif // deprecate shared_ptr, unique_ptr - -#if gsl_HAVE( IS_DEFAULT ) && ! gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 430, 600) - gsl_api gsl_constexpr span( span && ) gsl_noexcept = default; - gsl_api gsl_constexpr span( span const & ) = default; -#else - gsl_api gsl_constexpr span( span const & other ) - : first_( other.begin() ) - , last_ ( other.end() ) - {} -#endif - -#if gsl_HAVE( IS_DEFAULT ) - ~span() = default; -#else - ~span() {} -#endif - -#if gsl_HAVE( IS_DEFAULT ) - gsl_api gsl_constexpr14 span & operator=( span && ) gsl_noexcept = default; - gsl_api gsl_constexpr14 span & operator=( span const & ) gsl_noexcept = default; -#else - gsl_api span & operator=( span other ) gsl_noexcept - { - other.swap( *this ); - return *this; - } -#endif - - template< class U -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::value )) -#endif - > - gsl_api gsl_constexpr span( span const & other ) - : first_( other.begin() ) - , last_ ( other.end() ) - {} - -#if 0 - // Converting from other span ? - template< class U > operator=(); -#endif - - // 26.7.3.3 Subviews [span.sub] - - gsl_api gsl_constexpr14 span first( index_type count ) const gsl_noexcept - { - Expects( 0 <= count && count <= this->size() ); - return span( this->data(), count ); - } - - gsl_api gsl_constexpr14 span last( index_type count ) const gsl_noexcept - { - Expects( 0 <= count && count <= this->size() ); - return span( this->data() + this->size() - count, count ); - } - - gsl_api gsl_constexpr14 span subspan( index_type offset ) const gsl_noexcept - { - Expects( 0 <= offset && offset <= this->size() ); - return span( this->data() + offset, this->size() - offset ); - } - - gsl_api gsl_constexpr14 span subspan( index_type offset, index_type count ) const gsl_noexcept - { - Expects( - 0 <= offset && offset <= this->size() && - 0 <= count && count <= this->size() - offset ); - return span( this->data() + offset, count ); - } - - // 26.7.3.4 Observers [span.obs] - - gsl_api gsl_constexpr index_type size() const gsl_noexcept - { - return narrow_cast( last_ - first_ ); - } - - gsl_api gsl_constexpr std::ptrdiff_t ssize() const gsl_noexcept - { - return narrow_cast( last_ - first_ ); - } - - gsl_api gsl_constexpr index_type size_bytes() const gsl_noexcept - { - return size() * narrow_cast( sizeof( element_type ) ); - } - - gsl_api gsl_constexpr bool empty() const gsl_noexcept - { - return size() == 0; - } - - // 26.7.3.5 Element access [span.elem] - - gsl_api gsl_constexpr reference operator[]( index_type index ) const - { - return at( index ); - } - - gsl_api gsl_constexpr reference operator()( index_type index ) const - { - return at( index ); - } - - gsl_api gsl_constexpr14 reference at( index_type index ) const - { - Expects( index < size() ); - return first_[ index ]; - } - - gsl_api gsl_constexpr pointer data() const gsl_noexcept - { - return first_; - } - - // 26.7.3.6 Iterator support [span.iterators] - - gsl_api gsl_constexpr iterator begin() const gsl_noexcept - { - return iterator( first_ ); - } - - gsl_api gsl_constexpr iterator end() const gsl_noexcept - { - return iterator( last_ ); - } - - gsl_api gsl_constexpr const_iterator cbegin() const gsl_noexcept - { -#if gsl_CPP11_OR_GREATER - return { begin() }; -#else - return const_iterator( begin() ); -#endif - } - - gsl_api gsl_constexpr const_iterator cend() const gsl_noexcept - { -#if gsl_CPP11_OR_GREATER - return { end() }; -#else - return const_iterator( end() ); -#endif - } - - gsl_api gsl_constexpr reverse_iterator rbegin() const gsl_noexcept - { - return reverse_iterator( end() ); - } - - gsl_api gsl_constexpr reverse_iterator rend() const gsl_noexcept - { - return reverse_iterator( begin() ); - } - - gsl_api gsl_constexpr const_reverse_iterator crbegin() const gsl_noexcept - { - return const_reverse_iterator( cend() ); - } - - gsl_api gsl_constexpr const_reverse_iterator crend() const gsl_noexcept - { - return const_reverse_iterator( cbegin() ); - } - - gsl_api void swap( span & other ) gsl_noexcept - { - using std::swap; - swap( first_, other.first_ ); - swap( last_ , other.last_ ); - } - -#if ! gsl_DEPRECATE_TO_LEVEL( 3 ) - // member length() deprecated since 0.29.0 - - gsl_api gsl_constexpr index_type length() const gsl_noexcept - { - return size(); - } - - // member length_bytes() deprecated since 0.29.0 - - gsl_api gsl_constexpr index_type length_bytes() const gsl_noexcept - { - return size_bytes(); - } -#endif - -#if ! gsl_DEPRECATE_TO_LEVEL( 2 ) - // member as_bytes(), as_writeable_bytes deprecated since 0.17.0 - - gsl_api span< const byte > as_bytes() const gsl_noexcept - { - return span< const byte >( reinterpret_cast( data() ), size_bytes() ); // NOLINT - } - - gsl_api span< byte > as_writeable_bytes() const gsl_noexcept - { - return span< byte >( reinterpret_cast( data() ), size_bytes() ); // NOLINT - } - -#endif - - template< class U > - gsl_api span< U > as_span() const gsl_noexcept - { - Expects( ( this->size_bytes() % sizeof(U) ) == 0 ); - return span< U >( reinterpret_cast( this->data() ), this->size_bytes() / sizeof( U ) ); // NOLINT - } - -private: - pointer first_; - pointer last_; -}; - -// class template argument deduction guides: - -#if gsl_HAVE( DEDUCTION_GUIDES ) // gsl_CPP17_OR_GREATER - -template< class T, size_t N > -span( T (&)[N] ) -> span; - -template< class T, size_t N > -span( std::array & ) -> span; - -template< class T, size_t N > -span( std::array const & ) -> span; - -template< class Container > -span( Container& ) -> span; - -template< class Container > -span( Container const & ) -> span; - -#endif // gsl_HAVE( DEDUCTION_GUIDES ) - -// 26.7.3.7 Comparison operators [span.comparison] - -#if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator==( span const & l, span const & r ) -{ - return l.size() == r.size() - && (l.begin() == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator< ( span const & l, span const & r ) -{ - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} - -#else - -template< class T > -gsl_api inline gsl_constexpr bool operator==( span const & l, span const & r ) -{ - return l.size() == r.size() - && (l.begin() == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) ); -} - -template< class T > -gsl_api inline gsl_constexpr bool operator< ( span const & l, span const & r ) -{ - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} -#endif - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator!=( span const & l, span const & r ) -{ - return !( l == r ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator<=( span const & l, span const & r ) -{ - return !( r < l ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator> ( span const & l, span const & r ) -{ - return ( r < l ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr bool operator>=( span const & l, span const & r ) -{ - return !( l < r ); -} - -// span algorithms - -template< class T > -gsl_api inline gsl_constexpr std::size_t size( span const & spn ) -{ - return static_cast( spn.size() ); -} - -template< class T > -gsl_api inline gsl_constexpr std::ptrdiff_t ssize( span const & spn ) -{ - return spn.ssize(); -} - -namespace detail { - -template< class II, class N, class OI > -gsl_api inline OI copy_n( II first, N count, OI result ) -{ - if ( count > 0 ) - { - *result++ = *first; - for ( N i = 1; i < count; ++i ) - { - *result++ = *++first; - } - } - return result; -} -} - -template< class T, class U > -gsl_api inline void copy( span src, span dest ) -{ -#if gsl_CPP14_OR_GREATER // gsl_HAVE( TYPE_TRAITS ) (circumvent Travis clang 3.4) - static_assert( std::is_assignable::value, "Cannot assign elements of source span to elements of destination span" ); -#endif - Expects( dest.size() >= src.size() ); - detail::copy_n( src.data(), src.size(), dest.data() ); -} - -// span creator functions (see ctors) - -template< class T > -gsl_api inline span< const byte > as_bytes( span spn ) gsl_noexcept -{ - return span< const byte >( reinterpret_cast( spn.data() ), spn.size_bytes() ); // NOLINT -} - -template< class T> -gsl_api inline span< byte > as_writeable_bytes( span spn ) gsl_noexcept -{ - return span< byte >( reinterpret_cast( spn.data() ), spn.size_bytes() ); // NOLINT -} - -#if gsl_FEATURE_TO_STD( MAKE_SPAN ) - -template< class T > -gsl_api inline gsl_constexpr span -make_span( T * ptr, typename span::index_type count ) -{ - return span( ptr, count ); -} - -template< class T > -gsl_api inline gsl_constexpr span -make_span( T * first, T * last ) -{ - return span( first, last ); -} - -template< class T, size_t N > -gsl_api inline gsl_constexpr span -make_span( T (&arr)[N] ) -{ - return span( gsl_ADDRESSOF( arr[0] ), N ); -} - -#if gsl_HAVE( ARRAY ) - -template< class T, size_t N > -gsl_api inline gsl_constexpr span -make_span( std::array & arr ) -{ - return span( arr ); -} - -template< class T, size_t N > -gsl_api inline gsl_constexpr span -make_span( std::array const & arr ) -{ - return span( arr ); -} -#endif - -#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && gsl_HAVE( AUTO ) - -template< class Container, class = decltype(std::declval().data()) > -gsl_api inline gsl_constexpr auto -make_span( Container & cont ) -> span< typename Container::value_type > -{ - return span< typename Container::value_type >( cont ); -} - -template< class Container, class = decltype(std::declval().data()) > -gsl_api inline gsl_constexpr auto -make_span( Container const & cont ) -> span< const typename Container::value_type > -{ - return span< const typename Container::value_type >( cont ); -} - -#else - -template< class T > -gsl_api inline span -make_span( std::vector & cont ) -{ - return span( with_container, cont ); -} - -template< class T > -gsl_api inline span -make_span( std::vector const & cont ) -{ - return span( with_container, cont ); -} -#endif - -#if gsl_FEATURE_TO_STD( WITH_CONTAINER ) - -template< class Container > -gsl_api inline gsl_constexpr span -make_span( with_container_t, Container & cont ) gsl_noexcept -{ - return span< typename Container::value_type >( with_container, cont ); -} - -template< class Container > -gsl_api inline gsl_constexpr span -make_span( with_container_t, Container const & cont ) gsl_noexcept -{ - return span< const typename Container::value_type >( with_container, cont ); -} - -#endif // gsl_FEATURE_TO_STD( WITH_CONTAINER ) - -template< class Ptr > -gsl_api inline span -make_span( Ptr & ptr ) -{ - return span( ptr ); -} - -template< class Ptr > -gsl_api inline span -make_span( Ptr & ptr, typename span::index_type count ) -{ - return span( ptr, count); -} - -#endif // gsl_FEATURE_TO_STD( MAKE_SPAN ) - -#if gsl_FEATURE_TO_STD( BYTE_SPAN ) - -template< class T > -gsl_api inline gsl_constexpr span -byte_span( T & t ) gsl_noexcept -{ - return span( reinterpret_cast( &t ), sizeof(T) ); -} - -template< class T > -gsl_api inline gsl_constexpr span -byte_span( T const & t ) gsl_noexcept -{ - return span( reinterpret_cast( &t ), sizeof(T) ); -} - -#endif // gsl_FEATURE_TO_STD( BYTE_SPAN ) - -// -// basic_string_span: -// - -template< class T > -class basic_string_span; - -namespace detail { - -template< class T > -struct is_basic_string_span_oracle : std11::false_type {}; - -template< class T > -struct is_basic_string_span_oracle< basic_string_span > : std11::true_type {}; - -template< class T > -struct is_basic_string_span : is_basic_string_span_oracle< typename std11::remove_cv::type > {}; - -template< class T > -gsl_api inline gsl_constexpr14 std::size_t string_length( T * ptr, std::size_t max ) -{ - if ( ptr == gsl_nullptr || max <= 0 ) - return 0; - - std::size_t len = 0; - while ( len < max && ptr[len] ) // NOLINT - ++len; - - return len; -} - -} // namespace detail - -// -// basic_string_span<> - A view of contiguous characters, replace (*,len). -// -template< class T > -class basic_string_span -{ -public: - typedef T element_type; - typedef span span_type; - - typedef typename span_type::index_type index_type; - typedef typename span_type::difference_type difference_type; - - typedef typename span_type::pointer pointer ; - typedef typename span_type::reference reference ; - - typedef typename span_type::iterator iterator ; - typedef typename span_type::const_iterator const_iterator ; - typedef typename span_type::reverse_iterator reverse_iterator; - typedef typename span_type::const_reverse_iterator const_reverse_iterator; - - // construction: - -#if gsl_HAVE( IS_DEFAULT ) - gsl_api gsl_constexpr basic_string_span() gsl_noexcept = default; -#else - gsl_api gsl_constexpr basic_string_span() gsl_noexcept {} -#endif - -#if gsl_HAVE( NULLPTR ) - gsl_api gsl_constexpr basic_string_span( std::nullptr_t ptr ) gsl_noexcept - : span_( ptr, index_type( 0 ) ) - {} -#endif - - gsl_api gsl_constexpr basic_string_span( pointer ptr ) - : span_( remove_z( ptr, (std::numeric_limits::max)() ) ) - {} - - gsl_api gsl_constexpr basic_string_span( pointer ptr, index_type count ) - : span_( ptr, count ) - {} - - gsl_api gsl_constexpr basic_string_span( pointer firstElem, pointer lastElem ) - : span_( firstElem, lastElem ) - {} - - template< std::size_t N > - gsl_api gsl_constexpr basic_string_span( element_type (&arr)[N] ) - : span_( remove_z( gsl_ADDRESSOF( arr[0] ), N ) ) - {} - -#if gsl_HAVE( ARRAY ) - - template< std::size_t N > - gsl_api gsl_constexpr basic_string_span( std::array< typename std11::remove_const::type, N> & arr ) - : span_( remove_z( arr ) ) - {} - - template< std::size_t N > - gsl_api gsl_constexpr basic_string_span( std::array< typename std11::remove_const::type, N> const & arr ) - : span_( remove_z( arr ) ) - {} - -#endif - -#if gsl_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - - // Exclude: array, [basic_string,] basic_string_span - - template< class Container - gsl_REQUIRES_T(( - ! detail::is_std_array< Container >::value - && ! detail::is_basic_string_span< Container >::value - && std::is_convertible< typename Container::pointer, pointer >::value - && std::is_convertible< typename Container::pointer, decltype(std::declval().data()) >::value - )) - > - gsl_api gsl_constexpr basic_string_span( Container & cont ) - : span_( ( cont ) ) - {} - - // Exclude: array, [basic_string,] basic_string_span - - template< class Container - gsl_REQUIRES_T(( - ! detail::is_std_array< Container >::value - && ! detail::is_basic_string_span< Container >::value - && std::is_convertible< typename Container::pointer, pointer >::value - && std::is_convertible< typename Container::pointer, decltype(std::declval().data()) >::value - )) - > - gsl_api gsl_constexpr basic_string_span( Container const & cont ) - : span_( ( cont ) ) - {} - -#elif gsl_HAVE( UNCONSTRAINED_SPAN_CONTAINER_CTOR ) - - template< class Container > - gsl_api gsl_constexpr basic_string_span( Container & cont ) - : span_( cont ) - {} - - template< class Container > - gsl_api gsl_constexpr basic_string_span( Container const & cont ) - : span_( cont ) - {} - -#else - - template< class U > - gsl_api gsl_constexpr basic_string_span( span const & rhs ) - : span_( rhs ) - {} - -#endif - -#if gsl_FEATURE_TO_STD( WITH_CONTAINER ) - - template< class Container > - gsl_api gsl_constexpr basic_string_span( with_container_t, Container & cont ) - : span_( with_container, cont ) - {} -#endif - -#if gsl_HAVE( IS_DEFAULT ) -# if gsl_BETWEEN( gsl_COMPILER_GNUC_VERSION, 440, 600 ) - gsl_api gsl_constexpr basic_string_span( basic_string_span const & rhs ) = default; - - gsl_api gsl_constexpr basic_string_span( basic_string_span && rhs ) = default; -# else - gsl_api gsl_constexpr basic_string_span( basic_string_span const & rhs ) gsl_noexcept = default; - - gsl_api gsl_constexpr basic_string_span( basic_string_span && rhs ) gsl_noexcept = default; -# endif -#endif - - template< class U -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - gsl_REQUIRES_T(( std::is_convertible::pointer, pointer>::value )) -#endif - > - gsl_api gsl_constexpr basic_string_span( basic_string_span const & rhs ) - : span_( reinterpret_cast( rhs.data() ), rhs.length() ) // NOLINT - {} - -#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 120 - template< class U - gsl_REQUIRES_T(( std::is_convertible::pointer, pointer>::value )) - > - gsl_api gsl_constexpr basic_string_span( basic_string_span && rhs ) - : span_( reinterpret_cast( rhs.data() ), rhs.length() ) // NOLINT - {} -#endif - - template< class CharTraits, class Allocator > - gsl_api gsl_constexpr basic_string_span( - std::basic_string< typename std11::remove_const::type, CharTraits, Allocator > & str ) - : span_( gsl_ADDRESSOF( str[0] ), str.length() ) - {} - - template< class CharTraits, class Allocator > - gsl_api gsl_constexpr basic_string_span( - std::basic_string< typename std11::remove_const::type, CharTraits, Allocator > const & str ) - : span_( gsl_ADDRESSOF( str[0] ), str.length() ) - {} - - // destruction, assignment: - -#if gsl_HAVE( IS_DEFAULT ) - gsl_api ~basic_string_span() gsl_noexcept = default; - - gsl_api basic_string_span & operator=( basic_string_span const & rhs ) gsl_noexcept = default; - - gsl_api basic_string_span & operator=( basic_string_span && rhs ) gsl_noexcept = default; -#endif - - // sub span: - - gsl_api gsl_constexpr basic_string_span first( index_type count ) const - { - return span_.first( count ); - } - - gsl_api gsl_constexpr basic_string_span last( index_type count ) const - { - return span_.last( count ); - } - - gsl_api gsl_constexpr basic_string_span subspan( index_type offset ) const - { - return span_.subspan( offset ); - } - - gsl_api gsl_constexpr basic_string_span subspan( index_type offset, index_type count ) const - { - return span_.subspan( offset, count ); - } - - // observers: - - gsl_api gsl_constexpr index_type length() const gsl_noexcept - { - return span_.size(); - } - - gsl_api gsl_constexpr index_type size() const gsl_noexcept - { - return span_.size(); - } - - gsl_api gsl_constexpr index_type length_bytes() const gsl_noexcept - { - return span_.size_bytes(); - } - - gsl_api gsl_constexpr index_type size_bytes() const gsl_noexcept - { - return span_.size_bytes(); - } - - gsl_api gsl_constexpr bool empty() const gsl_noexcept - { - return size() == 0; - } - - gsl_api gsl_constexpr reference operator[]( index_type idx ) const - { - return span_[idx]; - } - - gsl_api gsl_constexpr reference operator()( index_type idx ) const - { - return span_[idx]; - } - - gsl_api gsl_constexpr pointer data() const gsl_noexcept - { - return span_.data(); - } - - gsl_api iterator begin() const gsl_noexcept - { - return span_.begin(); - } - - gsl_api iterator end() const gsl_noexcept - { - return span_.end(); - } - - gsl_api reverse_iterator rbegin() const gsl_noexcept - { - return span_.rbegin(); - } - - gsl_api reverse_iterator rend() const gsl_noexcept - { - return span_.rend(); - } - - // const version not in p0123r2: - - gsl_api const_iterator cbegin() const gsl_noexcept - { - return span_.cbegin(); - } - - gsl_api const_iterator cend() const gsl_noexcept - { - return span_.cend(); - } - - gsl_api const_reverse_iterator crbegin() const gsl_noexcept - { - return span_.crbegin(); - } - - gsl_api const_reverse_iterator crend() const gsl_noexcept - { - return span_.crend(); - } - -private: - gsl_api static gsl_constexpr14 span_type remove_z( pointer const & sz, std::size_t max ) - { - return span_type( sz, detail::string_length( sz, max ) ); - } - -#if gsl_HAVE( ARRAY ) - template< size_t N > - gsl_api static gsl_constexpr14 span_type remove_z( std::array::type, N> & arr ) - { - return remove_z( gsl_ADDRESSOF( arr[0] ), narrow_cast< std::size_t >( N ) ); - } - - template< size_t N > - gsl_api static gsl_constexpr14 span_type remove_z( std::array::type, N> const & arr ) - { - return remove_z( gsl_ADDRESSOF( arr[0] ), narrow_cast< std::size_t >( N ) ); - } -#endif - -private: - span_type span_; -}; - -// basic_string_span comparison functions: - -#if gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator==( basic_string_span const & l, U const & u ) gsl_noexcept -{ - const basic_string_span< typename std11::add_const::type > r( u ); - - return l.size() == r.size() - && std::equal( l.begin(), l.end(), r.begin() ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator<( basic_string_span const & l, U const & u ) gsl_noexcept -{ - const basic_string_span< typename std11::add_const::type > r( u ); - - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} - -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator==( U const & u, basic_string_span const & r ) gsl_noexcept -{ - const basic_string_span< typename std11::add_const::type > l( u ); - - return l.size() == r.size() - && std::equal( l.begin(), l.end(), r.begin() ); -} - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator<( U const & u, basic_string_span const & r ) gsl_noexcept -{ - const basic_string_span< typename std11::add_const::type > l( u ); - - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} -#endif - -#else //gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - -template< class T > -gsl_api inline gsl_constexpr14 bool operator==( basic_string_span const & l, basic_string_span const & r ) gsl_noexcept -{ - return l.size() == r.size() - && std::equal( l.begin(), l.end(), r.begin() ); -} - -template< class T > -gsl_api inline gsl_constexpr14 bool operator<( basic_string_span const & l, basic_string_span const & r ) gsl_noexcept -{ - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} - -#endif // gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator!=( basic_string_span const & l, U const & r ) gsl_noexcept -{ - return !( l == r ); -} - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator<=( basic_string_span const & l, U const & r ) gsl_noexcept -{ -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - return !( r < l ); -#else - basic_string_span< typename std11::add_const::type > rr( r ); - return !( rr < l ); -#endif -} - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator>( basic_string_span const & l, U const & r ) gsl_noexcept -{ -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) || ! gsl_CONFIG( ALLOWS_NONSTRICT_SPAN_COMPARISON ) - return ( r < l ); -#else - basic_string_span< typename std11::add_const::type > rr( r ); - return ( rr < l ); -#endif -} - -template< class T, class U > -gsl_api inline gsl_constexpr14 bool operator>=( basic_string_span const & l, U const & r ) gsl_noexcept -{ - return !( l < r ); -} - -#if gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator!=( U const & l, basic_string_span const & r ) gsl_noexcept -{ - return !( l == r ); -} - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator<=( U const & l, basic_string_span const & r ) gsl_noexcept -{ - return !( r < l ); -} - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator>( U const & l, basic_string_span const & r ) gsl_noexcept -{ - return ( r < l ); -} - -template< class T, class U - gsl_REQUIRES_T(( !detail::is_basic_string_span::value )) -> -gsl_api inline gsl_constexpr14 bool operator>=( U const & l, basic_string_span const & r ) gsl_noexcept -{ - return !( l < r ); -} - -#endif // gsl_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - -// convert basic_string_span to byte span: - -template< class T > -gsl_api inline span< const byte > as_bytes( basic_string_span spn ) gsl_noexcept -{ - return span< const byte >( reinterpret_cast( spn.data() ), spn.size_bytes() ); // NOLINT -} - -// -// String types: -// - -typedef char * zstring; -typedef const char * czstring; - -#if gsl_HAVE( WCHAR ) -typedef wchar_t * zwstring; -typedef const wchar_t * cwzstring; -#endif - -typedef basic_string_span< char > string_span; -typedef basic_string_span< char const > cstring_span; - -#if gsl_HAVE( WCHAR ) -typedef basic_string_span< wchar_t > wstring_span; -typedef basic_string_span< wchar_t const > cwstring_span; -#endif - -// to_string() allow (explicit) conversions from string_span to string - -#if 0 - -template< class T > -gsl_api inline std::basic_string< typename std::remove_const::type > to_string( basic_string_span spn ) -{ - std::string( spn.data(), spn.length() ); -} - -#else - -gsl_api inline std::string to_string( string_span const & spn ) -{ - return std::string( spn.data(), spn.length() ); -} - -gsl_api inline std::string to_string( cstring_span const & spn ) -{ - return std::string( spn.data(), spn.length() ); -} - -#if gsl_HAVE( WCHAR ) - -gsl_api inline std::wstring to_string( wstring_span const & spn ) -{ - return std::wstring( spn.data(), spn.length() ); -} - -gsl_api inline std::wstring to_string( cwstring_span const & spn ) -{ - return std::wstring( spn.data(), spn.length() ); -} - -#endif // gsl_HAVE( WCHAR ) -#endif // to_string() - -// -// Stream output for string_span types -// - -namespace detail { - -template< class Stream > -gsl_api void write_padding( Stream & os, std::streamsize n ) -{ - for ( std::streamsize i = 0; i < n; ++i ) - os.rdbuf()->sputc( os.fill() ); -} - -template< class Stream, class Span > -gsl_api Stream & write_to_stream( Stream & os, Span const & spn ) -{ - typename Stream::sentry sentry( os ); - - if ( !os ) - return os; - - const std::streamsize length = narrow( spn.length() ); - - // Whether, and how, to pad - const bool pad = ( length < os.width() ); - const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right; - - if ( left_pad ) - write_padding( os, os.width() - length ); - - // Write span characters - os.rdbuf()->sputn( spn.begin(), length ); - - if ( pad && !left_pad ) - write_padding( os, os.width() - length ); - - // Reset output stream width - os.width(0); - - return os; -} - -} // namespace detail - -template< typename Traits > -gsl_api std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, string_span const & spn ) -{ - return detail::write_to_stream( os, spn ); -} - -template< typename Traits > -gsl_api std::basic_ostream< char, Traits > & operator<<( std::basic_ostream< char, Traits > & os, cstring_span const & spn ) -{ - return detail::write_to_stream( os, spn ); -} - -#if gsl_HAVE( WCHAR ) - -template< typename Traits > -gsl_api std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, wstring_span const & spn ) -{ - return detail::write_to_stream( os, spn ); -} - -template< typename Traits > -gsl_api std::basic_ostream< wchar_t, Traits > & operator<<( std::basic_ostream< wchar_t, Traits > & os, cwstring_span const & spn ) -{ - return detail::write_to_stream( os, spn ); -} - -#endif // gsl_HAVE( WCHAR ) - -// -// ensure_sentinel() -// -// Provides a way to obtain a span from a contiguous sequence -// that ends with a (non-inclusive) sentinel value. -// -// Will fail-fast if sentinel cannot be found before max elements are examined. -// -namespace detail { - -template< class T, class SizeType, const T Sentinel > -gsl_api static span ensure_sentinel( T * seq, SizeType max = (std::numeric_limits::max)() ) -{ - typedef T * pointer; - - gsl_SUPPRESS_MSVC_WARNING( 26429, "f.23: symbol 'cur' is never tested for nullness, it can be marked as not_null" ) - - pointer cur = seq; - - while ( static_cast( cur - seq ) < max && *cur != Sentinel ) - ++cur; - - Expects( *cur == Sentinel ); - - return span( seq, narrow_cast< typename span::index_type >( cur - seq ) ); -} -} // namespace detail - -// -// ensure_z - creates a string_span for a czstring or cwzstring. -// Will fail fast if a null-terminator cannot be found before -// the limit of size_type. -// - -template< class T > -gsl_api inline span ensure_z( T * const & sz, size_t max = (std::numeric_limits::max)() ) -{ - return detail::ensure_sentinel( sz, max ); -} - -template< class T, size_t N > -gsl_api inline span ensure_z( T (&sz)[N] ) -{ - return ensure_z( gsl_ADDRESSOF( sz[0] ), N ); -} - -# if gsl_HAVE( TYPE_TRAITS ) - -template< class Container > -gsl_api inline span< typename std::remove_pointer::type > -ensure_z( Container & cont ) -{ - return ensure_z( cont.data(), cont.length() ); -} -# endif - -} // namespace gsl - -#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 120 - -namespace std { - -template<> -struct hash< gsl::byte > -{ -public: - std::size_t operator()( gsl::byte v ) const gsl_noexcept - { - return gsl::to_integer( v ); - } -}; - -} // namespace std - -#endif - -gsl_RESTORE_MSVC_WARNINGS() - -#endif // GSL_GSL_LITE_HPP_INCLUDED - -// end of file diff --git a/vendor/pugixml/pugiconfig.hpp b/vendor/pugixml/pugiconfig.hpp deleted file mode 100644 index 2f1027aa3..000000000 --- a/vendor/pugixml/pugiconfig.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/** - * pugixml parser - version 1.8 - * -------------------------------------------------------- - * Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef HEADER_PUGICONFIG_HPP -#define HEADER_PUGICONFIG_HPP - -// Uncomment this to enable wchar_t mode -// #define PUGIXML_WCHAR_MODE - -// Uncomment this to enable compact mode -// #define PUGIXML_COMPACT - -// Uncomment this to disable XPath -// #define PUGIXML_NO_XPATH - -// Uncomment this to disable STL -// #define PUGIXML_NO_STL - -// Uncomment this to disable exceptions -// #define PUGIXML_NO_EXCEPTIONS - -// Set this to control attributes for public classes/functions, i.e.: -// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL -// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL -// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall -// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead - -// Tune these constants to adjust memory-related behavior -// #define PUGIXML_MEMORY_PAGE_SIZE 32768 -// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 -// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 - -// Uncomment this to switch to header-only version -// #define PUGIXML_HEADER_ONLY - -// Uncomment this to enable long long support -#define PUGIXML_HAS_LONG_LONG - -#endif - -/** - * Copyright (c) 2006-2016 Arseny Kapoulkine - * - * 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 the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ diff --git a/vendor/pugixml/pugixml.cpp b/vendor/pugixml/pugixml.cpp deleted file mode 100644 index cac51a534..000000000 --- a/vendor/pugixml/pugixml.cpp +++ /dev/null @@ -1,12622 +0,0 @@ -/** - * pugixml parser - version 1.8 - * -------------------------------------------------------- - * Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef SOURCE_PUGIXML_CPP -#define SOURCE_PUGIXML_CPP - -#include "pugixml.hpp" - -#include -#include -#include -#include -#include - -#ifdef PUGIXML_WCHAR_MODE -# include -#endif - -#ifndef PUGIXML_NO_XPATH -# include -# include -# ifdef PUGIXML_NO_EXCEPTIONS -# include -# endif -#endif - -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// For placement new -#include - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) -# pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable -# pragma warning(disable: 4702) // unreachable code -# pragma warning(disable: 4996) // this function or variable may be unsafe -# pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged -#endif - -#ifdef __INTEL_COMPILER -# pragma warning(disable: 177) // function was declared but never referenced -# pragma warning(disable: 279) // controlling expression is constant -# pragma warning(disable: 1478 1786) // function was declared "deprecated" -# pragma warning(disable: 1684) // conversion from pointer to same-sized integral type -#endif - -#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY) -# pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away -#endif - -#ifdef __BORLANDC__ -# pragma option push -# pragma warn -8008 // condition is always false -# pragma warn -8066 // unreachable code -#endif - -#ifdef __SNC__ -// Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug -# pragma diag_suppress=178 // function was declared but never referenced -# pragma diag_suppress=237 // controlling expression is constant -#endif - -// Inlining controls -#if defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGI__NO_INLINE __declspec(noinline) -#elif defined(__GNUC__) -# define PUGI__NO_INLINE __attribute__((noinline)) -#else -# define PUGI__NO_INLINE -#endif - -// Branch weight controls -#if defined(__GNUC__) -# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) -#else -# define PUGI__UNLIKELY(cond) (cond) -#endif - -// Simple static assertion -#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } - -// Digital Mars C++ bug workaround for passing char loaded from memory via stack -#ifdef __DMC__ -# define PUGI__DMC_VOLATILE volatile -#else -# define PUGI__DMC_VOLATILE -#endif - -// Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) -#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) -using std::memcpy; -using std::memmove; -using std::memset; -#endif - -// Some MinGW versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions in strict ANSI mode -#if defined(PUGIXML_HAS_LONG_LONG) && defined(__MINGW32__) && defined(__STRICT_ANSI__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX) -# define LLONG_MAX 9223372036854775807LL -# define LLONG_MIN (-LLONG_MAX-1) -# define ULLONG_MAX (2ULL*LLONG_MAX+1) -#endif - -// In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features -#if defined(_MSC_VER) && !defined(__S3E__) -# define PUGI__MSVC_CRT_VERSION _MSC_VER -#endif - -#ifdef PUGIXML_HEADER_ONLY -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } -# define PUGI__FN inline -# define PUGI__FN_NO_INLINE inline -#else -# if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } -# else -# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace { -# define PUGI__NS_END } } } -# endif -# define PUGI__FN -# define PUGI__FN_NO_INLINE PUGI__NO_INLINE -#endif - -// uintptr_t -#if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561) -namespace pugi -{ -# ifndef _UINTPTR_T_DEFINED - typedef size_t uintptr_t; -# endif - - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -} -#else -# include -#endif - -// Memory allocation -PUGI__NS_BEGIN - PUGI__FN void* default_allocate(size_t size) - { - return malloc(size); - } - - PUGI__FN void default_deallocate(void* ptr) - { - free(ptr); - } - - template - struct xml_memory_management_function_storage - { - static allocation_function allocate; - static deallocation_function deallocate; - }; - - // Global allocation functions are stored in class statics so that in header mode linker deduplicates them - // Without a template<> we'll get multiple definitions of the same static - template allocation_function xml_memory_management_function_storage::allocate = default_allocate; - template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; - - typedef xml_memory_management_function_storage xml_memory; -PUGI__NS_END - -// String utilities -PUGI__NS_BEGIN - // Get string length - PUGI__FN size_t strlength(const char_t* s) - { - assert(s); - - #ifdef PUGIXML_WCHAR_MODE - return wcslen(s); - #else - return strlen(s); - #endif - } - - // Compare two strings - PUGI__FN bool strequal(const char_t* src, const char_t* dst) - { - assert(src && dst); - - #ifdef PUGIXML_WCHAR_MODE - return wcscmp(src, dst) == 0; - #else - return strcmp(src, dst) == 0; - #endif - } - - // Compare lhs with [rhs_begin, rhs_end) - PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) - { - for (size_t i = 0; i < count; ++i) - if (lhs[i] != rhs[i]) - return false; - - return lhs[count] == 0; - } - - // Get length of wide string, even if CRT lacks wide character support - PUGI__FN size_t strlength_wide(const wchar_t* s) - { - assert(s); - - #ifdef PUGIXML_WCHAR_MODE - return wcslen(s); - #else - const wchar_t* end = s; - while (*end) end++; - return static_cast(end - s); - #endif - } -PUGI__NS_END - -// auto_ptr-like object for exception recovery -PUGI__NS_BEGIN - template struct auto_deleter - { - typedef void (*D)(T*); - - T* data; - D deleter; - - auto_deleter(T* data_, D deleter_): data(data_), deleter(deleter_) - { - } - - ~auto_deleter() - { - if (data) deleter(data); - } - - T* release() - { - T* result = data; - data = 0; - return result; - } - }; -PUGI__NS_END - -#ifdef PUGIXML_COMPACT -PUGI__NS_BEGIN - class compact_hash_table - { - public: - compact_hash_table(): _items(0), _capacity(0), _count(0) - { - } - - void clear() - { - if (_items) - { - xml_memory::deallocate(_items); - _items = 0; - _capacity = 0; - _count = 0; - } - } - - void** find(const void* key) - { - assert(key); - - if (_capacity == 0) return 0; - - size_t hashmod = _capacity - 1; - size_t bucket = hash(key) & hashmod; - - for (size_t probe = 0; probe <= hashmod; ++probe) - { - item_t& probe_item = _items[bucket]; - - if (probe_item.key == key) - return &probe_item.value; - - if (probe_item.key == 0) - return 0; - - // hash collision, quadratic probing - bucket = (bucket + probe + 1) & hashmod; - } - - assert(false && "Hash table is full"); - return 0; - } - - void** insert(const void* key) - { - assert(key); - assert(_capacity != 0 && _count < _capacity - _capacity / 4); - - size_t hashmod = _capacity - 1; - size_t bucket = hash(key) & hashmod; - - for (size_t probe = 0; probe <= hashmod; ++probe) - { - item_t& probe_item = _items[bucket]; - - if (probe_item.key == 0) - { - probe_item.key = key; - _count++; - return &probe_item.value; - } - - if (probe_item.key == key) - return &probe_item.value; - - // hash collision, quadratic probing - bucket = (bucket + probe + 1) & hashmod; - } - - assert(false && "Hash table is full"); - return 0; - } - - bool reserve() - { - if (_count + 16 >= _capacity - _capacity / 4) - return rehash(); - - return true; - } - - private: - struct item_t - { - const void* key; - void* value; - }; - - item_t* _items; - size_t _capacity; - - size_t _count; - - bool rehash(); - - static unsigned int hash(const void* key) - { - unsigned int h = static_cast(reinterpret_cast(key)); - - // MurmurHash3 32-bit finalizer - h ^= h >> 16; - h *= 0x85ebca6bu; - h ^= h >> 13; - h *= 0xc2b2ae35u; - h ^= h >> 16; - - return h; - } - }; - - PUGI__FN_NO_INLINE bool compact_hash_table::rehash() - { - compact_hash_table rt; - rt._capacity = (_capacity == 0) ? 32 : _capacity * 2; - rt._items = static_cast(xml_memory::allocate(sizeof(item_t) * rt._capacity)); - - if (!rt._items) - return false; - - memset(rt._items, 0, sizeof(item_t) * rt._capacity); - - for (size_t i = 0; i < _capacity; ++i) - if (_items[i].key) - *rt.insert(_items[i].key) = _items[i].value; - - if (_items) - xml_memory::deallocate(_items); - - _capacity = rt._capacity; - _items = rt._items; - - assert(_count == rt._count); - - return true; - } - -PUGI__NS_END -#endif - -PUGI__NS_BEGIN -#ifdef PUGIXML_COMPACT - static const uintptr_t xml_memory_block_alignment = 4; -#else - static const uintptr_t xml_memory_block_alignment = sizeof(void*); -#endif - - // extra metadata bits - static const uintptr_t xml_memory_page_contents_shared_mask = 64; - static const uintptr_t xml_memory_page_name_allocated_mask = 32; - static const uintptr_t xml_memory_page_value_allocated_mask = 16; - static const uintptr_t xml_memory_page_type_mask = 15; - - // combined masks for string uniqueness - static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; - static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; - -#ifdef PUGIXML_COMPACT - #define PUGI__GETHEADER_IMPL(object, page, flags) // unused - #define PUGI__GETPAGE_IMPL(header) (header).get_page() -#else - #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast(object) - reinterpret_cast(page)) << 8) | (flags)) - // this macro casts pointers through void* to avoid 'cast increases required alignment of target type' warnings - #define PUGI__GETPAGE_IMPL(header) static_cast(const_cast(static_cast(reinterpret_cast(&header) - (header >> 8)))) -#endif - - #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header) - #define PUGI__NODETYPE(n) static_cast((n)->header & impl::xml_memory_page_type_mask) - - struct xml_allocator; - - struct xml_memory_page - { - static xml_memory_page* construct(void* memory) - { - xml_memory_page* result = static_cast(memory); - - result->allocator = 0; - result->prev = 0; - result->next = 0; - result->busy_size = 0; - result->freed_size = 0; - - #ifdef PUGIXML_COMPACT - result->compact_string_base = 0; - result->compact_shared_parent = 0; - result->compact_page_marker = 0; - #endif - - return result; - } - - xml_allocator* allocator; - - xml_memory_page* prev; - xml_memory_page* next; - - size_t busy_size; - size_t freed_size; - - #ifdef PUGIXML_COMPACT - char_t* compact_string_base; - void* compact_shared_parent; - uint32_t* compact_page_marker; - #endif - }; - - static const size_t xml_memory_page_size = - #ifdef PUGIXML_MEMORY_PAGE_SIZE - (PUGIXML_MEMORY_PAGE_SIZE) - #else - 32768 - #endif - - sizeof(xml_memory_page); - - struct xml_memory_string_header - { - uint16_t page_offset; // offset from page->data - uint16_t full_size; // 0 if string occupies whole page - }; - - struct xml_allocator - { - xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) - { - #ifdef PUGIXML_COMPACT - _hash = 0; - #endif - } - - xml_memory_page* allocate_page(size_t data_size) - { - size_t size = sizeof(xml_memory_page) + data_size; - - // allocate block with some alignment, leaving memory for worst-case padding - void* memory = xml_memory::allocate(size); - if (!memory) return 0; - - // prepare page structure - xml_memory_page* page = xml_memory_page::construct(memory); - assert(page); - - page->allocator = _root->allocator; - - return page; - } - - static void deallocate_page(xml_memory_page* page) - { - xml_memory::deallocate(page); - } - - void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); - - void* allocate_memory(size_t size, xml_memory_page*& out_page) - { - if (PUGI__UNLIKELY(_busy_size + size > xml_memory_page_size)) - return allocate_memory_oob(size, out_page); - - void* buf = reinterpret_cast(_root) + sizeof(xml_memory_page) + _busy_size; - - _busy_size += size; - - out_page = _root; - - return buf; - } - - #ifdef PUGIXML_COMPACT - void* allocate_object(size_t size, xml_memory_page*& out_page) - { - void* result = allocate_memory(size + sizeof(uint32_t), out_page); - if (!result) return 0; - - // adjust for marker - ptrdiff_t offset = static_cast(result) - reinterpret_cast(out_page->compact_page_marker); - - if (PUGI__UNLIKELY(static_cast(offset) >= 256 * xml_memory_block_alignment)) - { - // insert new marker - uint32_t* marker = static_cast(result); - - *marker = static_cast(reinterpret_cast(marker) - reinterpret_cast(out_page)); - out_page->compact_page_marker = marker; - - // since we don't reuse the page space until we reallocate it, we can just pretend that we freed the marker block - // this will make sure deallocate_memory correctly tracks the size - out_page->freed_size += sizeof(uint32_t); - - return marker + 1; - } - else - { - // roll back uint32_t part - _busy_size -= sizeof(uint32_t); - - return result; - } - } - #else - void* allocate_object(size_t size, xml_memory_page*& out_page) - { - return allocate_memory(size, out_page); - } - #endif - - void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) - { - if (page == _root) page->busy_size = _busy_size; - - assert(ptr >= reinterpret_cast(page) + sizeof(xml_memory_page) && ptr < reinterpret_cast(page) + sizeof(xml_memory_page) + page->busy_size); - (void)!ptr; - - page->freed_size += size; - assert(page->freed_size <= page->busy_size); - - if (page->freed_size == page->busy_size) - { - if (page->next == 0) - { - assert(_root == page); - - // top page freed, just reset sizes - page->busy_size = 0; - page->freed_size = 0; - - #ifdef PUGIXML_COMPACT - // reset compact state to maximize efficiency - page->compact_string_base = 0; - page->compact_shared_parent = 0; - page->compact_page_marker = 0; - #endif - - _busy_size = 0; - } - else - { - assert(_root != page); - assert(page->prev); - - // remove from the list - page->prev->next = page->next; - page->next->prev = page->prev; - - // deallocate - deallocate_page(page); - } - } - } - - char_t* allocate_string(size_t length) - { - static const size_t max_encoded_offset = (1 << 16) * xml_memory_block_alignment; - - PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); - - // allocate memory for string and header block - size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); - - // round size up to block alignment boundary - size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1); - - xml_memory_page* page; - xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); - - if (!header) return 0; - - // setup header - ptrdiff_t page_offset = reinterpret_cast(header) - reinterpret_cast(page) - sizeof(xml_memory_page); - - assert(page_offset % xml_memory_block_alignment == 0); - assert(page_offset >= 0 && static_cast(page_offset) < max_encoded_offset); - header->page_offset = static_cast(static_cast(page_offset) / xml_memory_block_alignment); - - // full_size == 0 for large strings that occupy the whole page - assert(full_size % xml_memory_block_alignment == 0); - assert(full_size < max_encoded_offset || (page->busy_size == full_size && page_offset == 0)); - header->full_size = static_cast(full_size < max_encoded_offset ? full_size / xml_memory_block_alignment : 0); - - // round-trip through void* to avoid 'cast increases required alignment of target type' warning - // header is guaranteed a pointer-sized alignment, which should be enough for char_t - return static_cast(static_cast(header + 1)); - } - - void deallocate_string(char_t* string) - { - // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings - // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string - - // get header - xml_memory_string_header* header = static_cast(static_cast(string)) - 1; - assert(header); - - // deallocate - size_t page_offset = sizeof(xml_memory_page) + header->page_offset * xml_memory_block_alignment; - xml_memory_page* page = reinterpret_cast(static_cast(reinterpret_cast(header) - page_offset)); - - // if full_size == 0 then this string occupies the whole page - size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size * xml_memory_block_alignment; - - deallocate_memory(header, full_size, page); - } - - bool reserve() - { - #ifdef PUGIXML_COMPACT - return _hash->reserve(); - #else - return true; - #endif - } - - xml_memory_page* _root; - size_t _busy_size; - - #ifdef PUGIXML_COMPACT - compact_hash_table* _hash; - #endif - }; - - PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) - { - const size_t large_allocation_threshold = xml_memory_page_size / 4; - - xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); - out_page = page; - - if (!page) return 0; - - if (size <= large_allocation_threshold) - { - _root->busy_size = _busy_size; - - // insert page at the end of linked list - page->prev = _root; - _root->next = page; - _root = page; - - _busy_size = size; - } - else - { - // insert page before the end of linked list, so that it is deleted as soon as possible - // the last page is not deleted even if it's empty (see deallocate_memory) - assert(_root->prev); - - page->prev = _root->prev; - page->next = _root; - - _root->prev->next = page; - _root->prev = page; - - page->busy_size = size; - } - - return reinterpret_cast(page) + sizeof(xml_memory_page); - } -PUGI__NS_END - -#ifdef PUGIXML_COMPACT -PUGI__NS_BEGIN - static const uintptr_t compact_alignment_log2 = 2; - static const uintptr_t compact_alignment = 1 << compact_alignment_log2; - - class compact_header - { - public: - compact_header(xml_memory_page* page, unsigned int flags) - { - PUGI__STATIC_ASSERT(xml_memory_block_alignment == compact_alignment); - - ptrdiff_t offset = (reinterpret_cast(this) - reinterpret_cast(page->compact_page_marker)); - assert(offset % compact_alignment == 0 && static_cast(offset) < 256 * compact_alignment); - - _page = static_cast(offset >> compact_alignment_log2); - _flags = static_cast(flags); - } - - void operator&=(uintptr_t mod) - { - _flags &= static_cast(mod); - } - - void operator|=(uintptr_t mod) - { - _flags |= static_cast(mod); - } - - uintptr_t operator&(uintptr_t mod) const - { - return _flags & mod; - } - - xml_memory_page* get_page() const - { - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - const char* page_marker = reinterpret_cast(this) - (_page << compact_alignment_log2); - const char* page = page_marker - *reinterpret_cast(static_cast(page_marker)); - - return const_cast(reinterpret_cast(static_cast(page))); - } - - private: - unsigned char _page; - unsigned char _flags; - }; - - PUGI__FN xml_memory_page* compact_get_page(const void* object, int header_offset) - { - const compact_header* header = reinterpret_cast(static_cast(object) - header_offset); - - return header->get_page(); - } - - template PUGI__FN_NO_INLINE T* compact_get_value(const void* object) - { - return static_cast(*compact_get_page(object, header_offset)->allocator->_hash->find(object)); - } - - template PUGI__FN_NO_INLINE void compact_set_value(const void* object, T* value) - { - *compact_get_page(object, header_offset)->allocator->_hash->insert(object) = value; - } - - template class compact_pointer - { - public: - compact_pointer(): _data(0) - { - } - - void operator=(const compact_pointer& rhs) - { - *this = rhs + 0; - } - - void operator=(T* value) - { - if (value) - { - // value is guaranteed to be compact-aligned; 'this' is not - // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*) - // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to - // compensate for arithmetic shift rounding for negative values - ptrdiff_t diff = reinterpret_cast(value) - reinterpret_cast(this); - ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start; - - if (static_cast(offset) <= 253) - _data = static_cast(offset + 1); - else - { - compact_set_value(this, value); - - _data = 255; - } - } - else - _data = 0; - } - - operator T*() const - { - if (_data) - { - if (_data < 255) - { - uintptr_t base = reinterpret_cast(this) & ~(compact_alignment - 1); - - return reinterpret_cast(base + ((_data - 1 + start) << compact_alignment_log2)); - } - else - return compact_get_value(this); - } - else - return 0; - } - - T* operator->() const - { - return *this; - } - - private: - unsigned char _data; - }; - - template class compact_pointer_parent - { - public: - compact_pointer_parent(): _data(0) - { - } - - void operator=(const compact_pointer_parent& rhs) - { - *this = rhs + 0; - } - - void operator=(T* value) - { - if (value) - { - // value is guaranteed to be compact-aligned; 'this' is not - // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*) - // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to - // compensate for arithmetic shift behavior for negative values - ptrdiff_t diff = reinterpret_cast(value) - reinterpret_cast(this); - ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533; - - if (static_cast(offset) <= 65533) - { - _data = static_cast(offset + 1); - } - else - { - xml_memory_page* page = compact_get_page(this, header_offset); - - if (PUGI__UNLIKELY(page->compact_shared_parent == 0)) - page->compact_shared_parent = value; - - if (page->compact_shared_parent == value) - { - _data = 65534; - } - else - { - compact_set_value(this, value); - - _data = 65535; - } - } - } - else - { - _data = 0; - } - } - - operator T*() const - { - if (_data) - { - if (_data < 65534) - { - uintptr_t base = reinterpret_cast(this) & ~(compact_alignment - 1); - - return reinterpret_cast(base + ((_data - 1 - 65533) << compact_alignment_log2)); - } - else if (_data == 65534) - return static_cast(compact_get_page(this, header_offset)->compact_shared_parent); - else - return compact_get_value(this); - } - else - return 0; - } - - T* operator->() const - { - return *this; - } - - private: - uint16_t _data; - }; - - template class compact_string - { - public: - compact_string(): _data(0) - { - } - - void operator=(const compact_string& rhs) - { - *this = rhs + 0; - } - - void operator=(char_t* value) - { - if (value) - { - xml_memory_page* page = compact_get_page(this, header_offset); - - if (PUGI__UNLIKELY(page->compact_string_base == 0)) - page->compact_string_base = value; - - ptrdiff_t offset = value - page->compact_string_base; - - if (static_cast(offset) < (65535 << 7)) - { - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - uint16_t* base = reinterpret_cast(static_cast(reinterpret_cast(this) - base_offset)); - - if (*base == 0) - { - *base = static_cast((offset >> 7) + 1); - _data = static_cast((offset & 127) + 1); - } - else - { - ptrdiff_t remainder = offset - ((*base - 1) << 7); - - if (static_cast(remainder) <= 253) - { - _data = static_cast(remainder + 1); - } - else - { - compact_set_value(this, value); - - _data = 255; - } - } - } - else - { - compact_set_value(this, value); - - _data = 255; - } - } - else - { - _data = 0; - } - } - - operator char_t*() const - { - if (_data) - { - if (_data < 255) - { - xml_memory_page* page = compact_get_page(this, header_offset); - - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - const uint16_t* base = reinterpret_cast(static_cast(reinterpret_cast(this) - base_offset)); - assert(*base); - - ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1); - - return page->compact_string_base + offset; - } - else - { - return compact_get_value(this); - } - } - else - return 0; - } - - private: - unsigned char _data; - }; -PUGI__NS_END -#endif - -#ifdef PUGIXML_COMPACT -namespace pugi -{ - struct xml_attribute_struct - { - xml_attribute_struct(impl::xml_memory_page* page): header(page, 0), namevalue_base(0) - { - PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 8); - } - - impl::compact_header header; - - uint16_t namevalue_base; - - impl::compact_string<4, 2> name; - impl::compact_string<5, 3> value; - - impl::compact_pointer prev_attribute_c; - impl::compact_pointer next_attribute; - }; - - struct xml_node_struct - { - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type), namevalue_base(0) - { - PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12); - } - - impl::compact_header header; - - uint16_t namevalue_base; - - impl::compact_string<4, 2> name; - impl::compact_string<5, 3> value; - - impl::compact_pointer_parent parent; - - impl::compact_pointer first_child; - - impl::compact_pointer prev_sibling_c; - impl::compact_pointer next_sibling; - - impl::compact_pointer first_attribute; - }; -} -#else -namespace pugi -{ - struct xml_attribute_struct - { - xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0) - { - header = PUGI__GETHEADER_IMPL(this, page, 0); - } - - uintptr_t header; - - char_t* name; - char_t* value; - - xml_attribute_struct* prev_attribute_c; - xml_attribute_struct* next_attribute; - }; - - struct xml_node_struct - { - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) - { - header = PUGI__GETHEADER_IMPL(this, page, type); - } - - uintptr_t header; - - char_t* name; - char_t* value; - - xml_node_struct* parent; - - xml_node_struct* first_child; - - xml_node_struct* prev_sibling_c; - xml_node_struct* next_sibling; - - xml_attribute_struct* first_attribute; - }; -} -#endif - -PUGI__NS_BEGIN - struct xml_extra_buffer - { - char_t* buffer; - xml_extra_buffer* next; - }; - - struct xml_document_struct: public xml_node_struct, public xml_allocator - { - xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) - { - } - - const char_t* buffer; - - xml_extra_buffer* extra_buffers; - - #ifdef PUGIXML_COMPACT - compact_hash_table hash; - #endif - }; - - template inline xml_allocator& get_allocator(const Object* object) - { - assert(object); - - return *PUGI__GETPAGE(object)->allocator; - } - - template inline xml_document_struct& get_document(const Object* object) - { - assert(object); - - return *static_cast(PUGI__GETPAGE(object)->allocator); - } -PUGI__NS_END - -// Low-level DOM operations -PUGI__NS_BEGIN - inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) - { - xml_memory_page* page; - void* memory = alloc.allocate_object(sizeof(xml_attribute_struct), page); - if (!memory) return 0; - - return new (memory) xml_attribute_struct(page); - } - - inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) - { - xml_memory_page* page; - void* memory = alloc.allocate_object(sizeof(xml_node_struct), page); - if (!memory) return 0; - - return new (memory) xml_node_struct(page, type); - } - - inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) - { - if (a->header & impl::xml_memory_page_name_allocated_mask) - alloc.deallocate_string(a->name); - - if (a->header & impl::xml_memory_page_value_allocated_mask) - alloc.deallocate_string(a->value); - - alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a)); - } - - inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) - { - if (n->header & impl::xml_memory_page_name_allocated_mask) - alloc.deallocate_string(n->name); - - if (n->header & impl::xml_memory_page_value_allocated_mask) - alloc.deallocate_string(n->value); - - for (xml_attribute_struct* attr = n->first_attribute; attr; ) - { - xml_attribute_struct* next = attr->next_attribute; - - destroy_attribute(attr, alloc); - - attr = next; - } - - for (xml_node_struct* child = n->first_child; child; ) - { - xml_node_struct* next = child->next_sibling; - - destroy_node(child, alloc); - - child = next; - } - - alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI__GETPAGE(n)); - } - - inline void append_node(xml_node_struct* child, xml_node_struct* node) - { - child->parent = node; - - xml_node_struct* head = node->first_child; - - if (head) - { - xml_node_struct* tail = head->prev_sibling_c; - - tail->next_sibling = child; - child->prev_sibling_c = tail; - head->prev_sibling_c = child; - } - else - { - node->first_child = child; - child->prev_sibling_c = child; - } - } - - inline void prepend_node(xml_node_struct* child, xml_node_struct* node) - { - child->parent = node; - - xml_node_struct* head = node->first_child; - - if (head) - { - child->prev_sibling_c = head->prev_sibling_c; - head->prev_sibling_c = child; - } - else - child->prev_sibling_c = child; - - child->next_sibling = head; - node->first_child = child; - } - - inline void insert_node_after(xml_node_struct* child, xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - child->parent = parent; - - if (node->next_sibling) - node->next_sibling->prev_sibling_c = child; - else - parent->first_child->prev_sibling_c = child; - - child->next_sibling = node->next_sibling; - child->prev_sibling_c = node; - - node->next_sibling = child; - } - - inline void insert_node_before(xml_node_struct* child, xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - child->parent = parent; - - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = child; - else - parent->first_child = child; - - child->prev_sibling_c = node->prev_sibling_c; - child->next_sibling = node; - - node->prev_sibling_c = child; - } - - inline void remove_node(xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - if (node->next_sibling) - node->next_sibling->prev_sibling_c = node->prev_sibling_c; - else - parent->first_child->prev_sibling_c = node->prev_sibling_c; - - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = node->next_sibling; - else - parent->first_child = node->next_sibling; - - node->parent = 0; - node->prev_sibling_c = 0; - node->next_sibling = 0; - } - - inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - xml_attribute_struct* head = node->first_attribute; - - if (head) - { - xml_attribute_struct* tail = head->prev_attribute_c; - - tail->next_attribute = attr; - attr->prev_attribute_c = tail; - head->prev_attribute_c = attr; - } - else - { - node->first_attribute = attr; - attr->prev_attribute_c = attr; - } - } - - inline void prepend_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - xml_attribute_struct* head = node->first_attribute; - - if (head) - { - attr->prev_attribute_c = head->prev_attribute_c; - head->prev_attribute_c = attr; - } - else - attr->prev_attribute_c = attr; - - attr->next_attribute = head; - node->first_attribute = attr; - } - - inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) - { - if (place->next_attribute) - place->next_attribute->prev_attribute_c = attr; - else - node->first_attribute->prev_attribute_c = attr; - - attr->next_attribute = place->next_attribute; - attr->prev_attribute_c = place; - place->next_attribute = attr; - } - - inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) - { - if (place->prev_attribute_c->next_attribute) - place->prev_attribute_c->next_attribute = attr; - else - node->first_attribute = attr; - - attr->prev_attribute_c = place->prev_attribute_c; - attr->next_attribute = place; - place->prev_attribute_c = attr; - } - - inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - if (attr->next_attribute) - attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; - else - node->first_attribute->prev_attribute_c = attr->prev_attribute_c; - - if (attr->prev_attribute_c->next_attribute) - attr->prev_attribute_c->next_attribute = attr->next_attribute; - else - node->first_attribute = attr->next_attribute; - - attr->prev_attribute_c = 0; - attr->next_attribute = 0; - } - - PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) - { - if (!alloc.reserve()) return 0; - - xml_node_struct* child = allocate_node(alloc, type); - if (!child) return 0; - - append_node(child, node); - - return child; - } - - PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) - { - if (!alloc.reserve()) return 0; - - xml_attribute_struct* attr = allocate_attribute(alloc); - if (!attr) return 0; - - append_attribute(attr, node); - - return attr; - } -PUGI__NS_END - -// Helper classes for code generation -PUGI__NS_BEGIN - struct opt_false - { - enum { value = 0 }; - }; - - struct opt_true - { - enum { value = 1 }; - }; -PUGI__NS_END - -// Unicode utilities -PUGI__NS_BEGIN - inline uint16_t endian_swap(uint16_t value) - { - return static_cast(((value & 0xff) << 8) | (value >> 8)); - } - - inline uint32_t endian_swap(uint32_t value) - { - return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); - } - - struct utf8_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) return result + 1; - // U+0080..U+07FF - else if (ch < 0x800) return result + 2; - // U+0800..U+FFFF - else return result + 3; - } - - static value_type high(value_type result, uint32_t) - { - // U+10000..U+10FFFF - return result + 4; - } - }; - - struct utf8_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) - { - *result = static_cast(ch); - return result + 1; - } - // U+0080..U+07FF - else if (ch < 0x800) - { - result[0] = static_cast(0xC0 | (ch >> 6)); - result[1] = static_cast(0x80 | (ch & 0x3F)); - return result + 2; - } - // U+0800..U+FFFF - else - { - result[0] = static_cast(0xE0 | (ch >> 12)); - result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[2] = static_cast(0x80 | (ch & 0x3F)); - return result + 3; - } - } - - static value_type high(value_type result, uint32_t ch) - { - // U+10000..U+10FFFF - result[0] = static_cast(0xF0 | (ch >> 18)); - result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); - result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[3] = static_cast(0x80 | (ch & 0x3F)); - return result + 4; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf16_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 2; - } - }; - - struct utf16_writer - { - typedef uint16_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - uint32_t msh = static_cast(ch - 0x10000) >> 10; - uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; - - result[0] = static_cast(0xD800 + msh); - result[1] = static_cast(0xDC00 + lsh); - - return result + 2; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf32_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 1; - } - }; - - struct utf32_writer - { - typedef uint32_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type any(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - }; - - struct latin1_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch > 255 ? '?' : ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - (void)ch; - - *result = '?'; - - return result + 1; - } - }; - - struct utf8_decoder - { - typedef uint8_t type; - - template static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits) - { - const uint8_t utf8_byte_mask = 0x3f; - - while (size) - { - uint8_t lead = *data; - - // 0xxxxxxx -> U+0000..U+007F - if (lead < 0x80) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - - // process aligned single-byte (ascii) blocks - if ((reinterpret_cast(data) & 3) == 0) - { - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - while (size >= 4 && (*static_cast(static_cast(data)) & 0x80808080) == 0) - { - result = Traits::low(result, data[0]); - result = Traits::low(result, data[1]); - result = Traits::low(result, data[2]); - result = Traits::low(result, data[3]); - data += 4; - size -= 4; - } - } - } - // 110xxxxx -> U+0080..U+07FF - else if (static_cast(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); - data += 2; - size -= 2; - } - // 1110xxxx -> U+0800-U+FFFF - else if (static_cast(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); - data += 3; - size -= 3; - } - // 11110xxx -> U+10000..U+10FFFF - else if (static_cast(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) - { - result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); - data += 4; - size -= 4; - } - // 10xxxxxx or 11111xxx -> invalid - else - { - data += 1; - size -= 1; - } - } - - return result; - } - }; - - template struct utf16_decoder - { - typedef uint16_t type; - - template static inline typename Traits::value_type process(const uint16_t* data, size_t size, typename Traits::value_type result, Traits) - { - while (size) - { - uint16_t lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+D7FF - if (lead < 0xD800) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - } - // U+E000..U+FFFF - else if (static_cast(lead - 0xE000) < 0x2000) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - } - // surrogate pair lead - else if (static_cast(lead - 0xD800) < 0x400 && size >= 2) - { - uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; - - if (static_cast(next - 0xDC00) < 0x400) - { - result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); - data += 2; - size -= 2; - } - else - { - data += 1; - size -= 1; - } - } - else - { - data += 1; - size -= 1; - } - } - - return result; - } - }; - - template struct utf32_decoder - { - typedef uint32_t type; - - template static inline typename Traits::value_type process(const uint32_t* data, size_t size, typename Traits::value_type result, Traits) - { - while (size) - { - uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+FFFF - if (lead < 0x10000) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - } - // U+10000..U+10FFFF - else - { - result = Traits::high(result, lead); - data += 1; - size -= 1; - } - } - - return result; - } - }; - - struct latin1_decoder - { - typedef uint8_t type; - - template static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits) - { - while (size) - { - result = Traits::low(result, *data); - data += 1; - size -= 1; - } - - return result; - } - }; - - template struct wchar_selector; - - template <> struct wchar_selector<2> - { - typedef uint16_t type; - typedef utf16_counter counter; - typedef utf16_writer writer; - typedef utf16_decoder decoder; - }; - - template <> struct wchar_selector<4> - { - typedef uint32_t type; - typedef utf32_counter counter; - typedef utf32_writer writer; - typedef utf32_decoder decoder; - }; - - typedef wchar_selector::counter wchar_counter; - typedef wchar_selector::writer wchar_writer; - - struct wchar_decoder - { - typedef wchar_t type; - - template static inline typename Traits::value_type process(const wchar_t* data, size_t size, typename Traits::value_type result, Traits traits) - { - typedef wchar_selector::decoder decoder; - - return decoder::process(reinterpret_cast(data), size, result, traits); - } - }; - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) - { - for (size_t i = 0; i < length; ++i) - result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); - } -#endif -PUGI__NS_END - -PUGI__NS_BEGIN - enum chartype_t - { - ct_parse_pcdata = 1, // \0, &, \r, < - ct_parse_attr = 2, // \0, &, \r, ', " - ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab - ct_space = 8, // \r, \n, space, tab - ct_parse_cdata = 16, // \0, ], >, \r - ct_parse_comment = 32, // \0, -, >, \r - ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . - ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : - }; - - static const unsigned char chartype_table[256] = - { - 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 - - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 - }; - - enum chartypex_t - { - ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > - ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " - ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ - ctx_digit = 8, // 0-9 - ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . - }; - - static const unsigned char chartypex_table[256] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 - 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 - - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 - - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 - }; - -#ifdef PUGIXML_WCHAR_MODE - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) -#else - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) -#endif - - #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) - #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) - - PUGI__FN bool is_little_endian() - { - unsigned int ui = 1; - - return *reinterpret_cast(&ui) == 1; - } - - PUGI__FN xml_encoding get_wchar_encoding() - { - PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); - - if (sizeof(wchar_t) == 2) - return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - else - return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - } - - PUGI__FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length) - { - #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; } - #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; } - - // check if we have a non-empty XML declaration - if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI__IS_CHARTYPE(data[5], ct_space))) - return false; - - // scan XML declaration until the encoding field - for (size_t i = 6; i + 1 < size; ++i) - { - // declaration can not contain ? in quoted values - if (data[i] == '?') - return false; - - if (data[i] == 'e' && data[i + 1] == 'n') - { - size_t offset = i; - - // encoding follows the version field which can't contain 'en' so this has to be the encoding if XML is well formed - PUGI__SCANCHAR('e'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('c'); PUGI__SCANCHAR('o'); - PUGI__SCANCHAR('d'); PUGI__SCANCHAR('i'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('g'); - - // S? = S? - PUGI__SCANCHARTYPE(ct_space); - PUGI__SCANCHAR('='); - PUGI__SCANCHARTYPE(ct_space); - - // the only two valid delimiters are ' and " - uint8_t delimiter = (offset < size && data[offset] == '"') ? '"' : '\''; - - PUGI__SCANCHAR(delimiter); - - size_t start = offset; - - out_encoding = data + offset; - - PUGI__SCANCHARTYPE(ct_symbol); - - out_length = offset - start; - - PUGI__SCANCHAR(delimiter); - - return true; - } - } - - return false; - - #undef PUGI__SCANCHAR - #undef PUGI__SCANCHARTYPE - } - - PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size) - { - // skip encoding autodetection if input buffer is too small - if (size < 4) return encoding_utf8; - - uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; - - // look for BOM in first few bytes - if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; - if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; - if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; - if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; - if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; - - // look for <, (contents); - - return guess_buffer_encoding(data, size); - } - - PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - size_t length = size / sizeof(char_t); - - if (is_mutable) - { - out_buffer = static_cast(const_cast(contents)); - out_length = length; - } - else - { - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - if (contents) - memcpy(buffer, contents, length * sizeof(char_t)); - else - assert(length == 0); - - buffer[length] = 0; - - out_buffer = buffer; - out_length = length + 1; - } - - return true; - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) - { - return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || - (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); - } - - PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const char_t* data = static_cast(contents); - size_t length = size / sizeof(char_t); - - if (is_mutable) - { - char_t* buffer = const_cast(data); - - convert_wchar_endian_swap(buffer, data, length); - - out_buffer = buffer; - out_length = length; - } - else - { - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - convert_wchar_endian_swap(buffer, data, length); - buffer[length] = 0; - - out_buffer = buffer; - out_length = length + 1; - } - - return true; - } - - template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) - { - const typename D::type* data = static_cast(contents); - size_t data_length = size / sizeof(typename D::type); - - // first pass: get length in wchar_t units - size_t length = D::process(data, data_length, 0, wchar_counter()); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf16 input to wchar_t - wchar_writer::value_type obegin = reinterpret_cast(buffer); - wchar_writer::value_type oend = D::process(data, data_length, obegin, wchar_writer()); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // get native encoding - xml_encoding wchar_encoding = get_wchar_encoding(); - - // fast path: no conversion required - if (encoding == wchar_encoding) - return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // only endian-swapping is required - if (need_endian_swap_utf(encoding, wchar_encoding)) - return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf8 - if (encoding == encoding_utf8) - return convert_buffer_generic(out_buffer, out_length, contents, size, utf8_decoder()); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()) : - convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()) : - convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) - return convert_buffer_generic(out_buffer, out_length, contents, size, latin1_decoder()); - - assert(false && "Invalid encoding"); - return false; - } -#else - template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) - { - const typename D::type* data = static_cast(contents); - size_t data_length = size / sizeof(typename D::type); - - // first pass: get length in utf8 units - size_t length = D::process(data, data_length, 0, utf8_counter()); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf16 input to utf8 - uint8_t* obegin = reinterpret_cast(buffer); - uint8_t* oend = D::process(data, data_length, obegin, utf8_writer()); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) - { - for (size_t i = 0; i < size; ++i) - if (data[i] > 127) - return i; - - return size; - } - - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const uint8_t* data = static_cast(contents); - size_t data_length = size; - - // get size of prefix that does not need utf8 conversion - size_t prefix_length = get_latin1_7bit_prefix_length(data, data_length); - assert(prefix_length <= data_length); - - const uint8_t* postfix = data + prefix_length; - size_t postfix_length = data_length - prefix_length; - - // if no conversion is needed, just return the original buffer - if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // first pass: get length in utf8 units - size_t length = prefix_length + latin1_decoder::process(postfix, postfix_length, 0, utf8_counter()); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert latin1 input to utf8 - memcpy(buffer, data, prefix_length); - - uint8_t* obegin = reinterpret_cast(buffer); - uint8_t* oend = latin1_decoder::process(postfix, postfix_length, obegin + prefix_length, utf8_writer()); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // fast path: no conversion required - if (encoding == encoding_utf8) - return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()) : - convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()) : - convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) - return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); - - assert(false && "Invalid encoding"); - return false; - } -#endif - - PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) - { - // get length in utf8 characters - return wchar_decoder::process(str, length, 0, utf8_counter()); - } - - PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) - { - // convert to utf8 - uint8_t* begin = reinterpret_cast(buffer); - uint8_t* end = wchar_decoder::process(str, length, begin, utf8_writer()); - - assert(begin + size == end); - (void)!end; - (void)!size; - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) - { - // first pass: get length in utf8 characters - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - std::string result; - result.resize(size); - - // second pass: convert to utf8 - if (size > 0) as_utf8_end(&result[0], size, str, length); - - return result; - } - - PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) - { - const uint8_t* data = reinterpret_cast(str); - - // first pass: get length in wchar_t units - size_t length = utf8_decoder::process(data, size, 0, wchar_counter()); - - // allocate resulting string - std::basic_string result; - result.resize(length); - - // second pass: convert to wchar_t - if (length > 0) - { - wchar_writer::value_type begin = reinterpret_cast(&result[0]); - wchar_writer::value_type end = utf8_decoder::process(data, size, begin, wchar_writer()); - - assert(begin + length == end); - (void)!end; - } - - return result; - } -#endif - - template - inline bool strcpy_insitu_allow(size_t length, const Header& header, uintptr_t header_mask, char_t* target) - { - // never reuse shared memory - if (header & xml_memory_page_contents_shared_mask) return false; - - size_t target_length = strlength(target); - - // always reuse document buffer memory if possible - if ((header & header_mask) == 0) return target_length >= length; - - // reuse heap memory if waste is not too great - const size_t reuse_threshold = 32; - - return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); - } - - template - PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask, const char_t* source, size_t source_length) - { - if (source_length == 0) - { - // empty string and null pointer are equivalent, so just deallocate old memory - xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; - - if (header & header_mask) alloc->deallocate_string(dest); - - // mark the string as not allocated - dest = 0; - header &= ~header_mask; - - return true; - } - else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest)) - { - // we can reuse old buffer, so just copy the new data (including zero terminator) - memcpy(dest, source, source_length * sizeof(char_t)); - dest[source_length] = 0; - - return true; - } - else - { - xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; - - if (!alloc->reserve()) return false; - - // allocate new buffer - char_t* buf = alloc->allocate_string(source_length + 1); - if (!buf) return false; - - // copy the string (including zero terminator) - memcpy(buf, source, source_length * sizeof(char_t)); - buf[source_length] = 0; - - // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) - if (header & header_mask) alloc->deallocate_string(dest); - - // the string is now allocated, so set the flag - dest = buf; - header |= header_mask; - - return true; - } - } - - struct gap - { - char_t* end; - size_t size; - - gap(): end(0), size(0) - { - } - - // Push new gap, move s count bytes further (skipping the gap). - // Collapse previous gap. - void push(char_t*& s, size_t count) - { - if (end) // there was a gap already; collapse it - { - // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - } - - s += count; // end of current gap - - // "merge" two gaps - end = s; - size += count; - } - - // Collapse all gaps, return past-the-end pointer - char_t* flush(char_t* s) - { - if (end) - { - // Move [old_gap_end, current_pos) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - - return s - size; - } - else return s; - } - }; - - PUGI__FN char_t* strconv_escape(char_t* s, gap& g) - { - char_t* stre = s + 1; - - switch (*stre) - { - case '#': // &#... - { - unsigned int ucsc = 0; - - if (stre[1] == 'x') // &#x... (hex code) - { - stre += 2; - - char_t ch = *stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(ch - '0') <= 9) - ucsc = 16 * ucsc + (ch - '0'); - else if (static_cast((ch | ' ') - 'a') <= 5) - ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - else // &#... (dec code) - { - char_t ch = *++stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(static_cast(ch) - '0') <= 9) - ucsc = 10 * ucsc + (ch - '0'); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - - #ifdef PUGIXML_WCHAR_MODE - s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); - #else - s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); - #endif - - g.push(s, stre - s); - return stre; - } - - case 'a': // &a - { - ++stre; - - if (*stre == 'm') // &am - { - if (*++stre == 'p' && *++stre == ';') // & - { - *s++ = '&'; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - else if (*stre == 'p') // &ap - { - if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' - { - *s++ = '\''; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - break; - } - - case 'g': // &g - { - if (*++stre == 't' && *++stre == ';') // > - { - *s++ = '>'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'l': // &l - { - if (*++stre == 't' && *++stre == ';') // < - { - *s++ = '<'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'q': // &q - { - if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " - { - *s++ = '"'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - default: - break; - } - - return stre; - } - - // Parser utilities - #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) - #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } - #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) - #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } - #define PUGI__POPNODE() { cursor = cursor->parent; } - #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } - #define PUGI__SCANWHILE(X) { while (X) ++s; } - #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } } - #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } - #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) - #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } - - PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here - { - *g.flush(s) = 0; - - return s + (s[2] == '>' ? 3 : 2); - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - typedef char_t* (*strconv_pcdata_t)(char_t*); - - template struct strconv_pcdata_impl - { - static char_t* parse(char_t* s) - { - gap g; - - char_t* begin = s; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata)); - - if (*s == '<') // PCDATA ends here - { - char_t* end = g.flush(s); - - if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) - --end; - - *end = 0; - - return s + 1; - } - else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (*s == 0) - { - char_t* end = g.flush(s); - - if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) - --end; - - *end = 0; - - return s; - } - else ++s; - } - } - }; - - PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); - - switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim) - { - case 0: return strconv_pcdata_impl::parse; - case 1: return strconv_pcdata_impl::parse; - case 2: return strconv_pcdata_impl::parse; - case 3: return strconv_pcdata_impl::parse; - case 4: return strconv_pcdata_impl::parse; - case 5: return strconv_pcdata_impl::parse; - case 6: return strconv_pcdata_impl::parse; - case 7: return strconv_pcdata_impl::parse; - default: assert(false); return 0; // should not get here - } - } - - typedef char_t* (*strconv_attribute_t)(char_t*, char_t); - - template struct strconv_attribute_impl - { - static char_t* parse_wnorm(char_t* s, char_t end_quote) - { - gap g; - - // trim leading whitespaces - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s; - - do ++str; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - g.push(s, str - s); - } - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); - - if (*s == end_quote) - { - char_t* str = g.flush(s); - - do *str-- = 0; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - *s++ = ' '; - - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s + 1; - while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; - - g.push(s, str - s); - } - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_wconv(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - if (*s == '\r') - { - *s++ = ' '; - - if (*s == '\n') g.push(s, 1); - } - else *s++ = ' '; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_eol(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == '\r') - { - *s++ = '\n'; - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_simple(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - }; - - PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); - - switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) - { - case 0: return strconv_attribute_impl::parse_simple; - case 1: return strconv_attribute_impl::parse_simple; - case 2: return strconv_attribute_impl::parse_eol; - case 3: return strconv_attribute_impl::parse_eol; - case 4: return strconv_attribute_impl::parse_wconv; - case 5: return strconv_attribute_impl::parse_wconv; - case 6: return strconv_attribute_impl::parse_wconv; - case 7: return strconv_attribute_impl::parse_wconv; - case 8: return strconv_attribute_impl::parse_wnorm; - case 9: return strconv_attribute_impl::parse_wnorm; - case 10: return strconv_attribute_impl::parse_wnorm; - case 11: return strconv_attribute_impl::parse_wnorm; - case 12: return strconv_attribute_impl::parse_wnorm; - case 13: return strconv_attribute_impl::parse_wnorm; - case 14: return strconv_attribute_impl::parse_wnorm; - case 15: return strconv_attribute_impl::parse_wnorm; - default: assert(false); return 0; // should not get here - } - } - - inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) - { - xml_parse_result result; - result.status = status; - result.offset = offset; - - return result; - } - - struct xml_parser - { - xml_allocator* alloc; - char_t* error_offset; - xml_parse_status error_status; - - xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) - { - } - - // DOCTYPE consists of nested sections of the following possible types: - // , , "...", '...' - // - // - // First group can not contain nested groups - // Second group can contain nested groups of the same type - // Third group can contain all other groups - char_t* parse_doctype_primitive(char_t* s) - { - if (*s == '"' || *s == '\'') - { - // quoted string - char_t ch = *s++; - PUGI__SCANFOR(*s == ch); - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s++; - } - else if (s[0] == '<' && s[1] == '?') - { - // - s += 2; - PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 2; - } - else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') - { - s += 4; - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 3; - } - else PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_doctype_ignore(char_t* s) - { - size_t depth = 0; - - assert(s[0] == '<' && s[1] == '!' && s[2] == '['); - s += 3; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] == '[') - { - // nested ignore section - s += 3; - depth++; - } - else if (s[0] == ']' && s[1] == ']' && s[2] == '>') - { - // ignore section end - s += 3; - - if (depth == 0) - return s; - - depth--; - } - else s++; - } - - PUGI__THROW_ERROR(status_bad_doctype, s); - } - - char_t* parse_doctype_group(char_t* s, char_t endch) - { - size_t depth = 0; - - assert((s[0] == '<' || s[0] == 0) && s[1] == '!'); - s += 2; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] != '-') - { - if (s[2] == '[') - { - // ignore - s = parse_doctype_ignore(s); - if (!s) return s; - } - else - { - // some control group - s += 2; - depth++; - } - } - else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') - { - // unknown tag (forbidden), or some primitive group - s = parse_doctype_primitive(s); - if (!s) return s; - } - else if (*s == '>') - { - if (depth == 0) - return s; - - depth--; - s++; - } - else s++; - } - - if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) - { - // parse node contents, starting with exclamation mark - ++s; - - if (*s == '-') // 'value = s; // Save the offset. - } - - if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) - { - s = strconv_comment(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); - } - else - { - // Scan for terminating '-->'. - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_comment, s); - - if (PUGI__OPTSET(parse_comments)) - *s = 0; // Zero-terminate this segment at the first terminating '-'. - - s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. - } - } - else PUGI__THROW_ERROR(status_bad_comment, s); - } - else if (*s == '[') - { - // 'value = s; // Save the offset. - - if (PUGI__OPTSET(parse_eol)) - { - s = strconv_cdata(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); - } - else - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - *s++ = 0; // Zero-terminate this segment. - } - } - else // Flagged for discard, but we still have to scan for the terminator. - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - ++s; - } - - s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. - } - else PUGI__THROW_ERROR(status_bad_cdata, s); - } - else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E')) - { - s -= 2; - - if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); - - char_t* mark = s + 9; - - s = parse_doctype_group(s, endch); - if (!s) return s; - - assert((*s == 0 && endch == '>') || *s == '>'); - if (*s) *s++ = 0; - - if (PUGI__OPTSET(parse_doctype)) - { - while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; - - PUGI__PUSHNODE(node_doctype); - - cursor->value = mark; - } - } - else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); - else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); - else PUGI__THROW_ERROR(status_unrecognized_tag, s); - - return s; - } - - char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) - { - // load into registers - xml_node_struct* cursor = ref_cursor; - char_t ch = 0; - - // parse node contents, starting with question mark - ++s; - - // read PI target - char_t* target = s; - - if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); - PUGI__CHECK_ERROR(status_bad_pi, s); - - // determine node type; stricmp / strcasecmp is not portable - bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; - - if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) - { - if (declaration) - { - // disallow non top-level declarations - if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__PUSHNODE(node_declaration); - } - else - { - PUGI__PUSHNODE(node_pi); - } - - cursor->name = target; - - PUGI__ENDSEG(); - - // parse value/attributes - if (ch == '?') - { - // empty node - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); - s += (*s == '>'); - - PUGI__POPNODE(); - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); - - // scan for tag end - char_t* value = s; - - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - if (declaration) - { - // replace ending ? with / so that 'element' terminates properly - *s = '/'; - - // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES - s = value; - } - else - { - // store value and step over > - cursor->value = value; - - PUGI__POPNODE(); - - PUGI__ENDSEG(); - - s += (*s == '>'); - } - } - else PUGI__THROW_ERROR(status_bad_pi, s); - } - else - { - // scan for tag end - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - s += (s[1] == '>' ? 2 : 1); - } - - // store from registers - ref_cursor = cursor; - - return s; - } - - char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch) - { - strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); - strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); - - char_t ch = 0; - xml_node_struct* cursor = root; - char_t* mark = s; - - while (*s != 0) - { - if (*s == '<') - { - ++s; - - LOC_TAG: - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' - { - PUGI__PUSHNODE(node_element); // Append a new node to the tree. - - cursor->name = s; - - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - - if (ch == '>') - { - // end of tag - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - LOC_ATTRIBUTES: - while (true) - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... - { - xml_attribute_struct* a = append_new_attribute(cursor, *alloc); // Make space for this attribute. - if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); - - a->name = s; // Save the offset. - - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - - if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); // Eat any whitespace. - - ch = *s; - ++s; - } - - if (ch == '=') // '<... #=...' - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (*s == '"' || *s == '\'') // '<... #="...' - { - ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. - ++s; // Step over the quote. - a->value = s; // Save the offset. - - s = strconv_attribute(s, ch); - - if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); - - // After this line the loop continues from the start; - // Whitespaces, / and > are ok, symbols and EOF are wrong, - // everything else will be detected - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else if (*s == '/') - { - ++s; - - if (*s == '>') - { - PUGI__POPNODE(); - s++; - break; - } - else if (*s == 0 && endch == '>') - { - PUGI__POPNODE(); - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '>') - { - ++s; - - break; - } - else if (*s == 0 && endch == '>') - { - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - - // !!! - } - else if (ch == '/') // '<#.../' - { - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); - - PUGI__POPNODE(); // Pop. - - s += (*s == '>'); - } - else if (ch == 0) - { - // we stepped over null terminator, backtrack & handle closing tag - --s; - - if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '/') - { - ++s; - - mark = s; - - char_t* name = cursor->name; - if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, mark); - - while (PUGI__IS_CHARTYPE(*s, ct_symbol)) - { - if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, mark); - } - - if (*name) - { - if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); - else PUGI__THROW_ERROR(status_end_element_mismatch, mark); - } - - PUGI__POPNODE(); // Pop. - - PUGI__SKIPWS(); - - if (*s == 0) - { - if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - } - else - { - if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - ++s; - } - } - else if (*s == '?') // 'first_child) continue; - } - } - - if (!PUGI__OPTSET(parse_trim_pcdata)) - s = mark; - - if (cursor->parent || PUGI__OPTSET(parse_fragment)) - { - if (PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value) - { - cursor->value = s; // Save the offset. - } - else - { - PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. - - cursor->value = s; // Save the offset. - - PUGI__POPNODE(); // Pop since this is a standalone. - } - - s = strconv_pcdata(s); - - if (!*s) break; - } - else - { - PUGI__SCANFOR(*s == '<'); // '...<' - if (!*s) break; - - ++s; - } - - // We're after '<' - goto LOC_TAG; - } - } - - // check that last tag is closed - if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s); - - return s; - } - - #ifdef PUGIXML_WCHAR_MODE - static char_t* parse_skip_bom(char_t* s) - { - unsigned int bom = 0xfeff; - return (s[0] == static_cast(bom)) ? s + 1 : s; - } - #else - static char_t* parse_skip_bom(char_t* s) - { - return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s; - } - #endif - - static bool has_element_node_siblings(xml_node_struct* node) - { - while (node) - { - if (PUGI__NODETYPE(node) == node_element) return true; - - node = node->next_sibling; - } - - return false; - } - - static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk) - { - // early-out for empty documents - if (length == 0) - return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); - - // get last child of the root before parsing - xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0; - - // create parser on stack - xml_parser parser(static_cast(xmldoc)); - - // save last character and make buffer zero-terminated (speeds up parsing) - char_t endch = buffer[length - 1]; - buffer[length - 1] = 0; - - // skip BOM to make sure it does not end up as part of parse output - char_t* buffer_data = parse_skip_bom(buffer); - - // perform actual parsing - parser.parse_tree(buffer_data, root, optmsk, endch); - - xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); - assert(result.offset >= 0 && static_cast(result.offset) <= length); - - if (result) - { - // since we removed last character, we have to handle the only possible false positive (stray <) - if (endch == '<') - return make_parse_result(status_unrecognized_tag, length - 1); - - // check if there are any element nodes parsed - xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0; - - if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) - return make_parse_result(status_no_document_element, length - 1); - } - else - { - // roll back offset if it occurs on a null terminator in the source buffer - if (result.offset > 0 && static_cast(result.offset) == length - 1 && endch == 0) - result.offset--; - } - - return result; - } - }; - - // Output facilities - PUGI__FN xml_encoding get_write_native_encoding() - { - #ifdef PUGIXML_WCHAR_MODE - return get_wchar_encoding(); - #else - return encoding_utf8; - #endif - } - - PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) - { - // replace wchar encoding with utf implementation - if (encoding == encoding_wchar) return get_wchar_encoding(); - - // replace utf16 encoding with utf16 with specific endianness - if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - // replace utf32 encoding with utf32 with specific endianness - if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - // only do autodetection if no explicit encoding is requested - if (encoding != encoding_auto) return encoding; - - // assume utf8 encoding - return encoding_utf8; - } - - template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T) - { - PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); - - typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); - - return static_cast(end - dest) * sizeof(*dest); - } - - template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T, bool opt_swap) - { - PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); - - typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); - - if (opt_swap) - { - for (typename T::value_type i = dest; i != end; ++i) - *i = endian_swap(*i); - } - - return static_cast(end - dest) * sizeof(*dest); - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - if (length < 1) return 0; - - // discard last character if it's the lead of a surrogate pair - return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; - } - - PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - // only endian-swapping is required - if (need_endian_swap_utf(encoding, get_wchar_encoding())) - { - convert_wchar_endian_swap(r_char, data, length); - - return length * sizeof(char_t); - } - - // convert to utf8 - if (encoding == encoding_utf8) - return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), utf8_writer()); - - // convert to utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return convert_buffer_output_generic(r_u16, data, length, wchar_decoder(), utf16_writer(), native_encoding != encoding); - } - - // convert to utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return convert_buffer_output_generic(r_u32, data, length, wchar_decoder(), utf32_writer(), native_encoding != encoding); - } - - // convert to latin1 - if (encoding == encoding_latin1) - return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), latin1_writer()); - - assert(false && "Invalid encoding"); - return 0; - } -#else - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - if (length < 5) return 0; - - for (size_t i = 1; i <= 4; ++i) - { - uint8_t ch = static_cast(data[length - i]); - - // either a standalone character or a leading one - if ((ch & 0xc0) != 0x80) return length - i; - } - - // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk - return length; - } - - PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return convert_buffer_output_generic(r_u16, data, length, utf8_decoder(), utf16_writer(), native_encoding != encoding); - } - - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return convert_buffer_output_generic(r_u32, data, length, utf8_decoder(), utf32_writer(), native_encoding != encoding); - } - - if (encoding == encoding_latin1) - return convert_buffer_output_generic(r_u8, data, length, utf8_decoder(), latin1_writer()); - - assert(false && "Invalid encoding"); - return 0; - } -#endif - - class xml_buffered_writer - { - xml_buffered_writer(const xml_buffered_writer&); - xml_buffered_writer& operator=(const xml_buffered_writer&); - - public: - xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) - { - PUGI__STATIC_ASSERT(bufcapacity >= 8); - } - - size_t flush() - { - flush(buffer, bufsize); - bufsize = 0; - return 0; - } - - void flush(const char_t* data, size_t size) - { - if (size == 0) return; - - // fast path, just write data - if (encoding == get_write_native_encoding()) - writer.write(data, size * sizeof(char_t)); - else - { - // convert chunk - size_t result = convert_buffer_output(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding); - assert(result <= sizeof(scratch)); - - // write data - writer.write(scratch.data_u8, result); - } - } - - void write_direct(const char_t* data, size_t length) - { - // flush the remaining buffer contents - flush(); - - // handle large chunks - if (length > bufcapacity) - { - if (encoding == get_write_native_encoding()) - { - // fast path, can just write data chunk - writer.write(data, length * sizeof(char_t)); - return; - } - - // need to convert in suitable chunks - while (length > bufcapacity) - { - // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer - // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) - size_t chunk_size = get_valid_length(data, bufcapacity); - assert(chunk_size); - - // convert chunk and write - flush(data, chunk_size); - - // iterate - data += chunk_size; - length -= chunk_size; - } - - // small tail is copied below - bufsize = 0; - } - - memcpy(buffer + bufsize, data, length * sizeof(char_t)); - bufsize += length; - } - - void write_buffer(const char_t* data, size_t length) - { - size_t offset = bufsize; - - if (offset + length <= bufcapacity) - { - memcpy(buffer + offset, data, length * sizeof(char_t)); - bufsize = offset + length; - } - else - { - write_direct(data, length); - } - } - - void write_string(const char_t* data) - { - // write the part of the string that fits in the buffer - size_t offset = bufsize; - - while (*data && offset < bufcapacity) - buffer[offset++] = *data++; - - // write the rest - if (offset < bufcapacity) - { - bufsize = offset; - } - else - { - // backtrack a bit if we have split the codepoint - size_t length = offset - bufsize; - size_t extra = length - get_valid_length(data - length, length); - - bufsize = offset - extra; - - write_direct(data - extra, strlength(data) + extra); - } - } - - void write(char_t d0) - { - size_t offset = bufsize; - if (offset > bufcapacity - 1) offset = flush(); - - buffer[offset + 0] = d0; - bufsize = offset + 1; - } - - void write(char_t d0, char_t d1) - { - size_t offset = bufsize; - if (offset > bufcapacity - 2) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - bufsize = offset + 2; - } - - void write(char_t d0, char_t d1, char_t d2) - { - size_t offset = bufsize; - if (offset > bufcapacity - 3) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - bufsize = offset + 3; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3) - { - size_t offset = bufsize; - if (offset > bufcapacity - 4) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - bufsize = offset + 4; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) - { - size_t offset = bufsize; - if (offset > bufcapacity - 5) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - buffer[offset + 4] = d4; - bufsize = offset + 5; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) - { - size_t offset = bufsize; - if (offset > bufcapacity - 6) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - buffer[offset + 4] = d4; - buffer[offset + 5] = d5; - bufsize = offset + 6; - } - - // utf8 maximum expansion: x4 (-> utf32) - // utf16 maximum expansion: x2 (-> utf32) - // utf32 maximum expansion: x1 - enum - { - bufcapacitybytes = - #ifdef PUGIXML_MEMORY_OUTPUT_STACK - PUGIXML_MEMORY_OUTPUT_STACK - #else - 10240 - #endif - , - bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4) - }; - - char_t buffer[bufcapacity]; - - union - { - uint8_t data_u8[4 * bufcapacity]; - uint16_t data_u16[2 * bufcapacity]; - uint32_t data_u32[bufcapacity]; - char_t data_char[bufcapacity]; - } scratch; - - xml_writer& writer; - size_t bufsize; - xml_encoding encoding; - }; - - PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) - { - while (*s) - { - const char_t* prev = s; - - // While *s is a usual symbol - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); - - writer.write_buffer(prev, static_cast(s - prev)); - - switch (*s) - { - case 0: break; - case '&': - writer.write('&', 'a', 'm', 'p', ';'); - ++s; - break; - case '<': - writer.write('&', 'l', 't', ';'); - ++s; - break; - case '>': - writer.write('&', 'g', 't', ';'); - ++s; - break; - case '"': - writer.write('&', 'q', 'u', 'o', 't', ';'); - ++s; - break; - default: // s is not a usual symbol - { - unsigned int ch = static_cast(*s++); - assert(ch < 32); - - writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); - } - } - } - } - - PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) - { - if (flags & format_no_escapes) - writer.write_string(s); - else - text_output_escaped(writer, s, type); - } - - PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) - { - do - { - writer.write('<', '!', '[', 'C', 'D'); - writer.write('A', 'T', 'A', '['); - - const char_t* prev = s; - - // look for ]]> sequence - we can't output it as is since it terminates CDATA - while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; - - // skip ]] if we stopped at ]]>, > will go to the next CDATA section - if (*s) s += 2; - - writer.write_buffer(prev, static_cast(s - prev)); - - writer.write(']', ']', '>'); - } - while (*s); - } - - PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) - { - switch (indent_length) - { - case 1: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0]); - break; - } - - case 2: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1]); - break; - } - - case 3: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1], indent[2]); - break; - } - - case 4: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1], indent[2], indent[3]); - break; - } - - default: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write_buffer(indent, indent_length); - } - } - } - - PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) - { - writer.write('<', '!', '-', '-'); - - while (*s) - { - const char_t* prev = s; - - // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body - while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s; - - writer.write_buffer(prev, static_cast(s - prev)); - - if (*s) - { - assert(*s == '-'); - - writer.write('-', ' '); - ++s; - } - } - - writer.write('-', '-', '>'); - } - - PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s) - { - while (*s) - { - const char_t* prev = s; - - // look for ?> sequence - we can't output it since ?> terminates PI - while (*s && !(s[0] == '?' && s[1] == '>')) ++s; - - writer.write_buffer(prev, static_cast(s - prev)); - - if (*s) - { - assert(s[0] == '?' && s[1] == '>'); - - writer.write('?', ' ', '>'); - s += 2; - } - } - } - - PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) - { - if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes) - { - writer.write('\n'); - - text_output_indent(writer, indent, indent_length, depth + 1); - } - else - { - writer.write(' '); - } - - writer.write_string(a->name ? a->name + 0 : default_name); - writer.write('=', '"'); - - if (a->value) - text_output(writer, a->value, ctx_special_attr, flags); - - writer.write('"'); - } - } - - PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - const char_t* name = node->name ? node->name + 0 : default_name; - - writer.write('<'); - writer.write_string(name); - - if (node->first_attribute) - node_output_attributes(writer, node, indent, indent_length, flags, depth); - - // element nodes can have value if parse_embed_pcdata was used - if (!node->value) - { - if (!node->first_child) - { - if (flags & format_no_empty_element_tags) - { - writer.write('>', '<', '/'); - writer.write_string(name); - writer.write('>'); - - return false; - } - else - { - if ((flags & format_raw) == 0) - writer.write(' '); - - writer.write('/', '>'); - - return false; - } - } - else - { - writer.write('>'); - - return true; - } - } - else - { - writer.write('>'); - - text_output(writer, node->value, ctx_special_pcdata, flags); - - if (!node->first_child) - { - writer.write('<', '/'); - writer.write_string(name); - writer.write('>'); - - return false; - } - else - { - return true; - } - } - } - - PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - const char_t* name = node->name ? node->name + 0 : default_name; - - writer.write('<', '/'); - writer.write_string(name); - writer.write('>'); - } - - PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - switch (PUGI__NODETYPE(node)) - { - case node_pcdata: - text_output(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags); - break; - - case node_cdata: - text_output_cdata(writer, node->value ? node->value + 0 : PUGIXML_TEXT("")); - break; - - case node_comment: - node_output_comment(writer, node->value ? node->value + 0 : PUGIXML_TEXT("")); - break; - - case node_pi: - writer.write('<', '?'); - writer.write_string(node->name ? node->name + 0 : default_name); - - if (node->value) - { - writer.write(' '); - node_output_pi_value(writer, node->value); - } - - writer.write('?', '>'); - break; - - case node_declaration: - writer.write('<', '?'); - writer.write_string(node->name ? node->name + 0 : default_name); - node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0); - writer.write('?', '>'); - break; - - case node_doctype: - writer.write('<', '!', 'D', 'O', 'C'); - writer.write('T', 'Y', 'P', 'E'); - - if (node->value) - { - writer.write(' '); - writer.write_string(node->value); - } - - writer.write('>'); - break; - - default: - assert(false && "Invalid node type"); - } - } - - enum indent_flags_t - { - indent_newline = 1, - indent_indent = 2 - }; - - PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) - { - size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0; - unsigned int indent_flags = indent_indent; - - xml_node_struct* node = root; - - do - { - assert(node); - - // begin writing current node - if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) - { - node_output_simple(writer, node, flags); - - indent_flags = 0; - } - else - { - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - - if ((indent_flags & indent_indent) && indent_length) - text_output_indent(writer, indent, indent_length, depth); - - if (PUGI__NODETYPE(node) == node_element) - { - indent_flags = indent_newline | indent_indent; - - if (node_output_start(writer, node, indent, indent_length, flags, depth)) - { - // element nodes can have value if parse_embed_pcdata was used - if (node->value) - indent_flags = 0; - - node = node->first_child; - depth++; - continue; - } - } - else if (PUGI__NODETYPE(node) == node_document) - { - indent_flags = indent_indent; - - if (node->first_child) - { - node = node->first_child; - continue; - } - } - else - { - node_output_simple(writer, node, flags); - - indent_flags = indent_newline | indent_indent; - } - } - - // continue to the next node - while (node != root) - { - if (node->next_sibling) - { - node = node->next_sibling; - break; - } - - node = node->parent; - - // write closing node - if (PUGI__NODETYPE(node) == node_element) - { - depth--; - - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - - if ((indent_flags & indent_indent) && indent_length) - text_output_indent(writer, indent, indent_length, depth); - - node_output_end(writer, node); - - indent_flags = indent_newline | indent_indent; - } - } - } - while (node != root); - - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - } - - PUGI__FN bool has_declaration(xml_node_struct* node) - { - for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) - { - xml_node_type type = PUGI__NODETYPE(child); - - if (type == node_declaration) return true; - if (type == node_element) return false; - } - - return false; - } - - PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) - { - for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) - if (a == attr) - return true; - - return false; - } - - PUGI__FN bool allow_insert_attribute(xml_node_type parent) - { - return parent == node_element || parent == node_declaration; - } - - PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child) - { - if (parent != node_document && parent != node_element) return false; - if (child == node_document || child == node_null) return false; - if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; - - return true; - } - - PUGI__FN bool allow_move(xml_node parent, xml_node child) - { - // check that child can be a child of parent - if (!allow_insert_child(parent.type(), child.type())) - return false; - - // check that node is not moved between documents - if (parent.root() != child.root()) - return false; - - // check that new parent is not in the child subtree - xml_node cur = parent; - - while (cur) - { - if (cur == child) - return false; - - cur = cur.parent(); - } - - return true; - } - - template - PUGI__FN void node_copy_string(String& dest, Header& header, uintptr_t header_mask, char_t* source, Header& source_header, xml_allocator* alloc) - { - assert(!dest && (header & header_mask) == 0); - - if (source) - { - if (alloc && (source_header & header_mask) == 0) - { - dest = source; - - // since strcpy_insitu can reuse document buffer memory we need to mark both source and dest as shared - header |= xml_memory_page_contents_shared_mask; - source_header |= xml_memory_page_contents_shared_mask; - } - else - strcpy_insitu(dest, header, header_mask, source, strlength(source)); - } - } - - PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) - { - node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); - node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); - - for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) - { - xml_attribute_struct* da = append_new_attribute(dn, get_allocator(dn)); - - if (da) - { - node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); - node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); - } - } - } - - PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) - { - xml_allocator& alloc = get_allocator(dn); - xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; - - node_copy_contents(dn, sn, shared_alloc); - - xml_node_struct* dit = dn; - xml_node_struct* sit = sn->first_child; - - while (sit && sit != sn) - { - if (sit != dn) - { - xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); - - if (copy) - { - node_copy_contents(copy, sit, shared_alloc); - - if (sit->first_child) - { - dit = copy; - sit = sit->first_child; - continue; - } - } - } - - // continue to the next node - do - { - if (sit->next_sibling) - { - sit = sit->next_sibling; - break; - } - - sit = sit->parent; - dit = dit->parent; - } - while (sit != sn); - } - } - - PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) - { - xml_allocator& alloc = get_allocator(da); - xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0; - - node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); - node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); - } - - inline bool is_text_node(xml_node_struct* node) - { - xml_node_type type = PUGI__NODETYPE(node); - - return type == node_pcdata || type == node_cdata; - } - - // get value with conversion functions - template U string_to_integer(const char_t* value, U minneg, U maxpos) - { - U result = 0; - const char_t* s = value; - - while (PUGI__IS_CHARTYPE(*s, ct_space)) - s++; - - bool negative = (*s == '-'); - - s += (*s == '+' || *s == '-'); - - bool overflow = false; - - if (s[0] == '0' && (s[1] | ' ') == 'x') - { - s += 2; - - // since overflow detection relies on length of the sequence skip leading zeros - while (*s == '0') - s++; - - const char_t* start = s; - - for (;;) - { - if (static_cast(*s - '0') < 10) - result = result * 16 + (*s - '0'); - else if (static_cast((*s | ' ') - 'a') < 6) - result = result * 16 + ((*s | ' ') - 'a' + 10); - else - break; - - s++; - } - - size_t digits = static_cast(s - start); - - overflow = digits > sizeof(U) * 2; - } - else - { - // since overflow detection relies on length of the sequence skip leading zeros - while (*s == '0') - s++; - - const char_t* start = s; - - for (;;) - { - if (static_cast(*s - '0') < 10) - result = result * 10 + (*s - '0'); - else - break; - - s++; - } - - size_t digits = static_cast(s - start); - - PUGI__STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2); - - const size_t max_digits10 = sizeof(U) == 8 ? 20 : sizeof(U) == 4 ? 10 : 5; - const char_t max_lead = sizeof(U) == 8 ? '1' : sizeof(U) == 4 ? '4' : '6'; - const size_t high_bit = sizeof(U) * 8 - 1; - - overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit))); - } - - if (negative) - return (overflow || result > minneg) ? 0 - minneg : 0 - result; - else - return (overflow || result > maxpos) ? maxpos : result; - } - - PUGI__FN int get_value_int(const char_t* value) - { - return string_to_integer(value, 0 - static_cast(INT_MIN), INT_MAX); - } - - PUGI__FN unsigned int get_value_uint(const char_t* value) - { - return string_to_integer(value, 0, UINT_MAX); - } - - PUGI__FN double get_value_double(const char_t* value) - { - #ifdef PUGIXML_WCHAR_MODE - return wcstod(value, 0); - #else - return strtod(value, 0); - #endif - } - - PUGI__FN float get_value_float(const char_t* value) - { - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstod(value, 0)); - #else - return static_cast(strtod(value, 0)); - #endif - } - - PUGI__FN bool get_value_bool(const char_t* value) - { - // only look at first char - char_t first = *value; - - // 1*, t* (true), T* (True), y* (yes), Y* (YES) - return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long get_value_llong(const char_t* value) - { - return string_to_integer(value, 0 - static_cast(LLONG_MIN), LLONG_MAX); - } - - PUGI__FN unsigned long long get_value_ullong(const char_t* value) - { - return string_to_integer(value, 0, ULLONG_MAX); - } -#endif - - template PUGI__FN char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative) - { - char_t* result = end - 1; - U rest = negative ? 0 - value : value; - - do - { - *result-- = static_cast('0' + (rest % 10)); - rest /= 10; - } - while (rest); - - assert(result >= begin); - (void)begin; - - *result = '-'; - - return result + !negative; - } - - // set value with conversion functions - template - PUGI__FN bool set_value_ascii(String& dest, Header& header, uintptr_t header_mask, char* buf) - { - #ifdef PUGIXML_WCHAR_MODE - char_t wbuf[128]; - assert(strlen(buf) < sizeof(wbuf) / sizeof(wbuf[0])); - - size_t offset = 0; - for (; buf[offset]; ++offset) wbuf[offset] = buf[offset]; - - return strcpy_insitu(dest, header, header_mask, wbuf, offset); - #else - return strcpy_insitu(dest, header, header_mask, buf, strlen(buf)); - #endif - } - - template - PUGI__FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative) - { - char_t buf[64]; - char_t* end = buf + sizeof(buf) / sizeof(buf[0]); - char_t* begin = integer_to_string(buf, end, value, negative); - - return strcpy_insitu(dest, header, header_mask, begin, end - begin); - } - - template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value) - { - char buf[128]; - sprintf(buf, "%.9g", value); - - return set_value_ascii(dest, header, header_mask, buf); - } - - template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value) - { - char buf[128]; - sprintf(buf, "%.17g", value); - - return set_value_ascii(dest, header, header_mask, buf); - } - - template - PUGI__FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value) - { - return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5); - } - - PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) - { - // check input buffer - if (!contents && size) return make_parse_result(status_io_error); - - // get actual encoding - xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); - - // get private buffer - char_t* buffer = 0; - size_t length = 0; - - if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); - - // delete original buffer if we performed a conversion - if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); - - // grab onto buffer if it's our buffer, user is responsible for deallocating contents himself - if (own || buffer != contents) *out_buffer = buffer; - - // store buffer for offset_debug - doc->buffer = buffer; - - // parse - xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options); - - // remember encoding - res.encoding = buffer_encoding; - - return res; - } - - // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick - PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) - { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) - // there are 64-bit versions of fseek/ftell, let's use them - typedef __int64 length_type; - - _fseeki64(file, 0, SEEK_END); - length_type length = _ftelli64(file); - _fseeki64(file, 0, SEEK_SET); - #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) - // there are 64-bit versions of fseek/ftell, let's use them - typedef off64_t length_type; - - fseeko64(file, 0, SEEK_END); - length_type length = ftello64(file); - fseeko64(file, 0, SEEK_SET); - #else - // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. - typedef long length_type; - - fseek(file, 0, SEEK_END); - length_type length = ftell(file); - fseek(file, 0, SEEK_SET); - #endif - - // check for I/O errors - if (length < 0) return status_io_error; - - // check for overflow - size_t result = static_cast(length); - - if (static_cast(result) != length) return status_out_of_memory; - - // finalize - out_result = result; - - return status_ok; - } - - // This function assumes that buffer has extra sizeof(char_t) writable bytes after size - PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) - { - // We only need to zero-terminate if encoding conversion does not do it for us - #ifdef PUGIXML_WCHAR_MODE - xml_encoding wchar_encoding = get_wchar_encoding(); - - if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding)) - { - size_t length = size / sizeof(char_t); - - static_cast(buffer)[length] = 0; - return (length + 1) * sizeof(char_t); - } - #else - if (encoding == encoding_utf8) - { - static_cast(buffer)[size] = 0; - return size + 1; - } - #endif - - return size; - } - - PUGI__FN xml_parse_result load_file_impl(xml_document_struct* doc, FILE* file, unsigned int options, xml_encoding encoding, char_t** out_buffer) - { - if (!file) return make_parse_result(status_file_not_found); - - // get file size (can result in I/O errors) - size_t size = 0; - xml_parse_status size_status = get_file_size(file, size); - if (size_status != status_ok) return make_parse_result(size_status); - - size_t max_suffix_size = sizeof(char_t); - - // allocate buffer for the whole file - char* contents = static_cast(xml_memory::allocate(size + max_suffix_size)); - if (!contents) return make_parse_result(status_out_of_memory); - - // read file in memory - size_t read_size = fread(contents, 1, size, file); - - if (read_size != size) - { - xml_memory::deallocate(contents); - return make_parse_result(status_io_error); - } - - xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size); - - return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer); - } - - PUGI__FN void close_file(FILE* file) - { - fclose(file); - } - -#ifndef PUGIXML_NO_STL - template struct xml_stream_chunk - { - static xml_stream_chunk* create() - { - void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); - if (!memory) return 0; - - return new (memory) xml_stream_chunk(); - } - - static void destroy(xml_stream_chunk* chunk) - { - // free chunk chain - while (chunk) - { - xml_stream_chunk* next_ = chunk->next; - - xml_memory::deallocate(chunk); - - chunk = next_; - } - } - - xml_stream_chunk(): next(0), size(0) - { - } - - xml_stream_chunk* next; - size_t size; - - T data[xml_memory_page_size / sizeof(T)]; - }; - - template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - auto_deleter > chunks(0, xml_stream_chunk::destroy); - - // read file to a chunk list - size_t total = 0; - xml_stream_chunk* last = 0; - - while (!stream.eof()) - { - // allocate new chunk - xml_stream_chunk* chunk = xml_stream_chunk::create(); - if (!chunk) return status_out_of_memory; - - // append chunk to list - if (last) last = last->next = chunk; - else chunks.data = last = chunk; - - // read data to chunk - stream.read(chunk->data, static_cast(sizeof(chunk->data) / sizeof(T))); - chunk->size = static_cast(stream.gcount()) * sizeof(T); - - // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // guard against huge files (chunk size is small enough to make this overflow check work) - if (total + chunk->size < total) return status_out_of_memory; - total += chunk->size; - } - - size_t max_suffix_size = sizeof(char_t); - - // copy chunk list to a contiguous buffer - char* buffer = static_cast(xml_memory::allocate(total + max_suffix_size)); - if (!buffer) return status_out_of_memory; - - char* write = buffer; - - for (xml_stream_chunk* chunk = chunks.data; chunk; chunk = chunk->next) - { - assert(write + chunk->size <= buffer + total); - memcpy(write, chunk->data, chunk->size); - write += chunk->size; - } - - assert(write == buffer + total); - - // return buffer - *out_buffer = buffer; - *out_size = total; - - return status_ok; - } - - template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - // get length of remaining data in stream - typename std::basic_istream::pos_type pos = stream.tellg(); - stream.seekg(0, std::ios::end); - std::streamoff length = stream.tellg() - pos; - stream.seekg(pos); - - if (stream.fail() || pos < 0) return status_io_error; - - // guard against huge files - size_t read_length = static_cast(length); - - if (static_cast(read_length) != length || length < 0) return status_out_of_memory; - - size_t max_suffix_size = sizeof(char_t); - - // read stream data into memory (guard against stream exceptions with buffer holder) - auto_deleter buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate); - if (!buffer.data) return status_out_of_memory; - - stream.read(static_cast(buffer.data), static_cast(read_length)); - - // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // return buffer - size_t actual_length = static_cast(stream.gcount()); - assert(actual_length <= read_length); - - *out_buffer = buffer.release(); - *out_size = actual_length * sizeof(T); - - return status_ok; - } - - template PUGI__FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) - { - void* buffer = 0; - size_t size = 0; - xml_parse_status status = status_ok; - - // if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits) - if (stream.fail()) return make_parse_result(status_io_error); - - // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory) - if (stream.tellg() < 0) - { - stream.clear(); // clear error flags that could be set by a failing tellg - status = load_stream_data_noseek(stream, &buffer, &size); - } - else - status = load_stream_data_seek(stream, &buffer, &size); - - if (status != status_ok) return make_parse_result(status); - - xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size); - - return load_buffer_impl(doc, doc, buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding, true, true, out_buffer); - } -#endif - -#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - return _wfopen(path, mode); - } -#else - PUGI__FN char* convert_path_heap(const wchar_t* str) - { - assert(str); - - // first pass: get length in utf8 characters - size_t length = strlength_wide(str); - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - char* result = static_cast(xml_memory::allocate(size + 1)); - if (!result) return 0; - - // second pass: convert to utf8 - as_utf8_end(result, size, str, length); - - // zero-terminate - result[size] = 0; - - return result; - } - - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - // there is no standard function to open wide paths, so our best bet is to try utf8 path - char* path_utf8 = convert_path_heap(path); - if (!path_utf8) return 0; - - // convert mode to ASCII (we mirror _wfopen interface) - char mode_ascii[4] = {0}; - for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); - - // try to open the utf8 path - FILE* result = fopen(path_utf8, mode_ascii); - - // free dummy buffer - xml_memory::deallocate(path_utf8); - - return result; - } -#endif - - PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) - { - if (!file) return false; - - xml_writer_file writer(file); - doc.save(writer, indent, flags, encoding); - - return ferror(file) == 0; - } - - struct name_null_sentry - { - xml_node_struct* node; - char_t* name; - - name_null_sentry(xml_node_struct* node_): node(node_), name(node_->name) - { - node->name = 0; - } - - ~name_null_sentry() - { - node->name = name; - } - }; -PUGI__NS_END - -namespace pugi -{ - PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) - { - } - - PUGI__FN void xml_writer_file::write(const void* data, size_t size) - { - size_t result = fwrite(data, 1, size, static_cast(file)); - (void)!result; // unfortunately we can't do proper error handling here - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) - { - } - - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) - { - } - - PUGI__FN void xml_writer_stream::write(const void* data, size_t size) - { - if (narrow_stream) - { - assert(!wide_stream); - narrow_stream->write(reinterpret_cast(data), static_cast(size)); - } - else - { - assert(wide_stream); - assert(size % sizeof(wchar_t) == 0); - - wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); - } - } -#endif - - PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) - { - } - - PUGI__FN xml_tree_walker::~xml_tree_walker() - { - } - - PUGI__FN int xml_tree_walker::depth() const - { - return _depth; - } - - PUGI__FN bool xml_tree_walker::begin(xml_node&) - { - return true; - } - - PUGI__FN bool xml_tree_walker::end(xml_node&) - { - return true; - } - - PUGI__FN xml_attribute::xml_attribute(): _attr(0) - { - } - - PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) - { - } - - PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) - { - } - - PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const - { - return _attr ? unspecified_bool_xml_attribute : 0; - } - - PUGI__FN bool xml_attribute::operator!() const - { - return !_attr; - } - - PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const - { - return (_attr == r._attr); - } - - PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const - { - return (_attr != r._attr); - } - - PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const - { - return (_attr < r._attr); - } - - PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const - { - return (_attr > r._attr); - } - - PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const - { - return (_attr <= r._attr); - } - - PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const - { - return (_attr >= r._attr); - } - - PUGI__FN xml_attribute xml_attribute::next_attribute() const - { - return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_attribute::previous_attribute() const - { - return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const - { - return (_attr && _attr->value) ? _attr->value + 0 : def; - } - - PUGI__FN int xml_attribute::as_int(int def) const - { - return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def; - } - - PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const - { - return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def; - } - - PUGI__FN double xml_attribute::as_double(double def) const - { - return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def; - } - - PUGI__FN float xml_attribute::as_float(float def) const - { - return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def; - } - - PUGI__FN bool xml_attribute::as_bool(bool def) const - { - return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_attribute::as_llong(long long def) const - { - return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def; - } - - PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const - { - return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def; - } -#endif - - PUGI__FN bool xml_attribute::empty() const - { - return !_attr; - } - - PUGI__FN const char_t* xml_attribute::name() const - { - return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_attribute::value() const - { - return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT(""); - } - - PUGI__FN size_t xml_attribute::hash_value() const - { - return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); - } - - PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const - { - return _attr; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(long rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) - { - set_value(rhs); - return *this; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) - { - set_value(rhs); - return *this; - } -#endif - - PUGI__FN bool xml_attribute::set_name(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); - } - - PUGI__FN bool xml_attribute::set_value(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); - } - - PUGI__FN bool xml_attribute::set_value(int rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); - } - - PUGI__FN bool xml_attribute::set_value(unsigned int rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); - } - - PUGI__FN bool xml_attribute::set_value(long rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); - } - - PUGI__FN bool xml_attribute::set_value(unsigned long rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); - } - - PUGI__FN bool xml_attribute::set_value(double rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(float rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(bool rhs) - { - if (!_attr) return false; - - return impl::set_value_bool(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_attribute::set_value(long long rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); - } - - PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) - { - if (!_attr) return false; - - return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); - } -#endif - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node::xml_node(): _root(0) - { - } - - PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) - { - } - - PUGI__FN static void unspecified_bool_xml_node(xml_node***) - { - } - - PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const - { - return _root ? unspecified_bool_xml_node : 0; - } - - PUGI__FN bool xml_node::operator!() const - { - return !_root; - } - - PUGI__FN xml_node::iterator xml_node::begin() const - { - return iterator(_root ? _root->first_child + 0 : 0, _root); - } - - PUGI__FN xml_node::iterator xml_node::end() const - { - return iterator(0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const - { - return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const - { - return attribute_iterator(0, _root); - } - - PUGI__FN xml_object_range xml_node::children() const - { - return xml_object_range(begin(), end()); - } - - PUGI__FN xml_object_range xml_node::children(const char_t* name_) const - { - return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); - } - - PUGI__FN xml_object_range xml_node::attributes() const - { - return xml_object_range(attributes_begin(), attributes_end()); - } - - PUGI__FN bool xml_node::operator==(const xml_node& r) const - { - return (_root == r._root); - } - - PUGI__FN bool xml_node::operator!=(const xml_node& r) const - { - return (_root != r._root); - } - - PUGI__FN bool xml_node::operator<(const xml_node& r) const - { - return (_root < r._root); - } - - PUGI__FN bool xml_node::operator>(const xml_node& r) const - { - return (_root > r._root); - } - - PUGI__FN bool xml_node::operator<=(const xml_node& r) const - { - return (_root <= r._root); - } - - PUGI__FN bool xml_node::operator>=(const xml_node& r) const - { - return (_root >= r._root); - } - - PUGI__FN bool xml_node::empty() const - { - return !_root; - } - - PUGI__FN const char_t* xml_node::name() const - { - return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node_type xml_node::type() const - { - return _root ? PUGI__NODETYPE(_root) : node_null; - } - - PUGI__FN const char_t* xml_node::value() const - { - return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node xml_node::child(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) - return xml_attribute(i); - - return xml_attribute(); - } - - PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_node xml_node::next_sibling() const - { - return _root ? xml_node(_root->next_sibling) : xml_node(); - } - - PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const - { - xml_attribute_struct* hint = hint_._attr; - - // if hint is not an attribute of node, behavior is not defined - assert(!hint || (_root && impl::is_attribute_of(hint, _root))); - - if (!_root) return xml_attribute(); - - // optimistically search from hint up until the end - for (xml_attribute_struct* i = hint; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) - { - // update hint to maximize efficiency of searching for consecutive attributes - hint_._attr = i->next_attribute; - - return xml_attribute(i); - } - - // wrap around and search from the first attribute until the hint - // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails - for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) - if (j->name && impl::strequal(name_, j->name)) - { - // update hint to maximize efficiency of searching for consecutive attributes - hint_._attr = j->next_attribute; - - return xml_attribute(j); - } - - return xml_attribute(); - } - - PUGI__FN xml_node xml_node::previous_sibling() const - { - if (!_root) return xml_node(); - - if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); - else return xml_node(); - } - - PUGI__FN xml_node xml_node::parent() const - { - return _root ? xml_node(_root->parent) : xml_node(); - } - - PUGI__FN xml_node xml_node::root() const - { - return _root ? xml_node(&impl::get_document(_root)) : xml_node(); - } - - PUGI__FN xml_text xml_node::text() const - { - return xml_text(_root); - } - - PUGI__FN const char_t* xml_node::child_value() const - { - if (!_root) return PUGIXML_TEXT(""); - - // element nodes can have value if parse_embed_pcdata was used - if (PUGI__NODETYPE(_root) == node_element && _root->value) - return _root->value; - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (impl::is_text_node(i) && i->value) - return i->value; - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const - { - return child(name_).child_value(); - } - - PUGI__FN xml_attribute xml_node::first_attribute() const - { - return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_node::last_attribute() const - { - return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN xml_node xml_node::first_child() const - { - return _root ? xml_node(_root->first_child) : xml_node(); - } - - PUGI__FN xml_node xml_node::last_child() const - { - return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); - } - - PUGI__FN bool xml_node::set_name(const char_t* rhs) - { - xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; - - if (type_ != node_element && type_ != node_pi && type_ != node_declaration) - return false; - - return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); - } - - PUGI__FN bool xml_node::set_value(const char_t* rhs) - { - xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; - - if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) - return false; - - return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); - } - - PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::append_attribute(a._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::prepend_attribute(a._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::insert_attribute_after(a._attr, attr._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::insert_attribute_before(a._attr, attr._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::append_attribute(a._attr, _root); - impl::node_copy_attribute(a._attr, proto._attr); - - return a; - } - - PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::prepend_attribute(a._attr, _root); - impl::node_copy_attribute(a._attr, proto._attr); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::insert_attribute_after(a._attr, attr._attr, _root); - impl::node_copy_attribute(a._attr, proto._attr); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(alloc)); - if (!a) return xml_attribute(); - - impl::insert_attribute_before(a._attr, attr._attr, _root); - impl::node_copy_attribute(a._attr, proto._attr); - - return a; - } - - PUGI__FN xml_node xml_node::append_child(xml_node_type type_) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::append_node(n._root, _root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::prepend_node(n._root, _root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::insert_node_before(n._root, node._root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::insert_node_after(n._root, node._root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::append_child(const char_t* name_) - { - xml_node result = append_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) - { - xml_node result = prepend_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_after(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_before(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::append_node(n._root, _root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::prepend_node(n._root, _root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::insert_node_after(n._root, node._root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - xml_node n(impl::allocate_node(alloc, type_)); - if (!n) return xml_node(); - - impl::insert_node_before(n._root, node._root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::append_move(const xml_node& moved) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::append_node(moved._root, _root); - - return moved; - } - - PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::prepend_node(moved._root, _root); - - return moved; - } - - PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - if (moved._root == node._root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::insert_node_after(moved._root, node._root); - - return moved; - } - - PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - if (moved._root == node._root) return xml_node(); - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::insert_node_before(moved._root, node._root); - - return moved; - } - - PUGI__FN bool xml_node::remove_attribute(const char_t* name_) - { - return remove_attribute(attribute(name_)); - } - - PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) - { - if (!_root || !a._attr) return false; - if (!impl::is_attribute_of(a._attr, _root)) return false; - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return false; - - impl::remove_attribute(a._attr, _root); - impl::destroy_attribute(a._attr, alloc); - - return true; - } - - PUGI__FN bool xml_node::remove_child(const char_t* name_) - { - return remove_child(child(name_)); - } - - PUGI__FN bool xml_node::remove_child(const xml_node& n) - { - if (!_root || !n._root || n._root->parent != _root) return false; - - impl::xml_allocator& alloc = impl::get_allocator(_root); - if (!alloc.reserve()) return false; - - impl::remove_node(n._root); - impl::destroy_node(n._root, alloc); - - return true; - } - - PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - // append_buffer is only valid for elements/documents - if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); - - // get document node - impl::xml_document_struct* doc = &impl::get_document(_root); - - // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense - doc->header |= impl::xml_memory_page_contents_shared_mask; - - // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) - impl::xml_memory_page* page = 0; - impl::xml_extra_buffer* extra = static_cast(doc->allocate_memory(sizeof(impl::xml_extra_buffer), page)); - (void)page; - - if (!extra) return impl::make_parse_result(status_out_of_memory); - - // add extra buffer to the list - extra->buffer = 0; - extra->next = doc->extra_buffers; - doc->extra_buffers = extra; - - // name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level - impl::name_null_sentry sentry(_root); - - return impl::load_buffer_impl(doc, _root, const_cast(contents), size, options, encoding, false, false, &extra->buffer); - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) - { - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); - } - - return xml_node(); - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN string_t xml_node::path(char_t delimiter) const - { - if (!_root) return string_t(); - - size_t offset = 0; - - for (xml_node_struct* i = _root; i; i = i->parent) - { - offset += (i != _root); - offset += i->name ? impl::strlength(i->name) : 0; - } - - string_t result; - result.resize(offset); - - for (xml_node_struct* j = _root; j; j = j->parent) - { - if (j != _root) - result[--offset] = delimiter; - - if (j->name && *j->name) - { - size_t length = impl::strlength(j->name); - - offset -= length; - memcpy(&result[offset], j->name, length * sizeof(char_t)); - } - } - - assert(offset == 0); - - return result; - } -#endif - - PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const - { - xml_node found = *this; // Current search context. - - if (!_root || !path_ || !path_[0]) return found; - - if (path_[0] == delimiter) - { - // Absolute path; e.g. '/foo/bar' - found = found.root(); - ++path_; - } - - const char_t* path_segment = path_; - - while (*path_segment == delimiter) ++path_segment; - - const char_t* path_segment_end = path_segment; - - while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; - - if (path_segment == path_segment_end) return found; - - const char_t* next_segment = path_segment_end; - - while (*next_segment == delimiter) ++next_segment; - - if (*path_segment == '.' && path_segment + 1 == path_segment_end) - return found.first_element_by_path(next_segment, delimiter); - else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) - return found.parent().first_element_by_path(next_segment, delimiter); - else - { - for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) - { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) - { - xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); - - if (subsearch) return subsearch; - } - } - - return xml_node(); - } - } - - PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) - { - walker._depth = -1; - - xml_node arg_begin = *this; - if (!walker.begin(arg_begin)) return false; - - xml_node cur = first_child(); - - if (cur) - { - ++walker._depth; - - do - { - xml_node arg_for_each = cur; - if (!walker.for_each(arg_for_each)) - return false; - - if (cur.first_child()) - { - ++walker._depth; - cur = cur.first_child(); - } - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - // Borland C++ workaround - while (!cur.next_sibling() && cur != *this && !cur.parent().empty()) - { - --walker._depth; - cur = cur.parent(); - } - - if (cur != *this) - cur = cur.next_sibling(); - } - } - while (cur && cur != *this); - } - - assert(walker._depth == -1); - - xml_node arg_end = *this; - return walker.end(arg_end); - } - - PUGI__FN size_t xml_node::hash_value() const - { - return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); - } - - PUGI__FN xml_node_struct* xml_node::internal_object() const - { - return _root; - } - - PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - if (!_root) return; - - impl::xml_buffered_writer buffered_writer(writer, encoding); - - impl::node_output(buffered_writer, _root, indent, flags, depth); - - buffered_writer.flush(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding, depth); - } - - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding_wchar, depth); - } -#endif - - PUGI__FN ptrdiff_t xml_node::offset_debug() const - { - if (!_root) return -1; - - impl::xml_document_struct& doc = impl::get_document(_root); - - // we can determine the offset reliably only if there is exactly once parse buffer - if (!doc.buffer || doc.extra_buffers) return -1; - - switch (type()) - { - case node_document: - return 0; - - case node_element: - case node_declaration: - case node_pi: - return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1; - - case node_pcdata: - case node_cdata: - case node_comment: - case node_doctype: - return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1; - - default: - return -1; - } - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) - { - } - - PUGI__FN xml_node_struct* xml_text::_data() const - { - if (!_root || impl::is_text_node(_root)) return _root; - - // element nodes can have value if parse_embed_pcdata was used - if (PUGI__NODETYPE(_root) == node_element && _root->value) - return _root; - - for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) - if (impl::is_text_node(node)) - return node; - - return 0; - } - - PUGI__FN xml_node_struct* xml_text::_data_new() - { - xml_node_struct* d = _data(); - if (d) return d; - - return xml_node(_root).append_child(node_pcdata).internal_object(); - } - - PUGI__FN xml_text::xml_text(): _root(0) - { - } - - PUGI__FN static void unspecified_bool_xml_text(xml_text***) - { - } - - PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const - { - return _data() ? unspecified_bool_xml_text : 0; - } - - PUGI__FN bool xml_text::operator!() const - { - return !_data(); - } - - PUGI__FN bool xml_text::empty() const - { - return _data() == 0; - } - - PUGI__FN const char_t* xml_text::get() const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_text::as_string(const char_t* def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : def; - } - - PUGI__FN int xml_text::as_int(int def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_int(d->value) : def; - } - - PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_uint(d->value) : def; - } - - PUGI__FN double xml_text::as_double(double def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_double(d->value) : def; - } - - PUGI__FN float xml_text::as_float(float def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_float(d->value) : def; - } - - PUGI__FN bool xml_text::as_bool(bool def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_bool(d->value) : def; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_text::as_llong(long long def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_llong(d->value) : def; - } - - PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_ullong(d->value) : def; - } -#endif - - PUGI__FN bool xml_text::set(const char_t* rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) : false; - } - - PUGI__FN bool xml_text::set(int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; - } - - PUGI__FN bool xml_text::set(unsigned int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; - } - - PUGI__FN bool xml_text::set(long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; - } - - PUGI__FN bool xml_text::set(unsigned long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; - } - - PUGI__FN bool xml_text::set(float rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(double rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(bool rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_text::set(long long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; - } - - PUGI__FN bool xml_text::set(unsigned long long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; - } -#endif - - PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(long rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned long rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(double rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(float rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(bool rhs) - { - set(rhs); - return *this; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_text& xml_text::operator=(long long rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) - { - set(rhs); - return *this; - } -#endif - - PUGI__FN xml_node xml_text::data() const - { - return xml_node(_data()); - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_text& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node_iterator::xml_node_iterator() - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const - { - return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const - { - return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_node& xml_node_iterator::operator*() const - { - assert(_wrap._root); - return _wrap; - } - - PUGI__FN xml_node* xml_node_iterator::operator->() const - { - assert(_wrap._root); - return const_cast(&_wrap); // BCC5 workaround - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() - { - assert(_wrap._root); - _wrap._root = _wrap._root->next_sibling; - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) - { - xml_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator--() - { - _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) - { - xml_node_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator() - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const - { - return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const - { - return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const - { - assert(_wrap._attr); - return _wrap; - } - - PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const - { - assert(_wrap._attr); - return const_cast(&_wrap); // BCC5 workaround - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() - { - assert(_wrap._attr); - _wrap._attr = _wrap._attr->next_attribute; - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) - { - xml_attribute_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator--() - { - _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) - { - xml_attribute_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) - { - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) - { - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) - { - } - - PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const - { - return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const - { - return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_node& xml_named_node_iterator::operator*() const - { - assert(_wrap._root); - return _wrap; - } - - PUGI__FN xml_node* xml_named_node_iterator::operator->() const - { - assert(_wrap._root); - return const_cast(&_wrap); // BCC5 workaround - } - - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() - { - assert(_wrap._root); - _wrap = _wrap.next_sibling(_name); - return *this; - } - - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) - { - xml_named_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator--() - { - if (_wrap._root) - _wrap = _wrap.previous_sibling(_name); - else - { - _wrap = _parent.last_child(); - - if (!impl::strequal(_wrap.name(), _name)) - _wrap = _wrap.previous_sibling(_name); - } - - return *this; - } - - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) - { - xml_named_node_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) - { - } - - PUGI__FN xml_parse_result::operator bool() const - { - return status == status_ok; - } - - PUGI__FN const char* xml_parse_result::description() const - { - switch (status) - { - case status_ok: return "No error"; - - case status_file_not_found: return "File was not found"; - case status_io_error: return "Error reading from file/stream"; - case status_out_of_memory: return "Could not allocate memory"; - case status_internal_error: return "Internal error occurred"; - - case status_unrecognized_tag: return "Could not determine tag type"; - - case status_bad_pi: return "Error parsing document declaration/processing instruction"; - case status_bad_comment: return "Error parsing comment"; - case status_bad_cdata: return "Error parsing CDATA section"; - case status_bad_doctype: return "Error parsing document type declaration"; - case status_bad_pcdata: return "Error parsing PCDATA section"; - case status_bad_start_element: return "Error parsing start element tag"; - case status_bad_attribute: return "Error parsing element attribute"; - case status_bad_end_element: return "Error parsing end element tag"; - case status_end_element_mismatch: return "Start-end tags mismatch"; - - case status_append_invalid_root: return "Unable to append nodes: root is not an element or document"; - - case status_no_document_element: return "No document element found"; - - default: return "Unknown error"; - } - } - - PUGI__FN xml_document::xml_document(): _buffer(0) - { - _create(); - } - - PUGI__FN xml_document::~xml_document() - { - _destroy(); - } - - PUGI__FN void xml_document::reset() - { - _destroy(); - _create(); - } - - PUGI__FN void xml_document::reset(const xml_document& proto) - { - reset(); - - for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) - append_copy(cur); - } - - PUGI__FN void xml_document::_create() - { - assert(!_root); - - #ifdef PUGIXML_COMPACT - const size_t page_offset = sizeof(uint32_t); - #else - const size_t page_offset = 0; - #endif - - // initialize sentinel page - PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory)); - - // prepare page structure - impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory); - assert(page); - - page->busy_size = impl::xml_memory_page_size; - - // setup first page marker - #ifdef PUGIXML_COMPACT - // round-trip through void* to avoid 'cast increases required alignment of target type' warning - page->compact_page_marker = reinterpret_cast(static_cast(reinterpret_cast(page) + sizeof(impl::xml_memory_page))); - *page->compact_page_marker = sizeof(impl::xml_memory_page); - #endif - - // allocate new root - _root = new (reinterpret_cast(page) + sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page); - _root->prev_sibling_c = _root; - - // setup sentinel page - page->allocator = static_cast(_root); - - // setup hash table pointer in allocator - #ifdef PUGIXML_COMPACT - page->allocator->_hash = &static_cast(_root)->hash; - #endif - - // verify the document allocation - assert(reinterpret_cast(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); - } - - PUGI__FN void xml_document::_destroy() - { - assert(_root); - - // destroy static storage - if (_buffer) - { - impl::xml_memory::deallocate(_buffer); - _buffer = 0; - } - - // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator) - for (impl::xml_extra_buffer* extra = static_cast(_root)->extra_buffers; extra; extra = extra->next) - { - if (extra->buffer) impl::xml_memory::deallocate(extra->buffer); - } - - // destroy dynamic storage, leave sentinel page (it's in static memory) - impl::xml_memory_page* root_page = PUGI__GETPAGE(_root); - assert(root_page && !root_page->prev); - assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); - - for (impl::xml_memory_page* page = root_page->next; page; ) - { - impl::xml_memory_page* next = page->next; - - impl::xml_allocator::deallocate_page(page); - - page = next; - } - - #ifdef PUGIXML_COMPACT - // destroy hash table - static_cast(_root)->hash.clear(); - #endif - - _root = 0; - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_stream_impl(static_cast(_root), stream, options, encoding, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) - { - reset(); - - return impl::load_stream_impl(static_cast(_root), stream, options, encoding_wchar, &_buffer); - } -#endif - - PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) - { - // Force native encoding (skip autodetection) - #ifdef PUGIXML_WCHAR_MODE - xml_encoding encoding = encoding_wchar; - #else - xml_encoding encoding = encoding_utf8; - #endif - - return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) - { - return load_string(contents, options); - } - - PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, "rb"), impl::close_file); - - return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(impl::open_file_wide(path_, L"rb"), impl::close_file); - - return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, const_cast(contents), size, options, encoding, false, false, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, false, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, true, &_buffer); - } - - PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - impl::xml_buffered_writer buffered_writer(writer, encoding); - - if ((flags & format_write_bom) && encoding != encoding_latin1) - { - // BOM always represents the codepoint U+FEFF, so just write it in native encoding - #ifdef PUGIXML_WCHAR_MODE - unsigned int bom = 0xfeff; - buffered_writer.write(static_cast(bom)); - #else - buffered_writer.write('\xef', '\xbb', '\xbf'); - #endif - } - - if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) - { - buffered_writer.write_string(PUGIXML_TEXT("'); - if (!(flags & format_raw)) buffered_writer.write('\n'); - } - - impl::node_output(buffered_writer, _root, indent, flags, 0); - - buffered_writer.flush(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding); - } - - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding_wchar); - } -#endif - - PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); - - return impl::save_file_impl(*this, file.data, indent, flags, encoding); - } - - PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file); - - return impl::save_file_impl(*this, file.data, indent, flags, encoding); - } - - PUGI__FN xml_node xml_document::document_element() const - { - assert(_root); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (PUGI__NODETYPE(i) == node_element) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) - { - assert(str); - - return impl::as_utf8_impl(str, impl::strlength_wide(str)); - } - - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) - { - return impl::as_utf8_impl(str.c_str(), str.size()); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) - { - assert(str); - - return impl::as_wide_impl(str, strlen(str)); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) - { - return impl::as_wide_impl(str.c_str(), str.size()); - } -#endif - - PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) - { - impl::xml_memory::allocate = allocate; - impl::xml_memory::deallocate = deallocate; - } - - PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() - { - return impl::xml_memory::allocate; - } - - PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() - { - return impl::xml_memory::deallocate; - } -} - -#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } -} -#endif - -#ifndef PUGIXML_NO_XPATH -// STL replacements -PUGI__NS_BEGIN - struct equal_to - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs == rhs; - } - }; - - struct not_equal_to - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs != rhs; - } - }; - - struct less - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs < rhs; - } - }; - - struct less_equal - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs <= rhs; - } - }; - - template void swap(T& lhs, T& rhs) - { - T temp = lhs; - lhs = rhs; - rhs = temp; - } - - template I min_element(I begin, I end, const Pred& pred) - { - I result = begin; - - for (I it = begin + 1; it != end; ++it) - if (pred(*it, *result)) - result = it; - - return result; - } - - template void reverse(I begin, I end) - { - while (end - begin > 1) swap(*begin++, *--end); - } - - template I unique(I begin, I end) - { - // fast skip head - while (end - begin > 1 && *begin != *(begin + 1)) begin++; - - if (begin == end) return begin; - - // last written element - I write = begin++; - - // merge unique elements - while (begin != end) - { - if (*begin != *write) - *++write = *begin++; - else - begin++; - } - - // past-the-end (write points to live element) - return write + 1; - } - - template void copy_backwards(I begin, I end, I target) - { - while (begin != end) *--target = *--end; - } - - template void insertion_sort(I begin, I end, const Pred& pred, T*) - { - assert(begin != end); - - for (I it = begin + 1; it != end; ++it) - { - T val = *it; - - if (pred(val, *begin)) - { - // move to front - copy_backwards(begin, it, it + 1); - *begin = val; - } - else - { - I hole = it; - - // move hole backwards - while (pred(val, *(hole - 1))) - { - *hole = *(hole - 1); - hole--; - } - - // fill hole with element - *hole = val; - } - } - } - - // std variant for elements with == - template void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend) - { - I eqbeg = middle, eqend = middle + 1; - - // expand equal range - while (eqbeg != begin && *(eqbeg - 1) == *eqbeg) --eqbeg; - while (eqend != end && *eqend == *eqbeg) ++eqend; - - // process outer elements - I ltend = eqbeg, gtbeg = eqend; - - for (;;) - { - // find the element from the right side that belongs to the left one - for (; gtbeg != end; ++gtbeg) - if (!pred(*eqbeg, *gtbeg)) - { - if (*gtbeg == *eqbeg) swap(*gtbeg, *eqend++); - else break; - } - - // find the element from the left side that belongs to the right one - for (; ltend != begin; --ltend) - if (!pred(*(ltend - 1), *eqbeg)) - { - if (*eqbeg == *(ltend - 1)) swap(*(ltend - 1), *--eqbeg); - else break; - } - - // scanned all elements - if (gtbeg == end && ltend == begin) - { - *out_eqbeg = eqbeg; - *out_eqend = eqend; - return; - } - - // make room for elements by moving equal area - if (gtbeg == end) - { - if (--ltend != --eqbeg) swap(*ltend, *eqbeg); - swap(*eqbeg, *--eqend); - } - else if (ltend == begin) - { - if (eqend != gtbeg) swap(*eqbeg, *eqend); - ++eqend; - swap(*gtbeg++, *eqbeg++); - } - else swap(*gtbeg++, *--ltend); - } - } - - template void median3(I first, I middle, I last, const Pred& pred) - { - if (pred(*middle, *first)) swap(*middle, *first); - if (pred(*last, *middle)) swap(*last, *middle); - if (pred(*middle, *first)) swap(*middle, *first); - } - - template void median(I first, I middle, I last, const Pred& pred) - { - if (last - first <= 40) - { - // median of three for small chunks - median3(first, middle, last, pred); - } - else - { - // median of nine - size_t step = (last - first + 1) / 8; - - median3(first, first + step, first + 2 * step, pred); - median3(middle - step, middle, middle + step, pred); - median3(last - 2 * step, last - step, last, pred); - median3(first + step, middle, last - step, pred); - } - } - - template void sort(I begin, I end, const Pred& pred) - { - // sort large chunks - while (end - begin > 32) - { - // find median element - I middle = begin + (end - begin) / 2; - median(begin, middle, end - 1, pred); - - // partition in three chunks (< = >) - I eqbeg, eqend; - partition(begin, middle, end, pred, &eqbeg, &eqend); - - // loop on larger half - if (eqbeg - begin > end - eqend) - { - sort(eqend, end, pred); - end = eqbeg; - } - else - { - sort(begin, eqbeg, pred); - begin = eqend; - } - } - - // insertion sort small chunk - if (begin != end) insertion_sort(begin, end, pred, &*begin); - } -PUGI__NS_END - -// Allocator used for AST and evaluation stacks -PUGI__NS_BEGIN - static const size_t xpath_memory_page_size = - #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE - PUGIXML_MEMORY_XPATH_PAGE_SIZE - #else - 4096 - #endif - ; - - static const uintptr_t xpath_memory_block_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*); - - struct xpath_memory_block - { - xpath_memory_block* next; - size_t capacity; - - union - { - char data[xpath_memory_page_size]; - double alignment; - }; - }; - - class xpath_allocator - { - xpath_memory_block* _root; - size_t _root_size; - - public: - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf* error_handler; - #endif - - xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size) - { - #ifdef PUGIXML_NO_EXCEPTIONS - error_handler = 0; - #endif - } - - void* allocate_nothrow(size_t size) - { - // round size up to block alignment boundary - size = (size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); - - if (_root_size + size <= _root->capacity) - { - void* buf = &_root->data[0] + _root_size; - _root_size += size; - return buf; - } - else - { - // make sure we have at least 1/4th of the page free after allocation to satisfy subsequent allocation requests - size_t block_capacity_base = sizeof(_root->data); - size_t block_capacity_req = size + block_capacity_base / 4; - size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req; - - size_t block_size = block_capacity + offsetof(xpath_memory_block, data); - - xpath_memory_block* block = static_cast(xml_memory::allocate(block_size)); - if (!block) return 0; - - block->next = _root; - block->capacity = block_capacity; - - _root = block; - _root_size = size; - - return block->data; - } - } - - void* allocate(size_t size) - { - void* result = allocate_nothrow(size); - - if (!result) - { - #ifdef PUGIXML_NO_EXCEPTIONS - assert(error_handler); - longjmp(*error_handler, 1); - #else - throw std::bad_alloc(); - #endif - } - - return result; - } - - void* reallocate(void* ptr, size_t old_size, size_t new_size) - { - // round size up to block alignment boundary - old_size = (old_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); - new_size = (new_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); - - // we can only reallocate the last object - assert(ptr == 0 || static_cast(ptr) + old_size == &_root->data[0] + _root_size); - - // adjust root size so that we have not allocated the object at all - bool only_object = (_root_size == old_size); - - if (ptr) _root_size -= old_size; - - // allocate a new version (this will obviously reuse the memory if possible) - void* result = allocate(new_size); - assert(result); - - // we have a new block - if (result != ptr && ptr) - { - // copy old data - assert(new_size >= old_size); - memcpy(result, ptr, old_size); - - // free the previous page if it had no other objects - if (only_object) - { - assert(_root->data == result); - assert(_root->next); - - xpath_memory_block* next = _root->next->next; - - if (next) - { - // deallocate the whole page, unless it was the first one - xml_memory::deallocate(_root->next); - _root->next = next; - } - } - } - - return result; - } - - void revert(const xpath_allocator& state) - { - // free all new pages - xpath_memory_block* cur = _root; - - while (cur != state._root) - { - xpath_memory_block* next = cur->next; - - xml_memory::deallocate(cur); - - cur = next; - } - - // restore state - _root = state._root; - _root_size = state._root_size; - } - - void release() - { - xpath_memory_block* cur = _root; - assert(cur); - - while (cur->next) - { - xpath_memory_block* next = cur->next; - - xml_memory::deallocate(cur); - - cur = next; - } - } - }; - - struct xpath_allocator_capture - { - xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc) - { - } - - ~xpath_allocator_capture() - { - _target->revert(_state); - } - - xpath_allocator* _target; - xpath_allocator _state; - }; - - struct xpath_stack - { - xpath_allocator* result; - xpath_allocator* temp; - }; - - struct xpath_stack_data - { - xpath_memory_block blocks[2]; - xpath_allocator result; - xpath_allocator temp; - xpath_stack stack; - - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf error_handler; - #endif - - xpath_stack_data(): result(blocks + 0), temp(blocks + 1) - { - blocks[0].next = blocks[1].next = 0; - blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data); - - stack.result = &result; - stack.temp = &temp; - - #ifdef PUGIXML_NO_EXCEPTIONS - result.error_handler = temp.error_handler = &error_handler; - #endif - } - - ~xpath_stack_data() - { - result.release(); - temp.release(); - } - }; -PUGI__NS_END - -// String class -PUGI__NS_BEGIN - class xpath_string - { - const char_t* _buffer; - bool _uses_heap; - size_t _length_heap; - - static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) - { - char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); - assert(result); - - memcpy(result, string, length * sizeof(char_t)); - result[length] = 0; - - return result; - } - - xpath_string(const char_t* buffer, bool uses_heap_, size_t length_heap): _buffer(buffer), _uses_heap(uses_heap_), _length_heap(length_heap) - { - } - - public: - static xpath_string from_const(const char_t* str) - { - return xpath_string(str, false, 0); - } - - static xpath_string from_heap_preallocated(const char_t* begin, const char_t* end) - { - assert(begin <= end && *end == 0); - - return xpath_string(begin, true, static_cast(end - begin)); - } - - static xpath_string from_heap(const char_t* begin, const char_t* end, xpath_allocator* alloc) - { - assert(begin <= end); - - size_t length = static_cast(end - begin); - - return length == 0 ? xpath_string() : xpath_string(duplicate_string(begin, length, alloc), true, length); - } - - xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false), _length_heap(0) - { - } - - void append(const xpath_string& o, xpath_allocator* alloc) - { - // skip empty sources - if (!*o._buffer) return; - - // fast append for constant empty target and constant source - if (!*_buffer && !_uses_heap && !o._uses_heap) - { - _buffer = o._buffer; - } - else - { - // need to make heap copy - size_t target_length = length(); - size_t source_length = o.length(); - size_t result_length = target_length + source_length; - - // allocate new buffer - char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); - assert(result); - - // append first string to the new buffer in case there was no reallocation - if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); - - // append second string to the new buffer - memcpy(result + target_length, o._buffer, source_length * sizeof(char_t)); - result[result_length] = 0; - - // finalize - _buffer = result; - _uses_heap = true; - _length_heap = result_length; - } - } - - const char_t* c_str() const - { - return _buffer; - } - - size_t length() const - { - return _uses_heap ? _length_heap : strlength(_buffer); - } - - char_t* data(xpath_allocator* alloc) - { - // make private heap copy - if (!_uses_heap) - { - size_t length_ = strlength(_buffer); - - _buffer = duplicate_string(_buffer, length_, alloc); - _uses_heap = true; - _length_heap = length_; - } - - return const_cast(_buffer); - } - - bool empty() const - { - return *_buffer == 0; - } - - bool operator==(const xpath_string& o) const - { - return strequal(_buffer, o._buffer); - } - - bool operator!=(const xpath_string& o) const - { - return !strequal(_buffer, o._buffer); - } - - bool uses_heap() const - { - return _uses_heap; - } - }; -PUGI__NS_END - -PUGI__NS_BEGIN - PUGI__FN bool starts_with(const char_t* string, const char_t* pattern) - { - while (*pattern && *string == *pattern) - { - string++; - pattern++; - } - - return *pattern == 0; - } - - PUGI__FN const char_t* find_char(const char_t* s, char_t c) - { - #ifdef PUGIXML_WCHAR_MODE - return wcschr(s, c); - #else - return strchr(s, c); - #endif - } - - PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p) - { - #ifdef PUGIXML_WCHAR_MODE - // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) - return (*p == 0) ? s : wcsstr(s, p); - #else - return strstr(s, p); - #endif - } - - // Converts symbol to lower case, if it is an ASCII one - PUGI__FN char_t tolower_ascii(char_t ch) - { - return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; - } - - PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) - { - if (na.attribute()) - return xpath_string::from_const(na.attribute().value()); - else - { - xml_node n = na.node(); - - switch (n.type()) - { - case node_pcdata: - case node_cdata: - case node_comment: - case node_pi: - return xpath_string::from_const(n.value()); - - case node_document: - case node_element: - { - xpath_string result; - - // element nodes can have value if parse_embed_pcdata was used - if (n.value()[0]) - result.append(xpath_string::from_const(n.value()), alloc); - - xml_node cur = n.first_child(); - - while (cur && cur != n) - { - if (cur.type() == node_pcdata || cur.type() == node_cdata) - result.append(xpath_string::from_const(cur.value()), alloc); - - if (cur.first_child()) - cur = cur.first_child(); - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur != n) - cur = cur.parent(); - - if (cur != n) cur = cur.next_sibling(); - } - } - - return result; - } - - default: - return xpath_string(); - } - } - } - - PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) - { - assert(ln->parent == rn->parent); - - // there is no common ancestor (the shared parent is null), nodes are from different documents - if (!ln->parent) return ln < rn; - - // determine sibling order - xml_node_struct* ls = ln; - xml_node_struct* rs = rn; - - while (ls && rs) - { - if (ls == rn) return true; - if (rs == ln) return false; - - ls = ls->next_sibling; - rs = rs->next_sibling; - } - - // if rn sibling chain ended ln must be before rn - return !rs; - } - - PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) - { - // find common ancestor at the same depth, if any - xml_node_struct* lp = ln; - xml_node_struct* rp = rn; - - while (lp && rp && lp->parent != rp->parent) - { - lp = lp->parent; - rp = rp->parent; - } - - // parents are the same! - if (lp && rp) return node_is_before_sibling(lp, rp); - - // nodes are at different depths, need to normalize heights - bool left_higher = !lp; - - while (lp) - { - lp = lp->parent; - ln = ln->parent; - } - - while (rp) - { - rp = rp->parent; - rn = rn->parent; - } - - // one node is the ancestor of the other - if (ln == rn) return left_higher; - - // find common ancestor... again - while (ln->parent != rn->parent) - { - ln = ln->parent; - rn = rn->parent; - } - - return node_is_before_sibling(ln, rn); - } - - PUGI__FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node) - { - while (node && node != parent) node = node->parent; - - return parent && node == parent; - } - - PUGI__FN const void* document_buffer_order(const xpath_node& xnode) - { - xml_node_struct* node = xnode.node().internal_object(); - - if (node) - { - if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0) - { - if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; - if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; - } - - return 0; - } - - xml_attribute_struct* attr = xnode.attribute().internal_object(); - - if (attr) - { - if ((get_document(attr).header & xml_memory_page_contents_shared_mask) == 0) - { - if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name; - if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; - } - - return 0; - } - - return 0; - } - - struct document_order_comparator - { - bool operator()(const xpath_node& lhs, const xpath_node& rhs) const - { - // optimized document order based check - const void* lo = document_buffer_order(lhs); - const void* ro = document_buffer_order(rhs); - - if (lo && ro) return lo < ro; - - // slow comparison - xml_node ln = lhs.node(), rn = rhs.node(); - - // compare attributes - if (lhs.attribute() && rhs.attribute()) - { - // shared parent - if (lhs.parent() == rhs.parent()) - { - // determine sibling order - for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) - if (a == rhs.attribute()) - return true; - - return false; - } - - // compare attribute parents - ln = lhs.parent(); - rn = rhs.parent(); - } - else if (lhs.attribute()) - { - // attributes go after the parent element - if (lhs.parent() == rhs.node()) return false; - - ln = lhs.parent(); - } - else if (rhs.attribute()) - { - // attributes go after the parent element - if (rhs.parent() == lhs.node()) return true; - - rn = rhs.parent(); - } - - if (ln == rn) return false; - - if (!ln || !rn) return ln < rn; - - return node_is_before(ln.internal_object(), rn.internal_object()); - } - }; - - struct duplicate_comparator - { - bool operator()(const xpath_node& lhs, const xpath_node& rhs) const - { - if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; - else return rhs.attribute() ? false : lhs.node() < rhs.node(); - } - }; - - PUGI__FN double gen_nan() - { - #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) - PUGI__STATIC_ASSERT(sizeof(float) == sizeof(uint32_t)); - typedef uint32_t UI; // BCC5 workaround - union { float f; UI i; } u; - u.i = 0x7fc00000; - return u.f; - #else - // fallback - const volatile double zero = 0.0; - return zero / zero; - #endif - } - - PUGI__FN bool is_nan(double value) - { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) - return !!_isnan(value); - #elif defined(fpclassify) && defined(FP_NAN) - return fpclassify(value) == FP_NAN; - #else - // fallback - const volatile double v = value; - return v != v; - #endif - } - - PUGI__FN const char_t* convert_number_to_string_special(double value) - { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) - if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; - if (_isnan(value)) return PUGIXML_TEXT("NaN"); - return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) - switch (fpclassify(value)) - { - case FP_NAN: - return PUGIXML_TEXT("NaN"); - - case FP_INFINITE: - return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - - case FP_ZERO: - return PUGIXML_TEXT("0"); - - default: - return 0; - } - #else - // fallback - const volatile double v = value; - - if (v == 0) return PUGIXML_TEXT("0"); - if (v != v) return PUGIXML_TEXT("NaN"); - if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - return 0; - #endif - } - - PUGI__FN bool convert_number_to_boolean(double value) - { - return (value != 0 && !is_nan(value)); - } - - PUGI__FN void truncate_zeros(char* begin, char* end) - { - while (begin != end && end[-1] == '0') end--; - - *end = 0; - } - - // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) - PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) - { - // get base values - int sign, exponent; - _ecvt_s(buffer, buffer_size, value, DBL_DIG + 1, &exponent, &sign); - - // truncate redundant zeros - truncate_zeros(buffer, buffer + strlen(buffer)); - - // fill results - *out_mantissa = buffer; - *out_exponent = exponent; - } -#else - PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) - { - // get a scientific notation value with IEEE DBL_DIG decimals - sprintf(buffer, "%.*e", DBL_DIG, value); - assert(strlen(buffer) < buffer_size); - (void)!buffer_size; - - // get the exponent (possibly negative) - char* exponent_string = strchr(buffer, 'e'); - assert(exponent_string); - - int exponent = atoi(exponent_string + 1); - - // extract mantissa string: skip sign - char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; - assert(mantissa[0] != '0' && mantissa[1] == '.'); - - // divide mantissa by 10 to eliminate integer part - mantissa[1] = mantissa[0]; - mantissa++; - exponent++; - - // remove extra mantissa digits and zero-terminate mantissa - truncate_zeros(mantissa, exponent_string); - - // fill results - *out_mantissa = mantissa; - *out_exponent = exponent; - } -#endif - - PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) - { - // try special number conversion - const char_t* special = convert_number_to_string_special(value); - if (special) return xpath_string::from_const(special); - - // get mantissa + exponent form - char mantissa_buffer[32]; - - char* mantissa; - int exponent; - convert_number_to_mantissa_exponent(value, mantissa_buffer, sizeof(mantissa_buffer), &mantissa, &exponent); - - // allocate a buffer of suitable length for the number - size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4; - char_t* result = static_cast(alloc->allocate(sizeof(char_t) * result_size)); - assert(result); - - // make the number! - char_t* s = result; - - // sign - if (value < 0) *s++ = '-'; - - // integer part - if (exponent <= 0) - { - *s++ = '0'; - } - else - { - while (exponent > 0) - { - assert(*mantissa == 0 || static_cast(static_cast(*mantissa) - '0') <= 9); - *s++ = *mantissa ? *mantissa++ : '0'; - exponent--; - } - } - - // fractional part - if (*mantissa) - { - // decimal point - *s++ = '.'; - - // extra zeroes from negative exponent - while (exponent < 0) - { - *s++ = '0'; - exponent++; - } - - // extra mantissa digits - while (*mantissa) - { - assert(static_cast(*mantissa - '0') <= 9); - *s++ = *mantissa++; - } - } - - // zero-terminate - assert(s < result + result_size); - *s = 0; - - return xpath_string::from_heap_preallocated(result, s); - } - - PUGI__FN bool check_string_to_number_format(const char_t* string) - { - // parse leading whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; - - // parse sign - if (*string == '-') ++string; - - if (!*string) return false; - - // if there is no integer part, there should be a decimal part with at least one digit - if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false; - - // parse integer part - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; - - // parse decimal part - if (*string == '.') - { - ++string; - - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; - } - - // parse trailing whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; - - return *string == 0; - } - - PUGI__FN double convert_string_to_number(const char_t* string) - { - // check string format - if (!check_string_to_number_format(string)) return gen_nan(); - - // parse string - #ifdef PUGIXML_WCHAR_MODE - return wcstod(string, 0); - #else - return strtod(string, 0); - #endif - } - - PUGI__FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result) - { - size_t length = static_cast(end - begin); - char_t* scratch = buffer; - - if (length >= sizeof(buffer) / sizeof(buffer[0])) - { - // need to make dummy on-heap copy - scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!scratch) return false; - } - - // copy string to zero-terminated buffer and perform conversion - memcpy(scratch, begin, length * sizeof(char_t)); - scratch[length] = 0; - - *out_result = convert_string_to_number(scratch); - - // free dummy buffer - if (scratch != buffer) xml_memory::deallocate(scratch); - - return true; - } - - PUGI__FN double round_nearest(double value) - { - return floor(value + 0.5); - } - - PUGI__FN double round_nearest_nzero(double value) - { - // same as round_nearest, but returns -0 for [-0.5, -0] - // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) - return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); - } - - PUGI__FN const char_t* qualified_name(const xpath_node& node) - { - return node.attribute() ? node.attribute().name() : node.node().name(); - } - - PUGI__FN const char_t* local_name(const xpath_node& node) - { - const char_t* name = qualified_name(node); - const char_t* p = find_char(name, ':'); - - return p ? p + 1 : name; - } - - struct namespace_uri_predicate - { - const char_t* prefix; - size_t prefix_length; - - namespace_uri_predicate(const char_t* name) - { - const char_t* pos = find_char(name, ':'); - - prefix = pos ? name : 0; - prefix_length = pos ? static_cast(pos - name) : 0; - } - - bool operator()(xml_attribute a) const - { - const char_t* name = a.name(); - - if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false; - - return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0; - } - }; - - PUGI__FN const char_t* namespace_uri(xml_node node) - { - namespace_uri_predicate pred = node.name(); - - xml_node p = node; - - while (p) - { - xml_attribute a = p.find_attribute(pred); - - if (a) return a.value(); - - p = p.parent(); - } - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) - { - namespace_uri_predicate pred = attr.name(); - - // Default namespace does not apply to attributes - if (!pred.prefix) return PUGIXML_TEXT(""); - - xml_node p = parent; - - while (p) - { - xml_attribute a = p.find_attribute(pred); - - if (a) return a.value(); - - p = p.parent(); - } - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* namespace_uri(const xpath_node& node) - { - return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); - } - - PUGI__FN char_t* normalize_space(char_t* buffer) - { - char_t* write = buffer; - - for (char_t* it = buffer; *it; ) - { - char_t ch = *it++; - - if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - // replace whitespace sequence with single space - while (PUGI__IS_CHARTYPE(*it, ct_space)) it++; - - // avoid leading spaces - if (write != buffer) *write++ = ' '; - } - else *write++ = ch; - } - - // remove trailing space - if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--; - - // zero-terminate - *write = 0; - - return write; - } - - PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) - { - char_t* write = buffer; - - while (*buffer) - { - PUGI__DMC_VOLATILE char_t ch = *buffer++; - - const char_t* pos = find_char(from, ch); - - if (!pos) - *write++ = ch; // do not process - else if (static_cast(pos - from) < to_length) - *write++ = to[pos - from]; // replace - } - - // zero-terminate - *write = 0; - - return write; - } - - PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) - { - unsigned char table[128] = {0}; - - while (*from) - { - unsigned int fc = static_cast(*from); - unsigned int tc = static_cast(*to); - - if (fc >= 128 || tc >= 128) - return 0; - - // code=128 means "skip character" - if (!table[fc]) - table[fc] = static_cast(tc ? tc : 128); - - from++; - if (tc) to++; - } - - for (int i = 0; i < 128; ++i) - if (!table[i]) - table[i] = static_cast(i); - - void* result = alloc->allocate_nothrow(sizeof(table)); - - if (result) - { - memcpy(result, table, sizeof(table)); - } - - return static_cast(result); - } - - PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table) - { - char_t* write = buffer; - - while (*buffer) - { - char_t ch = *buffer++; - unsigned int index = static_cast(ch); - - if (index < 128) - { - unsigned char code = table[index]; - - // code=128 means "skip character" (table size is 128 so 128 can be a special value) - // this code skips these characters without extra branches - *write = static_cast(code); - write += 1 - (code >> 7); - } - else - { - *write++ = ch; - } - } - - // zero-terminate - *write = 0; - - return write; - } - - inline bool is_xpath_attribute(const char_t* name) - { - return !(starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')); - } - - struct xpath_variable_boolean: xpath_variable - { - xpath_variable_boolean(): xpath_variable(xpath_type_boolean), value(false) - { - } - - bool value; - char_t name[1]; - }; - - struct xpath_variable_number: xpath_variable - { - xpath_variable_number(): xpath_variable(xpath_type_number), value(0) - { - } - - double value; - char_t name[1]; - }; - - struct xpath_variable_string: xpath_variable - { - xpath_variable_string(): xpath_variable(xpath_type_string), value(0) - { - } - - ~xpath_variable_string() - { - if (value) xml_memory::deallocate(value); - } - - char_t* value; - char_t name[1]; - }; - - struct xpath_variable_node_set: xpath_variable - { - xpath_variable_node_set(): xpath_variable(xpath_type_node_set) - { - } - - xpath_node_set value; - char_t name[1]; - }; - - static const xpath_node_set dummy_node_set; - - PUGI__FN unsigned int hash_string(const char_t* str) - { - // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) - unsigned int result = 0; - - while (*str) - { - result += static_cast(*str++); - result += result << 10; - result ^= result >> 6; - } - - result += result << 3; - result ^= result >> 11; - result += result << 15; - - return result; - } - - template PUGI__FN T* new_xpath_variable(const char_t* name) - { - size_t length = strlength(name); - if (length == 0) return 0; // empty variable names are invalid - - // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters - void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t)); - if (!memory) return 0; - - T* result = new (memory) T(); - - memcpy(result->name, name, (length + 1) * sizeof(char_t)); - - return result; - } - - PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) - { - switch (type) - { - case xpath_type_node_set: - return new_xpath_variable(name); - - case xpath_type_number: - return new_xpath_variable(name); - - case xpath_type_string: - return new_xpath_variable(name); - - case xpath_type_boolean: - return new_xpath_variable(name); - - default: - return 0; - } - } - - template PUGI__FN void delete_xpath_variable(T* var) - { - var->~T(); - xml_memory::deallocate(var); - } - - PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) - { - switch (type) - { - case xpath_type_node_set: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_number: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_string: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_boolean: - delete_xpath_variable(static_cast(var)); - break; - - default: - assert(false && "Invalid variable type"); - } - } - - PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) - { - switch (rhs->type()) - { - case xpath_type_node_set: - return lhs->set(static_cast(rhs)->value); - - case xpath_type_number: - return lhs->set(static_cast(rhs)->value); - - case xpath_type_string: - return lhs->set(static_cast(rhs)->value); - - case xpath_type_boolean: - return lhs->set(static_cast(rhs)->value); - - default: - assert(false && "Invalid variable type"); - return false; - } - } - - PUGI__FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result) - { - size_t length = static_cast(end - begin); - char_t* scratch = buffer; - - if (length >= sizeof(buffer) / sizeof(buffer[0])) - { - // need to make dummy on-heap copy - scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!scratch) return false; - } - - // copy string to zero-terminated buffer and perform lookup - memcpy(scratch, begin, length * sizeof(char_t)); - scratch[length] = 0; - - *out_result = set->get(scratch); - - // free dummy buffer - if (scratch != buffer) xml_memory::deallocate(scratch); - - return true; - } -PUGI__NS_END - -// Internal node set class -PUGI__NS_BEGIN - PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end) - { - if (end - begin < 2) - return xpath_node_set::type_sorted; - - document_order_comparator cmp; - - bool first = cmp(begin[0], begin[1]); - - for (const xpath_node* it = begin + 1; it + 1 < end; ++it) - if (cmp(it[0], it[1]) != first) - return xpath_node_set::type_unsorted; - - return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse; - } - - PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) - { - xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; - - if (type == xpath_node_set::type_unsorted) - { - xpath_node_set::type_t sorted = xpath_get_order(begin, end); - - if (sorted == xpath_node_set::type_unsorted) - { - sort(begin, end, document_order_comparator()); - - type = xpath_node_set::type_sorted; - } - else - type = sorted; - } - - if (type != order) reverse(begin, end); - - return order; - } - - PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) - { - if (begin == end) return xpath_node(); - - switch (type) - { - case xpath_node_set::type_sorted: - return *begin; - - case xpath_node_set::type_sorted_reverse: - return *(end - 1); - - case xpath_node_set::type_unsorted: - return *min_element(begin, end, document_order_comparator()); - - default: - assert(false && "Invalid node set type"); - return xpath_node(); - } - } - - class xpath_node_set_raw - { - xpath_node_set::type_t _type; - - xpath_node* _begin; - xpath_node* _end; - xpath_node* _eos; - - public: - xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) - { - } - - xpath_node* begin() const - { - return _begin; - } - - xpath_node* end() const - { - return _end; - } - - bool empty() const - { - return _begin == _end; - } - - size_t size() const - { - return static_cast(_end - _begin); - } - - xpath_node first() const - { - return xpath_first(_begin, _end, _type); - } - - void push_back_grow(const xpath_node& node, xpath_allocator* alloc); - - void push_back(const xpath_node& node, xpath_allocator* alloc) - { - if (_end != _eos) - *_end++ = node; - else - push_back_grow(node, alloc); - } - - void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc) - { - if (begin_ == end_) return; - - size_t size_ = static_cast(_end - _begin); - size_t capacity = static_cast(_eos - _begin); - size_t count = static_cast(end_ - begin_); - - if (size_ + count > capacity) - { - // reallocate the old array or allocate a new one - xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size_ + count) * sizeof(xpath_node))); - assert(data); - - // finalize - _begin = data; - _end = data + size_; - _eos = data + size_ + count; - } - - memcpy(_end, begin_, count * sizeof(xpath_node)); - _end += count; - } - - void sort_do() - { - _type = xpath_sort(_begin, _end, _type, false); - } - - void truncate(xpath_node* pos) - { - assert(_begin <= pos && pos <= _end); - - _end = pos; - } - - void remove_duplicates() - { - if (_type == xpath_node_set::type_unsorted) - sort(_begin, _end, duplicate_comparator()); - - _end = unique(_begin, _end); - } - - xpath_node_set::type_t type() const - { - return _type; - } - - void set_type(xpath_node_set::type_t value) - { - _type = value; - } - }; - - PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) - { - size_t capacity = static_cast(_eos - _begin); - - // get new capacity (1.5x rule) - size_t new_capacity = capacity + capacity / 2 + 1; - - // reallocate the old array or allocate a new one - xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); - assert(data); - - // finalize - _begin = data; - _end = data + capacity; - _eos = data + new_capacity; - - // push - *_end++ = node; - } -PUGI__NS_END - -PUGI__NS_BEGIN - struct xpath_context - { - xpath_node n; - size_t position, size; - - xpath_context(const xpath_node& n_, size_t position_, size_t size_): n(n_), position(position_), size(size_) - { - } - }; - - enum lexeme_t - { - lex_none = 0, - lex_equal, - lex_not_equal, - lex_less, - lex_greater, - lex_less_or_equal, - lex_greater_or_equal, - lex_plus, - lex_minus, - lex_multiply, - lex_union, - lex_var_ref, - lex_open_brace, - lex_close_brace, - lex_quoted_string, - lex_number, - lex_slash, - lex_double_slash, - lex_open_square_brace, - lex_close_square_brace, - lex_string, - lex_comma, - lex_axis_attribute, - lex_dot, - lex_double_dot, - lex_double_colon, - lex_eof - }; - - struct xpath_lexer_string - { - const char_t* begin; - const char_t* end; - - xpath_lexer_string(): begin(0), end(0) - { - } - - bool operator==(const char_t* other) const - { - size_t length = static_cast(end - begin); - - return strequalrange(other, begin, length); - } - }; - - class xpath_lexer - { - const char_t* _cur; - const char_t* _cur_lexeme_pos; - xpath_lexer_string _cur_lexeme_contents; - - lexeme_t _cur_lexeme; - - public: - explicit xpath_lexer(const char_t* query): _cur(query) - { - next(); - } - - const char_t* state() const - { - return _cur; - } - - void next() - { - const char_t* cur = _cur; - - while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; - - // save lexeme position for error reporting - _cur_lexeme_pos = cur; - - switch (*cur) - { - case 0: - _cur_lexeme = lex_eof; - break; - - case '>': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_greater_or_equal; - } - else - { - cur += 1; - _cur_lexeme = lex_greater; - } - break; - - case '<': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_less_or_equal; - } - else - { - cur += 1; - _cur_lexeme = lex_less; - } - break; - - case '!': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_not_equal; - } - else - { - _cur_lexeme = lex_none; - } - break; - - case '=': - cur += 1; - _cur_lexeme = lex_equal; - - break; - - case '+': - cur += 1; - _cur_lexeme = lex_plus; - - break; - - case '-': - cur += 1; - _cur_lexeme = lex_minus; - - break; - - case '*': - cur += 1; - _cur_lexeme = lex_multiply; - - break; - - case '|': - cur += 1; - _cur_lexeme = lex_union; - - break; - - case '$': - cur += 1; - - if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - - if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname - { - cur++; // : - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_var_ref; - } - else - { - _cur_lexeme = lex_none; - } - - break; - - case '(': - cur += 1; - _cur_lexeme = lex_open_brace; - - break; - - case ')': - cur += 1; - _cur_lexeme = lex_close_brace; - - break; - - case '[': - cur += 1; - _cur_lexeme = lex_open_square_brace; - - break; - - case ']': - cur += 1; - _cur_lexeme = lex_close_square_brace; - - break; - - case ',': - cur += 1; - _cur_lexeme = lex_comma; - - break; - - case '/': - if (*(cur+1) == '/') - { - cur += 2; - _cur_lexeme = lex_double_slash; - } - else - { - cur += 1; - _cur_lexeme = lex_slash; - } - break; - - case '.': - if (*(cur+1) == '.') - { - cur += 2; - _cur_lexeme = lex_double_dot; - } - else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit)) - { - _cur_lexeme_contents.begin = cur; // . - - ++cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_number; - } - else - { - cur += 1; - _cur_lexeme = lex_dot; - } - break; - - case '@': - cur += 1; - _cur_lexeme = lex_axis_attribute; - - break; - - case '"': - case '\'': - { - char_t terminator = *cur; - - ++cur; - - _cur_lexeme_contents.begin = cur; - while (*cur && *cur != terminator) cur++; - _cur_lexeme_contents.end = cur; - - if (!*cur) - _cur_lexeme = lex_none; - else - { - cur += 1; - _cur_lexeme = lex_quoted_string; - } - - break; - } - - case ':': - if (*(cur+1) == ':') - { - cur += 2; - _cur_lexeme = lex_double_colon; - } - else - { - _cur_lexeme = lex_none; - } - break; - - default: - if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - - if (*cur == '.') - { - cur++; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_number; - } - else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - - if (cur[0] == ':') - { - if (cur[1] == '*') // namespace test ncname:* - { - cur += 2; // :* - } - else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname - { - cur++; // : - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - } - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_string; - } - else - { - _cur_lexeme = lex_none; - } - } - - _cur = cur; - } - - lexeme_t current() const - { - return _cur_lexeme; - } - - const char_t* current_pos() const - { - return _cur_lexeme_pos; - } - - const xpath_lexer_string& contents() const - { - assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); - - return _cur_lexeme_contents; - } - }; - - enum ast_type_t - { - ast_unknown, - ast_op_or, // left or right - ast_op_and, // left and right - ast_op_equal, // left = right - ast_op_not_equal, // left != right - ast_op_less, // left < right - ast_op_greater, // left > right - ast_op_less_or_equal, // left <= right - ast_op_greater_or_equal, // left >= right - ast_op_add, // left + right - ast_op_subtract, // left - right - ast_op_multiply, // left * right - ast_op_divide, // left / right - ast_op_mod, // left % right - ast_op_negate, // left - right - ast_op_union, // left | right - ast_predicate, // apply predicate to set; next points to next predicate - ast_filter, // select * from left where right - ast_string_constant, // string constant - ast_number_constant, // number constant - ast_variable, // variable - ast_func_last, // last() - ast_func_position, // position() - ast_func_count, // count(left) - ast_func_id, // id(left) - ast_func_local_name_0, // local-name() - ast_func_local_name_1, // local-name(left) - ast_func_namespace_uri_0, // namespace-uri() - ast_func_namespace_uri_1, // namespace-uri(left) - ast_func_name_0, // name() - ast_func_name_1, // name(left) - ast_func_string_0, // string() - ast_func_string_1, // string(left) - ast_func_concat, // concat(left, right, siblings) - ast_func_starts_with, // starts_with(left, right) - ast_func_contains, // contains(left, right) - ast_func_substring_before, // substring-before(left, right) - ast_func_substring_after, // substring-after(left, right) - ast_func_substring_2, // substring(left, right) - ast_func_substring_3, // substring(left, right, third) - ast_func_string_length_0, // string-length() - ast_func_string_length_1, // string-length(left) - ast_func_normalize_space_0, // normalize-space() - ast_func_normalize_space_1, // normalize-space(left) - ast_func_translate, // translate(left, right, third) - ast_func_boolean, // boolean(left) - ast_func_not, // not(left) - ast_func_true, // true() - ast_func_false, // false() - ast_func_lang, // lang(left) - ast_func_number_0, // number() - ast_func_number_1, // number(left) - ast_func_sum, // sum(left) - ast_func_floor, // floor(left) - ast_func_ceiling, // ceiling(left) - ast_func_round, // round(left) - ast_step, // process set left with step - ast_step_root, // select root node - - ast_opt_translate_table, // translate(left, right, third) where right/third are constants - ast_opt_compare_attribute // @name = 'string' - }; - - enum axis_t - { - axis_ancestor, - axis_ancestor_or_self, - axis_attribute, - axis_child, - axis_descendant, - axis_descendant_or_self, - axis_following, - axis_following_sibling, - axis_namespace, - axis_parent, - axis_preceding, - axis_preceding_sibling, - axis_self - }; - - enum nodetest_t - { - nodetest_none, - nodetest_name, - nodetest_type_node, - nodetest_type_comment, - nodetest_type_pi, - nodetest_type_text, - nodetest_pi, - nodetest_all, - nodetest_all_in_namespace - }; - - enum predicate_t - { - predicate_default, - predicate_posinv, - predicate_constant, - predicate_constant_one - }; - - enum nodeset_eval_t - { - nodeset_eval_all, - nodeset_eval_any, - nodeset_eval_first - }; - - template struct axis_to_type - { - static const axis_t axis; - }; - - template const axis_t axis_to_type::axis = N; - - class xpath_ast_node - { - private: - // node type - char _type; - char _rettype; - - // for ast_step - char _axis; - - // for ast_step/ast_predicate/ast_filter - char _test; - - // tree node structure - xpath_ast_node* _left; - xpath_ast_node* _right; - xpath_ast_node* _next; - - union - { - // value for ast_string_constant - const char_t* string; - // value for ast_number_constant - double number; - // variable for ast_variable - xpath_variable* variable; - // node test for ast_step (node name/namespace/node type/pi target) - const char_t* nodetest; - // table for ast_opt_translate_table - const unsigned char* table; - } _data; - - xpath_ast_node(const xpath_ast_node&); - xpath_ast_node& operator=(const xpath_ast_node&); - - template static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) - { - xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); - - if (lt != xpath_type_node_set && rt != xpath_type_node_set) - { - if (lt == xpath_type_boolean || rt == xpath_type_boolean) - return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); - else if (lt == xpath_type_number || rt == xpath_type_number) - return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); - else if (lt == xpath_type_string || rt == xpath_type_string) - { - xpath_allocator_capture cr(stack.result); - - xpath_string ls = lhs->eval_string(c, stack); - xpath_string rs = rhs->eval_string(c, stack); - - return comp(ls, rs); - } - } - else if (lt == xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(string_value(*li, stack.result), string_value(*ri, stack.result))) - return true; - } - - return false; - } - else - { - if (lt == xpath_type_node_set) - { - swap(lhs, rhs); - swap(lt, rt); - } - - if (lt == xpath_type_boolean) - return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); - else if (lt == xpath_type_number) - { - xpath_allocator_capture cr(stack.result); - - double l = lhs->eval_number(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - - return false; - } - else if (lt == xpath_type_string) - { - xpath_allocator_capture cr(stack.result); - - xpath_string l = lhs->eval_string(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, string_value(*ri, stack.result))) - return true; - } - - return false; - } - } - - assert(false && "Wrong types"); - return false; - } - - static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval) - { - return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any; - } - - template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) - { - xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); - - if (lt != xpath_type_node_set && rt != xpath_type_node_set) - return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); - else if (lt == xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - { - xpath_allocator_capture cri(stack.result); - - double l = convert_string_to_number(string_value(*li, stack.result).c_str()); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture crii(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - } - - return false; - } - else if (lt != xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - double l = lhs->eval_number(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - - return false; - } - else if (lt == xpath_type_node_set && rt != xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); - double r = rhs->eval_number(c, stack); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - { - xpath_allocator_capture cri(stack.result); - - if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r)) - return true; - } - - return false; - } - else - { - assert(false && "Wrong types"); - return false; - } - } - - static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) - { - assert(ns.size() >= first); - assert(expr->rettype() != xpath_type_number); - - size_t i = 1; - size_t size = ns.size() - first; - - xpath_node* last = ns.begin() + first; - - // remove_if... or well, sort of - for (xpath_node* it = last; it != ns.end(); ++it, ++i) - { - xpath_context c(*it, i, size); - - if (expr->eval_boolean(c, stack)) - { - *last++ = *it; - - if (once) break; - } - } - - ns.truncate(last); - } - - static void apply_predicate_number(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) - { - assert(ns.size() >= first); - assert(expr->rettype() == xpath_type_number); - - size_t i = 1; - size_t size = ns.size() - first; - - xpath_node* last = ns.begin() + first; - - // remove_if... or well, sort of - for (xpath_node* it = last; it != ns.end(); ++it, ++i) - { - xpath_context c(*it, i, size); - - if (expr->eval_number(c, stack) == i) - { - *last++ = *it; - - if (once) break; - } - } - - ns.truncate(last); - } - - static void apply_predicate_number_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) - { - assert(ns.size() >= first); - assert(expr->rettype() == xpath_type_number); - - size_t size = ns.size() - first; - - xpath_node* last = ns.begin() + first; - - xpath_context c(xpath_node(), 1, size); - - double er = expr->eval_number(c, stack); - - if (er >= 1.0 && er <= size) - { - size_t eri = static_cast(er); - - if (er == eri) - { - xpath_node r = last[eri - 1]; - - *last++ = r; - } - } - - ns.truncate(last); - } - - void apply_predicate(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, bool once) - { - if (ns.size() == first) return; - - assert(_type == ast_filter || _type == ast_predicate); - - if (_test == predicate_constant || _test == predicate_constant_one) - apply_predicate_number_const(ns, first, _right, stack); - else if (_right->rettype() == xpath_type_number) - apply_predicate_number(ns, first, _right, stack, once); - else - apply_predicate_boolean(ns, first, _right, stack, once); - } - - void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval) - { - if (ns.size() == first) return; - - bool last_once = eval_once(ns.type(), eval); - - for (xpath_ast_node* pred = _right; pred; pred = pred->_next) - pred->apply_predicate(ns, first, stack, !pred->_next && last_once); - } - - bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc) - { - assert(a); - - const char_t* name = a->name ? a->name + 0 : PUGIXML_TEXT(""); - - switch (_test) - { - case nodetest_name: - if (strequal(name, _data.nodetest) && is_xpath_attribute(name)) - { - ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); - return true; - } - break; - - case nodetest_type_node: - case nodetest_all: - if (is_xpath_attribute(name)) - { - ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); - return true; - } - break; - - case nodetest_all_in_namespace: - if (starts_with(name, _data.nodetest) && is_xpath_attribute(name)) - { - ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); - return true; - } - break; - - default: - ; - } - - return false; - } - - bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc) - { - assert(n); - - xml_node_type type = PUGI__NODETYPE(n); - - switch (_test) - { - case nodetest_name: - if (type == node_element && n->name && strequal(n->name, _data.nodetest)) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_type_node: - ns.push_back(xml_node(n), alloc); - return true; - - case nodetest_type_comment: - if (type == node_comment) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_type_text: - if (type == node_pcdata || type == node_cdata) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_type_pi: - if (type == node_pi) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_pi: - if (type == node_pi && n->name && strequal(n->name, _data.nodetest)) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_all: - if (type == node_element) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - case nodetest_all_in_namespace: - if (type == node_element && n->name && starts_with(n->name, _data.nodetest)) - { - ns.push_back(xml_node(n), alloc); - return true; - } - break; - - default: - assert(false && "Unknown axis"); - } - - return false; - } - - template void step_fill(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc, bool once, T) - { - const axis_t axis = T::axis; - - switch (axis) - { - case axis_attribute: - { - for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute) - if (step_push(ns, a, n, alloc) & once) - return; - - break; - } - - case axis_child: - { - for (xml_node_struct* c = n->first_child; c; c = c->next_sibling) - if (step_push(ns, c, alloc) & once) - return; - - break; - } - - case axis_descendant: - case axis_descendant_or_self: - { - if (axis == axis_descendant_or_self) - if (step_push(ns, n, alloc) & once) - return; - - xml_node_struct* cur = n->first_child; - - while (cur) - { - if (step_push(ns, cur, alloc) & once) - return; - - if (cur->first_child) - cur = cur->first_child; - else - { - while (!cur->next_sibling) - { - cur = cur->parent; - - if (cur == n) return; - } - - cur = cur->next_sibling; - } - } - - break; - } - - case axis_following_sibling: - { - for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling) - if (step_push(ns, c, alloc) & once) - return; - - break; - } - - case axis_preceding_sibling: - { - for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c) - if (step_push(ns, c, alloc) & once) - return; - - break; - } - - case axis_following: - { - xml_node_struct* cur = n; - - // exit from this node so that we don't include descendants - while (!cur->next_sibling) - { - cur = cur->parent; - - if (!cur) return; - } - - cur = cur->next_sibling; - - while (cur) - { - if (step_push(ns, cur, alloc) & once) - return; - - if (cur->first_child) - cur = cur->first_child; - else - { - while (!cur->next_sibling) - { - cur = cur->parent; - - if (!cur) return; - } - - cur = cur->next_sibling; - } - } - - break; - } - - case axis_preceding: - { - xml_node_struct* cur = n; - - // exit from this node so that we don't include descendants - while (!cur->prev_sibling_c->next_sibling) - { - cur = cur->parent; - - if (!cur) return; - } - - cur = cur->prev_sibling_c; - - while (cur) - { - if (cur->first_child) - cur = cur->first_child->prev_sibling_c; - else - { - // leaf node, can't be ancestor - if (step_push(ns, cur, alloc) & once) - return; - - while (!cur->prev_sibling_c->next_sibling) - { - cur = cur->parent; - - if (!cur) return; - - if (!node_is_ancestor(cur, n)) - if (step_push(ns, cur, alloc) & once) - return; - } - - cur = cur->prev_sibling_c; - } - } - - break; - } - - case axis_ancestor: - case axis_ancestor_or_self: - { - if (axis == axis_ancestor_or_self) - if (step_push(ns, n, alloc) & once) - return; - - xml_node_struct* cur = n->parent; - - while (cur) - { - if (step_push(ns, cur, alloc) & once) - return; - - cur = cur->parent; - } - - break; - } - - case axis_self: - { - step_push(ns, n, alloc); - - break; - } - - case axis_parent: - { - if (n->parent) - step_push(ns, n->parent, alloc); - - break; - } - - default: - assert(false && "Unimplemented axis"); - } - } - - template void step_fill(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* p, xpath_allocator* alloc, bool once, T v) - { - const axis_t axis = T::axis; - - switch (axis) - { - case axis_ancestor: - case axis_ancestor_or_self: - { - if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test - if (step_push(ns, a, p, alloc) & once) - return; - - xml_node_struct* cur = p; - - while (cur) - { - if (step_push(ns, cur, alloc) & once) - return; - - cur = cur->parent; - } - - break; - } - - case axis_descendant_or_self: - case axis_self: - { - if (_test == nodetest_type_node) // reject attributes based on principal node type test - step_push(ns, a, p, alloc); - - break; - } - - case axis_following: - { - xml_node_struct* cur = p; - - while (cur) - { - if (cur->first_child) - cur = cur->first_child; - else - { - while (!cur->next_sibling) - { - cur = cur->parent; - - if (!cur) return; - } - - cur = cur->next_sibling; - } - - if (step_push(ns, cur, alloc) & once) - return; - } - - break; - } - - case axis_parent: - { - step_push(ns, p, alloc); - - break; - } - - case axis_preceding: - { - // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding - step_fill(ns, p, alloc, once, v); - break; - } - - default: - assert(false && "Unimplemented axis"); - } - } - - template void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v) - { - const axis_t axis = T::axis; - const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); - - if (xn.node()) - step_fill(ns, xn.node().internal_object(), alloc, once, v); - else if (axis_has_attributes && xn.attribute() && xn.parent()) - step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v); - } - - template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v) - { - const axis_t axis = T::axis; - const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); - const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; - - bool once = - (axis == axis_attribute && _test == nodetest_name) || - (!_right && eval_once(axis_type, eval)) || - (_right && !_right->_next && _right->_test == predicate_constant_one); - - xpath_node_set_raw ns; - ns.set_type(axis_type); - - if (_left) - { - xpath_node_set_raw s = _left->eval_node_set(c, stack, nodeset_eval_all); - - // self axis preserves the original order - if (axis == axis_self) ns.set_type(s.type()); - - for (const xpath_node* it = s.begin(); it != s.end(); ++it) - { - size_t size = ns.size(); - - // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes - if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); - - step_fill(ns, *it, stack.result, once, v); - if (_right) apply_predicates(ns, size, stack, eval); - } - } - else - { - step_fill(ns, c.n, stack.result, once, v); - if (_right) apply_predicates(ns, 0, stack, eval); - } - - // child, attribute and self axes always generate unique set of nodes - // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice - if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) - ns.remove_duplicates(); - - return ns; - } - - public: - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_string_constant); - _data.string = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_number_constant); - _data.number = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_variable); - _data.variable = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) - { - } - - xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): - _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(0), _next(0) - { - assert(type == ast_step); - _data.nodetest = contents; - } - - xpath_ast_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test): - _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast(test)), _left(left), _right(right), _next(0) - { - assert(type == ast_filter || type == ast_predicate); - } - - void set_next(xpath_ast_node* value) - { - _next = value; - } - - void set_right(xpath_ast_node* value) - { - _right = value; - } - - bool eval_boolean(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_op_or: - return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); - - case ast_op_and: - return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); - - case ast_op_equal: - return compare_eq(_left, _right, c, stack, equal_to()); - - case ast_op_not_equal: - return compare_eq(_left, _right, c, stack, not_equal_to()); - - case ast_op_less: - return compare_rel(_left, _right, c, stack, less()); - - case ast_op_greater: - return compare_rel(_right, _left, c, stack, less()); - - case ast_op_less_or_equal: - return compare_rel(_left, _right, c, stack, less_equal()); - - case ast_op_greater_or_equal: - return compare_rel(_right, _left, c, stack, less_equal()); - - case ast_func_starts_with: - { - xpath_allocator_capture cr(stack.result); - - xpath_string lr = _left->eval_string(c, stack); - xpath_string rr = _right->eval_string(c, stack); - - return starts_with(lr.c_str(), rr.c_str()); - } - - case ast_func_contains: - { - xpath_allocator_capture cr(stack.result); - - xpath_string lr = _left->eval_string(c, stack); - xpath_string rr = _right->eval_string(c, stack); - - return find_substring(lr.c_str(), rr.c_str()) != 0; - } - - case ast_func_boolean: - return _left->eval_boolean(c, stack); - - case ast_func_not: - return !_left->eval_boolean(c, stack); - - case ast_func_true: - return true; - - case ast_func_false: - return false; - - case ast_func_lang: - { - if (c.n.attribute()) return false; - - xpath_allocator_capture cr(stack.result); - - xpath_string lang = _left->eval_string(c, stack); - - for (xml_node n = c.n.node(); n; n = n.parent()) - { - xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); - - if (a) - { - const char_t* value = a.value(); - - // strnicmp / strncasecmp is not portable - for (const char_t* lit = lang.c_str(); *lit; ++lit) - { - if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; - ++value; - } - - return *value == 0 || *value == '-'; - } - } - - return false; - } - - case ast_opt_compare_attribute: - { - const char_t* value = (_right->_type == ast_string_constant) ? _right->_data.string : _right->_data.variable->get_string(); - - xml_attribute attr = c.n.node().attribute(_left->_data.nodetest); - - return attr && strequal(attr.value(), value) && is_xpath_attribute(attr.name()); - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_boolean) - return _data.variable->get_boolean(); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_number: - return convert_number_to_boolean(eval_number(c, stack)); - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return !eval_string(c, stack).empty(); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return !eval_node_set(c, stack, nodeset_eval_any).empty(); - } - - default: - assert(false && "Wrong expression for return type boolean"); - return false; - } - } - } - } - - double eval_number(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_op_add: - return _left->eval_number(c, stack) + _right->eval_number(c, stack); - - case ast_op_subtract: - return _left->eval_number(c, stack) - _right->eval_number(c, stack); - - case ast_op_multiply: - return _left->eval_number(c, stack) * _right->eval_number(c, stack); - - case ast_op_divide: - return _left->eval_number(c, stack) / _right->eval_number(c, stack); - - case ast_op_mod: - return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack)); - - case ast_op_negate: - return -_left->eval_number(c, stack); - - case ast_number_constant: - return _data.number; - - case ast_func_last: - return static_cast(c.size); - - case ast_func_position: - return static_cast(c.position); - - case ast_func_count: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(_left->eval_node_set(c, stack, nodeset_eval_all).size()); - } - - case ast_func_string_length_0: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(string_value(c.n, stack.result).length()); - } - - case ast_func_string_length_1: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(_left->eval_string(c, stack).length()); - } - - case ast_func_number_0: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(string_value(c.n, stack.result).c_str()); - } - - case ast_func_number_1: - return _left->eval_number(c, stack); - - case ast_func_sum: - { - xpath_allocator_capture cr(stack.result); - - double r = 0; - - xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all); - - for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) - { - xpath_allocator_capture cri(stack.result); - - r += convert_string_to_number(string_value(*it, stack.result).c_str()); - } - - return r; - } - - case ast_func_floor: - { - double r = _left->eval_number(c, stack); - - return r == r ? floor(r) : r; - } - - case ast_func_ceiling: - { - double r = _left->eval_number(c, stack); - - return r == r ? ceil(r) : r; - } - - case ast_func_round: - return round_nearest_nzero(_left->eval_number(c, stack)); - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_number) - return _data.variable->get_number(); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_boolean: - return eval_boolean(c, stack) ? 1 : 0; - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - default: - assert(false && "Wrong expression for return type number"); - return 0; - } - - } - } - } - - xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) - { - assert(_type == ast_func_concat); - - xpath_allocator_capture ct(stack.temp); - - // count the string number - size_t count = 1; - for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; - - // gather all strings - xpath_string static_buffer[4]; - xpath_string* buffer = static_buffer; - - // allocate on-heap for large concats - if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) - { - buffer = static_cast(stack.temp->allocate(count * sizeof(xpath_string))); - assert(buffer); - } - - // evaluate all strings to temporary stack - xpath_stack swapped_stack = {stack.temp, stack.result}; - - buffer[0] = _left->eval_string(c, swapped_stack); - - size_t pos = 1; - for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); - assert(pos == count); - - // get total length - size_t length = 0; - for (size_t i = 0; i < count; ++i) length += buffer[i].length(); - - // create final string - char_t* result = static_cast(stack.result->allocate((length + 1) * sizeof(char_t))); - assert(result); - - char_t* ri = result; - - for (size_t j = 0; j < count; ++j) - for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) - *ri++ = *bi; - - *ri = 0; - - return xpath_string::from_heap_preallocated(result, ri); - } - - xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_string_constant: - return xpath_string::from_const(_data.string); - - case ast_func_local_name_0: - { - xpath_node na = c.n; - - return xpath_string::from_const(local_name(na)); - } - - case ast_func_local_name_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); - xpath_node na = ns.first(); - - return xpath_string::from_const(local_name(na)); - } - - case ast_func_name_0: - { - xpath_node na = c.n; - - return xpath_string::from_const(qualified_name(na)); - } - - case ast_func_name_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); - xpath_node na = ns.first(); - - return xpath_string::from_const(qualified_name(na)); - } - - case ast_func_namespace_uri_0: - { - xpath_node na = c.n; - - return xpath_string::from_const(namespace_uri(na)); - } - - case ast_func_namespace_uri_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); - xpath_node na = ns.first(); - - return xpath_string::from_const(namespace_uri(na)); - } - - case ast_func_string_0: - return string_value(c.n, stack.result); - - case ast_func_string_1: - return _left->eval_string(c, stack); - - case ast_func_concat: - return eval_string_concat(c, stack); - - case ast_func_substring_before: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - xpath_string p = _right->eval_string(c, swapped_stack); - - const char_t* pos = find_substring(s.c_str(), p.c_str()); - - return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string(); - } - - case ast_func_substring_after: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - xpath_string p = _right->eval_string(c, swapped_stack); - - const char_t* pos = find_substring(s.c_str(), p.c_str()); - if (!pos) return xpath_string(); - - const char_t* rbegin = pos + p.length(); - const char_t* rend = s.c_str() + s.length(); - - return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); - } - - case ast_func_substring_2: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - size_t s_length = s.length(); - - double first = round_nearest(_right->eval_number(c, stack)); - - if (is_nan(first)) return xpath_string(); // NaN - else if (first >= s_length + 1) return xpath_string(); - - size_t pos = first < 1 ? 1 : static_cast(first); - assert(1 <= pos && pos <= s_length + 1); - - const char_t* rbegin = s.c_str() + (pos - 1); - const char_t* rend = s.c_str() + s.length(); - - return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); - } - - case ast_func_substring_3: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - size_t s_length = s.length(); - - double first = round_nearest(_right->eval_number(c, stack)); - double last = first + round_nearest(_right->_next->eval_number(c, stack)); - - if (is_nan(first) || is_nan(last)) return xpath_string(); - else if (first >= s_length + 1) return xpath_string(); - else if (first >= last) return xpath_string(); - else if (last < 1) return xpath_string(); - - size_t pos = first < 1 ? 1 : static_cast(first); - size_t end = last >= s_length + 1 ? s_length + 1 : static_cast(last); - - assert(1 <= pos && pos <= end && end <= s_length + 1); - const char_t* rbegin = s.c_str() + (pos - 1); - const char_t* rend = s.c_str() + (end - 1); - - return (end == s_length + 1 && !s.uses_heap()) ? xpath_string::from_const(rbegin) : xpath_string::from_heap(rbegin, rend, stack.result); - } - - case ast_func_normalize_space_0: - { - xpath_string s = string_value(c.n, stack.result); - - char_t* begin = s.data(stack.result); - char_t* end = normalize_space(begin); - - return xpath_string::from_heap_preallocated(begin, end); - } - - case ast_func_normalize_space_1: - { - xpath_string s = _left->eval_string(c, stack); - - char_t* begin = s.data(stack.result); - char_t* end = normalize_space(begin); - - return xpath_string::from_heap_preallocated(begin, end); - } - - case ast_func_translate: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, stack); - xpath_string from = _right->eval_string(c, swapped_stack); - xpath_string to = _right->_next->eval_string(c, swapped_stack); - - char_t* begin = s.data(stack.result); - char_t* end = translate(begin, from.c_str(), to.c_str(), to.length()); - - return xpath_string::from_heap_preallocated(begin, end); - } - - case ast_opt_translate_table: - { - xpath_string s = _left->eval_string(c, stack); - - char_t* begin = s.data(stack.result); - char_t* end = translate_table(begin, _data.table); - - return xpath_string::from_heap_preallocated(begin, end); - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_string) - return xpath_string::from_const(_data.variable->get_string()); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_boolean: - return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); - - case xpath_type_number: - return convert_number_to_string(eval_number(c, stack), stack.result); - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); - return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); - } - - default: - assert(false && "Wrong expression for return type string"); - return xpath_string(); - } - } - } - } - - xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval) - { - switch (_type) - { - case ast_op_union: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack, eval); - xpath_node_set_raw rs = _right->eval_node_set(c, stack, eval); - - // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother - rs.set_type(xpath_node_set::type_unsorted); - - rs.append(ls.begin(), ls.end(), stack.result); - rs.remove_duplicates(); - - return rs; - } - - case ast_filter: - { - xpath_node_set_raw set = _left->eval_node_set(c, stack, _test == predicate_constant_one ? nodeset_eval_first : nodeset_eval_all); - - // either expression is a number or it contains position() call; sort by document order - if (_test != predicate_posinv) set.sort_do(); - - bool once = eval_once(set.type(), eval); - - apply_predicate(set, 0, stack, once); - - return set; - } - - case ast_func_id: - return xpath_node_set_raw(); - - case ast_step: - { - switch (_axis) - { - case axis_ancestor: - return step_do(c, stack, eval, axis_to_type()); - - case axis_ancestor_or_self: - return step_do(c, stack, eval, axis_to_type()); - - case axis_attribute: - return step_do(c, stack, eval, axis_to_type()); - - case axis_child: - return step_do(c, stack, eval, axis_to_type()); - - case axis_descendant: - return step_do(c, stack, eval, axis_to_type()); - - case axis_descendant_or_self: - return step_do(c, stack, eval, axis_to_type()); - - case axis_following: - return step_do(c, stack, eval, axis_to_type()); - - case axis_following_sibling: - return step_do(c, stack, eval, axis_to_type()); - - case axis_namespace: - // namespaced axis is not supported - return xpath_node_set_raw(); - - case axis_parent: - return step_do(c, stack, eval, axis_to_type()); - - case axis_preceding: - return step_do(c, stack, eval, axis_to_type()); - - case axis_preceding_sibling: - return step_do(c, stack, eval, axis_to_type()); - - case axis_self: - return step_do(c, stack, eval, axis_to_type()); - - default: - assert(false && "Unknown axis"); - return xpath_node_set_raw(); - } - } - - case ast_step_root: - { - assert(!_right); // root step can't have any predicates - - xpath_node_set_raw ns; - - ns.set_type(xpath_node_set::type_sorted); - - if (c.n.node()) ns.push_back(c.n.node().root(), stack.result); - else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result); - - return ns; - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_node_set) - { - const xpath_node_set& s = _data.variable->get_node_set(); - - xpath_node_set_raw ns; - - ns.set_type(s.type()); - ns.append(s.begin(), s.end(), stack.result); - - return ns; - } - - // fallthrough to type conversion - } - - default: - assert(false && "Wrong expression for return type node set"); - return xpath_node_set_raw(); - } - } - - void optimize(xpath_allocator* alloc) - { - if (_left) - _left->optimize(alloc); - - if (_right) - _right->optimize(alloc); - - if (_next) - _next->optimize(alloc); - - optimize_self(alloc); - } - - void optimize_self(xpath_allocator* alloc) - { - // Rewrite [position()=expr] with [expr] - // Note that this step has to go before classification to recognize [position()=1] - if ((_type == ast_filter || _type == ast_predicate) && - _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number) - { - _right = _right->_right; - } - - // Classify filter/predicate ops to perform various optimizations during evaluation - if (_type == ast_filter || _type == ast_predicate) - { - assert(_test == predicate_default); - - if (_right->_type == ast_number_constant && _right->_data.number == 1.0) - _test = predicate_constant_one; - else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last)) - _test = predicate_constant; - else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr()) - _test = predicate_posinv; - } - - // Rewrite descendant-or-self::node()/child::foo with descendant::foo - // The former is a full form of //foo, the latter is much faster since it executes the node test immediately - // Do a similar kind of rewrite for self/descendant/descendant-or-self axes - // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1]) - if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && _left && - _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right && - is_posinv_step()) - { - if (_axis == axis_child || _axis == axis_descendant) - _axis = axis_descendant; - else - _axis = axis_descendant_or_self; - - _left = _left->_left; - } - - // Use optimized lookup table implementation for translate() with constant arguments - if (_type == ast_func_translate && _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant) - { - unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string); - - if (table) - { - _type = ast_opt_translate_table; - _data.table = table; - } - } - - // Use optimized path for @attr = 'value' or @attr = $value - if (_type == ast_op_equal && - _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right && - (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string))) - { - _type = ast_opt_compare_attribute; - } - } - - bool is_posinv_expr() const - { - switch (_type) - { - case ast_func_position: - case ast_func_last: - return false; - - case ast_string_constant: - case ast_number_constant: - case ast_variable: - return true; - - case ast_step: - case ast_step_root: - return true; - - case ast_predicate: - case ast_filter: - return true; - - default: - if (_left && !_left->is_posinv_expr()) return false; - - for (xpath_ast_node* n = _right; n; n = n->_next) - if (!n->is_posinv_expr()) return false; - - return true; - } - } - - bool is_posinv_step() const - { - assert(_type == ast_step); - - for (xpath_ast_node* n = _right; n; n = n->_next) - { - assert(n->_type == ast_predicate); - - if (n->_test != predicate_posinv) - return false; - } - - return true; - } - - xpath_value_type rettype() const - { - return static_cast(_rettype); - } - }; - - struct xpath_parser - { - xpath_allocator* _alloc; - xpath_lexer _lexer; - - const char_t* _query; - xpath_variable_set* _variables; - - xpath_parse_result* _result; - - char_t _scratch[32]; - - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf _error_handler; - #endif - - void throw_error(const char* message) - { - _result->error = message; - _result->offset = _lexer.current_pos() - _query; - - #ifdef PUGIXML_NO_EXCEPTIONS - longjmp(_error_handler, 1); - #else - throw xpath_exception(*_result); - #endif - } - - void throw_error_oom() - { - #ifdef PUGIXML_NO_EXCEPTIONS - throw_error("Out of memory"); - #else - throw std::bad_alloc(); - #endif - } - - void* alloc_node() - { - void* result = _alloc->allocate_nothrow(sizeof(xpath_ast_node)); - - if (!result) throw_error_oom(); - - return result; - } - - const char_t* alloc_string(const xpath_lexer_string& value) - { - if (value.begin) - { - size_t length = static_cast(value.end - value.begin); - - char_t* c = static_cast(_alloc->allocate_nothrow((length + 1) * sizeof(char_t))); - if (!c) throw_error_oom(); - assert(c); // workaround for clang static analysis - - memcpy(c, value.begin, length * sizeof(char_t)); - c[length] = 0; - - return c; - } - else return 0; - } - - xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2]) - { - assert(argc <= 1); - - if (argc == 1 && args[0]->rettype() != xpath_type_node_set) - throw_error("Function has to be applied to node set"); - - return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]); - } - - xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) - { - switch (name.begin[0]) - { - case 'b': - if (name == PUGIXML_TEXT("boolean") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]); - - break; - - case 'c': - if (name == PUGIXML_TEXT("count") && argc == 1) - { - if (args[0]->rettype() != xpath_type_node_set) - throw_error("Function has to be applied to node set"); - - return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]); - } - else if (name == PUGIXML_TEXT("contains") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]); - else if (name == PUGIXML_TEXT("concat") && argc >= 2) - return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("ceiling") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]); - - break; - - case 'f': - if (name == PUGIXML_TEXT("false") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean); - else if (name == PUGIXML_TEXT("floor") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]); - - break; - - case 'i': - if (name == PUGIXML_TEXT("id") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]); - - break; - - case 'l': - if (name == PUGIXML_TEXT("last") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number); - else if (name == PUGIXML_TEXT("lang") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]); - else if (name == PUGIXML_TEXT("local-name") && argc <= 1) - return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args); - - break; - - case 'n': - if (name == PUGIXML_TEXT("name") && argc <= 1) - return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args); - else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) - return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args); - else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("not") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]); - else if (name == PUGIXML_TEXT("number") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); - - break; - - case 'p': - if (name == PUGIXML_TEXT("position") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number); - - break; - - case 'r': - if (name == PUGIXML_TEXT("round") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]); - - break; - - case 's': - if (name == PUGIXML_TEXT("string") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); - else if (name == PUGIXML_TEXT("string-length") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]); - else if (name == PUGIXML_TEXT("starts-with") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring-before") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring-after") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3)) - return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("sum") && argc == 1) - { - if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); - return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]); - } - - break; - - case 't': - if (name == PUGIXML_TEXT("translate") && argc == 3) - return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("true") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean); - - break; - - default: - break; - } - - throw_error("Unrecognized function or wrong parameter count"); - - return 0; - } - - axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified) - { - specified = true; - - switch (name.begin[0]) - { - case 'a': - if (name == PUGIXML_TEXT("ancestor")) - return axis_ancestor; - else if (name == PUGIXML_TEXT("ancestor-or-self")) - return axis_ancestor_or_self; - else if (name == PUGIXML_TEXT("attribute")) - return axis_attribute; - - break; - - case 'c': - if (name == PUGIXML_TEXT("child")) - return axis_child; - - break; - - case 'd': - if (name == PUGIXML_TEXT("descendant")) - return axis_descendant; - else if (name == PUGIXML_TEXT("descendant-or-self")) - return axis_descendant_or_self; - - break; - - case 'f': - if (name == PUGIXML_TEXT("following")) - return axis_following; - else if (name == PUGIXML_TEXT("following-sibling")) - return axis_following_sibling; - - break; - - case 'n': - if (name == PUGIXML_TEXT("namespace")) - return axis_namespace; - - break; - - case 'p': - if (name == PUGIXML_TEXT("parent")) - return axis_parent; - else if (name == PUGIXML_TEXT("preceding")) - return axis_preceding; - else if (name == PUGIXML_TEXT("preceding-sibling")) - return axis_preceding_sibling; - - break; - - case 's': - if (name == PUGIXML_TEXT("self")) - return axis_self; - - break; - - default: - break; - } - - specified = false; - return axis_child; - } - - nodetest_t parse_node_test_type(const xpath_lexer_string& name) - { - switch (name.begin[0]) - { - case 'c': - if (name == PUGIXML_TEXT("comment")) - return nodetest_type_comment; - - break; - - case 'n': - if (name == PUGIXML_TEXT("node")) - return nodetest_type_node; - - break; - - case 'p': - if (name == PUGIXML_TEXT("processing-instruction")) - return nodetest_type_pi; - - break; - - case 't': - if (name == PUGIXML_TEXT("text")) - return nodetest_type_text; - - break; - - default: - break; - } - - return nodetest_none; - } - - // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall - xpath_ast_node* parse_primary_expression() - { - switch (_lexer.current()) - { - case lex_var_ref: - { - xpath_lexer_string name = _lexer.contents(); - - if (!_variables) - throw_error("Unknown variable: variable set is not provided"); - - xpath_variable* var = 0; - if (!get_variable_scratch(_scratch, _variables, name.begin, name.end, &var)) - throw_error_oom(); - - if (!var) - throw_error("Unknown variable: variable set does not contain the given name"); - - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var); - } - - case lex_open_brace: - { - _lexer.next(); - - xpath_ast_node* n = parse_expression(); - - if (_lexer.current() != lex_close_brace) - throw_error("Unmatched braces"); - - _lexer.next(); - - return n; - } - - case lex_quoted_string: - { - const char_t* value = alloc_string(_lexer.contents()); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value); - _lexer.next(); - - return n; - } - - case lex_number: - { - double value = 0; - - if (!convert_string_to_number_scratch(_scratch, _lexer.contents().begin, _lexer.contents().end, &value)) - throw_error_oom(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value); - _lexer.next(); - - return n; - } - - case lex_string: - { - xpath_ast_node* args[2] = {0}; - size_t argc = 0; - - xpath_lexer_string function = _lexer.contents(); - _lexer.next(); - - xpath_ast_node* last_arg = 0; - - if (_lexer.current() != lex_open_brace) - throw_error("Unrecognized function call"); - _lexer.next(); - - if (_lexer.current() != lex_close_brace) - args[argc++] = parse_expression(); - - while (_lexer.current() != lex_close_brace) - { - if (_lexer.current() != lex_comma) - throw_error("No comma between function arguments"); - _lexer.next(); - - xpath_ast_node* n = parse_expression(); - - if (argc < 2) args[argc] = n; - else last_arg->set_next(n); - - argc++; - last_arg = n; - } - - _lexer.next(); - - return parse_function(function, argc, args); - } - - default: - throw_error("Unrecognizable primary expression"); - - return 0; - } - } - - // FilterExpr ::= PrimaryExpr | FilterExpr Predicate - // Predicate ::= '[' PredicateExpr ']' - // PredicateExpr ::= Expr - xpath_ast_node* parse_filter_expression() - { - xpath_ast_node* n = parse_primary_expression(); - - while (_lexer.current() == lex_open_square_brace) - { - _lexer.next(); - - xpath_ast_node* expr = parse_expression(); - - if (n->rettype() != xpath_type_node_set) - throw_error("Predicate has to be applied to node set"); - - n = new (alloc_node()) xpath_ast_node(ast_filter, n, expr, predicate_default); - - if (_lexer.current() != lex_close_square_brace) - throw_error("Unmatched square brace"); - - _lexer.next(); - } - - return n; - } - - // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep - // AxisSpecifier ::= AxisName '::' | '@'? - // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' - // NameTest ::= '*' | NCName ':' '*' | QName - // AbbreviatedStep ::= '.' | '..' - xpath_ast_node* parse_step(xpath_ast_node* set) - { - if (set && set->rettype() != xpath_type_node_set) - throw_error("Step has to be applied to node set"); - - bool axis_specified = false; - axis_t axis = axis_child; // implied child axis - - if (_lexer.current() == lex_axis_attribute) - { - axis = axis_attribute; - axis_specified = true; - - _lexer.next(); - } - else if (_lexer.current() == lex_dot) - { - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); - } - else if (_lexer.current() == lex_double_dot) - { - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); - } - - nodetest_t nt_type = nodetest_none; - xpath_lexer_string nt_name; - - if (_lexer.current() == lex_string) - { - // node name test - nt_name = _lexer.contents(); - _lexer.next(); - - // was it an axis name? - if (_lexer.current() == lex_double_colon) - { - // parse axis name - if (axis_specified) - throw_error("Two axis specifiers in one step"); - - axis = parse_axis_name(nt_name, axis_specified); - - if (!axis_specified) - throw_error("Unknown axis"); - - // read actual node test - _lexer.next(); - - if (_lexer.current() == lex_multiply) - { - nt_type = nodetest_all; - nt_name = xpath_lexer_string(); - _lexer.next(); - } - else if (_lexer.current() == lex_string) - { - nt_name = _lexer.contents(); - _lexer.next(); - } - else throw_error("Unrecognized node test"); - } - - if (nt_type == nodetest_none) - { - // node type test or processing-instruction - if (_lexer.current() == lex_open_brace) - { - _lexer.next(); - - if (_lexer.current() == lex_close_brace) - { - _lexer.next(); - - nt_type = parse_node_test_type(nt_name); - - if (nt_type == nodetest_none) - throw_error("Unrecognized node type"); - - nt_name = xpath_lexer_string(); - } - else if (nt_name == PUGIXML_TEXT("processing-instruction")) - { - if (_lexer.current() != lex_quoted_string) - throw_error("Only literals are allowed as arguments to processing-instruction()"); - - nt_type = nodetest_pi; - nt_name = _lexer.contents(); - _lexer.next(); - - if (_lexer.current() != lex_close_brace) - throw_error("Unmatched brace near processing-instruction()"); - _lexer.next(); - } - else - { - throw_error("Unmatched brace near node type test"); - } - } - // QName or NCName:* - else - { - if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* - { - nt_name.end--; // erase * - - nt_type = nodetest_all_in_namespace; - } - else - { - nt_type = nodetest_name; - } - } - } - } - else if (_lexer.current() == lex_multiply) - { - nt_type = nodetest_all; - _lexer.next(); - } - else - { - throw_error("Unrecognized node test"); - } - - const char_t* nt_name_copy = alloc_string(nt_name); - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, nt_name_copy); - - xpath_ast_node* last = 0; - - while (_lexer.current() == lex_open_square_brace) - { - _lexer.next(); - - xpath_ast_node* expr = parse_expression(); - - xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, 0, expr, predicate_default); - - if (_lexer.current() != lex_close_square_brace) - throw_error("Unmatched square brace"); - _lexer.next(); - - if (last) last->set_next(pred); - else n->set_right(pred); - - last = pred; - } - - return n; - } - - // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step - xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) - { - xpath_ast_node* n = parse_step(set); - - while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) - { - lexeme_t l = _lexer.current(); - _lexer.next(); - - if (l == lex_double_slash) - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - - n = parse_step(n); - } - - return n; - } - - // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath - // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath - xpath_ast_node* parse_location_path() - { - if (_lexer.current() == lex_slash) - { - _lexer.next(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); - - // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path - lexeme_t l = _lexer.current(); - - if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) - return parse_relative_location_path(n); - else - return n; - } - else if (_lexer.current() == lex_double_slash) - { - _lexer.next(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - - return parse_relative_location_path(n); - } - - // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 - return parse_relative_location_path(0); - } - - // PathExpr ::= LocationPath - // | FilterExpr - // | FilterExpr '/' RelativeLocationPath - // | FilterExpr '//' RelativeLocationPath - // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr - // UnaryExpr ::= UnionExpr | '-' UnaryExpr - xpath_ast_node* parse_path_or_unary_expression() - { - // Clarification. - // PathExpr begins with either LocationPath or FilterExpr. - // FilterExpr begins with PrimaryExpr - // PrimaryExpr begins with '$' in case of it being a variable reference, - // '(' in case of it being an expression, string literal, number constant or - // function call. - - if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || - _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || - _lexer.current() == lex_string) - { - if (_lexer.current() == lex_string) - { - // This is either a function call, or not - if not, we shall proceed with location path - const char_t* state = _lexer.state(); - - while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; - - if (*state != '(') return parse_location_path(); - - // This looks like a function call; however this still can be a node-test. Check it. - if (parse_node_test_type(_lexer.contents()) != nodetest_none) - return parse_location_path(); - } - - xpath_ast_node* n = parse_filter_expression(); - - if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) - { - lexeme_t l = _lexer.current(); - _lexer.next(); - - if (l == lex_double_slash) - { - if (n->rettype() != xpath_type_node_set) - throw_error("Step has to be applied to node set"); - - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - } - - // select from location path - return parse_relative_location_path(n); - } - - return n; - } - else if (_lexer.current() == lex_minus) - { - _lexer.next(); - - // precedence 7+ - only parses union expressions - xpath_ast_node* expr = parse_expression_rec(parse_path_or_unary_expression(), 7); - - return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr); - } - else - { - return parse_location_path(); - } - } - - struct binary_op_t - { - ast_type_t asttype; - xpath_value_type rettype; - int precedence; - - binary_op_t(): asttype(ast_unknown), rettype(xpath_type_none), precedence(0) - { - } - - binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_): asttype(asttype_), rettype(rettype_), precedence(precedence_) - { - } - - static binary_op_t parse(xpath_lexer& lexer) - { - switch (lexer.current()) - { - case lex_string: - if (lexer.contents() == PUGIXML_TEXT("or")) - return binary_op_t(ast_op_or, xpath_type_boolean, 1); - else if (lexer.contents() == PUGIXML_TEXT("and")) - return binary_op_t(ast_op_and, xpath_type_boolean, 2); - else if (lexer.contents() == PUGIXML_TEXT("div")) - return binary_op_t(ast_op_divide, xpath_type_number, 6); - else if (lexer.contents() == PUGIXML_TEXT("mod")) - return binary_op_t(ast_op_mod, xpath_type_number, 6); - else - return binary_op_t(); - - case lex_equal: - return binary_op_t(ast_op_equal, xpath_type_boolean, 3); - - case lex_not_equal: - return binary_op_t(ast_op_not_equal, xpath_type_boolean, 3); - - case lex_less: - return binary_op_t(ast_op_less, xpath_type_boolean, 4); - - case lex_greater: - return binary_op_t(ast_op_greater, xpath_type_boolean, 4); - - case lex_less_or_equal: - return binary_op_t(ast_op_less_or_equal, xpath_type_boolean, 4); - - case lex_greater_or_equal: - return binary_op_t(ast_op_greater_or_equal, xpath_type_boolean, 4); - - case lex_plus: - return binary_op_t(ast_op_add, xpath_type_number, 5); - - case lex_minus: - return binary_op_t(ast_op_subtract, xpath_type_number, 5); - - case lex_multiply: - return binary_op_t(ast_op_multiply, xpath_type_number, 6); - - case lex_union: - return binary_op_t(ast_op_union, xpath_type_node_set, 7); - - default: - return binary_op_t(); - } - } - }; - - xpath_ast_node* parse_expression_rec(xpath_ast_node* lhs, int limit) - { - binary_op_t op = binary_op_t::parse(_lexer); - - while (op.asttype != ast_unknown && op.precedence >= limit) - { - _lexer.next(); - - xpath_ast_node* rhs = parse_path_or_unary_expression(); - - binary_op_t nextop = binary_op_t::parse(_lexer); - - while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence) - { - rhs = parse_expression_rec(rhs, nextop.precedence); - - nextop = binary_op_t::parse(_lexer); - } - - if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set)) - throw_error("Union operator has to be applied to node sets"); - - lhs = new (alloc_node()) xpath_ast_node(op.asttype, op.rettype, lhs, rhs); - - op = binary_op_t::parse(_lexer); - } - - return lhs; - } - - // Expr ::= OrExpr - // OrExpr ::= AndExpr | OrExpr 'or' AndExpr - // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr - // EqualityExpr ::= RelationalExpr - // | EqualityExpr '=' RelationalExpr - // | EqualityExpr '!=' RelationalExpr - // RelationalExpr ::= AdditiveExpr - // | RelationalExpr '<' AdditiveExpr - // | RelationalExpr '>' AdditiveExpr - // | RelationalExpr '<=' AdditiveExpr - // | RelationalExpr '>=' AdditiveExpr - // AdditiveExpr ::= MultiplicativeExpr - // | AdditiveExpr '+' MultiplicativeExpr - // | AdditiveExpr '-' MultiplicativeExpr - // MultiplicativeExpr ::= UnaryExpr - // | MultiplicativeExpr '*' UnaryExpr - // | MultiplicativeExpr 'div' UnaryExpr - // | MultiplicativeExpr 'mod' UnaryExpr - xpath_ast_node* parse_expression() - { - return parse_expression_rec(parse_path_or_unary_expression(), 0); - } - - xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) - { - } - - xpath_ast_node* parse() - { - xpath_ast_node* result = parse_expression(); - - // check if there are unparsed tokens left - if (_lexer.current() != lex_eof) - throw_error("Incorrect query"); - - return result; - } - - static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) - { - xpath_parser parser(query, variables, alloc, result); - - #ifdef PUGIXML_NO_EXCEPTIONS - int error = setjmp(parser._error_handler); - - return (error == 0) ? parser.parse() : 0; - #else - return parser.parse(); - #endif - } - }; - - struct xpath_query_impl - { - static xpath_query_impl* create() - { - void* memory = xml_memory::allocate(sizeof(xpath_query_impl)); - if (!memory) return 0; - - return new (memory) xpath_query_impl(); - } - - static void destroy(xpath_query_impl* impl) - { - // free all allocated pages - impl->alloc.release(); - - // free allocator memory (with the first page) - xml_memory::deallocate(impl); - } - - xpath_query_impl(): root(0), alloc(&block) - { - block.next = 0; - block.capacity = sizeof(block.data); - } - - xpath_ast_node* root; - xpath_allocator alloc; - xpath_memory_block block; - }; - - PUGI__FN xpath_string evaluate_string_impl(xpath_query_impl* impl, const xpath_node& n, xpath_stack_data& sd) - { - if (!impl) return xpath_string(); - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return xpath_string(); - #endif - - xpath_context c(n, 1, 1); - - return impl->root->eval_string(c, sd.stack); - } - - PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) - { - if (!impl) return 0; - - if (impl->root->rettype() != xpath_type_node_set) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return 0; - #else - xpath_parse_result res; - res.error = "Expression does not evaluate to node set"; - - throw xpath_exception(res); - #endif - } - - return impl->root; - } -PUGI__NS_END - -namespace pugi -{ -#ifndef PUGIXML_NO_EXCEPTIONS - PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) - { - assert(_result.error); - } - - PUGI__FN const char* xpath_exception::what() const throw() - { - return _result.error; - } - - PUGI__FN const xpath_parse_result& xpath_exception::result() const - { - return _result; - } -#endif - - PUGI__FN xpath_node::xpath_node() - { - } - - PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) - { - } - - PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) - { - } - - PUGI__FN xml_node xpath_node::node() const - { - return _attribute ? xml_node() : _node; - } - - PUGI__FN xml_attribute xpath_node::attribute() const - { - return _attribute; - } - - PUGI__FN xml_node xpath_node::parent() const - { - return _attribute ? _node : _node.parent(); - } - - PUGI__FN static void unspecified_bool_xpath_node(xpath_node***) - { - } - - PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const - { - return (_node || _attribute) ? unspecified_bool_xpath_node : 0; - } - - PUGI__FN bool xpath_node::operator!() const - { - return !(_node || _attribute); - } - - PUGI__FN bool xpath_node::operator==(const xpath_node& n) const - { - return _node == n._node && _attribute == n._attribute; - } - - PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const - { - return _node != n._node || _attribute != n._attribute; - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xpath_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_) - { - assert(begin_ <= end_); - - size_t size_ = static_cast(end_ - begin_); - - if (size_ <= 1) - { - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // use internal buffer - if (begin_ != end_) _storage = *begin_; - - _begin = &_storage; - _end = &_storage + size_; - _type = type_; - } - else - { - // make heap copy - xpath_node* storage = static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); - - if (!storage) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return; - #else - throw std::bad_alloc(); - #endif - } - - memcpy(storage, begin_, size_ * sizeof(xpath_node)); - - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // finalize - _begin = storage; - _end = storage + size_; - _type = type_; - } - } - -#ifdef PUGIXML_HAS_MOVE - PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) - { - _type = rhs._type; - _storage = rhs._storage; - _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin; - _end = _begin + (rhs._end - rhs._begin); - - rhs._type = type_unsorted; - rhs._begin = &rhs._storage; - rhs._end = rhs._begin; - } -#endif - - PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - } - - PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - _assign(begin_, end_, type_); - } - - PUGI__FN xpath_node_set::~xpath_node_set() - { - if (_begin != &_storage) - impl::xml_memory::deallocate(_begin); - } - - PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - _assign(ns._begin, ns._end, ns._type); - } - - PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) - { - if (this == &ns) return *this; - - _assign(ns._begin, ns._end, ns._type); - - return *this; - } - -#ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - _move(rhs); - } - - PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) - { - if (this == &rhs) return *this; - - if (_begin != &_storage) - impl::xml_memory::deallocate(_begin); - - _move(rhs); - - return *this; - } -#endif - - PUGI__FN xpath_node_set::type_t xpath_node_set::type() const - { - return _type; - } - - PUGI__FN size_t xpath_node_set::size() const - { - return _end - _begin; - } - - PUGI__FN bool xpath_node_set::empty() const - { - return _begin == _end; - } - - PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const - { - assert(index < size()); - return _begin[index]; - } - - PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const - { - return _begin; - } - - PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const - { - return _end; - } - - PUGI__FN void xpath_node_set::sort(bool reverse) - { - _type = impl::xpath_sort(_begin, _end, _type, reverse); - } - - PUGI__FN xpath_node xpath_node_set::first() const - { - return impl::xpath_first(_begin, _end, _type); - } - - PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) - { - } - - PUGI__FN xpath_parse_result::operator bool() const - { - return error == 0; - } - - PUGI__FN const char* xpath_parse_result::description() const - { - return error ? error : "No error"; - } - - PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) - { - } - - PUGI__FN const char_t* xpath_variable::name() const - { - switch (_type) - { - case xpath_type_node_set: - return static_cast(this)->name; - - case xpath_type_number: - return static_cast(this)->name; - - case xpath_type_string: - return static_cast(this)->name; - - case xpath_type_boolean: - return static_cast(this)->name; - - default: - assert(false && "Invalid variable type"); - return 0; - } - } - - PUGI__FN xpath_value_type xpath_variable::type() const - { - return _type; - } - - PUGI__FN bool xpath_variable::get_boolean() const - { - return (_type == xpath_type_boolean) ? static_cast(this)->value : false; - } - - PUGI__FN double xpath_variable::get_number() const - { - return (_type == xpath_type_number) ? static_cast(this)->value : impl::gen_nan(); - } - - PUGI__FN const char_t* xpath_variable::get_string() const - { - const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; - return value ? value : PUGIXML_TEXT(""); - } - - PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const - { - return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; - } - - PUGI__FN bool xpath_variable::set(bool value) - { - if (_type != xpath_type_boolean) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN bool xpath_variable::set(double value) - { - if (_type != xpath_type_number) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN bool xpath_variable::set(const char_t* value) - { - if (_type != xpath_type_string) return false; - - impl::xpath_variable_string* var = static_cast(this); - - // duplicate string - size_t size = (impl::strlength(value) + 1) * sizeof(char_t); - - char_t* copy = static_cast(impl::xml_memory::allocate(size)); - if (!copy) return false; - - memcpy(copy, value, size); - - // replace old string - if (var->value) impl::xml_memory::deallocate(var->value); - var->value = copy; - - return true; - } - - PUGI__FN bool xpath_variable::set(const xpath_node_set& value) - { - if (_type != xpath_type_node_set) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN xpath_variable_set::xpath_variable_set() - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - _data[i] = 0; - } - - PUGI__FN xpath_variable_set::~xpath_variable_set() - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - _destroy(_data[i]); - } - - PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - _data[i] = 0; - - _assign(rhs); - } - - PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) - { - if (this == &rhs) return *this; - - _assign(rhs); - - return *this; - } - -#ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - { - _data[i] = rhs._data[i]; - rhs._data[i] = 0; - } - } - - PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - { - _destroy(_data[i]); - - _data[i] = rhs._data[i]; - rhs._data[i] = 0; - } - - return *this; - } -#endif - - PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) - { - xpath_variable_set temp; - - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i])) - return; - - _swap(temp); - } - - PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs) - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - { - xpath_variable* chain = _data[i]; - - _data[i] = rhs._data[i]; - rhs._data[i] = chain; - } - } - - PUGI__FN xpath_variable* xpath_variable_set::_find(const char_t* name) const - { - const size_t hash_size = sizeof(_data) / sizeof(_data[0]); - size_t hash = impl::hash_string(name) % hash_size; - - // look for existing variable - for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) - return var; - - return 0; - } - - PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) - { - xpath_variable* last = 0; - - while (var) - { - // allocate storage for new variable - xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name()); - if (!nvar) return false; - - // link the variable to the result immediately to handle failures gracefully - if (last) - last->_next = nvar; - else - *out_result = nvar; - - last = nvar; - - // copy the value; this can fail due to out-of-memory conditions - if (!impl::copy_xpath_variable(nvar, var)) return false; - - var = var->_next; - } - - return true; - } - - PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var) - { - while (var) - { - xpath_variable* next = var->_next; - - impl::delete_xpath_variable(var->_type, var); - - var = next; - } - } - - PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) - { - const size_t hash_size = sizeof(_data) / sizeof(_data[0]); - size_t hash = impl::hash_string(name) % hash_size; - - // look for existing variable - for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) - return var->type() == type ? var : 0; - - // add new variable - xpath_variable* result = impl::new_xpath_variable(type, name); - - if (result) - { - result->_next = _data[hash]; - - _data[hash] = result; - } - - return result; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value) - { - xpath_variable* var = add(name, xpath_type_boolean); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, double value) - { - xpath_variable* var = add(name, xpath_type_number); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value) - { - xpath_variable* var = add(name, xpath_type_string); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) - { - xpath_variable* var = add(name, xpath_type_node_set); - return var ? var->set(value) : false; - } - - PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) - { - return _find(name); - } - - PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const - { - return _find(name); - } - - PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) - { - impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); - - if (!qimpl) - { - #ifdef PUGIXML_NO_EXCEPTIONS - _result.error = "Out of memory"; - #else - throw std::bad_alloc(); - #endif - } - else - { - using impl::auto_deleter; // MSVC7 workaround - auto_deleter impl(qimpl, impl::xpath_query_impl::destroy); - - qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result); - - if (qimpl->root) - { - qimpl->root->optimize(&qimpl->alloc); - - _impl = impl.release(); - _result.error = 0; - } - } - } - - PUGI__FN xpath_query::xpath_query(): _impl(0) - { - } - - PUGI__FN xpath_query::~xpath_query() - { - if (_impl) - impl::xpath_query_impl::destroy(static_cast(_impl)); - } - -#ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) - { - _impl = rhs._impl; - _result = rhs._result; - rhs._impl = 0; - rhs._result = xpath_parse_result(); - } - - PUGI__FN xpath_query& xpath_query::operator=(xpath_query&& rhs) - { - if (this == &rhs) return *this; - - if (_impl) - impl::xpath_query_impl::destroy(static_cast(_impl)); - - _impl = rhs._impl; - _result = rhs._result; - rhs._impl = 0; - rhs._result = xpath_parse_result(); - - return *this; - } -#endif - - PUGI__FN xpath_value_type xpath_query::return_type() const - { - if (!_impl) return xpath_type_none; - - return static_cast(_impl)->root->rettype(); - } - - PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const - { - if (!_impl) return false; - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return false; - #endif - - return static_cast(_impl)->root->eval_boolean(c, sd.stack); - } - - PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const - { - if (!_impl) return impl::gen_nan(); - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return impl::gen_nan(); - #endif - - return static_cast(_impl)->root->eval_number(c, sd.stack); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const - { - impl::xpath_stack_data sd; - - impl::xpath_string r = impl::evaluate_string_impl(static_cast(_impl), n, sd); - - return string_t(r.c_str(), r.length()); - } -#endif - - PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const - { - impl::xpath_stack_data sd; - - impl::xpath_string r = impl::evaluate_string_impl(static_cast(_impl), n, sd); - - size_t full_size = r.length() + 1; - - if (capacity > 0) - { - size_t size = (full_size < capacity) ? full_size : capacity; - assert(size > 0); - - memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); - buffer[size - 1] = 0; - } - - return full_size; - } - - PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const - { - impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); - if (!root) return xpath_node_set(); - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return xpath_node_set(); - #endif - - impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all); - - return xpath_node_set(r.begin(), r.end(), r.type()); - } - - PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const - { - impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); - if (!root) return xpath_node(); - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return xpath_node(); - #endif - - impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first); - - return r.first(); - } - - PUGI__FN const xpath_parse_result& xpath_query::result() const - { - return _result; - } - - PUGI__FN static void unspecified_bool_xpath_query(xpath_query***) - { - } - - PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const - { - return _impl ? unspecified_bool_xpath_query : 0; - } - - PUGI__FN bool xpath_query::operator!() const - { - return !_impl; - } - - PUGI__FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const - { - xpath_query q(query, variables); - return select_node(q); - } - - PUGI__FN xpath_node xml_node::select_node(const xpath_query& query) const - { - return query.evaluate_node(*this); - } - - PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const - { - xpath_query q(query, variables); - return select_nodes(q); - } - - PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const - { - return query.evaluate_node_set(*this); - } - - PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const - { - xpath_query q(query, variables); - return select_single_node(q); - } - - PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const - { - return query.evaluate_node(*this); - } -} - -#endif - -#ifdef __BORLANDC__ -# pragma option pop -#endif - -// Intel C++ does not properly keep warning state for function templates, -// so popping warning state at the end of translation unit leads to warnings in the middle. -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) -# pragma warning(pop) -#endif - -// Undefine all local macros (makes sure we're not leaking macros in header-only mode) -#undef PUGI__NO_INLINE -#undef PUGI__UNLIKELY -#undef PUGI__STATIC_ASSERT -#undef PUGI__DMC_VOLATILE -#undef PUGI__MSVC_CRT_VERSION -#undef PUGI__NS_BEGIN -#undef PUGI__NS_END -#undef PUGI__FN -#undef PUGI__FN_NO_INLINE -#undef PUGI__GETHEADER_IMPL -#undef PUGI__GETPAGE_IMPL -#undef PUGI__GETPAGE -#undef PUGI__NODETYPE -#undef PUGI__IS_CHARTYPE_IMPL -#undef PUGI__IS_CHARTYPE -#undef PUGI__IS_CHARTYPEX -#undef PUGI__ENDSWITH -#undef PUGI__SKIPWS -#undef PUGI__OPTSET -#undef PUGI__PUSHNODE -#undef PUGI__POPNODE -#undef PUGI__SCANFOR -#undef PUGI__SCANWHILE -#undef PUGI__SCANWHILE_UNROLL -#undef PUGI__ENDSEG -#undef PUGI__THROW_ERROR -#undef PUGI__CHECK_ERROR - -#endif - -/** - * Copyright (c) 2006-2016 Arseny Kapoulkine - * - * 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 the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ diff --git a/vendor/pugixml/pugixml.hpp b/vendor/pugixml/pugixml.hpp deleted file mode 100644 index 6288d4bd9..000000000 --- a/vendor/pugixml/pugixml.hpp +++ /dev/null @@ -1,1434 +0,0 @@ -/** - * pugixml parser - version 1.8 - * -------------------------------------------------------- - * Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef PUGIXML_VERSION -// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -# define PUGIXML_VERSION 180 -#endif - -// Include user configuration file (this can define various configuration macros) -#include "pugiconfig.hpp" - -#ifndef HEADER_PUGIXML_HPP -#define HEADER_PUGIXML_HPP - -// Include stddef.h for size_t and ptrdiff_t -#include - -// Include exception header for XPath -#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) -# include -#endif - -// Include STL headers -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// Macro for deprecated features -#ifndef PUGIXML_DEPRECATED -# if defined(__GNUC__) -# define PUGIXML_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGIXML_DEPRECATED __declspec(deprecated) -# else -# define PUGIXML_DEPRECATED -# endif -#endif - -// If no API is defined, assume default -#ifndef PUGIXML_API -# define PUGIXML_API -#endif - -// If no API for classes is defined, assume default -#ifndef PUGIXML_CLASS -# define PUGIXML_CLASS PUGIXML_API -#endif - -// If no API for functions is defined, assume default -#ifndef PUGIXML_FUNCTION -# define PUGIXML_FUNCTION PUGIXML_API -#endif - -// If the platform is known to have long long support, enable long long functions -#ifndef PUGIXML_HAS_LONG_LONG -# if __cplusplus >= 201103 -# define PUGIXML_HAS_LONG_LONG -# elif defined(_MSC_VER) && _MSC_VER >= 1400 -# define PUGIXML_HAS_LONG_LONG -# endif -#endif - -// If the platform is known to have move semantics support, compile move ctor/operator implementation -#ifndef PUGIXML_HAS_MOVE -# if __cplusplus >= 201103 -# define PUGIXML_HAS_MOVE -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define PUGIXML_HAS_MOVE -# endif -#endif - -// If C++ is 2011 or higher, add 'override' qualifiers -#ifndef PUGIXML_OVERRIDE -# if __cplusplus >= 201103 -# define PUGIXML_OVERRIDE override -# else -# define PUGIXML_OVERRIDE -# endif -#endif - -// Character interface macros -#ifdef PUGIXML_WCHAR_MODE -# define PUGIXML_TEXT(t) L ## t -# define PUGIXML_CHAR wchar_t -#else -# define PUGIXML_TEXT(t) t -# define PUGIXML_CHAR char -#endif - -namespace pugi -{ - // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE - typedef PUGIXML_CHAR char_t; - -#ifndef PUGIXML_NO_STL - // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE - typedef std::basic_string, std::allocator > string_t; -#endif -} - -// The PugiXML namespace -namespace pugi -{ - // Tree node types - enum xml_node_type - { - node_null, // Empty (null) node handle - node_document, // A document tree's absolute root - node_element, // Element tag, i.e. '' - node_pcdata, // Plain character data, i.e. 'text' - node_cdata, // Character data, i.e. '' - node_comment, // Comment tag, i.e. '' - node_pi, // Processing instruction, i.e. '' - node_declaration, // Document declaration, i.e. '' - node_doctype // Document type declaration, i.e. '' - }; - - // Parsing options - - // Minimal parsing mode (equivalent to turning all other flags off). - // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. - const unsigned int parse_minimal = 0x0000; - - // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. - const unsigned int parse_pi = 0x0001; - - // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. - const unsigned int parse_comments = 0x0002; - - // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. - const unsigned int parse_cdata = 0x0004; - - // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. - // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata = 0x0008; - - // This flag determines if character and entity references are expanded during parsing. This flag is on by default. - const unsigned int parse_escapes = 0x0010; - - // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. - const unsigned int parse_eol = 0x0020; - - // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. - const unsigned int parse_wconv_attribute = 0x0040; - - // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. - const unsigned int parse_wnorm_attribute = 0x0080; - - // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. - const unsigned int parse_declaration = 0x0100; - - // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. - const unsigned int parse_doctype = 0x0200; - - // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only - // of whitespace is added to the DOM tree. - // This flag is off by default; turning it on may result in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata_single = 0x0400; - - // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. - const unsigned int parse_trim_pcdata = 0x0800; - - // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document - // is a valid document. This flag is off by default. - const unsigned int parse_fragment = 0x1000; - - // This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of - // the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments. - // This flag is off by default. - const unsigned int parse_embed_pcdata = 0x2000; - - // The default parsing mode. - // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; - - // The full parsing mode. - // Nodes of all types are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; - - // These flags determine the encoding of input data for XML document - enum xml_encoding - { - encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range - { - public: - typedef It const_iterator; - typedef It iterator; - - xml_object_range(It b, It e): _begin(b), _end(e) - { - } - - It begin() const { return _begin; } - It end() const { return _end; } - - private: - It _begin, _end; - }; - - // Writer interface for node printing (see xml_node::print) - class PUGIXML_CLASS xml_writer - { - public: - virtual ~xml_writer() {} - - // Write memory chunk into stream/file/whatever - virtual void write(const void* data, size_t size) = 0; - }; - - // xml_writer implementation for FILE* - class PUGIXML_CLASS xml_writer_file: public xml_writer - { - public: - // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio - xml_writer_file(void* file); - - virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; - - private: - void* file; - }; - - #ifndef PUGIXML_NO_STL - // xml_writer implementation for streams - class PUGIXML_CLASS xml_writer_stream: public xml_writer - { - public: - // Construct writer from an output stream object - xml_writer_stream(std::basic_ostream >& stream); - xml_writer_stream(std::basic_ostream >& stream); - - virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; - - private: - std::basic_ostream >* narrow_stream; - std::basic_ostream >* wide_stream; - }; - #endif - - // A light-weight handle for manipulating attributes in DOM tree - class PUGIXML_CLASS xml_attribute - { - friend class xml_attribute_iterator; - friend class xml_node; - - private: - xml_attribute_struct* _attr; - - typedef void (*unspecified_bool_type)(xml_attribute***); - - public: - // Default constructor. Constructs an empty attribute. - xml_attribute(); - - // Constructs attribute from internal pointer - explicit xml_attribute(xml_attribute_struct* attr); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped attribute pointers) - bool operator==(const xml_attribute& r) const; - bool operator!=(const xml_attribute& r) const; - bool operator<(const xml_attribute& r) const; - bool operator>(const xml_attribute& r) const; - bool operator<=(const xml_attribute& r) const; - bool operator>=(const xml_attribute& r) const; - - // Check if attribute is empty - bool empty() const; - - // Get attribute name/value, or "" if attribute is empty - const char_t* name() const; - const char_t* value() const; - - // Get attribute value, or the default value if attribute is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty - bool as_bool(bool def = false) const; - - // Set attribute name/value (returns false if attribute is empty or there is not enough memory) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set_value(int rhs); - bool set_value(unsigned int rhs); - bool set_value(long rhs); - bool set_value(unsigned long rhs); - bool set_value(double rhs); - bool set_value(float rhs); - bool set_value(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set_value(long long rhs); - bool set_value(unsigned long long rhs); - #endif - - // Set attribute value (equivalent to set_value without error checking) - xml_attribute& operator=(const char_t* rhs); - xml_attribute& operator=(int rhs); - xml_attribute& operator=(unsigned int rhs); - xml_attribute& operator=(long rhs); - xml_attribute& operator=(unsigned long rhs); - xml_attribute& operator=(double rhs); - xml_attribute& operator=(float rhs); - xml_attribute& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_attribute& operator=(long long rhs); - xml_attribute& operator=(unsigned long long rhs); - #endif - - // Get next/previous attribute in the attribute list of the parent node - xml_attribute next_attribute() const; - xml_attribute previous_attribute() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_attribute_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); -#endif - - // A light-weight handle for manipulating nodes in DOM tree - class PUGIXML_CLASS xml_node - { - friend class xml_attribute_iterator; - friend class xml_node_iterator; - friend class xml_named_node_iterator; - - protected: - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_node***); - - public: - // Default constructor. Constructs an empty node. - xml_node(); - - // Constructs node from internal pointer - explicit xml_node(xml_node_struct* p); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped node pointers) - bool operator==(const xml_node& r) const; - bool operator!=(const xml_node& r) const; - bool operator<(const xml_node& r) const; - bool operator>(const xml_node& r) const; - bool operator<=(const xml_node& r) const; - bool operator>=(const xml_node& r) const; - - // Check if node is empty. - bool empty() const; - - // Get node type - xml_node_type type() const; - - // Get node name, or "" if node is empty or it has no name - const char_t* name() const; - - // Get node value, or "" if node is empty or it has no value - // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. - const char_t* value() const; - - // Get attribute list - xml_attribute first_attribute() const; - xml_attribute last_attribute() const; - - // Get children list - xml_node first_child() const; - xml_node last_child() const; - - // Get next/previous sibling in the children list of the parent node - xml_node next_sibling() const; - xml_node previous_sibling() const; - - // Get parent node - xml_node parent() const; - - // Get root of DOM tree this node belongs to - xml_node root() const; - - // Get text object for the current node - xml_text text() const; - - // Get child, attribute or next/previous sibling with the specified name - xml_node child(const char_t* name) const; - xml_attribute attribute(const char_t* name) const; - xml_node next_sibling(const char_t* name) const; - xml_node previous_sibling(const char_t* name) const; - - // Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast) - xml_attribute attribute(const char_t* name, xml_attribute& hint) const; - - // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA - const char_t* child_value() const; - - // Get child value of child with specified name. Equivalent to child(name).child_value(). - const char_t* child_value(const char_t* name) const; - - // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Add attribute with specified name. Returns added attribute, or empty attribute on errors. - xml_attribute append_attribute(const char_t* name); - xml_attribute prepend_attribute(const char_t* name); - xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); - xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); - - // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. - xml_attribute append_copy(const xml_attribute& proto); - xml_attribute prepend_copy(const xml_attribute& proto); - xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); - xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); - - // Add child node with specified type. Returns added node, or empty node on errors. - xml_node append_child(xml_node_type type = node_element); - xml_node prepend_child(xml_node_type type = node_element); - xml_node insert_child_after(xml_node_type type, const xml_node& node); - xml_node insert_child_before(xml_node_type type, const xml_node& node); - - // Add child element with specified name. Returns added node, or empty node on errors. - xml_node append_child(const char_t* name); - xml_node prepend_child(const char_t* name); - xml_node insert_child_after(const char_t* name, const xml_node& node); - xml_node insert_child_before(const char_t* name, const xml_node& node); - - // Add a copy of the specified node as a child. Returns added node, or empty node on errors. - xml_node append_copy(const xml_node& proto); - xml_node prepend_copy(const xml_node& proto); - xml_node insert_copy_after(const xml_node& proto, const xml_node& node); - xml_node insert_copy_before(const xml_node& proto, const xml_node& node); - - // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. - xml_node append_move(const xml_node& moved); - xml_node prepend_move(const xml_node& moved); - xml_node insert_move_after(const xml_node& moved, const xml_node& node); - xml_node insert_move_before(const xml_node& moved, const xml_node& node); - - // Remove specified attribute - bool remove_attribute(const xml_attribute& a); - bool remove_attribute(const char_t* name); - - // Remove specified child - bool remove_child(const xml_node& n); - bool remove_child(const char_t* name); - - // Parses buffer as an XML document fragment and appends all nodes as children of the current node. - // Copies/converts the buffer, so it may be deleted or changed after the function returns. - // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. - xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Find attribute using predicate. Returns first attribute for which predicate returned true. - template xml_attribute find_attribute(Predicate pred) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) - if (pred(attrib)) - return attrib; - - return xml_attribute(); - } - - // Find child node using predicate. Returns first child for which predicate returned true. - template xml_node find_child(Predicate pred) const - { - if (!_root) return xml_node(); - - for (xml_node node = first_child(); node; node = node.next_sibling()) - if (pred(node)) - return node; - - return xml_node(); - } - - // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. - template xml_node find_node(Predicate pred) const - { - if (!_root) return xml_node(); - - xml_node cur = first_child(); - - while (cur._root && cur._root != _root) - { - if (pred(cur)) return cur; - - if (cur.first_child()) cur = cur.first_child(); - else if (cur.next_sibling()) cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); - - if (cur._root != _root) cur = cur.next_sibling(); - } - } - - return xml_node(); - } - - // Find child node by attribute name/value - xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; - xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; - - #ifndef PUGIXML_NO_STL - // Get the absolute node path from root as a text string. - string_t path(char_t delimiter = '/') const; - #endif - - // Search for a node by path consisting of node names and . or .. elements. - xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; - - // Recursively traverse subtree with xml_tree_walker - bool traverse(xml_tree_walker& walker); - - #ifndef PUGIXML_NO_XPATH - // Select single node by evaluating XPath query. Returns first node from the resulting node set. - xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const; - xpath_node select_node(const xpath_query& query) const; - - // Select node set by evaluating XPath query - xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; - xpath_node_set select_nodes(const xpath_query& query) const; - - // (deprecated: use select_node instead) Select single node by evaluating XPath query. - xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; - xpath_node select_single_node(const xpath_query& query) const; - - #endif - - // Print subtree using a writer object - void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - - #ifndef PUGIXML_NO_STL - // Print subtree to stream - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; - #endif - - // Child nodes iterators - typedef xml_node_iterator iterator; - - iterator begin() const; - iterator end() const; - - // Attribute iterators - typedef xml_attribute_iterator attribute_iterator; - - attribute_iterator attributes_begin() const; - attribute_iterator attributes_end() const; - - // Range-based for support - xml_object_range children() const; - xml_object_range children(const char_t* name) const; - xml_object_range attributes() const; - - // Get node offset in parsed file/string (in char_t units) for debugging purposes - ptrdiff_t offset_debug() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_node_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); -#endif - - // A helper for working with text inside PCDATA nodes - class PUGIXML_CLASS xml_text - { - friend class xml_node; - - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_text***); - - explicit xml_text(xml_node_struct* root); - - xml_node_struct* _data_new(); - xml_node_struct* _data() const; - - public: - // Default constructor. Constructs an empty object. - xml_text(); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Check if text object is empty - bool empty() const; - - // Get text, or "" if object is empty - const char_t* get() const; - - // Get text, or the default value if object is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get text as a number, or the default value if conversion did not succeed or object is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty - bool as_bool(bool def = false) const; - - // Set text (returns false if object is empty or there is not enough memory) - bool set(const char_t* rhs); - - // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set(int rhs); - bool set(unsigned int rhs); - bool set(long rhs); - bool set(unsigned long rhs); - bool set(double rhs); - bool set(float rhs); - bool set(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set(long long rhs); - bool set(unsigned long long rhs); - #endif - - // Set text (equivalent to set without error checking) - xml_text& operator=(const char_t* rhs); - xml_text& operator=(int rhs); - xml_text& operator=(unsigned int rhs); - xml_text& operator=(long rhs); - xml_text& operator=(unsigned long rhs); - xml_text& operator=(double rhs); - xml_text& operator=(float rhs); - xml_text& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_text& operator=(long long rhs); - xml_text& operator=(unsigned long long rhs); - #endif - - // Get the data node (node_pcdata or node_cdata) for this object - xml_node data() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); -#endif - - // Child node iterator (a bidirectional iterator over a collection of xml_node) - class PUGIXML_CLASS xml_node_iterator - { - friend class xml_node; - - private: - mutable xml_node _wrap; - xml_node _parent; - - xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_node_iterator(); - - // Construct an iterator which points to the specified node - xml_node_iterator(const xml_node& node); - - // Iterator operators - bool operator==(const xml_node_iterator& rhs) const; - bool operator!=(const xml_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_node_iterator& operator++(); - xml_node_iterator operator++(int); - - const xml_node_iterator& operator--(); - xml_node_iterator operator--(int); - }; - - // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) - class PUGIXML_CLASS xml_attribute_iterator - { - friend class xml_node; - - private: - mutable xml_attribute _wrap; - xml_node _parent; - - xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_attribute value_type; - typedef xml_attribute* pointer; - typedef xml_attribute& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_attribute_iterator(); - - // Construct an iterator which points to the specified attribute - xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); - - // Iterator operators - bool operator==(const xml_attribute_iterator& rhs) const; - bool operator!=(const xml_attribute_iterator& rhs) const; - - xml_attribute& operator*() const; - xml_attribute* operator->() const; - - const xml_attribute_iterator& operator++(); - xml_attribute_iterator operator++(int); - - const xml_attribute_iterator& operator--(); - xml_attribute_iterator operator--(int); - }; - - // Named node range helper - class PUGIXML_CLASS xml_named_node_iterator - { - friend class xml_node; - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_named_node_iterator(); - - // Construct an iterator which points to the specified node - xml_named_node_iterator(const xml_node& node, const char_t* name); - - // Iterator operators - bool operator==(const xml_named_node_iterator& rhs) const; - bool operator!=(const xml_named_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_named_node_iterator& operator++(); - xml_named_node_iterator operator++(int); - - const xml_named_node_iterator& operator--(); - xml_named_node_iterator operator--(int); - - private: - mutable xml_node _wrap; - xml_node _parent; - const char_t* _name; - - xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); - }; - - // Abstract tree walker class (see xml_node::traverse) - class PUGIXML_CLASS xml_tree_walker - { - friend class xml_node; - - private: - int _depth; - - protected: - // Get current traversal depth - int depth() const; - - public: - xml_tree_walker(); - virtual ~xml_tree_walker(); - - // Callback that is called when traversal begins - virtual bool begin(xml_node& node); - - // Callback that is called for each node traversed - virtual bool for_each(xml_node& node) = 0; - - // Callback that is called when traversal ends - virtual bool end(xml_node& node); - }; - - // Parsing status, returned as part of xml_parse_result object - enum xml_parse_status - { - status_ok = 0, // No error - - status_file_not_found, // File was not found during load_file() - status_io_error, // Error reading from file/stream - status_out_of_memory, // Could not allocate memory - status_internal_error, // Internal error occurred - - status_unrecognized_tag, // Parser could not determine tag type - - status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction - status_bad_comment, // Parsing error occurred while parsing comment - status_bad_cdata, // Parsing error occurred while parsing CDATA section - status_bad_doctype, // Parsing error occurred while parsing document type declaration - status_bad_pcdata, // Parsing error occurred while parsing PCDATA section - status_bad_start_element, // Parsing error occurred while parsing start element tag - status_bad_attribute, // Parsing error occurred while parsing element attribute - status_bad_end_element, // Parsing error occurred while parsing end element tag - status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) - - status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) - - status_no_document_element // Parsing resulted in a document without element nodes - }; - - // Parsing result - struct PUGIXML_CLASS xml_parse_result - { - // Parsing status (see xml_parse_status) - xml_parse_status status; - - // Last parsed offset (in char_t units from start of input data) - ptrdiff_t offset; - - // Source document encoding - xml_encoding encoding; - - // Default constructor, initializes object to failed state - xml_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // Document class (DOM tree root) - class PUGIXML_CLASS xml_document: public xml_node - { - private: - char_t* _buffer; - - char _memory[192]; - - // Non-copyable semantics - xml_document(const xml_document&); - xml_document& operator=(const xml_document&); - - void _create(); - void _destroy(); - - public: - // Default constructor, makes empty document - xml_document(); - - // Destructor, invalidates all node/attribute handles to this document - ~xml_document(); - - // Removes all nodes, leaving the empty document - void reset(); - - // Removes all nodes, then copies the entire contents of the specified document - void reset(const xml_document& proto); - - #ifndef PUGIXML_NO_STL - // Load document from stream. - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); - #endif - - // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load(const char_t* contents, unsigned int options = parse_default); - - // Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); - - // Load document from file - xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. - xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. - xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). - xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). - void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - #ifndef PUGIXML_NO_STL - // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; - #endif - - // Save XML to file - bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - // Get document element - xml_node document_element() const; - }; - -#ifndef PUGIXML_NO_XPATH - // XPath query return type - enum xpath_value_type - { - xpath_type_none, // Unknown type (query failed to compile) - xpath_type_node_set, // Node set (xpath_node_set) - xpath_type_number, // Number - xpath_type_string, // String - xpath_type_boolean // Boolean - }; - - // XPath parsing result - struct PUGIXML_CLASS xpath_parse_result - { - // Error message (0 if no error) - const char* error; - - // Last parsed offset (in char_t units from string start) - ptrdiff_t offset; - - // Default constructor, initializes object to failed state - xpath_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // A single XPath variable - class PUGIXML_CLASS xpath_variable - { - friend class xpath_variable_set; - - protected: - xpath_value_type _type; - xpath_variable* _next; - - xpath_variable(xpath_value_type type); - - // Non-copyable semantics - xpath_variable(const xpath_variable&); - xpath_variable& operator=(const xpath_variable&); - - public: - // Get variable name - const char_t* name() const; - - // Get variable type - xpath_value_type type() const; - - // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error - bool get_boolean() const; - double get_number() const; - const char_t* get_string() const; - const xpath_node_set& get_node_set() const; - - // Set variable value; no type conversion is performed, false is returned on type mismatch error - bool set(bool value); - bool set(double value); - bool set(const char_t* value); - bool set(const xpath_node_set& value); - }; - - // A set of XPath variables - class PUGIXML_CLASS xpath_variable_set - { - private: - xpath_variable* _data[64]; - - void _assign(const xpath_variable_set& rhs); - void _swap(xpath_variable_set& rhs); - - xpath_variable* _find(const char_t* name) const; - - static bool _clone(xpath_variable* var, xpath_variable** out_result); - static void _destroy(xpath_variable* var); - - public: - // Default constructor/destructor - xpath_variable_set(); - ~xpath_variable_set(); - - // Copy constructor/assignment operator - xpath_variable_set(const xpath_variable_set& rhs); - xpath_variable_set& operator=(const xpath_variable_set& rhs); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_variable_set(xpath_variable_set&& rhs); - xpath_variable_set& operator=(xpath_variable_set&& rhs); - #endif - - // Add a new variable or get the existing one, if the types match - xpath_variable* add(const char_t* name, xpath_value_type type); - - // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch - bool set(const char_t* name, bool value); - bool set(const char_t* name, double value); - bool set(const char_t* name, const char_t* value); - bool set(const char_t* name, const xpath_node_set& value); - - // Get existing variable by name - xpath_variable* get(const char_t* name); - const xpath_variable* get(const char_t* name) const; - }; - - // A compiled XPath query object - class PUGIXML_CLASS xpath_query - { - private: - void* _impl; - xpath_parse_result _result; - - typedef void (*unspecified_bool_type)(xpath_query***); - - // Non-copyable semantics - xpath_query(const xpath_query&); - xpath_query& operator=(const xpath_query&); - - public: - // Construct a compiled object from XPath expression. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. - explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); - - // Constructor - xpath_query(); - - // Destructor - ~xpath_query(); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_query(xpath_query&& rhs); - xpath_query& operator=(xpath_query&& rhs); - #endif - - // Get query expression return type - xpath_value_type return_type() const; - - // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - bool evaluate_boolean(const xpath_node& n) const; - - // Evaluate expression as double value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - double evaluate_number(const xpath_node& n) const; - - #ifndef PUGIXML_NO_STL - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - string_t evaluate_string(const xpath_node& n) const; - #endif - - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. - size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; - - // Evaluate expression as node set in the specified context. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. - xpath_node_set evaluate_node_set(const xpath_node& n) const; - - // Evaluate expression as node set in the specified context. - // Return first node in document order, or empty node if node set is empty. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node instead. - xpath_node evaluate_node(const xpath_node& n) const; - - // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) - const xpath_parse_result& result() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - }; - - #ifndef PUGIXML_NO_EXCEPTIONS - // XPath exception class - class PUGIXML_CLASS xpath_exception: public std::exception - { - private: - xpath_parse_result _result; - - public: - // Construct exception from parse result - explicit xpath_exception(const xpath_parse_result& result); - - // Get error message - virtual const char* what() const throw() PUGIXML_OVERRIDE; - - // Get parse result - const xpath_parse_result& result() const; - }; - #endif - - // XPath node class (either xml_node or xml_attribute) - class PUGIXML_CLASS xpath_node - { - private: - xml_node _node; - xml_attribute _attribute; - - typedef void (*unspecified_bool_type)(xpath_node***); - - public: - // Default constructor; constructs empty XPath node - xpath_node(); - - // Construct XPath node from XML node/attribute - xpath_node(const xml_node& node); - xpath_node(const xml_attribute& attribute, const xml_node& parent); - - // Get node/attribute, if any - xml_node node() const; - xml_attribute attribute() const; - - // Get parent of contained node/attribute - xml_node parent() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators - bool operator==(const xpath_node& n) const; - bool operator!=(const xpath_node& n) const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); -#endif - - // A fixed-size collection of XPath nodes - class PUGIXML_CLASS xpath_node_set - { - public: - // Collection type - enum type_t - { - type_unsorted, // Not ordered - type_sorted, // Sorted by document order (ascending) - type_sorted_reverse // Sorted by document order (descending) - }; - - // Constant iterator type - typedef const xpath_node* const_iterator; - - // We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work - typedef const xpath_node* iterator; - - // Default constructor. Constructs empty set. - xpath_node_set(); - - // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful - xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); - - // Destructor - ~xpath_node_set(); - - // Copy constructor/assignment operator - xpath_node_set(const xpath_node_set& ns); - xpath_node_set& operator=(const xpath_node_set& ns); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_node_set(xpath_node_set&& rhs); - xpath_node_set& operator=(xpath_node_set&& rhs); - #endif - - // Get collection type - type_t type() const; - - // Get collection size - size_t size() const; - - // Indexing operator - const xpath_node& operator[](size_t index) const; - - // Collection iterators - const_iterator begin() const; - const_iterator end() const; - - // Sort the collection in ascending/descending order by document order - void sort(bool reverse = false); - - // Get first node in the collection by document order - xpath_node first() const; - - // Check if collection is empty - bool empty() const; - - private: - type_t _type; - - xpath_node _storage; - - xpath_node* _begin; - xpath_node* _end; - - void _assign(const_iterator begin, const_iterator end, type_t type); - void _move(xpath_node_set& rhs); - }; -#endif - -#ifndef PUGIXML_NO_STL - // Convert wide string to UTF8 - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); - - // Convert UTF8 to wide string - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); -#endif - - // Memory allocation function interface; returns pointer to allocated memory or NULL on failure - typedef void* (*allocation_function)(size_t size); - - // Memory deallocation function interface - typedef void (*deallocation_function)(void* ptr); - - // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. - void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); - - // Get current memory management functions - allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); - deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); -} - -#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); -} -#endif - -#endif - -// Make sure implementation is included in header-only mode -// Use macro expansion in #include to work around QMake (QTBUG-11923) -#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) -# define PUGIXML_SOURCE "pugixml.cpp" -# include PUGIXML_SOURCE -#endif - -/** - * Copyright (c) 2006-2016 Arseny Kapoulkine - * - * 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 the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ diff --git a/vendor/xtensor/CMakeLists.txt b/vendor/xtensor/CMakeLists.txt deleted file mode 100644 index d4d3b355d..000000000 --- a/vendor/xtensor/CMakeLists.txt +++ /dev/null @@ -1,191 +0,0 @@ -############################################################################ -# Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht # -# # -# Distributed under the terms of the BSD 3-Clause License. # -# # -# The full license is in the file LICENSE, distributed with this software. # -############################################################################ - -cmake_minimum_required(VERSION 3.1) -project(xtensor) - -set(XTENSOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) - -# Versionning -# =========== - -file(STRINGS "${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp" xtensor_version_defines - REGEX "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH)") -foreach(ver ${xtensor_version_defines}) - if(ver MATCHES "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") - set(XTENSOR_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") - endif() -endforeach() -set(${PROJECT_NAME}_VERSION - ${XTENSOR_VERSION_MAJOR}.${XTENSOR_VERSION_MINOR}.${XTENSOR_VERSION_PATCH}) -message(STATUS "Building xtensor v${${PROJECT_NAME}_VERSION}") - -# Dependencies -# ============ - -#find_package(xtl 0.4.9 REQUIRED) - -#message(STATUS "Found xtl: ${xtl_INCLUDE_DIRS}/xtl") - -#find_package(nlohmann_json 3.1.1) - -# Build -# ===== - -set(XTENSOR_HEADERS - ${XTENSOR_INCLUDE_DIR}/xtensor/xaccumulator.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xadapt.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xarray.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xassign.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xaxis_iterator.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xbroadcast.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xbuffer_adaptor.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xbuilder.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xcomplex.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xconcepts.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xcontainer.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xcsv.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xeval.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xexception.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xexpression.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xfixed.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xfunction.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xfunctor_view.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xgenerator.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xindex_view.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xinfo.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xio.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xiterable.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xiterator.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xjson.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xlayout.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xmath.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xnoalias.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xnorm.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xnpy.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoffset_view.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoperation.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoptional.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly_base.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly_storage.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xrandom.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xreducer.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xscalar.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xsemantic.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xshape.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xslice.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xsort.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xstorage.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xstrided_view.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xstrided_view_base.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xstrides.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_forward.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_simd.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xutils.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xvectorize.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xview.hpp - ${XTENSOR_INCLUDE_DIR}/xtensor/xview_utils.hpp -) - -add_library(xtensor INTERFACE) -target_include_directories(xtensor INTERFACE $ - $) -target_link_libraries(xtensor INTERFACE xtl) - -OPTION(XTENSOR_ENABLE_ASSERT "xtensor bound check" OFF) -OPTION(XTENSOR_CHECK_DIMENSION "xtensor dimension check" OFF) -OPTION(XTENSOR_USE_XSIMD "simd acceleration for xtensor" OFF) -OPTION(BUILD_TESTS "xtensor test suite" OFF) -OPTION(BUILD_BENCHMARK "xtensor benchmark" OFF) -OPTION(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF) -OPTION(DOWNLOAD_GBENCHMARK "download google benchmark and build from source" ON) -OPTION(DEFAULT_COLUMN_MAJOR "set default layout to column major" OFF) -OPTION(DISABLE_VS2017 "disables the compilation of some test with Visual Studio 2017" OFF) - -if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) - set(BUILD_TESTS ON) -endif() - -if(XTENSOR_ENABLE_ASSERT OR XTENSOR_CHECK_DIMENSION) - add_definitions(-DXTENSOR_ENABLE_ASSERT) -endif() - -if(XTENSOR_CHECK_DIMENSION) - add_definitions(-DXTENSOR_ENABLE_CHECK_DIMENSION) -endif() - -if(XTENSOR_USE_XSIMD) - add_definitions(-DXTENSOR_USE_XSIMD) - find_package(xsimd 4.1.6 REQUIRED) - message(STATUS "Found xsimd: ${xsimd_INCLUDE_DIRS}/xsimd") - target_link_libraries(xtensor INTERFACE xsimd) -endif() - -if(DEFAULT_COLUMN_MAJOR) - add_definitions(-DXTENSOR_DEFAULT_LAYOUT=layout_type::column_major) -endif() - -if(DISABLE_VS2017) - add_definitions(-DDISABLE_VS2017) -endif() - -if(BUILD_TESTS) - add_subdirectory(test) -endif() - -if(BUILD_BENCHMARK) - add_subdirectory(benchmark) -endif() - -# Installation -# ============ - -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -install(TARGETS xtensor - EXPORT ${PROJECT_NAME}-targets) - -# Makes the project importable from the build directory -export(EXPORT ${PROJECT_NAME}-targets - FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") - -install(FILES ${XTENSOR_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtensor) - -set(XTENSOR_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE - STRING "install path for xtensorConfig.cmake") - -configure_package_config_file(${PROJECT_NAME}Config.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR}) - -# xtensor is header-only and does not depend on the architecture. -# Remove CMAKE_SIZEOF_VOID_P from xtensorConfigVersion.cmake so that an xtensorConfig.cmake -# generated for a 64 bit target can be used for 32 bit targets and vice versa. -set(_XTENSOR_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) -unset(CMAKE_SIZEOF_VOID_P) -write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${${PROJECT_NAME}_VERSION} - COMPATIBILITY AnyNewerVersion) -set(CMAKE_SIZEOF_VOID_P ${_XTENSOR_CMAKE_SIZEOF_VOID_P}) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR}) -install(EXPORT ${PROJECT_NAME}-targets - FILE ${PROJECT_NAME}Targets.cmake - DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR}) - -configure_file(${PROJECT_NAME}.pc.in - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" - @ONLY) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") diff --git a/vendor/xtensor/include/xtensor/xaccumulator.hpp b/vendor/xtensor/include/xtensor/xaccumulator.hpp deleted file mode 100644 index f2b446ff3..000000000 --- a/vendor/xtensor/include/xtensor/xaccumulator.hpp +++ /dev/null @@ -1,266 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ACCUMULATOR_HPP -#define XTENSOR_ACCUMULATOR_HPP - -#include -#include -#include -#include - -#include "xexpression.hpp" -#include "xstrides.hpp" -#include "xtensor_forward.hpp" - -namespace xt -{ - -#define DEFAULT_STRATEGY_ACCUMULATORS evaluation_strategy::immediate - - /************** - * accumulate * - **************/ - - template - struct xaccumulator_functor - : public std::tuple - { - using self_type = xaccumulator_functor; - using base_type = std::tuple; - using accumulate_functor_type = ACCUMULATE_FUNC; - using init_functor_type = INIT_FUNC; - - xaccumulator_functor() - : base_type() - { - } - - template - xaccumulator_functor(RF&& accumulate_func) - : base_type(std::forward(accumulate_func), INIT_FUNC()) - { - } - - template - xaccumulator_functor(RF&& accumulate_func, IF&& init_func) - : base_type(std::forward(accumulate_func), std::forward(init_func)) - { - } - }; - - template - auto make_xaccumulator_functor(RF&& accumulate_func) - { - using accumulator_type = xaccumulator_functor>; - return accumulator_type(std::forward(accumulate_func)); - } - - template - auto make_xaccumulator_functor(RF&& accumulate_func, IF&& init_func) - { - using accumulator_type = xaccumulator_functor, std::remove_reference_t>; - return accumulator_type(std::forward(accumulate_func), std::forward(init_func)); - } - - namespace detail - { - template - xarray::value_type> accumulator_impl(F&&, E&&, std::size_t, EVS) - { - static_assert(!std::is_same::value, "Lazy accumulators not yet implemented."); - } - - template - xarray::value_type> accumulator_impl(F&&, E&&, EVS) - { - static_assert(!std::is_same::value, "Lazy accumulators not yet implemented."); - } - - template - struct xaccumulator_return_type - { - using type = xarray; - }; - - template - struct xaccumulator_return_type, R> - { - using type = xtensor; - }; - - template - using xaccumulator_return_type_t = typename xaccumulator_return_type::type; - - template - inline auto accumulator_init_with_f(F&& f, E& e, std::size_t axis) - { - // this function is the equivalent (but hopefully faster) to (if axis == 1) - // e[:, 0, :, :, ...] = f(e[:, 0, :, :, ...]) - // so that all "first" values are initialized in a first pass - - std::size_t outer_loop_size, inner_loop_size, outer_stride, inner_stride, pos = 0; - - auto set_loop_sizes = [&outer_loop_size, &inner_loop_size](auto first, auto last, std::ptrdiff_t ax) { - outer_loop_size = std::accumulate(first, first + ax, - std::size_t(1), std::multiplies()); - inner_loop_size = std::accumulate(first + ax + 1, last, - std::size_t(1), std::multiplies()); - }; - - auto set_loop_strides = [&outer_stride, &inner_stride](auto first, auto last, std::ptrdiff_t ax) { - outer_stride = ax == 0 ? 1 : *std::min_element(first, first + ax); - inner_stride = (ax == std::distance(first, last) - 1) ? 1 : *std::min_element(first + ax + 1, last); - }; - - set_loop_sizes(e.shape().begin(), e.shape().end(), static_cast(axis)); - set_loop_strides(e.strides().begin(), e.strides().end(), static_cast(axis)); - - if (e.layout() == layout_type::column_major) - { - // swap for better memory locality (smaller stride in the inner loop) - std::swap(outer_loop_size, inner_loop_size); - std::swap(outer_stride, inner_stride); - } - - for (std::size_t i = 0; i < outer_loop_size; ++i) - { - pos = i * outer_stride; - for (std::size_t j = 0; j < inner_loop_size; ++j) - { - e.storage()[pos] = f(e.storage()[pos]); - pos += inner_stride; - } - } - } - - template - inline auto accumulator_impl(F&& f, E&& e, std::size_t axis, evaluation_strategy::immediate) - { - using accumulate_functor = std::decay_t(f))>; - using function_return_type = typename accumulate_functor::result_type; - using result_type = xaccumulator_return_type_t, function_return_type>; - - if (axis >= e.dimension()) - { - throw std::runtime_error("Axis larger than expression dimension in accumulator."); - } - - result_type result = e; // assign + make a copy, we need it anyways - - std::size_t inner_stride = result.strides()[axis]; - std::size_t outer_stride = 1; // this is either going row- or column-wise (strides.back / strides.front) - std::size_t outer_loop_size = 0; - std::size_t inner_loop_size = 0; - - auto set_loop_sizes = [&outer_loop_size, &inner_loop_size](auto first, auto last, std::ptrdiff_t ax) { - outer_loop_size = std::accumulate(first, - first + ax, - std::size_t(1), std::multiplies()); - - inner_loop_size = std::accumulate(first + ax, - last, - std::size_t(1), std::multiplies()); - }; - - if (result_type::static_layout == layout_type::row_major) - { - set_loop_sizes(result.shape().cbegin(), result.shape().cend(), static_cast(axis)); - } - else - { - set_loop_sizes(result.shape().cbegin(), result.shape().cend(), static_cast(axis + 1)); - std::swap(inner_loop_size, outer_loop_size); - } - - std::size_t pos = 0; - - inner_loop_size = inner_loop_size - inner_stride; - - // activate the init loop if we have an init function other than identity - if (!std::is_same(f)), xtl::identity>::value) - { - accumulator_init_with_f(std::get<1>(f), result, axis); - } - - pos = 0; - for (std::size_t i = 0; i < outer_loop_size; ++i) - { - for (std::size_t j = 0; j < inner_loop_size; ++j) - { - result.storage()[pos + inner_stride] = std::get<0>(f)(result.storage()[pos], - result.storage()[pos + inner_stride]); - pos += outer_stride; - } - pos += inner_stride; - } - return result; - } - - template - inline auto accumulator_impl(F&& f, E&& e, evaluation_strategy::immediate) - { - using accumulate_functor = std::decay_t(f))>; - using T = typename accumulate_functor::result_type; - - using result_type = xtensor; - std::size_t sz = e.size(); - auto result = result_type::from_shape({sz}); - - auto it = e.template begin(); - - result.storage()[0] = std::get<1>(f)(*it); - ++it; - - for (std::size_t idx = 0; it != e.template end(); ++it) - { - result.storage()[idx + 1] = std::get<0>(f)(result.storage()[idx], *it); - ++idx; - } - return result; - } - } - - /** - * Accumulate and flatten array - * **NOTE** This function is not lazy! - * - * @param f functor to use for accumulation - * @param e xexpression to be accumulated - * @param evaluation_strategy evaluation strategy of the accumulation - * - * @return returns xarray filled with accumulated values - */ - template ::value, int> = 0> - inline auto accumulate(F&& f, E&& e, EVS evaluation_strategy = EVS()) - { - // Note we need to check is_integral above in order to prohibit EVS = int, and not taking the std::size_t - // overload below! - return detail::accumulator_impl(std::forward(f), std::forward(e), evaluation_strategy); - } - - /** - * Accumulate over axis - * **NOTE** This function is not lazy! - * - * @param f Functor to use for accumulation - * @param e xexpression to accumulate - * @param axis Axis to perform accumulation over - * @param evaluation_strategy evaluation strategy of the accumulation - * - * @return returns xarray filled with accumulated values - */ - template - inline auto accumulate(F&& f, E&& e, std::size_t axis, EVS evaluation_strategy = EVS()) - { - return detail::accumulator_impl(std::forward(f), std::forward(e), axis, evaluation_strategy); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xadapt.hpp b/vendor/xtensor/include/xtensor/xadapt.hpp deleted file mode 100644 index b080bd0b7..000000000 --- a/vendor/xtensor/include/xtensor/xadapt.hpp +++ /dev/null @@ -1,322 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ADAPT_HPP -#define XTENSOR_ADAPT_HPP - -#include -#include -#include -#include - -#include - -#include "xarray.hpp" -#include "xtensor.hpp" - -namespace xt -{ - namespace detail - { - template - struct array_size_impl; - - template - struct array_size_impl> - { - static constexpr std::size_t value = N; - }; - - template - using array_size = array_size_impl>; - } - - /************************** - * xarray_adaptor builder * - **************************/ - - /** - * Constructs an xarray_adaptor of the given stl-like container, - * with the specified shape and layout. - * @param container the container to adapt - * @param shape the shape of the xarray_adaptor - * @param l the layout_type of the xarray_adaptor - */ - template >::value, int> = 0> - xarray_adaptor, L, std::decay_t> - adapt(C&& container, const SC& shape, layout_type l = L); - - /** - * Constructs an xarray_adaptor of the given stl-like container, - * with the specified shape and strides. - * @param container the container to adapt - * @param shape the shape of the xarray_adaptor - * @param strides the strides of the xarray_adaptor - */ - template >::value, int> = 0, - typename std::enable_if_t>::value, int> = 0> - xarray_adaptor, layout_type::dynamic, std::decay_t> - adapt(C&& container, SC&& shape, SS&& strides); - - /** - * Constructs an xarray_adaptor of the given dynamically allocated C array, - * with the specified shape and layout. - * @param pointer the pointer to the beginning of the dynamic array - * @param size the size of the dynamic array - * @param ownership indicates whether the adaptor takes ownership of the array. - * Possible values are ``no_ownerhsip()`` or ``acquire_ownership()`` - * @param shape the shape of the xarray_adaptor - * @param l the layout_type of the xarray_adaptor - * @param alloc the allocator used for allocating / deallocating the dynamic array - */ - template >>>, - typename std::enable_if_t>::value, int> = 0> - xarray_adaptor, O, A>, L, SC> - adapt(P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A()); - - /** - * Constructs an xarray_adaptor of the given dynamically allocated C array, - * with the specified shape and layout. - * @param pointer the pointer to the beginning of the dynamic array - * @param size the size of the dynamic array - * @param ownership indicates whether the adaptor takes ownership of the array. - * Possible values are ``no_ownerhsip()`` or ``acquire_ownership()`` - * @param shape the shape of the xarray_adaptor - * @param strides the strides of the xarray_adaptor - * @param alloc the allocator used for allocating / deallocating the dynamic array - */ - template >>>, - typename std::enable_if_t>::value, int> = 0, - typename std::enable_if_t>::value, int> = 0> - xarray_adaptor, O, A>, layout_type::dynamic, std::decay_t> - adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A()); - - /*************************** - * xtensor_adaptor builder * - ***************************/ - - /** - * Constructs a 1-D xtensor_adaptor of the given stl-like container, - * with the specified layout_type. - * @param container the container to adapt - * @param l the layout_type of the xtensor_adaptor - */ - template - xtensor_adaptor - adapt(C&& container, layout_type l = L); - - /** - * Constructs an xtensor_adaptor of the given stl-like container, - * with the specified shape and layout_type. - * @param container the container to adapt - * @param shape the shape of the xtensor_adaptor - * @param l the layout_type of the xtensor_adaptor - */ - template >::value, int> = 0> - xtensor_adaptor::value, L> - adapt(C&& container, const SC& shape, layout_type l = L); - - /** - * Constructs an xtensor_adaptor of the given stl-like container, - * with the specified shape and strides. - * @param container the container to adapt - * @param shape the shape of the xtensor_adaptor - * @param strides the strides of the xtensor_adaptor - */ - template >::value, int> = 0, - typename std::enable_if_t>::value, int> = 0> - xtensor_adaptor::value, layout_type::dynamic> - adapt(C&& container, SC&& shape, SS&& strides); - - /** - * Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array, - * with the specified layout. - * @param pointer the pointer to the beginning of the dynamic array - * @param size the size of the dynamic array - * @param ownership indicates whether the adaptor takes ownership of the array. - * Possible values are ``no_ownerhsip()`` or ``acquire_ownership()`` - * @param l the layout_type of the xtensor_adaptor - * @param alloc the allocator used for allocating / deallocating the dynamic array - */ - template >>>> - xtensor_adaptor, O, A>, 1, L> - adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A()); - - /** - * Constructs an xtensor_adaptor of the given dynamically allocated C array, - * with the specified shape and layout. - * @param pointer the pointer to the beginning of the dynamic array - * @param size the size of the dynamic array - * @param ownership indicates whether the adaptor takes ownership of the array. - * Possible values are ``no_ownerhsip()`` or ``acquire_ownership()`` - * @param shape the shape of the xtensor_adaptor - * @param l the layout_type of the xtensor_adaptor - * @param alloc the allocator used for allocating / deallocating the dynamic array - */ - template >>>, - typename std::enable_if_t>::value, int> = 0> - xtensor_adaptor, O, A>, detail::array_size::value, L> - adapt(P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A()); - - /** - * Constructs an xtensor_adaptor of the given dynamically allocated C array, - * with the specified shape and strides. - * @param pointer the pointer to the beginning of the dynamic array - * @param size the size of the dynamic array - * @param ownership indicates whether the adaptor takes ownership of the array. - * Possible values are ``no_ownerhsip()`` or ``acquire_ownership()`` - * @param shape the shape of the xtensor_adaptor - * @param strides the strides of the xtensor_adaptor - * @param alloc the allocator used for allocating / deallocating the dynamic array - */ - template >>>, - typename std::enable_if_t>::value, int> = 0, - typename std::enable_if_t>::value, int> = 0> - xtensor_adaptor, O, A>, detail::array_size::value, layout_type::dynamic> - adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A()); - - /***************************************** - * xarray_adaptor builder implementation * - *****************************************/ - - // shape only - container version - template >::value, int>> - inline xarray_adaptor, L, std::decay_t> - adapt(C&& container, const SC& shape, layout_type l) - { - using return_type = xarray_adaptor, L, std::decay_t>; - return return_type(std::forward(container), shape, l); - } - - // shape and strides - container version - template >::value, int>, - typename std::enable_if_t>::value, int>> - inline xarray_adaptor, layout_type::dynamic, std::decay_t> - adapt(C&& container, SC&& shape, SS&& strides) - { - using return_type = xarray_adaptor, layout_type::dynamic, std::decay_t>; - return return_type(std::forward(container), - xtl::forward_sequence(shape), - xtl::forward_sequence(strides)); - } - - // shape only - buffer version - template >::value, int>> - inline xarray_adaptor, O, A>, L, SC> - adapt(P&& pointer, typename A::size_type size, O, const SC& shape, layout_type l, const A& alloc) - { - using buffer_type = xbuffer_adaptor, O, A>; - using return_type = xarray_adaptor; - buffer_type buf(std::forward

(pointer), size, alloc); - return return_type(std::move(buf), shape, l); - } - - // shape and strides - buffer version - template >::value, int>, - typename std::enable_if_t>::value, int>> - inline xarray_adaptor, O, A>, layout_type::dynamic, std::decay_t> - adapt(P&& pointer, typename A::size_type size, O, SC&& shape, SS&& strides, const A& alloc) - { - using buffer_type = xbuffer_adaptor, O, A>; - using return_type = xarray_adaptor>; - buffer_type buf(std::forward

(pointer), size, alloc); - return return_type(std::move(buf), - xtl::forward_sequence(shape), - xtl::forward_sequence(strides)); - } - - /****************************************** - * xtensor_adaptor builder implementation * - ******************************************/ - - // 1-D case - container version - template - inline xtensor_adaptor - adapt(C&& container, layout_type l) - { - const std::array::size_type, 1> shape{container.size()}; - using return_type = xtensor_adaptor, 1, L>; - return return_type(std::forward(container), shape, l); - } - - // shape only - container version - template >::value, int>> - inline xtensor_adaptor::value, L> - adapt(C&& container, const SC& shape, layout_type l) - { - constexpr std::size_t N = detail::array_size::value; - using return_type = xtensor_adaptor, N, L>; - return return_type(std::forward(container), shape, l); - } - - // shape and strides - container version - template >::value, int>, - typename std::enable_if_t>::value, int>> - inline xtensor_adaptor::value, layout_type::dynamic> - adapt(C&& container, SC&& shape, SS&& strides) - { - constexpr std::size_t N = detail::array_size::value; - using return_type = xtensor_adaptor, N, layout_type::dynamic>; - return return_type(std::forward(container), - xtl::forward_sequence(shape), - xtl::forward_sequence(strides)); - } - - // 1-D case - buffer version - template - inline xtensor_adaptor, O, A>, 1, L> - adapt(P&& pointer, typename A::size_type size, O, layout_type l, const A& alloc) - { - using buffer_type = xbuffer_adaptor, O, A>; - using return_type = xtensor_adaptor; - buffer_type buf(std::forward

(pointer), size, alloc); - const std::array shape{size}; - return return_type(std::move(buf), shape, l); - } - - // shape only - buffer version - template >::value, int>> - inline xtensor_adaptor, O, A>, detail::array_size::value, L> - adapt(P&& pointer, typename A::size_type size, O, const SC& shape, layout_type l, const A& alloc) - { - using buffer_type = xbuffer_adaptor, O, A>; - constexpr std::size_t N = detail::array_size::value; - using return_type = xtensor_adaptor; - buffer_type buf(std::forward

(pointer), size, alloc); - return return_type(std::move(buf), shape, l); - } - - // shape and strides - buffer version - template >::value, int>, - typename std::enable_if_t>::value, int>> - inline xtensor_adaptor, O, A>, detail::array_size::value, layout_type::dynamic> - adapt(P&& pointer, typename A::size_type size, O, SC&& shape, SS&& strides, const A& alloc) - { - using buffer_type = xbuffer_adaptor, O, A>; - constexpr std::size_t N = detail::array_size::value; - using return_type = xtensor_adaptor; - buffer_type buf(std::forward

(pointer), size, alloc); - return return_type(std::move(buf), - xtl::forward_sequence(shape), - xtl::forward_sequence(strides)); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xarray.hpp b/vendor/xtensor/include/xtensor/xarray.hpp deleted file mode 100644 index 7c51f2812..000000000 --- a/vendor/xtensor/include/xtensor/xarray.hpp +++ /dev/null @@ -1,550 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ARRAY_HPP -#define XTENSOR_ARRAY_HPP - -#include -#include -#include - -#include - -#include "xbuffer_adaptor.hpp" -#include "xcontainer.hpp" -#include "xsemantic.hpp" - -namespace xt -{ - - /******************************** - * xarray_container declaration * - ********************************/ - - template - struct xcontainer_inner_types> - { - using storage_type = EC; - using shape_type = SC; - using strides_type = shape_type; - using backstrides_type = shape_type; - using inner_shape_type = shape_type; - using inner_strides_type = strides_type; - using inner_backstrides_type = backstrides_type; - using temporary_type = xarray_container; - static constexpr layout_type layout = L; - }; - - template - struct xiterable_inner_types> - : xcontainer_iterable_types> - { - }; - - /** - * @class xarray_container - * @brief Dense multidimensional container with tensor semantic. - * - * The xarray_container class implements a dense multidimensional container - * with tensor semantic. - * - * @tparam EC The type of the container holding the elements. - * @tparam L The layout_type of the container. - * @tparam SC The type of the containers holding the shape and the strides. - * @tparam Tag The expression tag. - * @sa xarray - */ - template - class xarray_container : public xstrided_container>, - public xcontainer_semantic> - { - public: - - using self_type = xarray_container; - using base_type = xstrided_container; - using semantic_base = xcontainer_semantic; - using storage_type = typename base_type::storage_type; - using allocator_type = typename base_type::allocator_type; - using value_type = typename base_type::value_type; - using reference = typename base_type::reference; - using const_reference = typename base_type::const_reference; - using pointer = typename base_type::pointer; - using const_pointer = typename base_type::const_pointer; - using shape_type = typename base_type::shape_type; - using inner_shape_type = typename base_type::inner_shape_type; - using strides_type = typename base_type::strides_type; - using backstrides_type = typename base_type::backstrides_type; - using inner_strides_type = typename base_type::inner_strides_type; - using temporary_type = typename semantic_base::temporary_type; - using expression_tag = Tag; - - xarray_container(); - explicit xarray_container(const shape_type& shape, layout_type l = L); - explicit xarray_container(const shape_type& shape, const_reference value, layout_type l = L); - explicit xarray_container(const shape_type& shape, const strides_type& strides); - explicit xarray_container(const shape_type& shape, const strides_type& strides, const_reference value); - explicit xarray_container(storage_type&& storage, inner_shape_type&& shape, inner_strides_type&& strides); - - xarray_container(const value_type& t); - xarray_container(nested_initializer_list_t t); - xarray_container(nested_initializer_list_t t); - xarray_container(nested_initializer_list_t t); - xarray_container(nested_initializer_list_t t); - xarray_container(nested_initializer_list_t t); - - template - static xarray_container from_shape(S&& s); - - ~xarray_container() = default; - - xarray_container(const xarray_container&) = default; - xarray_container& operator=(const xarray_container&) = default; - - xarray_container(xarray_container&&) = default; - xarray_container& operator=(xarray_container&&) = default; - - template - xarray_container(const xexpression& e); - - template - xarray_container& operator=(const xexpression& e); - - private: - - storage_type m_storage; - - storage_type& storage_impl() noexcept; - const storage_type& storage_impl() const noexcept; - - friend class xcontainer>; - }; - - /****************************** - * xarray_adaptor declaration * - ******************************/ - - template - struct xcontainer_inner_types> - { - using storage_type = std::remove_reference_t; - using shape_type = SC; - using strides_type = shape_type; - using backstrides_type = shape_type; - using inner_shape_type = shape_type; - using inner_strides_type = strides_type; - using inner_backstrides_type = backstrides_type; - using temporary_type = xarray_container, L, SC, Tag>; - static constexpr layout_type layout = L; - }; - - template - struct xiterable_inner_types> - : xcontainer_iterable_types> - { - }; - - /** - * @class xarray_adaptor - * @brief Dense multidimensional container adaptor with - * tensor semantic. - * - * The xarray_adaptor class implements a dense multidimensional - * container adaptor with tensor semantic. It is used to provide - * a multidimensional container semantic and a tensor semantic to - * stl-like containers. - * - * @tparam EC The closure for the container type to adapt. - * @tparam L The layout_type of the adaptor. - * @tparam SC The type of the containers holding the shape and the strides. - * @tparam Tag The expression tag. - */ - template - class xarray_adaptor : public xstrided_container>, - public xcontainer_semantic> - { - public: - - using container_closure_type = EC; - - using self_type = xarray_adaptor; - using base_type = xstrided_container; - using semantic_base = xcontainer_semantic; - using storage_type = typename base_type::storage_type; - using allocator_type = typename base_type::allocator_type; - using shape_type = typename base_type::shape_type; - using strides_type = typename base_type::strides_type; - using backstrides_type = typename base_type::backstrides_type; - using temporary_type = typename semantic_base::temporary_type; - using expression_tag = Tag; - - xarray_adaptor(storage_type&& storage); - xarray_adaptor(const storage_type& storage); - - template - xarray_adaptor(D&& storage, const shape_type& shape, layout_type l = L); - - template - xarray_adaptor(D&& storage, const shape_type& shape, const strides_type& strides); - - ~xarray_adaptor() = default; - - xarray_adaptor(const xarray_adaptor&) = default; - xarray_adaptor& operator=(const xarray_adaptor&); - - xarray_adaptor(xarray_adaptor&&) = default; - xarray_adaptor& operator=(xarray_adaptor&&); - xarray_adaptor& operator=(temporary_type&&); - - template - xarray_adaptor& operator=(const xexpression& e); - - private: - - container_closure_type m_storage; - - storage_type& storage_impl() noexcept; - const storage_type& storage_impl() const noexcept; - - - friend class xcontainer>; - }; - - /*********************************** - * xarray_container implementation * - ***********************************/ - - /** - * @name Constructors - */ - //@{ - /** - * Allocates an uninitialized xarray_container that holds 0 element. - */ - template - inline xarray_container::xarray_container() - : base_type(), m_storage(1, value_type()) - { - } - - /** - * Allocates an uninitialized xarray_container with the specified shape and - * layout_type. - * @param shape the shape of the xarray_container - * @param l the layout_type of the xarray_container - */ - template - inline xarray_container::xarray_container(const shape_type& shape, layout_type l) - : base_type() - { - base_type::resize(shape, l); - } - - /** - * Allocates an xarray_container with the specified shape and layout_type. Elements - * are initialized to the specified value. - * @param shape the shape of the xarray_container - * @param value the value of the elements - * @param l the layout_type of the xarray_container - */ - template - inline xarray_container::xarray_container(const shape_type& shape, const_reference value, layout_type l) - : base_type() - { - base_type::resize(shape, l); - std::fill(m_storage.begin(), m_storage.end(), value); - } - - /** - * Allocates an uninitialized xarray_container with the specified shape and strides. - * @param shape the shape of the xarray_container - * @param strides the strides of the xarray_container - */ - template - inline xarray_container::xarray_container(const shape_type& shape, const strides_type& strides) - : base_type() - { - base_type::resize(shape, strides); - } - - /** - * Allocates an uninitialized xarray_container with the specified shape and strides. - * Elements are initialized to the specified value. - * @param shape the shape of the xarray_container - * @param strides the strides of the xarray_container - * @param value the value of the elements - */ - template - inline xarray_container::xarray_container(const shape_type& shape, const strides_type& strides, const_reference value) - : base_type() - { - base_type::resize(shape, strides); - std::fill(m_storage.begin(), m_storage.end(), value); - } - - /** - * Allocates an xarray_container that holds a single element initialized to the - * specified value. - * @param t the value of the element - */ - template - inline xarray_container::xarray_container(const value_type& t) - : base_type() - { - base_type::resize(xt::shape(t), true); - nested_copy(m_storage.begin(), t); - } - - /** - * Allocates an xarray_container by moving specified data, shape and strides - * - * @param storage the data for the xarray_container - * @param shape the shape of the xarray_container - * @param strides the strides of the xarray_container - */ - template - inline xarray_container::xarray_container(storage_type&& storage, inner_shape_type&& shape, inner_strides_type&& strides) - : base_type(std::move(shape), std::move(strides)), m_storage(std::move(storage)) - { - } - //@} - - /** - * @name Constructors from initializer list - */ - //@{ - /** - * Allocates a one-dimensional xarray_container. - * @param t the elements of the xarray_container - */ - template - inline xarray_container::xarray_container(nested_initializer_list_t t) - : base_type() - { - base_type::resize(xt::shape(t)); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } - - /** - * Allocates a two-dimensional xarray_container. - * @param t the elements of the xarray_container - */ - template - inline xarray_container::xarray_container(nested_initializer_list_t t) - : base_type() - { - base_type::resize(xt::shape(t)); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } - - /** - * Allocates a three-dimensional xarray_container. - * @param t the elements of the xarray_container - */ - template - inline xarray_container::xarray_container(nested_initializer_list_t t) - : base_type() - { - base_type::resize(xt::shape(t)); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } - - /** - * Allocates a four-dimensional xarray_container. - * @param t the elements of the xarray_container - */ - template - inline xarray_container::xarray_container(nested_initializer_list_t t) - : base_type() - { - base_type::resize(xt::shape(t)); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } - - /** - * Allocates a five-dimensional xarray_container. - * @param t the elements of the xarray_container - */ - template - inline xarray_container::xarray_container(nested_initializer_list_t t) - : base_type() - { - base_type::resize(xt::shape(t)); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } - //@} - - /** - * Allocates and returns an xarray_container with the specified shape. - * @param s the shape of the xarray_container - */ - template - template - inline xarray_container xarray_container::from_shape(S&& s) - { - shape_type shape = xtl::forward_sequence(s); - return self_type(shape); - } - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended copy constructor. - */ - template - template - inline xarray_container::xarray_container(const xexpression& e) - : base_type() - { - // Avoids unintialized data because of (m_shape == shape) condition - // in resize (called by assign), which is always true when dimension == 0. - if (e.derived_cast().dimension() == 0) - { - detail::resize_data_container(m_storage, std::size_t(1)); - } - semantic_base::assign(e); - } - - /** - * The extended assignment operator. - */ - template - template - inline auto xarray_container::operator=(const xexpression& e) -> self_type& - { - return semantic_base::operator=(e); - } - //@} - - template - inline auto xarray_container::storage_impl() noexcept -> storage_type& - { - return m_storage; - } - - template - inline auto xarray_container::storage_impl() const noexcept -> const storage_type& - { - return m_storage; - } - - /****************** - * xarray_adaptor * - ******************/ - - /** - * @name Constructors - */ - //@{ - /** - * Constructs an xarray_adaptor of the given stl-like container. - * @param storage the container to adapt - */ - template - inline xarray_adaptor::xarray_adaptor(storage_type&& storage) - : base_type(), m_storage(std::move(storage)) - { - } - - /** - * Constructs an xarray_adaptor of the given stl-like container. - * @param storage the container to adapt - */ - template - inline xarray_adaptor::xarray_adaptor(const storage_type& storage) - : base_type(), m_storage(storage) - { - } - - /** - * Constructs an xarray_adaptor of the given stl-like container, - * with the specified shape and layout_type. - * @param storage the container to adapt - * @param shape the shape of the xarray_adaptor - * @param l the layout_type of the xarray_adaptor - */ - template - template - inline xarray_adaptor::xarray_adaptor(D&& storage, const shape_type& shape, layout_type l) - : base_type(), m_storage(std::forward(storage)) - { - base_type::resize(shape, l); - } - - /** - * Constructs an xarray_adaptor of the given stl-like container, - * with the specified shape and strides. - * @param storage the container to adapt - * @param shape the shape of the xarray_adaptor - * @param strides the strides of the xarray_adaptor - */ - template - template - inline xarray_adaptor::xarray_adaptor(D&& storage, const shape_type& shape, const strides_type& strides) - : base_type(), m_storage(std::forward(storage)) - { - base_type::resize(shape, strides); - } - //@} - - template - inline auto xarray_adaptor::operator=(const xarray_adaptor& rhs) -> self_type& - { - base_type::operator=(rhs); - m_storage = rhs.m_storage; - return *this; - } - - template - inline auto xarray_adaptor::operator=(xarray_adaptor&& rhs) -> self_type& - { - base_type::operator=(std::move(rhs)); - m_storage = rhs.m_storage; - return *this; - } - - template - inline auto xarray_adaptor::operator=(temporary_type&& rhs) -> self_type& - { - base_type::shape_impl() = std::move(const_cast(rhs.shape())); - base_type::strides_impl() = std::move(const_cast(rhs.strides())); - base_type::backstrides_impl() = std::move(const_cast(rhs.backstrides())); - m_storage = std::move(rhs.storage()); - return *this; - } - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended assignment operator. - */ - template - template - inline auto xarray_adaptor::operator=(const xexpression& e) -> self_type& - { - return semantic_base::operator=(e); - } - //@} - - template - inline auto xarray_adaptor::storage_impl() noexcept -> storage_type& - { - return m_storage; - } - - template - inline auto xarray_adaptor::storage_impl() const noexcept -> const storage_type& - { - return m_storage; - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xassign.hpp b/vendor/xtensor/include/xtensor/xassign.hpp deleted file mode 100644 index 1b2f4c00d..000000000 --- a/vendor/xtensor/include/xtensor/xassign.hpp +++ /dev/null @@ -1,783 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ASSIGN_HPP -#define XTENSOR_ASSIGN_HPP - -#include -#include -#include - -#include - -#include "xconcepts.hpp" -#include "xexpression.hpp" -#include "xiterator.hpp" -#include "xstrides.hpp" -#include "xtensor_forward.hpp" -#include "xutils.hpp" - -namespace xt -{ - - /******************** - * Assign functions * - ********************/ - - template - void assign_data(xexpression& e1, const xexpression& e2, bool trivial); - - template - void assign_xexpression(xexpression& e1, const xexpression& e2); - - template - void computed_assign(xexpression& e1, const xexpression& e2); - - template - void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f); - - template - void assert_compatible_shape(const xexpression& e1, const xexpression& e2); - - template - void strided_assign(E1& e1, const E2& e2, std::false_type /*disable*/); - - template - void strided_assign(E1& e1, const E2& e2, std::true_type /*enable*/); - - /************************ - * xexpression_assigner * - ************************/ - - template - class xexpression_assigner_base; - - template <> - class xexpression_assigner_base - { - public: - - template - static void assign_data(xexpression& e1, const xexpression& e2, bool trivial); - }; - - template - class xexpression_assigner : public xexpression_assigner_base - { - public: - - using base_type = xexpression_assigner_base; - - template - static void assign_xexpression(xexpression& e1, const xexpression& e2); - - template - static void computed_assign(xexpression& e1, const xexpression& e2); - - template - static void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f); - - template - static void assert_compatible_shape(const xexpression& e1, const xexpression& e2); - - private: - - template - static bool resize(xexpression& e1, const xexpression& e2); - }; - - /***************** - * data_assigner * - *****************/ - - template - class data_assigner - { - public: - - using lhs_iterator = typename E1::stepper; - using rhs_iterator = typename E2::const_stepper; - using shape_type = typename E1::shape_type; - using index_type = xindex_type_t; - using size_type = typename lhs_iterator::size_type; - using difference_type = typename lhs_iterator::difference_type; - - data_assigner(E1& e1, const E2& e2); - - void run(); - - void step(size_type i); - void step(size_type i, size_type n); - void reset(size_type i); - - void to_end(layout_type); - - private: - - E1& m_e1; - - lhs_iterator m_lhs; - rhs_iterator m_rhs; - - index_type m_index; - }; - - /******************** - * trivial_assigner * - ********************/ - - template - struct trivial_assigner - { - template - static void run(E1& e1, const E2& e2); - }; - - /*********************************** - * Assign functions implementation * - ***********************************/ - - template - inline void assign_data(xexpression& e1, const xexpression& e2, bool trivial) - { - using tag = xexpression_tag_t; - xexpression_assigner::assign_data(e1, e2, trivial); - } - - template - inline void assign_xexpression(xexpression& e1, const xexpression& e2) - { - xtl::mpl::static_if::value>([&](auto self) - { - self(e2).derived_cast().assign_to(e1); - }, /*else*/ [&](auto /*self*/) - { - using tag = xexpression_tag_t; - xexpression_assigner::assign_xexpression(e1, e2); - }); - } - - template - inline void computed_assign(xexpression& e1, const xexpression& e2) - { - using tag = xexpression_tag_t; - xexpression_assigner::computed_assign(e1, e2); - } - - template - inline void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f) - { - using tag = xexpression_tag_t; - xexpression_assigner::scalar_computed_assign(e1, e2, std::forward(f)); - } - - template - inline void assert_compatible_shape(const xexpression& e1, const xexpression& e2) - { - using tag = xexpression_tag_t; - xexpression_assigner::assert_compatible_shape(e1, e2); - } - - /*************************************** - * xexpression_assigner implementation * - ***************************************/ - - namespace detail - { - template - inline bool is_trivial_broadcast(const E1& e1, const E2& e2) - { - return (E1::contiguous_layout && E2::contiguous_layout && (E1::static_layout == E2::static_layout)) - || e2.is_trivial_broadcast(e1.strides()); - } - - template - inline bool is_trivial_broadcast(const xview&, const E2&) - { - return false; - } - - template > - struct forbid_simd_assign - { - static constexpr bool value = true; - }; - - // Double steps check for xfunction because the default - // parameter void_t of forbid_simd_assign prevents additional - // specializations. - template - struct xfunction_forbid_simd; - - template - struct forbid_simd_assign().template load_simd(typename E::size_type(0)))>> - { - static constexpr bool value = false || xfunction_forbid_simd::value; - }; - - template - struct xfunction_forbid_simd - { - static constexpr bool value = false; - }; - - template - struct xfunction_forbid_simd> - { - static constexpr bool value = xtl::disjunction< - std::integral_constant::type>::value>...>::value; - }; - - template - struct has_simd_apply : std::false_type {}; - - template - struct has_simd_apply)>> - : std::true_type - { - }; - - template - struct has_step_leading : std::false_type - { - }; - - template - struct has_step_leading().step_leading())>> - : std::true_type - { - }; - - template - struct use_strided_loop - { - static constexpr bool stepper_deref() { return std::is_reference::value; } - static constexpr bool value = has_strides::value && has_step_leading::value && stepper_deref(); - }; - - template - struct use_strided_loop> - { - static constexpr bool value = true; - }; - - template - struct use_strided_loop> - { - static constexpr bool value = xtl::conjunction>...>::value && - has_simd_apply>::value; - }; - } - - template - struct xassign_traits - { - // constexpr methods instead of constexpr data members avoid the need of difinitions at namespace - // scope of these data members (since they are odr-used). - static constexpr bool contiguous_layout() { return E1::contiguous_layout && E2::contiguous_layout; } - static constexpr bool same_type() { return std::is_same::value; } - static constexpr bool simd_size() { return xsimd::simd_traits::size > 1; } - static constexpr bool forbid_simd() { return detail::forbid_simd_assign::value; } - static constexpr bool simd_assign() { return contiguous_layout() && same_type() && simd_size() && !forbid_simd(); } - static constexpr bool simd_strided_loop() { return same_type() && simd_size() && detail::use_strided_loop::value && detail::use_strided_loop::value; } - }; - - template - inline void xexpression_assigner_base::assign_data(xexpression& e1, const xexpression& e2, bool trivial) - { - E1& de1 = e1.derived_cast(); - const E2& de2 = e2.derived_cast(); - - bool trivial_broadcast = trivial && detail::is_trivial_broadcast(de1, de2); - - if (trivial_broadcast) - { - constexpr bool simd_assign = xassign_traits::simd_assign(); - trivial_assigner::run(de1, de2); - } - else if (xassign_traits::simd_strided_loop()) - { - strided_assign(de1, de2, std::integral_constant::simd_strided_loop()>{}); - } - else - { - data_assigner assigner(de1, de2); - assigner.run(); - } - } - - template - template - inline void xexpression_assigner::assign_xexpression(xexpression& e1, const xexpression& e2) - { - bool trivial_broadcast = resize(e1, e2); - base_type::assign_data(e1, e2, trivial_broadcast); - } - - template - template - inline void xexpression_assigner::computed_assign(xexpression& e1, const xexpression& e2) - { - using shape_type = typename E1::shape_type; - using size_type = typename E1::size_type; - - E1& de1 = e1.derived_cast(); - const E2& de2 = e2.derived_cast(); - - size_type dim = de2.dimension(); - shape_type shape = xtl::make_sequence(dim, size_type(0)); - bool trivial_broadcast = de2.broadcast_shape(shape, true); - - if (dim > de1.dimension() || shape > de1.shape()) - { - typename E1::temporary_type tmp(shape); - base_type::assign_data(tmp, e2, trivial_broadcast); - de1.assign_temporary(std::move(tmp)); - } - else - { - base_type::assign_data(e1, e2, trivial_broadcast); - } - } - - template - template - inline void xexpression_assigner::scalar_computed_assign(xexpression& e1, const E2& e2, F&& f) - { - E1& d = e1.derived_cast(); - using size_type = typename E1::size_type; - auto dst = d.storage().begin(); - for (size_type i = d.size(); i > 0; --i) - { - *dst = f(*dst, e2); - ++dst; - } - } - - template - template - inline void xexpression_assigner::assert_compatible_shape(const xexpression& e1, const xexpression& e2) - { - const E1& de1 = e1.derived_cast(); - const E2& de2 = e2.derived_cast(); - if (!broadcastable(de2.shape(), de1.shape())) - { - throw_broadcast_error(de2.shape(), de1.shape()); - } - } - - template - template - inline bool xexpression_assigner::resize(xexpression& e1, const xexpression& e2) - { - using shape_type = typename E1::shape_type; - using size_type = typename E1::size_type; - const E2& de2 = e2.derived_cast(); - size_type size = de2.dimension(); - shape_type shape = xtl::make_sequence(size, size_type(0)); - bool trivial_broadcast = de2.broadcast_shape(shape, true); - e1.derived_cast().resize(std::move(shape)); - return trivial_broadcast; - } - - /******************************** - * data_assigner implementation * - ********************************/ - - template - inline data_assigner::data_assigner(E1& e1, const E2& e2) - : m_e1(e1), m_lhs(e1.stepper_begin(e1.shape())), - m_rhs(e2.stepper_begin(e1.shape())), - m_index(xtl::make_sequence(e1.shape().size(), size_type(0))) - { - } - - template - inline void data_assigner::run() - { - using size_type = typename E1::size_type; - using argument_type = std::decay_t; - using result_type = std::decay_t; - constexpr bool is_narrowing = is_narrowing_conversion::value; - - size_type s = m_e1.size(); - for (size_type i = 0; i < s; ++i) - { - *m_lhs = conditional_cast(*m_rhs); - stepper_tools::increment_stepper(*this, m_index, m_e1.shape()); - } - } - - template - inline void data_assigner::step(size_type i) - { - m_lhs.step(i); - m_rhs.step(i); - } - - template - inline void data_assigner::step(size_type i, size_type n) - { - m_lhs.step(i, n); - m_rhs.step(i, n); - } - - template - inline void data_assigner::reset(size_type i) - { - m_lhs.reset(i); - m_rhs.reset(i); - } - - template - inline void data_assigner::to_end(layout_type l) - { - m_lhs.to_end(l); - m_rhs.to_end(l); - } - - /*********************************** - * trivial_assigner implementation * - ***********************************/ - - template - template - inline void trivial_assigner::run(E1& e1, const E2& e2) - { - using lhs_align_mode = xsimd::container_alignment_t; - constexpr bool is_aligned = std::is_same::value; - using rhs_align_mode = std::conditional_t; - using value_type = std::common_type_t; - using simd_type = xsimd::simd_type; - using size_type = typename E1::size_type; - size_type size = e1.size(); - size_type simd_size = simd_type::size; - - size_type align_begin = is_aligned ? 0 : xsimd::get_alignment_offset(e1.data(), size, simd_size); - size_type align_end = align_begin + ((size - align_begin) & ~(simd_size - 1)); - - for (size_type i = 0; i < align_begin; ++i) - { - e1.data_element(i) = e2.data_element(i); - } - for (size_type i = align_begin; i < align_end; i += simd_size) - { - e1.template store_simd(i, e2.template load_simd(i)); - } - for (size_type i = align_end; i < size; ++i) - { - e1.data_element(i) = e2.data_element(i); - } - } - - namespace assigner_detail - { - template - inline void assign_loop(It src, Ot dst, std::size_t n) - { - for(; n > 0; --n) - { - *dst = static_cast(*src); - ++src; - ++dst; - } - } - - template - inline void trivial_assigner_run_impl(E1& e1, const E2& e2, std::true_type) - { - using size_type = typename E1::size_type; - auto src = e2.storage_cbegin(); - auto dst = e1.storage_begin(); - assign_loop(src, dst, e1.size()); - } - - template - inline void trivial_assigner_run_impl(E1&, const E2&, std::false_type) - { - XTENSOR_PRECONDITION(false, - "Internal error: trivial_assigner called with unrelated types."); - } - } - - template <> - template - inline void trivial_assigner::run(E1& e1, const E2& e2) - { - using is_convertible = std::is_convertible::value_type, - typename std::decay_t::value_type>; - // If the types are not compatible, this function is still instantiated but never called. - // To avoid compilation problems in effectively unused code trivial_assigner_run_impl is - // empty in this case. - assigner_detail::trivial_assigner_run_impl(e1, e2, is_convertible()); - } - - /*********************** - * Strided assign loop * - ***********************/ - - namespace strided_assign_detail - { - template - struct idx_tools; - - template <> - struct idx_tools - { - template - static void next_idx(T& outer_index, T& outer_shape) - { - auto i = outer_index.size(); - for (; i > 0; --i) - { - if (outer_index[i - 1] + 1 >= outer_shape[i - 1]) - { - outer_index[i - 1] = 0; - } - else - { - outer_index[i - 1]++; - break; - } - } - } - }; - - template <> - struct idx_tools - { - template - static void next_idx(T& outer_index, T& outer_shape) - { - using size_type = typename T::size_type; - size_type i = 0; - auto sz = outer_index.size(); - for (; i < sz; ++i) - { - if (outer_index[i] + 1 >= outer_shape[i]) - { - outer_index[i] = 0; - } - else - { - outer_index[i]++; - break; - } - } - } - }; - - template - struct check_strides_functor - { - using strides_type = S; - - check_strides_functor(const S& strides) - : m_cut(L == layout_type::row_major ? 0 : strides.size()), - m_strides(strides) - { - } - - template - std::enable_if_t - operator()(const T& el) - { - auto var = check_strides_overlap::get(m_strides, el.strides()); - if (var > m_cut) - { - m_cut = var; - } - return m_cut; - } - - template - std::enable_if_t - operator()(const T& el) - { - auto var = check_strides_overlap::get(m_strides, el.strides()); - if (var < m_cut) - { - m_cut = var; - } - return m_cut; - } - - template - std::size_t operator()(const xt::xscalar& /*el*/) - { - return m_cut; - } - - template - std::size_t operator()(const xt::xfunction& xf) - { - xt::for_each(*this, xf.arguments()); - return m_cut; - } - - private: - - std::size_t m_cut; - const strides_type& m_strides; - }; - - template - auto get_loop_sizes(const E1& e1, const E2& e2) - { - std::size_t cut = 0; - - // TODO! if E1 is !contigous --> initialize cut to sensible value! - if (e1.strides().back() == 1) - { - auto csf = check_strides_functor(e1.strides()); - cut = csf(e2); - } - else if (e1.strides().front() == 1) - { - auto csf = check_strides_functor(e1.strides()); - cut = csf(e2); - } - - using shape_value_type = typename E1::shape_type::value_type; - std::size_t outer_loop_size = static_cast( - std::accumulate(e1.shape().begin(), e1.shape().begin() + static_cast(cut), - shape_value_type(1), std::multiplies{})); - std::size_t inner_loop_size = static_cast( - std::accumulate(e1.shape().begin() + static_cast(cut), e1.shape().end(), - shape_value_type(1), std::multiplies{})); - - if (e1.strides().back() != 1) // column major mode - { - std::swap(outer_loop_size, inner_loop_size); - } - - return std::make_tuple(inner_loop_size, outer_loop_size, cut); - } - } - - template - void strided_assign(E1& e1, const E2& e2, std::true_type /*enable*/) - { - bool fallback = false, is_row_major = true; - - std::size_t inner_loop_size, outer_loop_size, cut; - std::tie(inner_loop_size, outer_loop_size, cut) = strided_assign_detail::get_loop_sizes(e1, e2); - - if (E1::static_layout == layout_type::row_major || e1.strides().back() == 1) // row major case - { - if (cut == e1.dimension()) - { - fallback = true; - } - } - else if (E1::static_layout == layout_type::column_major || e1.strides().front() == 1) // col major case - { - is_row_major = false; - if (cut == 0) - { - fallback = true; - } - } - else - { - fallback = true; - } - - if (fallback) - { - data_assigner assigner(e1, e2); - assigner.run(); - return; - } - - // TODO can we get rid of this and use `shape_type`? - dynamic_shape idx; - - using iterator_type = decltype(e1.shape().begin()); - iterator_type max_shape_begin, max_shape_end; - if (is_row_major) - { - xt::resize_container(idx, cut); - max_shape_begin = e1.shape().begin(); - max_shape_end = e1.shape().begin() + static_cast(cut); - } - else - { - xt::resize_container(idx, e1.shape().size() - cut); - max_shape_begin = e1.shape().begin() + static_cast(cut); - max_shape_end = e1.shape().end(); - } - - // add this when we have std::array index! - // std::fill(idx.begin(), idx.end(), 0); - - dynamic_shape max(max_shape_begin, max_shape_end); - - using simd_type = xsimd::simd_type; - - std::size_t simd_size = inner_loop_size / simd_type::size; - std::size_t simd_rest = inner_loop_size % simd_type::size; - - auto fct_stepper = e2.stepper_begin(e1.shape()); - auto res_stepper = e1.stepper_begin(e1.shape()); - - // TODO in 1D case this is ambigous -- could be RM or CM. - // Use default layout to make decision - std::size_t step_dim = 0; - if (!is_row_major) // row major case - { - step_dim = cut; - } - - for (std::size_t ox = 0; ox < outer_loop_size; ++ox) - { - for (std::size_t i = 0; i < simd_size; i++) - { - res_stepper.template store_simd(fct_stepper.template step_simd()); - } - for (std::size_t i = 0; i < simd_rest; ++i) - { - *(res_stepper) = *(fct_stepper); - res_stepper.step_leading(); - fct_stepper.step_leading(); - } - - is_row_major ? - strided_assign_detail::idx_tools::next_idx(idx, max) : - strided_assign_detail::idx_tools::next_idx(idx, max); - - fct_stepper.to_begin(); - - // need to step E1 as well if not contigous assign (e.g. view) - if (!E1::contiguous_layout) - { - res_stepper.to_begin(); - for (std::size_t i = 0; i < idx.size(); ++i) - { - fct_stepper.step(i + step_dim, idx[i]); - res_stepper.step(i + step_dim, idx[i]); - } - } - else - { - for (std::size_t i = 0; i < idx.size(); ++i) - { - fct_stepper.step(i + step_dim, idx[i]); - } - } - } - } - - template - inline void strided_assign(E1& /*e1*/, const E2& /*e2*/, std::false_type /*disable*/) - { - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xaxis_iterator.hpp b/vendor/xtensor/include/xtensor/xaxis_iterator.hpp deleted file mode 100644 index e544791b8..000000000 --- a/vendor/xtensor/include/xtensor/xaxis_iterator.hpp +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_AXIS_ITERATOR_HPP -#define XTENSOR_AXIS_ITERATOR_HPP - -#include - -#include "xview.hpp" - -namespace xt -{ - - /****************** - * xaxis_iterator * - ******************/ - - template - class xaxis_iterator - { - public: - - using self_type = xaxis_iterator; - - using xexpression_type = std::decay_t; - using size_type = typename xexpression_type::size_type; - using difference_type = typename xexpression_type::difference_type; - using value_type = xview; - using reference = std::remove_reference_t>; - using pointer = xtl::xclosure_pointer>>; - - using iterator_category = std::forward_iterator_tag; - - xaxis_iterator(); - template - xaxis_iterator(CTA&& e, size_type index); - - self_type& operator++(); - self_type operator++(int); - - reference operator*() const; - pointer operator->() const; - - bool equal(const self_type& rhs) const; - - private: - - using storing_type = xtl::ptr_closure_type_t; - mutable storing_type p_expression; - size_type m_index; - - template - std::enable_if_t::value, std::add_lvalue_reference_t>> - deref(T val) const; - - template - std::enable_if_t::value, T> - deref(T& val) const; - - template - std::enable_if_t::value, T> - get_storage_init(CTA&& e) const; - - template - std::enable_if_t::value, T> - get_storage_init(CTA&& e) const; - }; - - template - bool operator==(const xaxis_iterator& lhs, const xaxis_iterator& rhs); - - template - bool operator!=(const xaxis_iterator& lhs, const xaxis_iterator& rhs); - - template - auto axis_begin(E&& e); - - template - auto axis_end(E&& e); - - /********************************* - * xaxis_iterator implementation * - *********************************/ - - template - template - inline std::enable_if_t::value, std::add_lvalue_reference_t>> - xaxis_iterator::deref(T val) const - { - return *val; - } - - template - template - inline std::enable_if_t::value, T> - xaxis_iterator::deref(T& val) const - { - return val; - } - - template - template - inline std::enable_if_t::value, T> - xaxis_iterator::get_storage_init(CTA&& e) const - { - return &e; - } - - template - template - inline std::enable_if_t::value, T> - xaxis_iterator::get_storage_init(CTA&& e) const - { - return e; - } - - template - inline xaxis_iterator::xaxis_iterator() - : p_expression(nullptr), m_index(0) - { - } - - template - template - inline xaxis_iterator::xaxis_iterator(CTA&& e, size_type index) - : p_expression(get_storage_init(std::forward(e))), m_index(index) - { - } - - template - inline auto xaxis_iterator::operator++() -> self_type& - { - ++m_index; - return *this; - } - - template - inline auto xaxis_iterator::operator++(int) -> self_type - { - self_type tmp(*this); - ++(*this); - return tmp; - } - - template - inline auto xaxis_iterator::operator*() const -> reference - { - return view(deref(p_expression), size_type(m_index)); - } - - template - inline auto xaxis_iterator::operator->() const -> pointer - { - return xtl::closure_pointer(operator*()); - } - - template - inline bool xaxis_iterator::equal(const self_type& rhs) const - { - return p_expression == rhs.p_expression && m_index == rhs.m_index; - } - - template - inline bool operator==(const xaxis_iterator& lhs, const xaxis_iterator& rhs) - { - return lhs.equal(rhs); - } - - template - inline bool operator!=(const xaxis_iterator& lhs, const xaxis_iterator& rhs) - { - return !(lhs == rhs); - } - - template - inline auto axis_begin(E&& e) - { - using return_type = xaxis_iterator>; - using size_type = typename std::decay_t::size_type; - return return_type(std::forward(e), size_type(0)); - } - - template - inline auto axis_end(E&& e) - { - using return_type = xaxis_iterator>; - using size_type = typename std::decay_t::size_type; - return return_type(std::forward(e), size_type(e.shape()[0])); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xbroadcast.hpp b/vendor/xtensor/include/xtensor/xbroadcast.hpp deleted file mode 100644 index 77c04f041..000000000 --- a/vendor/xtensor/include/xtensor/xbroadcast.hpp +++ /dev/null @@ -1,412 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_BROADCAST_HPP -#define XTENSOR_BROADCAST_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "xexpression.hpp" -#include "xiterable.hpp" -#include "xscalar.hpp" -#include "xstrides.hpp" -#include "xutils.hpp" - -namespace xt -{ - - /************* - * broadcast * - *************/ - - template - auto broadcast(E&& e, const S& s); - -#ifdef X_OLD_CLANG - template - auto broadcast(E&& e, std::initializer_list s); -#else - template - auto broadcast(E&& e, const I (&s)[L]); -#endif - - /************** - * xbroadcast * - **************/ - - template - class xbroadcast; - - template - struct xiterable_inner_types> - { - using xexpression_type = std::decay_t; - using inner_shape_type = promote_shape_t; - using const_stepper = typename xexpression_type::const_stepper; - using stepper = const_stepper; - }; - - /** - * @class xbroadcast - * @brief Broadcasted xexpression to a specified shape. - * - * The xbroadcast class implements the broadcasting of an \ref xexpression - * to a specified shape. xbroadcast is not meant to be used directly, but - * only with the \ref broadcast helper functions. - * - * @tparam CT the closure type of the \ref xexpression to broadcast - * @tparam X the type of the specified shape. - * - * @sa broadcast - */ - template - class xbroadcast : public xexpression>, - public xconst_iterable> - { - public: - - using self_type = xbroadcast; - using xexpression_type = std::decay_t; - - using value_type = typename xexpression_type::value_type; - using reference = typename xexpression_type::reference; - using const_reference = typename xexpression_type::const_reference; - using pointer = typename xexpression_type::pointer; - using const_pointer = typename xexpression_type::const_pointer; - using size_type = typename xexpression_type::size_type; - using difference_type = typename xexpression_type::difference_type; - - using iterable_base = xconst_iterable; - using inner_shape_type = typename iterable_base::inner_shape_type; - using shape_type = inner_shape_type; - - using stepper = typename iterable_base::stepper; - using const_stepper = typename iterable_base::const_stepper; - - static constexpr layout_type static_layout = xexpression_type::static_layout; - //static constexpr bool contiguous_layout = xexpression_type::contiguous_layout; - static constexpr bool contiguous_layout = false; - - template - xbroadcast(CTA&& e, S&& s); - - size_type size() const noexcept; - size_type dimension() const noexcept; - const inner_shape_type& shape() const noexcept; - layout_type layout() const noexcept; - - template - const_reference operator()(Args... args) const; - - template - const_reference at(Args... args) const; - - template - const_reference unchecked(Args... args) const; - - template - disable_integral_t operator[](const S& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - const_reference element(It first, It last) const; - - template - bool broadcast_shape(S& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const S& strides) const noexcept; - - template - const_stepper stepper_begin(const S& shape) const noexcept; - template - const_stepper stepper_end(const S& shape, layout_type l) const noexcept; - - template ::value>> - void assign_to(xexpression& e) const; - - private: - - CT m_e; - inner_shape_type m_shape; - }; - - /**************************** - * broadcast implementation * - ****************************/ - - /** - * @brief Returns an \ref xexpression broadcasting the given expression to - * a specified shape. - * - * @tparam e the \ref xexpression to broadcast - * @tparam s the specified shape to broadcast. - * - * The returned expression either hold a const reference to \p e or a copy - * depending on whether \p e is an lvalue or an rvalue. - */ - template - inline auto broadcast(E&& e, const S& s) - { - using broadcast_type = xbroadcast, S>; - using shape_type = typename broadcast_type::shape_type; - return broadcast_type(std::forward(e), xtl::forward_sequence(s)); - } - -#ifdef X_OLD_CLANG - template - inline auto broadcast(E&& e, std::initializer_list s) - { - using broadcast_type = xbroadcast, std::vector>; - using shape_type = typename broadcast_type::shape_type; - return broadcast_type(std::forward(e), xtl::forward_sequence(s)); - } -#else - template - inline auto broadcast(E&& e, const I (&s)[L]) - { - using broadcast_type = xbroadcast, std::array>; - using shape_type = typename broadcast_type::shape_type; - return broadcast_type(std::forward(e), xtl::forward_sequence(s)); - } -#endif - - /***************************** - * xbroadcast implementation * - *****************************/ - - /** - * @name Constructor - */ - //@{ - /** - * Constructs an xbroadcast expression broadcasting the specified - * \ref xexpression to the given shape - * - * @param e the expression to broadcast - * @param s the shape to apply - */ - template - template - inline xbroadcast::xbroadcast(CTA&& e, S&& s) - : m_e(std::forward(e)), m_shape(std::forward(s)) - { - xt::broadcast_shape(m_e.shape(), m_shape); - } - //@} - - /** - * @name Size and shape - */ - /** - * Returns the size of the expression. - */ - template - inline auto xbroadcast::size() const noexcept -> size_type - { - return compute_size(shape()); - } - - /** - * Returns the number of dimensions of the expression. - */ - template - inline auto xbroadcast::dimension() const noexcept -> size_type - { - return m_shape.size(); - } - - /** - * Returns the shape of the expression. - */ - template - inline auto xbroadcast::shape() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - /** - * Returns the layout_type of the expression. - */ - template - inline layout_type xbroadcast::layout() const noexcept - { - return m_e.layout(); - } - //@} - - /** - * @name Data - */ - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the expression. - */ - template - template - inline auto xbroadcast::operator()(Args... args) const -> const_reference - { - return m_e(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the expression. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xbroadcast::at(Args... args) const -> const_reference - { - check_access(shape(), static_cast(args)...); - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the expression. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the expression, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xbroadcast::unchecked(Args... args) const -> const_reference - { - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param index a sequence of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices in the sequence should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xbroadcast::operator[](const S& index) const - -> disable_integral_t - { - return element(index.cbegin(), index.cend()); - } - - template - template - inline auto xbroadcast::operator[](std::initializer_list index) const -> const_reference - { - return element(index.begin(), index.end()); - } - - template - inline auto xbroadcast::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the function. - */ - template - template - inline auto xbroadcast::element(It, It last) const -> const_reference - { - return m_e.element(last - dimension(), last); - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the function to the specified parameter. - * @param shape the result shape - * @param reuse_cache parameter for internal optimization - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xbroadcast::broadcast_shape(S& shape, bool) const - { - return xt::broadcast_shape(m_shape, shape); - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xbroadcast::is_trivial_broadcast(const S& strides) const noexcept - { - return dimension() == m_e.dimension() && - std::equal(m_shape.cbegin(), m_shape.cend(), m_e.shape().cbegin()) && - m_e.is_trivial_broadcast(strides); - } - //@} - - template - template - inline auto xbroadcast::stepper_begin(const S& shape) const noexcept -> const_stepper - { - // Could check if (broadcastable(shape, m_shape) - return m_e.stepper_begin(shape); - } - - template - template - inline auto xbroadcast::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - // Could check if (broadcastable(shape, m_shape) - return m_e.stepper_end(shape, l); - } - - template - template - inline void xbroadcast::assign_to(xexpression& e) const - { - auto& ed = e.derived_cast(); - ed.resize(m_shape); - std::fill(ed.begin(), ed.end(), m_e()); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xbuffer_adaptor.hpp b/vendor/xtensor/include/xtensor/xbuffer_adaptor.hpp deleted file mode 100644 index d8d331685..000000000 --- a/vendor/xtensor/include/xtensor/xbuffer_adaptor.hpp +++ /dev/null @@ -1,623 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_BUFFER_ADAPTOR_HPP -#define XTENSOR_BUFFER_ADAPTOR_HPP - -#include -#include -#include -#include -#include - -#include - -#include "xstorage.hpp" - -namespace xt -{ - /****************************** - * xbuffer_adator declaration * - ******************************/ - - struct no_ownership - { - }; - - struct acquire_ownership - { - }; - - template >>> - class xbuffer_adaptor; - - /********************************* - * xbuffer_adator implementation * - *********************************/ - - namespace detail - { - template - class xbuffer_storage - { - public: - - using self_type = xbuffer_storage; - using allocator_type = A; - using value_type = typename allocator_type::value_type; - using reference = std::conditional_t>>::value, - typename allocator_type::const_reference, - typename allocator_type::reference>; - using const_reference = typename allocator_type::const_reference; - using pointer = std::conditional_t>>::value, - typename allocator_type::const_pointer, - typename allocator_type::pointer>; - using const_pointer = typename allocator_type::const_pointer; - using size_type = typename allocator_type::size_type; - using difference_type = typename allocator_type::difference_type; - - xbuffer_storage(); - - template - xbuffer_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type()); - - size_type size() const noexcept; - void resize(size_type size); - - pointer data() noexcept; - const_pointer data() const noexcept; - - void swap(self_type& rhs) noexcept; - - private: - - pointer p_data; - size_type m_size; - }; - - template - class xbuffer_owner_storage - { - public: - - using self_type = xbuffer_owner_storage; - using allocator_type = A; - using value_type = typename allocator_type::value_type; - using reference = std::conditional_t>>::value, - typename allocator_type::const_reference, - typename allocator_type::reference>; - using const_reference = typename allocator_type::const_reference; - using pointer = std::conditional_t>>::value, - typename allocator_type::const_pointer, - typename allocator_type::pointer>; - using const_pointer = typename allocator_type::const_pointer; - using size_type = typename allocator_type::size_type; - using difference_type = typename allocator_type::difference_type; - - xbuffer_owner_storage() = default; - - template - xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type()); - - ~xbuffer_owner_storage(); - - xbuffer_owner_storage(const self_type&) = delete; - self_type& operator=(const self_type&); - - xbuffer_owner_storage(self_type&&); - self_type& operator=(self_type&&); - - size_type size() const noexcept; - void resize(size_type size); - - pointer data() noexcept; - const_pointer data() const noexcept; - - allocator_type get_allocator() const noexcept; - - void swap(self_type& rhs) noexcept; - - private: - - xtl::xclosure_wrapper m_data; - size_type m_size; - bool m_moved_from; - allocator_type m_allocator; - }; - - template - struct get_buffer_storage - { - using type = xbuffer_storage; - }; - - template - struct get_buffer_storage - { - using type = xbuffer_owner_storage; - }; - - template - using buffer_storage_t = typename get_buffer_storage::type; - } - - template - class xbuffer_adaptor : private detail::buffer_storage_t - { - public: - - using base_type = detail::buffer_storage_t; - using self_type = xbuffer_adaptor; - using allocator_type = typename base_type::allocator_type; - using value_type = typename base_type::value_type; - using reference = typename base_type::reference; - using const_reference = typename base_type::const_reference; - using pointer = typename base_type::pointer; - using const_pointer = typename base_type::const_pointer; - using temporary_type = uvector; - - using size_type = typename base_type::size_type; - using difference_type = typename base_type::difference_type; - - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - xbuffer_adaptor() = default; - - template - xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc = allocator_type()); - - ~xbuffer_adaptor() = default; - - xbuffer_adaptor(const self_type&) = default; - self_type& operator=(const self_type&) = default; - - xbuffer_adaptor(self_type&&) = default; - xbuffer_adaptor& operator=(self_type&&) = default; - - self_type& operator=(temporary_type&&); - - bool empty() const noexcept; - using base_type::size; - using base_type::resize; - - reference operator[](size_type i); - const_reference operator[](size_type i) const; - - reference front(); - const_reference front() const; - - reference back(); - const_reference back() const; - - iterator begin(); - iterator end(); - - const_iterator begin() const; - const_iterator end() const; - const_iterator cbegin() const; - const_iterator cend() const; - - reverse_iterator rbegin(); - reverse_iterator rend(); - - const_reverse_iterator rbegin() const; - const_reverse_iterator rend() const; - const_reverse_iterator crbegin() const; - const_reverse_iterator crend() const; - - using base_type::data; - using base_type::swap; - }; - - template - bool operator==(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - bool operator!=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - bool operator<(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - bool operator<=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - bool operator>(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - bool operator>=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs); - - template - void swap(xbuffer_adaptor& lhs, - xbuffer_adaptor& rhs) noexcept; - - /************************************ - * temporary_container metafunction * - ************************************/ - - template - struct temporary_container - { - using type = C; - }; - - template - struct temporary_container> - { - using type = typename xbuffer_adaptor::temporary_type; - }; - - template - using temporary_container_t = typename temporary_container::type; - - /********************************** - * xbuffer_storage implementation * - **********************************/ - - namespace detail - { - template - inline xbuffer_storage::xbuffer_storage() - : p_data(nullptr), m_size(0) - { - } - - template - template - inline xbuffer_storage::xbuffer_storage(P&& data, size_type size, const allocator_type&) - : p_data(std::forward

(data)), m_size(size) - { - } - - template - inline auto xbuffer_storage::size() const noexcept -> size_type - { - return m_size; - } - - template - inline void xbuffer_storage::resize(size_type size) - { - if (size != m_size) - { - throw std::runtime_error("xbuffer_storage not resizable"); - } - } - - template - inline auto xbuffer_storage::data() noexcept -> pointer - { - return p_data; - } - - template - inline auto xbuffer_storage::data() const noexcept -> const_pointer - { - return p_data; - } - - template - inline void xbuffer_storage::swap(self_type& rhs) noexcept - { - using std::swap; - swap(p_data, rhs.p_data); - swap(m_size, rhs.m_size); - } - } - - /**************************************** - * xbuffer_owner_storage implementation * - ****************************************/ - - namespace detail - { - template - template - inline xbuffer_owner_storage::xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc) - : m_data(std::forward

(data)), m_size(size), m_moved_from(false), m_allocator(alloc) - { - } - - template - inline xbuffer_owner_storage::~xbuffer_owner_storage() - { - if (!m_moved_from) - { - safe_destroy_deallocate(m_allocator, m_data.get(), m_size); - m_size = 0; - } - } - - template - inline auto xbuffer_owner_storage::operator=(const self_type& rhs) -> self_type& - { - using std::swap; - if (this != &rhs) - { - allocator_type al = std::allocator_traits::select_on_container_copy_construction(rhs.get_allocator()); - pointer tmp = safe_init_allocate(al, rhs.m_size); - if (xtrivially_default_constructible::value) - { - std::uninitialized_copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp); - } - else - { - std::copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp); - } - swap(m_data.get(), tmp); - m_size = rhs.m_size; - swap(m_allocator, al); - safe_destroy_deallocate(al, tmp, m_size); - } - return *this; - } - - template - inline xbuffer_owner_storage::xbuffer_owner_storage(self_type&& rhs) - : m_data(std::move(rhs.m_data)), m_size(std::move(rhs.m_size)), m_moved_from(std::move(rhs.m_moved_from)), m_allocator(std::move(rhs.m_allocator)) - { - rhs.m_moved_from = true; - rhs.m_size = 0; - } - - template - inline auto xbuffer_owner_storage::operator=(self_type&& rhs) -> self_type& - { - swap(rhs); - rhs.m_moved_from = true; - return *this; - } - - template - inline auto xbuffer_owner_storage::size() const noexcept -> size_type - { - return m_size; - } - - template - void xbuffer_owner_storage::resize(size_type size) - { - using std::swap; - if (size != m_size) - { - pointer tmp = safe_init_allocate(m_allocator, size); - swap(m_data.get(), tmp); - swap(m_size, size); - safe_destroy_deallocate(m_allocator, tmp, size); - } - } - - template - inline auto xbuffer_owner_storage::data() noexcept -> pointer - { - return m_data.get(); - } - - template - inline auto xbuffer_owner_storage::data() const noexcept -> const_pointer - { - return m_data.get(); - } - - template - inline auto xbuffer_owner_storage::get_allocator() const noexcept -> allocator_type - { - return allocator_type(m_allocator); - } - - template - inline void xbuffer_owner_storage::swap(self_type& rhs) noexcept - { - using std::swap; - swap(m_data, rhs.m_data); - swap(m_size, rhs.m_size); - swap(m_allocator, rhs.m_allocator); - } - } - - /********************************** - * xbuffer_adaptor implementation * - **********************************/ - - template - template - inline xbuffer_adaptor::xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc) - : base_type(std::forward

(data), size, alloc) - { - } - - template - inline auto xbuffer_adaptor::operator=(temporary_type&& tmp) -> self_type& - { - base_type::resize(tmp.size()); - std::copy(tmp.cbegin(), tmp.cend(), begin()); - return *this; - } - - template - bool xbuffer_adaptor::empty() const noexcept - { - return size() == 0; - } - - template - inline auto xbuffer_adaptor::operator[](size_type i) -> reference - { - return data()[i]; - } - - template - inline auto xbuffer_adaptor::operator[](size_type i) const -> const_reference - { - return data()[i]; - } - - template - inline auto xbuffer_adaptor::front() -> reference - { - return data()[0]; - } - - template - inline auto xbuffer_adaptor::front() const -> const_reference - { - return data()[0]; - } - - template - inline auto xbuffer_adaptor::back() -> reference - { - return data()[size() - 1]; - } - - template - inline auto xbuffer_adaptor::back() const -> const_reference - { - return data()[size() - 1]; - } - - template - inline auto xbuffer_adaptor::begin() -> iterator - { - return data(); - } - - template - inline auto xbuffer_adaptor::end() -> iterator - { - return data() + size(); - } - - template - inline auto xbuffer_adaptor::begin() const -> const_iterator - { - return data(); - } - - template - inline auto xbuffer_adaptor::end() const -> const_iterator - { - return data() + size(); - } - - template - inline auto xbuffer_adaptor::cbegin() const -> const_iterator - { - return begin(); - } - - template - inline auto xbuffer_adaptor::cend() const -> const_iterator - { - return end(); - } - - template - inline auto xbuffer_adaptor::rbegin() -> reverse_iterator - { - return reverse_iterator(end()); - } - - template - inline auto xbuffer_adaptor::rend() -> reverse_iterator - { - return reverse_iterator(begin()); - } - - template - inline auto xbuffer_adaptor::rbegin() const -> const_reverse_iterator - { - return const_reverse_iterator(end()); - } - - template - inline auto xbuffer_adaptor::rend() const -> const_reverse_iterator - { - return const_reverse_iterator(begin()); - } - - template - inline auto xbuffer_adaptor::crbegin() const -> const_reverse_iterator - { - return rbegin(); - } - - template - inline auto xbuffer_adaptor::crend() const -> const_reverse_iterator - { - return rend(); - } - - template - inline bool operator==(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - template - inline bool operator!=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return !(lhs == rhs); - } - - template - inline bool operator<(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end(), - std::less()); - } - - template - inline bool operator<=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end(), - std::less_equal()); - } - - template - inline bool operator>(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end(), - std::greater()); - } - - template - inline bool operator>=(const xbuffer_adaptor& lhs, - const xbuffer_adaptor& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end(), - std::greater_equal()); - } - - template - inline void swap(xbuffer_adaptor& lhs, - xbuffer_adaptor& rhs) noexcept - { - lhs.swap(rhs); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xbuilder.hpp b/vendor/xtensor/include/xtensor/xbuilder.hpp deleted file mode 100644 index c3e34b8ac..000000000 --- a/vendor/xtensor/include/xtensor/xbuilder.hpp +++ /dev/null @@ -1,918 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -/** - * @brief standard mathematical functions for xexpressions - */ - -#ifndef XTENSOR_BUILDER_HPP -#define XTENSOR_BUILDER_HPP - -#include -#include -#include -#include -#include -#include -#ifdef X_OLD_CLANG - #include -#endif - -#include -#include - -#include "xbroadcast.hpp" -#include "xfunction.hpp" -#include "xgenerator.hpp" -#include "xoperation.hpp" - -namespace xt -{ - - /******** - * ones * - ********/ - - /** - * Returns an \ref xexpression containing ones of the specified shape. - * @tparam shape the shape of the returned expression. - */ - template - inline auto ones(S shape) noexcept - { - return broadcast(T(1), std::forward(shape)); - } - -#ifdef X_OLD_CLANG - template - inline auto ones(std::initializer_list shape) noexcept - { - return broadcast(T(1), shape); - } -#else - template - inline auto ones(const I (&shape)[L]) noexcept - { - return broadcast(T(1), shape); - } -#endif - - /********* - * zeros * - *********/ - - /** - * Returns an \ref xexpression containing zeros of the specified shape. - * @tparam shape the shape of the returned expression. - */ - template - inline auto zeros(S shape) noexcept - { - return broadcast(T(0), std::forward(shape)); - } - -#ifdef X_OLD_CLANG - template - inline auto zeros(std::initializer_list shape) noexcept - { - return broadcast(T(0), shape); - } -#else - template - inline auto zeros(const I (&shape)[L]) noexcept - { - return broadcast(T(0), shape); - } -#endif - - /** - * Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of - * with value_type T and shape. Selects the best container match automatically - * from the supplied shape. - * - * - ``std::vector`` → ``xarray`` - * - ``std::array`` or ``initializer_list`` → ``xtensor`` - * - ``xshape`` → ``xtensor_fixed>`` - * - * @param shape shape of the new xcontainer - */ - template - inline xarray empty(const S& shape) - { - return xarray::from_shape(shape); - } - - template - inline xtensor empty(const std::array& shape) - { - using shape_type = typename xtensor::shape_type; - return xtensor(xtl::forward_sequence(shape)); - } - -#ifndef X_OLD_CLANG - template - inline xtensor empty(const I(&shape)[N]) - { - using shape_type = typename xtensor::shape_type; - return xtensor(xtl::forward_sequence(shape)); - } -#endif - - template - inline xtensor_fixed, L> empty(const fixed_shape& /*shape*/) - { - return xtensor_fixed, L>(); - } - - /** - * Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of - * the same shape, value type and layout as the input xexpression *e*. - * - * @param e the xexpression from which to extract shape, value type and layout. - */ - template - inline typename E::temporary_type empty_like(const xexpression& e) - { - typename E::temporary_type res(e.derived_cast().shape()); - return res; - } - - /** - * Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with *fill_value* and of - * the same shape, value type and layout as the input xexpression *e*. - * - * @param e the xexpression from which to extract shape, value type and layout. - * @param fill_value the value used to set each element of the returned xcontainer. - */ - template - inline typename E::temporary_type full_like(const xexpression& e, typename E::value_type fill_value) - { - typename E::temporary_type res(e.derived_cast().shape(), fill_value); - return res; - } - - /** - * Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with zeros and of - * the same shape, value type and layout as the input xexpression *e*. - * - * Note: contrary to zeros(shape), this function returns a non-lazy, allocated container! - * Use ``xt::zeros(e.shape());` for a lazy version. - * - * @param e the xexpression from which to extract shape, value type and layout. - */ - template - inline typename E::temporary_type zeros_like(const xexpression& e) - { - return full_like(e, typename E::value_type(0)); - } - - /** - * Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with ones and of - * the same shape, value type and layout as the input xexpression *e*. - * - * Note: contrary to ones(shape), this function returns a non-lazy, evaluated container! - * Use ``xt::ones(e.shape());`` for a lazy version. - * - * @param e the xexpression from which to extract shape, value type and layout. - */ - template - inline typename E::temporary_type ones_like(const xexpression& e) - { - return full_like(e, typename E::value_type(1)); - } - - namespace detail - { - template - class arange_impl - { - public: - - using value_type = T; - - arange_impl(T start, T stop, T step) - : m_start(start), m_stop(stop), m_step(step) - { - } - - template - inline T operator()(Args... args) const - { - return access_impl(args...); - } - - template - inline T element(It first, It) const - { - return m_start + m_step * T(*first); - } - - template - inline void assign_to(xexpression& e) const noexcept - { - auto& de = e.derived_cast(); - value_type value = m_start; - - for (auto& el : de.storage()) - { - el = value; - value += m_step; - } - } - - private: - - value_type m_start; - value_type m_stop; - value_type m_step; - - template - inline T access_impl(T1 t, Args...) const - { - return m_start + m_step * T(t); - } - - inline T access_impl() const - { - return m_start; - } - }; - - template - class fn_impl - { - public: - - using value_type = typename F::value_type; - using size_type = std::size_t; - - fn_impl(F&& f) - : m_ft(f) - { - } - - inline value_type operator()() const - { - size_type idx[1] = {0ul}; - return access_impl(std::begin(idx), std::end(idx)); - } - - template - inline value_type operator()(Args... args) const - { - size_type idx[sizeof...(Args)] = {static_cast(args)...}; - return access_impl(std::begin(idx), std::end(idx)); - } - - template - inline value_type element(It first, It last) const - { - return access_impl(first, last); - } - - private: - - F m_ft; - template - inline value_type access_impl(const It& begin, const It& end) const - { - return m_ft(begin, end); - } - }; - - template - class eye_fn - { - public: - - using value_type = T; - - eye_fn(int k) - : m_k(k) - { - } - - template - inline T operator()(const It& /*begin*/, const It& end) const - { - using lvalue_type = typename std::iterator_traits::value_type; - return *(end - 1) == *(end - 2) + static_cast(static_cast(m_k)) ? T(1) : T(0); - } - - private: - - int m_k; - }; - } - - /** - * Generates an array with ones on the diagonal. - * @param shape shape of the resulting expression - * @param k index of the diagonal. 0 (default) refers to the main diagonal, - * a positive value refers to an upper diagonal, and a negative - * value to a lower diagonal. - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto eye(const std::vector& shape, int k = 0) - { - return detail::make_xgenerator(detail::fn_impl>(detail::eye_fn(k)), shape); - } - - /** - * Generates a (n x n) array with ones on the diagonal. - * @param n length of the diagonal. - * @param k index of the diagonal. 0 (default) refers to the main diagonal, - * a positive value refers to an upper diagonal, and a negative - * value to a lower diagonal. - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto eye(std::size_t n, int k = 0) - { - return eye({n, n}, k); - } - - /** - * Generates numbers evenly spaced within given half-open interval [start, stop). - * @param start start of the interval - * @param stop stop of the interval - * @param step stepsize - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto arange(T start, T stop, T step = 1) noexcept - { - std::size_t shape = static_cast(std::ceil((stop - start) / step)); - return detail::make_xgenerator(detail::arange_impl(start, stop, step), {shape}); - } - - /** - * Generate numbers evenly spaced within given half-open interval [0, stop) - * with a step size of 1. - * @param stop stop of the interval - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto arange(T stop) noexcept - { - return arange(T(0), stop, T(1)); - } - - /** - * Generates @a num_samples evenly spaced numbers over given interval - * @param start start of interval - * @param stop stop of interval - * @param num_samples number of samples (defaults to 50) - * @param endpoint if true, include endpoint (defaults to true) - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto linspace(T start, T stop, std::size_t num_samples = 50, bool endpoint = true) noexcept - { - using fp_type = std::common_type_t; - fp_type step = fp_type(stop - start) / fp_type(num_samples - (endpoint ? 1 : 0)); - return cast(detail::make_xgenerator(detail::arange_impl(fp_type(start), fp_type(stop), step), {num_samples})); - } - - /** - * Generates @a num_samples numbers evenly spaced on a log scale over given interval - * @param start start of interval (pow(base, start) is the first value). - * @param stop stop of interval (pow(base, stop) is the final value, except if endpoint = false) - * @param num_samples number of samples (defaults to 50) - * @param base the base of the log space. - * @param endpoint if true, include endpoint (defaults to true) - * @tparam T value_type of xexpression - * @return xgenerator that generates the values on access - */ - template - inline auto logspace(T start, T stop, std::size_t num_samples, T base = 10, bool endpoint = true) noexcept - { - return cast(pow(std::move(base), linspace(start, stop, num_samples, endpoint))); - } - - namespace detail - { - template - class concatenate_impl - { - public: - - using size_type = std::size_t; - using value_type = promote_type_t::value_type...>; - - inline concatenate_impl(std::tuple&& t, size_type axis) - : m_t(t), m_axis(axis) - { - } - - template - inline value_type operator()(Args... args) const - { - // TODO: avoid memory allocation - return access_impl(xindex({static_cast(args)...})); - } - - template - inline value_type element(It first, It last) const - { - // TODO: avoid memory allocation - return access_impl(xindex(first, last)); - } - - private: - - inline value_type access_impl(xindex idx) const - { - auto match = [this, &idx](auto& arr) { - if (idx[this->m_axis] >= arr.shape()[this->m_axis]) - { - idx[this->m_axis] -= arr.shape()[this->m_axis]; - return false; - } - return true; - }; - - auto get = [&idx](auto& arr) { - return arr[idx]; - }; - - size_type i = 0; - for (; i < sizeof...(CT); ++i) - { - if (apply(i, match, m_t)) - { - break; - } - } - return apply(i, get, m_t); - } - - std::tuple m_t; - size_type m_axis; - }; - - template - class stack_impl - { - public: - - using size_type = std::size_t; - using value_type = promote_type_t::value_type...>; - - inline stack_impl(std::tuple&& t, size_type axis) - : m_t(t), m_axis(axis) - { - } - - template - inline value_type operator()(Args... args) const - { - // TODO: avoid memory allocation - return access_impl(xindex({static_cast(args)...})); - } - - template - inline value_type element(It first, It last) const - { - // TODO: avoid memory allocation - return access_impl(xindex(first, last)); - } - - private: - - inline value_type access_impl(xindex idx) const - { - auto get_item = [&idx](auto& arr) { - return arr[idx]; - }; - size_type i = idx[m_axis]; - idx.erase(idx.begin() + std::ptrdiff_t(m_axis)); - return apply(i, get_item, m_t); - } - - const std::tuple m_t; - const size_type m_axis; - }; - - template - class repeat_impl - { - public: - - using xexpression_type = std::decay_t; - using size_type = typename xexpression_type::size_type; - using value_type = typename xexpression_type::value_type; - - template - repeat_impl(CTA&& source, size_type axis) - : m_source(std::forward(source)), m_axis(axis) - { - } - - template - value_type operator()(Args... args) const - { - std::array args_arr = {static_cast(args)...}; - return m_source(args_arr[m_axis]); - } - - template - inline value_type element(It first, It) const - { - return m_source(*(first + static_cast(m_axis))); - } - - private: - - CT m_source; - size_type m_axis; - }; - } - - /** - * @brief Creates tuples from arguments for \ref concatenate and \ref stack. - * Very similar to std::make_tuple. - */ - template - inline auto xtuple(Types&&... args) - { - return std::tuple...>(std::forward(args)...); - } - - /** - * @brief Concatenates xexpressions along \em axis. - * - * @param t \ref xtuple of xexpressions to concatenate - * @param axis axis along which elements are concatenated - * @returns xgenerator evaluating to concatenated elements - * - * \code{.cpp} - * xt::xarray a = {{1, 2, 3}}; - * xt::xarray b = {{2, 3, 4}}; - * xt::xarray c = xt::concatenate(xt::xtuple(a, b)); // => {{1, 2, 3}, - * {2, 3, 4}} - * xt::xarray d = xt::concatenate(xt::xtuple(a, b), 1); // => {{1, 2, 3, 2, 3, 4}} - * \endcode - */ - template - inline auto concatenate(std::tuple&& t, std::size_t axis = 0) - { - using shape_type = promote_shape_t::shape_type...>; - shape_type new_shape = xtl::forward_sequence(std::get<0>(t).shape()); - auto shape_at_axis = [&axis](std::size_t prev, auto& arr) -> std::size_t { - return prev + arr.shape()[axis]; - }; - new_shape[axis] += accumulate(shape_at_axis, std::size_t(0), t) - new_shape[axis]; - return detail::make_xgenerator(detail::concatenate_impl(std::forward>(t), axis), new_shape); - } - - namespace detail - { - template - inline std::array add_axis(std::array arr, std::size_t axis, std::size_t value) - { - std::array temp; - std::copy(arr.begin(), arr.begin() + axis, temp.begin()); - temp[axis] = value; - std::copy(arr.begin() + axis, arr.end(), temp.begin() + axis + 1); - return temp; - } - - template - inline T add_axis(T arr, std::size_t axis, std::size_t value) - { - T temp(arr); - temp.insert(temp.begin() + std::ptrdiff_t(axis), value); - return temp; - } - } - - /** - * @brief Stack xexpressions along \em axis. - * Stacking always creates a new dimension along which elements are stacked. - * - * @param t \ref xtuple of xexpressions to concatenate - * @param axis axis along which elements are stacked - * @returns xgenerator evaluating to stacked elements - * - * \code{.cpp} - * xt::xarray a = {1, 2, 3}; - * xt::xarray b = {5, 6, 7}; - * xt::xarray s = xt::stack(xt::xtuple(a, b)); // => {{1, 2, 3}, - * {5, 6, 7}} - * xt::xarray t = xt::stack(xt::xtuple(a, b), 1); // => {{1, 5}, - * {2, 6}, - * {3, 7}} - * \endcode - */ - template - inline auto stack(std::tuple&& t, std::size_t axis = 0) - { - using shape_type = promote_shape_t::shape_type...>; - auto new_shape = detail::add_axis(xtl::forward_sequence(std::get<0>(t).shape()), axis, sizeof...(CT)); - return detail::make_xgenerator(detail::stack_impl(std::forward>(t), axis), new_shape); - } - - namespace detail - { - - template - inline auto meshgrid_impl(std::index_sequence, E&&... e) noexcept - { -#if defined X_OLD_CLANG || defined _MSC_VER - const std::array shape = {e.shape()[0]...}; - return std::make_tuple( - detail::make_xgenerator( - detail::repeat_impl>(std::forward(e), I), - shape - )... - ); -#else - return std::make_tuple( - detail::make_xgenerator( - detail::repeat_impl>(std::forward(e), I), - {e.shape()[0]...} - )... - ); -#endif - } - } - - /** - * @brief Return coordinate tensors from coordinate vectors. - * Make N-D coordinate tensor expressions for vectorized evaluations of N-D scalar/vector - * fields over N-D grids, given one-dimensional coordinate arrays x1, x2,..., xn. - * - * @param e xexpressions to concatenate - * @returns tuple of xgenerator expressions. - */ - template - inline auto meshgrid(E&&... e) noexcept - { - return detail::meshgrid_impl(std::make_index_sequence(), std::forward(e)...); - } - - namespace detail - { - template - class diagonal_fn - { - public: - - using xexpression_type = std::decay_t; - using value_type = typename xexpression_type::value_type; - - template - diagonal_fn(CTA&& source, int offset, std::size_t axis_1, std::size_t axis_2) - : m_source(std::forward(source)), m_offset(offset), m_axis_1(axis_1), m_axis_2(axis_2) - { - } - - template - inline value_type operator()(It begin, It) const - { - xindex idx(m_source.shape().size()); - - for (std::size_t i = 0; i < idx.size(); i++) - { - if (i != m_axis_1 && i != m_axis_2) - { - idx[i] = *begin++; - } - } - using it_vtype = typename std::iterator_traits::value_type; - it_vtype uoffset = static_cast(m_offset); - if (m_offset >= 0) - { - idx[m_axis_1] = *(begin); - idx[m_axis_2] = *(begin) + uoffset; - } - else - { - idx[m_axis_1] = *(begin) - uoffset; - idx[m_axis_2] = *(begin); - } - return m_source[idx]; - } - - private: - - CT m_source; - const int m_offset; - const std::size_t m_axis_1; - const std::size_t m_axis_2; - }; - - template - class diag_fn - { - public: - - using xexpression_type = std::decay_t; - using value_type = typename xexpression_type::value_type; - - template - diag_fn(CTA&& source, int k) - : m_source(std::forward(source)), m_k(k) - { - } - - template - inline value_type operator()(It begin, It) const - { - using it_vtype = typename std::iterator_traits::value_type; - it_vtype umk = static_cast(m_k); - if (m_k > 0) - { - return *begin + umk == *(begin + 1) ? m_source(*begin) : value_type(0); - } - else - { - return *begin + umk == *(begin + 1) ? m_source(*begin + umk) : value_type(0); - } - } - - private: - - CT m_source; - const int m_k; - }; - - template - class trilu_fn - { - public: - - using xexpression_type = std::decay_t; - using value_type = typename xexpression_type::value_type; - using signed_idx_type = long int; - - template - trilu_fn(CTA&& source, int k, Comp comp) - : m_source(std::forward(source)), m_k(k), m_comp(comp) - { - } - - template - inline value_type operator()(It begin, It end) const - { - // have to cast to signed int otherwise -1 can lead to overflow - return m_comp(signed_idx_type(*begin) + m_k, signed_idx_type(*(begin + 1))) ? m_source.element(begin, end) : value_type(0); - } - - private: - - CT m_source; - const signed_idx_type m_k; - const Comp m_comp; - }; - } - - namespace detail - { - // meta-function returning the shape type for a diagonal - template - struct diagonal_shape_type - { - using type = ST; - }; - - template - struct diagonal_shape_type> - { - using type = std::array; - }; - } - - /** - * @brief Returns the elements on the diagonal of arr - * If arr has more than two dimensions, then the axes specified by - * axis_1 and axis_2 are used to determine the 2-D sub-array whose - * diagonal is returned. The shape of the resulting array can be - * determined by removing axis1 and axis2 and appending an index - * to the right equal to the size of the resulting diagonals. - * - * @param arr the input array - * @param offset offset of the diagonal from the main diagonal. Can - * be positive or negative. - * @param axis_1 Axis to be used as the first axis of the 2-D sub-arrays - * from which the diagonals should be taken. - * @param axis_2 Axis to be used as the second axis of the 2-D sub-arrays - * from which the diagonals should be taken. - * @returns xexpression with values of the diagonal - * - * \code{.cpp} - * xt::xarray a = {{1, 2, 3}, - * {4, 5, 6} - * {7, 8, 9}}; - * auto b = xt::diagonal(a); // => {1, 5, 9} - * \endcode - */ - template - inline auto diagonal(E&& arr, int offset = 0, std::size_t axis_1 = 0, std::size_t axis_2 = 1) - { - using CT = xclosure_t; - using shape_type = typename detail::diagonal_shape_type::shape_type>::type; - - auto shape = arr.shape(); - auto dimension = arr.dimension(); - - // The following shape calculation code is an almost verbatim adaptation of numpy: - // https://github.com/numpy/numpy/blob/2aabeafb97bea4e1bfa29d946fbf31e1104e7ae0/numpy/core/src/multiarray/item_selection.c#L1799 - auto ret_shape = xtl::make_sequence(dimension - 1, 0); - int dim_1 = static_cast(shape[axis_1]); - int dim_2 = static_cast(shape[axis_2]); - - offset >= 0 ? dim_2 -= offset : dim_1 += offset; - - auto diag_size = std::size_t(dim_2 < dim_1 ? dim_2 : dim_1); - - std::size_t i = 0; - for (std::size_t idim = 0; idim < dimension; ++idim) - { - if (idim != axis_1 && idim != axis_2) - { - ret_shape[i++] = shape[idim]; - } - } - - ret_shape.back() = diag_size; - - return detail::make_xgenerator(detail::fn_impl>(detail::diagonal_fn(std::forward(arr), offset, axis_1, axis_2)), - ret_shape); - } - - /** - * @brief xexpression with values of arr on the diagonal, zeroes otherwise - * - * @param arr the 1D input array of length n - * @param k the offset of the considered diagonal - * @returns xexpression function with shape n x n and arr on the diagonal - * - * \code{.cpp} - * xt::xarray a = {1, 5, 9}; - * auto b = xt::diag(a); // => {{1, 0, 0}, - * // {0, 5, 0}, - * // {0, 0, 9}} - * \endcode - */ - template - inline auto diag(E&& arr, int k = 0) - { - using CT = xclosure_t; - std::size_t sk = std::size_t(std::abs(k)); - std::size_t s = arr.shape()[0] + sk; - return detail::make_xgenerator(detail::fn_impl>(detail::diag_fn(std::forward(arr), k)), - {s, s}); - } - - /** - * @brief Extract lower triangular matrix from xexpression. The parameter k selects the - * offset of the diagonal. - * - * @param arr the input array - * @param k the diagonal above which to zero elements. 0 (default) selects the main diagonal, - * k < 0 is below the main diagonal, k > 0 above. - * @returns xexpression containing lower triangle from arr, 0 otherwise - */ - template - inline auto tril(E&& arr, int k = 0) - { - using CT = xclosure_t; - auto shape = arr.shape(); - return detail::make_xgenerator(detail::fn_impl>>( - detail::trilu_fn>(std::forward(arr), k, std::greater_equal())), - shape); - } - - /** - * @brief Extract upper triangular matrix from xexpression. The parameter k selects the - * offset of the diagonal. - * - * @param arr the input array - * @param k the diagonal below which to zero elements. 0 (default) selects the main diagonal, - * k < 0 is below the main diagonal, k > 0 above. - * @returns xexpression containing lower triangle from arr, 0 otherwise - */ - template - inline auto triu(E&& arr, int k = 0) - { - using CT = xclosure_t; - auto shape = arr.shape(); - return detail::make_xgenerator(detail::fn_impl>>( - detail::trilu_fn>(std::forward(arr), k, std::less_equal())), - shape); - } -} -#endif diff --git a/vendor/xtensor/include/xtensor/xcomplex.hpp b/vendor/xtensor/include/xtensor/xcomplex.hpp deleted file mode 100644 index e47842aa1..000000000 --- a/vendor/xtensor/include/xtensor/xcomplex.hpp +++ /dev/null @@ -1,251 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_COMPLEX_HPP -#define XTENSOR_COMPLEX_HPP - -#include -#include - -#include - -#include "xtensor/xbuilder.hpp" -#include "xtensor/xexpression.hpp" -#include "xtensor/xoffset_view.hpp" - -namespace xt -{ - - /****************************** - * real and imag declarations * - ******************************/ - - template - decltype(auto) real(E&& e) noexcept; - - template - decltype(auto) imag(E&& e) noexcept; - - /******************************** - * real and imag implementation * - ********************************/ - - namespace detail - { - template - struct complex_helper - { - template - static inline auto real(E&& e) noexcept - { - using real_type = typename std::decay_t::value_type::value_type; - return xoffset_view, real_type, 0>(std::forward(e)); - } - - template - static inline auto imag(E&& e) noexcept - { - using real_type = typename std::decay_t::value_type::value_type; - return xoffset_view, real_type, sizeof(real_type)>(std::forward(e)); - } - }; - - template <> - struct complex_helper - { - template - static inline decltype(auto) real(E&& e) noexcept - { - return e; - } - - template - static inline auto imag(E&& e) noexcept - { - return zeros::value_type>(e.shape()); - } - }; - - template - struct complex_expression_helper - { - template - static inline auto real(E&& e) noexcept - { - return detail::complex_helper::value_type>::value>::real(e); - } - - template - static inline auto imag(E&& e) noexcept - { - return detail::complex_helper::value_type>::value>::imag(e); - } - }; - - template <> - struct complex_expression_helper - { - template - static inline decltype(auto) real(E&& e) noexcept - { - return xtl::forward_real(std::forward(e)); - } - - template - static inline decltype(auto) imag(E&& e) noexcept - { - return xtl::forward_imag(std::forward(e)); - } - }; - } - - /** - * @brief Returns an \ref xexpression representing the real part of the given expression. - * - * @tparam e the \ref xexpression - * - * The returned expression either hold a const reference to \p e or a copy - * depending on whether \p e is an lvalue or an rvalue. - */ - template - inline decltype(auto) real(E&& e) noexcept - { - return detail::complex_expression_helper>::value>::real(std::forward(e)); - } - - /** - * @brief Returns an \ref xexpression representing the imaginary part of the given expression. - * - * @tparam e the \ref xexpression - * - * The returned expression either hold a const reference to \p e or a copy - * depending on whether \p e is an lvalue or an rvalue. - */ - template - inline decltype(auto) imag(E&& e) noexcept - { - return detail::complex_expression_helper>::value>::imag(std::forward(e)); - } - -#define UNARY_COMPLEX_FUNCTOR(NAME) \ - template \ - struct NAME##_fun \ - { \ - using argument_type = T; \ - using result_type = decltype(std::NAME(std::declval())); \ - constexpr result_type operator()(const T& t) const \ - { \ - using std::NAME; \ - return NAME(t); \ - } \ - } - - namespace math - { - UNARY_COMPLEX_FUNCTOR(norm); - UNARY_COMPLEX_FUNCTOR(arg); - - namespace detail - { - // libc++ (OSX) conj is unfortunately broken and returns - // std::complex instead of T. - template - constexpr T conj(const T& c) - { - return c; - } - - template - constexpr std::complex conj(const std::complex& c) - { - return std::complex(c.real(), -c.imag()); - } - } - - template - struct conj_fun - { - using argument_type = T; - using result_type = decltype(detail::conj(std::declval())); - using simd_value_type = xsimd::simd_type; - constexpr result_type operator()(const T& t) const - { - return detail::conj(t); - } - constexpr simd_value_type simd_apply(const simd_value_type& t) const - { - return detail::conj(t); - } - }; - } - -#undef UNARY_COMPLEX_FUNCTOR - - /** - * @brief Returns an \ref xfunction evaluating to the complex conjugate of the given expression. - * - * @param e the \ref xexpression - */ - template - inline auto conj(E&& e) noexcept - { - using value_type = typename std::decay_t::value_type; - using functor = math::conj_fun; - using result_type = typename functor::result_type; - using type = xfunction>; - return type(functor(), std::forward(e)); - } - - /** - * @brief Calculates the phase angle (in radians) elementwise for the complex numbers in e. - * @param e the \ref xexpression - */ - template - inline auto arg(E&& e) noexcept - { - using value_type = typename std::decay_t::value_type; - using functor = math::arg_fun; - using result_type = typename functor::result_type; - using type = xfunction>; - return type(functor(), std::forward(e)); - } - - /** - * @brief Calculates the phase angle elementwise for the complex numbers in e. - * Note that this function might be slightly less perfomant than \ref arg. - * @param e the \ref xexpression - * @param deg calculate angle in degrees instead of radians - */ - template - inline auto angle(E&& e, bool deg = false) noexcept - { - using value_type = xtl::complex_value_type_t::value_type>; - value_type multiplier = 1.0; - if (deg) - { - multiplier = value_type(180) / numeric_constants::PI; - } - return arg(std::forward(e)) * std::move(multiplier); - } - - /** - * Calculates the squared magnitude elementwise for the complex numbers in e. - * Equivalent to pow(real(e), 2) + pow(imag(e), 2). - * @param e the \ref xexpression - */ - template - inline auto norm(E&& e) noexcept - { - using value_type = typename std::decay_t::value_type; - using functor = math::norm_fun; - using result_type = typename functor::result_type; - using type = xfunction>; - return type(functor(), std::forward(e)); - } -} -#endif diff --git a/vendor/xtensor/include/xtensor/xconcepts.hpp b/vendor/xtensor/include/xtensor/xconcepts.hpp deleted file mode 100644 index 1845c6b03..000000000 --- a/vendor/xtensor/include/xtensor/xconcepts.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2017, Ullrich Koethe * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_CONCEPTS_HPP -#define XTENSOR_CONCEPTS_HPP - -#include - -/***************************************************** - * concept checking and type inference functionality * - *****************************************************/ - -namespace xt -{ - - /****************************************** - * XTENSOR_REQUIRE concept checking macro * - ******************************************/ - - struct concept_check_successful - { - }; - - template - using concept_check = typename std::enable_if::type; - - /** @brief Concept checking macro (more readable than sfinae). - - The macro is used as the last argument in a template declaration. - It must be followed by a static boolean expression in angle brackets. - The template will only be included in overload resolution when - this expression evaluates to 'true'. - - Example: - \code - template ::value>> - T foo(T t) - {...} - \endcode - */ - #define XTENSOR_REQUIRE typename = concept_check - - /******************** - * iterator_concept * - ********************/ - - /** @brief Traits class to check if a type is an iterator. - - This is useful in concept checking to make sure that a given template - is only instantiated when the argument is an iterator. - Currently, we apply the simple rule that class @tparam T - is either a pointer or a C-array or has an embedded typedef - 'iterator_category'. More sophisticated checks can easily - be added when needed. - - If @tparam T is indeed an iterator, the class' value member - is true: - \code - template ::value>> - T foo(T t) - {...} - \endcode - */ - template - struct iterator_concept - { - using V = std::decay_t; - - static char test(...); - - template - static int test(U*, typename U::iterator_category* = 0); - - static const bool value = - std::is_array::value || - std::is_pointer::value || - std::is_same())), int>::value; - }; - - /** @brief Check if a conversion may loose information. - - @tparam FROM source type - @tparam TO target type - - When data is converted from a big type (e.g. int64_t or double) - to a smaller type (e.g. int32_t), most compilers issue a 'possible loss of data' - warning. This metafunction allows you to detect these situations and take appropriate - actions. - - If loss of data may occur, member is_narrowing_conversion::value is true. Currently, - the check is only implemented for built-in types, i.e. types where std::is_arithmetic - is true. - */ - template - struct is_narrowing_conversion - { - using argument_type = std::decay_t; - using result_type = std::decay_t; - - static const bool value = std::is_arithmetic::value && - (sizeof(result_type) < sizeof(argument_type) || - (std::is_integral::value && std::is_floating_point::value)); - }; -} // namespace xt - -#endif // XCONCEPTS_HPP diff --git a/vendor/xtensor/include/xtensor/xcontainer.hpp b/vendor/xtensor/include/xtensor/xcontainer.hpp deleted file mode 100644 index 80df1907f..000000000 --- a/vendor/xtensor/include/xtensor/xcontainer.hpp +++ /dev/null @@ -1,1418 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_CONTAINER_HPP -#define XTENSOR_CONTAINER_HPP - -#include -#include -#include -#include -#include - -#include -#include - -#include "xiterable.hpp" -#include "xiterator.hpp" -#include "xmath.hpp" -#include "xoperation.hpp" -#include "xstrides.hpp" -#include "xtensor_forward.hpp" - -namespace xt -{ - template - struct xcontainer_iterable_types - { - using inner_shape_type = typename xcontainer_inner_types::inner_shape_type; - using storage_type = typename xcontainer_inner_types::storage_type; - using stepper = xstepper; - using const_stepper = xstepper; - }; - -#define DL XTENSOR_DEFAULT_LAYOUT - - namespace detail - { - template - struct allocator_type_impl - { - using type = typename T::allocator_type; - }; - - template - struct allocator_type_impl> - { - using type = std::allocator; // fake allocator for testing - }; - } - - template - using allocator_type_t = typename detail::allocator_type_impl::type; - - - /** - * @class xcontainer - * @brief Base class for dense multidimensional containers. - * - * The xcontainer class defines the interface for dense multidimensional - * container classes. It does not embed any data container, this responsibility - * is delegated to the inheriting classes. - * - * @tparam D The derived type, i.e. the inheriting class for which xcontainer - * provides the interface. - */ - template - class xcontainer : private xiterable - { - public: - - using derived_type = D; - - using inner_types = xcontainer_inner_types; - using storage_type = typename inner_types::storage_type; - using allocator_type = allocator_type_t>; - using value_type = typename storage_type::value_type; - using reference = std::conditional_t::value, - typename storage_type::const_reference, - typename storage_type::reference>; - using const_reference = typename storage_type::const_reference; - using pointer = typename storage_type::pointer; - using const_pointer = typename storage_type::const_pointer; - using size_type = typename storage_type::size_type; - using difference_type = typename storage_type::difference_type; - using simd_value_type = xsimd::simd_type; - - using shape_type = typename inner_types::shape_type; - using strides_type = typename inner_types::strides_type; - using backstrides_type = typename inner_types::backstrides_type; - - using inner_shape_type = typename inner_types::inner_shape_type; - using inner_strides_type = typename inner_types::inner_strides_type; - using inner_backstrides_type = typename inner_types::inner_backstrides_type; - - using iterable_base = xiterable; - using stepper = typename iterable_base::stepper; - using const_stepper = typename iterable_base::const_stepper; - - static constexpr layout_type static_layout = inner_types::layout; - static constexpr bool contiguous_layout = static_layout != layout_type::dynamic; - using data_alignment = xsimd::container_alignment_t; - using simd_type = xsimd::simd_type; - - static_assert(static_layout != layout_type::any, "Container layout can never be layout_type::any!"); - - size_type size() const noexcept; - - constexpr size_type dimension() const noexcept; - - constexpr const inner_shape_type& shape() const noexcept; - constexpr const inner_strides_type& strides() const noexcept; - constexpr const inner_backstrides_type& backstrides() const noexcept; - - template - void fill(const T& value); - - template - reference operator()(Args... args); - - template - const_reference operator()(Args... args) const; - - template - reference at(Args... args); - - template - const_reference at(Args... args) const; - - template - reference unchecked(Args... args); - - template - const_reference unchecked(Args... args) const; - - template - disable_integral_t operator[](const S& index); - template - reference operator[](std::initializer_list index); - reference operator[](size_type i); - - template - disable_integral_t operator[](const S& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - reference element(It first, It last); - template - const_reference element(It first, It last) const; - - storage_type& storage() noexcept; - const storage_type& storage() const noexcept; - - value_type* data() noexcept; - const value_type* data() const noexcept; - const size_type data_offset() const noexcept; - - template - bool broadcast_shape(S& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const S& strides) const noexcept; - - template - stepper stepper_begin(const S& shape) noexcept; - template - stepper stepper_end(const S& shape, layout_type l) noexcept; - - template - const_stepper stepper_begin(const S& shape) const noexcept; - template - const_stepper stepper_end(const S& shape, layout_type l) const noexcept; - - reference data_element(size_type i); - const_reference data_element(size_type i) const; - - template - using simd_return_type = xsimd::simd_return_type; - - template - void store_simd(size_type i, const simd& e); - template - simd_return_type load_simd(size_type i) const; - -#if defined(_MSC_VER) && _MSC_VER >= 1910 - // Workaround for compiler bug in Visual Studio 2017 with respect to alias templates with non-type parameters. - template - using layout_iterator = xiterator; - template - using const_layout_iterator = xiterator; - template - using reverse_layout_iterator = std::reverse_iterator>; - template - using const_reverse_layout_iterator = std::reverse_iterator>; -#else - template - using layout_iterator = typename iterable_base::template layout_iterator; - template - using const_layout_iterator = typename iterable_base::template const_layout_iterator; - template - using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator; - template - using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator; -#endif - - template - using broadcast_iterator = typename iterable_base::template broadcast_iterator; - template - using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator; - template - using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator; - template - using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator; - - using storage_iterator = typename storage_type::iterator; - using const_storage_iterator = typename storage_type::const_iterator; - using reverse_storage_iterator = typename storage_type::reverse_iterator; - using const_reverse_storage_iterator = typename storage_type::const_reverse_iterator; - - template - using select_iterator_impl = std::conditional_t; - - template - using select_iterator = select_iterator_impl>; - template - using select_const_iterator = select_iterator_impl>; - template - using select_reverse_iterator = select_iterator_impl>; - template - using select_const_reverse_iterator = select_iterator_impl>; - - using iterator = select_iterator

; - using const_iterator = select_const_iterator
; - using reverse_iterator = select_reverse_iterator
; - using const_reverse_iterator = select_const_reverse_iterator
; - - template - select_iterator begin() noexcept; - template - select_iterator end() noexcept; - - template - select_const_iterator begin() const noexcept; - template - select_const_iterator end() const noexcept; - template - select_const_iterator cbegin() const noexcept; - template - select_const_iterator cend() const noexcept; - - template - select_reverse_iterator rbegin() noexcept; - template - select_reverse_iterator rend() noexcept; - - template - select_const_reverse_iterator rbegin() const noexcept; - template - select_const_reverse_iterator rend() const noexcept; - template - select_const_reverse_iterator crbegin() const noexcept; - template - select_const_reverse_iterator crend() const noexcept; - - template - broadcast_iterator begin(const S& shape) noexcept; - template - broadcast_iterator end(const S& shape) noexcept; - - template - const_broadcast_iterator begin(const S& shape) const noexcept; - template - const_broadcast_iterator end(const S& shape) const noexcept; - template - const_broadcast_iterator cbegin(const S& shape) const noexcept; - template - const_broadcast_iterator cend(const S& shape) const noexcept; - - - template - reverse_broadcast_iterator rbegin(const S& shape) noexcept; - template - reverse_broadcast_iterator rend(const S& shape) noexcept; - - template - const_reverse_broadcast_iterator rbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator rend(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crend(const S& shape) const noexcept; - - template - storage_iterator storage_begin() noexcept; - template - storage_iterator storage_end() noexcept; - - template - const_storage_iterator storage_begin() const noexcept; - template - const_storage_iterator storage_end() const noexcept; - template - const_storage_iterator storage_cbegin() const noexcept; - template - const_storage_iterator storage_cend() const noexcept; - - template - reverse_storage_iterator storage_rbegin() noexcept; - template - reverse_storage_iterator storage_rend() noexcept; - - template - const_reverse_storage_iterator storage_rbegin() const noexcept; - template - const_reverse_storage_iterator storage_rend() const noexcept; - template - const_reverse_storage_iterator storage_crbegin() const noexcept; - template - const_reverse_storage_iterator storage_crend() const noexcept; - - using container_iterator = storage_iterator; - using const_container_iterator = const_storage_iterator; - - protected: - - xcontainer() = default; - ~xcontainer() = default; - - xcontainer(const xcontainer&) = default; - xcontainer& operator=(const xcontainer&) = default; - - xcontainer(xcontainer&&) = default; - xcontainer& operator=(xcontainer&&) = default; - - container_iterator data_xbegin() noexcept; - const_container_iterator data_xbegin() const noexcept; - container_iterator data_xend(layout_type l) noexcept; - const_container_iterator data_xend(layout_type l) const noexcept; - - protected: - - derived_type& derived_cast() & noexcept; - const derived_type& derived_cast() const & noexcept; - derived_type derived_cast() && noexcept; - - private: - - friend class xiterable; - friend class xconst_iterable; - - template - friend class xstepper; - - template - It data_xend_impl(It end, layout_type l) const noexcept; - - inner_shape_type& mutable_shape(); - inner_strides_type& mutable_strides(); - inner_backstrides_type& mutable_backstrides(); - }; - -#undef DL - - /** - * @class xstrided_container - * @brief Partial implementation of xcontainer that embeds the strides and the shape - * - * The xstrided_container class is a partial implementation of the xcontainer interface - * that embed the strides and the shape of the multidimensional container. It does - * not embed the data container, this responsibility is delegated to the inheriting - * classes. - * - * @tparam D The derived type, i.e. the inheriting class for which xstrided_container - * provides the partial imlpementation of xcontainer. - */ - template - class xstrided_container : public xcontainer - { - public: - - using base_type = xcontainer; - using storage_type = typename base_type::storage_type; - using value_type = typename base_type::value_type; - using reference = typename base_type::reference; - using const_reference = typename base_type::const_reference; - using pointer = typename base_type::pointer; - using const_pointer = typename base_type::const_pointer; - using size_type = typename base_type::size_type; - using shape_type = typename base_type::shape_type; - using strides_type = typename base_type::strides_type; - using inner_shape_type = typename base_type::inner_shape_type; - using inner_strides_type = typename base_type::inner_strides_type; - using inner_backstrides_type = typename base_type::inner_backstrides_type; - - template - void resize(S&& shape, bool force = false); - template - void resize(S&& shape, layout_type l); - template - void resize(S&& shape, const strides_type& strides); - - template - void reshape(S&& shape, layout_type layout = base_type::static_layout); - - layout_type layout() const noexcept; - - protected: - - xstrided_container() noexcept; - ~xstrided_container() = default; - - xstrided_container(const xstrided_container&) = default; - xstrided_container& operator=(const xstrided_container&) = default; - - xstrided_container(xstrided_container&&) = default; - xstrided_container& operator=(xstrided_container&&) = default; - - explicit xstrided_container(inner_shape_type&&, inner_strides_type&&) noexcept; - - inner_shape_type& shape_impl() noexcept; - const inner_shape_type& shape_impl() const noexcept; - - inner_strides_type& strides_impl() noexcept; - const inner_strides_type& strides_impl() const noexcept; - - inner_backstrides_type& backstrides_impl() noexcept; - const inner_backstrides_type& backstrides_impl() const noexcept; - - private: - - inner_shape_type m_shape; - inner_strides_type m_strides; - inner_backstrides_type m_backstrides; - layout_type m_layout = base_type::static_layout; - }; - - /****************************** - * xcontainer implementation * - ******************************/ - - template - template - inline It xcontainer::data_xend_impl(It end, layout_type l) const noexcept - { - return strided_data_end(*this, end, l); - } - - template - inline auto xcontainer::mutable_shape() -> inner_shape_type& - { - return derived_cast().shape_impl(); - } - - template - inline auto xcontainer::mutable_strides() -> inner_strides_type& - { - return derived_cast().strides_impl(); - } - - template - inline auto xcontainer::mutable_backstrides() -> inner_backstrides_type& - { - return derived_cast().backstrides_impl(); - } - - /** - * @name Size and shape - */ - //@{ - /** - * Returns the number of element in the container. - */ - template - inline auto xcontainer::size() const noexcept -> size_type - { - return contiguous_layout ? storage().size() : compute_size(shape()); - } - - /** - * Returns the number of dimensions of the container. - */ - template - inline constexpr auto xcontainer::dimension() const noexcept -> size_type - { - return shape().size(); - } - - /** - * Returns the shape of the container. - */ - template - constexpr inline auto xcontainer::shape() const noexcept -> const inner_shape_type& - { - return derived_cast().shape_impl(); - } - - /** - * Returns the strides of the container. - */ - template - constexpr inline auto xcontainer::strides() const noexcept -> const inner_strides_type& - { - return derived_cast().strides_impl(); - } - - /** - * Returns the backstrides of the container. - */ - template - constexpr inline auto xcontainer::backstrides() const noexcept -> const inner_backstrides_type& - { - return derived_cast().backstrides_impl(); - } - //@} - - /** - * @name Data - */ - //@{ - - /** - * Fills the container with the given value. - * @param value the value to fill the container with. - */ - template - template - inline void xcontainer::fill(const T& value) - { - std::fill(storage_begin(), storage_end(), value); - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the container. - */ - template - template - inline auto xcontainer::operator()(Args... args) -> reference - { - XTENSOR_TRY(check_index(shape(), args...)); - XTENSOR_CHECK_DIMENSION(shape(), args...); - size_type index = xt::data_offset(strides(), static_cast(args)...); - return storage()[index]; - } - - /** - * Returns a constant reference to the element at the specified position in the container. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the container. - */ - template - template - inline auto xcontainer::operator()(Args... args) const -> const_reference - { - XTENSOR_TRY(check_index(shape(), args...)); - XTENSOR_CHECK_DIMENSION(shape(), args...); - size_type index = xt::data_offset(strides(), static_cast(args)...); - return storage()[index]; - } - - /** - * Returns a reference to the element at the specified position in the container, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the container. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xcontainer::at(Args... args) -> reference - { - check_access(shape(), static_cast(args)...); - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the container, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the container. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xcontainer::at(Args... args) const -> const_reference - { - check_access(shape(), static_cast(args)...); - return this->operator()(args...); - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the container, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xcontainer::unchecked(Args... args) -> reference - { - size_type index = xt::unchecked_data_offset(strides(), static_cast(args)...); - return storage()[index]; - } - - /** - * Returns a constant reference to the element at the specified position in the container. - * @param args a list of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the container, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xcontainer::unchecked(Args... args) const -> const_reference - { - size_type index = xt::unchecked_data_offset(strides(), static_cast(args)...); - return storage()[index]; - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param index a sequence of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices in the list should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xcontainer::operator[](const S& index) - -> disable_integral_t - { - return element(index.cbegin(), index.cend()); - } - - template - template - inline auto xcontainer::operator[](std::initializer_list index) -> reference - { - return element(index.begin(), index.end()); - } - - template - inline auto xcontainer::operator[](size_type i) -> reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the container. - * @param index a sequence of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices in the list should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xcontainer::operator[](const S& index) const - -> disable_integral_t - { - return element(index.cbegin(), index.cend()); - } - - template - template - inline auto xcontainer::operator[](std::initializer_list index) const -> const_reference - { - return element(index.begin(), index.end()); - } - - template - inline auto xcontainer::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xcontainer::element(It first, It last) -> reference - { - XTENSOR_TRY(check_element_index(shape(), first, last)); - return storage()[element_offset(strides(), first, last)]; - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xcontainer::element(It first, It last) const -> const_reference - { - XTENSOR_TRY(check_element_index(shape(), first, last)); - return storage()[element_offset(strides(), first, last)]; - } - - /** - * Returns a reference to the buffer containing the elements of the container. - */ - template - inline auto xcontainer::storage() noexcept -> storage_type& - { - return derived_cast().storage_impl(); - } - - /** - * Returns a constant reference to the buffer containing the elements of the - * container. - */ - template - inline auto xcontainer::storage() const noexcept -> const storage_type& - { - return derived_cast().storage_impl(); - } - - /** - * Returns a pointer to the underlying array serving as element storage. The pointer - * is such that range [data(); data() + size()] is always a valid range, even if the - * container is empty (data() is not is not dereferenceable in that case) - */ - template - inline auto xcontainer::data() noexcept -> value_type* - { - return storage().data(); - } - - /** - * Returns a constant pointer to the underlying array serving as element storage. The pointer - * is such that range [data(); data() + size()] is always a valid range, even if the - * container is empty (data() is not is not dereferenceable in that case) - */ - template - inline auto xcontainer::data() const noexcept -> const value_type* - { - return storage().data(); - } - - /** - * Returns the offset to the first element in the container. - */ - template - inline auto xcontainer::data_offset() const noexcept -> const size_type - { - return size_type(0); - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the container to the specified parameter. - * @param shape the result shape - * @param reuse_cache parameter for internal optimization - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xcontainer::broadcast_shape(S& shape, bool) const - { - return xt::broadcast_shape(this->shape(), shape); - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xcontainer::is_trivial_broadcast(const S& str) const noexcept - { - return str.size() == strides().size() && - std::equal(str.cbegin(), str.cend(), strides().begin()); - } - //@} - - /**************** - * Iterator api * - ****************/ - - template - template - inline auto xcontainer::begin() noexcept -> select_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_begin(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template begin(); - }); - } - - template - template - inline auto xcontainer::end() noexcept -> select_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_end(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template end(); - }); - } - - template - template - inline auto xcontainer::begin() const noexcept -> select_const_iterator - { - return this->template cbegin(); - } - - template - template - inline auto xcontainer::end() const noexcept -> select_const_iterator - { - return this->template cend(); - } - - template - template - inline auto xcontainer::cbegin() const noexcept -> select_const_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_cbegin(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template cbegin(); - }); - } - - template - template - inline auto xcontainer::cend() const noexcept -> select_const_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_cend(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template cend(); - }); - } - - template - template - inline auto xcontainer::rbegin() noexcept -> select_reverse_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_rbegin(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template rbegin(); - }); - } - - template - template - inline auto xcontainer::rend() noexcept -> select_reverse_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_rend(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template rend(); - }); - } - - template - template - inline auto xcontainer::rbegin() const noexcept -> select_const_reverse_iterator - { - return this->template crbegin(); - } - - template - template - inline auto xcontainer::rend() const noexcept -> select_const_reverse_iterator - { - return this->template crend(); - } - - template - template - inline auto xcontainer::crbegin() const noexcept -> select_const_reverse_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_crbegin(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template crbegin(); - }); - } - - template - template - inline auto xcontainer::crend() const noexcept -> select_const_reverse_iterator - { - return xtl::mpl::static_if([&](auto self) - { - return self(*this).template storage_crend(); - }, /*else*/ [&](auto self) - { - return self(*this).iterable_base::template crend(); - }); - } - - /***************************** - * Broadcasting iterator api * - *****************************/ - - template - template - inline auto xcontainer::begin(const S& shape) noexcept -> broadcast_iterator - { - return iterable_base::template begin(shape); - } - - template - template - inline auto xcontainer::end(const S& shape) noexcept -> broadcast_iterator - { - return iterable_base::template end(shape); - } - - template - template - inline auto xcontainer::begin(const S& shape) const noexcept -> const_broadcast_iterator - { - return iterable_base::template begin(shape); - } - - template - template - inline auto xcontainer::end(const S& shape) const noexcept -> const_broadcast_iterator - { - return iterable_base::template end(shape); - } - - template - template - inline auto xcontainer::cbegin(const S& shape) const noexcept -> const_broadcast_iterator - { - return iterable_base::template cbegin(shape); - } - - template - template - inline auto xcontainer::cend(const S& shape) const noexcept -> const_broadcast_iterator - { - return iterable_base::template cend(shape); - } - - template - template - inline auto xcontainer::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator - { - return iterable_base::template rbegin(shape); - } - - template - template - inline auto xcontainer::rend(const S& shape) noexcept -> reverse_broadcast_iterator - { - return iterable_base::template rend(shape); - } - - template - template - inline auto xcontainer::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return iterable_base::template rbegin(shape); - } - - template - template - inline auto xcontainer::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return iterable_base::template rend(shape); - } - - template - template - inline auto xcontainer::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return iterable_base::template crbegin(shape); - } - - template - template - inline auto xcontainer::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return iterable_base::template crend(shape); - } - - /*********************** - * Linear iterator api * - ***********************/ - - template - template - inline auto xcontainer::storage_begin() noexcept -> storage_iterator - { - return storage().begin(); - } - - template - template - inline auto xcontainer::storage_end() noexcept -> storage_iterator - { - return storage().end(); - } - - template - template - inline auto xcontainer::storage_begin() const noexcept -> const_storage_iterator - { - return storage().begin(); - } - - template - template - inline auto xcontainer::storage_end() const noexcept -> const_storage_iterator - { - return storage().end(); - } - - template - template - inline auto xcontainer::storage_cbegin() const noexcept -> const_storage_iterator - { - return storage().cbegin(); - } - - template - template - inline auto xcontainer::storage_cend() const noexcept -> const_storage_iterator - { - return storage().cend(); - } - - template - template - inline auto xcontainer::storage_rbegin() noexcept -> reverse_storage_iterator - { - return storage().rbegin(); - } - - template - template - inline auto xcontainer::storage_rend() noexcept -> reverse_storage_iterator - { - return storage().rend(); - } - - template - template - inline auto xcontainer::storage_rbegin() const noexcept -> const_reverse_storage_iterator - { - return storage().rbegin(); - } - - template - template - inline auto xcontainer::storage_rend() const noexcept -> const_reverse_storage_iterator - { - return storage().rend(); - } - - template - template - inline auto xcontainer::storage_crbegin() const noexcept -> const_reverse_storage_iterator - { - return storage().crbegin(); - } - - template - template - inline auto xcontainer::storage_crend() const noexcept -> const_reverse_storage_iterator - { - return storage().crend(); - } - - /*************** - * stepper api * - ***************/ - - template - template - inline auto xcontainer::stepper_begin(const S& shape) noexcept -> stepper - { - size_type offset = shape.size() - dimension(); - return stepper(static_cast(this), data_xbegin(), offset); - } - - template - template - inline auto xcontainer::stepper_end(const S& shape, layout_type l) noexcept -> stepper - { - size_type offset = shape.size() - dimension(); - return stepper(static_cast(this), data_xend(l), offset); - } - - template - template - inline auto xcontainer::stepper_begin(const S& shape) const noexcept -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(static_cast(this), data_xbegin(), offset); - } - - template - template - inline auto xcontainer::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(static_cast(this), data_xend(l), offset); - } - - template - inline auto xcontainer::data_xbegin() noexcept -> container_iterator - { - return storage().begin(); - } - - template - inline auto xcontainer::data_xbegin() const noexcept -> const_container_iterator - { - return storage().begin(); - } - - template - inline auto xcontainer::data_xend(layout_type l) noexcept -> container_iterator - { - return data_xend_impl(storage().end(), l); - } - - template - inline auto xcontainer::data_xend(layout_type l) const noexcept -> const_container_iterator - { - return data_xend_impl(storage().end(), l); - } - - template - inline auto xcontainer::derived_cast() & noexcept -> derived_type& - { - return *static_cast(this); - } - - template - inline auto xcontainer::derived_cast() const & noexcept -> const derived_type& - { - return *static_cast(this); - } - - template - inline auto xcontainer::derived_cast() && noexcept -> derived_type - { - return *static_cast(this); - } - - template - inline auto xcontainer::data_element(size_type i) -> reference - { - return storage()[i]; - } - - template - inline auto xcontainer::data_element(size_type i) const -> const_reference - { - return storage()[i]; - } - - template - template - inline void xcontainer::store_simd(size_type i, const simd& e) - { - using align_mode = driven_align_mode_t; - xsimd::store_simd(&(storage()[i]), e, align_mode()); - } - - template - template - inline auto xcontainer::load_simd(size_type i) const -> simd_return_type - { - using align_mode = driven_align_mode_t; - return xsimd::load_simd(&(storage()[i]), align_mode()); - } - - /************************************* - * xstrided_container implementation * - *************************************/ - - template - inline xstrided_container::xstrided_container() noexcept - : base_type() - { - m_shape = xtl::make_sequence(base_type::dimension(), 1); - m_strides = xtl::make_sequence(base_type::dimension(), 0); - m_backstrides = xtl::make_sequence(base_type::dimension(), 0); - } - - template - inline xstrided_container::xstrided_container(inner_shape_type&& shape, inner_strides_type&& strides) noexcept - : base_type(), m_shape(std::move(shape)), m_strides(std::move(strides)) - { - m_backstrides = xtl::make_sequence(m_shape.size(), 0); - adapt_strides(m_shape, m_strides, m_backstrides); - } - - template - inline auto xstrided_container::shape_impl() noexcept -> inner_shape_type& - { - return m_shape; - } - - template - inline auto xstrided_container::shape_impl() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - template - inline auto xstrided_container::strides_impl() noexcept -> inner_strides_type& - { - return m_strides; - } - - template - inline auto xstrided_container::strides_impl() const noexcept -> const inner_strides_type& - { - return m_strides; - } - - template - inline auto xstrided_container::backstrides_impl() noexcept -> inner_backstrides_type& - { - return m_backstrides; - } - - template - inline auto xstrided_container::backstrides_impl() const noexcept -> const inner_backstrides_type& - { - return m_backstrides; - } - - /** - * Return the layout_type of the container - * @return layout_type of the container - */ - template - layout_type xstrided_container::layout() const noexcept - { - return m_layout; - } - - namespace detail - { - template - inline void resize_data_container(C& c, S size) - { - xt::resize_container(c, size); - } - - template - inline void resize_data_container(const C& c, S size) - { - (void) c; // remove unused parameter warning - (void) size; - XTENSOR_ASSERT_MSG(c.size() == size, "Trying to resize const data container with wrong size."); - } - } - - /** - * resizes the container. - * @param shape the new shape - * @param force force reshaping, even if the shape stays the same (default: false) - */ - template - template - inline void xstrided_container::resize(S&& shape, bool force) - { - if (m_shape.size() != shape.size() || !std::equal(std::begin(shape), std::end(shape), std::begin(m_shape)) || force) - { - if (m_layout == layout_type::dynamic || m_layout == layout_type::any) - { - m_layout = XTENSOR_DEFAULT_LAYOUT; // fall back to default layout - } - m_shape = xtl::forward_sequence(shape); - resize_container(m_strides, m_shape.size()); - resize_container(m_backstrides, m_shape.size()); - size_type data_size = compute_strides(m_shape, m_layout, m_strides, m_backstrides); - detail::resize_data_container(this->storage(), data_size); - } - } - - /** - * resizes the container. - * @param shape the new shape - * @param l the new layout_type - */ - template - template - inline void xstrided_container::resize(S&& shape, layout_type l) - { - if (base_type::static_layout != layout_type::dynamic && l != base_type::static_layout) - { - throw std::runtime_error("Cannot change layout_type if template parameter not layout_type::dynamic."); - } - m_layout = l; - resize(std::forward(shape), true); - } - - /** - * Resizes the container. - * @param shape the new shape - * @param strides the new strides - */ - template - template - inline void xstrided_container::resize(S&& shape, const strides_type& strides) - { - if (base_type::static_layout != layout_type::dynamic) - { - throw std::runtime_error("Cannot resize with custom strides when layout() is != layout_type::dynamic."); - } - m_shape = xtl::forward_sequence(shape); - m_strides = strides; - resize_container(m_backstrides, m_strides.size()); - adapt_strides(m_shape, m_strides, m_backstrides); - m_layout = layout_type::dynamic; - detail::resize_data_container(this->storage(), compute_size(m_shape)); - } - - /** - * Reshapes the container and keeps old elements - * @param shape the new shape (has to have same number of elements as the original container) - * @param layout the layout to compute the strides (defaults to static layout of the container, - * or for a container with dynamic layout to XTENSOR_DEFAULT_LAYOUT) - */ - template - template - inline void xstrided_container::reshape(S&& shape, layout_type layout) - { - if (compute_size(shape) != this->size()) - { - throw std::runtime_error("Cannot reshape with incorrect number of elements. Do you mean to resize?"); - } - if (layout == layout_type::dynamic || layout == layout_type::any) - { - layout = XTENSOR_DEFAULT_LAYOUT; // fall back to default layout - } - if (layout != base_type::static_layout && base_type::static_layout != layout_type::dynamic) - { - throw std::runtime_error("Cannot reshape with different layout if static layout != dynamic."); - } - m_layout = layout; - m_shape = xtl::forward_sequence(shape); - resize_container(m_strides, m_shape.size()); - resize_container(m_backstrides, m_shape.size()); - compute_strides(m_shape, m_layout, m_strides, m_backstrides); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xcsv.hpp b/vendor/xtensor/include/xtensor/xcsv.hpp deleted file mode 100644 index 4a2716d40..000000000 --- a/vendor/xtensor/include/xtensor/xcsv.hpp +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_CSV_HPP -#define XTENSOR_CSV_HPP - -#include -#include -#include -#include -#include -#include - -#include "xtensor.hpp" - -namespace xt -{ - - /************************************** - * load_csv and dump_csv declarations * - **************************************/ - - template > - using xcsv_tensor = xtensor_container, 2, layout_type::row_major>; - - template > - xcsv_tensor load_csv(std::istream& stream); - - template - void dump_csv(std::ostream& stream, const xexpression& e); - - /***************************************** - * load_csv and dump_csv implementations * - *****************************************/ - - namespace detail - { - template - inline T lexical_cast(const std::string& cell) - { - T res; - std::istringstream iss(cell); - iss >> res; - return res; - } - - template <> - inline float lexical_cast(const std::string& cell) { return std::stof(cell); } - - template <> - inline double lexical_cast(const std::string& cell) { return std::stod(cell); } - - template <> - inline long double lexical_cast(const std::string& cell) { return std::stold(cell); } - - template <> - inline int lexical_cast(const std::string& cell) { return std::stoi(cell); } - - template <> - inline long lexical_cast(const std::string& cell) { return std::stol(cell); } - - template <> - inline long long lexical_cast(const std::string& cell) { return std::stoll(cell); } - - template <> - inline unsigned int lexical_cast(const std::string& cell) { return static_cast(std::stoul(cell)); } - - template <> - inline unsigned long lexical_cast(const std::string& cell) { return std::stoul(cell); } - - template <> - inline unsigned long long lexical_cast(const std::string& cell) { return std::stoull(cell); } - - template - ST load_csv_row(std::istream& row_stream, OI output, std::string cell) - { - ST length = 0; - while (std::getline(row_stream, cell, ',')) - { - *output++ = lexical_cast(cell); - ++length; - } - return length; - } - } - - /** - * @brief Load tensor from CSV. - * - * Returns an \ref xexpression for the parsed CSV - * @param stream the input stream containing the CSV encoded values - */ - template - xcsv_tensor load_csv(std::istream& stream) - { - using tensor_type = xcsv_tensor; - using storage_type = typename tensor_type::storage_type; - using size_type = typename tensor_type::size_type; - using inner_shape_type = typename tensor_type::inner_shape_type; - using inner_strides_type = typename tensor_type::inner_strides_type; - using output_iterator = std::back_insert_iterator; - - storage_type data; - size_type nbrow = 0, nbcol = 0; - { - output_iterator output(data); - std::string row, cell; - while (std::getline(stream, row)) - { - std::stringstream row_stream(row); - nbcol = detail::load_csv_row(row_stream, output, cell); - ++nbrow; - } - } - inner_shape_type shape = {nbrow, nbcol}; - inner_strides_type strides; // no need for initializer list for stack-allocated strides_type - size_type data_size = compute_strides(shape, layout_type::row_major, strides); - // Sanity check for data size. - if (data.size() != data_size) - { - throw std::runtime_error("Inconsistent row lengths in CSV"); - } - return tensor_type(std::move(data), std::move(shape), std::move(strides)); - } - - /** - * @brief Dump tensor to CSV. - * - * @param stream the output stream to write the CSV encoded values - * @param e the tensor expression to serialize - */ - template - void dump_csv(std::ostream& stream, const xexpression& e) - { - using size_type = typename E::size_type; - const E& ex = e.derived_cast(); - if (ex.dimension() != 2) - { - throw std::runtime_error("Only 2-D expressions can be serialized to CSV"); - } - size_type nbrows = ex.shape()[0], nbcols = ex.shape()[1]; - auto st = ex.stepper_begin(ex.shape()); - for (size_type r = 0; r != nbrows; ++r) - { - for (size_type c = 0; c != nbcols; ++c) - { - stream << *st; - if (c != nbcols - 1) - { - st.step(1); - stream << ','; - } - else - { - st.reset(1); - st.step(0); - stream << std::endl; - } - } - } - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xeval.hpp b/vendor/xtensor/include/xtensor/xeval.hpp deleted file mode 100644 index 18d53beea..000000000 --- a/vendor/xtensor/include/xtensor/xeval.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_EVAL_HPP -#define XTENSOR_EVAL_HPP - -#include "xtensor_forward.hpp" - -namespace xt -{ - - namespace detail - { - template - using is_container = std::is_base_of>, T>; - } - - /** - * Force evaluation of xexpression. - * @return xarray or xtensor depending on shape type - * - * \code{.cpp} - * xarray a = {1,2,3,4}; - * auto&& b = xt::eval(a); // b is a reference to a, no copy! - * auto&& c = xt::eval(a + b); // c is xarray, not an xexpression - * \endcode - */ - template - inline auto eval(T&& t) - -> std::enable_if_t>::value, T&&> - { - return std::forward(t); - } - - /// @cond DOXYGEN_INCLUDE_SFINAE - template > - inline auto eval(T&& t) - -> std::enable_if_t::value && detail::is_array::value, xtensor::value>> - { - return xtensor::value>(std::forward(t)); - } - - template > - inline auto eval(T&& t) - -> std::enable_if_t::value && !detail::is_array::value, xt::xarray> - { - return xarray(std::forward(t)); - } - /// @endcond -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xexception.hpp b/vendor/xtensor/include/xtensor/xexception.hpp deleted file mode 100644 index 689ce31e0..000000000 --- a/vendor/xtensor/include/xtensor/xexception.hpp +++ /dev/null @@ -1,219 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_EXCEPTION_HPP -#define XTENSOR_EXCEPTION_HPP - -#include -#include -#include -#include - -namespace xt -{ - - /******************* - * broadcast_error * - *******************/ - - class broadcast_error : public std::runtime_error - { - public: - - explicit broadcast_error(const char* msg) - : std::runtime_error(msg) - { - } - }; - - template - [[noreturn]] void throw_broadcast_error(const S1& lhs, const S2& rhs); - - /********************************** - * broadcast_error implementation * - **********************************/ - -#ifdef NDEBUG - // Do not inline this function - template - [[noreturn]] void throw_broadcast_error(const S1&, const S2&) - { - throw broadcast_error("Incompatible dimension of arrays, compile in DEBUG for more info"); - } -#else - template - [[noreturn]] void throw_broadcast_error(const S1& lhs, const S2& rhs) - { - std::ostringstream buf("Incompatible dimension of arrays:", std::ios_base::ate); - - buf << "\n LHS shape = ("; - using size_type1 = typename S1::value_type; - std::ostream_iterator iter1(buf, ", "); - std::copy(lhs.cbegin(), lhs.cend(), iter1); - - buf << ")\n RHS shape = ("; - using size_type2 = typename S2::value_type; - std::ostream_iterator iter2(buf, ", "); - std::copy(rhs.cbegin(), rhs.cend(), iter2); - buf << ")"; - - throw broadcast_error(buf.str().c_str()); - } -#endif - - /******************* - * transpose_error * - *******************/ - - class transpose_error : public std::runtime_error - { - public: - - explicit transpose_error(const char* msg) - : std::runtime_error(msg) - { - } - }; - - /*************** - * check_index * - ***************/ - - template - void check_index(const S& shape, Args... args); - - template - void check_element_index(const S& shape, It first, It last); - - namespace detail - { - template - inline void check_index_impl(const S&) - { - } - - template - inline void check_index_impl(const S& shape, std::size_t arg, Args... args) - { - if (sizeof...(Args) + 1 > shape.size()) - { - check_index_impl(shape, args...); - } - else - { - if (arg >= std::size_t(shape[dim]) && shape[dim] != 1) - { - throw std::out_of_range("index " + std::to_string(arg) + " is out of bounds for axis " - + std::to_string(dim) + " with size " + std::to_string(shape[dim])); - } - check_index_impl(shape, args...); - } - } - } - - template - inline void check_index(const S& shape, Args... args) - { - using value_type = typename S::value_type; - detail::check_index_impl(shape, static_cast(args)...); - } - - template - inline void check_element_index(const S& shape, It first, It last) - { - using value_type = typename std::iterator_traits::value_type; - auto dst = static_cast(last - first); - It efirst = last - static_cast((std::min)(shape.size(), dst)); - std::size_t axis = 0; - while (efirst != last) - { - if (*efirst >= value_type(shape[axis]) && shape[axis] != 1) - { - throw std::out_of_range("index " + std::to_string(*efirst) + " is out of bounds for axis " - + std::to_string(axis) + " with size " + std::to_string(shape[axis])); - } - ++efirst, ++axis; - } - } - - /******************* - * check_dimension * - *******************/ - - template - inline void check_dimension(const S& shape, Args...) - { - if (sizeof...(Args) > shape.size()) - { - throw std::out_of_range("Number of arguments (" + std::to_string(sizeof...(Args)) + ") us greater " - + "than the number of dimensions (" + std::to_string(shape.size()) + ")"); - } - } - - /**************** - * check_access * - ****************/ - - template - inline void check_access(const S& shape, Args... args) - { - check_dimension(shape, args...); - check_index(shape, args...); - } - -#ifdef XTENSOR_ENABLE_ASSERT -#define XTENSOR_TRY(expr) XTENSOR_TRY_IMPL(expr, __FILE__, __LINE__) -#define XTENSOR_TRY_IMPL(expr, file, line) \ - try \ - { \ - expr; \ - } \ - catch (std::exception& e) \ - { \ - throw std::runtime_error(std::string(file) + ':' + std::to_string(line) + ": check failed\n\t" + std::string(e.what())); \ - } -#else -#define XTENSOR_TRY(expr) -#endif - -#ifdef XTENSOR_ENABLE_ASSERT -#define XTENSOR_ASSERT(expr) XTENSOR_ASSERT_IMPL(expr, __FILE__, __LINE__) -#define XTENSOR_ASSERT_IMPL(expr, file, line) \ - if (!(expr)) \ - { \ - throw std::runtime_error(std::string(file) + ':' + std::to_string(line) + ": assertion failed (" #expr ") \n\t"); \ - } -#else -#define XTENSOR_ASSERT(expr) -#endif - -#ifdef XTENSOR_ENABLE_CHECK_DIMENSION -#define XTENSOR_CHECK_DIMENSION(S, ARGS) XTENSOR_TRY(check_dimension(S, ARGS)) -#else -#define XTENSOR_CHECK_DIMENSION(S, ARGS) -#endif - -#ifdef XTENSOR_ENABLE_ASSERT -#define XTENSOR_ASSERT_MSG(expr, msg) \ - if (!(expr)) \ - { \ - throw std::runtime_error(std::string("Assertion error!\n") + msg + \ - "\n " + __FILE__ + '(' + std::to_string(__LINE__) + ")\n"); \ - } -#else -#define XTENSOR_ASSERT_MSG(expr, msg) -#endif - -#define XTENSOR_PRECONDITION(expr, msg) \ - if (!(expr)) \ - { \ - throw std::runtime_error(std::string("Precondition violation!\n") + msg + \ - "\n " + __FILE__ + '(' + std::to_string(__LINE__) + ")\n"); \ - } -} -#endif // XEXCEPTION_HPP diff --git a/vendor/xtensor/include/xtensor/xexpression.hpp b/vendor/xtensor/include/xtensor/xexpression.hpp deleted file mode 100644 index a83ea0c58..000000000 --- a/vendor/xtensor/include/xtensor/xexpression.hpp +++ /dev/null @@ -1,307 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_EXPRESSION_HPP -#define XTENSOR_EXPRESSION_HPP - -#include -#include -#include - -#include -#include - -#include "xshape.hpp" -#include "xutils.hpp" - -namespace xt -{ - - /*************************** - * xexpression declaration * - ***************************/ - - /** - * @class xexpression - * @brief Base class for xexpressions - * - * The xexpression class is the base class for all classes representing an expression - * that can be evaluated to a multidimensional container with tensor semantic. - * Functions that can apply to any xexpression regardless of its specific type should take a - * xexpression argument. - * - * \tparam E The derived type. - * - */ - template - class xexpression - { - public: - - using derived_type = D; - - derived_type& derived_cast() & noexcept; - const derived_type& derived_cast() const & noexcept; - derived_type derived_cast() && noexcept; - - protected: - - xexpression() = default; - ~xexpression() = default; - - xexpression(const xexpression&) = default; - xexpression& operator=(const xexpression&) = default; - - xexpression(xexpression&&) = default; - xexpression& operator=(xexpression&&) = default; - }; - - /****************************** - * xexpression implementation * - ******************************/ - - /** - * @name Downcast functions - */ - //@{ - /** - * Returns a reference to the actual derived type of the xexpression. - */ - template - inline auto xexpression::derived_cast() & noexcept -> derived_type& - { - return *static_cast(this); - } - - /** - * Returns a constant reference to the actual derived type of the xexpression. - */ - template - inline auto xexpression::derived_cast() const & noexcept -> const derived_type& - { - return *static_cast(this); - } - - /** - * Returns a constant reference to the actual derived type of the xexpression. - */ - template - inline auto xexpression::derived_cast() && noexcept -> derived_type - { - return *static_cast(this); - } - //@} - - namespace detail - { - template - struct is_xexpression_impl : std::is_base_of>, std::decay_t> - { - }; - - template - struct is_xexpression_impl> : std::true_type - { - }; - } - - template - using is_xexpression = detail::is_xexpression_impl; - - template - using enable_xexpression = typename std::enable_if::value, R>::type; - - template - using disable_xexpression = typename std::enable_if::value, R>::type; - - template - using has_xexpression = xtl::disjunction...>; - - /************ - * xclosure * - ************/ - - template - class xscalar; - - template - struct xclosure - { - using type = xtl::closure_type_t; - }; - - template - struct xclosure>> - { - using type = xscalar>; - }; - - template - using xclosure_t = typename xclosure::type; - - template - struct const_xclosure - { - using type = xtl::const_closure_type_t; - }; - - template - struct const_xclosure>> - { - using type = xscalar>; - }; - - template - using const_xclosure_t = typename const_xclosure::type; - - /*************** - * xvalue_type * - ***************/ - - namespace detail - { - template - struct xvalue_type_impl - { - using type = E; - }; - - template - struct xvalue_type_impl::value>> - { - using type = typename E::value_type; - }; - } - - template - using xvalue_type = detail::xvalue_type_impl; - - template - using xvalue_type_t = typename xvalue_type::type; - - /************************* - * expression tag system * - *************************/ - - struct xscalar_expression_tag - { - }; - - struct xtensor_expression_tag - { - }; - - struct xoptional_expression_tag - { - }; - - namespace detail - { - template > - struct get_expression_tag - { - using type = xtensor_expression_tag; - }; - - template - struct get_expression_tag::expression_tag>> - { - using type = typename std::decay_t::expression_tag; - }; - - template - using get_expression_tag_t = typename get_expression_tag::type; - - template - struct expression_tag_and; - - template - struct expression_tag_and - { - using type = T; - }; - - template - struct expression_tag_and - { - using type = T; - }; - - template <> - struct expression_tag_and - { - using type = xscalar_expression_tag; - }; - - template - struct expression_tag_and - { - using type = T; - }; - - template - struct expression_tag_and - : expression_tag_and - { - }; - - template <> - struct expression_tag_and - { - using type = xoptional_expression_tag; - }; - - template <> - struct expression_tag_and - : expression_tag_and - { - }; - - template - struct expression_tag_and - : expression_tag_and::type> - { - }; - - template - using expression_tag_and_t = typename expression_tag_and::type; - } - - template - struct xexpression_tag - { - using type = detail::expression_tag_and_t>>...>; - }; - - template - using xexpression_tag_t = typename xexpression_tag::type; - - template - struct is_xtensor_expression : std::is_same, xtensor_expression_tag> - { - }; - - template - struct is_xoptional_expression : std::is_same, xoptional_expression_tag> - { - }; - - /******************************** - * xoptional_comparable concept * - ********************************/ - - template - struct xoptional_comparable : xtl::conjunction, - is_xoptional_expression - >... - > - { - }; -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xfixed.hpp b/vendor/xtensor/include/xtensor/xfixed.hpp deleted file mode 100644 index 443882597..000000000 --- a/vendor/xtensor/include/xtensor/xfixed.hpp +++ /dev/null @@ -1,818 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_FIXED_HPP -#define XTENSOR_FIXED_HPP - -#include -#include -#include -#include -#include - -#include "xcontainer.hpp" -#include "xstrides.hpp" -#include "xstorage.hpp" -#include "xsemantic.hpp" - -#ifdef _MSC_VER - #define XTENSOR_CONSTEXPR_ENHANCED const - #define XTENSOR_CONSTEXPR_ENHANCED_STATIC const - #define XTENSOR_CONSTEXPR_RETURN -#else - #define XTENSOR_CONSTEXPR_ENHANCED constexpr - #define XTENSOR_CONSTEXPR_RETURN constexpr - #define XTENSOR_CONSTEXPR_ENHANCED_STATIC constexpr static - #define XTENSOR_HAS_CONSTEXPR_ENHANCED -#endif - -namespace xt -{ - /** - * @class fixed_shape - * Fixed shape implementation for compile time defined arrays. - * @sa xshape - */ - template - class fixed_shape - { - public: - - using cast_type = const_array; - - constexpr static std::size_t size() - { - return sizeof...(X); - } - - constexpr fixed_shape() - { - } - - constexpr operator cast_type() const - { - return {{X...}}; - } - }; -} - -namespace std -{ - template - class tuple_size> : - public integral_constant - { - }; -} - -namespace xtl -{ - namespace detail - { - template - struct sequence_builder> - { - using sequence_type = xt::const_array; - using value_type = typename sequence_type::value_type; - using size_type = typename sequence_type::size_type; - - inline static sequence_type make(size_type /*size*/, value_type /*v*/) - { - return sequence_type(); - } - }; - } -} - -namespace xt -{ - - /********************** - * xfixed declaration * - **********************/ - - template - class xfixed_container; - - namespace detail - { - /************************************************************************************** - The following is something we can currently only dream about -- for when we drop - support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;) - - template - constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L) - { - if (shape[idx] == 1) - { - return std::size_t(0); - } - - std::size_t data_size = 1; - std::size_t stride = 1; - if (L == layout_type::row_major) - { - // because we have a integer sequence that counts - // from 0 to sz - 1, we need to "invert" idx here - idx = shape.size() - idx; - for (std::size_t i = idx; i != 0; --i) - { - stride = data_size; - data_size = stride * shape[i - 1]; - } - } - else - { - for (std::size_t i = 0; i < idx + 1; ++i) - { - stride = data_size; - data_size = stride * shape[i]; - } - } - return stride; - } - - *****************************************************************************************/ - - template - struct at - { - constexpr static std::size_t arr[sizeof...(X)] = {X...}; - constexpr static std::size_t value = arr[IDX]; - }; - - template - struct calculate_stride; - - template - struct calculate_stride - { - constexpr static std::size_t value = Y * calculate_stride::value; - }; - - template - struct calculate_stride - { - constexpr static std::size_t value = 1; - }; - - template - struct calculate_stride_row_major - { - constexpr static std::size_t value = at::value * calculate_stride_row_major::value; - }; - - template - struct calculate_stride_row_major<0, X...> - { - constexpr static std::size_t value = 1; - }; - - template - struct calculate_stride - { - constexpr static std::size_t value = calculate_stride_row_major::value; - }; - - template - constexpr const_array - get_strides_impl(const xt::fixed_shape& /*shape*/, std::index_sequence) - { - static_assert((L == layout_type::row_major) || (L == layout_type::column_major), - "Layout not supported for fixed array"); - return {{at::value == 1 ? 0 : calculate_stride::value...}}; - } - - template - constexpr T get_backstrides_impl(const T& shape, const T& strides, std::index_sequence) - { - return {{(strides[I] * (shape[I] - 1))...}}; - } - - template - struct compute_size_impl; - - template - struct compute_size_impl - { - constexpr static std::size_t value = Y * compute_size_impl::value; - }; - - template - struct compute_size_impl - { - constexpr static std::size_t value = X; - }; - - template <> - struct compute_size_impl<> - { - // support for 0D xtensor fixed (empty shape = xshape<>) - constexpr static std::size_t value = 1; - }; - - // TODO unify with constexpr compute_size when dropping MSVC 2015 - template - struct fixed_compute_size; - - template - struct fixed_compute_size> - { - constexpr static std::size_t value = compute_size_impl::value; - }; - - template - struct get_init_type_impl; - - template - struct get_init_type_impl - { - using type = V[Y]; - }; - - template - struct get_init_type_impl - { - using type = V[1]; - }; - - template - struct get_init_type_impl - { - using tmp_type = typename get_init_type_impl::type; - using type = tmp_type[Y]; - }; - } - - template - constexpr const_array get_strides(const fixed_shape& shape) noexcept - { - return detail::get_strides_impl(shape, std::make_index_sequence{}); - } - - template - constexpr T get_backstrides(const T& shape, const T& strides) noexcept - { - return detail::get_backstrides_impl(shape, strides, - std::make_index_sequence::value>{}); - } - - template - struct get_init_type; - - template - struct get_init_type> - { - using type = typename detail::get_init_type_impl::type; - }; - - template - using get_init_type_t = typename get_init_type::type; - - template - struct xcontainer_inner_types> - { - using inner_shape_type = typename S::cast_type; - using inner_strides_type = inner_shape_type; - using backstrides_type = inner_shape_type; - using inner_backstrides_type = backstrides_type; - using shape_type = std::array::value>; - using strides_type = shape_type; - using storage_type = aligned_array::value>; - using temporary_type = xfixed_container; - static constexpr layout_type layout = L; - }; - - template - struct xiterable_inner_types> - : xcontainer_iterable_types> - { - }; - - /** - * @class xfixed_container - * @brief Dense multidimensional container with tensor semantic and fixed - * dimension. - * - * The xfixed_container class implements a dense multidimensional container - * with tensor semantic and fixed dimension - * - * @tparam ET The type of the elements. - * @tparam S The xshape template paramter of the container. - * @tparam L The layout_type of the tensor. - * @tparam Tag The expression tag. - * @sa xtensor_fixed - */ - template - class xfixed_container : public xcontainer>, - public xcontainer_semantic> - { - public: - - using self_type = xfixed_container; - using base_type = xcontainer; - using semantic_base = xcontainer_semantic; - - using storage_type = typename base_type::storage_type; - using value_type = typename base_type::value_type; - using reference = typename base_type::reference; - using const_reference = typename base_type::const_reference; - using pointer = typename base_type::pointer; - using const_pointer = typename base_type::const_pointer; - using shape_type = typename base_type::shape_type; - using inner_shape_type = typename base_type::inner_shape_type; - using strides_type = typename base_type::strides_type; - using backstrides_type = typename base_type::backstrides_type; - using inner_backstrides_type = typename base_type::inner_backstrides_type; - using inner_strides_type = typename base_type::inner_strides_type; - using temporary_type = typename semantic_base::temporary_type; - using expression_tag = Tag; - - constexpr static std::size_t N = std::tuple_size::value; - - xfixed_container(); -#if defined(_MSC_VER) && _MSC_VER < 1910 - explicit xfixed_container(value_type v); -#else - [[deprecated]] explicit xfixed_container(value_type v); -#endif - explicit xfixed_container(const inner_shape_type& shape, layout_type l = L); - explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L); - -#ifndef X_OLD_CLANG - xfixed_container(const get_init_type_t& init); -#else - // remove this enable_if when removing the other value_type constructor - template , class EN = std::enable_if_t> - xfixed_container(nested_initializer_list_t t); -#endif - - ~xfixed_container() = default; - - xfixed_container(const xfixed_container&) = default; - xfixed_container& operator=(const xfixed_container&) = default; - - xfixed_container(xfixed_container&&) = default; - xfixed_container& operator=(xfixed_container&&) = default; - - template - xfixed_container(const xexpression& e); - - template - xfixed_container& operator=(const xexpression& e); - - template - void resize(ST&& shape, bool force = false) const; - - template - void reshape(ST&& shape, layout_type layout = L) const; - - template - bool broadcast_shape(ST& s, bool reuse_cache = false) const; - - constexpr layout_type layout() const noexcept; - - private: - - storage_type m_storage; - - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S(); - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides(S()); - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type m_backstrides = get_backstrides(m_shape, m_strides); - - storage_type& storage_impl() noexcept; - const storage_type& storage_impl() const noexcept; - - XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept; - XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept; - XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept; - - friend class xcontainer>; - }; - -#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED - // Out of line definitions to prevent linker errors prior to C++17 - template - constexpr typename xfixed_container::inner_shape_type xfixed_container::m_shape; - - template - constexpr typename xfixed_container::inner_strides_type xfixed_container::m_strides; - - template - constexpr typename xfixed_container::inner_backstrides_type xfixed_container::m_backstrides; -#endif - - /**************************************** - * xfixed_container_adaptor declaration * - ****************************************/ - - template - class xfixed_adaptor; - - template - struct xcontainer_inner_types> - { - using storage_type = std::remove_reference_t; - using inner_shape_type = typename S::cast_type; - using inner_strides_type = inner_shape_type; - using backstrides_type = inner_shape_type; - using inner_backstrides_type = backstrides_type; - using shape_type = std::array::value>; - using strides_type = shape_type; - using temporary_type = xfixed_container; - static constexpr layout_type layout = L; - }; - - template - struct xiterable_inner_types> - : xcontainer_iterable_types> - { - }; - - /** - * @class xfixed_adaptor - * @brief Dense multidimensional container adaptor with tensor semantic - * and fixed dimension. - * - * The xfixed_adaptor class implements a dense multidimensional - * container adaptor with tensor semantic and fixed dimension. It - * is used to provide a multidimensional container semantic and a - * tensor semantic to stl-like containers. - * - * @tparam EC The closure for the container type to adapt. - * @tparam S The xshape template parameter for the fixed shape of the adaptor - * @tparam L The layout_type of the adaptor. - * @tparam Tag The expression tag. - */ - template - class xfixed_adaptor : public xcontainer>, - public xcontainer_semantic> - { - public: - - using container_closure_type = EC; - - using self_type = xfixed_adaptor; - using base_type = xcontainer; - using semantic_base = xcontainer_semantic; - using storage_type = typename base_type::storage_type; - using shape_type = typename base_type::shape_type; - using strides_type = typename base_type::strides_type; - using backstrides_type = typename base_type::backstrides_type; - using inner_shape_type = typename base_type::inner_shape_type; - using inner_strides_type = typename base_type::inner_strides_type; - using inner_backstrides_type = typename base_type::inner_backstrides_type; - using temporary_type = typename semantic_base::temporary_type; - using expression_tag = Tag; - - xfixed_adaptor(storage_type&& data); - xfixed_adaptor(const storage_type& data); - - template - xfixed_adaptor(D&& data); - - ~xfixed_adaptor() = default; - - xfixed_adaptor(const xfixed_adaptor&) = default; - xfixed_adaptor& operator=(const xfixed_adaptor&); - - xfixed_adaptor(xfixed_adaptor&&) = default; - xfixed_adaptor& operator=(xfixed_adaptor&&); - xfixed_adaptor& operator=(temporary_type&&); - - template - xfixed_adaptor& operator=(const xexpression& e); - - constexpr layout_type layout() const noexcept; - - private: - - container_closure_type m_storage; - - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S(); - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides(S()); - XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type m_backstrides = get_backstrides(m_shape, m_strides); - - storage_type& storage_impl() noexcept; - const storage_type& storage_impl() const noexcept; - - XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept; - XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept; - XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept; - - friend class xcontainer>; - }; - -#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED - // Out of line definitions to prevent linker errors prior to C++17 - template - constexpr typename xfixed_adaptor::inner_shape_type xfixed_adaptor::m_shape; - - template - constexpr typename xfixed_adaptor::inner_strides_type xfixed_adaptor::m_strides; - - template - constexpr typename xfixed_adaptor::inner_backstrides_type xfixed_adaptor::m_backstrides; -#endif - - /************************************ - * xfixed_container implementation * - ************************************/ - - /** - * @name Constructors - */ - //@{ - /** - * Create an uninitialized xfixed_container according to the shape template parameter. - */ - template - inline xfixed_container::xfixed_container() - { - } - - /** - * Create an xfixed_container, and initialize with the value of v. - * - * @param v the fill value - */ - template - inline xfixed_container::xfixed_container(value_type v) - { - std::fill(this->begin(), this->end(), v); - } - - /** - * Create an uninitialized xfixed_container. - * Note this function is only provided for homogenity, and the shape & layout argument is - * disregarded (the template shape is always used). - * - * @param shape the shape of the xfixed_container (unused!) - * @param l the layout_type of the xfixed_container (unused!) - */ - template - inline xfixed_container::xfixed_container(const inner_shape_type& /*shape*/, layout_type /*l*/) - { - } - - /** - * Create an xfixed_container, and initialize with the value of v. - * Note, the shape argument to this function is only provided for homogenity, - * and the shape argument is disregarded (the template shape is always used). - * - * @param shape the shape of the xfixed_container (unused!) - * @param v the fill value - * @param l the layout_type of the xfixed_container (unused!) - */ - template - inline xfixed_container::xfixed_container(const inner_shape_type& /*shape*/, value_type v, layout_type /*l*/) - : xfixed_container(v) - { - } - - /** - * Allocates an xfixed_container with shape S with values from a C array. - * The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for ``xt::xshape``. - * C arrays can be initialized with the initializer list syntax, but the size is checked at compile - * time to prevent errors. - * Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime. - */ -#ifndef X_OLD_CLANG - template - inline xfixed_container::xfixed_container(const get_init_type_t& init) - { - std::copy(reinterpret_cast(&init), reinterpret_cast(&init) + this->size(), - this->template begin()); - } -#else - template - template - inline xfixed_container::xfixed_container(nested_initializer_list_t t) - { - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); - } -#endif - //@} - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended copy constructor. - */ - template - template - inline xfixed_container::xfixed_container(const xexpression& e) - { - semantic_base::assign(e); - } - - /** - * The extended assignment operator. - */ - template - template - inline auto xfixed_container::operator=(const xexpression& e) -> self_type& - { - return semantic_base::operator=(e); - } - //@} - - /** - * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different - * size throws an assert in debug mode. - */ - template - template - inline void xfixed_container::resize(ST&& shape, bool) const - { - (void)(shape); // remove unused parameter warning if XTENSOR_ASSERT undefined - XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()); - } - - /** - * Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``. - */ - template - template - inline void xfixed_container::reshape(ST&& shape, layout_type layout) const - { - if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && layout == L)) - { - throw std::runtime_error("Trying to reshape xtensor_fixed with different shape or layout."); - } - } - - template - template - inline bool xfixed_container::broadcast_shape(ST& shape, bool) const - { - return xt::broadcast_shape(m_shape, shape); - } - - template - constexpr layout_type xfixed_container::layout() const noexcept - { - return base_type::static_layout; - } - - template - inline auto xfixed_container::storage_impl() noexcept -> storage_type& - { - return m_storage; - } - - template - inline auto xfixed_container::storage_impl() const noexcept -> const storage_type& - { - return m_storage; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_container::shape_impl() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_container::strides_impl() const noexcept -> const inner_strides_type& - { - return m_strides; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_container::backstrides_impl() const noexcept -> const inner_backstrides_type& - { - return m_backstrides; - } - - /******************* - * xfixed_adaptor * - *******************/ - - /** - * @name Constructors - */ - //@{ - /** - * Constructs an xfixed_adaptor of the given stl-like container. - * @param data the container to adapt - */ - template - inline xfixed_adaptor::xfixed_adaptor(storage_type&& data) - : base_type(), m_storage(std::move(data)) - { - } - - /** - * Constructs an xfixed_adaptor of the given stl-like container. - * @param data the container to adapt - */ - template - inline xfixed_adaptor::xfixed_adaptor(const storage_type& data) - : base_type(), m_storage(data) - { - } - - /** - * Constructs an xfixed_adaptor of the given stl-like container, - * with the specified shape and layout_type. - * @param data the container to adapt - */ - template - template - inline xfixed_adaptor::xfixed_adaptor(D&& data) - : base_type(), m_storage(std::forward(data)) - { - } - //@} - - template - inline auto xfixed_adaptor::operator=(const xfixed_adaptor& rhs) -> self_type& - { - base_type::operator=(rhs); - m_storage = rhs.m_storage; - return *this; - } - - template - inline auto xfixed_adaptor::operator=(xfixed_adaptor&& rhs) -> self_type& - { - base_type::operator=(std::move(rhs)); - m_storage = rhs.m_storage; - return *this; - } - - template - inline auto xfixed_adaptor::operator=(temporary_type&& rhs) -> self_type& - { - m_storage = xtl::forward_sequence(std::move(rhs.storage())); - return *this; - } - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended assignment operator. - */ - template - template - inline auto xfixed_adaptor::operator=(const xexpression& e) -> self_type& - { - return semantic_base::operator=(e); - } - //@} - - template - inline auto xfixed_adaptor::storage_impl() noexcept -> storage_type& - { - return m_storage; - } - - template - inline auto xfixed_adaptor::storage_impl() const noexcept -> const storage_type& - { - return m_storage; - } - - template - constexpr layout_type xfixed_adaptor::layout() const noexcept - { - return base_type::static_layout; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor::shape_impl() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor::strides_impl() const noexcept -> const inner_strides_type& - { - return m_strides; - } - - template - XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor::backstrides_impl() const noexcept -> const inner_backstrides_type& - { - return m_backstrides; - } -} - -#undef XTENSOR_CONSTEXPR_ENHANCED -#undef XTENSOR_CONSTEXPR_RETURN -#undef XTENSOR_CONSTEXPR_ENHANCED_STATIC -#undef XTENSOR_HAS_CONSTEXPR_ENHANCED - -#endif diff --git a/vendor/xtensor/include/xtensor/xfunction.hpp b/vendor/xtensor/include/xtensor/xfunction.hpp deleted file mode 100644 index 91fe86f36..000000000 --- a/vendor/xtensor/include/xtensor/xfunction.hpp +++ /dev/null @@ -1,1184 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_FUNCTION_HPP -#define XTENSOR_FUNCTION_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "xexpression.hpp" -#include "xiterable.hpp" -#include "xlayout.hpp" -#include "xscalar.hpp" -#include "xstrides.hpp" -#include "xtensor_simd.hpp" -#include "xutils.hpp" - -namespace xt -{ - - namespace detail - { - - /******************** - * common_size_type * - ********************/ - - template - struct common_size_type - { - using type = std::common_type_t; - }; - - template <> - struct common_size_type<> - { - using type = std::size_t; - }; - - template - using common_size_type_t = typename common_size_type::type; - - template - using conjunction_c = xtl::conjunction...>; - - /************************** - * common_difference type * - **************************/ - - template - struct common_difference_type - { - using type = std::common_type_t; - }; - - template <> - struct common_difference_type<> - { - using type = std::ptrdiff_t; - }; - - template - using common_difference_type_t = typename common_difference_type::type; - - /********************* - * common_value_type * - *********************/ - - template - struct common_value_type - { - using type = promote_type_t...>; - }; - - template - using common_value_type_t = typename common_value_type::type; - - template > - struct simd_return_type - { - }; - - template - struct simd_return_type)>> - { - using type = xsimd::simd_type>; - }; - - template - using simd_return_type_t = typename simd_return_type::type; - - template - struct functor_return_type - { - using type = R; - using simd_type = xsimd::simd_type; - }; - - template - struct functor_return_type> - { - using type = std::complex; - using simd_type = xsimd::simd_type>; - }; - - template - struct functor_return_type - { - using type = bool; - using simd_type = xsimd::simd_bool_type; - }; - - template <> - struct functor_return_type - { - using type = bool; - using simd_type = bool; - }; - } - - template - class xfunction_iterator; - - template - class xfunction_stepper; - - template - class xfunction_base; - - template - struct xiterable_inner_types> - { - using inner_shape_type = promote_shape_t::shape_type...>; - using const_stepper = xfunction_stepper; - using stepper = const_stepper; - }; - - /****************** - * xfunction_base * - ******************/ - -#define DL XTENSOR_DEFAULT_LAYOUT - - /** - * @class xfunction_base - * @brief Base class for multidimensional function operating on - * xexpression. - * - * The xfunction_base class implements a multidimensional function - * operating on xexpression. Inheriting classes specify which - * kind of xexpression the xfunction_base operates on. - * - * @tparam F the function type - * @tparam R the return type of the function - * @tparam CT the closure types for arguments of the function - */ - template - class xfunction_base : private xconst_iterable> - { - public: - - using self_type = xfunction_base; - using only_scalar = all_xscalar; - using functor_type = typename std::remove_reference::type; - using tuple_type = std::tuple; - - using value_type = R; - using reference = value_type; - using const_reference = value_type; - using pointer = value_type*; - using const_pointer = const value_type*; - using size_type = detail::common_size_type_t...>; - using difference_type = detail::common_difference_type_t...>; - using simd_value_type = typename detail::functor_return_type...>, R>::simd_type; - using simd_argument_type = xsimd::simd_type...>>; - using iterable_base = xconst_iterable>; - using inner_shape_type = typename iterable_base::inner_shape_type; - using shape_type = inner_shape_type; - - using stepper = typename iterable_base::stepper; - using const_stepper = typename iterable_base::const_stepper; - - static constexpr layout_type static_layout = compute_layout(std::decay_t::static_layout...); - static constexpr bool contiguous_layout = detail::conjunction_c::contiguous_layout...>::value; - - template - using layout_iterator = typename iterable_base::template layout_iterator; - template - using const_layout_iterator = typename iterable_base::template const_layout_iterator; - template - using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator; - template - using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator; - - template - using broadcast_iterator = typename iterable_base::template broadcast_iterator; - template - using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator; - template - using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator; - template - using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator; - - using const_storage_iterator = xfunction_iterator; - using storage_iterator = const_storage_iterator; - using const_reverse_storage_iterator = std::reverse_iterator; - using reverse_storage_iterator = std::reverse_iterator; - - using iterator = typename iterable_base::iterator; - using const_iterator = typename iterable_base::const_iterator; - using reverse_iterator = typename iterable_base::reverse_iterator; - using const_reverse_iterator = typename iterable_base::const_reverse_iterator; - - size_type size() const noexcept; - size_type dimension() const noexcept; - const shape_type& shape() const; - layout_type layout() const noexcept; - - template - const_reference operator()(Args... args) const; - - template - const_reference at(Args... args) const; - - template - const_reference unchecked(Args... args) const; - - template - disable_integral_t operator[](const S& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - const_reference element(It first, It last) const; - - template - bool broadcast_shape(S& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const S& strides) const noexcept; - - using iterable_base::begin; - using iterable_base::end; - using iterable_base::cbegin; - using iterable_base::cend; - using iterable_base::rbegin; - using iterable_base::rend; - using iterable_base::crbegin; - using iterable_base::crend; - - template - const_storage_iterator storage_begin() const noexcept; - template - const_storage_iterator storage_end() const noexcept; - template - const_storage_iterator storage_cbegin() const noexcept; - template - const_storage_iterator storage_cend() const noexcept; - - template - const_reverse_storage_iterator storage_rbegin() const noexcept; - template - const_reverse_storage_iterator storage_rend() const noexcept; - template - const_reverse_storage_iterator storage_crbegin() const noexcept; - template - const_reverse_storage_iterator storage_crend() const noexcept; - - template - const_stepper stepper_begin(const S& shape) const noexcept; - template - const_stepper stepper_end(const S& shape, layout_type l) const noexcept; - - const_reference data_element(size_type i) const; - - template ::type> - operator value_type() const; - - template - detail::simd_return_type_t load_simd(size_type i) const; - - const tuple_type& arguments() const noexcept; - - protected: - - template , self_type>::value>> - xfunction_base(Func&& f, CTA&&... e) noexcept; - - ~xfunction_base() = default; - - xfunction_base(const xfunction_base&) = default; - xfunction_base& operator=(const xfunction_base&) = default; - - xfunction_base(xfunction_base&&) = default; - xfunction_base& operator=(xfunction_base&&) = default; - - private: - - template - layout_type layout_impl(std::index_sequence) const noexcept; - - template - const_reference access_impl(std::index_sequence, Args... args) const; - - template - const_reference unchecked_impl(std::index_sequence, Args... args) const; - - template - const_reference element_access_impl(std::index_sequence, It first, It last) const; - - template - const_reference data_element_impl(std::index_sequence, size_type i) const; - - template - auto load_simd_impl(std::index_sequence, size_type i) const; - - template - const_stepper build_stepper(Func&& f, std::index_sequence) const noexcept; - - template - const_storage_iterator build_iterator(Func&& f, std::index_sequence) const noexcept; - - size_type compute_dimension() const noexcept; - - tuple_type m_e; - functor_type m_f; - mutable shape_type m_shape; - mutable bool m_shape_trivial; - mutable bool m_shape_computed; - - friend class xfunction_iterator; - friend class xfunction_stepper; - friend class xconst_iterable; - }; - -#undef DL - - /********************** - * xfunction_iterator * - **********************/ - - template - class xscalar; - - namespace detail - { - template - struct get_iterator_impl - { - using type = typename C::storage_iterator; - }; - - template - struct get_iterator_impl - { - using type = typename C::const_storage_iterator; - }; - - template - struct get_iterator_impl> - { - using type = typename xscalar::dummy_iterator; - }; - - template - struct get_iterator_impl> - { - using type = typename xscalar::const_dummy_iterator; - }; - } - - template - using get_iterator = typename detail::get_iterator_impl::type; - - template - class xfunction_iterator : public xtl::xrandom_access_iterator_base, - typename xfunction_base::value_type, - typename xfunction_base::difference_type, - typename xfunction_base::pointer, - typename xfunction_base::reference> - { - public: - - using self_type = xfunction_iterator; - using functor_type = typename std::remove_reference::type; - using xfunction_type = xfunction_base; - - using value_type = typename xfunction_type::value_type; - using reference = typename xfunction_type::value_type; - using pointer = typename xfunction_type::const_pointer; - using difference_type = typename xfunction_type::difference_type; - using iterator_category = std::random_access_iterator_tag; - - template - xfunction_iterator(const xfunction_type* func, It&&... it) noexcept; - - self_type& operator++(); - self_type& operator--(); - - self_type& operator+=(difference_type n); - self_type& operator-=(difference_type n); - - difference_type operator-(const self_type& rhs) const; - - reference operator*() const; - - bool equal(const self_type& rhs) const; - bool less_than(const self_type& rhs) const; - - private: - - using data_type = std::tuple>...>; - - template - reference deref_impl(std::index_sequence) const; - - template - difference_type tuple_max_diff(std::index_sequence, - const data_type& lhs, - const data_type& rhs) const; - - const xfunction_type* p_f; - data_type m_it; - }; - - template - bool operator==(const xfunction_iterator& it1, - const xfunction_iterator& it2); - - template - bool operator<(const xfunction_iterator& it1, - const xfunction_iterator& it2); - - /********************* - * xfunction_stepper * - *********************/ - - template - class xfunction_stepper - { - public: - - using self_type = xfunction_stepper; - using functor_type = typename std::remove_reference::type; - using xfunction_type = xfunction_base; - - using value_type = typename xfunction_type::value_type; - using reference = typename xfunction_type::value_type; - using pointer = typename xfunction_type::const_pointer; - using size_type = typename xfunction_type::size_type; - using difference_type = typename xfunction_type::difference_type; - - using shape_type = typename xfunction_type::shape_type; - - template - xfunction_stepper(const xfunction_type* func, It&&... it) noexcept; - - void step(size_type dim); - void step_back(size_type dim); - void step(size_type dim, size_type n); - void step_back(size_type dim, size_type n); - void reset(size_type dim); - void reset_back(size_type dim); - - void to_begin(); - void to_end(layout_type l); - - reference operator*() const; - - template - ST step_simd(); - - value_type step_leading(); - - private: - - template - reference deref_impl(std::index_sequence) const; - - template - ST step_simd_impl(std::index_sequence); - - template - value_type step_leading_impl(std::index_sequence); - - const xfunction_type* p_f; - std::tuple::const_stepper...> m_it; - }; - - /************* - * xfunction * - *************/ - - /** - * @class xfunction - * @brief Multidimensional function operating on - * xtensor expressions. - * - * The xfunction class implements a multidimensional function - * operating on xtensor expressions. - * - * @tparam F the function type - * @tparam R the return type of the function - * @tparam CT the closure types for arguments of the function - */ - template - class xfunction : public xfunction_base, - public xexpression> - { - public: - - using self_type = xfunction; - using base_type = xfunction_base; - - template , self_type>::value>> - xfunction(Func&& f, CTA&&... e) noexcept; - - ~xfunction() = default; - - xfunction(const xfunction&) = default; - xfunction& operator=(const xfunction&) = default; - - xfunction(xfunction&&) = default; - xfunction& operator=(xfunction&&) = default; - }; - - /********************************* - * xfunction_base implementation * - *********************************/ - - /** - * @name Constructor - */ - //@{ - /** - * Constructs an xfunction_base applying the specified function to the given - * arguments. - * @param f the function to apply - * @param e the \ref xexpression arguments - */ - template - template - inline xfunction_base::xfunction_base(Func&& f, CTA&&... e) noexcept - : m_e(std::forward(e)...), m_f(std::forward(f)), m_shape(xtl::make_sequence(0, size_type(0))), - m_shape_computed(false) - { - } - //@} - - /** - * @name Size and shape - */ - //@{ - /** - * Returns the size of the expression. - */ - template - inline auto xfunction_base::size() const noexcept -> size_type - { - return compute_size(shape()); - } - - /** - * Returns the number of dimensions of the function. - */ - template - inline auto xfunction_base::dimension() const noexcept -> size_type - { - size_type dimension = m_shape_computed ? m_shape.size() : compute_dimension(); - return dimension; - } - - /** - * Returns the shape of the xfunction. - */ - template - inline auto xfunction_base::shape() const -> const shape_type& - { - if (!m_shape_computed) - { - m_shape = xtl::make_sequence(compute_dimension(), size_type(0)); - m_shape_trivial = broadcast_shape(m_shape, false); - m_shape_computed = true; - } - return m_shape; - } - - /** - * Returns the layout_type of the xfunction. - */ - template - inline layout_type xfunction_base::layout() const noexcept - { - return layout_impl(std::make_index_sequence()); - } - //@} - - /** - * @name Data - */ - /** - * Returns a constant reference to the element at the specified position in the function. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the function. - */ - template - template - inline auto xfunction_base::operator()(Args... args) const -> const_reference - { - // The static cast prevents the compiler from instantiating the template methods with signed integers, - // leading to warning about signed/unsigned conversions in the deeper layers of the access methods - return access_impl(std::make_index_sequence(), static_cast(args)...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the expression. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xfunction_base::at(Args... args) const -> const_reference - { - check_access(shape(), static_cast(args)...); - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the expression. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the expression, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xfunction_base::unchecked(Args... args) const -> const_reference - { - // The static cast prevents the compiler from instantiating the template methods with signed integers, - // leading to warning about signed/unsigned conversions in the deeper layers of the access methods - return unchecked_impl(std::make_index_sequence(), static_cast(args)...); - } - - template - template - inline auto xfunction_base::operator[](const S& index) const - -> disable_integral_t - { - return element(index.cbegin(), index.cend()); - } - - template - template - inline auto xfunction_base::operator[](std::initializer_list index) const -> const_reference - { - return element(index.begin(), index.end()); - } - - template - inline auto xfunction_base::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the function. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xfunction_base::element(It first, It last) const -> const_reference - { - return element_access_impl(std::make_index_sequence(), first, last); - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the function to the specified parameter. - * @param shape the result shape - * @param reuse_cache boolean for reusing a previously computed shape - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xfunction_base::broadcast_shape(S& shape, bool reuse_cache) const - { - if (reuse_cache && m_shape_computed) - { - std::copy(m_shape.cbegin(), m_shape.cend(), shape.begin()); - return m_shape_trivial; - } - else - { - // e.broadcast_shape must be evaluated even if b is false - auto func = [&shape](bool b, auto&& e) { return e.broadcast_shape(shape) && b; }; - return accumulate(func, true, m_e); - } - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xfunction_base::is_trivial_broadcast(const S& strides) const noexcept - { - auto func = [&strides](bool b, auto&& e) { return b && e.is_trivial_broadcast(strides); }; - return accumulate(func, true, m_e); - } - //@} - - template - template - inline auto xfunction_base::storage_begin() const noexcept -> const_storage_iterator - { - return storage_cbegin(); - } - - template - template - inline auto xfunction_base::storage_end() const noexcept -> const_storage_iterator - { - return storage_cend(); - } - - template - template - inline auto xfunction_base::storage_cbegin() const noexcept -> const_storage_iterator - { - auto f = [](const auto& e) noexcept { return detail::trivial_begin(e); }; - return build_iterator(f, std::make_index_sequence()); - } - - template - template - inline auto xfunction_base::storage_cend() const noexcept -> const_storage_iterator - { - auto f = [](const auto& e) noexcept { return detail::trivial_end(e); }; - return build_iterator(f, std::make_index_sequence()); - } - - template - template - inline auto xfunction_base::storage_rbegin() const noexcept -> const_reverse_storage_iterator - { - return storage_crbegin(); - } - - template - template - inline auto xfunction_base::storage_rend() const noexcept -> const_reverse_storage_iterator - { - return storage_crend(); - } - - template - template - inline auto xfunction_base::storage_crbegin() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(storage_cend()); - } - - template - template - inline auto xfunction_base::storage_crend() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(storage_cbegin()); - } - - template - template - inline auto xfunction_base::stepper_begin(const S& shape) const noexcept -> const_stepper - { - auto f = [&shape](const auto& e) noexcept { return e.stepper_begin(shape); }; - return build_stepper(f, std::make_index_sequence()); - } - - template - template - inline auto xfunction_base::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - auto f = [&shape, l](const auto& e) noexcept { return e.stepper_end(shape, l); }; - return build_stepper(f, std::make_index_sequence()); - } - - template - inline auto xfunction_base::data_element(size_type i) const -> const_reference - { - return data_element_impl(std::make_index_sequence(), i); - } - - template - template - inline xfunction_base::operator value_type() const - { - return operator()(); - } - - template - template - inline auto xfunction_base::load_simd(size_type i) const -> detail::simd_return_type_t - { - return load_simd_impl(std::make_index_sequence(), i); - } - - template - inline auto xfunction_base::arguments() const noexcept -> const tuple_type& - { - return m_e; - } - - template - template - inline layout_type xfunction_base::layout_impl(std::index_sequence) const noexcept - { - return compute_layout(std::get(m_e).layout()...); - } - - template - template - inline auto xfunction_base::access_impl(std::index_sequence, Args... args) const -> const_reference - { - XTENSOR_TRY(check_index(shape(), args...)); - XTENSOR_CHECK_DIMENSION(shape(), args...); - return m_f(std::get(m_e)(args...)...); - } - - template - template - inline auto xfunction_base::unchecked_impl(std::index_sequence, Args... args) const -> const_reference - { - return m_f(std::get(m_e).unchecked(args...)...); - } - - template - template - inline auto xfunction_base::element_access_impl(std::index_sequence, It first, It last) const -> const_reference - { - XTENSOR_TRY(check_element_index(shape(), first, last)); - return m_f((std::get(m_e).element(first, last))...); - } - - template - template - inline auto xfunction_base::data_element_impl(std::index_sequence, size_type i) const -> const_reference - { - return m_f((std::get(m_e).data_element(i))...); - } - - namespace detail - { -// TODO: add traits for batch_bool in xsimd and remove this ugly hack - - template - struct is_batch_bool - { - static constexpr bool value = false; - }; - -#ifdef XTENSOR_USE_XSIMD - template - struct is_batch_bool> - { - static constexpr bool value = true; - }; -#endif - - // This metafunction avoids loading boolean values as batches of floating points and - // reciprocally. However, we cannot always load data as batches of their scalar type - // since this prevents mixed arithmetic. - template - struct get_simd_type - { - using simd_value_type = typename std::decay_t::simd_value_type; - static constexpr bool is_arg_bool = is_batch_bool::value; - static constexpr bool is_res_bool = is_batch_bool::value; - using type = std::conditional_t>; - }; - - template - using get_simd_type_t = typename get_simd_type::type; - } - - template - template - inline auto xfunction_base::load_simd_impl(std::index_sequence, size_type i) const - { - return m_f.simd_apply((std::get(m_e) - .template load_simd, simd, simd_argument_type>>(i))...); - } - - template - template - inline auto xfunction_base::build_stepper(Func&& f, std::index_sequence) const noexcept -> const_stepper - { - return const_stepper(this, f(std::get(m_e))...); - } - - template - template - inline auto xfunction_base::build_iterator(Func&& f, std::index_sequence) const noexcept -> const_storage_iterator - { - return const_storage_iterator(this, f(std::get(m_e))...); - } - - template - inline auto xfunction_base::compute_dimension() const noexcept -> size_type - { - auto func = [](size_type d, auto&& e) noexcept { return (std::max)(d, e.dimension()); }; - return accumulate(func, size_type(0), m_e); - } - - /************************************* - * xfunction_iterator implementation * - *************************************/ - - template - template - inline xfunction_iterator::xfunction_iterator(const xfunction_type* func, It&&... it) noexcept - : p_f(func), m_it(std::forward(it)...) - { - } - - template - inline auto xfunction_iterator::operator++() -> self_type& - { - auto f = [](auto& it) { ++it; }; - for_each(f, m_it); - return *this; - } - - template - inline auto xfunction_iterator::operator--() -> self_type& - { - auto f = [](auto& it) { return --it; }; - for_each(f, m_it); - return *this; - } - - template - inline auto xfunction_iterator::operator+=(difference_type n) -> self_type& - { - auto f = [n](auto& it) { it += n; }; - for_each(f, m_it); - return *this; - } - - template - inline auto xfunction_iterator::operator-=(difference_type n) -> self_type& - { - auto f = [n](auto& it) { it -= n; }; - for_each(f, m_it); - return *this; - } - - template - inline auto xfunction_iterator::operator-(const self_type& rhs) const -> difference_type - { - return tuple_max_diff(std::make_index_sequence(), m_it, rhs.m_it); - } - - template - inline auto xfunction_iterator::operator*() const -> reference - { - return deref_impl(std::make_index_sequence()); - } - - template - inline bool xfunction_iterator::equal(const self_type& rhs) const - { - return p_f == rhs.p_f && m_it == rhs.m_it; - } - - template - inline bool xfunction_iterator::less_than(const self_type& rhs) const - { - return p_f == rhs.p_f && m_it < rhs.m_it; - } - - template - template - inline auto xfunction_iterator::deref_impl(std::index_sequence) const -> reference - { - return (p_f->m_f)(*std::get(m_it)...); - } - - template - template - inline auto xfunction_iterator::tuple_max_diff(std::index_sequence, - const data_type& lhs, - const data_type& rhs) const -> difference_type - { - auto diff = std::make_tuple((std::get(lhs) - std::get(rhs))...); - auto func = [](difference_type n, auto&& v) { return (std::max)(n, v); }; - return accumulate(func, difference_type(0), diff); - } - - template - inline bool operator==(const xfunction_iterator& it1, - const xfunction_iterator& it2) - { - return it1.equal(it2); - } - - template - inline bool operator<(const xfunction_iterator& it1, - const xfunction_iterator& it2) - { - return it1.less_than(it2); - } - - /************************************ - * xfunction_stepper implementation * - ************************************/ - - template - template - inline xfunction_stepper::xfunction_stepper(const xfunction_type* func, It&&... it) noexcept - : p_f(func), m_it(std::forward(it)...) - { - } - - template - inline void xfunction_stepper::step(size_type dim) - { - auto f = [dim](auto& it) { it.step(dim); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::step_back(size_type dim) - { - auto f = [dim](auto& it) { it.step_back(dim); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::step(size_type dim, size_type n) - { - auto f = [dim, n](auto& it) { it.step(dim, n); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::step_back(size_type dim, size_type n) - { - auto f = [dim, n](auto& it) { it.step_back(dim, n); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::reset(size_type dim) - { - auto f = [dim](auto& it) { it.reset(dim); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::reset_back(size_type dim) - { - auto f = [dim](auto& it) { it.reset_back(dim); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::to_begin() - { - auto f = [](auto& it) { it.to_begin(); }; - for_each(f, m_it); - } - - template - inline void xfunction_stepper::to_end(layout_type l) - { - auto f = [l](auto& it) { it.to_end(l); }; - for_each(f, m_it); - } - - template - inline auto xfunction_stepper::operator*() const -> reference - { - return deref_impl(std::make_index_sequence()); - } - - template - template - inline auto xfunction_stepper::deref_impl(std::index_sequence) const -> reference - { - return (p_f->m_f)(*std::get(m_it)...); - } - - template - template - inline ST xfunction_stepper::step_simd_impl(std::index_sequence) - { - return (p_f->m_f.simd_apply)(std::get(m_it).template - step_simd, ST, typename xfunction_type::simd_argument_type>>()...); - } - - template - template - inline ST xfunction_stepper::step_simd() - { - return step_simd_impl(std::make_index_sequence()); - } - - template - template - inline auto xfunction_stepper::step_leading_impl(std::index_sequence) - -> value_type - { - return (p_f->m_f)(std::get(m_it).step_leading()...); - } - - template - inline auto xfunction_stepper::step_leading() - -> value_type - { - return step_leading_impl(std::make_index_sequence()); - } - - /**************************** - * xfunction implementation * - ****************************/ - - /** - * Constructs an xfunction applying the specified function to the given - * arguments. - * @param f the function to apply - * @param e the \ref xexpression arguments - */ - template - template - xfunction::xfunction(Func&& f, CTA&&... e) noexcept - : base_type(std::forward(f), std::forward(e)...) - { - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xfunctor_view.hpp b/vendor/xtensor/include/xtensor/xfunctor_view.hpp deleted file mode 100644 index 6cba79575..000000000 --- a/vendor/xtensor/include/xtensor/xfunctor_view.hpp +++ /dev/null @@ -1,1349 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_FUNCTOR_VIEW_HPP -#define XTENSOR_FUNCTOR_VIEW_HPP - -#include -#include -#include -#include -#include - -#include - -#include "xtensor/xexpression.hpp" -#include "xtensor/xiterator.hpp" -#include "xtensor/xsemantic.hpp" -#include "xtensor/xutils.hpp" - -#include "xtensor/xarray.hpp" -#include "xtensor/xtensor.hpp" - -namespace xt -{ - - /***************************** - * xfunctor_view declaration * - *****************************/ - - template - class xfunctor_iterator; - - template - class xfunctor_stepper; - - template - class xfunctor_view; - - /******************************** - * xfunctor_view_temporary_type * - ********************************/ - - namespace detail - { - template - struct functorview_temporary_type_impl - { - using type = xarray; - }; - - template - struct functorview_temporary_type_impl, L> - { - using type = xtensor; - }; - } - - template - struct xfunctor_view_temporary_type - { - using type = typename detail::functorview_temporary_type_impl::type; - }; - - template - struct xcontainer_inner_types> - { - using xexpression_type = std::decay_t; - using temporary_type = typename xfunctor_view_temporary_type::type; - }; - -#define DL XTENSOR_DEFAULT_LAYOUT - /** - * @class xfunctor_view - * @brief View of an xexpression . - * - * The xfunctor_view class is an expression addressing its elements by applying a functor to the - * corresponding element of an underlying expression. Unlike e.g. xgenerator, an xfunctor_view is - * an lvalue. It is used e.g. to access real and imaginary parts of complex expressions. - * - * xfunctor_view is not meant to be used directly, but through helper functions such - * as \ref real or \ref imag. - * - * @tparam F the functor type to be applied to the elements of specified expression. - * @tparam CT the closure type of the \ref xexpression type underlying this view - * - * @sa real, imag - */ - template - class xfunctor_view : public xview_semantic> - { - public: - - using self_type = xfunctor_view; - using xexpression_type = std::decay_t; - using semantic_base = xview_semantic; - using functor_type = typename std::decay_t; - - using value_type = typename functor_type::value_type; - using reference = typename functor_type::reference; - using const_reference = typename functor_type::const_reference; - using pointer = typename functor_type::pointer; - using const_pointer = typename functor_type::const_pointer; - using size_type = typename xexpression_type::size_type; - using difference_type = typename xexpression_type::difference_type; - - using shape_type = typename xexpression_type::shape_type; - - static constexpr layout_type static_layout = xexpression_type::static_layout; - static constexpr bool contiguous_layout = false; - - using stepper = xfunctor_stepper; - using const_stepper = xfunctor_stepper; - - template - using layout_iterator = xfunctor_iterator>; - template - using const_layout_iterator = xfunctor_iterator>; - - template - using reverse_layout_iterator = xfunctor_iterator>; - template - using const_reverse_layout_iterator = xfunctor_iterator>; - - template - using broadcast_iterator = xfunctor_iterator>; - template - using const_broadcast_iterator = xfunctor_iterator>; - - template - using reverse_broadcast_iterator = xfunctor_iterator>; - template - using const_reverse_broadcast_iterator = xfunctor_iterator>; - - using storage_iterator = xfunctor_iterator; - using const_storage_iterator = xfunctor_iterator; - using reverse_storage_iterator = xfunctor_iterator; - using const_reverse_storage_iterator = xfunctor_iterator; - - using iterator = xfunctor_iterator; - using const_iterator = xfunctor_iterator; - using reverse_iterator = xfunctor_iterator; - using const_reverse_iterator = xfunctor_iterator; - - explicit xfunctor_view(CT) noexcept; - - template - xfunctor_view(Func&&, E&&) noexcept; - - template - self_type& operator=(const xexpression& e); - - template - disable_xexpression& operator=(const E& e); - - size_type size() const noexcept; - size_type dimension() const noexcept; - const shape_type& shape() const noexcept; - layout_type layout() const noexcept; - - template - reference operator()(Args... args); - - template - reference at(Args... args); - - template - reference unchecked(Args... args); - - template - disable_integral_t operator[](const S& index); - template - reference operator[](std::initializer_list index); - reference operator[](size_type i); - - template - reference element(IT first, IT last); - - template - const_reference operator()(Args... args) const; - - template - const_reference unchecked(Args... args) const; - - template - const_reference at(Args... args) const; - - template - disable_integral_t operator[](const S& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - const_reference element(IT first, IT last) const; - - template - bool broadcast_shape(S& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const S& strides) const; - - template - auto begin() noexcept; - template - auto end() noexcept; - - template - auto begin() const noexcept; - template - auto end() const noexcept; - template - auto cbegin() const noexcept; - template - auto cend() const noexcept; - - template - auto rbegin() noexcept; - template - auto rend() noexcept; - - template - auto rbegin() const noexcept; - template - auto rend() const noexcept; - template - auto crbegin() const noexcept; - template - auto crend() const noexcept; - - template - broadcast_iterator begin(const S& shape) noexcept; - template - broadcast_iterator end(const S& shape) noexcept; - - template - const_broadcast_iterator begin(const S& shape) const noexcept; - template - const_broadcast_iterator end(const S& shape) const noexcept; - template - const_broadcast_iterator cbegin(const S& shape) const noexcept; - template - const_broadcast_iterator cend(const S& shape) const noexcept; - - template - reverse_broadcast_iterator rbegin(const S& shape) noexcept; - template - reverse_broadcast_iterator rend(const S& shape) noexcept; - - template - const_reverse_broadcast_iterator rbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator rend(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crend(const S& shape) const noexcept; - - template - storage_iterator storage_begin() noexcept; - template - storage_iterator storage_end() noexcept; - - template - const_storage_iterator storage_begin() const noexcept; - template - const_storage_iterator storage_end() const noexcept; - template - const_storage_iterator storage_cbegin() const noexcept; - template - const_storage_iterator storage_cend() const noexcept; - - template - reverse_storage_iterator storage_rbegin() noexcept; - template - reverse_storage_iterator storage_rend() noexcept; - - template - const_reverse_storage_iterator storage_rbegin() const noexcept; - template - const_reverse_storage_iterator storage_rend() const noexcept; - template - const_reverse_storage_iterator storage_crbegin() const noexcept; - template - const_reverse_storage_iterator storage_crend() const noexcept; - - template - stepper stepper_begin(const S& shape) noexcept; - template - stepper stepper_end(const S& shape, layout_type l) noexcept; - template - const_stepper stepper_begin(const S& shape) const noexcept; - template - const_stepper stepper_end(const S& shape, layout_type l) const noexcept; - - private: - - CT m_e; - functor_type m_functor; - - using temporary_type = typename xcontainer_inner_types::temporary_type; - void assign_temporary_impl(temporary_type&& tmp); - friend class xview_semantic>; - }; - -#undef DL - - /********************************* - * xfunctor_iterator declaration * - *********************************/ - - template - class xfunctor_iterator : public xtl::xrandom_access_iterator_base, - typename F::value_type, - typename std::iterator_traits::difference_type, - typename xtl::xproxy_wrapper()(*(IT())))>::pointer, - xtl::xproxy_wrapper()(*(IT())))>> - { - public: - - using functor_type = std::decay_t; - using subiterator_traits = std::iterator_traits; - - using value_type = typename functor_type::value_type; - using reference = xtl::xproxy_wrapper()(*(IT())))>; - using pointer = typename reference::pointer; - using difference_type = typename subiterator_traits::difference_type; - using iterator_category = typename subiterator_traits::iterator_category; - - using self_type = xfunctor_iterator; - - xfunctor_iterator(const IT&, const functor_type*); - - self_type& operator++(); - self_type& operator--(); - - self_type& operator+=(difference_type n); - self_type& operator-=(difference_type n); - - difference_type operator-(xfunctor_iterator rhs) const; - - reference operator*() const; - pointer operator->() const; - - bool equal(const xfunctor_iterator& rhs) const; - bool less_than(const xfunctor_iterator& rhs) const; - - private: - - IT m_it; - const functor_type* p_functor; - }; - - template - bool operator==(const xfunctor_iterator& lhs, - const xfunctor_iterator& rhs); - - template - bool operator<(const xfunctor_iterator& lhs, - const xfunctor_iterator& rhs); - - /******************************** - * xfunctor_stepper declaration * - ********************************/ - - template - class xfunctor_stepper - { - public: - - using functor_type = std::decay_t; - - using value_type = typename functor_type::value_type; - using reference = apply_cv_t; - using pointer = std::remove_reference_t*; - using size_type = typename ST::size_type; - using difference_type = typename ST::difference_type; - - xfunctor_stepper() = default; - xfunctor_stepper(const ST&, const functor_type*); - - reference operator*() const; - - void step(size_type dim); - void step_back(size_type dim); - void step(size_type dim, size_type n); - void step_back(size_type dim, size_type n); - void reset(size_type dim); - void reset_back(size_type dim); - - void to_begin(); - void to_end(layout_type); - - private: - - ST m_stepper; - const functor_type* p_functor; - }; - - /******************************** - * xfunctor_view implementation * - ********************************/ - - /** - * @name Constructors - */ - //@{ - - /** - * Constructs an xfunctor_view expression wrappering the specified \ref xexpression. - * - * @param e the underlying expression - */ - template - inline xfunctor_view::xfunctor_view(CT e) noexcept - : m_e(e), m_functor(functor_type()) - { - } - - /** - * Constructs an xfunctor_view expression wrappering the specified \ref xexpression. - * - * @param func the functor to be applied to the elements of the underlying expression. - * @param e the underlying expression - */ - template - template - inline xfunctor_view::xfunctor_view(Func&& func, E&& e) noexcept - : m_e(std::forward(e)), m_functor(std::forward(func)) - { - } - //@} - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended assignment operator. - */ - template - template - inline auto xfunctor_view::operator=(const xexpression& e) -> self_type& - { - bool cond = (e.derived_cast().shape().size() == dimension()) && std::equal(shape().begin(), shape().end(), e.derived_cast().shape().begin()); - if (!cond) - { - semantic_base::operator=(broadcast(e.derived_cast(), shape())); - } - else - { - semantic_base::operator=(e); - } - return *this; - } - //@} - - template - template - inline auto xfunctor_view::operator=(const E& e) -> disable_xexpression& - { - std::fill(begin(), end(), e); - return *this; - } - - template - inline void xfunctor_view::assign_temporary_impl(temporary_type&& tmp) - { - std::copy(tmp.cbegin(), tmp.cend(), begin()); - } - - /** - * @name Size and shape - */ - /** - * Returns the size of the expression. - */ - template - inline auto xfunctor_view::size() const noexcept -> size_type - { - return m_e.size(); - } - - /** - * Returns the number of dimensions of the expression. - */ - template - inline auto xfunctor_view::dimension() const noexcept -> size_type - { - return m_e.dimension(); - } - - /** - * Returns the shape of the expression. - */ - template - inline auto xfunctor_view::shape() const noexcept -> const shape_type& - { - return m_e.shape(); - } - - /** - * Returns the layout_type of the expression. - */ - template - inline layout_type xfunctor_view::layout() const noexcept - { - return m_e.layout(); - } - //@} - - /** - * @name Data - */ - /** - * Returns a reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the expression. - */ - template - template - inline auto xfunctor_view::operator()(Args... args) -> reference - { - XTENSOR_TRY(check_index(shape(), args...)); - XTENSOR_CHECK_DIMENSION(shape(), args...); - return m_functor(m_e(args...)); - } - - /** - * Returns a reference to the element at the specified position in the expression, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the expression. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xfunctor_view::at(Args... args) -> reference - { - check_access(shape(), args...); - return this->operator()(args...); - } - - /** - * Returns a reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the expression. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the expression, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xfunctor_view::unchecked(Args... args) -> reference - { - return m_functor(m_e.unchecked(args...)); - } - - /** - * Returns a reference to the element at the specified position in the expression. - * @param index a sequence of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices in the sequence should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xfunctor_view::operator[](const S& index) - -> disable_integral_t - { - return m_functor(m_e[index]); - } - - template - template - inline auto xfunctor_view::operator[](std::initializer_list index) - -> reference - { - return m_functor(m_e[index]); - } - - template - inline auto xfunctor_view::operator[](size_type i) -> reference - { - return operator()(i); - } - - /** - * Returns a reference to the element at the specified position in the expression. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the function. - */ - template - template - inline auto xfunctor_view::element(IT first, IT last) -> reference - { - XTENSOR_TRY(check_element_index(shape(), first, last)); - return m_functor(m_e.element(first, last)); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the expression. - */ - template - template - inline auto xfunctor_view::operator()(Args... args) const -> const_reference - { - XTENSOR_TRY(check_index(shape(), args...)); - XTENSOR_CHECK_DIMENSION(shape(), args...); - return m_functor(m_e(args...)); - } - - /** - * Returns a constant reference to the element at the specified position in the expression, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the expression. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xfunctor_view::at(Args... args) const -> const_reference - { - check_access(shape(), args...); - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the expression. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the expression, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xfunctor_view::unchecked(Args... args) const -> const_reference - { - return m_functor(m_e.unchecked(args...)); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param index a sequence of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices in the sequence should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xfunctor_view::operator[](const S& index) const - -> disable_integral_t - { - return m_functor(m_e[index]); - } - - template - template - inline auto xfunctor_view::operator[](std::initializer_list index) const - -> const_reference - { - return m_functor(m_e[index]); - } - - template - inline auto xfunctor_view::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the function. - */ - template - template - inline auto xfunctor_view::element(IT first, IT last) const -> const_reference - { - XTENSOR_TRY(check_element_index(shape(), first, last)); - return m_functor(m_e.element(first, last)); - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the function to the specified parameter. - * @param shape the result shape - * @param reuse_cache boolean for reusing a previously computed shape - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xfunctor_view::broadcast_shape(S& shape, bool reuse_cache) const - { - return m_e.broadcast_shape(shape, reuse_cache); - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xfunctor_view::is_trivial_broadcast(const S& strides) const - { - return m_e.is_trivial_broadcast(strides); - } - //@} - - /** - * @name Iterators - */ - //@{ - /** - * Returns an iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::begin() noexcept - { - return xfunctor_iterator())> - (m_e.template begin(), &m_functor); - } - - /** - * Returns an iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::end() noexcept - { - return xfunctor_iterator())> - (m_e.template end(), &m_functor); - } - - /** - * Returns a constant iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::begin() const noexcept - { - return this->template cbegin(); - } - - /** - * Returns a constant iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::end() const noexcept - { - return this->template cend(); - } - - /** - * Returns a constant iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::cbegin() const noexcept - { - return xfunctor_iterator())> - (m_e.template cbegin(), &m_functor); - } - - /** - * Returns a constant iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::cend() const noexcept - { - return xfunctor_iterator())> - (m_e.template cend(), &m_functor); - } - //@} - - /** - * @name Broadcast iterators - */ - //@{ - /** - * Returns a constant iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::begin(const S& shape) noexcept -> broadcast_iterator - { - return broadcast_iterator(m_e.template begin(shape), &m_functor); - } - - /** - * Returns a constant iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::end(const S& shape) noexcept -> broadcast_iterator - { - return broadcast_iterator(m_e.template end(shape), &m_functor); - } - - /** - * Returns a constant iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::begin(const S& shape) const noexcept -> const_broadcast_iterator - { - return cbegin(shape); - } - - /** - * Returns a constant iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::end(const S& shape) const noexcept -> const_broadcast_iterator - { - return cend(shape); - } - - /** - * Returns a constant iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::cbegin(const S& shape) const noexcept -> const_broadcast_iterator - { - return const_broadcast_iterator(m_e.template cbegin(shape), &m_functor); - } - - /** - * Returns a constant iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::cend(const S& shape) const noexcept -> const_broadcast_iterator - { - return const_broadcast_iterator(m_e.template cend(shape), &m_functor); - } - //@} - - /** - * @name Reverse iterators - */ - //@{ - /** - * Returns an iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rbegin() noexcept - { - return xfunctor_iterator())> - (m_e.template rbegin(), &m_functor); - } - - /** - * Returns an iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rend() noexcept - { - return xfunctor_iterator())> - (m_e.template rend(), &m_functor); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rbegin() const noexcept - { - return this->template crbegin(); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rend() const noexcept - { - return this->template crend(); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::crbegin() const noexcept - { - return xfunctor_iterator())> - (m_e.template rbegin(), &m_functor); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::crend() const noexcept - { - return xfunctor_iterator())> - (m_e.template rend(), &m_functor); - } - //@} - - /** - * @name Reverse broadcast iterators - */ - /** - * Returns an iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator - { - return reverse_broadcast_iterator(m_e.template rbegin(shape), &m_functor); - } - - /** - * Returns an iterator to the element following the last element of the - * reversed expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rend(const S& shape) noexcept -> reverse_broadcast_iterator - { - return reverse_broadcast_iterator(m_e.template rend(shape), &m_functor); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return crbegin(shape); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::rend(const S& /*shape*/) const noexcept -> const_reverse_broadcast_iterator - { - return crend(); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::crbegin(const S& /*shape*/) const noexcept -> const_reverse_broadcast_iterator - { - return const_reverse_broadcast_iterator(m_e.template crbegin(), &m_functor); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xfunctor_view::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return const_reverse_broadcast_iterator(m_e.template crend(shape), &m_functor); - } - //@} - - template - template - inline auto xfunctor_view::storage_begin() noexcept -> storage_iterator - { - return storage_iterator(m_e.template storage_begin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_end() noexcept -> storage_iterator - { - return storage_iterator(m_e.template storage_end(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_begin() const noexcept -> const_storage_iterator - { - return const_storage_iterator(m_e.template storage_begin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_end() const noexcept -> const_storage_iterator - { - return const_storage_iterator(m_e.template storage_end(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_cbegin() const noexcept -> const_storage_iterator - { - return const_storage_iterator(m_e.template storage_cbegin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_cend() const noexcept -> const_storage_iterator - { - return const_storage_iterator(m_e.template storage_cend(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_rbegin() noexcept -> reverse_storage_iterator - { - return reverse_storage_iterator(m_e.template storage_rbegin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_rend() noexcept -> reverse_storage_iterator - { - return reverse_storage_iterator(m_e.template storage_rend(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_rbegin() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(m_e.template storage_rbegin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_rend() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(m_e.template storage_rend(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_crbegin() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(m_e.template storage_crbegin(), &m_functor); - } - - template - template - inline auto xfunctor_view::storage_crend() const noexcept -> const_reverse_storage_iterator - { - return const_reverse_storage_iterator(m_e.template storage_crend(), &m_functor); - } - - /*************** - * stepper api * - ***************/ - - template - template - inline auto xfunctor_view::stepper_begin(const S& shape) noexcept -> stepper - { - return stepper(m_e.stepper_begin(shape), &m_functor); - } - - template - template - inline auto xfunctor_view::stepper_end(const S& shape, layout_type l) noexcept -> stepper - { - return stepper(m_e.stepper_end(shape, l), &m_functor); - } - - template - template - inline auto xfunctor_view::stepper_begin(const S& shape) const noexcept -> const_stepper - { - const xexpression_type& const_m_e = m_e; - return const_stepper(const_m_e.stepper_begin(shape), &m_functor); - } - - template - template - inline auto xfunctor_view::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - const xexpression_type& const_m_e = m_e; - return const_stepper(const_m_e.stepper_end(shape, l), &m_functor); - } - - /************************************ - * xfunctor_iterator implementation * - ************************************/ - - template - xfunctor_iterator::xfunctor_iterator(const IT& it, const functor_type* pf) - : m_it(it), p_functor(pf) - { - } - - template - inline auto xfunctor_iterator::operator++() -> self_type& - { - ++m_it; - return *this; - } - - template - inline auto xfunctor_iterator::operator--() -> self_type& - { - --m_it; - return *this; - } - - template - inline auto xfunctor_iterator::operator+=(difference_type n) -> self_type& - { - m_it += n; - return *this; - } - - template - inline auto xfunctor_iterator::operator-=(difference_type n) -> self_type& - { - m_it -= n; - return *this; - } - - template - inline auto xfunctor_iterator::operator-(xfunctor_iterator rhs) const -> difference_type - { - return m_it - rhs.m_it; - } - - template - auto xfunctor_iterator::operator*() const -> reference - { - return xtl::proxy_wrapper((*p_functor)(*m_it)); - } - - template - auto xfunctor_iterator::operator->() const -> pointer - { - return &(operator*()); - } - - template - auto xfunctor_iterator::equal(const xfunctor_iterator& rhs) const -> bool - { - return m_it == rhs.m_it; - } - - template - auto xfunctor_iterator::less_than(const xfunctor_iterator& rhs) const -> bool - { - return m_it < rhs.m_it; - } - - template - bool operator==(const xfunctor_iterator& lhs, - const xfunctor_iterator& rhs) - { - return lhs.equal(rhs); - } - - template - bool operator<(const xfunctor_iterator& lhs, - const xfunctor_iterator& rhs) - { - return !lhs.less_than(rhs); - } - - /*********************************** - * xfunctor_stepper implementation * - ***********************************/ - - template - xfunctor_stepper::xfunctor_stepper(const ST& stepper, const functor_type* pf) - : m_stepper(stepper), p_functor(pf) - { - } - - template - auto xfunctor_stepper::operator*() const -> reference - { - return (*p_functor)(*m_stepper); - } - - template - void xfunctor_stepper::step(size_type dim) - { - m_stepper.step(dim); - } - - template - void xfunctor_stepper::step_back(size_type dim) - { - m_stepper.step_back(dim); - } - - template - void xfunctor_stepper::step(size_type dim, size_type n) - { - m_stepper.step(dim, n); - } - - template - void xfunctor_stepper::step_back(size_type dim, size_type n) - { - m_stepper.step_back(dim, n); - } - - template - void xfunctor_stepper::reset(size_type dim) - { - m_stepper.reset(dim); - } - - template - void xfunctor_stepper::reset_back(size_type dim) - { - m_stepper.reset_back(dim); - } - - template - void xfunctor_stepper::to_begin() - { - m_stepper.to_begin(); - } - - template - void xfunctor_stepper::to_end(layout_type l) - { - m_stepper.to_end(l); - } -} -#endif diff --git a/vendor/xtensor/include/xtensor/xgenerator.hpp b/vendor/xtensor/include/xtensor/xgenerator.hpp deleted file mode 100644 index f1118fe43..000000000 --- a/vendor/xtensor/include/xtensor/xgenerator.hpp +++ /dev/null @@ -1,401 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_GENERATOR_HPP -#define XTENSOR_GENERATOR_HPP - -#include -#include -#include -#include -#include -#include - -#include - -#include "xexpression.hpp" -#include "xiterable.hpp" -#include "xstrides.hpp" -#include "xutils.hpp" - -namespace xt -{ - - /************** - * xgenerator * - **************/ - - template - class xgenerator; - - template - struct xiterable_inner_types> - { - using inner_shape_type = S; - using const_stepper = xindexed_stepper, true>; - using stepper = const_stepper; - }; - - /** - * @class xgenerator - * @brief Multidimensional function operating on indices. - * - * The xgenerator class implements a multidimensional function, - * generating a value from the supplied indices. - * - * @tparam F the function type - * @tparam R the return type of the function - * @tparam S the shape type of the generator - */ - template - class xgenerator : public xexpression>, - public xconst_iterable> - { - public: - - using self_type = xgenerator; - using functor_type = typename std::remove_reference::type; - - using value_type = R; - using reference = value_type; - using const_reference = value_type; - using pointer = value_type*; - using const_pointer = const value_type*; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - using iterable_base = xconst_iterable; - using inner_shape_type = typename iterable_base::inner_shape_type; - using shape_type = inner_shape_type; - using strides_type = S; - - using stepper = typename iterable_base::stepper; - using const_stepper = typename iterable_base::const_stepper; - - static constexpr layout_type static_layout = layout_type::any; - static constexpr bool contiguous_layout = false; - - template - xgenerator(Func&& f, const S& shape) noexcept; - - size_type size() const noexcept; - size_type dimension() const noexcept; - const inner_shape_type& shape() const noexcept; - layout_type layout() const noexcept; - - template - const_reference operator()(Args... args) const; - template - const_reference at(Args... args) const; - template - const_reference unchecked(Args... args) const; - template - disable_integral_t operator[](const OS& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - const_reference element(It first, It last) const; - - template - bool broadcast_shape(O& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const O& /*strides*/) const noexcept; - - template - const_stepper stepper_begin(const O& shape) const noexcept; - template - const_stepper stepper_end(const O& shape, layout_type) const noexcept; - - template ::value>> - void assign_to(xexpression& e) const noexcept; - - private: - - template - void adapt_index() const; - - template - void adapt_index(I& arg, Args&... args) const; - - functor_type m_f; - inner_shape_type m_shape; - }; - - /***************************** - * xgenerator implementation * - *****************************/ - - /** - * @name Constructor - */ - //@{ - /** - * Constructs an xgenerator applying the specified function over the - * given shape. - * @param f the function to apply - * @param shape the shape of the xgenerator - */ - template - template - inline xgenerator::xgenerator(Func&& f, const S& shape) noexcept - : m_f(std::forward(f)), m_shape(shape) - { - } - //@} - - /** - * @name Size and shape - */ - //@{ - /** - * Returns the size of the expression. - */ - template - inline auto xgenerator::size() const noexcept -> size_type - { - return compute_size(shape()); - } - - /** - * Returns the number of dimensions of the function. - */ - template - inline auto xgenerator::dimension() const noexcept -> size_type - { - return m_shape.size(); - } - - /** - * Returns the shape of the xgenerator. - */ - template - inline auto xgenerator::shape() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - template - inline layout_type xgenerator::layout() const noexcept - { - return static_layout; - } - - //@} - - /** - * @name Data - */ - /** - * Returns the evaluated element at the specified position in the function. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal or greater than - * the number of dimensions of the function. - */ - template - template - inline auto xgenerator::operator()(Args... args) const -> const_reference - { - XTENSOR_TRY(check_index(shape(), args...)); - adapt_index<0>(args...); - return m_f(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression, - * after dimension and bounds checking. - * @param args a list of indices specifying the position in the function. Indices - * must be unsigned integers, the number of indices should be equal to the number of dimensions - * of the expression. - * @exception std::out_of_range if the number of argument is greater than the number of dimensions - * or if indices are out of bounds. - */ - template - template - inline auto xgenerator::at(Args... args) const -> const_reference - { - check_access(shape(), args...); - return this->operator()(args...); - } - - /** - * Returns a constant reference to the element at the specified position in the expression. - * @param args a list of indices specifying the position in the expression. Indices - * must be unsigned integers, the number of indices must be equal to the number of - * dimensions of the expression, else the behavior is undefined. - * - * @warning This method is meant for performance, for expressions with a dynamic - * number of dimensions (i.e. not known at compile time). Since it may have - * undefined behavior (see parameters), operator() should be prefered whenever - * it is possible. - * @warning This method is NOT compatible with broadcasting, meaning the following - * code has undefined behavior: - * \code{.cpp} - * xt::xarray a = {{0, 1}, {2, 3}}; - * xt::xarray b = {0, 1}; - * auto fd = a + b; - * double res = fd.uncheked(0, 1); - * \endcode - */ - template - template - inline auto xgenerator::unchecked(Args... args) const -> const_reference - { - return m_f(args...); - } - - template - template - inline auto xgenerator::operator[](const OS& index) const - -> disable_integral_t - { - return element(index.cbegin(), index.cend()); - } - - template - template - inline auto xgenerator::operator[](std::initializer_list index) const - -> const_reference - { - return element(index.begin(), index.end()); - } - - template - inline auto xgenerator::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the function. - * @param first iterator starting the sequence of indices - * @param last iterator ending the sequence of indices - * The number of indices in the sequence should be equal to or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xgenerator::element(It first, It last) const -> const_reference - { - using bounded_iterator = xbounded_iterator; - XTENSOR_TRY(check_element_index(shape(), first, last)); - return m_f.element(bounded_iterator(first, shape().cbegin()), bounded_iterator(last, shape().cend())); - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the function to the specified parameter. - * @param shape the result shape - * @param reuse_cache parameter for internal optimization - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xgenerator::broadcast_shape(O& shape, bool) const - { - return xt::broadcast_shape(m_shape, shape); - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xgenerator::is_trivial_broadcast(const O& /*strides*/) const noexcept - { - return false; - } - //@} - - template - template - inline auto xgenerator::stepper_begin(const O& shape) const noexcept -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(this, offset); - } - - template - template - inline auto xgenerator::stepper_end(const O& shape, layout_type) const noexcept -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(this, offset, true); - } - - template - template - inline void xgenerator::assign_to(xexpression& e) const noexcept - { - e.derived_cast().resize(m_shape); - m_f.assign_to(e); - } - - template - template - inline void xgenerator::adapt_index() const - { - } - - template - template - inline void xgenerator::adapt_index(I& arg, Args&... args) const - { - using value_type = typename decltype(m_shape)::value_type; - if (sizeof...(Args) + 1 > m_shape.size()) - { - adapt_index(args...); - } - else - { - if (static_cast(arg) >= m_shape[dim] && m_shape[dim] == 1) - { - arg = 0; - } - adapt_index(args...); - } - } - - namespace detail - { -#ifdef X_OLD_CLANG - template - inline auto make_xgenerator(Functor&& f, std::initializer_list shape) noexcept - { - using shape_type = std::vector; - using type = xgenerator; - return type(std::forward(f), xtl::forward_sequence(shape)); - } -#else - template - inline auto make_xgenerator(Functor&& f, const I (&shape)[L]) noexcept - { - using shape_type = std::array; - using type = xgenerator; - return type(std::forward(f), xtl::forward_sequence(shape)); - } -#endif - - template - inline auto make_xgenerator(Functor&& f, S&& shape) noexcept - { - using type = xgenerator>; - return type(std::forward(f), std::forward(shape)); - } - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xindex_view.hpp b/vendor/xtensor/include/xtensor/xindex_view.hpp deleted file mode 100644 index ef46c1bbb..000000000 --- a/vendor/xtensor/include/xtensor/xindex_view.hpp +++ /dev/null @@ -1,745 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_INDEX_VIEW_HPP -#define XTENSOR_INDEX_VIEW_HPP - -#include -#include -#include -#include -#include - -#include "xexpression.hpp" -#include "xiterable.hpp" -#include "xstrides.hpp" -#include "xutils.hpp" - -namespace xt -{ - - template - class xindex_view; - - template - struct xcontainer_inner_types> - { - using xexpression_type = std::decay_t; - using temporary_type = xarray; - }; - - template - struct xiterable_inner_types> - { - using inner_shape_type = std::array; - using const_stepper = xindexed_stepper, true>; - using stepper = xindexed_stepper, false>; - }; - - /*************** - * xindex_view * - ***************/ - - /** - * @class xindex_view - * @brief View of an xexpression from vector of indices. - * - * The xindex_view class implements a flat (1D) view into a multidimensional - * xexpression yielding the values at the indices of the index array. - * xindex_view is not meant to be used directly, but only with the \ref index_view - * and \ref filter helper functions. - * - * @tparam CT the closure type of the \ref xexpression type underlying this view - * @tparam I the index array type of the view - * - * @sa index_view, filter - */ - template - class xindex_view : public xview_semantic>, - public xiterable> - { - public: - - using self_type = xindex_view; - using xexpression_type = std::decay_t; - using semantic_base = xview_semantic; - - using value_type = typename xexpression_type::value_type; - using reference = typename xexpression_type::reference; - using const_reference = typename xexpression_type::const_reference; - using pointer = typename xexpression_type::pointer; - using const_pointer = typename xexpression_type::const_pointer; - using size_type = typename xexpression_type::size_type; - using difference_type = typename xexpression_type::difference_type; - - using iterable_base = xiterable; - using inner_shape_type = typename iterable_base::inner_shape_type; - using shape_type = inner_shape_type; - using strides_type = shape_type; - - using indices_type = I; - - using stepper = typename iterable_base::stepper; - using const_stepper = typename iterable_base::const_stepper; - - using temporary_type = typename xcontainer_inner_types::temporary_type; - using base_index_type = xindex_type_t; - - static constexpr layout_type static_layout = layout_type::dynamic; - static constexpr bool contiguous_layout = false; - - template - xindex_view(CTA&& e, I2&& indices) noexcept; - - template - self_type& operator=(const xexpression& e); - - template - disable_xexpression& operator=(const E& e); - - size_type size() const noexcept; - size_type dimension() const noexcept; - const inner_shape_type& shape() const noexcept; - layout_type layout() const noexcept; - - template - void fill(const T& value); - - reference operator()(size_type idx = size_type(0)); - template - reference operator()(size_type idx0, size_type idx1, Args... args); - reference unchecked(size_type idx); - template - disable_integral_t operator[](const S& index); - template - reference operator[](std::initializer_list index); - reference operator[](size_type i); - - template - reference element(It first, It last); - - const_reference operator()(size_type idx = size_type(0)) const; - template - const_reference operator()(size_type idx0, size_type idx1, Args... args) const; - const_reference unchecked(size_type idx) const; - template - disable_integral_t operator[](const S& index) const; - template - const_reference operator[](std::initializer_list index) const; - const_reference operator[](size_type i) const; - - template - const_reference element(It first, It last) const; - - template - bool broadcast_shape(O& shape, bool reuse_cache = false) const; - - template - bool is_trivial_broadcast(const O& /*strides*/) const noexcept; - - template - stepper stepper_begin(const ST& shape); - template - stepper stepper_end(const ST& shape, layout_type); - - template - const_stepper stepper_begin(const ST& shape) const; - template - const_stepper stepper_end(const ST& shape, layout_type) const; - - private: - - CT m_e; - const indices_type m_indices; - const inner_shape_type m_shape; - - void assign_temporary_impl(temporary_type&& tmp); - - friend class xview_semantic>; - }; - - /*************** - * xfiltration * - ***************/ - - /** - * @class xfiltration - * @brief Filter of a xexpression for fast scalar assign. - * - * The xfiltration class implements a lazy filtration of a multidimentional - * \ref xexpression, optimized for scalar and computed scalar assignments. - * Actually, the \ref xfiltration class IS NOT an \ref xexpression and the - * scalar and computed scalar assignments are the only method it provides. - * The filtering condition is not evaluated until the filtration is assigned. - * - * xfiltration is not meant to be used directly, but only with the \ref filtration - * helper function. - * - * @tparam ECT the closure type of the \ref xexpression type underlying this filtration - * @tparam CCR the closure type of the filtering \ref xexpression type - * - * @sa filtration - */ - template - class xfiltration - { - public: - - using self_type = xfiltration; - using xexpression_type = std::decay_t; - using const_reference = typename xexpression_type::const_reference; - - template - xfiltration(ECTA&& e, CCTA&& condition); - - template - disable_xexpression operator=(const E&); - - template - disable_xexpression operator+=(const E&); - - template - disable_xexpression operator-=(const E&); - - template - disable_xexpression operator*=(const E&); - - template - disable_xexpression operator/=(const E&); - - template - disable_xexpression operator%=(const E&); - - private: - - template - self_type& apply(F&& func); - - ECT m_e; - CCT m_condition; - }; - - /****************************** - * xindex_view implementation * - ******************************/ - - /** - * @name Constructor - */ - //@{ - /** - * Constructs an xindex_view, selecting the indices specified by \a indices. - * The resulting xexpression has a 1D shape with a length of n for n indices. - * - * @param e the underlying xexpression for this view - * @param indices the indices to select - */ - template - template - inline xindex_view::xindex_view(CTA&& e, I2&& indices) noexcept - : m_e(std::forward(e)), m_indices(std::forward(indices)), m_shape({ m_indices.size() }) - { - } - //@} - - /** - * @name Extended copy semantic - */ - //@{ - /** - * The extended assignment operator. - */ - template - template - inline auto xindex_view::operator=(const xexpression& e) -> self_type& - { - return semantic_base::operator=(e); - } - //@} - - template - template - inline auto xindex_view::operator=(const E& e) -> disable_xexpression& - { - std::fill(this->begin(), this->end(), e); - return *this; - } - - template - inline void xindex_view::assign_temporary_impl(temporary_type&& tmp) - { - std::copy(tmp.cbegin(), tmp.cend(), this->begin()); - } - - /** - * @name Size and shape - */ - //@{ - /** - * Returns the size of the xindex_view. - */ - template - inline auto xindex_view::size() const noexcept -> size_type - { - return compute_size(shape()); - } - - /** - * Returns the number of dimensions of the xindex_view. - */ - template - inline auto xindex_view::dimension() const noexcept -> size_type - { - return 1; - } - - /** - * Returns the shape of the xindex_view. - */ - template - inline auto xindex_view::shape() const noexcept -> const inner_shape_type& - { - return m_shape; - } - - template - inline layout_type xindex_view::layout() const noexcept - { - return static_layout; - } - - //@} - - /** - * @name Data - */ - //@{ - - /** - * Fills the view with the given value. - * @param value the value to fill the view with. - */ - template - template - inline void xindex_view::fill(const T& value) - { - std::fill(this->storage_begin(), this->storage_end(), value); - } - - /** - * Returns a reference to the element at the specified position in the xindex_view. - * @param idx index specifying the position in the index_view. More indices may be provided, - * only the last one will be used. - */ - template - inline auto xindex_view::operator()(size_type idx) -> reference - { - return m_e[m_indices[idx]]; - } - - template - template - inline auto xindex_view::operator()(size_type, size_type idx1, Args... args) -> reference - { - return this->operator()(idx1, static_cast(args)...); - } - - /** - * Returns a reference to the element at the specified position in the xindex_view. - * @param idx index specifying the position in the index_view. - */ - template - inline auto xindex_view::unchecked(size_type idx) -> reference - { - return this->operator()(idx); - } - - /** - * Returns a constant reference to the element at the specified position in the xindex_view. - * @param idx index specifying the position in the index_view. More indices may be provided, - * only the last one will be used. - */ - template - inline auto xindex_view::operator()(size_type idx) const -> const_reference - { - return m_e[m_indices[idx]]; - } - - template - template - inline auto xindex_view::operator()(size_type, size_type idx1, Args... args) const -> const_reference - { - return this->operator()(idx1, args...); - } - - /** - * Returns a constant reference to the element at the specified position in the xindex_view. - * @param idx index specifying the position in the index_view. - */ - template - inline auto xindex_view::unchecked(size_type idx) const -> const_reference - { - return this->operator()(idx); - } - - /** - * Returns a reference to the element at the specified position in the container. - * @param index a sequence of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices in the list should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xindex_view::operator[](const S& index) - -> disable_integral_t - { - return m_e[m_indices[index[0]]]; - } - - template - template - inline auto xindex_view::operator[](std::initializer_list index) - -> reference - { - return m_e[m_indices[*(index.begin())]]; - } - - template - inline auto xindex_view::operator[](size_type i) -> reference - { - return operator()(i); - } - - /** - * Returns a constant reference to the element at the specified position in the container. - * @param index a sequence of indices specifying the position in the container. Indices - * must be unsigned integers, the number of indices in the list should be equal or greater - * than the number of dimensions of the container. - */ - template - template - inline auto xindex_view::operator[](const S& index) const - -> disable_integral_t - { - return m_e[m_indices[index[0]]]; - } - - template - template - inline auto xindex_view::operator[](std::initializer_list index) const - -> const_reference - { - return m_e[m_indices[*(index.begin())]]; - } - - template - inline auto xindex_view::operator[](size_type i) const -> const_reference - { - return operator()(i); - } - - /** - * Returns a reference to the element at the specified position in the xindex_view. - * @param first iterator starting the sequence of indices - * The number of indices in the sequence should be equal to or greater 1. - */ - template - template - inline auto xindex_view::element(It first, It /*last*/) -> reference - { - return m_e[m_indices[(*first)]]; - } - - /** - * Returns a reference to the element at the specified position in the xindex_view. - * @param first iterator starting the sequence of indices - * The number of indices in the sequence should be equal to or greater 1. - */ - template - template - inline auto xindex_view::element(It first, It /*last*/) const -> const_reference - { - return m_e[m_indices[(*first)]]; - } - //@} - - /** - * @name Broadcasting - */ - //@{ - /** - * Broadcast the shape of the xindex_view to the specified parameter. - * @param shape the result shape - * @param reuse_cache parameter for internal optimization - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xindex_view::broadcast_shape(O& shape, bool) const - { - return xt::broadcast_shape(m_shape, shape); - } - - /** - * Compares the specified strides with those of the container to see whether - * the broadcasting is trivial. - * @return a boolean indicating whether the broadcasting is trivial - */ - template - template - inline bool xindex_view::is_trivial_broadcast(const O& /*strides*/) const noexcept - { - return false; - } - //@} - - /*************** - * stepper api * - ***************/ - - template - template - inline auto xindex_view::stepper_begin(const ST& shape) -> stepper - { - size_type offset = shape.size() - dimension(); - return stepper(this, offset); - } - - template - template - inline auto xindex_view::stepper_end(const ST& shape, layout_type) -> stepper - { - size_type offset = shape.size() - dimension(); - return stepper(this, offset, true); - } - - template - template - inline auto xindex_view::stepper_begin(const ST& shape) const -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(this, offset); - } - - template - template - inline auto xindex_view::stepper_end(const ST& shape, layout_type) const -> const_stepper - { - size_type offset = shape.size() - dimension(); - return const_stepper(this, offset, true); - } - - /****************************** - * xfiltration implementation * - ******************************/ - - /** - * @name Constructor - */ - //@{ - /** - * Constructs a xfiltration on the given expression \c e, selecting - * the elements matching the specified \c condition. - * - * @param e the \ref xexpression to filter. - * @param condition the filtering \ref xexpression to apply. - */ - template - template - inline xfiltration::xfiltration(ECTA&& e, CCTA&& condition) - : m_e(std::forward(e)), m_condition(std::forward(condition)) - { - } - //@} - - /** - * @name Extended copy semantic - */ - //@{ - /** - * Assigns the scalar \c e to \c *this. - * @param e the scalar to assign. - * @return a reference to \ *this. - */ - template - template - inline auto xfiltration::operator=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? e : v; }); - } - //@} - - /** - * @name Computed assignement - */ - //@{ - /** - * Adds the scalar \c e to \c *this. - * @param e the scalar to add. - * @return a reference to \c *this. - */ - template - template - inline auto xfiltration::operator+=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? v + e : v; }); - } - - /** - * Subtracts the scalar \c e from \c *this. - * @param e the scalar to subtract. - * @return a reference to \c *this. - */ - template - template - inline auto xfiltration::operator-=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? v - e : v; }); - } - - /** - * Multiplies \c *this with the scalar \c e. - * @param e the scalar involved in the operation. - * @return a reference to \c *this. - */ - template - template - inline auto xfiltration::operator*=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? v * e : v; }); - } - - /** - * Divides \c *this by the scalar \c e. - * @param e the scalar involved in the operation. - * @return a reference to \c *this. - */ - template - template - inline auto xfiltration::operator/=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? v / e : v; }); - } - - /** - * Computes the remainder of \c *this after division by the scalar \c e. - * @param e the scalar involved in the operation. - * @return a reference to \c *this. - */ - template - template - inline auto xfiltration::operator%=(const E& e) -> disable_xexpression - { - return apply([this, &e](const_reference v, bool cond) { return cond ? v % e : v; }); - } - - template - template - inline auto xfiltration::apply(F&& func) -> self_type& - { - std::transform(m_e.cbegin(), m_e.cend(), m_condition.cbegin(), m_e.begin(), func); - return *this; - } - - /** - * @brief creates an indexview from a container of indices. - * - * Returns a 1D view with the elements at \a indices selected. - * - * @param e the underlying xexpression - * @param indices the indices to select - * - * \code{.cpp} - * xarray a = {{1,5,3}, {4,5,6}}; - * b = index_view(a, {{0, 0}, {1, 0}, {1, 1}}); - * std::cout << b << std::endl; // {1, 4, 5} - * b += 100; - * std::cout << a << std::endl; // {{101, 5, 3}, {104, 105, 6}} - * \endcode - */ - template - inline auto index_view(E&& e, I&& indices) noexcept - { - using view_type = xindex_view, std::decay_t>; - return view_type(std::forward(e), std::forward(indices)); - } -#ifdef X_OLD_CLANG - template - inline auto index_view(E&& e, std::initializer_list> indices) noexcept - { - std::vector idx; - for (auto it = indices.begin(); it != indices.end(); ++it) - { - idx.emplace_back(xindex(it->begin(), it->end())); - } - using view_type = xindex_view, std::vector>; - return view_type(std::forward(e), std::move(idx)); - } -#else - template - inline auto index_view(E&& e, const xindex (&indices)[L]) noexcept - { - using view_type = xindex_view, std::array>; - return view_type(std::forward(e), to_array(indices)); - } -#endif - - /** - * @brief creates a view into \a e filtered by \a condition. - * - * Returns a 1D view with the elements selected where \a condition evaluates to \em true. - * This is equivalent to \verbatim{index_view(e, where(condition));}\endverbatim - * The returned view is not optimal if you just want to assign a scalar to the filtered - * elements. In that case, you should consider using the \ref filtration function - * instead. - * - * @param e the underlying xexpression - * @param condition xexpression with shape of \a e which selects indices - * - * \code{.cpp} - * xarray a = {{1,5,3}, {4,5,6}}; - * b = filter(a, a >= 5); - * std::cout << b << std::endl; // {5, 5, 6} - * \endcode - * - * \sa filtration - */ - template - inline auto filter(E&& e, O&& condition) noexcept - { - auto indices = where(std::forward(condition)); - using view_type = xindex_view, decltype(indices)>; - return view_type(std::forward(e), std::move(indices)); - } - - /** - * @brief creates a filtration of \c e filtered by \a condition. - * - * Returns a lazy filtration optimized for scalar assignment. - * Actually, scalar assignment and computed scalar assignments - * are the only available methods of the filtration, the filtration - * IS NOT an \ref xexpression. - * - * @param e the \ref xexpression to filter - * @param condition the filtering \ref xexpression - * - * \code{.cpp} - * xarray a = {{1,5,3}, {4,5,6}}; - * filtration(a, a >= 5) += 2; - * std::cout << a << std::endl; // {{1, 7, 3}, {4, 7, 8}} - * \endcode - */ - template - inline auto filtration(E&& e, C&& condition) noexcept - { - using filtration_type = xfiltration, xclosure_t>; - return filtration_type(std::forward(e), std::forward(condition)); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xinfo.hpp b/vendor/xtensor/include/xtensor/xinfo.hpp deleted file mode 100644 index 50da4f6cd..000000000 --- a/vendor/xtensor/include/xtensor/xinfo.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_INFO_HPP -#define XTENSOR_INFO_HPP - -#include - -#ifndef _MSC_VER -# if __cplusplus < 201103 -# define CONSTEXPR11_TN -# define CONSTEXPR14_TN -# define NOEXCEPT_TN -# elif __cplusplus < 201402 -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN -# define NOEXCEPT_TN noexcept -# else -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN constexpr -# define NOEXCEPT_TN noexcept -# endif -#else // _MSC_VER -# if _MSC_VER < 1900 -# define CONSTEXPR11_TN -# define CONSTEXPR14_TN -# define NOEXCEPT_TN -# elif _MSC_VER < 2000 -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN -# define NOEXCEPT_TN noexcept -# else -# define CONSTEXPR11_TN constexpr -# define CONSTEXPR14_TN constexpr -# define NOEXCEPT_TN noexcept -# endif -#endif - -namespace xt -{ - // see http://stackoverflow.com/a/20170989 - struct static_string - { - template - explicit CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN - : data(a), size(N - 1) - { - } - - CONSTEXPR11_TN static_string(const char* a, const std::size_t sz) NOEXCEPT_TN - : data(a), size(sz) - { - } - - const char* const data; - const std::size_t size; - }; - - template - CONSTEXPR14_TN static_string type_name() - { -#ifdef __clang__ - static_string p(__PRETTY_FUNCTION__); - return static_string(p.data + 39, p.size - 39 - 1); -#elif defined(__GNUC__) - static_string p(__PRETTY_FUNCTION__); -#if __cplusplus < 201402 - return static_string(p.data + 36, p.size - 36 - 1); -#else - return static_string(p.data + 54, p.size - 54 - 1); -#endif -#elif defined(_MSC_VER) - static const static_string p(__FUNCSIG__); - return static_string(p.data + 47, p.size - 47 - 7); -#endif - } - - template - std::string type_to_string() - { - static_string static_name = type_name(); - return std::string(static_name.data, static_name.size); - } - - template - std::string info(const T& t) - { - std::string s; - s += "\nValue type: " + type_to_string(); - s += "\nLayout: "; - if (t.layout() == layout_type::row_major) - { - s += "row_major"; - } - else if (t.layout() == layout_type::column_major) - { - s += "column_major"; - } - else if (t.layout() == layout_type::dynamic) - { - s += "dynamic"; - } - else - { - s += "any"; - } - s += "\nShape: ("; - bool first = true; - for (const auto& el : t.shape()) - { - if (!first) - { - s += ", "; - } - first = false; - s += std::to_string(el); - } - s += ")\nStrides: ("; - first = true; - for (const auto& el : t.strides()) - { - if (!first) - { - s += ", "; - } - first = false; - s += std::to_string(el); - } - s += ")\nSize: " + std::to_string(t.size()) + "\n"; - return s; - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xio.hpp b/vendor/xtensor/include/xtensor/xio.hpp deleted file mode 100644 index fa778996d..000000000 --- a/vendor/xtensor/include/xtensor/xio.hpp +++ /dev/null @@ -1,634 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_IO_HPP -#define XTENSOR_IO_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "xexpression.hpp" -#include "xmath.hpp" -#include "xstrided_view.hpp" - -namespace xt -{ - - template - inline std::ostream& operator<<(std::ostream& out, const xexpression& e); - - namespace print_options - { - struct print_options_impl - { - std::size_t edgeitems = 3; - std::size_t line_width = 75; - std::size_t threshold = 1000; - std::streamsize precision = -1; // default precision - }; - - inline print_options_impl& print_options() - { - static print_options_impl po; - return po; - } - - /** - * @brief Sets the line width. After \a line_width chars, - * a new line is added. - * - * @param line_width The line width - */ - inline void set_line_width(std::size_t line_width) - { - print_options().line_width = line_width; - } - - /** - * @brief Sets the threshold after which summarization is triggered (default: 1000). - * - * @param threshold The number of elements in the xexpression that triggers - * summarization in the output - */ - inline void set_threshold(std::size_t threshold) - { - print_options().threshold = threshold; - } - - /** - * @brief Sets the number of edge items. If the summarization is - * triggered, this value defines how many items of each dimension - * are printed. - * - * @param edgeitems The number of edge items - */ - inline void set_edgeitems(std::size_t edgeitems) - { - print_options().edgeitems = edgeitems; - } - - /** - * @brief Sets the precision for printing floating point values. - * - * @param precision The number of digits for floating point output - */ - inline void set_precision(std::streamsize precision) - { - print_options().precision = precision; - } - } - - /************************************** - * xexpression ostream implementation * - **************************************/ - - namespace detail - { - template - std::ostream& xoutput(std::ostream& out, const E& e, - xstrided_slice_vector& slices, F& printer, std::size_t blanks, - std::streamsize element_width, std::size_t edgeitems, std::size_t line_width) - { - using size_type = typename E::size_type; - - const auto view = xt::strided_view(e, slices); - if (view.dimension() == 0) - { - printer.print_next(out); - } - else - { - std::string indents(blanks, ' '); - - size_type i = 0; - size_type elems_on_line = 0; - size_type ewp2 = static_cast(element_width) + size_type(2); - size_type line_lim = static_cast(std::floor(line_width / ewp2)); - - out << '{'; - for (; i != size_type(view.shape()[0] - 1); ++i) - { - if (edgeitems && size_type(view.shape()[0]) > (edgeitems * 2) && i == edgeitems) - { - out << "..., "; - if (view.dimension() > 1) - { - elems_on_line = 0; - out << std::endl - << indents; - } - i = size_type(view.shape()[0]) - edgeitems; - } - if (view.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim) - { - out << std::endl - << indents; - elems_on_line = 0; - } - slices.push_back(static_cast(i)); - xoutput(out, e, slices, printer, blanks + 1, element_width, edgeitems, line_width) << ','; - slices.pop_back(); - elems_on_line++; - - if (view.dimension() == 1) - { - out << ' '; - } - else - { - out << std::endl - << indents; - } - } - if (view.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim) - { - out << std::endl - << indents; - } - slices.push_back(static_cast(i)); - xoutput(out, e, slices, printer, blanks + 1, element_width, edgeitems, line_width) << '}'; - slices.pop_back(); - } - return out; - } - - template - static void recurser_run(F& fn, const E& e, xstrided_slice_vector& slices, std::size_t lim = 0) - { - using size_type = typename E::size_type; - const auto view = strided_view(e, slices); - if (view.dimension() == 0) - { - fn.update(view()); - } - else - { - size_type i = 0; - for (; i != static_cast(view.shape()[0] - 1); ++i) - { - if (lim && size_type(view.shape()[0]) > (lim * 2) && i == lim) - { - i = static_cast(view.shape()[0]) - lim; - } - slices.push_back(static_cast(i)); - recurser_run(fn, e, slices, lim); - slices.pop_back(); - } - slices.push_back(static_cast(i)); - recurser_run(fn, e, slices, lim); - slices.pop_back(); - } - } - - template - struct printer; - - template - struct printer::value>> - { - using value_type = std::decay_t; - using cache_type = std::vector; - using cache_iterator = typename cache_type::const_iterator; - - explicit printer(std::streamsize precision) - : m_precision(precision) - { - } - - void init() - { - m_precision = m_required_precision < m_precision ? m_required_precision : m_precision; - m_it = m_cache.cbegin(); - if (m_scientific) - { - // 3 = sign, number and dot and 4 = "e+00" - m_width = m_precision + 7; - if (m_large_exponent) - { - // = e+000 (additional number) - m_width += 1; - } - } - else - { - std::streamsize decimals = 1; // print a leading 0 - if (std::floor(m_max) != 0) - { - decimals += std::streamsize(std::log10(std::floor(m_max))); - } - // 2 => sign and dot - m_width = 2 + decimals + m_precision; - } - if (!m_required_precision) - { - --m_width; - } - } - - std::ostream& print_next(std::ostream& out) - { - if (!m_scientific) - { - std::stringstream buf; - buf.width(m_width); - buf << std::fixed; - buf.precision(m_precision); - buf << (*m_it); - if (!m_required_precision) - { - buf << '.'; - } - std::string res = buf.str(); - auto sit = res.rbegin(); - while (*sit == '0') - { - *sit = ' '; - ++sit; - } - out << res; - } - else - { - if (!m_large_exponent) - { - out << std::scientific; - out.width(m_width); - out << (*m_it); - } - else - { - std::stringstream buf; - buf.width(m_width); - buf << std::scientific; - buf.precision(m_precision); - buf << (*m_it); - std::string res = buf.str(); - - if (res[res.size() - 4] == 'e') - { - res.erase(0, 1); - res.insert(res.size() - 2, "0"); - } - out << res; - } - } - ++m_it; - return out; - } - - void update(const value_type& val) - { - if (val != 0 && !std::isinf(val) && !std::isnan(val)) - { - if (!m_scientific || !m_large_exponent) - { - int exponent = 1 + int(std::log10(math::abs(val))); - if (exponent <= -5 || exponent > 7) - { - m_scientific = true; - m_required_precision = m_precision; - if (exponent <= -100 || exponent >= 100) - { - m_large_exponent = true; - } - } - } - if (math::abs(val) > m_max) - { - m_max = math::abs(val); - } - if (m_required_precision < m_precision) - { - while (std::floor(val * std::pow(10, m_required_precision)) != val * std::pow(10, m_required_precision)) - { - m_required_precision++; - } - } - } - m_cache.push_back(val); - } - - std::streamsize width() - { - return m_width; - } - - private: - - bool m_large_exponent = false; - bool m_scientific = false; - std::streamsize m_width = 9; - std::streamsize m_precision; - std::streamsize m_required_precision = 0; - value_type m_max = 0; - - cache_type m_cache; - cache_iterator m_it; - }; - - template - struct printer::value && !std::is_same::value>> - { - using value_type = std::decay_t; - using cache_type = std::vector; - using cache_iterator = typename cache_type::const_iterator; - - explicit printer(std::streamsize) - { - } - - void init() - { - m_it = m_cache.cbegin(); - m_width = 1 + std::streamsize(std::log10(m_max)) + m_sign; - } - - std::ostream& print_next(std::ostream& out) - { - // + enables printing of chars etc. as numbers - // TODO should chars be printed as numbers? - out.width(m_width); - out << +(*m_it); - ++m_it; - return out; - } - - void update(const value_type& val) - { - if (math::abs(val) > m_max) - { - m_max = math::abs(val); - } - if (std::is_signed::value && val < 0) - { - m_sign = true; - } - m_cache.push_back(val); - } - - std::streamsize width() - { - return m_width; - } - - private: - - std::streamsize m_width; - bool m_sign = false; - value_type m_max = 0; - - cache_type m_cache; - cache_iterator m_it; - }; - - template - struct printer::value>> - { - using value_type = bool; - using cache_type = std::vector; - using cache_iterator = typename cache_type::const_iterator; - - explicit printer(std::streamsize) - { - } - - void init() - { - m_it = m_cache.cbegin(); - } - - std::ostream& print_next(std::ostream& out) - { - if (*m_it) - { - out << " true"; - } - else - { - out << "false"; - } - // TODO: the following std::setw(5) isn't working correctly on OSX. - //out << std::boolalpha << std::setw(m_width) << (*m_it); - ++m_it; - return out; - } - - void update(const value_type& val) - { - m_cache.push_back(val); - } - - std::streamsize width() - { - return m_width; - } - - private: - - std::streamsize m_width = 5; - - cache_type m_cache; - cache_iterator m_it; - }; - - template - struct printer::value>> - { - using value_type = std::decay_t; - using cache_type = std::vector; - using cache_iterator = typename cache_type::const_iterator; - - explicit printer(std::streamsize precision) - : real_printer(precision), imag_printer(precision) - { - } - - void init() - { - real_printer.init(); - imag_printer.init(); - m_it = m_signs.cbegin(); - } - - std::ostream& print_next(std::ostream& out) - { - real_printer.print_next(out); - if (*m_it) - { - out << "-"; - } - else - { - out << "+"; - } - std::stringstream buf; - imag_printer.print_next(buf); - std::string s = buf.str(); - if (s[0] == ' ') - { - s.erase(0, 1); // erase space for +/- - } - // insert j at end of number - std::size_t idx = s.find_last_not_of(" "); - s.insert(idx + 1, "i"); - out << s; - ++m_it; - return out; - } - - void update(const value_type& val) - { - real_printer.update(val.real()); - imag_printer.update(std::abs(val.imag())); - m_signs.push_back(std::signbit(val.imag())); - } - - std::streamsize width() - { - return real_printer.width() + imag_printer.width() + 2; - } - - private: - - printer real_printer, imag_printer; - cache_type m_signs; - cache_iterator m_it; - }; - - template - struct printer::value && !xtl::is_complex::value>> - { - using value_type = std::decay_t; - using cache_type = std::vector; - using cache_iterator = typename cache_type::const_iterator; - - explicit printer(std::streamsize) - { - } - - void init() - { - m_it = m_cache.cbegin(); - if (m_width > 20) - { - m_width = 0; - } - } - - std::ostream& print_next(std::ostream& out) - { - out.width(m_width); - out << *m_it; - ++m_it; - return out; - } - - void update(const value_type& val) - { - std::stringstream buf; - buf << val; - std::string s = buf.str(); - if (int(s.size()) > m_width) - { - m_width = std::streamsize(s.size()); - } - m_cache.push_back(s); - } - - std::streamsize width() - { - return m_width; - } - - private: - - std::streamsize m_width = 0; - cache_type m_cache; - cache_iterator m_it; - }; - - template - struct custom_formatter - { - using value_type = std::decay_t; - - template - custom_formatter(F&& func) - : m_func(func) - { - } - - std::string operator()(const value_type& val) const - { - return m_func(val); - } - - private: - - std::function m_func; - }; - } - - template - std::ostream& pretty_print(const xexpression& e, F&& func, std::ostream& out = std::cout) - { - xfunction, std::string, const_xclosure_t> print_fun(detail::custom_formatter(std::forward(func)), e); - return pretty_print(print_fun, out); - } - - template - std::ostream& pretty_print(const xexpression& e, std::ostream& out = std::cout) - { - const E& d = e.derived_cast(); - - size_t lim = 0; - std::size_t sz = compute_size(d.shape()); - if (sz > print_options::print_options().threshold) - { - lim = print_options::print_options().edgeitems; - } - if (sz == 0) - { - out << "{}"; - return out; - } - - auto temp_precision = out.precision(); - auto precision = temp_precision; - if (print_options::print_options().precision != -1) - { - out.precision(print_options::print_options().precision); - precision = print_options::print_options().precision; - } - - detail::printer p(precision); - - xstrided_slice_vector sv; - detail::recurser_run(p, d, sv, lim); - p.init(); - sv.clear(); - xoutput(out, d, sv, p, 1, p.width(), lim, print_options::print_options().line_width); - - out.precision(temp_precision); // restore precision - - return out; - } - - template - inline std::ostream& operator<<(std::ostream& out, const xexpression& e) - { - return pretty_print(e, out); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xiterable.hpp b/vendor/xtensor/include/xtensor/xiterable.hpp deleted file mode 100644 index 9eb4a55f2..000000000 --- a/vendor/xtensor/include/xtensor/xiterable.hpp +++ /dev/null @@ -1,824 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ITERABLE_HPP -#define XTENSOR_ITERABLE_HPP - -#include "xiterator.hpp" - -namespace xt -{ - - /******************* - * xconst_iterable * - *******************/ - - template - struct xiterable_inner_types; - -#define DL XTENSOR_DEFAULT_LAYOUT - - /** - * @class xconst_iterable - * @brief Base class for multidimensional iterable constant expressions - * - * The xconst_iterable class defines the interface for multidimensional - * constant expressions that can be iterated. - * - * @tparam D The derived type, i.e. the inheriting class for which xconst_iterable - * provides the interface. - */ - template - class xconst_iterable - { - public: - - using derived_type = D; - - using iterable_types = xiterable_inner_types; - using inner_shape_type = typename iterable_types::inner_shape_type; - - using stepper = typename iterable_types::stepper; - using const_stepper = typename iterable_types::const_stepper; - - template - using layout_iterator = xiterator; - template - using const_layout_iterator = xiterator; - template - using reverse_layout_iterator = std::reverse_iterator>; - template - using const_reverse_layout_iterator = std::reverse_iterator>; - - template - using broadcast_iterator = xiterator; - template - using const_broadcast_iterator = xiterator; - template - using reverse_broadcast_iterator = std::reverse_iterator>; - template - using const_reverse_broadcast_iterator = std::reverse_iterator>; - - using storage_iterator = layout_iterator
; - using const_storage_iterator = const_layout_iterator
; - using reverse_storage_iterator = reverse_layout_iterator
; - using const_reverse_storage_iterator = const_reverse_layout_iterator
; - - using iterator = layout_iterator
; - using const_iterator = const_layout_iterator
; - using reverse_iterator = reverse_layout_iterator
; - using const_reverse_iterator = const_reverse_layout_iterator
; - - template - const_layout_iterator begin() const noexcept; - template - const_layout_iterator end() const noexcept; - template - const_layout_iterator cbegin() const noexcept; - template - const_layout_iterator cend() const noexcept; - - template - const_reverse_layout_iterator rbegin() const noexcept; - template - const_reverse_layout_iterator rend() const noexcept; - template - const_reverse_layout_iterator crbegin() const noexcept; - template - const_reverse_layout_iterator crend() const noexcept; - - template - const_broadcast_iterator begin(const S& shape) const noexcept; - template - const_broadcast_iterator end(const S& shape) const noexcept; - template - const_broadcast_iterator cbegin(const S& shape) const noexcept; - template - const_broadcast_iterator cend(const S& shape) const noexcept; - - template - const_reverse_broadcast_iterator rbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator rend(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crbegin(const S& shape) const noexcept; - template - const_reverse_broadcast_iterator crend(const S& shape) const noexcept; - - template - const_layout_iterator storage_begin() const noexcept; - template - const_layout_iterator storage_end() const noexcept; - template - const_layout_iterator storage_cbegin() const noexcept; - template - const_layout_iterator storage_cend() const noexcept; - - template - const_reverse_layout_iterator storage_rbegin() const noexcept; - template - const_reverse_layout_iterator storage_rend() const noexcept; - template - const_reverse_layout_iterator storage_crbegin() const noexcept; - template - const_reverse_layout_iterator storage_crend() const noexcept; - - protected: - - const inner_shape_type& get_shape() const; - - private: - - template - const_layout_iterator get_cbegin(bool end_index) const noexcept; - template - const_layout_iterator get_cend(bool end_index) const noexcept; - - template - const_broadcast_iterator get_cbegin(const S& shape, bool end_index) const noexcept; - template - const_broadcast_iterator get_cend(const S& shape, bool end_index) const noexcept; - - template - const_stepper get_stepper_begin(const S& shape) const noexcept; - template - const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept; - - const derived_type& derived_cast() const; - }; - - /************* - * xiterable * - *************/ - - /** - * @class xiterable - * @brief Base class for multidimensional iterable expressions - * - * The xiterable class defines the interface for multidimensional - * expressions that can be iterated. - * - * @tparam D The derived type, i.e. the inheriting class for which xiterable - * provides the interface. - */ - template - class xiterable : public xconst_iterable - { - public: - - using derived_type = D; - - using base_type = xconst_iterable; - using inner_shape_type = typename base_type::inner_shape_type; - - using stepper = typename base_type::stepper; - using const_stepper = typename base_type::const_stepper; - - template - using layout_iterator = typename base_type::template layout_iterator; - template - using const_layout_iterator = typename base_type::template const_layout_iterator; - template - using reverse_layout_iterator = typename base_type::template reverse_layout_iterator; - template - using const_reverse_layout_iterator = typename base_type::template const_reverse_layout_iterator; - - template - using broadcast_iterator = typename base_type::template broadcast_iterator; - template - using const_broadcast_iterator = typename base_type::template const_broadcast_iterator; - template - using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator; - template - using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator; - - using iterator = typename base_type::iterator; - using const_iterator = typename base_type::const_iterator; - using reverse_iterator = typename base_type::reverse_iterator; - using const_reverse_iterator = typename base_type::const_reverse_iterator; - - using base_type::begin; - using base_type::end; - using base_type::rbegin; - using base_type::rend; - using base_type::storage_begin; - using base_type::storage_end; - - template - layout_iterator begin() noexcept; - template - layout_iterator end() noexcept; - - template - reverse_layout_iterator rbegin() noexcept; - template - reverse_layout_iterator rend() noexcept; - - template - broadcast_iterator begin(const S& shape) noexcept; - template - broadcast_iterator end(const S& shape) noexcept; - - template - reverse_broadcast_iterator rbegin(const S& shape) noexcept; - template - reverse_broadcast_iterator rend(const S& shape) noexcept; - - template - layout_iterator storage_begin() noexcept; - template - layout_iterator storage_end() noexcept; - - template - reverse_layout_iterator storage_rbegin() noexcept; - template - reverse_layout_iterator storage_rend() noexcept; - - private: - - template - layout_iterator get_begin(bool end_index) noexcept; - template - layout_iterator get_end(bool end_index) noexcept; - - template - broadcast_iterator get_begin(const S& shape, bool end_index) noexcept; - template - broadcast_iterator get_end(const S& shape, bool end_index) noexcept; - - template - stepper get_stepper_begin(const S& shape) noexcept; - template - stepper get_stepper_end(const S& shape, layout_type l) noexcept; - - template - const_stepper get_stepper_begin(const S& shape) const noexcept; - template - const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept; - - derived_type& derived_cast(); - }; - -#undef DL - - /********************************** - * xconst_iterable implementation * - **********************************/ - - /** - * @name Constant iterators - */ - //@{ - /** - * Returns a constant iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::begin() const noexcept -> const_layout_iterator - { - return this->template cbegin(); - } - - /** - * Returns a constant iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::end() const noexcept -> const_layout_iterator - { - return this->template cend(); - } - - /** - * Returns a constant iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::cbegin() const noexcept -> const_layout_iterator - { - return this->template get_cbegin(false); - } - - /** - * Returns a constant iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::cend() const noexcept -> const_layout_iterator - { - return this->template get_cend(true); - } - //@} - - /** - * @name Constant reverse iterators - */ - //@{ - /** - * Returns a constant iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::rbegin() const noexcept -> const_reverse_layout_iterator - { - return this->template crbegin(); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::rend() const noexcept -> const_reverse_layout_iterator - { - return this->template crend(); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::crbegin() const noexcept -> const_reverse_layout_iterator - { - return const_reverse_layout_iterator(get_cend(true)); - } - - /** - * Returns a constant iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::crend() const noexcept -> const_reverse_layout_iterator - { - return const_reverse_layout_iterator(get_cbegin(false)); - } - //@} - - /** - * @name Constant broadcast iterators - */ - //@{ - /** - * Returns a constant iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::begin(const S& shape) const noexcept -> const_broadcast_iterator - { - return cbegin(shape); - } - - /** - * Returns a constant iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::end(const S& shape) const noexcept -> const_broadcast_iterator - { - return cend(shape); - } - - /** - * Returns a constant iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::cbegin(const S& shape) const noexcept -> const_broadcast_iterator - { - return get_cbegin(shape, false); - } - - /** - * Returns a constant iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::cend(const S& shape) const noexcept -> const_broadcast_iterator - { - return get_cend(shape, true); - } - //@} - - /** - * @name Constant reverse broadcast iterators - */ - //@{ - /** - * Returns a constant iterator to the first element of the reversed expression. - * The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return crbegin(shape); - } - - /** - * Returns a constant iterator to the element following the last element of the - * reversed expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return crend(shape); - } - - /** - * Returns a constant iterator to the first element of the reversed expression. - * The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return const_reverse_broadcast_iterator(get_cend(shape, true)); - } - - /** - * Returns a constant iterator to the element following the last element of the - * reversed expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xconst_iterable::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator - { - return const_reverse_broadcast_iterator(get_cbegin(shape, false)); - } - //@} - - template - template - inline auto xconst_iterable::storage_begin() const noexcept -> const_layout_iterator - { - return this->template cbegin(); - } - - template - template - inline auto xconst_iterable::storage_end() const noexcept -> const_layout_iterator - { - return this->template cend(); - } - - template - template - inline auto xconst_iterable::storage_cbegin() const noexcept -> const_layout_iterator - { - return this->template cbegin(); - } - - template - template - inline auto xconst_iterable::storage_cend() const noexcept -> const_layout_iterator - { - return this->template cend(); - } - - template - template - inline auto xconst_iterable::storage_rbegin() const noexcept -> const_reverse_layout_iterator - { - return this->template crbegin(); - } - - template - template - inline auto xconst_iterable::storage_rend() const noexcept -> const_reverse_layout_iterator - { - return this->template crend(); - } - - template - template - inline auto xconst_iterable::storage_crbegin() const noexcept -> const_reverse_layout_iterator - { - return this->template crbegin(); - } - - template - template - inline auto xconst_iterable::storage_crend() const noexcept -> const_reverse_layout_iterator - { - return this->template crend(); - } - - template - template - inline auto xconst_iterable::get_cbegin(bool end_index) const noexcept -> const_layout_iterator - { - return const_layout_iterator(get_stepper_begin(get_shape()), &get_shape(), end_index); - } - - template - template - inline auto xconst_iterable::get_cend(bool end_index) const noexcept -> const_layout_iterator - { - return const_layout_iterator(get_stepper_end(get_shape(), L), &get_shape(), end_index); - } - - template - template - inline auto xconst_iterable::get_cbegin(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator - { - return const_broadcast_iterator(get_stepper_begin(shape), shape, end_index); - } - - template - template - inline auto xconst_iterable::get_cend(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator - { - return const_broadcast_iterator(get_stepper_end(shape, L), shape, end_index); - } - - template - template - inline auto xconst_iterable::get_stepper_begin(const S& shape) const noexcept -> const_stepper - { - return derived_cast().stepper_begin(shape); - } - - template - template - inline auto xconst_iterable::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - return derived_cast().stepper_end(shape, l); - } - - template - inline auto xconst_iterable::get_shape() const -> const inner_shape_type& - { - return derived_cast().shape(); - } - - template - inline auto xconst_iterable::derived_cast() const -> const derived_type& - { - return *static_cast(this); - } - - /**************************** - * xiterable implementation * - ****************************/ - - /** - * @name Iterators - */ - //@{ - /** - * Returns an iterator to the first element of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::begin() noexcept -> layout_iterator - { - return get_begin(false); - } - - /** - * Returns an iterator to the element following the last element - * of the expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::end() noexcept -> layout_iterator - { - return get_end(true); - } - //@} - - /** - * @name Reverse iterators - */ - //@{ - /** - * Returns an iterator to the first element of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::rbegin() noexcept -> reverse_layout_iterator - { - return reverse_layout_iterator(get_end(true)); - } - - /** - * Returns an iterator to the element following the last element - * of the reversed expression. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::rend() noexcept -> reverse_layout_iterator - { - return reverse_layout_iterator(get_begin(false)); - } - //@} - - /** - * @name Broadcast iterators - */ - //@{ - /** - * Returns an iterator to the first element of the expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::begin(const S& shape) noexcept -> broadcast_iterator - { - return get_begin(shape, false); - } - - /** - * Returns an iterator to the element following the last element of the - * expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::end(const S& shape) noexcept -> broadcast_iterator - { - return get_end(shape, true); - } - //@} - - /** - * @name Reverse broadcast iterators - */ - //@{ - /** - * Returns an iterator to the first element of the reversed expression. The - * iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator - { - return reverse_broadcast_iterator(get_end(shape, true)); - } - - /** - * Returns an iterator to the element following the last element of the - * reversed expression. The iteration is broadcasted to the specified shape. - * @param shape the shape used for broadcasting - * @tparam S type of the \c shape parameter. - * @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT. - */ - template - template - inline auto xiterable::rend(const S& shape) noexcept -> reverse_broadcast_iterator - { - return reverse_broadcast_iterator(get_begin(shape, false)); - } - //@} - - template - template - inline auto xiterable::storage_begin() noexcept -> layout_iterator - { - return this->template begin(); - } - - template - template - inline auto xiterable::storage_end() noexcept -> layout_iterator - { - return this->template end(); - } - - template - template - inline auto xiterable::storage_rbegin() noexcept -> reverse_layout_iterator - { - return this->template rbegin(); - } - - template - template - inline auto xiterable::storage_rend() noexcept -> reverse_layout_iterator - { - return this->template rend(); - } - - template - template - inline auto xiterable::get_begin(bool end_index) noexcept -> layout_iterator - { - return layout_iterator(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index); - } - - template - template - inline auto xiterable::get_end(bool end_index) noexcept -> layout_iterator - { - return layout_iterator(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index); - } - - template - template - inline auto xiterable::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator - { - return broadcast_iterator(get_stepper_begin(shape), shape, end_index); - } - - template - template - inline auto xiterable::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator - { - return broadcast_iterator(get_stepper_end(shape, L), shape, end_index); - } - - template - template - inline auto xiterable::get_stepper_begin(const S& shape) noexcept -> stepper - { - return derived_cast().stepper_begin(shape); - } - - template - template - inline auto xiterable::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper - { - return derived_cast().stepper_end(shape, l); - } - - template - template - inline auto xiterable::get_stepper_begin(const S& shape) const noexcept -> const_stepper - { - return derived_cast().stepper_begin(shape); - } - - template - template - inline auto xiterable::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper - { - return derived_cast().stepper_end(shape, l); - } - - template - inline auto xiterable::derived_cast() -> derived_type& - { - return *static_cast(this); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xiterator.hpp b/vendor/xtensor/include/xtensor/xiterator.hpp deleted file mode 100644 index 01b795051..000000000 --- a/vendor/xtensor/include/xtensor/xiterator.hpp +++ /dev/null @@ -1,1123 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_ITERATOR_HPP -#define XTENSOR_ITERATOR_HPP - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "xexception.hpp" -#include "xlayout.hpp" -#include "xshape.hpp" -#include "xutils.hpp" - -namespace xt -{ - - /*********************** - * iterator meta utils * - ***********************/ - - template - class xscalar; - - namespace detail - { - template - struct get_stepper_iterator_impl - { - using type = typename C::container_iterator; - }; - - template - struct get_stepper_iterator_impl - { - using type = typename C::const_container_iterator; - }; - - template - struct get_stepper_iterator_impl> - { - using type = typename xscalar::dummy_iterator; - }; - - template - struct get_stepper_iterator_impl> - { - using type = typename xscalar::const_dummy_iterator; - }; - } - - template - using get_stepper_iterator = typename detail::get_stepper_iterator_impl::type; - - namespace detail - { - template - struct index_type_impl - { - using type = dynamic_shape; - }; - - template - struct index_type_impl> - { - using type = std::array; - }; - } - - template - using xindex_type_t = typename detail::index_type_impl::type; - - /************ - * xstepper * - ************/ - - template - class xstepper - { - public: - - using storage_type = C; - using subiterator_type = get_stepper_iterator; - using subiterator_traits = std::iterator_traits; - using value_type = typename subiterator_traits::value_type; - using reference = typename subiterator_traits::reference; - using pointer = typename subiterator_traits::pointer; - using difference_type = typename subiterator_traits::difference_type; - using size_type = typename storage_type::size_type; - using shape_type = typename storage_type::shape_type; - using simd_type = xsimd::simd_type; - - xstepper() = default; - xstepper(storage_type* c, subiterator_type it, size_type offset) noexcept; - - reference operator*() const; - - void step(size_type dim, size_type n = 1); - void step_back(size_type dim, size_type n = 1); - void reset(size_type dim); - void reset_back(size_type dim); - - void to_begin(); - void to_end(layout_type l); - - template - R step_simd(); - - value_type step_leading(); - - template - void store_simd(const R& vec); - - private: - - storage_type* p_c; - subiterator_type m_it; - size_type m_offset; - }; - - template - struct stepper_tools - { - // For performance reasons, increment_stepper and decrement_stepper are - // specialized for the case where n=1, which underlies operator++ and - // operator-- on xiterators. - - template - static void increment_stepper(S& stepper, - IT& index, - const ST& shape); - - template - static void decrement_stepper(S& stepper, - IT& index, - const ST& shape); - - template - static void increment_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n); - - template - static void decrement_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n); - }; - - /******************** - * xindexed_stepper * - ********************/ - - template - class xindexed_stepper - { - public: - - using self_type = xindexed_stepper; - using xexpression_type = std::conditional_t; - - using value_type = typename xexpression_type::value_type; - using reference = std::conditional_t; - using pointer = std::conditional_t; - using size_type = typename xexpression_type::size_type; - using difference_type = typename xexpression_type::difference_type; - - using shape_type = typename xexpression_type::shape_type; - using index_type = xindex_type_t; - - xindexed_stepper() = default; - xindexed_stepper(xexpression_type* e, size_type offset, bool end = false) noexcept; - - reference operator*() const; - - void step(size_type dim, size_type n = 1); - void step_back(size_type dim, size_type n = 1); - void reset(size_type dim); - void reset_back(size_type dim); - - void to_begin(); - void to_end(layout_type l); - - private: - - xexpression_type* p_e; - index_type m_index; - size_type m_offset; - }; - - template - struct is_indexed_stepper - { - static const bool value = false; - }; - - template - struct is_indexed_stepper> - { - static const bool value = true; - }; - - /************* - * xiterator * - *************/ - - namespace detail - { - template - class shape_storage - { - public: - - using shape_type = S; - using param_type = const S&; - - shape_storage() = default; - shape_storage(param_type shape); - const S& shape() const; - - private: - - S m_shape; - }; - - template - class shape_storage - { - public: - - using shape_type = S; - using param_type = const S*; - - shape_storage(param_type shape = 0); - const S& shape() const; - - private: - - const S* p_shape; - }; - - template - struct LAYOUT_FORBIDEN_FOR_XITERATOR; - } - - template - class xiterator : public xtl::xrandom_access_iterator_base, - typename It::value_type, - typename It::difference_type, - typename It::pointer, - typename It::reference>, - private detail::shape_storage - { - public: - - using self_type = xiterator; - - using subiterator_type = It; - using value_type = typename subiterator_type::value_type; - using reference = typename subiterator_type::reference; - using pointer = typename subiterator_type::pointer; - using difference_type = typename subiterator_type::difference_type; - using size_type = typename subiterator_type::size_type; - using iterator_category = std::random_access_iterator_tag; - - using private_base = detail::shape_storage; - using shape_type = typename private_base::shape_type; - using shape_param_type = typename private_base::param_type; - using index_type = xindex_type_t; - - xiterator() = default; - // end_index means either reverse_iterator && !end or !reverse_iterator && end - xiterator(It it, shape_param_type shape, bool end_index); - - self_type& operator++(); - self_type& operator--(); - - self_type& operator+=(difference_type n); - self_type& operator-=(difference_type n); - - difference_type operator-(const self_type& rhs) const; - - reference operator*() const; - pointer operator->() const; - - bool equal(const xiterator& rhs) const; - bool less_than(const xiterator& rhs) const; - - private: - - subiterator_type m_it; - index_type m_index; - difference_type m_linear_index; - - using checking_type = typename detail::LAYOUT_FORBIDEN_FOR_XITERATOR::type; - }; - - template - bool operator==(const xiterator& lhs, - const xiterator& rhs); - - template - bool operator<(const xiterator& lhs, - const xiterator& rhs); - - /********************* - * xbounded_iterator * - *********************/ - - template - class xbounded_iterator : public xtl::xrandom_access_iterator_base, - typename std::iterator_traits::value_type, - typename std::iterator_traits::difference_type, - typename std::iterator_traits::pointer, - typename std::iterator_traits::reference> - { - public: - - using self_type = xbounded_iterator; - - using subiterator_type = It; - using bound_iterator_type = BIt; - using value_type = typename std::iterator_traits::value_type; - using reference = typename std::iterator_traits::reference; - using pointer = typename std::iterator_traits::pointer; - using difference_type = typename std::iterator_traits::difference_type; - using iterator_category = std::random_access_iterator_tag; - - xbounded_iterator() = default; - xbounded_iterator(It it, BIt bound_it); - - self_type& operator++(); - self_type& operator--(); - - self_type& operator+=(difference_type n); - self_type& operator-=(difference_type n); - - difference_type operator-(const self_type& rhs) const; - - value_type operator*() const; - - bool equal(const self_type& rhs) const; - bool less_than(const self_type& rhs) const; - - private: - - subiterator_type m_it; - bound_iterator_type m_bound_it; - }; - - template - bool operator==(const xbounded_iterator& lhs, - const xbounded_iterator& rhs); - - template - bool operator<(const xbounded_iterator& lhs, - const xbounded_iterator& rhs); - - /******************************* - * trivial_begin / trivial_end * - *******************************/ - - namespace detail - { - template - constexpr auto trivial_begin(C& c) noexcept - { - return c.storage_begin(); - } - - template - constexpr auto trivial_end(C& c) noexcept - { - return c.storage_end(); - } - - template - constexpr auto trivial_begin(const C& c) noexcept - { - return c.storage_begin(); - } - - template - constexpr auto trivial_end(const C& c) noexcept - { - return c.storage_end(); - } - } - - /*************************** - * xstepper implementation * - ***************************/ - - template - inline xstepper::xstepper(storage_type* c, subiterator_type it, size_type offset) noexcept - : p_c(c), m_it(it), m_offset(offset) - { - } - - template - inline auto xstepper::operator*() const -> reference - { - return *m_it; - } - - template - inline void xstepper::step(size_type dim, size_type n) - { - if (dim >= m_offset) - { - using strides_value_type = decltype(p_c->strides()[0]); - m_it += difference_type(static_cast(n) * p_c->strides()[dim - m_offset]); - } - } - - template - inline void xstepper::step_back(size_type dim, size_type n) - { - if (dim >= m_offset) - { - using strides_value_type = decltype(p_c->strides()[0]); - m_it -= difference_type(static_cast(n) * p_c->strides()[dim - m_offset]); - } - } - - template - inline void xstepper::reset(size_type dim) - { - if (dim >= m_offset) - { - m_it -= difference_type(p_c->backstrides()[dim - m_offset]); - } - } - - template - inline void xstepper::reset_back(size_type dim) - { - if (dim >= m_offset) - { - m_it += difference_type(p_c->backstrides()[dim - m_offset]); - } - } - - template - inline void xstepper::to_begin() - { - m_it = p_c->data_xbegin(); - } - - template - inline void xstepper::to_end(layout_type l) - { - m_it = p_c->data_xend(l); - } - - template - template - inline R xstepper::step_simd() - { - R reg; - reg.load_unaligned(&(*m_it)); - m_it += xsimd::revert_simd_traits::size; - return reg; - } - - template - template - inline void xstepper::store_simd(const R& vec) - { - vec.store_unaligned(&(*m_it)); - m_it += xsimd::revert_simd_traits::size;; - } - - template - auto xstepper::step_leading() -> value_type - { - ++m_it; - return *m_it; - } - - template <> - template - void stepper_tools::increment_stepper(S& stepper, - IT& index, - const ST& shape) - { - using size_type = typename S::size_type; - size_type i = index.size(); - while (i != 0) - { - --i; - if (index[i] != shape[i] - 1) - { - ++index[i]; - stepper.step(i); - return; - } - else - { - index[i] = 0; - if (i != 0) - { - stepper.reset(i); - } - } - } - if (i == 0) - { - std::copy(shape.cbegin(), shape.cend(), index.begin()); - stepper.to_end(layout_type::row_major); - } - } - - template <> - template - void stepper_tools::increment_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n) - { - using size_type = typename S::size_type; - size_type i = index.size(); - size_type leading_i = index.size() - 1; - while (i != 0 && n != 0) - { - --i; - size_type inc = (i == leading_i) ? n : 1; - if (index[i] + inc < shape[i]) - { - index[i] += inc; - stepper.step(i, inc); - n -= inc; - if (i != leading_i || index.size() == 1) - { - i = index.size(); - } - } - else - { - if (i == leading_i) - { - size_type off = shape[i] - index[i] - 1; - stepper.step(i, off); - n -= off; - } - index[i] = 0; - if (i != 0) - { - stepper.reset(i); - } - } - } - if (i == 0) - { - std::copy(shape.cbegin(), shape.cend(), index.begin()); - stepper.to_end(layout_type::row_major); - } - } - - template <> - template - void stepper_tools::decrement_stepper(S& stepper, - IT& index, - const ST& shape) - { - using size_type = typename S::size_type; - size_type i = index.size(); - while (i != 0) - { - --i; - if (index[i] != 0) - { - --index[i]; - stepper.step_back(i); - return; - } - else - { - index[i] = shape[i] - 1; - if (i != 0) - { - stepper.reset_back(i); - } - } - } - if (i == 0) - { - stepper.to_begin(); - } - } - - template <> - template - void stepper_tools::decrement_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n) - { - using size_type = typename S::size_type; - size_type i = index.size(); - size_type leading_i = index.size() - 1; - while (i != 0 && n != 0) - { - --i; - size_type inc = (i == leading_i) ? n : 1; - if (index[i] >= inc) - { - index[i] -= inc; - stepper.step_back(i, inc); - n -= inc; - if (i != leading_i || index.size() == 1) - { - i = index.size(); - } - } - else - { - if (i == leading_i) - { - size_type off = index[i]; - stepper.step_back(i, off); - n -= off; - } - index[i] = shape[i] - 1; - if (i != 0) - { - stepper.reset_back(i); - } - } - } - if (i == 0) - { - stepper.to_begin(); - } - } - - template <> - template - void stepper_tools::increment_stepper(S& stepper, - IT& index, - const ST& shape) - { - using size_type = typename S::size_type; - size_type size = index.size(); - size_type i = 0; - while (i != size) - { - if (index[i] != shape[i] - 1) - { - ++index[i]; - stepper.step(i); - return; - } - else - { - index[i] = 0; - if (i != size - 1) - { - stepper.reset(i); - } - } - ++i; - } - if (i == size) - { - std::copy(shape.cbegin(), shape.cend(), index.begin()); - stepper.to_end(layout_type::column_major); - } - } - - template <> - template - void stepper_tools::increment_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n) - { - using size_type = typename S::size_type; - size_type size = index.size(); - size_type i = 0; - size_type leading_i = 0; - while (i != size && n != 0) - { - size_type inc = (i == leading_i) ? n : 1; - if (index[i] + inc < shape[i]) - { - index[i] += inc; - stepper.step(i, inc); - n -= inc; - if (i != leading_i || index.size() == 1) - { - i = 0; - continue; - } - } - else - { - if (i == leading_i) - { - size_type off = shape[i] - index[i] - 1; - stepper.step(i, off); - n -= off; - } - index[i] = 0; - if (i != size - 1) - { - stepper.reset(i); - } - } - ++i; - } - if (i == size) - { - std::copy(shape.cbegin(), shape.cend(), index.begin()); - stepper.to_end(layout_type::column_major); - } - } - - template <> - template - void stepper_tools::decrement_stepper(S& stepper, - IT& index, - const ST& shape) - { - using size_type = typename S::size_type; - size_type size = index.size(); - size_type i = 0; - while (i != size) - { - if (index[i] != 0) - { - --index[i]; - stepper.step_back(i); - return; - } - else - { - index[i] = shape[i] - 1; - if (i != size - 1) - { - stepper.reset_back(i); - } - } - ++i; - } - if (i == size) - { - stepper.to_begin(); - } - } - - template <> - template - void stepper_tools::decrement_stepper(S& stepper, - IT& index, - const ST& shape, - typename S::size_type n) - { - using size_type = typename S::size_type; - size_type size = index.size(); - size_type i = 0; - size_type leading_i = 0; - while (i != size && n != 0) - { - size_type inc = (i == leading_i) ? n : 1; - if (index[i] >= inc) - { - index[i] -= inc; - stepper.step_back(i, inc); - n -= inc; - if (i != leading_i || index.size() == 1) - { - i = 0; - continue; - } - } - else - { - if (i == leading_i) - { - size_type off = index[i]; - stepper.step_back(i, off); - n -= off; - } - index[i] = shape[i] - 1; - if (i != size - 1) - { - stepper.reset_back(i); - } - } - ++i; - } - if (i == size) - { - stepper.to_begin(); - } - } - - /*********************************** - * xindexed_stepper implementation * - ***********************************/ - - template - inline xindexed_stepper::xindexed_stepper(xexpression_type* e, size_type offset, bool end) noexcept - : p_e(e), m_index(xtl::make_sequence(e->shape().size(), size_type(0))), m_offset(offset) - { - if (end) - { - // Note: the layout here doesn't matter (unused) but using default layout looks more "correct" - to_end(XTENSOR_DEFAULT_LAYOUT); - } - } - - template - inline auto xindexed_stepper::operator*() const -> reference - { - return p_e->element(m_index.cbegin(), m_index.cend()); - } - - template - inline void xindexed_stepper::step(size_type dim, size_type n) - { - if (dim >= m_offset) - { - m_index[dim - m_offset] += static_cast(n); - } - } - - template - inline void xindexed_stepper::step_back(size_type dim, size_type n) - { - if (dim >= m_offset) - { - m_index[dim - m_offset] -= static_cast(n); - } - } - - template - inline void xindexed_stepper::reset(size_type dim) - { - if (dim >= m_offset) - { - m_index[dim - m_offset] = 0; - } - } - - template - inline void xindexed_stepper::reset_back(size_type dim) - { - if (dim >= m_offset) - { - m_index[dim - m_offset] = p_e->shape()[dim - m_offset] - 1; - } - } - - template - inline void xindexed_stepper::to_begin() - { - std::fill(m_index.begin(), m_index.end(), size_type(0)); - } - - template - inline void xindexed_stepper::to_end(layout_type) - { - std::copy(p_e->shape().begin(), p_e->shape().end(), m_index.begin()); - } - - /**************************** - * xiterator implementation * - ****************************/ - - namespace detail - { - template - inline shape_storage::shape_storage(param_type shape) - : m_shape(shape) - { - } - - template - inline const S& shape_storage::shape() const - { - return m_shape; - } - - template - inline shape_storage::shape_storage(param_type shape) - : p_shape(shape) - { - } - - template - inline const S& shape_storage::shape() const - { - return *p_shape; - } - - template <> - struct LAYOUT_FORBIDEN_FOR_XITERATOR - { - using type = int; - }; - - template <> - struct LAYOUT_FORBIDEN_FOR_XITERATOR - { - using type = int; - }; - } - - template - inline xiterator::xiterator(It it, shape_param_type shape, bool end_index) - : private_base(shape), m_it(it), - m_index(end_index ? xtl::forward_sequence(this->shape()) - : xtl::make_sequence(this->shape().size(), size_type(0))), - m_linear_index(0) - { - // end_index means either reverse_iterator && !end or !reverse_iterator && end - if (end_index) - { - if (m_index.size() != size_type(0)) - { - auto iter_begin = (L == layout_type::row_major) ? m_index.begin() : m_index.begin() + 1; - auto iter_end = (L == layout_type::row_major) ? m_index.end() - 1 : m_index.end(); - std::transform(iter_begin, iter_end, iter_begin, [](const auto& v) { return v - 1; }); - } - m_linear_index = difference_type(std::accumulate(this->shape().cbegin(), this->shape().cend(), - size_type(1), std::multiplies())); - } - } - - template - inline auto xiterator::operator++() -> self_type& - { - stepper_tools::increment_stepper(m_it, m_index, this->shape()); - ++m_linear_index; - return *this; - } - - template - inline auto xiterator::operator--() -> self_type& - { - stepper_tools::decrement_stepper(m_it, m_index, this->shape()); - --m_linear_index; - return *this; - } - - template - inline auto xiterator::operator+=(difference_type n) -> self_type& - { - if (n >= 0) - { - stepper_tools::increment_stepper(m_it, m_index, this->shape(), static_cast(n)); - } - else - { - stepper_tools::decrement_stepper(m_it, m_index, this->shape(), static_cast(-n)); - } - m_linear_index += n; - return *this; - } - - template - inline auto xiterator::operator-=(difference_type n) -> self_type& - { - if (n >= 0) - { - stepper_tools::decrement_stepper(m_it, m_index, this->shape(), static_cast(n)); - } - else - { - stepper_tools::increment_stepper(m_it, m_index, this->shape(), static_cast(-n)); - } - m_linear_index -= n; - return *this; - } - - template - inline auto xiterator::operator-(const self_type& rhs) const -> difference_type - { - return m_linear_index - rhs.m_linear_index; - } - - template - inline auto xiterator::operator*() const -> reference - { - return *m_it; - } - - template - inline auto xiterator::operator->() const -> pointer - { - return &(*m_it); - } - - template - inline bool xiterator::equal(const xiterator& rhs) const - { - XTENSOR_ASSERT(this->shape() == rhs.shape()); - return m_linear_index == rhs.m_linear_index; - } - - template - inline bool xiterator::less_than(const xiterator& rhs) const - { - XTENSOR_ASSERT(this->shape() == rhs.shape()); - return m_linear_index < rhs.m_linear_index; - } - - template - inline bool operator==(const xiterator& lhs, - const xiterator& rhs) - { - return lhs.equal(rhs); - } - - template - bool operator<(const xiterator& lhs, - const xiterator& rhs) - { - return lhs.less_than(rhs); - } - - /************************************ - * xbounded_iterator implementation * - ************************************/ - - template - xbounded_iterator::xbounded_iterator(It it, BIt bound_it) - : m_it(it), m_bound_it(bound_it) - { - } - - template - inline auto xbounded_iterator::operator++() -> self_type& - { - ++m_it; - ++m_bound_it; - return *this; - } - - template - inline auto xbounded_iterator::operator--() -> self_type& - { - --m_it; - --m_bound_it; - return *this; - } - - template - inline auto xbounded_iterator::operator+=(difference_type n) -> self_type& - { - m_it += n; - m_bound_it += n; - return *this; - } - - template - inline auto xbounded_iterator::operator-=(difference_type n) -> self_type& - { - m_it -= n; - m_bound_it -= n; - return *this; - } - - template - inline auto xbounded_iterator::operator-(const self_type& rhs) const -> difference_type - { - return m_it - rhs.m_it; - } - - template - inline auto xbounded_iterator::operator*() const -> value_type - { - using type = decltype(*m_bound_it); - return (static_cast(*m_it) < *m_bound_it) ? *m_it : static_cast((*m_bound_it) - 1); - } - - template - inline bool xbounded_iterator::equal(const self_type& rhs) const - { - return m_it == rhs.m_it && m_bound_it == rhs.m_bound_it; - } - - template - inline bool xbounded_iterator::less_than(const self_type& rhs) const - { - return m_it < rhs.m_it; - } - - template - inline bool operator==(const xbounded_iterator& lhs, - const xbounded_iterator& rhs) - { - return lhs.equal(rhs); - } - - template - inline bool operator<(const xbounded_iterator& lhs, - const xbounded_iterator& rhs) - { - return lhs.less_than(rhs); - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xjson.hpp b/vendor/xtensor/include/xtensor/xjson.hpp deleted file mode 100644 index b0d33ed8a..000000000 --- a/vendor/xtensor/include/xtensor/xjson.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_JSON_HPP -#define XTENSOR_JSON_HPP - -#include -#include -#include - -#include - -#include "xstrided_view.hpp" - -namespace xt -{ - /************************************* - * to_json and from_json declaration * - *************************************/ - - template - enable_xexpression to_json(nlohmann::json&, const E&); - - template - enable_xcontainer_semantics from_json(const nlohmann::json&, E&); - - /// @cond DOXYGEN_INCLUDE_SFINAE - template - enable_xview_semantics from_json(const nlohmann::json&, E&); - /// @endcond - - /**************************************** - * to_json and from_json implementation * - ****************************************/ - - namespace detail - { - template - void to_json_impl(nlohmann::json& j, const xexpression& e, xstrided_slice_vector& slices) - { - const auto view = strided_view(e.derived_cast(), slices); - if (view.dimension() == 0) - { - j = view(); - } - else - { - j = nlohmann::json::array(); - using size_type = typename D::size_type; - size_type nrows = view.shape()[0]; - for (size_type i = 0; i != nrows; ++i) - { - slices.push_back(i); - nlohmann::json k; - to_json_impl(k, e, slices); - j.push_back(std::move(k)); - slices.pop_back(); - } - } - } - - template - inline void from_json_impl(const nlohmann::json& j, xexpression& e, xstrided_slice_vector& slices) - { - auto view = strided_view(e.derived_cast(), slices); - - if (view.dimension() == 0) - { - view() = j; - } - else - { - using size_type = typename D::size_type; - size_type nrows = view.shape()[0]; - for (size_type i = 0; i != nrows; ++i) - { - slices.push_back(i); - const nlohmann::json& k = j[i]; - from_json_impl(k, e, slices); - slices.pop_back(); - } - } - } - - inline unsigned int json_dimension(const nlohmann::json& j) - { - if (j.is_array() && j.size()) - { - return 1 + json_dimension(j[0]); - } - else - { - return 0; - } - } - - template - inline void json_shape(const nlohmann::json& j, S& s, std::size_t pos = 0) - { - if (j.is_array()) - { - auto size = j.size(); - s[pos] = size; - if (size) - { - json_shape(j[0], s, pos + 1); - } - } - } - } - - /** - * @brief JSON serialization of an xtensor expression. - * - * The to_json method is used by the nlohmann_json package for automatic - * serialization of user-defined types. The method is picked up by - * argument-dependent lookup. - * - * @param j a JSON object - * @param e a const \ref xexpression - */ - template - inline enable_xexpression to_json(nlohmann::json& j, const E& e) - { - auto sv = xstrided_slice_vector(); - detail::to_json_impl(j, e, sv); - } - - /** - * @brief JSON deserialization of a xtensor expression with a container or - * a view semantics. - * - * The from_json method is used by the nlohmann_json library for automatic - * serialization of user-defined types. The method is picked up by - * argument-dependent lookup. - * - * Note: for converting a JSON object to a value, nlohmann_json requiress - * the value type to be default constructible, which is typically not the - * case for expressions with a view semantics. In this case, from_json can - * be called directly. - * - * @param j a const JSON object - * @param e an \ref xexpression - */ - template - inline enable_xcontainer_semantics from_json(const nlohmann::json& j, E& e) - { - auto dimension = detail::json_dimension(j); - auto s = xtl::make_sequence(dimension); - detail::json_shape(j, s); - - // In the case of a container, we resize the container. - e.resize(s); - - auto sv = xstrided_slice_vector(); - detail::from_json_impl(j, e, sv); - } - - /// @cond DOXYGEN_INCLUDE_SFINAE - template - inline enable_xview_semantics from_json(const nlohmann::json& j, E& e) - { - typename E::shape_type s; - detail::json_shape(j, s); - - // In the case of a view, we check the size of the container. - if (!std::equal(s.cbegin(), s.cend(), e.shape().cbegin())) - { - throw std::runtime_error("Shape mismatch when deserializing JSON to view"); - } - - auto sv = xstrided_slice_vector(); - detail::from_json_impl(j, e, sv); - } - /// @endcond -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xlayout.hpp b/vendor/xtensor/include/xtensor/xlayout.hpp deleted file mode 100644 index 5ec8a340c..000000000 --- a/vendor/xtensor/include/xtensor/xlayout.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTENSOR_LAYOUT_HPP -#define XTENSOR_LAYOUT_HPP - -#include "xtensor_config.hpp" - -namespace xt -{ - /*! layout_type enum for xcontainer based xexpressions */ - enum class layout_type - { - /*! dynamic layout_type: you can resize to row major, column major, or use custom strides */ - dynamic = 0x00, - /*! layout_type compatible with all others */ - any = 0xFF, - /*! row major layout_type */ - row_major = 0x01, - /*! column major layout_type */ - column_major = 0x02 - }; - - /** - * Implementation of the following logical table: - * - * @verbatim - | d | a | r | c | - --+---+---+---+---+ - d | d | d | d | d | - a | d | a | r | c | - r | d | r | r | d | - c | d | c | d | c | - d = dynamic, a = any, r = row_major, c = column_major. - @endverbatim - * Using bitmasks to avoid nested if-else statements. - * - * @param args the input layouts. - * @return the output layout, computed with the previous logical table. - */ - template - constexpr layout_type compute_layout(Args... args) noexcept; - - constexpr layout_type default_assignable_layout(layout_type l) noexcept; - - /****************** - * Implementation * - ******************/ - - namespace detail - { - constexpr layout_type compute_layout_impl() noexcept - { - return layout_type::any; - } - - constexpr layout_type compute_layout_impl(layout_type l) noexcept - { - return l; - } - - constexpr layout_type compute_layout_impl(layout_type lhs, layout_type rhs) noexcept - { - using type = std::underlying_type_t; - return layout_type(static_cast(lhs) & static_cast(rhs)); - } - - template - constexpr layout_type compute_layout_impl(layout_type lhs, Args... args) noexcept - { - return compute_layout_impl(lhs, compute_layout_impl(args...)); - } - } - - template - constexpr layout_type compute_layout(Args... args) noexcept - { - return detail::compute_layout_impl(args...); - } - - constexpr layout_type default_assignable_layout(layout_type l) noexcept - { - return (l == layout_type::row_major || l == layout_type::column_major) ? - l : XTENSOR_DEFAULT_LAYOUT; - } -} - -#endif diff --git a/vendor/xtensor/include/xtensor/xmath.hpp b/vendor/xtensor/include/xtensor/xmath.hpp deleted file mode 100644 index 41332b180..000000000 --- a/vendor/xtensor/include/xtensor/xmath.hpp +++ /dev/null @@ -1,2146 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -/** - * @brief standard mathematical functions for xexpressions - */ - -#ifndef XTENSOR_MATH_HPP -#define XTENSOR_MATH_HPP - -#include -#include -#include -#include - -#include - -#include "xaccumulator.hpp" -#include "xoperation.hpp" -#include "xreducer.hpp" -#include "xslice.hpp" -#include "xstrided_view.hpp" -#include "xeval.hpp" - -namespace xt -{ - template - struct numeric_constants - { - static constexpr T PI = 3.141592653589793238463; - static constexpr T PI_2 = 1.57079632679489661923; - static constexpr T PI_4 = 0.785398163397448309616; - static constexpr T D_1_PI = 0.318309886183790671538; - static constexpr T D_2_PI = 0.636619772367581343076; - static constexpr T D_2_SQRTPI = 1.12837916709551257390; - static constexpr T SQRT2 = 1.41421356237309504880; - static constexpr T SQRT1_2 = 0.707106781186547524401; - static constexpr T E = 2.71828182845904523536; - static constexpr T LOG2E = 1.44269504088896340736; - static constexpr T LOG10E = 0.434294481903251827651; - static constexpr T LN2 = 0.693147180559945309417; - }; - - /*********** - * Helpers * - ***********/ - -#define XTENSOR_UNSIGNED_ABS_FUNC(T) \ -constexpr inline T abs(const T& x) \ -{ \ - return x; \ -} \ - -#define XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, T) \ -constexpr inline bool FUNC_NAME(const T& /*x*/) noexcept \ -{ \ - return RETURN_VAL; \ -} \ - -#define XTENSOR_INT_SPECIALIZATION(FUNC_NAME, RETURN_VAL) \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, char); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, short); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, int); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, long); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, long long); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned char); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned short); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned int); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned long); \ -XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned long long); \ - - -#define XTENSOR_UNARY_MATH_FUNCTOR_IMPL(NAME, R) \ - template \ - struct NAME##_fun \ - { \ - static auto exec(const T& arg) \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - template \ - using frt = xt::detail::functor_return_type; \ - using return_type = frt; \ - using argument_type = T; \ - using result_type = decltype(exec(std::declval())); \ - using simd_value_type = xsimd::simd_type; \ - using simd_result_type = typename return_type::simd_type; \ - constexpr result_type operator()(const T& arg) const \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - template \ - constexpr typename frt, R>::simd_type \ - simd_apply(const B& arg) const \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - template \ - struct rebind \ - { \ - using type = NAME##_fun; \ - }; \ - } - -#define XTENSOR_UNARY_MATH_FUNCTOR(NAME) XTENSOR_UNARY_MATH_FUNCTOR_IMPL(NAME, T) -#define XTENSOR_UNARY_BOOL_FUNCTOR(NAME) XTENSOR_UNARY_MATH_FUNCTOR_IMPL(NAME, bool) - -#define XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(NAME) \ - template \ - struct NAME##_fun \ - { \ - static auto exec(const T& arg) \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - using argument_type = T; \ - using result_type = decltype(exec(std::declval())); \ - using simd_value_type = argument_type; \ - using simd_result_type = result_type; \ - constexpr result_type operator()(const T& arg) const \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - template \ - constexpr simd_result_type simd_apply(const B& arg) const \ - { \ - using math::NAME; \ - return NAME(arg); \ - } \ - template \ - struct rebind \ - { \ - using type = NAME##_fun; \ - }; \ - } - -#define XTENSOR_BINARY_MATH_FUNCTOR_IMPL(NAME, R) \ - template \ - struct NAME##_fun \ - { \ - static auto exec(const T& arg1, const T& arg2) \ - { \ - using math::NAME; \ - return NAME(arg1, arg2); \ - } \ - template \ - using frt = xt::detail::functor_return_type; \ - using return_type = xt::detail::functor_return_type; \ - using first_argument_type = T; \ - using second_argument_type = T; \ - using result_type = decltype(exec(std::declval(), std::declval())); \ - using simd_value_type = xsimd::simd_type; \ - using simd_result_type = typename return_type::simd_type; \ - constexpr result_type operator()(const T& arg1, const T& arg2) const \ - { \ - using math::NAME; \ - return NAME(arg1, arg2); \ - } \ - template \ - constexpr typename frt, R>::simd_type \ - simd_apply(const B& arg1, const B& arg2) const \ - { \ - using math::NAME; \ - return NAME(arg1, arg2); \ - } \ - template \ - struct rebind \ - { \ - using type = NAME##_fun; \ - }; \ - } - -#define XTENSOR_BINARY_MATH_FUNCTOR(NAME) XTENSOR_BINARY_MATH_FUNCTOR_IMPL(NAME, T) -#define XTENSOR_BINARY_BOOL_FUNCTOR(NAME) XTENSOR_BINARY_MATH_FUNCTOR_IMPL(NAME, bool) - -#define XTENSOR_TERNARY_MATH_FUNCTOR_IMPL(NAME, R) \ - template \ - struct NAME##_fun \ - { \ - static auto exec(const T& arg1, const T& arg2, const T& arg3) \ - { \ - using math::NAME; \ - return NAME(arg1, arg2, arg3); \ - } \ - template \ - using frt = xt::detail::functor_return_type; \ - using return_type = xt::detail::functor_return_type; \ - using first_argument_type = T; \ - using second_argument_type = T; \ - using third_argument_type = T; \ - using result_type = decltype(exec(std::declval(), std::declval(), \ - std::declval())); \ - using simd_value_type = xsimd::simd_type; \ - using simd_result_type = typename return_type::simd_type; \ - constexpr result_type operator()(const T& arg1, \ - const T& arg2, \ - const T& arg3) const \ - { \ - using math::NAME; \ - return NAME(arg1, arg2, arg3); \ - } \ - template \ - constexpr typename frt, R>::simd_type \ - simd_apply(const B& arg1, const B& arg2, const B& arg3) const \ - { \ - using math::NAME; \ - return NAME(arg1, arg2, arg3); \ - } \ - template \ - struct rebind \ - { \ - using type = NAME##_fun; \ - }; \ - } - -#define XTENSOR_TERNARY_MATH_FUNCTOR(NAME) XTENSOR_TERNARY_MATH_FUNCTOR_IMPL(NAME, T) -#define XTENSOR_TERNARY_BOOL_FUNCTOR(NAME) XTENSOR_TERNARY_MATH_FUNCTOR_IMPL(NAME, bool) - - namespace math - { - using std::abs; - using std::fabs; - - using std::cos; - using std::sin; - using std::tan; - using std::acos; - using std::asin; - using std::atan; - - using std::cosh; - using std::sinh; - using std::tanh; - using std::acosh; - using std::asinh; - using std::atanh; - - using std::sqrt; - using std::cbrt; - - using std::exp; - using std::exp2; - using std::expm1; - using std::log; - using std::log2; - using std::log10; - using std::log1p; - using std::logb; - using std::ilogb; - - using std::floor; - using std::ceil; - using std::trunc; - using std::round; - using std::lround; - using std::llround; - using std::rint; - using std::nearbyint; - using std::remainder; - - using std::erf; - using std::erfc; - using std::erfc; - using std::tgamma; - using std::lgamma; - - using std::conj; - using std::real; - using std::imag; - using std::arg; - - using std::atan2; - using std::copysign; - using std::fdim; - using std::fmax; - using std::fmin; - using std::fmod; - using std::hypot; - using std::pow; - - using std::fma; - - using std::isnan; - using std::isinf; - using std::isfinite; - using std::fpclassify; - - // Overload isinf, isnan and isfinite for complex datatypes, - // following the Python specification: - template - inline bool isinf(const std::complex& c) - { - return std::isinf(std::real(c)) || std::isinf(std::imag(c)); - } - - template - inline bool isnan(const std::complex& c) - { - return std::isnan(std::real(c)) || std::isnan(std::imag(c)); - } - - template - inline bool isfinite(const std::complex& c) - { - return !isinf(c) && !isnan(c); - } - - // The following specializations are needed to avoid 'ambiguous overload' errors, - // whereas 'unsigned char' and 'unsigned short' are automatically converted to 'int'. - // we're still adding those functions to silence warnings - XTENSOR_UNSIGNED_ABS_FUNC(unsigned char); - XTENSOR_UNSIGNED_ABS_FUNC(unsigned short); - XTENSOR_UNSIGNED_ABS_FUNC(unsigned int); - XTENSOR_UNSIGNED_ABS_FUNC(unsigned long); - XTENSOR_UNSIGNED_ABS_FUNC(unsigned long long); - -#ifdef _WIN32 - XTENSOR_INT_SPECIALIZATION(isinf, false); - XTENSOR_INT_SPECIALIZATION(isnan, false); - XTENSOR_INT_SPECIALIZATION(isfinite, true); -#endif - - XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(abs); - - XTENSOR_UNARY_MATH_FUNCTOR(fabs); - XTENSOR_BINARY_MATH_FUNCTOR(fmod); - XTENSOR_BINARY_MATH_FUNCTOR(remainder); - XTENSOR_TERNARY_MATH_FUNCTOR(fma); - XTENSOR_BINARY_MATH_FUNCTOR(fmax); - XTENSOR_BINARY_MATH_FUNCTOR(fmin); - XTENSOR_BINARY_MATH_FUNCTOR(fdim); - XTENSOR_UNARY_MATH_FUNCTOR(exp); - XTENSOR_UNARY_MATH_FUNCTOR(exp2); - XTENSOR_UNARY_MATH_FUNCTOR(expm1); - XTENSOR_UNARY_MATH_FUNCTOR(log); - XTENSOR_UNARY_MATH_FUNCTOR(log10); - XTENSOR_UNARY_MATH_FUNCTOR(log2); - XTENSOR_UNARY_MATH_FUNCTOR(log1p); - XTENSOR_BINARY_MATH_FUNCTOR(pow); - XTENSOR_UNARY_MATH_FUNCTOR(sqrt); - XTENSOR_UNARY_MATH_FUNCTOR(cbrt); - XTENSOR_BINARY_MATH_FUNCTOR(hypot); - XTENSOR_UNARY_MATH_FUNCTOR(sin); - XTENSOR_UNARY_MATH_FUNCTOR(cos); - XTENSOR_UNARY_MATH_FUNCTOR(tan); - XTENSOR_UNARY_MATH_FUNCTOR(asin); - XTENSOR_UNARY_MATH_FUNCTOR(acos); - XTENSOR_UNARY_MATH_FUNCTOR(atan); - XTENSOR_BINARY_MATH_FUNCTOR(atan2); - XTENSOR_UNARY_MATH_FUNCTOR(sinh); - XTENSOR_UNARY_MATH_FUNCTOR(cosh); - XTENSOR_UNARY_MATH_FUNCTOR(tanh); - XTENSOR_UNARY_MATH_FUNCTOR(asinh); - XTENSOR_UNARY_MATH_FUNCTOR(acosh); - XTENSOR_UNARY_MATH_FUNCTOR(atanh); - XTENSOR_UNARY_MATH_FUNCTOR(erf); - XTENSOR_UNARY_MATH_FUNCTOR(erfc); - XTENSOR_UNARY_MATH_FUNCTOR(tgamma); - XTENSOR_UNARY_MATH_FUNCTOR(lgamma); - XTENSOR_UNARY_MATH_FUNCTOR(ceil); - XTENSOR_UNARY_MATH_FUNCTOR(floor); - XTENSOR_UNARY_MATH_FUNCTOR(trunc); - XTENSOR_UNARY_MATH_FUNCTOR(round); - XTENSOR_UNARY_MATH_FUNCTOR(nearbyint); - XTENSOR_UNARY_MATH_FUNCTOR(rint); - XTENSOR_UNARY_BOOL_FUNCTOR(isfinite); - XTENSOR_UNARY_BOOL_FUNCTOR(isinf); - XTENSOR_UNARY_BOOL_FUNCTOR(isnan); - } - -#undef XTENSOR_UNARY_MATH_FUNCTOR -#undef XTENSOR_UNARY_BOOL_FUNCTOR -#undef XTENSOR_UNARY_MATH_FUNCTOR_IMPL -#undef XTENSOR_BINARY_MATH_FUNCTOR -#undef XTENSOR_BINARY_BOOL_FUNCTOR -#undef XTENSOR_BINARY_MATH_FUNCTOR_IMPL -#undef XTENSOR_TERNARY_MATH_FUNCTOR -#undef XTENSOR_TERNARY_BOOL_FUNCTOR -#undef XTENSOR_TERNARY_MATH_FUNCTOR_IMPL -#undef XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING -#undef XTENSOR_UNSIGNED_ABS_FUNC - -#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, RESULT_TYPE) \ - template >::value, int>> \ - inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \ - { \ - using result_type = RESULT_TYPE; \ - using functor_type = FUNCTOR; \ - return reduce(make_xreducer_functor(functor_type()), std::forward(e), \ - std::forward(axes), es); \ - } \ - \ - template ::value, int>> \ - inline auto NAME(E&& e, EVS es = EVS()) \ - { \ - using result_type = RESULT_TYPE; \ - using functor_type = FUNCTOR; \ - return reduce(make_xreducer_functor(functor_type()), std::forward(e), es); \ - } - -#define XTENSOR_OLD_CLANG_REDUCER(NAME, FUNCTOR, RESULT_TYPE) \ - template \ - inline auto NAME(E&& e, std::initializer_list axes, EVS es = EVS()) \ - { \ - using result_type = RESULT_TYPE; \ - using functor_type = FUNCTOR; \ - return reduce(make_xreducer_functor(functor_type()), std::forward(e), axes, es); \ - } \ - -#define XTENSOR_MODERN_CLANG_REDUCER(NAME, FUNCTOR, RESULT_TYPE) \ - template \ - inline auto NAME(E&& e, const I (&axes)[N], EVS es = EVS()) \ - { \ - using result_type = RESULT_TYPE; \ - using functor_type = FUNCTOR; \ - return reduce(make_xreducer_functor(functor_type()), std::forward(e), axes, es); \ - } - - /******************* - * basic functions * - *******************/ - - /** - * @defgroup basic_functions Basic functions - */ - - /** - * @ingroup basic_functions - * @brief Absolute value function. - * - * Returns an \ref xfunction for the element-wise absolute value - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto abs(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup basic_functions - * @brief Absolute value function. - * - * Returns an \ref xfunction for the element-wise absolute value - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto fabs(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup basic_functions - * @brief Remainder of the floating point division operation. - * - * Returns an \ref xfunction for the element-wise remainder of - * the floating point division operation e1 / e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto fmod(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Signed remainder of the division operation. - * - * Returns an \ref xfunction for the element-wise signed remainder - * of the floating point division operation e1 / e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto remainder(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Fused multiply-add operation. - * - * Returns an \ref xfunction for e1 * e2 + e3 as if - * to infinite precision and rounded only once to fit the result type. - * @param e1 an \ref xfunction or a scalar - * @param e2 an \ref xfunction or a scalar - * @param e3 an \ref xfunction or a scalar - * @return an \ref xfunction - * @note e1, e2 and e3 can't be scalars every three. - */ - template - inline auto fma(E1&& e1, E2&& e2, E3&& e3) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2), std::forward(e3)); - } - - /** - * @ingroup basic_functions - * @brief Maximum function. - * - * Returns an \ref xfunction for the element-wise maximum - * of \a e1 and \a e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto fmax(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Minimum function. - * - * Returns an \ref xfunction for the element-wise minimum - * of \a e1 and \a e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto fmin(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Positive difference function. - * - * Returns an \ref xfunction for the element-wise positive - * difference of \a e1 and \a e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto fdim(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - namespace math - { - template - struct minimum - { - using result_type = T; - using simd_value_type = xsimd::simd_type; - - constexpr result_type operator()(const T& t1, const T& t2) const noexcept - { - return (t1 < t2) ? t1 : t2; - } - - constexpr simd_value_type simd_apply(const simd_value_type& t1, const simd_value_type& t2) const noexcept - { - return xsimd::select(t1 < t2, t1, t2); - } - }; - - template - struct maximum - { - using result_type = T; - using simd_value_type = xsimd::simd_type; - - constexpr result_type operator()(const T& t1, const T& t2) const noexcept - { - return (t1 > t2) ? t1 : t2; - } - - constexpr simd_value_type simd_apply(const simd_value_type& t1, const simd_value_type& t2) const noexcept - { - return xsimd::select(t1 > t2, t1, t2); - } - }; - - template - struct clamp_fun - { - using first_argument_type = T; - using second_argument_type = T; - using third_argument_type = T; - using result_type = T; - using simd_value_type = xsimd::simd_type; - - constexpr T operator()(const T& v, const T& lo, const T& hi) const - { - return v < lo ? lo : hi < v ? hi : v; - } - - constexpr simd_value_type simd_apply(const simd_value_type& v, - const simd_value_type& lo, - const simd_value_type& hi) const - { - return xsimd::select(v < lo, lo, xsimd::select(hi < v, hi, v)); - } - }; - } - - /** - * @ingroup basic_functions - * @brief Elementwise maximum - * - * Returns an \ref xfunction for the element-wise - * maximum between e1 and e2. - * @param e1 an \ref xexpression - * @param e2 an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto maximum(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Elementwise minimum - * - * Returns an \ref xfunction for the element-wise - * minimum between e1 and e2. - * @param e1 an \ref xexpression - * @param e2 an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto minimum(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup basic_functions - * @brief Maximum element along given axis. - * - * Returns an \ref xreducer for the maximum of elements over given - * \em axes. - * @param e an \ref xexpression - * @param axes the axes along which the maximum is found (optional) - * @param es evaluation strategy of the reducer - * @return an \ref xreducer - */ - XTENSOR_REDUCER_FUNCTION(amax, math::maximum, typename std::decay_t::value_type); -#ifdef X_OLD_CLANG - XTENSOR_OLD_CLANG_REDUCER(amax, math::maximum, typename std::decay_t::value_type); -#else - XTENSOR_MODERN_CLANG_REDUCER(amax, math::maximum, typename std::decay_t::value_type); -#endif - - /** - * @ingroup basic_functions - * @brief Minimum element along given axis. - * - * Returns an \ref xreducer for the minimum of elements over given - * \em axes. - * @param e an \ref xexpression - * @param axes the axes along which the minimum is found (optional) - * @param es evaluation strategy of the reducer - * @return an \ref xreducer - */ - XTENSOR_REDUCER_FUNCTION(amin, math::minimum, typename std::decay_t::value_type); -#ifdef X_OLD_CLANG - XTENSOR_OLD_CLANG_REDUCER(amin, math::minimum, typename std::decay_t::value_type); -#else - XTENSOR_MODERN_CLANG_REDUCER(amin, math::minimum, typename std::decay_t::value_type); -#endif - - /** - * @ingroup basic_functions - * @brief Clip values between hi and lo - * - * Returns an \ref xfunction for the element-wise clipped - * values between lo and hi - * @param e1 an \ref xexpression or a scalar - * @param lo a scalar - * @param hi a scalar - * - * @return a \ref xfunction - */ - template - inline auto clip(E1&& e1, E2&& lo, E3&& hi) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(lo), std::forward(hi)); - } - - namespace math - { - namespace detail - { - template - constexpr std::enable_if_t::value, T> - sign_impl(T x) - { - return std::isnan(x) ? std::numeric_limits::quiet_NaN() : x == 0 ? T(copysign(T(0), x)) : T(copysign(T(1), x)); - } - - template - inline std::enable_if_t::value, T> - sign_impl(T x) - { - typename T::value_type e = (x.real() != T(0)) ? x.real() : x.imag(); - return T(sign_impl(e), 0); - } - - template - constexpr std::enable_if_t::value, T> - sign_impl(T x) - { - return T(x > T(0)); - } - } - - template - struct sign_fun - { - using argument_type = T; - using result_type = T; - - constexpr T operator()(const T& x) const - { - return detail::sign_impl(x); - } - }; - } - - /** - * @ingroup basic_functions - * @brief Returns an element-wise indication of the sign of a number - * - * If the number is positive, returns +1. If negative, -1. If the number - * is zero, returns 0. - * - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto sign(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /************************* - * exponential functions * - *************************/ - - /** - * @defgroup exp_functions Exponential functions - */ - - /** - * @ingroup exp_functions - * @brief Natural exponential function. - * - * Returns an \ref xfunction for the element-wise natural - * exponential of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto exp(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Base 2 exponential function. - * - * Returns an \ref xfunction for the element-wise base 2 - * exponential of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto exp2(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Natural exponential minus one function. - * - * Returns an \ref xfunction for the element-wise natural - * exponential of \em e, minus 1. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto expm1(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Natural logarithm function. - * - * Returns an \ref xfunction for the element-wise natural - * logarithm of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto log(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Base 10 logarithm function. - * - * Returns an \ref xfunction for the element-wise base 10 - * logarithm of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto log10(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Base 2 logarithm function. - * - * Returns an \ref xfunction for the element-wise base 2 - * logarithm of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto log2(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup exp_functions - * @brief Natural logarithm of one plus function. - * - * Returns an \ref xfunction for the element-wise natural - * logarithm of \em e, plus 1. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto log1p(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /******************* - * power functions * - *******************/ - - /** - * @defgroup pow_functions Power functions - */ - - /** - * @ingroup pow_functions - * @brief Power function. - * - * Returns an \ref xfunction for the element-wise value of - * of \em e1 raised to the power \em e2. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto pow(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /** - * @ingroup pow_functions - * @brief Square root function. - * - * Returns an \ref xfunction for the element-wise square - * root of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto sqrt(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup pow_functions - * @brief Cubic root function. - * - * Returns an \ref xfunction for the element-wise cubic - * root of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto cbrt(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup pow_functions - * @brief Hypotenuse function. - * - * Returns an \ref xfunction for the element-wise square - * root of the sum of the square of \em e1 and \em e2, avoiding - * overflow and underflow at intermediate stages of computation. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto hypot(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /*************************** - * trigonometric functions * - ***************************/ - - /** - * @defgroup trigo_functions Trigonometric function - */ - - /** - * @ingroup trigo_functions - * @brief Sine function. - * - * Returns an \ref xfunction for the element-wise sine - * of \em e (measured in radians). - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto sin(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Cosine function. - * - * Returns an \ref xfunction for the element-wise cosine - * of \em e (measured in radians). - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto cos(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Tangent function. - * - * Returns an \ref xfunction for the element-wise tangent - * of \em e (measured in radians). - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto tan(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Arcsine function. - * - * Returns an \ref xfunction for the element-wise arcsine - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto asin(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Arccosine function. - * - * Returns an \ref xfunction for the element-wise arccosine - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto acos(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Arctangent function. - * - * Returns an \ref xfunction for the element-wise arctangent - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto atan(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup trigo_functions - * @brief Artangent function, using signs to determine quadrants. - * - * Returns an \ref xfunction for the element-wise arctangent - * of e1 / e2, using the signs of arguments to determine the - * correct quadrant. - * @param e1 an \ref xexpression or a scalar - * @param e2 an \ref xexpression or a scalar - * @return an \ref xfunction - * @note e1 and e2 can't be both scalars. - */ - template - inline auto atan2(E1&& e1, E2&& e2) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e1), std::forward(e2)); - } - - /************************ - * hyperbolic functions * - ************************/ - - /** - * @defgroup hyper_functions Hyperbolic functions - */ - - /** - * @ingroup hyper_functions - * @brief Hyperbolic sine function. - * - * Returns an \ref xfunction for the element-wise hyperbolic - * sine of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto sinh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup hyper_functions - * @brief Hyperbolic cosine function. - * - * Returns an \ref xfunction for the element-wise hyperbolic - * cosine of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto cosh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup hyper_functions - * @brief Hyperbolic tangent function. - * - * Returns an \ref xfunction for the element-wise hyperbolic - * tangent of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto tanh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup hyper_functions - * @brief Inverse hyperbolic sine function. - * - * Returns an \ref xfunction for the element-wise inverse hyperbolic - * sine of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto asinh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup hyper_functions - * @brief Inverse hyperbolic cosine function. - * - * Returns an \ref xfunction for the element-wise inverse hyperbolic - * cosine of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto acosh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup hyper_functions - * @brief Inverse hyperbolic tangent function. - * - * Returns an \ref xfunction for the element-wise inverse hyperbolic - * tangent of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto atanh(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /***************************** - * error and gamma functions * - *****************************/ - - /** - * @defgroup err_functions Error and gamma functions - */ - - /** - * @ingroup err_functions - * @brief Error function. - * - * Returns an \ref xfunction for the element-wise error function - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto erf(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup err_functions - * @brief Complementary error function. - * - * Returns an \ref xfunction for the element-wise complementary - * error function of \em e, whithout loss of precision for large argument. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto erfc(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup err_functions - * @brief Gamma function. - * - * Returns an \ref xfunction for the element-wise gamma function - * of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto tgamma(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup err_functions - * @brief Natural logarithm of the gamma function. - * - * Returns an \ref xfunction for the element-wise logarithm of - * the asbolute value fo the gamma function of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto lgamma(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /********************************************* - * nearest integer floating point operations * - *********************************************/ - - /** - * @defgroup nearint_functions Nearest integer floating point operations - */ - - /** - * @ingroup nearint_functions - * @brief ceil function. - * - * Returns an \ref xfunction for the element-wise smallest integer value - * not less than \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto ceil(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup nearint_functions - * @brief floor function. - * - * Returns an \ref xfunction for the element-wise smallest integer value - * not greater than \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto floor(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup nearint_functions - * @brief trunc function. - * - * Returns an \ref xfunction for the element-wise nearest integer not greater - * in magnitude than \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto trunc(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup nearint_functions - * @brief round function. - * - * Returns an \ref xfunction for the element-wise nearest integer value - * to \em e, rounding halfway cases away from zero, regardless of the - * current rounding mode. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto round(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup nearint_functions - * @brief nearbyint function. - * - * Returns an \ref xfunction for the element-wise rounding of \em e to integer - * values in floating point format, using the current rounding mode. nearbyint - * never raises FE_INEXACT error. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto nearbyint(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup nearint_functions - * @brief rint function. - * - * Returns an \ref xfunction for the element-wise rounding of \em e to integer - * values in floating point format, using the current rounding mode. Contrary - * to nearbyint, rint may raise FE_INEXACT error. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto rint(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /**************************** - * classification functions * - ****************************/ - - /** - * @defgroup classif_functions Classification functions - */ - - /** - * @ingroup classif_functions - * @brief finite value check - * - * Returns an \ref xfunction for the element-wise finite value check - * tangent of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto isfinite(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup classif_functions - * @brief infinity check - * - * Returns an \ref xfunction for the element-wise infinity check - * tangent of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto isinf(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - /** - * @ingroup classif_functions - * @brief NaN check - * - * Returns an \ref xfunction for the element-wise NaN check - * tangent of \em e. - * @param e an \ref xexpression - * @return an \ref xfunction - */ - template - inline auto isnan(E&& e) noexcept - -> detail::xfunction_type_t - { - return detail::make_xfunction(std::forward(e)); - } - - namespace detail - { - template - inline auto get_functor(T&& args, std::index_sequence) - { - return FUNCTOR(std::get(args)...); - } - - template